2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "../librpc/gen_ndr/cli_srvsvc.h"
35 #include "../librpc/gen_ndr/srv_samr.h"
36 #include "../librpc/gen_ndr/srv_srvsvc.h"
37 #include "../librpc/gen_ndr/rap.h"
38 #include "../lib/util/binsearch.h"
39 #include "../libcli/auth/libcli_auth.h"
40 #include "rpc_client/init_lsa.h"
41 #include "rpc_server/rpc_ncacn_np.h"
48 #define NERR_Success 0
49 #define NERR_badpass 86
50 #define NERR_notsupported 50
52 #define NERR_BASE (2100)
53 #define NERR_BufTooSmall (NERR_BASE+23)
54 #define NERR_JobNotFound (NERR_BASE+51)
55 #define NERR_DestNotFound (NERR_BASE+52)
57 #define ACCESS_READ 0x01
58 #define ACCESS_WRITE 0x02
59 #define ACCESS_CREATE 0x04
61 #define SHPWLEN 8 /* share password length */
63 /* Limit size of ipc replies */
65 static char *smb_realloc_limit(void *ptr
, size_t size
)
69 size
= MAX((size
),4*1024);
70 val
= (char *)SMB_REALLOC(ptr
,size
);
72 memset(val
,'\0',size
);
77 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
78 connection_struct
*conn
, uint16 vuid
,
79 char *param
, int tpscnt
,
80 char *data
, int tdscnt
,
81 int mdrcnt
, int mprcnt
,
82 char **rdata
, char **rparam
,
83 int *rdata_len
, int *rparam_len
);
85 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
86 connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
87 int mdrcnt
, int mprcnt
,
88 char **rdata
, char **rparam
,
89 int *rdata_len
, int *rparam_len
);
92 static int CopyExpanded(connection_struct
*conn
,
93 int snum
, char **dst
, char *src
, int *p_space_remaining
)
95 TALLOC_CTX
*ctx
= talloc_tos();
99 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
100 *p_space_remaining
<= 0) {
104 buf
= talloc_strdup(ctx
, src
);
106 *p_space_remaining
= 0;
109 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
111 *p_space_remaining
= 0;
114 buf
= talloc_sub_advanced(ctx
,
115 lp_servicename(SNUM(conn
)),
116 conn
->server_info
->unix_name
,
118 conn
->server_info
->utok
.gid
,
119 conn
->server_info
->sanitized_username
,
120 conn
->server_info
->info3
->base
.domain
.string
,
123 *p_space_remaining
= 0;
126 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
131 (*p_space_remaining
) -= l
;
135 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
138 if (!src
|| !dst
|| !n
|| !(*dst
)) {
141 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
150 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
152 TALLOC_CTX
*ctx
= talloc_tos();
157 buf
= talloc_strdup(ctx
,s
);
161 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
165 buf
= talloc_sub_advanced(ctx
,
166 lp_servicename(SNUM(conn
)),
167 conn
->server_info
->unix_name
,
169 conn
->server_info
->utok
.gid
,
170 conn
->server_info
->sanitized_username
,
171 conn
->server_info
->info3
->base
.domain
.string
,
176 return strlen(buf
) + 1;
179 /*******************************************************************
180 Check a API string for validity when we only need to check the prefix.
181 ******************************************************************/
183 static bool prefix_ok(const char *str
, const char *prefix
)
185 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
189 const char *format
; /* formatstring for structure */
190 const char *subformat
; /* subformat for structure */
191 char *base
; /* baseaddress of buffer */
192 int buflen
; /* remaining size for fixed part; on init: length of base */
193 int subcount
; /* count of substructures */
194 char *structbuf
; /* pointer into buffer for remaining fixed part */
195 int stringlen
; /* remaining size for variable part */
196 char *stringbuf
; /* pointer into buffer for remaining variable part */
197 int neededlen
; /* total needed size */
198 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
199 const char *curpos
; /* current position; pointer into format or subformat */
203 static int get_counter(const char **p
)
209 if (!isdigit((int)**p
)) {
215 n
= 10 * n
+ (i
- '0');
223 static int getlen(const char *p
)
232 case 'W': /* word (2 byte) */
235 case 'K': /* status word? (2 byte) */
238 case 'N': /* count of substructures (word) at end */
241 case 'D': /* double word (4 byte) */
242 case 'z': /* offset to zero terminated string (4 byte) */
243 case 'l': /* offset to user data (4 byte) */
246 case 'b': /* offset to data (with counter) (4 byte) */
250 case 'B': /* byte (with optional counter) */
251 n
+= get_counter(&p
);
258 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
263 if (!p
->format
|| !p
->base
) {
267 i
= count
* getlen(p
->format
);
269 i
+= subcount
* getlen(p
->subformat
);
271 p
->structbuf
= p
->base
;
275 p
->curpos
= p
->format
;
281 * This is the old error code we used. Aparently
282 * WinNT/2k systems return ERRbuftoosmall (2123) and
283 * OS/2 needs this. I'm leaving this here so we can revert
286 p
->errcode
= ERRmoredata
;
288 p
->errcode
= ERRbuftoosmall
;
291 p
->errcode
= NERR_Success
;
295 p
->stringbuf
= p
->base
+ i
;
297 return (p
->errcode
== NERR_Success
);
300 static int package(struct pack_desc
*p
, ...)
303 int needed
=0, stringneeded
;
304 const char *str
=NULL
;
305 int is_string
=0, stringused
;
312 p
->curpos
= p
->format
;
314 p
->curpos
= p
->subformat
;
319 str
= va_arg(args
,char*);
320 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
329 switch( *p
->curpos
++ ) {
330 case 'W': /* word (2 byte) */
332 temp
= va_arg(args
,int);
333 if (p
->buflen
>= needed
) {
334 SSVAL(p
->structbuf
,0,temp
);
337 case 'K': /* status word? (2 byte) */
339 temp
= va_arg(args
,int);
340 if (p
->buflen
>= needed
) {
341 SSVAL(p
->structbuf
,0,temp
);
344 case 'N': /* count of substructures (word) at end */
346 p
->subcount
= va_arg(args
,int);
347 if (p
->buflen
>= needed
) {
348 SSVAL(p
->structbuf
,0,p
->subcount
);
351 case 'D': /* double word (4 byte) */
353 temp
= va_arg(args
,int);
354 if (p
->buflen
>= needed
) {
355 SIVAL(p
->structbuf
,0,temp
);
358 case 'B': /* byte (with optional counter) */
359 needed
= get_counter(&p
->curpos
);
361 char *s
= va_arg(args
,char*);
362 if (p
->buflen
>= needed
) {
363 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
367 case 'z': /* offset to zero terminated string (4 byte) */
368 str
= va_arg(args
,char*);
369 stringneeded
= (str
? strlen(str
)+1 : 0);
372 case 'l': /* offset to user data (4 byte) */
373 str
= va_arg(args
,char*);
374 stringneeded
= va_arg(args
,int);
377 case 'b': /* offset to data (with counter) (4 byte) */
378 str
= va_arg(args
,char*);
379 stringneeded
= get_counter(&p
->curpos
);
385 if (stringneeded
>= 0) {
387 if (p
->buflen
>= needed
) {
388 stringused
= stringneeded
;
389 if (stringused
> p
->stringlen
) {
390 stringused
= (is_string
? p
->stringlen
: 0);
391 if (p
->errcode
== NERR_Success
) {
392 p
->errcode
= ERRmoredata
;
396 SIVAL(p
->structbuf
,0,0);
398 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
399 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
401 p
->stringbuf
[stringused
-1] = '\0';
403 p
->stringbuf
+= stringused
;
404 p
->stringlen
-= stringused
;
405 p
->usedlen
+= stringused
;
408 p
->neededlen
+= stringneeded
;
411 p
->neededlen
+= needed
;
412 if (p
->buflen
>= needed
) {
413 p
->structbuf
+= needed
;
415 p
->usedlen
+= needed
;
417 if (p
->errcode
== NERR_Success
) {
418 p
->errcode
= ERRmoredata
;
425 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
426 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
428 #define PACK(desc,t,v) package(desc,v)
429 #define PACKl(desc,t,v,l) package(desc,v,l)
432 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
437 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
442 /****************************************************************************
444 ****************************************************************************/
446 static void PackDriverData(struct pack_desc
* desc
)
448 char drivdata
[4+4+32];
449 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
450 SIVAL(drivdata
,4,1000); /* lVersion */
451 memset(drivdata
+8,0,32); /* szDeviceName */
452 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
453 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
456 static int check_printq_info(struct pack_desc
* desc
,
457 unsigned int uLevel
, char *id1
, char *id2
)
459 desc
->subformat
= NULL
;
462 desc
->format
= "B13";
465 desc
->format
= "B13BWWWzzzzzWW";
468 desc
->format
= "B13BWWWzzzzzWN";
469 desc
->subformat
= "WB21BB16B10zWWzDDz";
472 desc
->format
= "zWWWWzzzzWWzzl";
475 desc
->format
= "zWWWWzzzzWNzzl";
476 desc
->subformat
= "WWzWWDDzz";
485 desc
->format
= "WzzzzzzzzN";
486 desc
->subformat
= "z";
489 DEBUG(0,("check_printq_info: invalid level %d\n",
493 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
494 DEBUG(0,("check_printq_info: invalid format %s\n",
495 id1
? id1
: "<NULL>" ));
498 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
499 DEBUG(0,("check_printq_info: invalid subformat %s\n",
500 id2
? id2
: "<NULL>" ));
507 #define RAP_JOB_STATUS_QUEUED 0
508 #define RAP_JOB_STATUS_PAUSED 1
509 #define RAP_JOB_STATUS_SPOOLING 2
510 #define RAP_JOB_STATUS_PRINTING 3
511 #define RAP_JOB_STATUS_PRINTED 4
513 #define RAP_QUEUE_STATUS_PAUSED 1
514 #define RAP_QUEUE_STATUS_ERROR 2
516 /* turn a print job status into a on the wire status
518 static int printj_spoolss_status(int v
)
520 if (v
== JOB_STATUS_QUEUED
)
521 return RAP_JOB_STATUS_QUEUED
;
522 if (v
& JOB_STATUS_PAUSED
)
523 return RAP_JOB_STATUS_PAUSED
;
524 if (v
& JOB_STATUS_SPOOLING
)
525 return RAP_JOB_STATUS_SPOOLING
;
526 if (v
& JOB_STATUS_PRINTING
)
527 return RAP_JOB_STATUS_PRINTING
;
531 /* turn a print queue status into a on the wire status
533 static int printq_spoolss_status(int v
)
535 if (v
== PRINTER_STATUS_OK
)
537 if (v
& PRINTER_STATUS_PAUSED
)
538 return RAP_QUEUE_STATUS_PAUSED
;
539 return RAP_QUEUE_STATUS_ERROR
;
542 static void fill_spoolss_printjob_info(int uLevel
,
543 struct pack_desc
*desc
,
544 struct spoolss_JobInfo2
*info2
,
547 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
549 /* the client expects localtime */
550 t
-= get_time_zone(t
);
552 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
554 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
555 PACKS(desc
,"B",""); /* pad */
556 PACKS(desc
,"B16",""); /* szNotifyName */
557 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
558 PACKS(desc
,"z",""); /* pszParms */
559 PACKI(desc
,"W",n
+1); /* uPosition */
560 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
561 PACKS(desc
,"z",""); /* pszStatus */
562 PACKI(desc
,"D", t
); /* ulSubmitted */
563 PACKI(desc
,"D", info2
->size
); /* ulSize */
564 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
566 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
567 PACKI(desc
,"W", info2
->priority
); /* uPriority */
568 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
569 PACKI(desc
,"W",n
+1); /* uPosition */
570 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
571 PACKI(desc
,"D",t
); /* ulSubmitted */
572 PACKI(desc
,"D", info2
->size
); /* ulSize */
573 PACKS(desc
,"z","Samba"); /* pszComment */
574 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
576 PACKS(desc
,"z",""); /* pszNotifyName */
577 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
578 PACKS(desc
,"z",""); /* pszParms */
579 PACKS(desc
,"z",""); /* pszStatus */
580 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
581 PACKS(desc
,"z","lpd"); /* pszQProcName */
582 PACKS(desc
,"z",""); /* pszQProcParms */
583 PACKS(desc
,"z","NULL"); /* pszDriverName */
584 PackDriverData(desc
); /* pDriverData */
585 PACKS(desc
,"z",""); /* pszPrinterName */
586 } else if (uLevel
== 4) { /* OS2 */
587 PACKS(desc
,"z",""); /* pszSpoolFileName */
588 PACKS(desc
,"z",""); /* pszPortName */
589 PACKS(desc
,"z",""); /* pszStatus */
590 PACKI(desc
,"D",0); /* ulPagesSpooled */
591 PACKI(desc
,"D",0); /* ulPagesSent */
592 PACKI(desc
,"D",0); /* ulPagesPrinted */
593 PACKI(desc
,"D",0); /* ulTimePrinted */
594 PACKI(desc
,"D",0); /* ulExtendJobStatus */
595 PACKI(desc
,"D",0); /* ulStartPage */
596 PACKI(desc
,"D",0); /* ulEndPage */
601 /********************************************************************
602 Respond to the DosPrintQInfo command with a level of 52
603 This is used to get printer driver information for Win9x clients
604 ********************************************************************/
605 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
606 struct pack_desc
* desc
, int count
,
607 const char *printer_name
)
611 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
612 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
613 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
615 PACKI(desc
, "W", 0x0400); /* don't know */
616 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
617 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
618 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
619 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
621 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
622 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
623 PACKS(desc
,"z", location
); /* share to retrieve files */
625 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
626 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
627 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
629 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
630 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
631 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
632 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
633 DEBUG(3,("Driver Location: %s:\n",location
));
634 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
635 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
636 PACKI(desc
,"N",count
); /* number of files to copy */
638 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
640 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
641 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
642 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
647 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
650 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
652 desc
->errcode
=NERR_Success
;
656 static const char *strip_unc(const char *unc
)
664 if ((p
= strrchr(unc
, '\\')) != NULL
) {
671 static void fill_printq_info(int uLevel
,
672 struct pack_desc
* desc
,
674 union spoolss_JobInfo
*job_info
,
675 struct spoolss_DriverInfo3
*driver_info
,
676 struct spoolss_PrinterInfo2
*printer_info
)
682 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
687 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
690 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
694 if (uLevel
== 1 || uLevel
== 2) {
695 PACKS(desc
,"B",""); /* alignment */
696 PACKI(desc
,"W",5); /* priority */
697 PACKI(desc
,"W",0); /* start time */
698 PACKI(desc
,"W",0); /* until time */
699 PACKS(desc
,"z",""); /* pSepFile */
700 PACKS(desc
,"z","lpd"); /* pPrProc */
701 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
702 PACKS(desc
,"z",""); /* pParms */
703 if (printer_info
->printername
== NULL
) {
704 PACKS(desc
,"z","UNKNOWN PRINTER");
705 PACKI(desc
,"W",LPSTAT_ERROR
);
707 PACKS(desc
,"z", printer_info
->comment
);
708 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
710 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
713 if (uLevel
== 3 || uLevel
== 4) {
714 PACKI(desc
,"W",5); /* uPriority */
715 PACKI(desc
,"W",0); /* uStarttime */
716 PACKI(desc
,"W",0); /* uUntiltime */
717 PACKI(desc
,"W",5); /* pad1 */
718 PACKS(desc
,"z",""); /* pszSepFile */
719 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
720 PACKS(desc
,"z",NULL
); /* pszParms */
721 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
722 /* "don't ask" that it's done this way to fix corrupted
723 Win9X/ME printer comments. */
724 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
725 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
726 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
727 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
728 PackDriverData(desc
); /* pDriverData */
731 if (uLevel
== 2 || uLevel
== 4) {
733 for (i
= 0; i
< count
; i
++) {
734 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
739 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
742 /* This function returns the number of files for a given driver */
743 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
747 /* count the number of files */
748 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
754 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
755 connection_struct
*conn
, uint16 vuid
,
756 char *param
, int tpscnt
,
757 char *data
, int tdscnt
,
758 int mdrcnt
,int mprcnt
,
759 char **rdata
,char **rparam
,
760 int *rdata_len
,int *rparam_len
)
762 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
763 char *str2
= skip_string(param
,tpscnt
,str1
);
764 char *p
= skip_string(param
,tpscnt
,str2
);
769 struct pack_desc desc
;
772 WERROR werr
= WERR_OK
;
773 TALLOC_CTX
*mem_ctx
= talloc_tos();
775 struct rpc_pipe_client
*cli
= NULL
;
776 struct policy_handle handle
;
777 struct spoolss_DevmodeContainer devmode_ctr
;
778 union spoolss_DriverInfo driver_info
;
779 union spoolss_JobInfo
*job_info
= NULL
;
780 union spoolss_PrinterInfo printer_info
;
782 if (!str1
|| !str2
|| !p
) {
785 memset((char *)&desc
,'\0',sizeof(desc
));
787 p
= skip_string(param
,tpscnt
,p
);
791 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
792 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
793 /* str3 may be null here and is checked in check_printq_info(). */
795 /* remove any trailing username */
796 if ((p
= strchr_m(QueueName
,'%')))
799 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
801 /* check it's a supported varient */
802 if (!prefix_ok(str1
,"zWrLh"))
804 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
806 * Patch from Scott Moomaw <scott@bridgewater.edu>
807 * to return the 'invalid info level' error if an
808 * unknown level was requested.
812 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
816 SSVALS(*rparam
,0,ERRunknownlevel
);
824 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
825 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
829 status
= rpc_pipe_open_interface(conn
,
830 &ndr_table_spoolss
.syntax_id
,
832 &conn
->sconn
->client_id
,
833 conn
->sconn
->msg_ctx
,
835 if (!NT_STATUS_IS_OK(status
)) {
836 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
838 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
842 ZERO_STRUCT(devmode_ctr
);
844 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
851 if (!NT_STATUS_IS_OK(status
)) {
852 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
855 if (!W_ERROR_IS_OK(werr
)) {
856 desc
.errcode
= W_ERROR_V(werr
);
860 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
865 if (!W_ERROR_IS_OK(werr
)) {
866 desc
.errcode
= W_ERROR_V(werr
);
871 uint32_t server_major_version
;
872 uint32_t server_minor_version
;
874 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
882 &server_major_version
,
883 &server_minor_version
);
884 if (!W_ERROR_IS_OK(werr
)) {
885 desc
.errcode
= W_ERROR_V(werr
);
889 count
= get_printerdrivernumber(&driver_info
.info3
);
890 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
893 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
901 if (!W_ERROR_IS_OK(werr
)) {
902 desc
.errcode
= W_ERROR_V(werr
);
910 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
915 desc
.buflen
= mdrcnt
;
918 * Don't return data but need to get correct length
919 * init_package will return wrong size if buflen=0
921 desc
.buflen
= getlen(desc
.format
);
922 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
925 if (init_package(&desc
,1,count
)) {
926 desc
.subcount
= count
;
927 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
930 *rdata_len
= desc
.usedlen
;
933 * We must set the return code to ERRbuftoosmall
934 * in order to support lanman style printing with Win NT/2k
937 if (!mdrcnt
&& lp_disable_spoolss())
938 desc
.errcode
= ERRbuftoosmall
;
941 if (cli
&& is_valid_policy_hnd(&handle
)) {
942 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
945 *rdata_len
= desc
.usedlen
;
947 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
952 SSVALS(*rparam
,0,desc
.errcode
);
954 SSVAL(*rparam
,4,desc
.neededlen
);
956 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
963 /****************************************************************************
964 View list of all print jobs on all queues.
965 ****************************************************************************/
967 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
968 connection_struct
*conn
, uint16 vuid
,
969 char *param
, int tpscnt
,
970 char *data
, int tdscnt
,
971 int mdrcnt
, int mprcnt
,
972 char **rdata
, char** rparam
,
973 int *rdata_len
, int *rparam_len
)
975 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
976 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
977 char *p
= skip_string(param
,tpscnt
,output_format1
);
978 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
979 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
981 struct pack_desc desc
;
982 int *subcntarr
= NULL
;
983 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
985 WERROR werr
= WERR_OK
;
986 TALLOC_CTX
*mem_ctx
= talloc_tos();
988 struct rpc_pipe_client
*cli
= NULL
;
989 struct spoolss_DevmodeContainer devmode_ctr
;
990 uint32_t num_printers
;
991 union spoolss_PrinterInfo
*printer_info
;
992 union spoolss_DriverInfo
*driver_info
;
993 union spoolss_JobInfo
**job_info
;
995 if (!param_format
|| !output_format1
|| !p
) {
999 memset((char *)&desc
,'\0',sizeof(desc
));
1001 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1003 if (!prefix_ok(param_format
,"WrLeh")) {
1006 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1008 * Patch from Scott Moomaw <scott@bridgewater.edu>
1009 * to return the 'invalid info level' error if an
1010 * unknown level was requested.
1014 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1018 SSVALS(*rparam
,0,ERRunknownlevel
);
1024 status
= rpc_pipe_open_interface(conn
,
1025 &ndr_table_spoolss
.syntax_id
,
1027 &conn
->sconn
->client_id
,
1028 conn
->sconn
->msg_ctx
,
1030 if (!NT_STATUS_IS_OK(status
)) {
1031 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1032 nt_errstr(status
)));
1033 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1037 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1039 cli
->srv_name_slash
,
1044 if (!W_ERROR_IS_OK(werr
)) {
1045 desc
.errcode
= W_ERROR_V(werr
);
1049 queuecnt
= num_printers
;
1051 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1052 if (job_info
== NULL
) {
1056 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1057 if (driver_info
== NULL
) {
1061 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1062 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1067 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1073 desc
.buflen
= mdrcnt
;
1076 for (i
= 0; i
< num_printers
; i
++) {
1079 struct policy_handle handle
;
1080 const char *printername
;
1082 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1083 if (printername
== NULL
) {
1087 ZERO_STRUCT(handle
);
1088 ZERO_STRUCT(devmode_ctr
);
1090 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
1097 if (!NT_STATUS_IS_OK(status
)) {
1098 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1101 if (!W_ERROR_IS_OK(werr
)) {
1102 desc
.errcode
= W_ERROR_V(werr
);
1106 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1114 if (!W_ERROR_IS_OK(werr
)) {
1115 desc
.errcode
= W_ERROR_V(werr
);
1120 uint32_t server_major_version
;
1121 uint32_t server_minor_version
;
1123 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1131 &server_major_version
,
1132 &server_minor_version
);
1133 if (!W_ERROR_IS_OK(werr
)) {
1134 desc
.errcode
= W_ERROR_V(werr
);
1139 subcntarr
[i
] = num_jobs
;
1140 subcnt
+= subcntarr
[i
];
1142 if (cli
&& is_valid_policy_hnd(&handle
)) {
1143 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
1147 if (init_package(&desc
,queuecnt
,subcnt
)) {
1148 for (i
= 0; i
< num_printers
; i
++) {
1149 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1150 if (desc
.errcode
== NERR_Success
) {
1156 SAFE_FREE(subcntarr
);
1158 *rdata_len
= desc
.usedlen
;
1160 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1164 SSVALS(*rparam
,0,desc
.errcode
);
1166 SSVAL(*rparam
,4,succnt
);
1167 SSVAL(*rparam
,6,queuecnt
);
1173 SAFE_FREE(subcntarr
);
1178 /****************************************************************************
1179 Get info level for a server list query.
1180 ****************************************************************************/
1182 static bool check_server_info(int uLevel
, char* id
)
1186 if (strcmp(id
,"B16") != 0) {
1191 if (strcmp(id
,"B16BBDz") != 0) {
1201 struct srv_info_struct
{
1209 /*******************************************************************
1210 Get server info lists from the files saved by nmbd. Return the
1212 ******************************************************************/
1214 static int get_server_info(uint32 servertype
,
1215 struct srv_info_struct
**servers
,
1221 bool local_list_only
;
1224 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1226 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1230 /* request for everything is code for request all servers */
1231 if (servertype
== SV_TYPE_ALL
) {
1232 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1235 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1237 DEBUG(4,("Servertype search: %8x\n",servertype
));
1239 for (i
=0;lines
[i
];i
++) {
1241 struct srv_info_struct
*s
;
1242 const char *ptr
= lines
[i
];
1244 TALLOC_CTX
*frame
= NULL
;
1251 if (count
== alloced
) {
1253 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1255 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1259 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1261 s
= &(*servers
)[count
];
1263 frame
= talloc_stackframe();
1265 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1269 fstrcpy(s
->name
, p
);
1272 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1278 s
->comment
[0] = '\0';
1279 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1283 fstrcpy(s
->comment
, p
);
1284 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1286 s
->domain
[0] = '\0';
1287 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1288 /* this allows us to cope with an old nmbd */
1289 fstrcpy(s
->domain
,lp_workgroup());
1291 fstrcpy(s
->domain
, p
);
1295 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1296 DEBUG(4,("r:host file "));
1300 /* Filter the servers/domains we return based on what was asked for. */
1302 /* Check to see if we are being asked for a local list only. */
1303 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1304 DEBUG(4,("r: local list only"));
1308 /* doesn't match up: don't want it */
1309 if (!(servertype
& s
->type
)) {
1310 DEBUG(4,("r:serv type "));
1314 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1315 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1316 DEBUG(4,("s: dom mismatch "));
1320 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1324 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1325 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1328 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1329 s
->name
, s
->type
, s
->comment
, s
->domain
));
1330 s
->server_added
= True
;
1333 DEBUG(4,("%20s %8x %25s %15s\n",
1334 s
->name
, s
->type
, s
->comment
, s
->domain
));
1342 /*******************************************************************
1343 Fill in a server info structure.
1344 ******************************************************************/
1346 static int fill_srv_info(struct srv_info_struct
*service
,
1347 int uLevel
, char **buf
, int *buflen
,
1348 char **stringbuf
, int *stringspace
, char *baseaddr
)
1371 len
= strlen(service
->comment
)+1;
1375 *buflen
= struct_len
;
1377 return struct_len
+ len
;
1382 if (*buflen
< struct_len
) {
1389 p2
= p
+ struct_len
;
1390 l2
= *buflen
- struct_len
;
1398 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1402 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1403 SIVAL(p
,18,service
->type
);
1404 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1405 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1410 *buf
= p
+ struct_len
;
1411 *buflen
-= struct_len
;
1422 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1424 return StrCaseCmp(s1
->name
,s2
->name
);
1427 /****************************************************************************
1428 View list of servers available (or possibly domains). The info is
1429 extracted from lists saved by nmbd on the local host.
1430 ****************************************************************************/
1432 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1433 connection_struct
*conn
, uint16 vuid
,
1434 char *param
, int tpscnt
,
1435 char *data
, int tdscnt
,
1436 int mdrcnt
, int mprcnt
, char **rdata
,
1437 char **rparam
, int *rdata_len
, int *rparam_len
)
1439 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1440 char *str2
= skip_string(param
,tpscnt
,str1
);
1441 char *p
= skip_string(param
,tpscnt
,str2
);
1442 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1443 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1444 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1446 int data_len
, fixed_len
, string_len
;
1447 int f_len
= 0, s_len
= 0;
1448 struct srv_info_struct
*servers
=NULL
;
1449 int counted
=0,total
=0;
1452 bool domain_request
;
1455 if (!str1
|| !str2
|| !p
) {
1459 /* If someone sets all the bits they don't really mean to set
1460 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1463 if (servertype
== SV_TYPE_ALL
) {
1464 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1467 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1468 any other bit (they may just set this bit on its own) they
1469 want all the locally seen servers. However this bit can be
1470 set on its own so set the requested servers to be
1471 ALL - DOMAIN_ENUM. */
1473 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1474 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1477 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1478 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1482 if (!prefix_ok(str1
,"WrLehD")) {
1485 if (!check_server_info(uLevel
,str2
)) {
1489 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1490 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1491 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1493 if (strcmp(str1
, "WrLehDz") == 0) {
1494 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1497 pull_ascii_fstring(domain
, p
);
1499 fstrcpy(domain
, lp_workgroup());
1502 DEBUG(4, ("domain [%s]\n", domain
));
1504 if (lp_browse_list()) {
1505 total
= get_server_info(servertype
,&servers
,domain
);
1508 data_len
= fixed_len
= string_len
= 0;
1511 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1514 char *lastname
=NULL
;
1516 for (i
=0;i
<total
;i
++) {
1517 struct srv_info_struct
*s
= &servers
[i
];
1519 if (lastname
&& strequal(lastname
,s
->name
)) {
1523 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1524 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1525 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1527 if (data_len
< buf_len
) {
1530 string_len
+= s_len
;
1537 *rdata_len
= fixed_len
+ string_len
;
1538 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1543 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1549 char *lastname
=NULL
;
1550 int count2
= counted
;
1552 for (i
= 0; i
< total
&& count2
;i
++) {
1553 struct srv_info_struct
*s
= &servers
[i
];
1555 if (lastname
&& strequal(lastname
,s
->name
)) {
1559 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1560 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1561 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1567 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1571 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1573 SSVAL(*rparam
,4,counted
);
1574 SSVAL(*rparam
,6,counted
+missed
);
1578 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1579 domain
,uLevel
,counted
,counted
+missed
));
1584 static int srv_name_match(const char *n1
, const char *n2
)
1587 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1589 * In Windows, FirstNameToReturn need not be an exact match:
1590 * the server will return a list of servers that exist on
1591 * the network greater than or equal to the FirstNameToReturn.
1593 int ret
= StrCaseCmp(n1
, n2
);
1602 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1603 connection_struct
*conn
, uint16 vuid
,
1604 char *param
, int tpscnt
,
1605 char *data
, int tdscnt
,
1606 int mdrcnt
, int mprcnt
, char **rdata
,
1607 char **rparam
, int *rdata_len
, int *rparam_len
)
1609 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1610 char *str2
= skip_string(param
,tpscnt
,str1
);
1611 char *p
= skip_string(param
,tpscnt
,str2
);
1612 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1613 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1614 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1616 int data_len
, fixed_len
, string_len
;
1617 int f_len
= 0, s_len
= 0;
1618 struct srv_info_struct
*servers
=NULL
;
1619 int counted
=0,first
=0,total
=0;
1623 bool domain_request
;
1626 if (!str1
|| !str2
|| !p
) {
1630 /* If someone sets all the bits they don't really mean to set
1631 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1634 if (servertype
== SV_TYPE_ALL
) {
1635 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1638 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1639 any other bit (they may just set this bit on its own) they
1640 want all the locally seen servers. However this bit can be
1641 set on its own so set the requested servers to be
1642 ALL - DOMAIN_ENUM. */
1644 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1645 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1648 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1649 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1653 if (strcmp(str1
, "WrLehDzz") != 0) {
1656 if (!check_server_info(uLevel
,str2
)) {
1660 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1661 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1662 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1664 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1667 pull_ascii_fstring(domain
, p
);
1668 if (domain
[0] == '\0') {
1669 fstrcpy(domain
, lp_workgroup());
1671 p
= skip_string(param
,tpscnt
,p
);
1672 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1675 pull_ascii_fstring(first_name
, p
);
1677 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1678 domain
, first_name
));
1680 if (lp_browse_list()) {
1681 total
= get_server_info(servertype
,&servers
,domain
);
1684 data_len
= fixed_len
= string_len
= 0;
1687 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1689 if (first_name
[0] != '\0') {
1690 struct srv_info_struct
*first_server
= NULL
;
1692 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1693 srv_name_match
, first_server
);
1695 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1697 * The binary search may not find the exact match
1698 * so we need to search backward to find the first match
1700 * This implements the strange matching windows
1701 * implements. (see the comment in srv_name_match().
1705 ret
= StrCaseCmp(first_name
,
1706 servers
[first
-1].name
);
1713 /* we should return no entries */
1719 char *lastname
=NULL
;
1721 for (i
=first
;i
<total
;i
++) {
1722 struct srv_info_struct
*s
= &servers
[i
];
1724 if (lastname
&& strequal(lastname
,s
->name
)) {
1728 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1729 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1730 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1732 if (data_len
< buf_len
) {
1735 string_len
+= s_len
;
1742 *rdata_len
= fixed_len
+ string_len
;
1743 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1748 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1754 char *lastname
=NULL
;
1755 int count2
= counted
;
1757 for (i
= first
; i
< total
&& count2
;i
++) {
1758 struct srv_info_struct
*s
= &servers
[i
];
1760 if (lastname
&& strequal(lastname
,s
->name
)) {
1764 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1765 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1766 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1772 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1776 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1778 SSVAL(*rparam
,4,counted
);
1779 SSVAL(*rparam
,6,counted
+missed
);
1781 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1782 domain
,uLevel
,first
,first_name
,
1783 first
< total
? servers
[first
].name
: "",
1784 counted
,counted
+missed
));
1791 /****************************************************************************
1792 command 0x34 - suspected of being a "Lookup Names" stub api
1793 ****************************************************************************/
1795 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1796 connection_struct
*conn
, uint16 vuid
,
1797 char *param
, int tpscnt
,
1798 char *data
, int tdscnt
,
1799 int mdrcnt
, int mprcnt
, char **rdata
,
1800 char **rparam
, int *rdata_len
, int *rparam_len
)
1802 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1803 char *str2
= skip_string(param
,tpscnt
,str1
);
1804 char *p
= skip_string(param
,tpscnt
,str2
);
1805 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1806 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1810 if (!str1
|| !str2
|| !p
) {
1814 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1815 str1
, str2
, p
, uLevel
, buf_len
));
1817 if (!prefix_ok(str1
,"zWrLeh")) {
1824 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1829 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1831 SSVAL(*rparam
,4,counted
);
1832 SSVAL(*rparam
,6,counted
+missed
);
1837 /****************************************************************************
1838 get info about a share
1839 ****************************************************************************/
1841 static bool check_share_info(int uLevel
, char* id
)
1845 if (strcmp(id
,"B13") != 0) {
1850 /* Level-2 descriptor is allowed (and ignored) */
1851 if (strcmp(id
,"B13BWz") != 0 &&
1852 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1857 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1862 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1872 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1873 char** buf
, int* buflen
,
1874 char** stringbuf
, int* stringspace
, char* baseaddr
)
1903 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1906 len
+= strlen(lp_pathname(snum
)) + 1;
1909 *buflen
= struct_len
;
1914 return struct_len
+ len
;
1919 if ((*buflen
) < struct_len
) {
1927 p2
= p
+ struct_len
;
1928 l2
= (*buflen
) - struct_len
;
1935 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1941 type
= STYPE_DISKTREE
;
1942 if (lp_print_ok(snum
)) {
1943 type
= STYPE_PRINTQ
;
1945 if (strequal("IPC",lp_fstype(snum
))) {
1948 SSVAL(p
,14,type
); /* device type */
1949 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1950 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1954 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1955 SSVALS(p
,22,-1); /* max uses */
1956 SSVAL(p
,24,1); /* current uses */
1957 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1958 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1959 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1963 memset(p
+40,0,SHPWLEN
+2);
1974 (*buf
) = p
+ struct_len
;
1975 (*buflen
) -= struct_len
;
1977 (*stringspace
) = l2
;
1986 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
1987 connection_struct
*conn
,uint16 vuid
,
1988 char *param
, int tpscnt
,
1989 char *data
, int tdscnt
,
1990 int mdrcnt
,int mprcnt
,
1991 char **rdata
,char **rparam
,
1992 int *rdata_len
,int *rparam_len
)
1994 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1995 char *str2
= skip_string(param
,tpscnt
,str1
);
1996 char *netname
= skip_string(param
,tpscnt
,str2
);
1997 char *p
= skip_string(param
,tpscnt
,netname
);
1998 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2001 if (!str1
|| !str2
|| !netname
|| !p
) {
2005 snum
= find_service(netname
);
2010 /* check it's a supported varient */
2011 if (!prefix_ok(str1
,"zWrLh")) {
2014 if (!check_share_info(uLevel
,str2
)) {
2018 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2023 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2024 if (*rdata_len
< 0) {
2029 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2033 SSVAL(*rparam
,0,NERR_Success
);
2034 SSVAL(*rparam
,2,0); /* converter word */
2035 SSVAL(*rparam
,4,*rdata_len
);
2040 /****************************************************************************
2041 View the list of available shares.
2043 This function is the server side of the NetShareEnum() RAP call.
2044 It fills the return buffer with share names and share comments.
2045 Note that the return buffer normally (in all known cases) allows only
2046 twelve byte strings for share names (plus one for a nul terminator).
2047 Share names longer than 12 bytes must be skipped.
2048 ****************************************************************************/
2050 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2051 connection_struct
*conn
, uint16 vuid
,
2052 char *param
, int tpscnt
,
2053 char *data
, int tdscnt
,
2061 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2062 char *str2
= skip_string(param
,tpscnt
,str1
);
2063 char *p
= skip_string(param
,tpscnt
,str2
);
2064 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2065 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2068 int total
=0,counted
=0;
2069 bool missed
= False
;
2071 int data_len
, fixed_len
, string_len
;
2072 int f_len
= 0, s_len
= 0;
2074 if (!str1
|| !str2
|| !p
) {
2078 if (!prefix_ok(str1
,"WrLeh")) {
2081 if (!check_share_info(uLevel
,str2
)) {
2085 /* Ensure all the usershares are loaded. */
2087 load_registry_shares();
2088 count
= load_usershare_shares();
2091 data_len
= fixed_len
= string_len
= 0;
2092 for (i
=0;i
<count
;i
++) {
2093 fstring servicename_dos
;
2094 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2097 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2098 /* Maximum name length = 13. */
2099 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2101 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2102 if (data_len
< buf_len
) {
2105 string_len
+= s_len
;
2112 *rdata_len
= fixed_len
+ string_len
;
2113 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2118 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2123 for( i
= 0; i
< count
; i
++ ) {
2124 fstring servicename_dos
;
2125 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2129 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2130 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2131 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2138 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2142 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2144 SSVAL(*rparam
,4,counted
);
2145 SSVAL(*rparam
,6,total
);
2147 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2148 counted
,total
,uLevel
,
2149 buf_len
,*rdata_len
,mdrcnt
));
2154 /****************************************************************************
2156 ****************************************************************************/
2158 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2159 connection_struct
*conn
,uint16 vuid
,
2160 char *param
, int tpscnt
,
2161 char *data
, int tdscnt
,
2162 int mdrcnt
,int mprcnt
,
2163 char **rdata
,char **rparam
,
2164 int *rdata_len
,int *rparam_len
)
2166 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2167 char *str2
= skip_string(param
,tpscnt
,str1
);
2168 char *p
= skip_string(param
,tpscnt
,str2
);
2169 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2172 char *pathname
= NULL
;
2173 unsigned int offset
;
2175 size_t converted_size
;
2177 WERROR werr
= WERR_OK
;
2178 TALLOC_CTX
*mem_ctx
= talloc_tos();
2180 struct rpc_pipe_client
*cli
= NULL
;
2181 union srvsvc_NetShareInfo info
;
2182 struct srvsvc_NetShareInfo2 info2
;
2184 if (!str1
|| !str2
|| !p
) {
2188 /* check it's a supported varient */
2189 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2192 if (!check_share_info(uLevel
,str2
)) {
2199 /* Do we have a string ? */
2200 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2203 pull_ascii_fstring(sharename
,data
);
2209 /* only support disk share adds */
2210 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2214 offset
= IVAL(data
, 16);
2215 if (offset
>= mdrcnt
) {
2216 res
= ERRinvalidparam
;
2220 /* Do we have a string ? */
2221 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2224 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2226 offset
= IVAL(data
, 26);
2228 if (offset
>= mdrcnt
) {
2229 res
= ERRinvalidparam
;
2233 /* Do we have a string ? */
2234 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2238 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2239 offset
? (data
+offset
) : "", &converted_size
))
2241 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2249 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2251 &conn
->sconn
->client_id
,
2252 conn
->sconn
->msg_ctx
,
2254 if (!NT_STATUS_IS_OK(status
)) {
2255 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2256 nt_errstr(status
)));
2257 res
= W_ERROR_V(ntstatus_to_werror(status
));
2261 info2
.name
= sharename
;
2262 info2
.type
= STYPE_DISKTREE
;
2263 info2
.comment
= comment
;
2264 info2
.permissions
= 0;
2265 info2
.max_users
= 0;
2266 info2
.current_users
= 0;
2267 info2
.path
= pathname
;
2268 info2
.password
= NULL
;
2270 info
.info2
= &info2
;
2272 status
= rpccli_srvsvc_NetShareAdd(cli
, mem_ctx
,
2273 cli
->srv_name_slash
,
2278 if (!NT_STATUS_IS_OK(status
)) {
2279 res
= W_ERROR_V(ntstatus_to_werror(status
));
2282 if (!W_ERROR_IS_OK(werr
)) {
2283 res
= W_ERROR_V(werr
);
2288 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2292 SSVAL(*rparam
,0,NERR_Success
);
2293 SSVAL(*rparam
,2,0); /* converter word */
2294 SSVAL(*rparam
,4,*rdata_len
);
2302 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2307 SSVAL(*rparam
,0,res
);
2312 /****************************************************************************
2313 view list of groups available
2314 ****************************************************************************/
2316 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2317 connection_struct
*conn
,uint16 vuid
,
2318 char *param
, int tpscnt
,
2319 char *data
, int tdscnt
,
2320 int mdrcnt
,int mprcnt
,
2321 char **rdata
,char **rparam
,
2322 int *rdata_len
,int *rparam_len
)
2326 int resume_context
, cli_buf_size
;
2327 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2328 char *str2
= skip_string(param
,tpscnt
,str1
);
2329 char *p
= skip_string(param
,tpscnt
,str2
);
2331 uint32_t num_groups
;
2332 uint32_t resume_handle
;
2333 struct rpc_pipe_client
*samr_pipe
;
2334 struct policy_handle samr_handle
, domain_handle
;
2337 if (!str1
|| !str2
|| !p
) {
2341 if (strcmp(str1
,"WrLeh") != 0) {
2346 * W-> resume context (number of users to skip)
2347 * r -> return parameter pointer to receive buffer
2348 * L -> length of receive buffer
2349 * e -> return parameter number of entries
2350 * h -> return parameter total number of users
2353 if (strcmp("B21",str2
) != 0) {
2357 status
= rpc_pipe_open_internal(
2358 talloc_tos(), &ndr_table_samr
.syntax_id
,
2359 conn
->server_info
, &conn
->sconn
->client_id
,
2360 conn
->sconn
->msg_ctx
, &samr_pipe
);
2361 if (!NT_STATUS_IS_OK(status
)) {
2362 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2363 nt_errstr(status
)));
2367 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2368 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2369 if (!NT_STATUS_IS_OK(status
)) {
2370 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2371 nt_errstr(status
)));
2375 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2376 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2377 get_global_sam_sid(), &domain_handle
);
2378 if (!NT_STATUS_IS_OK(status
)) {
2379 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2380 nt_errstr(status
)));
2381 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2385 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2386 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2387 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2388 "%d\n", resume_context
, cli_buf_size
));
2390 *rdata_len
= cli_buf_size
;
2391 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2398 errflags
= NERR_Success
;
2403 struct samr_SamArray
*sam_entries
;
2404 uint32_t num_entries
;
2406 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2411 if (!NT_STATUS_IS_OK(status
)) {
2412 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2413 "%s\n", nt_errstr(status
)));
2417 if (num_entries
== 0) {
2418 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2419 "no entries -- done\n"));
2423 for(i
=0; i
<num_entries
; i
++) {
2426 name
= sam_entries
->entries
[i
].name
.string
;
2428 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2429 /* set overflow error */
2430 DEBUG(3,("overflow on entry %d group %s\n", i
,
2436 /* truncate the name at 21 chars. */
2438 strlcpy(p
, name
, 21);
2439 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2441 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2446 if (errflags
!= NERR_Success
) {
2450 TALLOC_FREE(sam_entries
);
2453 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2454 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2456 *rdata_len
= PTR_DIFF(p
,*rdata
);
2459 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2463 SSVAL(*rparam
, 0, errflags
);
2464 SSVAL(*rparam
, 2, 0); /* converter word */
2465 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2466 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2471 /*******************************************************************
2472 Get groups that a user is a member of.
2473 ******************************************************************/
2475 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2476 connection_struct
*conn
,uint16 vuid
,
2477 char *param
, int tpscnt
,
2478 char *data
, int tdscnt
,
2479 int mdrcnt
,int mprcnt
,
2480 char **rdata
,char **rparam
,
2481 int *rdata_len
,int *rparam_len
)
2483 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2484 char *str2
= skip_string(param
,tpscnt
,str1
);
2485 char *UserName
= skip_string(param
,tpscnt
,str2
);
2486 char *p
= skip_string(param
,tpscnt
,UserName
);
2487 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2488 const char *level_string
;
2494 struct rpc_pipe_client
*samr_pipe
;
2495 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2496 struct lsa_String name
;
2497 struct lsa_Strings names
;
2498 struct samr_Ids type
, rid
;
2499 struct samr_RidWithAttributeArray
*rids
;
2502 if (!str1
|| !str2
|| !UserName
|| !p
) {
2507 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2512 /* check it's a supported varient */
2514 if ( strcmp(str1
,"zWrLeh") != 0 )
2519 level_string
= "B21";
2525 if (strcmp(level_string
,str2
) != 0)
2528 *rdata_len
= mdrcnt
+ 1024;
2529 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2534 SSVAL(*rparam
,0,NERR_Success
);
2535 SSVAL(*rparam
,2,0); /* converter word */
2538 endp
= *rdata
+ *rdata_len
;
2540 status
= rpc_pipe_open_internal(
2541 talloc_tos(), &ndr_table_samr
.syntax_id
,
2542 conn
->server_info
, &conn
->sconn
->client_id
,
2543 conn
->sconn
->msg_ctx
, &samr_pipe
);
2544 if (!NT_STATUS_IS_OK(status
)) {
2545 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2546 nt_errstr(status
)));
2550 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2551 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2552 if (!NT_STATUS_IS_OK(status
)) {
2553 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2554 nt_errstr(status
)));
2558 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2559 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2560 get_global_sam_sid(), &domain_handle
);
2561 if (!NT_STATUS_IS_OK(status
)) {
2562 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2563 nt_errstr(status
)));
2567 name
.string
= UserName
;
2569 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2570 &domain_handle
, 1, &name
,
2572 if (!NT_STATUS_IS_OK(status
)) {
2573 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2574 nt_errstr(status
)));
2578 if (type
.ids
[0] != SID_NAME_USER
) {
2579 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2580 sid_type_lookup(type
.ids
[0])));
2584 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2586 SAMR_USER_ACCESS_GET_GROUPS
,
2587 rid
.ids
[0], &user_handle
);
2588 if (!NT_STATUS_IS_OK(status
)) {
2589 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2590 nt_errstr(status
)));
2594 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2595 &user_handle
, &rids
);
2596 if (!NT_STATUS_IS_OK(status
)) {
2597 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2598 nt_errstr(status
)));
2602 for (i
=0; i
<rids
->count
; i
++) {
2604 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2606 1, &rids
->rids
[i
].rid
,
2608 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2609 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2615 *rdata_len
= PTR_DIFF(p
,*rdata
);
2617 SSVAL(*rparam
,4,count
); /* is this right?? */
2618 SSVAL(*rparam
,6,count
); /* is this right?? */
2623 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2625 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2627 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2632 /*******************************************************************
2634 ******************************************************************/
2636 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2637 connection_struct
*conn
, uint16 vuid
,
2638 char *param
, int tpscnt
,
2639 char *data
, int tdscnt
,
2640 int mdrcnt
,int mprcnt
,
2641 char **rdata
,char **rparam
,
2642 int *rdata_len
,int *rparam_len
)
2647 int i
, resume_context
, cli_buf_size
;
2648 uint32_t resume_handle
;
2650 struct rpc_pipe_client
*samr_pipe
;
2651 struct policy_handle samr_handle
, domain_handle
;
2654 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2655 char *str2
= skip_string(param
,tpscnt
,str1
);
2656 char *p
= skip_string(param
,tpscnt
,str2
);
2659 if (!str1
|| !str2
|| !p
) {
2663 if (strcmp(str1
,"WrLeh") != 0)
2666 * W-> resume context (number of users to skip)
2667 * r -> return parameter pointer to receive buffer
2668 * L -> length of receive buffer
2669 * e -> return parameter number of entries
2670 * h -> return parameter total number of users
2673 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2674 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2675 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2676 resume_context
, cli_buf_size
));
2679 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2684 /* check it's a supported varient */
2685 if (strcmp("B21",str2
) != 0)
2688 *rdata_len
= cli_buf_size
;
2689 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2695 endp
= *rdata
+ *rdata_len
;
2697 status
= rpc_pipe_open_internal(
2698 talloc_tos(), &ndr_table_samr
.syntax_id
,
2699 conn
->server_info
, &conn
->sconn
->client_id
,
2700 conn
->sconn
->msg_ctx
, &samr_pipe
);
2701 if (!NT_STATUS_IS_OK(status
)) {
2702 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2703 nt_errstr(status
)));
2707 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2708 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2709 if (!NT_STATUS_IS_OK(status
)) {
2710 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2711 nt_errstr(status
)));
2715 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2716 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2717 get_global_sam_sid(), &domain_handle
);
2718 if (!NT_STATUS_IS_OK(status
)) {
2719 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2720 nt_errstr(status
)));
2721 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2725 errflags
=NERR_Success
;
2730 struct samr_SamArray
*sam_entries
;
2731 uint32_t num_entries
;
2733 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2739 if (!NT_STATUS_IS_OK(status
)) {
2740 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2741 "%s\n", nt_errstr(status
)));
2745 if (num_entries
== 0) {
2746 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2747 "no entries -- done\n"));
2751 for (i
=0; i
<num_entries
; i
++) {
2754 name
= sam_entries
->entries
[i
].name
.string
;
2756 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2757 &&(strlen(name
)<=21)) {
2758 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2759 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2760 "username %s\n",count_sent
,p
));
2764 /* set overflow error */
2765 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2766 "username %s\n",count_sent
,name
));
2772 if (errflags
!= NERR_Success
) {
2776 TALLOC_FREE(sam_entries
);
2779 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2780 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2782 *rdata_len
= PTR_DIFF(p
,*rdata
);
2784 SSVAL(*rparam
,0,errflags
);
2785 SSVAL(*rparam
,2,0); /* converter word */
2786 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2787 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2792 /****************************************************************************
2793 Get the time of day info.
2794 ****************************************************************************/
2796 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2797 connection_struct
*conn
,uint16 vuid
,
2798 char *param
, int tpscnt
,
2799 char *data
, int tdscnt
,
2800 int mdrcnt
,int mprcnt
,
2801 char **rdata
,char **rparam
,
2802 int *rdata_len
,int *rparam_len
)
2805 time_t unixdate
= time(NULL
);
2809 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2815 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2820 SSVAL(*rparam
,0,NERR_Success
);
2821 SSVAL(*rparam
,2,0); /* converter word */
2825 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2826 by NT in a "net time" operation,
2827 it seems to ignore the one below */
2829 /* the client expects to get localtime, not GMT, in this bit
2830 (I think, this needs testing) */
2831 t
= localtime(&unixdate
);
2836 SIVAL(p
,4,0); /* msecs ? */
2837 SCVAL(p
,8,t
->tm_hour
);
2838 SCVAL(p
,9,t
->tm_min
);
2839 SCVAL(p
,10,t
->tm_sec
);
2840 SCVAL(p
,11,0); /* hundredths of seconds */
2841 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2842 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2843 SCVAL(p
,16,t
->tm_mday
);
2844 SCVAL(p
,17,t
->tm_mon
+ 1);
2845 SSVAL(p
,18,1900+t
->tm_year
);
2846 SCVAL(p
,20,t
->tm_wday
);
2851 /****************************************************************************
2852 Set the user password.
2853 *****************************************************************************/
2855 static bool api_SetUserPassword(struct smbd_server_connection
*sconn
,
2856 connection_struct
*conn
,uint16 vuid
,
2857 char *param
, int tpscnt
,
2858 char *data
, int tdscnt
,
2859 int mdrcnt
,int mprcnt
,
2860 char **rdata
,char **rparam
,
2861 int *rdata_len
,int *rparam_len
)
2863 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2866 fstring pass1
,pass2
;
2867 TALLOC_CTX
*mem_ctx
= talloc_tos();
2869 struct rpc_pipe_client
*cli
= NULL
;
2870 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2871 struct lsa_String domain_name
;
2872 struct dom_sid2
*domain_sid
;
2873 struct lsa_String names
;
2874 struct samr_Ids rids
;
2875 struct samr_Ids types
;
2876 struct samr_Password old_lm_hash
;
2877 struct samr_Password new_lm_hash
;
2878 int errcode
= NERR_badpass
;
2883 /* Skip 2 strings. */
2884 p
= skip_string(param
,tpscnt
,np
);
2885 p
= skip_string(param
,tpscnt
,p
);
2891 /* Do we have a string ? */
2892 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2895 pull_ascii_fstring(user
,p
);
2897 p
= skip_string(param
,tpscnt
,p
);
2902 memset(pass1
,'\0',sizeof(pass1
));
2903 memset(pass2
,'\0',sizeof(pass2
));
2905 * We use 31 here not 32 as we're checking
2906 * the last byte we want to access is safe.
2908 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2912 memcpy(pass2
,p
+16,16);
2914 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
2915 if (encrypted
== -1) {
2916 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2920 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
2921 if (min_pwd_length
== -1) {
2922 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2927 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2934 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2935 user
, encrypted
, min_pwd_length
));
2937 ZERO_STRUCT(connect_handle
);
2938 ZERO_STRUCT(domain_handle
);
2939 ZERO_STRUCT(user_handle
);
2941 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
2943 &conn
->sconn
->client_id
,
2944 conn
->sconn
->msg_ctx
,
2946 if (!NT_STATUS_IS_OK(status
)) {
2947 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2948 nt_errstr(status
)));
2949 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2953 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
2955 SAMR_ACCESS_CONNECT_TO_SERVER
|
2956 SAMR_ACCESS_ENUM_DOMAINS
|
2957 SAMR_ACCESS_LOOKUP_DOMAIN
,
2959 if (!NT_STATUS_IS_OK(status
)) {
2960 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2964 init_lsa_String(&domain_name
, get_global_sam_name());
2966 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
2970 if (!NT_STATUS_IS_OK(status
)) {
2971 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2975 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
2977 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2980 if (!NT_STATUS_IS_OK(status
)) {
2981 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2985 init_lsa_String(&names
, user
);
2987 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
2993 if (!NT_STATUS_IS_OK(status
)) {
2994 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2998 if (rids
.count
!= 1) {
2999 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
3002 if (rids
.count
!= types
.count
) {
3003 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3006 if (types
.ids
[0] != SID_NAME_USER
) {
3007 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3013 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
3015 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
3018 if (!NT_STATUS_IS_OK(status
)) {
3019 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3023 if (encrypted
== 0) {
3024 E_deshash(pass1
, old_lm_hash
.hash
);
3025 E_deshash(pass2
, new_lm_hash
.hash
);
3027 ZERO_STRUCT(old_lm_hash
);
3028 ZERO_STRUCT(new_lm_hash
);
3029 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
3030 memcpy(new_lm_hash
.hash
, pass1
, MIN(strlen(pass2
), 16));
3033 status
= rpccli_samr_ChangePasswordUser(cli
, mem_ctx
,
3035 true, /* lm_present */
3038 false, /* nt_present */
3039 NULL
, /* old_nt_crypted */
3040 NULL
, /* new_nt_crypted */
3041 false, /* cross1_present */
3042 NULL
, /* nt_cross */
3043 false, /* cross2_present */
3044 NULL
); /* lm_cross */
3045 if (!NT_STATUS_IS_OK(status
)) {
3046 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3050 errcode
= NERR_Success
;
3053 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
3054 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
3056 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
3057 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
3059 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
3060 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
3063 memset((char *)pass1
,'\0',sizeof(fstring
));
3064 memset((char *)pass2
,'\0',sizeof(fstring
));
3066 SSVAL(*rparam
,0,errcode
);
3067 SSVAL(*rparam
,2,0); /* converter word */
3071 /****************************************************************************
3072 Set the user password (SamOEM version - gets plaintext).
3073 ****************************************************************************/
3075 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3076 connection_struct
*conn
,uint16 vuid
,
3077 char *param
, int tpscnt
,
3078 char *data
, int tdscnt
,
3079 int mdrcnt
,int mprcnt
,
3080 char **rdata
,char **rparam
,
3081 int *rdata_len
,int *rparam_len
)
3084 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3086 TALLOC_CTX
*mem_ctx
= talloc_tos();
3088 struct rpc_pipe_client
*cli
= NULL
;
3089 struct lsa_AsciiString server
, account
;
3090 struct samr_CryptPassword password
;
3091 struct samr_Password hash
;
3092 int errcode
= NERR_badpass
;
3096 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3106 SSVAL(*rparam
,0,NERR_badpass
);
3109 * Check the parameter definition is correct.
3112 /* Do we have a string ? */
3113 if (skip_string(param
,tpscnt
,p
) == 0) {
3116 if(!strequal(p
, "zsT")) {
3117 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3120 p
= skip_string(param
, tpscnt
, p
);
3125 /* Do we have a string ? */
3126 if (skip_string(param
,tpscnt
,p
) == 0) {
3129 if(!strequal(p
, "B516B16")) {
3130 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3133 p
= skip_string(param
,tpscnt
,p
);
3137 /* Do we have a string ? */
3138 if (skip_string(param
,tpscnt
,p
) == 0) {
3141 p
+= pull_ascii_fstring(user
,p
);
3143 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3145 if (tdscnt
!= 532) {
3146 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3150 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3151 if (bufsize
!= 532) {
3152 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3156 memcpy(password
.data
, data
, 516);
3157 memcpy(hash
.hash
, data
+516, 16);
3159 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3161 &conn
->sconn
->client_id
,
3162 conn
->sconn
->msg_ctx
,
3164 if (!NT_STATUS_IS_OK(status
)) {
3165 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3166 nt_errstr(status
)));
3167 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3171 init_lsa_AsciiString(&server
, global_myname());
3172 init_lsa_AsciiString(&account
, user
);
3174 status
= rpccli_samr_OemChangePasswordUser2(cli
, mem_ctx
,
3179 if (!NT_STATUS_IS_OK(status
)) {
3180 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3184 errcode
= NERR_Success
;
3186 SSVAL(*rparam
,0,errcode
);
3187 SSVAL(*rparam
,2,0); /* converter word */
3192 /****************************************************************************
3195 ****************************************************************************/
3197 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3198 connection_struct
*conn
,uint16 vuid
,
3199 char *param
, int tpscnt
,
3200 char *data
, int tdscnt
,
3201 int mdrcnt
,int mprcnt
,
3202 char **rdata
,char **rparam
,
3203 int *rdata_len
,int *rparam_len
)
3205 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3206 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3207 char *str2
= skip_string(param
,tpscnt
,str1
);
3208 char *p
= skip_string(param
,tpscnt
,str2
);
3212 WERROR werr
= WERR_OK
;
3214 TALLOC_CTX
*mem_ctx
= talloc_tos();
3216 struct rpc_pipe_client
*cli
= NULL
;
3217 struct policy_handle handle
;
3218 struct spoolss_DevmodeContainer devmode_ctr
;
3219 enum spoolss_JobControl command
;
3221 if (!str1
|| !str2
|| !p
) {
3225 * We use 1 here not 2 as we're checking
3226 * the last byte we want to access is safe.
3228 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3231 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3234 /* check it's a supported varient */
3235 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3239 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3245 ZERO_STRUCT(handle
);
3247 status
= rpc_pipe_open_interface(conn
,
3248 &ndr_table_spoolss
.syntax_id
,
3250 &conn
->sconn
->client_id
,
3251 conn
->sconn
->msg_ctx
,
3253 if (!NT_STATUS_IS_OK(status
)) {
3254 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3255 nt_errstr(status
)));
3256 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3260 ZERO_STRUCT(devmode_ctr
);
3262 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3266 JOB_ACCESS_ADMINISTER
,
3269 if (!NT_STATUS_IS_OK(status
)) {
3270 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3273 if (!W_ERROR_IS_OK(werr
)) {
3274 errcode
= W_ERROR_V(werr
);
3278 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3279 * and NERR_DestNotFound if share did not exist */
3281 errcode
= NERR_Success
;
3284 case 81: /* delete */
3285 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3287 case 82: /* pause */
3288 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3290 case 83: /* resume */
3291 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3294 errcode
= NERR_notsupported
;
3298 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3301 NULL
, /* unique ptr ctr */
3304 if (!NT_STATUS_IS_OK(status
)) {
3305 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3308 if (!W_ERROR_IS_OK(werr
)) {
3309 errcode
= W_ERROR_V(werr
);
3314 if (cli
&& is_valid_policy_hnd(&handle
)) {
3315 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3318 SSVAL(*rparam
,0,errcode
);
3319 SSVAL(*rparam
,2,0); /* converter word */
3324 /****************************************************************************
3325 Purge a print queue - or pause or resume it.
3326 ****************************************************************************/
3328 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3329 connection_struct
*conn
,uint16 vuid
,
3330 char *param
, int tpscnt
,
3331 char *data
, int tdscnt
,
3332 int mdrcnt
,int mprcnt
,
3333 char **rdata
,char **rparam
,
3334 int *rdata_len
,int *rparam_len
)
3336 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3337 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3338 char *str2
= skip_string(param
,tpscnt
,str1
);
3339 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3340 int errcode
= NERR_notsupported
;
3341 WERROR werr
= WERR_OK
;
3344 TALLOC_CTX
*mem_ctx
= talloc_tos();
3345 struct rpc_pipe_client
*cli
= NULL
;
3346 struct policy_handle handle
;
3347 struct spoolss_SetPrinterInfoCtr info_ctr
;
3348 struct spoolss_DevmodeContainer devmode_ctr
;
3349 struct sec_desc_buf secdesc_ctr
;
3350 enum spoolss_PrinterControl command
;
3352 if (!str1
|| !str2
|| !QueueName
) {
3356 /* check it's a supported varient */
3357 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3361 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3367 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3371 ZERO_STRUCT(handle
);
3373 status
= rpc_pipe_open_interface(conn
,
3374 &ndr_table_spoolss
.syntax_id
,
3376 &conn
->sconn
->client_id
,
3377 conn
->sconn
->msg_ctx
,
3379 if (!NT_STATUS_IS_OK(status
)) {
3380 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3381 nt_errstr(status
)));
3382 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3386 ZERO_STRUCT(devmode_ctr
);
3388 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3392 SEC_FLAG_MAXIMUM_ALLOWED
,
3395 if (!NT_STATUS_IS_OK(status
)) {
3396 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3399 if (!W_ERROR_IS_OK(werr
)) {
3400 errcode
= W_ERROR_V(werr
);
3405 case 74: /* Pause queue */
3406 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3408 case 75: /* Resume queue */
3409 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3411 case 103: /* Purge */
3412 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3415 werr
= WERR_NOT_SUPPORTED
;
3419 if (!W_ERROR_IS_OK(werr
)) {
3420 errcode
= W_ERROR_V(werr
);
3424 ZERO_STRUCT(info_ctr
);
3425 ZERO_STRUCT(secdesc_ctr
);
3427 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3434 if (!NT_STATUS_IS_OK(status
)) {
3435 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3438 if (!W_ERROR_IS_OK(werr
)) {
3439 errcode
= W_ERROR_V(werr
);
3443 errcode
= W_ERROR_V(werr
);
3447 if (cli
&& is_valid_policy_hnd(&handle
)) {
3448 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3451 SSVAL(*rparam
,0,errcode
);
3452 SSVAL(*rparam
,2,0); /* converter word */
3457 /****************************************************************************
3458 set the property of a print job (undocumented?)
3459 ? function = 0xb -> set name of print job
3460 ? function = 0x6 -> move print job up/down
3461 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3462 or <WWsTP> <WB21BB16B10zWWzDDz>
3463 ****************************************************************************/
3465 static int check_printjob_info(struct pack_desc
* desc
,
3466 int uLevel
, char* id
)
3468 desc
->subformat
= NULL
;
3470 case 0: desc
->format
= "W"; break;
3471 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3472 case 2: desc
->format
= "WWzWWDDzz"; break;
3473 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3474 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3476 DEBUG(0,("check_printjob_info: invalid level %d\n",
3480 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3481 DEBUG(0,("check_printjob_info: invalid format %s\n",
3482 id
? id
: "<NULL>" ));
3488 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3489 connection_struct
*conn
, uint16 vuid
,
3490 char *param
, int tpscnt
,
3491 char *data
, int tdscnt
,
3492 int mdrcnt
,int mprcnt
,
3493 char **rdata
,char **rparam
,
3494 int *rdata_len
,int *rparam_len
)
3496 struct pack_desc desc
;
3497 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3498 char *str2
= skip_string(param
,tpscnt
,str1
);
3499 char *p
= skip_string(param
,tpscnt
,str2
);
3502 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3503 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3506 TALLOC_CTX
*mem_ctx
= talloc_tos();
3509 struct rpc_pipe_client
*cli
= NULL
;
3510 struct policy_handle handle
;
3511 struct spoolss_DevmodeContainer devmode_ctr
;
3512 struct spoolss_JobInfoContainer ctr
;
3513 union spoolss_JobInfo info
;
3514 struct spoolss_SetJobInfo1 info1
;
3516 if (!str1
|| !str2
|| !p
) {
3520 * We use 1 here not 2 as we're checking
3521 * the last byte we want to access is safe.
3523 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3526 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3529 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3536 /* check it's a supported varient */
3537 if ((strcmp(str1
,"WWsTP")) ||
3538 (!check_printjob_info(&desc
,uLevel
,str2
)))
3541 errcode
= NERR_notsupported
;
3545 /* change print job name, data gives the name */
3551 ZERO_STRUCT(handle
);
3553 status
= rpc_pipe_open_interface(conn
,
3554 &ndr_table_spoolss
.syntax_id
,
3556 &conn
->sconn
->client_id
,
3557 conn
->sconn
->msg_ctx
,
3559 if (!NT_STATUS_IS_OK(status
)) {
3560 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3561 nt_errstr(status
)));
3562 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3566 ZERO_STRUCT(devmode_ctr
);
3568 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3575 if (!NT_STATUS_IS_OK(status
)) {
3576 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3579 if (!W_ERROR_IS_OK(werr
)) {
3580 errcode
= W_ERROR_V(werr
);
3584 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3590 if (!W_ERROR_IS_OK(werr
)) {
3591 errcode
= W_ERROR_V(werr
);
3597 info1
.job_id
= info
.info1
.job_id
;
3598 info1
.printer_name
= info
.info1
.printer_name
;
3599 info1
.user_name
= info
.info1
.user_name
;
3600 info1
.document_name
= data
;
3601 info1
.data_type
= info
.info1
.data_type
;
3602 info1
.text_status
= info
.info1
.text_status
;
3603 info1
.status
= info
.info1
.status
;
3604 info1
.priority
= info
.info1
.priority
;
3605 info1
.position
= info
.info1
.position
;
3606 info1
.total_pages
= info
.info1
.total_pages
;
3607 info1
.pages_printed
= info
.info1
.pages_printed
;
3608 info1
.submitted
= info
.info1
.submitted
;
3611 ctr
.info
.info1
= &info1
;
3613 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3619 if (!NT_STATUS_IS_OK(status
)) {
3620 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3623 if (!W_ERROR_IS_OK(werr
)) {
3624 errcode
= W_ERROR_V(werr
);
3628 errcode
= NERR_Success
;
3631 if (cli
&& is_valid_policy_hnd(&handle
)) {
3632 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3635 SSVALS(*rparam
,0,errcode
);
3636 SSVAL(*rparam
,2,0); /* converter word */
3642 /****************************************************************************
3643 Get info about the server.
3644 ****************************************************************************/
3646 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3647 connection_struct
*conn
,uint16 vuid
,
3648 char *param
, int tpscnt
,
3649 char *data
, int tdscnt
,
3650 int mdrcnt
,int mprcnt
,
3651 char **rdata
,char **rparam
,
3652 int *rdata_len
,int *rparam_len
)
3654 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3655 char *str2
= skip_string(param
,tpscnt
,str1
);
3656 char *p
= skip_string(param
,tpscnt
,str2
);
3657 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3663 TALLOC_CTX
*mem_ctx
= talloc_tos();
3664 struct rpc_pipe_client
*cli
= NULL
;
3665 union srvsvc_NetSrvInfo info
;
3668 if (!str1
|| !str2
|| !p
) {
3672 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3674 /* check it's a supported varient */
3675 if (!prefix_ok(str1
,"WrLh")) {
3681 if (strcmp(str2
,"B16") != 0) {
3687 if (strcmp(str2
,"B16BBDz") != 0) {
3693 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3699 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3705 if (strcmp(str2
,"DN") != 0) {
3711 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3720 *rdata_len
= mdrcnt
;
3721 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3727 p2
= p
+ struct_len
;
3729 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3731 &conn
->sconn
->client_id
,
3732 conn
->sconn
->msg_ctx
,
3734 if (!NT_STATUS_IS_OK(status
)) {
3735 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3736 nt_errstr(status
)));
3737 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3741 status
= rpccli_srvsvc_NetSrvGetInfo(cli
, mem_ctx
,
3746 if (!NT_STATUS_IS_OK(status
)) {
3747 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3750 if (!W_ERROR_IS_OK(werr
)) {
3751 errcode
= W_ERROR_V(werr
);
3755 if (info
.info101
== NULL
) {
3756 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3761 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3762 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3766 SCVAL(p
,0,info
.info101
->version_major
);
3767 SCVAL(p
,1,info
.info101
->version_minor
);
3768 SIVAL(p
,2,info
.info101
->server_type
);
3770 if (mdrcnt
== struct_len
) {
3773 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3774 if (mdrcnt
- struct_len
<= 0) {
3778 info
.info101
->comment
,
3779 MIN(mdrcnt
- struct_len
,
3780 MAX_SERVER_STRING_LENGTH
),
3782 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3790 return False
; /* not yet implemented */
3793 errcode
= NERR_Success
;
3797 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3800 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3804 SSVAL(*rparam
,0,errcode
);
3805 SSVAL(*rparam
,2,0); /* converter word */
3806 SSVAL(*rparam
,4,*rdata_len
);
3811 /****************************************************************************
3812 Get info about the server.
3813 ****************************************************************************/
3815 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3816 connection_struct
*conn
,uint16 vuid
,
3817 char *param
, int tpscnt
,
3818 char *data
, int tdscnt
,
3819 int mdrcnt
,int mprcnt
,
3820 char **rdata
,char **rparam
,
3821 int *rdata_len
,int *rparam_len
)
3823 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3824 char *str2
= skip_string(param
,tpscnt
,str1
);
3825 char *p
= skip_string(param
,tpscnt
,str2
);
3828 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3830 if (!str1
|| !str2
|| !p
) {
3834 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3837 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3842 /* check it's a supported varient */
3843 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3847 *rdata_len
= mdrcnt
+ 1024;
3848 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3853 SSVAL(*rparam
,0,NERR_Success
);
3854 SSVAL(*rparam
,2,0); /* converter word */
3857 endp
= *rdata
+ *rdata_len
;
3859 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3864 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3865 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3867 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3873 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3874 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3875 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3881 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3882 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3884 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3890 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3891 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3894 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3895 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3896 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3902 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3903 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3904 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3910 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3912 SSVAL(*rparam
,4,*rdata_len
);
3917 /****************************************************************************
3918 get info about a user
3920 struct user_info_11 {
3921 char usri11_name[21]; 0-20
3923 char *usri11_comment; 22-25
3924 char *usri11_usr_comment; 26-29
3925 unsigned short usri11_priv; 30-31
3926 unsigned long usri11_auth_flags; 32-35
3927 long usri11_password_age; 36-39
3928 char *usri11_homedir; 40-43
3929 char *usri11_parms; 44-47
3930 long usri11_last_logon; 48-51
3931 long usri11_last_logoff; 52-55
3932 unsigned short usri11_bad_pw_count; 56-57
3933 unsigned short usri11_num_logons; 58-59
3934 char *usri11_logon_server; 60-63
3935 unsigned short usri11_country_code; 64-65
3936 char *usri11_workstations; 66-69
3937 unsigned long usri11_max_storage; 70-73
3938 unsigned short usri11_units_per_week; 74-75
3939 unsigned char *usri11_logon_hours; 76-79
3940 unsigned short usri11_code_page; 80-81
3945 usri11_name specifies the user name for which information is retrieved
3947 usri11_pad aligns the next data structure element to a word boundary
3949 usri11_comment is a null terminated ASCII comment
3951 usri11_user_comment is a null terminated ASCII comment about the user
3953 usri11_priv specifies the level of the privilege assigned to the user.
3954 The possible values are:
3956 Name Value Description
3957 USER_PRIV_GUEST 0 Guest privilege
3958 USER_PRIV_USER 1 User privilege
3959 USER_PRV_ADMIN 2 Administrator privilege
3961 usri11_auth_flags specifies the account operator privileges. The
3962 possible values are:
3964 Name Value Description
3965 AF_OP_PRINT 0 Print operator
3968 Leach, Naik [Page 28]
3972 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3975 AF_OP_COMM 1 Communications operator
3976 AF_OP_SERVER 2 Server operator
3977 AF_OP_ACCOUNTS 3 Accounts operator
3980 usri11_password_age specifies how many seconds have elapsed since the
3981 password was last changed.
3983 usri11_home_dir points to a null terminated ASCII string that contains
3984 the path name of the user's home directory.
3986 usri11_parms points to a null terminated ASCII string that is set
3987 aside for use by applications.
3989 usri11_last_logon specifies the time when the user last logged on.
3990 This value is stored as the number of seconds elapsed since
3991 00:00:00, January 1, 1970.
3993 usri11_last_logoff specifies the time when the user last logged off.
3994 This value is stored as the number of seconds elapsed since
3995 00:00:00, January 1, 1970. A value of 0 means the last logoff
3998 usri11_bad_pw_count specifies the number of incorrect passwords
3999 entered since the last successful logon.
4001 usri11_log1_num_logons specifies the number of times this user has
4002 logged on. A value of -1 means the number of logons is unknown.
4004 usri11_logon_server points to a null terminated ASCII string that
4005 contains the name of the server to which logon requests are sent.
4006 A null string indicates logon requests should be sent to the
4009 usri11_country_code specifies the country code for the user's language
4012 usri11_workstations points to a null terminated ASCII string that
4013 contains the names of workstations the user may log on from.
4014 There may be up to 8 workstations, with the names separated by
4015 commas. A null strings indicates there are no restrictions.
4017 usri11_max_storage specifies the maximum amount of disk space the user
4018 can occupy. A value of 0xffffffff indicates there are no
4021 usri11_units_per_week specifies the equal number of time units into
4022 which a week is divided. This value must be equal to 168.
4024 usri11_logon_hours points to a 21 byte (168 bits) string that
4025 specifies the time during which the user can log on. Each bit
4026 represents one unique hour in a week. The first bit (bit 0, word
4027 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4031 Leach, Naik [Page 29]
4035 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4038 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4039 are no restrictions.
4041 usri11_code_page specifies the code page for the user's language of
4044 All of the pointers in this data structure need to be treated
4045 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4046 to be ignored. The converter word returned in the parameters section
4047 needs to be subtracted from the lower 16 bits to calculate an offset
4048 into the return buffer where this ASCII string resides.
4050 There is no auxiliary data in the response.
4052 ****************************************************************************/
4054 #define usri11_name 0
4055 #define usri11_pad 21
4056 #define usri11_comment 22
4057 #define usri11_usr_comment 26
4058 #define usri11_full_name 30
4059 #define usri11_priv 34
4060 #define usri11_auth_flags 36
4061 #define usri11_password_age 40
4062 #define usri11_homedir 44
4063 #define usri11_parms 48
4064 #define usri11_last_logon 52
4065 #define usri11_last_logoff 56
4066 #define usri11_bad_pw_count 60
4067 #define usri11_num_logons 62
4068 #define usri11_logon_server 64
4069 #define usri11_country_code 68
4070 #define usri11_workstations 70
4071 #define usri11_max_storage 74
4072 #define usri11_units_per_week 78
4073 #define usri11_logon_hours 80
4074 #define usri11_code_page 84
4075 #define usri11_end 86
4077 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4078 connection_struct
*conn
, uint16 vuid
,
4079 char *param
, int tpscnt
,
4080 char *data
, int tdscnt
,
4081 int mdrcnt
,int mprcnt
,
4082 char **rdata
,char **rparam
,
4083 int *rdata_len
,int *rparam_len
)
4085 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4086 char *str2
= skip_string(param
,tpscnt
,str1
);
4087 char *UserName
= skip_string(param
,tpscnt
,str2
);
4088 char *p
= skip_string(param
,tpscnt
,UserName
);
4089 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4092 const char *level_string
;
4094 TALLOC_CTX
*mem_ctx
= talloc_tos();
4096 struct rpc_pipe_client
*cli
= NULL
;
4097 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4098 struct lsa_String domain_name
;
4099 struct dom_sid2
*domain_sid
;
4100 struct lsa_String names
;
4101 struct samr_Ids rids
;
4102 struct samr_Ids types
;
4103 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4105 union samr_UserInfo
*info
;
4107 if (!str1
|| !str2
|| !UserName
|| !p
) {
4112 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4117 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4119 /* check it's a supported variant */
4120 if (strcmp(str1
,"zWrLh") != 0) {
4124 case 0: level_string
= "B21"; break;
4125 case 1: level_string
= "B21BB16DWzzWz"; break;
4126 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4127 case 10: level_string
= "B21Bzzz"; break;
4128 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4129 default: return False
;
4132 if (strcmp(level_string
,str2
) != 0) {
4136 *rdata_len
= mdrcnt
+ 1024;
4137 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4143 endp
= *rdata
+ *rdata_len
;
4144 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4149 ZERO_STRUCT(connect_handle
);
4150 ZERO_STRUCT(domain_handle
);
4151 ZERO_STRUCT(user_handle
);
4153 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
4155 &conn
->sconn
->client_id
,
4156 conn
->sconn
->msg_ctx
,
4158 if (!NT_STATUS_IS_OK(status
)) {
4159 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4160 nt_errstr(status
)));
4161 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4165 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
4167 SAMR_ACCESS_CONNECT_TO_SERVER
|
4168 SAMR_ACCESS_ENUM_DOMAINS
|
4169 SAMR_ACCESS_LOOKUP_DOMAIN
,
4171 if (!NT_STATUS_IS_OK(status
)) {
4172 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4176 init_lsa_String(&domain_name
, get_global_sam_name());
4178 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
4182 if (!NT_STATUS_IS_OK(status
)) {
4183 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4187 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
4189 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4192 if (!NT_STATUS_IS_OK(status
)) {
4193 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4197 init_lsa_String(&names
, UserName
);
4199 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
4205 if (!NT_STATUS_IS_OK(status
)) {
4206 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4210 if (rids
.count
!= 1) {
4211 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4214 if (rids
.count
!= types
.count
) {
4215 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4218 if (types
.ids
[0] != SID_NAME_USER
) {
4219 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4225 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
4227 SAMR_USER_ACCESS_GET_LOCALE
|
4228 SAMR_USER_ACCESS_GET_LOGONINFO
|
4229 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4230 SAMR_USER_ACCESS_GET_GROUPS
|
4231 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4232 SEC_STD_READ_CONTROL
,
4235 if (!NT_STATUS_IS_OK(status
)) {
4236 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4240 status
= rpccli_samr_QueryUserInfo2(cli
, mem_ctx
,
4244 if (!NT_STATUS_IS_OK(status
)) {
4245 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4250 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4253 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4258 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4259 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4260 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4265 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4266 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4267 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4272 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4273 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4274 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4275 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4282 const char *homedir
= info
->info21
.home_directory
.string
;
4283 /* modelled after NTAS 3.51 reply */
4284 SSVAL(p
,usri11_priv
,
4285 (get_current_uid(conn
) == sec_initial_uid())?
4286 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4287 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4288 SIVALS(p
,usri11_password_age
,-1); /* password age */
4289 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4290 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4291 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4295 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4296 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4297 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4301 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4302 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4303 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4304 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4305 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4306 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4307 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4311 SSVAL(p
,usri11_country_code
,0); /* country code */
4313 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4314 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4315 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4320 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4321 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4322 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4324 /* a simple way to get logon hours at all times. */
4326 SCVAL(p2
,21,0); /* fix zero termination */
4327 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4332 SSVAL(p
,usri11_code_page
,0); /* code page */
4335 if (uLevel
== 1 || uLevel
== 2) {
4336 memset(p
+22,' ',16); /* password */
4337 SIVALS(p
,38,-1); /* password age */
4339 (get_current_uid(conn
) == sec_initial_uid())?
4340 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4341 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4342 strlcpy(p2
, info
->info21
.home_directory
.string
,
4344 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4348 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4350 SSVAL(p
,52,0); /* flags */
4351 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4352 strlcpy(p2
, info
->info21
.logon_script
.string
,
4354 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4359 SIVAL(p
,58,0); /* auth_flags */
4360 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4361 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4362 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4366 SIVAL(p
,66,0); /* urs_comment */
4367 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4368 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4369 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4373 SIVAL(p
,74,0); /* workstations */
4374 SIVAL(p
,78,0); /* last_logon */
4375 SIVAL(p
,82,0); /* last_logoff */
4376 SIVALS(p
,86,-1); /* acct_expires */
4377 SIVALS(p
,90,-1); /* max_storage */
4378 SSVAL(p
,94,168); /* units_per_week */
4379 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4382 SSVALS(p
,100,-1); /* bad_pw_count */
4383 SSVALS(p
,102,-1); /* num_logons */
4384 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4386 TALLOC_CTX
*ctx
= talloc_tos();
4387 int space_rem
= *rdata_len
- (p2
- *rdata
);
4390 if (space_rem
<= 0) {
4393 tmp
= talloc_strdup(ctx
, "\\\\%L");
4397 tmp
= talloc_sub_basic(ctx
,
4410 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4414 SSVAL(p
,108,49); /* country_code */
4415 SSVAL(p
,110,860); /* code page */
4419 errcode
= NERR_Success
;
4422 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4424 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
4425 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
4427 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
4428 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
4430 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
4431 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
4434 SSVAL(*rparam
,0,errcode
);
4435 SSVAL(*rparam
,2,0); /* converter word */
4436 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4441 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4442 connection_struct
*conn
,uint16 vuid
,
4443 char *param
, int tpscnt
,
4444 char *data
, int tdscnt
,
4445 int mdrcnt
,int mprcnt
,
4446 char **rdata
,char **rparam
,
4447 int *rdata_len
,int *rparam_len
)
4449 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4450 char *str2
= skip_string(param
,tpscnt
,str1
);
4451 char *p
= skip_string(param
,tpscnt
,str2
);
4453 struct pack_desc desc
;
4455 /* With share level security vuid will always be zero.
4456 Don't depend on vuser being non-null !!. JRA */
4457 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4459 if (!str1
|| !str2
|| !p
) {
4464 DEBUG(3,(" Username of UID %d is %s\n",
4465 (int)vuser
->server_info
->utok
.uid
,
4466 vuser
->server_info
->unix_name
));
4469 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4470 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4475 memset((char *)&desc
,'\0',sizeof(desc
));
4477 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4479 /* check it's a supported varient */
4480 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4483 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4487 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4494 desc
.buflen
= mdrcnt
;
4495 desc
.subformat
= NULL
;
4498 if (init_package(&desc
,1,0)) {
4499 PACKI(&desc
,"W",0); /* code */
4500 PACKS(&desc
,"B21",name
); /* eff. name */
4501 PACKS(&desc
,"B",""); /* pad */
4503 (get_current_uid(conn
) == sec_initial_uid())?
4504 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4505 PACKI(&desc
,"D",0); /* auth flags XXX */
4506 PACKI(&desc
,"W",0); /* num logons */
4507 PACKI(&desc
,"W",0); /* bad pw count */
4508 PACKI(&desc
,"D",0); /* last logon */
4509 PACKI(&desc
,"D",-1); /* last logoff */
4510 PACKI(&desc
,"D",-1); /* logoff time */
4511 PACKI(&desc
,"D",-1); /* kickoff time */
4512 PACKI(&desc
,"D",0); /* password age */
4513 PACKI(&desc
,"D",0); /* password can change */
4514 PACKI(&desc
,"D",-1); /* password must change */
4518 fstrcpy(mypath
,"\\\\");
4519 fstrcat(mypath
,get_local_machine_name());
4521 PACKS(&desc
,"z",mypath
); /* computer */
4524 PACKS(&desc
,"z",lp_workgroup());/* domain */
4525 PACKS(&desc
,"z", vuser
?
4526 vuser
->server_info
->info3
->base
.logon_script
.string
4527 : ""); /* script path */
4528 PACKI(&desc
,"D",0x00000000); /* reserved */
4531 *rdata_len
= desc
.usedlen
;
4533 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4537 SSVALS(*rparam
,0,desc
.errcode
);
4539 SSVAL(*rparam
,4,desc
.neededlen
);
4541 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4546 /****************************************************************************
4547 api_WAccessGetUserPerms
4548 ****************************************************************************/
4550 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4551 connection_struct
*conn
,uint16 vuid
,
4552 char *param
, int tpscnt
,
4553 char *data
, int tdscnt
,
4554 int mdrcnt
,int mprcnt
,
4555 char **rdata
,char **rparam
,
4556 int *rdata_len
,int *rparam_len
)
4558 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4559 char *str2
= skip_string(param
,tpscnt
,str1
);
4560 char *user
= skip_string(param
,tpscnt
,str2
);
4561 char *resource
= skip_string(param
,tpscnt
,user
);
4563 if (!str1
|| !str2
|| !user
|| !resource
) {
4567 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4570 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4572 /* check it's a supported varient */
4573 if (strcmp(str1
,"zzh") != 0) {
4576 if (strcmp(str2
,"") != 0) {
4581 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4585 SSVALS(*rparam
,0,0); /* errorcode */
4586 SSVAL(*rparam
,2,0); /* converter word */
4587 SSVAL(*rparam
,4,0x7f); /* permission flags */
4592 /****************************************************************************
4593 api_WPrintJobEnumerate
4594 ****************************************************************************/
4596 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4597 connection_struct
*conn
, uint16 vuid
,
4598 char *param
, int tpscnt
,
4599 char *data
, int tdscnt
,
4600 int mdrcnt
,int mprcnt
,
4601 char **rdata
,char **rparam
,
4602 int *rdata_len
,int *rparam_len
)
4604 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4605 char *str2
= skip_string(param
,tpscnt
,str1
);
4606 char *p
= skip_string(param
,tpscnt
,str2
);
4610 struct pack_desc desc
;
4613 TALLOC_CTX
*mem_ctx
= talloc_tos();
4616 struct rpc_pipe_client
*cli
= NULL
;
4617 struct policy_handle handle
;
4618 struct spoolss_DevmodeContainer devmode_ctr
;
4619 union spoolss_JobInfo info
;
4621 if (!str1
|| !str2
|| !p
) {
4625 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4627 memset((char *)&desc
,'\0',sizeof(desc
));
4628 memset((char *)&status
,'\0',sizeof(status
));
4630 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4632 /* check it's a supported varient */
4633 if (strcmp(str1
,"WWrLh") != 0) {
4636 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4640 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4644 ZERO_STRUCT(handle
);
4646 status
= rpc_pipe_open_interface(conn
,
4647 &ndr_table_spoolss
.syntax_id
,
4649 &conn
->sconn
->client_id
,
4650 conn
->sconn
->msg_ctx
,
4652 if (!NT_STATUS_IS_OK(status
)) {
4653 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4654 nt_errstr(status
)));
4655 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4659 ZERO_STRUCT(devmode_ctr
);
4661 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4668 if (!NT_STATUS_IS_OK(status
)) {
4669 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4672 if (!W_ERROR_IS_OK(werr
)) {
4673 desc
.errcode
= W_ERROR_V(werr
);
4677 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4683 if (!W_ERROR_IS_OK(werr
)) {
4684 desc
.errcode
= W_ERROR_V(werr
);
4689 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4694 desc
.buflen
= mdrcnt
;
4697 * Don't return data but need to get correct length
4698 * init_package will return wrong size if buflen=0
4700 desc
.buflen
= getlen(desc
.format
);
4701 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4704 if (init_package(&desc
,1,0)) {
4705 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4706 *rdata_len
= desc
.usedlen
;
4708 desc
.errcode
= NERR_JobNotFound
;
4712 if (cli
&& is_valid_policy_hnd(&handle
)) {
4713 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4717 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4721 SSVALS(*rparam
,0,desc
.errcode
);
4723 SSVAL(*rparam
,4,desc
.neededlen
);
4727 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4732 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4733 connection_struct
*conn
, uint16 vuid
,
4734 char *param
, int tpscnt
,
4735 char *data
, int tdscnt
,
4736 int mdrcnt
,int mprcnt
,
4737 char **rdata
,char **rparam
,
4738 int *rdata_len
,int *rparam_len
)
4740 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4741 char *str2
= skip_string(param
,tpscnt
,str1
);
4742 char *p
= skip_string(param
,tpscnt
,str2
);
4746 struct pack_desc desc
;
4748 TALLOC_CTX
*mem_ctx
= talloc_tos();
4751 struct rpc_pipe_client
*cli
= NULL
;
4752 struct policy_handle handle
;
4753 struct spoolss_DevmodeContainer devmode_ctr
;
4755 union spoolss_JobInfo
*info
;
4757 if (!str1
|| !str2
|| !p
) {
4761 memset((char *)&desc
,'\0',sizeof(desc
));
4763 p
= skip_string(param
,tpscnt
,p
);
4767 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4769 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4771 /* check it's a supported variant */
4772 if (strcmp(str1
,"zWrLeh") != 0) {
4777 return False
; /* defined only for uLevel 0,1,2 */
4780 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4784 ZERO_STRUCT(handle
);
4786 status
= rpc_pipe_open_interface(conn
,
4787 &ndr_table_spoolss
.syntax_id
,
4789 &conn
->sconn
->client_id
,
4790 conn
->sconn
->msg_ctx
,
4792 if (!NT_STATUS_IS_OK(status
)) {
4793 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4794 nt_errstr(status
)));
4795 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4799 ZERO_STRUCT(devmode_ctr
);
4801 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4805 SEC_FLAG_MAXIMUM_ALLOWED
,
4808 if (!NT_STATUS_IS_OK(status
)) {
4809 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4812 if (!W_ERROR_IS_OK(werr
)) {
4813 desc
.errcode
= W_ERROR_V(werr
);
4817 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4825 if (!W_ERROR_IS_OK(werr
)) {
4826 desc
.errcode
= W_ERROR_V(werr
);
4831 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4837 desc
.buflen
= mdrcnt
;
4839 if (init_package(&desc
,count
,0)) {
4841 for (i
= 0; i
< count
; i
++) {
4842 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4843 if (desc
.errcode
== NERR_Success
) {
4849 if (cli
&& is_valid_policy_hnd(&handle
)) {
4850 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4853 *rdata_len
= desc
.usedlen
;
4856 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4860 SSVALS(*rparam
,0,desc
.errcode
);
4862 SSVAL(*rparam
,4,succnt
);
4863 SSVAL(*rparam
,6,count
);
4865 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4870 static int check_printdest_info(struct pack_desc
* desc
,
4871 int uLevel
, char* id
)
4873 desc
->subformat
= NULL
;
4876 desc
->format
= "B9";
4879 desc
->format
= "B9B21WWzW";
4885 desc
->format
= "zzzWWzzzWW";
4888 DEBUG(0,("check_printdest_info: invalid level %d\n",
4892 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4893 DEBUG(0,("check_printdest_info: invalid string %s\n",
4894 id
? id
: "<NULL>" ));
4900 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4901 struct pack_desc
* desc
)
4905 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4906 buf
[sizeof(buf
)-1] = 0;
4910 PACKS(desc
,"B9",buf
); /* szName */
4912 PACKS(desc
,"B21",""); /* szUserName */
4913 PACKI(desc
,"W",0); /* uJobId */
4914 PACKI(desc
,"W",0); /* fsStatus */
4915 PACKS(desc
,"z",""); /* pszStatus */
4916 PACKI(desc
,"W",0); /* time */
4920 if (uLevel
== 2 || uLevel
== 3) {
4921 PACKS(desc
,"z",buf
); /* pszPrinterName */
4923 PACKS(desc
,"z",""); /* pszUserName */
4924 PACKS(desc
,"z",""); /* pszLogAddr */
4925 PACKI(desc
,"W",0); /* uJobId */
4926 PACKI(desc
,"W",0); /* fsStatus */
4927 PACKS(desc
,"z",""); /* pszStatus */
4928 PACKS(desc
,"z",""); /* pszComment */
4929 PACKS(desc
,"z","NULL"); /* pszDrivers */
4930 PACKI(desc
,"W",0); /* time */
4931 PACKI(desc
,"W",0); /* pad1 */
4936 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4937 connection_struct
*conn
, uint16 vuid
,
4938 char *param
, int tpscnt
,
4939 char *data
, int tdscnt
,
4940 int mdrcnt
,int mprcnt
,
4941 char **rdata
,char **rparam
,
4942 int *rdata_len
,int *rparam_len
)
4944 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4945 char *str2
= skip_string(param
,tpscnt
,str1
);
4946 char *p
= skip_string(param
,tpscnt
,str2
);
4947 char* PrinterName
= p
;
4949 struct pack_desc desc
;
4952 TALLOC_CTX
*mem_ctx
= talloc_tos();
4955 struct rpc_pipe_client
*cli
= NULL
;
4956 struct policy_handle handle
;
4957 struct spoolss_DevmodeContainer devmode_ctr
;
4958 union spoolss_PrinterInfo info
;
4960 if (!str1
|| !str2
|| !p
) {
4964 memset((char *)&desc
,'\0',sizeof(desc
));
4966 p
= skip_string(param
,tpscnt
,p
);
4970 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4972 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4974 /* check it's a supported varient */
4975 if (strcmp(str1
,"zWrLh") != 0) {
4978 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4982 ZERO_STRUCT(handle
);
4984 status
= rpc_pipe_open_interface(conn
,
4985 &ndr_table_spoolss
.syntax_id
,
4987 &conn
->sconn
->client_id
,
4988 conn
->sconn
->msg_ctx
,
4990 if (!NT_STATUS_IS_OK(status
)) {
4991 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4992 nt_errstr(status
)));
4993 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4997 ZERO_STRUCT(devmode_ctr
);
4999 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
5003 SEC_FLAG_MAXIMUM_ALLOWED
,
5006 if (!NT_STATUS_IS_OK(status
)) {
5008 desc
.errcode
= NERR_DestNotFound
;
5012 if (!W_ERROR_IS_OK(werr
)) {
5014 desc
.errcode
= NERR_DestNotFound
;
5019 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5024 if (!W_ERROR_IS_OK(werr
)) {
5026 desc
.errcode
= NERR_DestNotFound
;
5032 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5037 desc
.buflen
= mdrcnt
;
5040 * Don't return data but need to get correct length
5041 * init_package will return wrong size if buflen=0
5043 desc
.buflen
= getlen(desc
.format
);
5044 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5046 if (init_package(&desc
,1,0)) {
5047 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5051 if (cli
&& is_valid_policy_hnd(&handle
)) {
5052 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
5055 *rdata_len
= desc
.usedlen
;
5058 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5062 SSVALS(*rparam
,0,desc
.errcode
);
5064 SSVAL(*rparam
,4,desc
.neededlen
);
5066 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5072 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5073 connection_struct
*conn
, uint16 vuid
,
5074 char *param
, int tpscnt
,
5075 char *data
, int tdscnt
,
5076 int mdrcnt
,int mprcnt
,
5077 char **rdata
,char **rparam
,
5078 int *rdata_len
,int *rparam_len
)
5080 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5081 char *str2
= skip_string(param
,tpscnt
,str1
);
5082 char *p
= skip_string(param
,tpscnt
,str2
);
5086 struct pack_desc desc
;
5088 TALLOC_CTX
*mem_ctx
= talloc_tos();
5091 struct rpc_pipe_client
*cli
= NULL
;
5092 union spoolss_PrinterInfo
*info
;
5095 if (!str1
|| !str2
|| !p
) {
5099 memset((char *)&desc
,'\0',sizeof(desc
));
5101 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5103 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5105 /* check it's a supported varient */
5106 if (strcmp(str1
,"WrLeh") != 0) {
5109 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5115 status
= rpc_pipe_open_interface(conn
,
5116 &ndr_table_spoolss
.syntax_id
,
5118 &conn
->sconn
->client_id
,
5119 conn
->sconn
->msg_ctx
,
5121 if (!NT_STATUS_IS_OK(status
)) {
5122 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5123 nt_errstr(status
)));
5124 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5128 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5130 cli
->srv_name_slash
,
5135 if (!W_ERROR_IS_OK(werr
)) {
5136 desc
.errcode
= W_ERROR_V(werr
);
5138 desc
.errcode
= NERR_DestNotFound
;
5146 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5153 desc
.buflen
= mdrcnt
;
5154 if (init_package(&desc
,queuecnt
,0)) {
5157 for (i
= 0; i
< count
; i
++) {
5158 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5160 if (desc
.errcode
== NERR_Success
) {
5166 *rdata_len
= desc
.usedlen
;
5169 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5173 SSVALS(*rparam
,0,desc
.errcode
);
5175 SSVAL(*rparam
,4,succnt
);
5176 SSVAL(*rparam
,6,queuecnt
);
5178 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5183 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5184 connection_struct
*conn
, uint16 vuid
,
5185 char *param
, int tpscnt
,
5186 char *data
, int tdscnt
,
5187 int mdrcnt
,int mprcnt
,
5188 char **rdata
,char **rparam
,
5189 int *rdata_len
,int *rparam_len
)
5191 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5192 char *str2
= skip_string(param
,tpscnt
,str1
);
5193 char *p
= skip_string(param
,tpscnt
,str2
);
5196 struct pack_desc desc
;
5198 if (!str1
|| !str2
|| !p
) {
5202 memset((char *)&desc
,'\0',sizeof(desc
));
5204 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5206 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5208 /* check it's a supported varient */
5209 if (strcmp(str1
,"WrLeh") != 0) {
5212 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5217 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5223 desc
.buflen
= mdrcnt
;
5224 if (init_package(&desc
,1,0)) {
5225 PACKS(&desc
,"B41","NULL");
5228 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5230 *rdata_len
= desc
.usedlen
;
5233 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5237 SSVALS(*rparam
,0,desc
.errcode
);
5239 SSVAL(*rparam
,4,succnt
);
5242 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5247 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5248 connection_struct
*conn
, uint16 vuid
,
5249 char *param
, int tpscnt
,
5250 char *data
, int tdscnt
,
5251 int mdrcnt
,int mprcnt
,
5252 char **rdata
,char **rparam
,
5253 int *rdata_len
,int *rparam_len
)
5255 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5256 char *str2
= skip_string(param
,tpscnt
,str1
);
5257 char *p
= skip_string(param
,tpscnt
,str2
);
5260 struct pack_desc desc
;
5262 if (!str1
|| !str2
|| !p
) {
5265 memset((char *)&desc
,'\0',sizeof(desc
));
5267 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5269 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5271 /* check it's a supported varient */
5272 if (strcmp(str1
,"WrLeh") != 0) {
5275 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5280 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5286 desc
.buflen
= mdrcnt
;
5288 if (init_package(&desc
,1,0)) {
5289 PACKS(&desc
,"B13","lpd");
5292 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5294 *rdata_len
= desc
.usedlen
;
5297 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5301 SSVALS(*rparam
,0,desc
.errcode
);
5303 SSVAL(*rparam
,4,succnt
);
5306 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5311 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5312 connection_struct
*conn
, uint16 vuid
,
5313 char *param
, int tpscnt
,
5314 char *data
, int tdscnt
,
5315 int mdrcnt
,int mprcnt
,
5316 char **rdata
,char **rparam
,
5317 int *rdata_len
,int *rparam_len
)
5319 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5320 char *str2
= skip_string(param
,tpscnt
,str1
);
5321 char *p
= skip_string(param
,tpscnt
,str2
);
5324 struct pack_desc desc
;
5326 if (!str1
|| !str2
|| !p
) {
5330 memset((char *)&desc
,'\0',sizeof(desc
));
5332 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5334 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5336 /* check it's a supported varient */
5337 if (strcmp(str1
,"WrLeh") != 0) {
5340 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5345 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5350 memset((char *)&desc
,'\0',sizeof(desc
));
5352 desc
.buflen
= mdrcnt
;
5354 if (init_package(&desc
,1,0)) {
5355 PACKS(&desc
,"B13","lp0");
5358 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5360 *rdata_len
= desc
.usedlen
;
5363 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5367 SSVALS(*rparam
,0,desc
.errcode
);
5369 SSVAL(*rparam
,4,succnt
);
5372 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5377 /****************************************************************************
5379 ****************************************************************************/
5381 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5382 connection_struct
*conn
, uint16 vuid
,
5383 char *param
, int tpscnt
,
5384 char *data
, int tdscnt
,
5385 int mdrcnt
,int mprcnt
,
5386 char **rdata
,char **rparam
,
5387 int *rdata_len
,int *rparam_len
)
5390 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5391 char *str2
= skip_string(param
,tpscnt
,str1
);
5392 char *p
= skip_string(param
,tpscnt
,str2
);
5394 struct pack_desc desc
;
5395 struct sessionid
*session_list
;
5396 int i
, num_sessions
;
5398 if (!str1
|| !str2
|| !p
) {
5402 memset((char *)&desc
,'\0',sizeof(desc
));
5404 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5406 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5407 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5408 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5410 /* check it's a supported varient */
5411 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5414 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5418 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5421 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5426 memset((char *)&desc
,'\0',sizeof(desc
));
5428 desc
.buflen
= mdrcnt
;
5430 if (!init_package(&desc
,num_sessions
,0)) {
5434 for(i
=0; i
<num_sessions
; i
++) {
5435 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5436 PACKS(&desc
, "z", session_list
[i
].username
);
5437 PACKI(&desc
, "W", 1); /* num conns */
5438 PACKI(&desc
, "W", 0); /* num opens */
5439 PACKI(&desc
, "W", 1); /* num users */
5440 PACKI(&desc
, "D", 0); /* session time */
5441 PACKI(&desc
, "D", 0); /* idle time */
5442 PACKI(&desc
, "D", 0); /* flags */
5443 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5446 *rdata_len
= desc
.usedlen
;
5449 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5453 SSVALS(*rparam
,0,desc
.errcode
);
5454 SSVAL(*rparam
,2,0); /* converter */
5455 SSVAL(*rparam
,4,num_sessions
); /* count */
5457 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5463 /****************************************************************************
5464 The buffer was too small.
5465 ****************************************************************************/
5467 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5468 connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5469 int mdrcnt
, int mprcnt
,
5470 char **rdata
, char **rparam
,
5471 int *rdata_len
, int *rparam_len
)
5473 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5474 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5481 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5483 DEBUG(3,("Supplied buffer too small in API command\n"));
5488 /****************************************************************************
5489 The request is not supported.
5490 ****************************************************************************/
5492 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5493 connection_struct
*conn
, uint16 vuid
,
5494 char *param
, int tpscnt
,
5495 char *data
, int tdscnt
,
5496 int mdrcnt
, int mprcnt
,
5497 char **rdata
, char **rparam
,
5498 int *rdata_len
, int *rparam_len
)
5501 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5508 SSVAL(*rparam
,0,NERR_notsupported
);
5509 SSVAL(*rparam
,2,0); /* converter word */
5511 DEBUG(3,("Unsupported API command\n"));
5516 static const struct {
5519 bool (*fn
)(struct smbd_server_connection
*sconn
,
5520 connection_struct
*, uint16
,
5523 int,int,char **,char **,int *,int *);
5524 bool auth_user
; /* Deny anonymous access? */
5525 } api_commands
[] = {
5526 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5527 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5528 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5529 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5530 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5531 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5532 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5533 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5534 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5535 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5536 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5537 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5538 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5539 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5540 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5541 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5542 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5543 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5544 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5545 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5546 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5547 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5548 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5549 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5550 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5551 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5552 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5553 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5554 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5555 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5556 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5557 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5558 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5559 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5560 {NULL
, -1, api_Unsupported
}
5561 /* The following RAP calls are not implemented by Samba:
5563 RAP_WFileEnum2 - anon not OK
5568 /****************************************************************************
5569 Handle remote api calls.
5570 ****************************************************************************/
5572 void api_reply(connection_struct
*conn
, uint16 vuid
,
5573 struct smb_request
*req
,
5574 char *data
, char *params
,
5575 int tdscnt
, int tpscnt
,
5576 int mdrcnt
, int mprcnt
)
5580 char *rparam
= NULL
;
5581 const char *name1
= NULL
;
5582 const char *name2
= NULL
;
5589 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5590 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5595 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5598 api_command
= SVAL(params
,0);
5599 /* Is there a string at position params+2 ? */
5600 if (skip_string(params
,tpscnt
,params
+2)) {
5605 name2
= skip_string(params
,tpscnt
,params
+2);
5610 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5614 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5616 for (i
=0;api_commands
[i
].name
;i
++) {
5617 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5618 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5623 /* Check whether this api call can be done anonymously */
5625 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5626 user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5628 if (!user
|| user
->server_info
->guest
) {
5629 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5634 rdata
= (char *)SMB_MALLOC(1024);
5636 memset(rdata
,'\0',1024);
5639 rparam
= (char *)SMB_MALLOC(1024);
5641 memset(rparam
,'\0',1024);
5644 if(!rdata
|| !rparam
) {
5645 DEBUG(0,("api_reply: malloc fail !\n"));
5648 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5652 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5654 params
,tpscnt
, /* params + length */
5655 data
,tdscnt
, /* data + length */
5657 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5660 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5661 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5663 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5666 /* if we get False back then it's actually unsupported */
5668 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5670 tdscnt
,mdrcnt
,mprcnt
,
5671 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5674 /* If api_Unsupported returns false we can't return anything. */
5676 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5677 rdata
, rdata_len
, False
);