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/smbd.h"
30 #include "smbd/globals.h"
31 #include "rpc_client/rpc_client.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
34 #include "rpc_client/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "../librpc/gen_ndr/ndr_srvsvc_c.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 "../libcli/security/security.h"
43 #include "passdb/machine_sid.h"
45 #include "rpc_server/rpc_ncacn_np.h"
52 #define NERR_Success 0
53 #define NERR_badpass 86
54 #define NERR_notsupported 50
56 #define NERR_BASE (2100)
57 #define NERR_BufTooSmall (NERR_BASE+23)
58 #define NERR_JobNotFound (NERR_BASE+51)
59 #define NERR_DestNotFound (NERR_BASE+52)
61 #define ACCESS_READ 0x01
62 #define ACCESS_WRITE 0x02
63 #define ACCESS_CREATE 0x04
65 #define SHPWLEN 8 /* share password length */
67 /* Limit size of ipc replies */
69 static char *smb_realloc_limit(void *ptr
, size_t size
)
73 size
= MAX((size
),4*1024);
74 val
= (char *)SMB_REALLOC(ptr
,size
);
76 memset(val
,'\0',size
);
81 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
82 connection_struct
*conn
, uint64_t vuid
,
83 char *param
, int tpscnt
,
84 char *data
, int tdscnt
,
85 int mdrcnt
, int mprcnt
,
86 char **rdata
, char **rparam
,
87 int *rdata_len
, int *rparam_len
);
89 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
90 connection_struct
*conn
, uint64_t vuid
, char *param
, char *data
,
91 int mdrcnt
, int mprcnt
,
92 char **rdata
, char **rparam
,
93 int *rdata_len
, int *rparam_len
);
96 static int CopyExpanded(connection_struct
*conn
,
97 int snum
, char **dst
, char *src
, int *p_space_remaining
)
99 TALLOC_CTX
*ctx
= talloc_tos();
103 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
104 *p_space_remaining
<= 0) {
108 buf
= talloc_strdup(ctx
, src
);
110 *p_space_remaining
= 0;
113 buf
= talloc_string_sub(ctx
, buf
,"%S", lp_servicename(ctx
, snum
));
115 *p_space_remaining
= 0;
118 buf
= talloc_sub_advanced(ctx
,
119 lp_servicename(ctx
, SNUM(conn
)),
120 conn
->session_info
->unix_info
->unix_name
,
122 conn
->session_info
->unix_token
->gid
,
123 conn
->session_info
->unix_info
->sanitized_username
,
124 conn
->session_info
->info
->domain_name
,
127 *p_space_remaining
= 0;
130 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
135 (*p_space_remaining
) -= l
;
139 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
142 if (!src
|| !dst
|| !n
|| !(*dst
)) {
145 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
154 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
156 TALLOC_CTX
*ctx
= talloc_tos();
161 buf
= talloc_strdup(ctx
,s
);
165 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(ctx
, snum
));
169 buf
= talloc_sub_advanced(ctx
,
170 lp_servicename(ctx
, SNUM(conn
)),
171 conn
->session_info
->unix_info
->unix_name
,
173 conn
->session_info
->unix_token
->gid
,
174 conn
->session_info
->unix_info
->sanitized_username
,
175 conn
->session_info
->info
->domain_name
,
180 return strlen(buf
) + 1;
183 /*******************************************************************
184 Check a API string for validity when we only need to check the prefix.
185 ******************************************************************/
187 static bool prefix_ok(const char *str
, const char *prefix
)
189 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
193 const char *format
; /* formatstring for structure */
194 const char *subformat
; /* subformat for structure */
195 char *base
; /* baseaddress of buffer */
196 int buflen
; /* remaining size for fixed part; on init: length of base */
197 int subcount
; /* count of substructures */
198 char *structbuf
; /* pointer into buffer for remaining fixed part */
199 int stringlen
; /* remaining size for variable part */
200 char *stringbuf
; /* pointer into buffer for remaining variable part */
201 int neededlen
; /* total needed size */
202 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
203 const char *curpos
; /* current position; pointer into format or subformat */
207 static int get_counter(const char **p
)
213 if (!isdigit((int)**p
)) {
219 n
= 10 * n
+ (i
- '0');
227 static int getlen(const char *p
)
236 case 'W': /* word (2 byte) */
239 case 'K': /* status word? (2 byte) */
242 case 'N': /* count of substructures (word) at end */
245 case 'D': /* double word (4 byte) */
246 case 'z': /* offset to zero terminated string (4 byte) */
247 case 'l': /* offset to user data (4 byte) */
250 case 'b': /* offset to data (with counter) (4 byte) */
254 case 'B': /* byte (with optional counter) */
255 n
+= get_counter(&p
);
262 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
267 if (!p
->format
|| !p
->base
) {
271 i
= count
* getlen(p
->format
);
273 i
+= subcount
* getlen(p
->subformat
);
275 p
->structbuf
= p
->base
;
279 p
->curpos
= p
->format
;
285 * This is the old error code we used. Aparently
286 * WinNT/2k systems return ERRbuftoosmall (2123) and
287 * OS/2 needs this. I'm leaving this here so we can revert
290 p
->errcode
= ERRmoredata
;
292 p
->errcode
= ERRbuftoosmall
;
295 p
->errcode
= NERR_Success
;
299 p
->stringbuf
= p
->base
+ i
;
301 return (p
->errcode
== NERR_Success
);
304 static int package(struct pack_desc
*p
, ...)
307 int needed
=0, stringneeded
;
308 const char *str
=NULL
;
309 int is_string
=0, stringused
;
316 p
->curpos
= p
->format
;
318 p
->curpos
= p
->subformat
;
323 str
= va_arg(args
,char*);
324 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
333 switch( *p
->curpos
++ ) {
334 case 'W': /* word (2 byte) */
336 temp
= va_arg(args
,int);
337 if (p
->buflen
>= needed
) {
338 SSVAL(p
->structbuf
,0,temp
);
341 case 'K': /* status word? (2 byte) */
343 temp
= va_arg(args
,int);
344 if (p
->buflen
>= needed
) {
345 SSVAL(p
->structbuf
,0,temp
);
348 case 'N': /* count of substructures (word) at end */
350 p
->subcount
= va_arg(args
,int);
351 if (p
->buflen
>= needed
) {
352 SSVAL(p
->structbuf
,0,p
->subcount
);
355 case 'D': /* double word (4 byte) */
357 temp
= va_arg(args
,int);
358 if (p
->buflen
>= needed
) {
359 SIVAL(p
->structbuf
,0,temp
);
362 case 'B': /* byte (with optional counter) */
363 needed
= get_counter(&p
->curpos
);
365 char *s
= va_arg(args
,char*);
366 if (p
->buflen
>= needed
) {
367 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
371 case 'z': /* offset to zero terminated string (4 byte) */
372 str
= va_arg(args
,char*);
373 stringneeded
= (str
? strlen(str
)+1 : 0);
376 case 'l': /* offset to user data (4 byte) */
377 str
= va_arg(args
,char*);
378 stringneeded
= va_arg(args
,int);
381 case 'b': /* offset to data (with counter) (4 byte) */
382 str
= va_arg(args
,char*);
383 stringneeded
= get_counter(&p
->curpos
);
389 if (stringneeded
>= 0) {
391 if (p
->buflen
>= needed
) {
392 stringused
= stringneeded
;
393 if (stringused
> p
->stringlen
) {
394 stringused
= (is_string
? p
->stringlen
: 0);
395 if (p
->errcode
== NERR_Success
) {
396 p
->errcode
= ERRmoredata
;
400 SIVAL(p
->structbuf
,0,0);
402 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
403 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
405 p
->stringbuf
[stringused
-1] = '\0';
407 p
->stringbuf
+= stringused
;
408 p
->stringlen
-= stringused
;
409 p
->usedlen
+= stringused
;
412 p
->neededlen
+= stringneeded
;
415 p
->neededlen
+= needed
;
416 if (p
->buflen
>= needed
) {
417 p
->structbuf
+= needed
;
419 p
->usedlen
+= needed
;
421 if (p
->errcode
== NERR_Success
) {
422 p
->errcode
= ERRmoredata
;
429 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
430 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
432 #define PACK(desc,t,v) package(desc,v)
433 #define PACKl(desc,t,v,l) package(desc,v,l)
436 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
441 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
446 /****************************************************************************
448 ****************************************************************************/
450 static void PackDriverData(struct pack_desc
* desc
)
452 char drivdata
[4+4+32];
453 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
454 SIVAL(drivdata
,4,1000); /* lVersion */
455 memset(drivdata
+8,0,32); /* szDeviceName */
456 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
457 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
460 static int check_printq_info(struct pack_desc
* desc
,
461 unsigned int uLevel
, char *id1
, char *id2
)
463 desc
->subformat
= NULL
;
466 desc
->format
= "B13";
469 desc
->format
= "B13BWWWzzzzzWW";
472 desc
->format
= "B13BWWWzzzzzWN";
473 desc
->subformat
= "WB21BB16B10zWWzDDz";
476 desc
->format
= "zWWWWzzzzWWzzl";
479 desc
->format
= "zWWWWzzzzWNzzl";
480 desc
->subformat
= "WWzWWDDzz";
489 desc
->format
= "WzzzzzzzzN";
490 desc
->subformat
= "z";
493 DEBUG(0,("check_printq_info: invalid level %d\n",
497 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
498 DEBUG(0,("check_printq_info: invalid format %s\n",
499 id1
? id1
: "<NULL>" ));
502 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
503 DEBUG(0,("check_printq_info: invalid subformat %s\n",
504 id2
? id2
: "<NULL>" ));
511 #define RAP_JOB_STATUS_QUEUED 0
512 #define RAP_JOB_STATUS_PAUSED 1
513 #define RAP_JOB_STATUS_SPOOLING 2
514 #define RAP_JOB_STATUS_PRINTING 3
515 #define RAP_JOB_STATUS_PRINTED 4
517 #define RAP_QUEUE_STATUS_PAUSED 1
518 #define RAP_QUEUE_STATUS_ERROR 2
520 /* turn a print job status into a on the wire status
522 static int printj_spoolss_status(int v
)
524 if (v
== JOB_STATUS_QUEUED
)
525 return RAP_JOB_STATUS_QUEUED
;
526 if (v
& JOB_STATUS_PAUSED
)
527 return RAP_JOB_STATUS_PAUSED
;
528 if (v
& JOB_STATUS_SPOOLING
)
529 return RAP_JOB_STATUS_SPOOLING
;
530 if (v
& JOB_STATUS_PRINTING
)
531 return RAP_JOB_STATUS_PRINTING
;
535 /* turn a print queue status into a on the wire status
537 static int printq_spoolss_status(int v
)
539 if (v
== PRINTER_STATUS_OK
)
541 if (v
& PRINTER_STATUS_PAUSED
)
542 return RAP_QUEUE_STATUS_PAUSED
;
543 return RAP_QUEUE_STATUS_ERROR
;
546 static void fill_spoolss_printjob_info(int uLevel
,
547 struct pack_desc
*desc
,
548 struct spoolss_JobInfo2
*info2
,
551 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
553 /* the client expects localtime */
554 t
-= get_time_zone(t
);
556 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
558 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
559 PACKS(desc
,"B",""); /* pad */
560 PACKS(desc
,"B16",""); /* szNotifyName */
561 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
562 PACKS(desc
,"z",""); /* pszParms */
563 PACKI(desc
,"W",n
+1); /* uPosition */
564 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
565 PACKS(desc
,"z",""); /* pszStatus */
566 PACKI(desc
,"D", t
); /* ulSubmitted */
567 PACKI(desc
,"D", info2
->size
); /* ulSize */
568 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
570 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
571 PACKI(desc
,"W", info2
->priority
); /* uPriority */
572 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
573 PACKI(desc
,"W",n
+1); /* uPosition */
574 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
575 PACKI(desc
,"D",t
); /* ulSubmitted */
576 PACKI(desc
,"D", info2
->size
); /* ulSize */
577 PACKS(desc
,"z","Samba"); /* pszComment */
578 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
580 PACKS(desc
,"z",""); /* pszNotifyName */
581 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
582 PACKS(desc
,"z",""); /* pszParms */
583 PACKS(desc
,"z",""); /* pszStatus */
584 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
585 PACKS(desc
,"z","lpd"); /* pszQProcName */
586 PACKS(desc
,"z",""); /* pszQProcParms */
587 PACKS(desc
,"z","NULL"); /* pszDriverName */
588 PackDriverData(desc
); /* pDriverData */
589 PACKS(desc
,"z",""); /* pszPrinterName */
590 } else if (uLevel
== 4) { /* OS2 */
591 PACKS(desc
,"z",""); /* pszSpoolFileName */
592 PACKS(desc
,"z",""); /* pszPortName */
593 PACKS(desc
,"z",""); /* pszStatus */
594 PACKI(desc
,"D",0); /* ulPagesSpooled */
595 PACKI(desc
,"D",0); /* ulPagesSent */
596 PACKI(desc
,"D",0); /* ulPagesPrinted */
597 PACKI(desc
,"D",0); /* ulTimePrinted */
598 PACKI(desc
,"D",0); /* ulExtendJobStatus */
599 PACKI(desc
,"D",0); /* ulStartPage */
600 PACKI(desc
,"D",0); /* ulEndPage */
605 /********************************************************************
606 Respond to the DosPrintQInfo command with a level of 52
607 This is used to get printer driver information for Win9x clients
608 ********************************************************************/
609 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
610 struct pack_desc
* desc
, int count
,
611 const char *printer_name
)
615 trim_string(discard_const_p(char, driver
->driver_path
), "\\print$\\WIN40\\0\\", 0);
616 trim_string(discard_const_p(char, driver
->data_file
), "\\print$\\WIN40\\0\\", 0);
617 trim_string(discard_const_p(char, driver
->help_file
), "\\print$\\WIN40\\0\\", 0);
619 PACKI(desc
, "W", 0x0400); /* don't know */
620 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
621 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
622 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
623 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
625 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
626 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
627 PACKS(desc
,"z", location
); /* share to retrieve files */
629 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
630 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
631 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
633 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
634 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
635 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
636 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
637 DEBUG(3,("Driver Location: %s:\n",location
));
638 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
639 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
640 PACKI(desc
,"N",count
); /* number of files to copy */
642 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
644 trim_string(discard_const_p(char, driver
->dependent_files
[i
]), "\\print$\\WIN40\\0\\", 0);
645 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
646 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
651 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
654 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
656 desc
->errcode
=NERR_Success
;
660 static const char *strip_unc(const char *unc
)
668 if ((p
= strrchr(unc
, '\\')) != NULL
) {
675 static void fill_printq_info(int uLevel
,
676 struct pack_desc
* desc
,
678 union spoolss_JobInfo
*job_info
,
679 struct spoolss_DriverInfo3
*driver_info
,
680 struct spoolss_PrinterInfo2
*printer_info
)
686 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
691 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
694 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
698 if (uLevel
== 1 || uLevel
== 2) {
699 PACKS(desc
,"B",""); /* alignment */
700 PACKI(desc
,"W",5); /* priority */
701 PACKI(desc
,"W",0); /* start time */
702 PACKI(desc
,"W",0); /* until time */
703 PACKS(desc
,"z",""); /* pSepFile */
704 PACKS(desc
,"z","lpd"); /* pPrProc */
705 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
706 PACKS(desc
,"z",""); /* pParms */
707 if (printer_info
->printername
== NULL
) {
708 PACKS(desc
,"z","UNKNOWN PRINTER");
709 PACKI(desc
,"W",LPSTAT_ERROR
);
711 PACKS(desc
,"z", printer_info
->comment
);
712 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
714 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
717 if (uLevel
== 3 || uLevel
== 4) {
718 PACKI(desc
,"W",5); /* uPriority */
719 PACKI(desc
,"W",0); /* uStarttime */
720 PACKI(desc
,"W",0); /* uUntiltime */
721 PACKI(desc
,"W",5); /* pad1 */
722 PACKS(desc
,"z",""); /* pszSepFile */
723 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
724 PACKS(desc
,"z",NULL
); /* pszParms */
725 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
726 /* "don't ask" that it's done this way to fix corrupted
727 Win9X/ME printer comments. */
728 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
729 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
730 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
731 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
732 PackDriverData(desc
); /* pDriverData */
735 if (uLevel
== 2 || uLevel
== 4) {
737 for (i
= 0; i
< count
; i
++) {
738 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
743 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
746 /* This function returns the number of files for a given driver */
747 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
751 /* count the number of files */
752 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
758 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
759 connection_struct
*conn
, uint64_t vuid
,
760 char *param
, int tpscnt
,
761 char *data
, int tdscnt
,
762 int mdrcnt
,int mprcnt
,
763 char **rdata
,char **rparam
,
764 int *rdata_len
,int *rparam_len
)
766 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
767 char *str2
= skip_string(param
,tpscnt
,str1
);
768 char *p
= skip_string(param
,tpscnt
,str2
);
773 struct pack_desc desc
;
776 WERROR werr
= WERR_OK
;
777 TALLOC_CTX
*mem_ctx
= talloc_tos();
779 struct rpc_pipe_client
*cli
= NULL
;
780 struct dcerpc_binding_handle
*b
= NULL
;
781 struct policy_handle handle
;
782 struct spoolss_DevmodeContainer devmode_ctr
;
783 union spoolss_DriverInfo driver_info
;
784 union spoolss_JobInfo
*job_info
= NULL
;
785 union spoolss_PrinterInfo printer_info
;
787 if (!str1
|| !str2
|| !p
) {
790 memset((char *)&desc
,'\0',sizeof(desc
));
792 p
= skip_string(param
,tpscnt
,p
);
796 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
797 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
798 /* str3 may be null here and is checked in check_printq_info(). */
800 /* remove any trailing username */
801 if ((p
= strchr_m(QueueName
,'%')))
804 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
806 /* check it's a supported varient */
807 if (!prefix_ok(str1
,"zWrLh"))
809 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
811 * Patch from Scott Moomaw <scott@bridgewater.edu>
812 * to return the 'invalid info level' error if an
813 * unknown level was requested.
817 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
821 SSVALS(*rparam
,0,ERRunknownlevel
);
829 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
830 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
834 status
= rpc_pipe_open_interface(conn
,
835 &ndr_table_spoolss
.syntax_id
,
837 conn
->sconn
->remote_address
,
838 conn
->sconn
->msg_ctx
,
840 if (!NT_STATUS_IS_OK(status
)) {
841 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
843 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
846 b
= cli
->binding_handle
;
848 ZERO_STRUCT(devmode_ctr
);
850 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
857 if (!NT_STATUS_IS_OK(status
)) {
858 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
861 if (!W_ERROR_IS_OK(werr
)) {
862 desc
.errcode
= W_ERROR_V(werr
);
866 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
871 if (!W_ERROR_IS_OK(werr
)) {
872 desc
.errcode
= W_ERROR_V(werr
);
877 uint32_t server_major_version
;
878 uint32_t server_minor_version
;
880 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
888 &server_major_version
,
889 &server_minor_version
);
890 if (!W_ERROR_IS_OK(werr
)) {
891 desc
.errcode
= W_ERROR_V(werr
);
895 count
= get_printerdrivernumber(&driver_info
.info3
);
896 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
899 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
907 if (!W_ERROR_IS_OK(werr
)) {
908 desc
.errcode
= W_ERROR_V(werr
);
916 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
921 desc
.buflen
= mdrcnt
;
924 * Don't return data but need to get correct length
925 * init_package will return wrong size if buflen=0
927 desc
.buflen
= getlen(desc
.format
);
928 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
931 if (init_package(&desc
,1,count
)) {
932 desc
.subcount
= count
;
933 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
936 *rdata_len
= desc
.usedlen
;
939 * We must set the return code to ERRbuftoosmall
940 * in order to support lanman style printing with Win NT/2k
943 if (!mdrcnt
&& lp_disable_spoolss())
944 desc
.errcode
= ERRbuftoosmall
;
947 if (b
&& is_valid_policy_hnd(&handle
)) {
948 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
951 *rdata_len
= desc
.usedlen
;
953 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
958 SSVALS(*rparam
,0,desc
.errcode
);
960 SSVAL(*rparam
,4,desc
.neededlen
);
962 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
969 /****************************************************************************
970 View list of all print jobs on all queues.
971 ****************************************************************************/
973 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
974 connection_struct
*conn
, uint64_t vuid
,
975 char *param
, int tpscnt
,
976 char *data
, int tdscnt
,
977 int mdrcnt
, int mprcnt
,
978 char **rdata
, char** rparam
,
979 int *rdata_len
, int *rparam_len
)
981 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
982 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
983 char *p
= skip_string(param
,tpscnt
,output_format1
);
984 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
985 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
987 struct pack_desc desc
;
988 int *subcntarr
= NULL
;
989 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
991 WERROR werr
= WERR_OK
;
992 TALLOC_CTX
*mem_ctx
= talloc_tos();
994 struct rpc_pipe_client
*cli
= NULL
;
995 struct dcerpc_binding_handle
*b
= NULL
;
996 struct spoolss_DevmodeContainer devmode_ctr
;
997 uint32_t num_printers
;
998 union spoolss_PrinterInfo
*printer_info
;
999 union spoolss_DriverInfo
*driver_info
;
1000 union spoolss_JobInfo
**job_info
;
1002 if (!param_format
|| !output_format1
|| !p
) {
1006 memset((char *)&desc
,'\0',sizeof(desc
));
1008 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1010 if (!prefix_ok(param_format
,"WrLeh")) {
1013 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1015 * Patch from Scott Moomaw <scott@bridgewater.edu>
1016 * to return the 'invalid info level' error if an
1017 * unknown level was requested.
1021 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1025 SSVALS(*rparam
,0,ERRunknownlevel
);
1031 status
= rpc_pipe_open_interface(conn
,
1032 &ndr_table_spoolss
.syntax_id
,
1034 conn
->sconn
->remote_address
,
1035 conn
->sconn
->msg_ctx
,
1037 if (!NT_STATUS_IS_OK(status
)) {
1038 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1039 nt_errstr(status
)));
1040 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1043 b
= cli
->binding_handle
;
1045 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1047 cli
->srv_name_slash
,
1052 if (!W_ERROR_IS_OK(werr
)) {
1053 desc
.errcode
= W_ERROR_V(werr
);
1057 queuecnt
= num_printers
;
1059 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1060 if (job_info
== NULL
) {
1064 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1065 if (driver_info
== NULL
) {
1069 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1070 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1075 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1081 desc
.buflen
= mdrcnt
;
1084 for (i
= 0; i
< num_printers
; i
++) {
1087 struct policy_handle handle
;
1088 const char *printername
;
1090 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1091 if (printername
== NULL
) {
1095 ZERO_STRUCT(handle
);
1096 ZERO_STRUCT(devmode_ctr
);
1098 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
1105 if (!NT_STATUS_IS_OK(status
)) {
1106 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1109 if (!W_ERROR_IS_OK(werr
)) {
1110 desc
.errcode
= W_ERROR_V(werr
);
1114 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1122 if (!W_ERROR_IS_OK(werr
)) {
1123 desc
.errcode
= W_ERROR_V(werr
);
1128 uint32_t server_major_version
;
1129 uint32_t server_minor_version
;
1131 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1139 &server_major_version
,
1140 &server_minor_version
);
1141 if (!W_ERROR_IS_OK(werr
)) {
1142 desc
.errcode
= W_ERROR_V(werr
);
1147 subcntarr
[i
] = num_jobs
;
1148 subcnt
+= subcntarr
[i
];
1150 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1153 if (init_package(&desc
,queuecnt
,subcnt
)) {
1154 for (i
= 0; i
< num_printers
; i
++) {
1155 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1156 if (desc
.errcode
== NERR_Success
) {
1163 SAFE_FREE(subcntarr
);
1164 *rdata_len
= desc
.usedlen
;
1166 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1170 SSVALS(*rparam
,0,desc
.errcode
);
1172 SSVAL(*rparam
,4,succnt
);
1173 SSVAL(*rparam
,6,queuecnt
);
1179 SAFE_FREE(subcntarr
);
1184 /****************************************************************************
1185 Get info level for a server list query.
1186 ****************************************************************************/
1188 static bool check_session_info(int uLevel
, char* id
)
1192 if (strcmp(id
,"B16") != 0) {
1197 if (strcmp(id
,"B16BBDz") != 0) {
1207 struct srv_info_struct
{
1215 /*******************************************************************
1216 Get server info lists from the files saved by nmbd. Return the
1218 ******************************************************************/
1220 static int get_session_info(uint32 servertype
,
1221 struct srv_info_struct
**servers
,
1227 bool local_list_only
;
1230 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1232 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1236 /* request for everything is code for request all servers */
1237 if (servertype
== SV_TYPE_ALL
) {
1238 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1241 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1243 DEBUG(4,("Servertype search: %8x\n",servertype
));
1245 for (i
=0;lines
[i
];i
++) {
1247 struct srv_info_struct
*s
;
1248 const char *ptr
= lines
[i
];
1250 TALLOC_CTX
*frame
= NULL
;
1257 if (count
== alloced
) {
1259 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1261 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1265 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1267 s
= &(*servers
)[count
];
1269 frame
= talloc_stackframe();
1271 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1275 fstrcpy(s
->name
, p
);
1278 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1284 s
->comment
[0] = '\0';
1285 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1289 fstrcpy(s
->comment
, p
);
1290 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1292 s
->domain
[0] = '\0';
1293 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1294 /* this allows us to cope with an old nmbd */
1295 fstrcpy(s
->domain
,lp_workgroup());
1297 fstrcpy(s
->domain
, p
);
1301 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1302 DEBUG(4,("r:host file "));
1306 /* Filter the servers/domains we return based on what was asked for. */
1308 /* Check to see if we are being asked for a local list only. */
1309 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1310 DEBUG(4,("r: local list only"));
1314 /* doesn't match up: don't want it */
1315 if (!(servertype
& s
->type
)) {
1316 DEBUG(4,("r:serv type "));
1320 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1321 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1322 DEBUG(4,("s: dom mismatch "));
1326 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1330 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1331 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1334 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1335 s
->name
, s
->type
, s
->comment
, s
->domain
));
1336 s
->server_added
= True
;
1339 DEBUG(4,("%20s %8x %25s %15s\n",
1340 s
->name
, s
->type
, s
->comment
, s
->domain
));
1348 /*******************************************************************
1349 Fill in a server info structure.
1350 ******************************************************************/
1352 static int fill_srv_info(struct srv_info_struct
*service
,
1353 int uLevel
, char **buf
, int *buflen
,
1354 char **stringbuf
, int *stringspace
, char *baseaddr
)
1377 len
= strlen(service
->comment
)+1;
1381 *buflen
= struct_len
;
1383 return struct_len
+ len
;
1388 if (*buflen
< struct_len
) {
1395 p2
= p
+ struct_len
;
1396 l2
= *buflen
- struct_len
;
1404 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1408 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1409 SIVAL(p
,18,service
->type
);
1410 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1411 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1416 *buf
= p
+ struct_len
;
1417 *buflen
-= struct_len
;
1428 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1430 return strcasecmp_m(s1
->name
,s2
->name
);
1433 /****************************************************************************
1434 View list of servers available (or possibly domains). The info is
1435 extracted from lists saved by nmbd on the local host.
1436 ****************************************************************************/
1438 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1439 connection_struct
*conn
, uint64_t vuid
,
1440 char *param
, int tpscnt
,
1441 char *data
, int tdscnt
,
1442 int mdrcnt
, int mprcnt
, char **rdata
,
1443 char **rparam
, int *rdata_len
, int *rparam_len
)
1445 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1446 char *str2
= skip_string(param
,tpscnt
,str1
);
1447 char *p
= skip_string(param
,tpscnt
,str2
);
1448 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1449 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1450 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1452 int data_len
, fixed_len
, string_len
;
1453 int f_len
= 0, s_len
= 0;
1454 struct srv_info_struct
*servers
=NULL
;
1455 int counted
=0,total
=0;
1458 bool domain_request
;
1461 if (!str1
|| !str2
|| !p
) {
1465 /* If someone sets all the bits they don't really mean to set
1466 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1469 if (servertype
== SV_TYPE_ALL
) {
1470 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1473 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1474 any other bit (they may just set this bit on its own) they
1475 want all the locally seen servers. However this bit can be
1476 set on its own so set the requested servers to be
1477 ALL - DOMAIN_ENUM. */
1479 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1480 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1483 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1484 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1488 if (!prefix_ok(str1
,"WrLehD")) {
1491 if (!check_session_info(uLevel
,str2
)) {
1495 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1496 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1497 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1499 if (strcmp(str1
, "WrLehDz") == 0) {
1500 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1503 pull_ascii_fstring(domain
, p
);
1505 fstrcpy(domain
, lp_workgroup());
1508 DEBUG(4, ("domain [%s]\n", domain
));
1510 if (lp_browse_list()) {
1511 total
= get_session_info(servertype
,&servers
,domain
);
1514 data_len
= fixed_len
= string_len
= 0;
1517 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1520 char *lastname
=NULL
;
1522 for (i
=0;i
<total
;i
++) {
1523 struct srv_info_struct
*s
= &servers
[i
];
1525 if (lastname
&& strequal(lastname
,s
->name
)) {
1529 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1530 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1531 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1533 if (data_len
< buf_len
) {
1536 string_len
+= s_len
;
1543 *rdata_len
= fixed_len
+ string_len
;
1544 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1549 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1555 char *lastname
=NULL
;
1556 int count2
= counted
;
1558 for (i
= 0; i
< total
&& count2
;i
++) {
1559 struct srv_info_struct
*s
= &servers
[i
];
1561 if (lastname
&& strequal(lastname
,s
->name
)) {
1565 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1566 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1567 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1573 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1577 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1579 SSVAL(*rparam
,4,counted
);
1580 SSVAL(*rparam
,6,counted
+missed
);
1584 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1585 domain
,uLevel
,counted
,counted
+missed
));
1590 static int srv_name_match(const char *n1
, const char *n2
)
1593 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1595 * In Windows, FirstNameToReturn need not be an exact match:
1596 * the server will return a list of servers that exist on
1597 * the network greater than or equal to the FirstNameToReturn.
1599 int ret
= strcasecmp_m(n1
, n2
);
1608 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1609 connection_struct
*conn
, uint64_t vuid
,
1610 char *param
, int tpscnt
,
1611 char *data
, int tdscnt
,
1612 int mdrcnt
, int mprcnt
, char **rdata
,
1613 char **rparam
, int *rdata_len
, int *rparam_len
)
1615 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1616 char *str2
= skip_string(param
,tpscnt
,str1
);
1617 char *p
= skip_string(param
,tpscnt
,str2
);
1618 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1619 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1620 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1622 int data_len
, fixed_len
, string_len
;
1623 int f_len
= 0, s_len
= 0;
1624 struct srv_info_struct
*servers
=NULL
;
1625 int counted
=0,first
=0,total
=0;
1629 bool domain_request
;
1632 if (!str1
|| !str2
|| !p
) {
1636 /* If someone sets all the bits they don't really mean to set
1637 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1640 if (servertype
== SV_TYPE_ALL
) {
1641 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1644 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1645 any other bit (they may just set this bit on its own) they
1646 want all the locally seen servers. However this bit can be
1647 set on its own so set the requested servers to be
1648 ALL - DOMAIN_ENUM. */
1650 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1651 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1654 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1655 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1659 if (strcmp(str1
, "WrLehDzz") != 0) {
1662 if (!check_session_info(uLevel
,str2
)) {
1666 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1667 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1668 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1670 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1673 pull_ascii_fstring(domain
, p
);
1674 if (domain
[0] == '\0') {
1675 fstrcpy(domain
, lp_workgroup());
1677 p
= skip_string(param
,tpscnt
,p
);
1678 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1681 pull_ascii_fstring(first_name
, p
);
1683 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1684 domain
, first_name
));
1686 if (lp_browse_list()) {
1687 total
= get_session_info(servertype
,&servers
,domain
);
1690 data_len
= fixed_len
= string_len
= 0;
1693 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1695 if (first_name
[0] != '\0') {
1696 struct srv_info_struct
*first_server
= NULL
;
1698 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1699 srv_name_match
, first_server
);
1701 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1703 * The binary search may not find the exact match
1704 * so we need to search backward to find the first match
1706 * This implements the strange matching windows
1707 * implements. (see the comment in srv_name_match().
1711 ret
= strcasecmp_m(first_name
,
1712 servers
[first
-1].name
);
1719 /* we should return no entries */
1725 char *lastname
=NULL
;
1727 for (i
=first
;i
<total
;i
++) {
1728 struct srv_info_struct
*s
= &servers
[i
];
1730 if (lastname
&& strequal(lastname
,s
->name
)) {
1734 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1735 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1736 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1738 if (data_len
< buf_len
) {
1741 string_len
+= s_len
;
1748 *rdata_len
= fixed_len
+ string_len
;
1749 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1754 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1760 char *lastname
=NULL
;
1761 int count2
= counted
;
1763 for (i
= first
; i
< total
&& count2
;i
++) {
1764 struct srv_info_struct
*s
= &servers
[i
];
1766 if (lastname
&& strequal(lastname
,s
->name
)) {
1770 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1771 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1772 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1778 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1782 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1784 SSVAL(*rparam
,4,counted
);
1785 SSVAL(*rparam
,6,counted
+missed
);
1787 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1788 domain
,uLevel
,first
,first_name
,
1789 first
< total
? servers
[first
].name
: "",
1790 counted
,counted
+missed
));
1797 /****************************************************************************
1798 command 0x34 - suspected of being a "Lookup Names" stub api
1799 ****************************************************************************/
1801 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1802 connection_struct
*conn
, uint64_t vuid
,
1803 char *param
, int tpscnt
,
1804 char *data
, int tdscnt
,
1805 int mdrcnt
, int mprcnt
, char **rdata
,
1806 char **rparam
, int *rdata_len
, int *rparam_len
)
1808 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1809 char *str2
= skip_string(param
,tpscnt
,str1
);
1810 char *p
= skip_string(param
,tpscnt
,str2
);
1811 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1812 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1816 if (!str1
|| !str2
|| !p
) {
1820 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1821 str1
, str2
, p
, uLevel
, buf_len
));
1823 if (!prefix_ok(str1
,"zWrLeh")) {
1830 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1835 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1837 SSVAL(*rparam
,4,counted
);
1838 SSVAL(*rparam
,6,counted
+missed
);
1843 /****************************************************************************
1844 get info about a share
1845 ****************************************************************************/
1847 static bool check_share_info(int uLevel
, char* id
)
1851 if (strcmp(id
,"B13") != 0) {
1856 /* Level-2 descriptor is allowed (and ignored) */
1857 if (strcmp(id
,"B13BWz") != 0 &&
1858 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1863 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1868 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1878 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1879 char** buf
, int* buflen
,
1880 char** stringbuf
, int* stringspace
, char* baseaddr
)
1909 len
+= StrlenExpanded(conn
,snum
,lp_comment(talloc_tos(), snum
));
1912 len
+= strlen(lp_pathname(talloc_tos(), snum
)) + 1;
1915 *buflen
= struct_len
;
1920 return struct_len
+ len
;
1925 if ((*buflen
) < struct_len
) {
1933 p2
= p
+ struct_len
;
1934 l2
= (*buflen
) - struct_len
;
1941 push_ascii(p
,lp_servicename(talloc_tos(), snum
),13, STR_TERMINATE
);
1947 type
= STYPE_DISKTREE
;
1948 if (lp_print_ok(snum
)) {
1949 type
= STYPE_PRINTQ
;
1951 if (strequal("IPC",lp_fstype(talloc_tos(),snum
))) {
1954 SSVAL(p
,14,type
); /* device type */
1955 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1956 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(talloc_tos(),snum
),&l2
);
1960 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1961 SSVALS(p
,22,-1); /* max uses */
1962 SSVAL(p
,24,1); /* current uses */
1963 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1964 len
+= CopyAndAdvance(&p2
,lp_pathname(talloc_tos(),snum
),&l2
);
1965 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1969 memset(p
+40,0,SHPWLEN
+2);
1980 (*buf
) = p
+ struct_len
;
1981 (*buflen
) -= struct_len
;
1983 (*stringspace
) = l2
;
1992 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
1993 connection_struct
*conn
,uint64_t vuid
,
1994 char *param
, int tpscnt
,
1995 char *data
, int tdscnt
,
1996 int mdrcnt
,int mprcnt
,
1997 char **rdata
,char **rparam
,
1998 int *rdata_len
,int *rparam_len
)
2000 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2001 char *str2
= skip_string(param
,tpscnt
,str1
);
2002 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2003 char *netname
= NULL
;
2004 char *p
= skip_string(param
,tpscnt
,netname
);
2005 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2008 if (!str1
|| !str2
|| !netname_in
|| !p
) {
2012 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2013 if (snum
< 0 || !netname
) {
2017 /* check it's a supported varient */
2018 if (!prefix_ok(str1
,"zWrLh")) {
2021 if (!check_share_info(uLevel
,str2
)) {
2025 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2030 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2031 if (*rdata_len
< 0) {
2036 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2040 SSVAL(*rparam
,0,NERR_Success
);
2041 SSVAL(*rparam
,2,0); /* converter word */
2042 SSVAL(*rparam
,4,*rdata_len
);
2047 /****************************************************************************
2048 View the list of available shares.
2050 This function is the server side of the NetShareEnum() RAP call.
2051 It fills the return buffer with share names and share comments.
2052 Note that the return buffer normally (in all known cases) allows only
2053 twelve byte strings for share names (plus one for a nul terminator).
2054 Share names longer than 12 bytes must be skipped.
2055 ****************************************************************************/
2057 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2058 connection_struct
*conn
, uint64_t vuid
,
2059 char *param
, int tpscnt
,
2060 char *data
, int tdscnt
,
2068 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2069 char *str2
= skip_string(param
,tpscnt
,str1
);
2070 char *p
= skip_string(param
,tpscnt
,str2
);
2071 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2072 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2075 int total
=0,counted
=0;
2076 bool missed
= False
;
2078 int data_len
, fixed_len
, string_len
;
2079 int f_len
= 0, s_len
= 0;
2081 if (!str1
|| !str2
|| !p
) {
2085 if (!prefix_ok(str1
,"WrLeh")) {
2088 if (!check_share_info(uLevel
,str2
)) {
2092 /* Ensure all the usershares are loaded. */
2094 load_registry_shares();
2095 count
= load_usershare_shares(NULL
, connections_snum_used
);
2098 data_len
= fixed_len
= string_len
= 0;
2099 for (i
=0;i
<count
;i
++) {
2100 fstring servicename_dos
;
2101 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2104 push_ascii_fstring(servicename_dos
, lp_servicename(talloc_tos(), i
));
2105 /* Maximum name length = 13. */
2106 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2108 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2109 if (data_len
< buf_len
) {
2112 string_len
+= s_len
;
2119 *rdata_len
= fixed_len
+ string_len
;
2120 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2125 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2130 for( i
= 0; i
< count
; i
++ ) {
2131 fstring servicename_dos
;
2132 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2136 push_ascii_fstring(servicename_dos
,
2137 lp_servicename(talloc_tos(), i
));
2138 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2139 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2146 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2150 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2152 SSVAL(*rparam
,4,counted
);
2153 SSVAL(*rparam
,6,total
);
2155 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2156 counted
,total
,uLevel
,
2157 buf_len
,*rdata_len
,mdrcnt
));
2162 /****************************************************************************
2164 ****************************************************************************/
2166 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2167 connection_struct
*conn
,uint64_t vuid
,
2168 char *param
, int tpscnt
,
2169 char *data
, int tdscnt
,
2170 int mdrcnt
,int mprcnt
,
2171 char **rdata
,char **rparam
,
2172 int *rdata_len
,int *rparam_len
)
2174 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2175 char *str2
= skip_string(param
,tpscnt
,str1
);
2176 char *p
= skip_string(param
,tpscnt
,str2
);
2177 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2180 char *pathname
= NULL
;
2181 unsigned int offset
;
2183 size_t converted_size
;
2185 WERROR werr
= WERR_OK
;
2186 TALLOC_CTX
*mem_ctx
= talloc_tos();
2188 struct rpc_pipe_client
*cli
= NULL
;
2189 union srvsvc_NetShareInfo info
;
2190 struct srvsvc_NetShareInfo2 info2
;
2191 struct dcerpc_binding_handle
*b
;
2193 if (!str1
|| !str2
|| !p
) {
2197 /* check it's a supported varient */
2198 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2201 if (!check_share_info(uLevel
,str2
)) {
2208 /* Do we have a string ? */
2209 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2212 pull_ascii_fstring(sharename
,data
);
2218 /* only support disk share adds */
2219 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2223 offset
= IVAL(data
, 16);
2224 if (offset
>= mdrcnt
) {
2225 res
= ERRinvalidparam
;
2229 /* Do we have a string ? */
2230 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2233 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2235 offset
= IVAL(data
, 26);
2237 if (offset
>= mdrcnt
) {
2238 res
= ERRinvalidparam
;
2242 /* Do we have a string ? */
2243 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2247 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2248 offset
? (data
+offset
) : "", &converted_size
))
2250 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2258 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2260 conn
->sconn
->remote_address
,
2261 conn
->sconn
->msg_ctx
,
2263 if (!NT_STATUS_IS_OK(status
)) {
2264 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2265 nt_errstr(status
)));
2266 res
= W_ERROR_V(ntstatus_to_werror(status
));
2270 b
= cli
->binding_handle
;
2272 info2
.name
= sharename
;
2273 info2
.type
= STYPE_DISKTREE
;
2274 info2
.comment
= comment
;
2275 info2
.permissions
= 0;
2276 info2
.max_users
= 0;
2277 info2
.current_users
= 0;
2278 info2
.path
= pathname
;
2279 info2
.password
= NULL
;
2281 info
.info2
= &info2
;
2283 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2284 cli
->srv_name_slash
,
2289 if (!NT_STATUS_IS_OK(status
)) {
2290 res
= W_ERROR_V(ntstatus_to_werror(status
));
2293 if (!W_ERROR_IS_OK(werr
)) {
2294 res
= W_ERROR_V(werr
);
2299 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2303 SSVAL(*rparam
,0,NERR_Success
);
2304 SSVAL(*rparam
,2,0); /* converter word */
2305 SSVAL(*rparam
,4,*rdata_len
);
2313 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2318 SSVAL(*rparam
,0,res
);
2323 /****************************************************************************
2324 view list of groups available
2325 ****************************************************************************/
2327 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2328 connection_struct
*conn
,uint64_t vuid
,
2329 char *param
, int tpscnt
,
2330 char *data
, int tdscnt
,
2331 int mdrcnt
,int mprcnt
,
2332 char **rdata
,char **rparam
,
2333 int *rdata_len
,int *rparam_len
)
2337 int resume_context
, cli_buf_size
;
2338 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2339 char *str2
= skip_string(param
,tpscnt
,str1
);
2340 char *p
= skip_string(param
,tpscnt
,str2
);
2342 uint32_t num_groups
;
2343 uint32_t resume_handle
;
2344 struct rpc_pipe_client
*samr_pipe
;
2345 struct policy_handle samr_handle
, domain_handle
;
2346 NTSTATUS status
, result
;
2347 struct dcerpc_binding_handle
*b
;
2349 if (!str1
|| !str2
|| !p
) {
2353 if (strcmp(str1
,"WrLeh") != 0) {
2358 * W-> resume context (number of users to skip)
2359 * r -> return parameter pointer to receive buffer
2360 * L -> length of receive buffer
2361 * e -> return parameter number of entries
2362 * h -> return parameter total number of users
2365 if (strcmp("B21",str2
) != 0) {
2369 status
= rpc_pipe_open_interface(
2370 talloc_tos(), &ndr_table_samr
.syntax_id
,
2371 conn
->session_info
, conn
->sconn
->remote_address
,
2372 conn
->sconn
->msg_ctx
, &samr_pipe
);
2373 if (!NT_STATUS_IS_OK(status
)) {
2374 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2375 nt_errstr(status
)));
2379 b
= samr_pipe
->binding_handle
;
2381 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2382 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2384 if (!NT_STATUS_IS_OK(status
)) {
2385 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2386 nt_errstr(status
)));
2389 if (!NT_STATUS_IS_OK(result
)) {
2390 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2391 nt_errstr(result
)));
2395 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2396 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2397 get_global_sam_sid(), &domain_handle
,
2399 if (!NT_STATUS_IS_OK(status
)) {
2400 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2401 nt_errstr(status
)));
2402 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2405 if (!NT_STATUS_IS_OK(result
)) {
2406 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2407 nt_errstr(result
)));
2408 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2412 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2413 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2414 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2415 "%d\n", resume_context
, cli_buf_size
));
2417 *rdata_len
= cli_buf_size
;
2418 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2425 errflags
= NERR_Success
;
2430 struct samr_SamArray
*sam_entries
;
2431 uint32_t num_entries
;
2433 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2439 if (!NT_STATUS_IS_OK(status
)) {
2440 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2441 "%s\n", nt_errstr(status
)));
2444 if (!NT_STATUS_IS_OK(result
)) {
2446 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2447 "%s\n", nt_errstr(result
)));
2451 if (num_entries
== 0) {
2452 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2453 "no entries -- done\n"));
2457 for(i
=0; i
<num_entries
; i
++) {
2460 name
= sam_entries
->entries
[i
].name
.string
;
2462 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2463 /* set overflow error */
2464 DEBUG(3,("overflow on entry %d group %s\n", i
,
2470 /* truncate the name at 21 chars. */
2472 strlcpy(p
, name
, 21);
2473 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2475 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2480 if (errflags
!= NERR_Success
) {
2484 TALLOC_FREE(sam_entries
);
2487 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2488 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2490 *rdata_len
= PTR_DIFF(p
,*rdata
);
2493 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2497 SSVAL(*rparam
, 0, errflags
);
2498 SSVAL(*rparam
, 2, 0); /* converter word */
2499 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2500 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2505 /*******************************************************************
2506 Get groups that a user is a member of.
2507 ******************************************************************/
2509 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2510 connection_struct
*conn
,uint64_t vuid
,
2511 char *param
, int tpscnt
,
2512 char *data
, int tdscnt
,
2513 int mdrcnt
,int mprcnt
,
2514 char **rdata
,char **rparam
,
2515 int *rdata_len
,int *rparam_len
)
2517 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2518 char *str2
= skip_string(param
,tpscnt
,str1
);
2519 char *UserName
= skip_string(param
,tpscnt
,str2
);
2520 char *p
= skip_string(param
,tpscnt
,UserName
);
2521 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2522 const char *level_string
;
2528 struct rpc_pipe_client
*samr_pipe
;
2529 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2530 struct lsa_String name
;
2531 struct lsa_Strings names
;
2532 struct samr_Ids type
, rid
;
2533 struct samr_RidWithAttributeArray
*rids
;
2534 NTSTATUS status
, result
;
2535 struct dcerpc_binding_handle
*b
;
2537 if (!str1
|| !str2
|| !UserName
|| !p
) {
2542 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2547 /* check it's a supported varient */
2549 if ( strcmp(str1
,"zWrLeh") != 0 )
2554 level_string
= "B21";
2560 if (strcmp(level_string
,str2
) != 0)
2563 *rdata_len
= mdrcnt
+ 1024;
2564 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2569 SSVAL(*rparam
,0,NERR_Success
);
2570 SSVAL(*rparam
,2,0); /* converter word */
2573 endp
= *rdata
+ *rdata_len
;
2575 status
= rpc_pipe_open_interface(
2576 talloc_tos(), &ndr_table_samr
.syntax_id
,
2577 conn
->session_info
, conn
->sconn
->remote_address
,
2578 conn
->sconn
->msg_ctx
, &samr_pipe
);
2579 if (!NT_STATUS_IS_OK(status
)) {
2580 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2581 nt_errstr(status
)));
2585 b
= samr_pipe
->binding_handle
;
2587 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2588 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2590 if (!NT_STATUS_IS_OK(status
)) {
2591 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2592 nt_errstr(status
)));
2595 if (!NT_STATUS_IS_OK(result
)) {
2596 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2597 nt_errstr(result
)));
2601 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2602 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2603 get_global_sam_sid(), &domain_handle
,
2605 if (!NT_STATUS_IS_OK(status
)) {
2606 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2607 nt_errstr(status
)));
2610 if (!NT_STATUS_IS_OK(result
)) {
2611 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2612 nt_errstr(result
)));
2616 name
.string
= UserName
;
2618 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2619 &domain_handle
, 1, &name
,
2622 if (!NT_STATUS_IS_OK(status
)) {
2623 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2624 nt_errstr(status
)));
2627 if (!NT_STATUS_IS_OK(result
)) {
2628 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2629 nt_errstr(result
)));
2633 if (type
.ids
[0] != SID_NAME_USER
) {
2634 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2635 sid_type_lookup(type
.ids
[0])));
2639 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2641 SAMR_USER_ACCESS_GET_GROUPS
,
2642 rid
.ids
[0], &user_handle
,
2644 if (!NT_STATUS_IS_OK(status
)) {
2645 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2646 nt_errstr(status
)));
2649 if (!NT_STATUS_IS_OK(result
)) {
2650 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2651 nt_errstr(result
)));
2655 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2656 &user_handle
, &rids
,
2658 if (!NT_STATUS_IS_OK(status
)) {
2659 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2660 nt_errstr(status
)));
2663 if (!NT_STATUS_IS_OK(result
)) {
2664 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2665 nt_errstr(result
)));
2669 for (i
=0; i
<rids
->count
; i
++) {
2671 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2673 1, &rids
->rids
[i
].rid
,
2676 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2677 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2683 *rdata_len
= PTR_DIFF(p
,*rdata
);
2685 SSVAL(*rparam
,4,count
); /* is this right?? */
2686 SSVAL(*rparam
,6,count
); /* is this right?? */
2691 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2693 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2695 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2700 /*******************************************************************
2702 ******************************************************************/
2704 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2705 connection_struct
*conn
, uint64_t vuid
,
2706 char *param
, int tpscnt
,
2707 char *data
, int tdscnt
,
2708 int mdrcnt
,int mprcnt
,
2709 char **rdata
,char **rparam
,
2710 int *rdata_len
,int *rparam_len
)
2715 int i
, resume_context
, cli_buf_size
;
2716 uint32_t resume_handle
;
2718 struct rpc_pipe_client
*samr_pipe
;
2719 struct policy_handle samr_handle
, domain_handle
;
2720 NTSTATUS status
, result
;
2722 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2723 char *str2
= skip_string(param
,tpscnt
,str1
);
2724 char *p
= skip_string(param
,tpscnt
,str2
);
2727 struct dcerpc_binding_handle
*b
;
2729 if (!str1
|| !str2
|| !p
) {
2733 if (strcmp(str1
,"WrLeh") != 0)
2736 * W-> resume context (number of users to skip)
2737 * r -> return parameter pointer to receive buffer
2738 * L -> length of receive buffer
2739 * e -> return parameter number of entries
2740 * h -> return parameter total number of users
2743 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2744 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2745 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2746 resume_context
, cli_buf_size
));
2749 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2754 /* check it's a supported varient */
2755 if (strcmp("B21",str2
) != 0)
2758 *rdata_len
= cli_buf_size
;
2759 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2765 endp
= *rdata
+ *rdata_len
;
2767 status
= rpc_pipe_open_interface(
2768 talloc_tos(), &ndr_table_samr
.syntax_id
,
2769 conn
->session_info
, conn
->sconn
->remote_address
,
2770 conn
->sconn
->msg_ctx
, &samr_pipe
);
2771 if (!NT_STATUS_IS_OK(status
)) {
2772 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2773 nt_errstr(status
)));
2777 b
= samr_pipe
->binding_handle
;
2779 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2780 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2782 if (!NT_STATUS_IS_OK(status
)) {
2783 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2784 nt_errstr(status
)));
2787 if (!NT_STATUS_IS_OK(result
)) {
2788 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2789 nt_errstr(result
)));
2793 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2794 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2795 get_global_sam_sid(), &domain_handle
,
2797 if (!NT_STATUS_IS_OK(status
)) {
2798 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2799 nt_errstr(status
)));
2800 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2803 if (!NT_STATUS_IS_OK(result
)) {
2804 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2805 nt_errstr(result
)));
2806 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2810 errflags
=NERR_Success
;
2815 struct samr_SamArray
*sam_entries
;
2816 uint32_t num_entries
;
2818 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2825 if (!NT_STATUS_IS_OK(status
)) {
2826 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2827 "%s\n", nt_errstr(status
)));
2830 if (!NT_STATUS_IS_OK(result
)) {
2831 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2832 "%s\n", nt_errstr(result
)));
2836 if (num_entries
== 0) {
2837 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2838 "no entries -- done\n"));
2842 for (i
=0; i
<num_entries
; i
++) {
2845 name
= sam_entries
->entries
[i
].name
.string
;
2847 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2848 &&(strlen(name
)<=21)) {
2849 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2850 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2851 "username %s\n",count_sent
,p
));
2855 /* set overflow error */
2856 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2857 "username %s\n",count_sent
,name
));
2863 if (errflags
!= NERR_Success
) {
2867 TALLOC_FREE(sam_entries
);
2870 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2871 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2873 *rdata_len
= PTR_DIFF(p
,*rdata
);
2875 SSVAL(*rparam
,0,errflags
);
2876 SSVAL(*rparam
,2,0); /* converter word */
2877 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2878 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2883 /****************************************************************************
2884 Get the time of day info.
2885 ****************************************************************************/
2887 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2888 connection_struct
*conn
,uint64_t vuid
,
2889 char *param
, int tpscnt
,
2890 char *data
, int tdscnt
,
2891 int mdrcnt
,int mprcnt
,
2892 char **rdata
,char **rparam
,
2893 int *rdata_len
,int *rparam_len
)
2896 time_t unixdate
= time(NULL
);
2900 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2906 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2911 SSVAL(*rparam
,0,NERR_Success
);
2912 SSVAL(*rparam
,2,0); /* converter word */
2916 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2917 by NT in a "net time" operation,
2918 it seems to ignore the one below */
2920 /* the client expects to get localtime, not GMT, in this bit
2921 (I think, this needs testing) */
2922 t
= localtime(&unixdate
);
2927 SIVAL(p
,4,0); /* msecs ? */
2928 SCVAL(p
,8,t
->tm_hour
);
2929 SCVAL(p
,9,t
->tm_min
);
2930 SCVAL(p
,10,t
->tm_sec
);
2931 SCVAL(p
,11,0); /* hundredths of seconds */
2932 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2933 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2934 SCVAL(p
,16,t
->tm_mday
);
2935 SCVAL(p
,17,t
->tm_mon
+ 1);
2936 SSVAL(p
,18,1900+t
->tm_year
);
2937 SCVAL(p
,20,t
->tm_wday
);
2942 /****************************************************************************
2943 Set the user password.
2944 *****************************************************************************/
2946 static bool api_SetUserPassword(struct smbd_server_connection
*sconn
,
2947 connection_struct
*conn
,uint64_t vuid
,
2948 char *param
, int tpscnt
,
2949 char *data
, int tdscnt
,
2950 int mdrcnt
,int mprcnt
,
2951 char **rdata
,char **rparam
,
2952 int *rdata_len
,int *rparam_len
)
2954 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2957 fstring pass1
,pass2
;
2958 TALLOC_CTX
*mem_ctx
= talloc_tos();
2959 NTSTATUS status
, result
;
2960 struct rpc_pipe_client
*cli
= NULL
;
2961 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2962 struct lsa_String domain_name
;
2963 struct dom_sid2
*domain_sid
;
2964 struct lsa_String names
;
2965 struct samr_Ids rids
;
2966 struct samr_Ids types
;
2967 struct samr_Password old_lm_hash
;
2968 struct samr_Password new_lm_hash
;
2969 int errcode
= NERR_badpass
;
2973 struct dcerpc_binding_handle
*b
= NULL
;
2975 /* Skip 2 strings. */
2976 p
= skip_string(param
,tpscnt
,np
);
2977 p
= skip_string(param
,tpscnt
,p
);
2983 /* Do we have a string ? */
2984 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2987 pull_ascii_fstring(user
,p
);
2989 p
= skip_string(param
,tpscnt
,p
);
2994 memset(pass1
,'\0',sizeof(pass1
));
2995 memset(pass2
,'\0',sizeof(pass2
));
2997 * We use 31 here not 32 as we're checking
2998 * the last byte we want to access is safe.
3000 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
3004 memcpy(pass2
,p
+16,16);
3006 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
3007 if (encrypted
== -1) {
3008 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3012 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
3013 if (min_pwd_length
== -1) {
3014 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3019 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3026 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
3027 user
, encrypted
, min_pwd_length
));
3029 ZERO_STRUCT(connect_handle
);
3030 ZERO_STRUCT(domain_handle
);
3031 ZERO_STRUCT(user_handle
);
3033 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
.syntax_id
,
3035 conn
->sconn
->remote_address
,
3036 conn
->sconn
->msg_ctx
,
3038 if (!NT_STATUS_IS_OK(status
)) {
3039 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
3040 nt_errstr(status
)));
3041 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3045 b
= cli
->binding_handle
;
3047 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
3049 SAMR_ACCESS_CONNECT_TO_SERVER
|
3050 SAMR_ACCESS_ENUM_DOMAINS
|
3051 SAMR_ACCESS_LOOKUP_DOMAIN
,
3054 if (!NT_STATUS_IS_OK(status
)) {
3055 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3058 if (!NT_STATUS_IS_OK(result
)) {
3059 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3063 init_lsa_String(&domain_name
, get_global_sam_name());
3065 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
3070 if (!NT_STATUS_IS_OK(status
)) {
3071 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3074 if (!NT_STATUS_IS_OK(result
)) {
3075 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3079 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
3081 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
3085 if (!NT_STATUS_IS_OK(status
)) {
3086 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3089 if (!NT_STATUS_IS_OK(result
)) {
3090 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3094 init_lsa_String(&names
, user
);
3096 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
3103 if (!NT_STATUS_IS_OK(status
)) {
3104 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3107 if (!NT_STATUS_IS_OK(result
)) {
3108 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3112 if (rids
.count
!= 1) {
3113 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
3116 if (rids
.count
!= types
.count
) {
3117 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3120 if (types
.ids
[0] != SID_NAME_USER
) {
3121 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3127 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
3129 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
3133 if (!NT_STATUS_IS_OK(status
)) {
3134 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3137 if (!NT_STATUS_IS_OK(result
)) {
3138 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3142 if (encrypted
== 0) {
3143 E_deshash(pass1
, old_lm_hash
.hash
);
3144 E_deshash(pass2
, new_lm_hash
.hash
);
3146 ZERO_STRUCT(old_lm_hash
);
3147 ZERO_STRUCT(new_lm_hash
);
3148 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
3149 memcpy(new_lm_hash
.hash
, pass2
, MIN(strlen(pass2
), 16));
3152 status
= dcerpc_samr_ChangePasswordUser(b
, mem_ctx
,
3154 true, /* lm_present */
3157 false, /* nt_present */
3158 NULL
, /* old_nt_crypted */
3159 NULL
, /* new_nt_crypted */
3160 false, /* cross1_present */
3161 NULL
, /* nt_cross */
3162 false, /* cross2_present */
3163 NULL
, /* lm_cross */
3165 if (!NT_STATUS_IS_OK(status
)) {
3166 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3169 if (!NT_STATUS_IS_OK(result
)) {
3170 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3174 errcode
= NERR_Success
;
3177 if (b
&& is_valid_policy_hnd(&user_handle
)) {
3178 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
3180 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
3181 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
3183 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
3184 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
3187 memset((char *)pass1
,'\0',sizeof(fstring
));
3188 memset((char *)pass2
,'\0',sizeof(fstring
));
3190 SSVAL(*rparam
,0,errcode
);
3191 SSVAL(*rparam
,2,0); /* converter word */
3195 /****************************************************************************
3196 Set the user password (SamOEM version - gets plaintext).
3197 ****************************************************************************/
3199 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3200 connection_struct
*conn
,uint64_t vuid
,
3201 char *param
, int tpscnt
,
3202 char *data
, int tdscnt
,
3203 int mdrcnt
,int mprcnt
,
3204 char **rdata
,char **rparam
,
3205 int *rdata_len
,int *rparam_len
)
3208 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3210 TALLOC_CTX
*mem_ctx
= talloc_tos();
3211 NTSTATUS status
, result
;
3212 struct rpc_pipe_client
*cli
= NULL
;
3213 struct lsa_AsciiString server
, account
;
3214 struct samr_CryptPassword password
;
3215 struct samr_Password hash
;
3216 int errcode
= NERR_badpass
;
3218 struct dcerpc_binding_handle
*b
;
3221 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3231 SSVAL(*rparam
,0,NERR_badpass
);
3234 * Check the parameter definition is correct.
3237 /* Do we have a string ? */
3238 if (skip_string(param
,tpscnt
,p
) == 0) {
3241 if(!strequal(p
, "zsT")) {
3242 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3245 p
= skip_string(param
, tpscnt
, p
);
3250 /* Do we have a string ? */
3251 if (skip_string(param
,tpscnt
,p
) == 0) {
3254 if(!strequal(p
, "B516B16")) {
3255 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3258 p
= skip_string(param
,tpscnt
,p
);
3262 /* Do we have a string ? */
3263 if (skip_string(param
,tpscnt
,p
) == 0) {
3266 p
+= pull_ascii_fstring(user
,p
);
3268 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3270 if (tdscnt
!= 532) {
3271 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3275 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3276 if (bufsize
!= 532) {
3277 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3281 memcpy(password
.data
, data
, 516);
3282 memcpy(hash
.hash
, data
+516, 16);
3284 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
.syntax_id
,
3286 conn
->sconn
->remote_address
,
3287 conn
->sconn
->msg_ctx
,
3289 if (!NT_STATUS_IS_OK(status
)) {
3290 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3291 nt_errstr(status
)));
3292 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3296 b
= cli
->binding_handle
;
3298 init_lsa_AsciiString(&server
, lp_netbios_name());
3299 init_lsa_AsciiString(&account
, user
);
3301 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3307 if (!NT_STATUS_IS_OK(status
)) {
3308 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3311 if (!NT_STATUS_IS_OK(result
)) {
3312 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3316 errcode
= NERR_Success
;
3318 SSVAL(*rparam
,0,errcode
);
3319 SSVAL(*rparam
,2,0); /* converter word */
3324 /****************************************************************************
3327 ****************************************************************************/
3329 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3330 connection_struct
*conn
,uint64_t vuid
,
3331 char *param
, int tpscnt
,
3332 char *data
, int tdscnt
,
3333 int mdrcnt
,int mprcnt
,
3334 char **rdata
,char **rparam
,
3335 int *rdata_len
,int *rparam_len
)
3337 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3338 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3339 char *str2
= skip_string(param
,tpscnt
,str1
);
3340 char *p
= skip_string(param
,tpscnt
,str2
);
3344 WERROR werr
= WERR_OK
;
3346 TALLOC_CTX
*mem_ctx
= talloc_tos();
3348 struct rpc_pipe_client
*cli
= NULL
;
3349 struct dcerpc_binding_handle
*b
= NULL
;
3350 struct policy_handle handle
;
3351 struct spoolss_DevmodeContainer devmode_ctr
;
3352 enum spoolss_JobControl command
;
3354 if (!str1
|| !str2
|| !p
) {
3358 * We use 1 here not 2 as we're checking
3359 * the last byte we want to access is safe.
3361 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3364 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3367 /* check it's a supported varient */
3368 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3372 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3378 ZERO_STRUCT(handle
);
3380 status
= rpc_pipe_open_interface(conn
,
3381 &ndr_table_spoolss
.syntax_id
,
3383 conn
->sconn
->remote_address
,
3384 conn
->sconn
->msg_ctx
,
3386 if (!NT_STATUS_IS_OK(status
)) {
3387 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3388 nt_errstr(status
)));
3389 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3392 b
= cli
->binding_handle
;
3394 ZERO_STRUCT(devmode_ctr
);
3396 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3400 JOB_ACCESS_ADMINISTER
,
3403 if (!NT_STATUS_IS_OK(status
)) {
3404 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3407 if (!W_ERROR_IS_OK(werr
)) {
3408 errcode
= W_ERROR_V(werr
);
3412 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3413 * and NERR_DestNotFound if share did not exist */
3415 errcode
= NERR_Success
;
3418 case 81: /* delete */
3419 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3421 case 82: /* pause */
3422 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3424 case 83: /* resume */
3425 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3428 errcode
= NERR_notsupported
;
3432 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3435 NULL
, /* unique ptr ctr */
3438 if (!NT_STATUS_IS_OK(status
)) {
3439 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3442 if (!W_ERROR_IS_OK(werr
)) {
3443 errcode
= W_ERROR_V(werr
);
3448 if (b
&& is_valid_policy_hnd(&handle
)) {
3449 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3452 SSVAL(*rparam
,0,errcode
);
3453 SSVAL(*rparam
,2,0); /* converter word */
3458 /****************************************************************************
3459 Purge a print queue - or pause or resume it.
3460 ****************************************************************************/
3462 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3463 connection_struct
*conn
,uint64_t vuid
,
3464 char *param
, int tpscnt
,
3465 char *data
, int tdscnt
,
3466 int mdrcnt
,int mprcnt
,
3467 char **rdata
,char **rparam
,
3468 int *rdata_len
,int *rparam_len
)
3470 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3471 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3472 char *str2
= skip_string(param
,tpscnt
,str1
);
3473 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3474 int errcode
= NERR_notsupported
;
3475 WERROR werr
= WERR_OK
;
3478 TALLOC_CTX
*mem_ctx
= talloc_tos();
3479 struct rpc_pipe_client
*cli
= NULL
;
3480 struct dcerpc_binding_handle
*b
= NULL
;
3481 struct policy_handle handle
;
3482 struct spoolss_SetPrinterInfoCtr info_ctr
;
3483 struct spoolss_DevmodeContainer devmode_ctr
;
3484 struct sec_desc_buf secdesc_ctr
;
3485 enum spoolss_PrinterControl command
;
3487 if (!str1
|| !str2
|| !QueueName
) {
3491 /* check it's a supported varient */
3492 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3496 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3502 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3506 ZERO_STRUCT(handle
);
3508 status
= rpc_pipe_open_interface(conn
,
3509 &ndr_table_spoolss
.syntax_id
,
3511 conn
->sconn
->remote_address
,
3512 conn
->sconn
->msg_ctx
,
3514 if (!NT_STATUS_IS_OK(status
)) {
3515 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3516 nt_errstr(status
)));
3517 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3520 b
= cli
->binding_handle
;
3522 ZERO_STRUCT(devmode_ctr
);
3524 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3528 PRINTER_ACCESS_ADMINISTER
,
3531 if (!NT_STATUS_IS_OK(status
)) {
3532 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3535 if (!W_ERROR_IS_OK(werr
)) {
3536 errcode
= W_ERROR_V(werr
);
3541 case 74: /* Pause queue */
3542 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3544 case 75: /* Resume queue */
3545 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3547 case 103: /* Purge */
3548 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3551 werr
= WERR_NOT_SUPPORTED
;
3555 if (!W_ERROR_IS_OK(werr
)) {
3556 errcode
= W_ERROR_V(werr
);
3560 ZERO_STRUCT(info_ctr
);
3561 ZERO_STRUCT(secdesc_ctr
);
3563 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3570 if (!NT_STATUS_IS_OK(status
)) {
3571 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3574 if (!W_ERROR_IS_OK(werr
)) {
3575 errcode
= W_ERROR_V(werr
);
3579 errcode
= W_ERROR_V(werr
);
3583 if (b
&& is_valid_policy_hnd(&handle
)) {
3584 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3587 SSVAL(*rparam
,0,errcode
);
3588 SSVAL(*rparam
,2,0); /* converter word */
3593 /****************************************************************************
3594 set the property of a print job (undocumented?)
3595 ? function = 0xb -> set name of print job
3596 ? function = 0x6 -> move print job up/down
3597 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3598 or <WWsTP> <WB21BB16B10zWWzDDz>
3599 ****************************************************************************/
3601 static int check_printjob_info(struct pack_desc
* desc
,
3602 int uLevel
, char* id
)
3604 desc
->subformat
= NULL
;
3606 case 0: desc
->format
= "W"; break;
3607 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3608 case 2: desc
->format
= "WWzWWDDzz"; break;
3609 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3610 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3612 DEBUG(0,("check_printjob_info: invalid level %d\n",
3616 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3617 DEBUG(0,("check_printjob_info: invalid format %s\n",
3618 id
? id
: "<NULL>" ));
3624 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3625 connection_struct
*conn
, uint64_t vuid
,
3626 char *param
, int tpscnt
,
3627 char *data
, int tdscnt
,
3628 int mdrcnt
,int mprcnt
,
3629 char **rdata
,char **rparam
,
3630 int *rdata_len
,int *rparam_len
)
3632 struct pack_desc desc
;
3633 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3634 char *str2
= skip_string(param
,tpscnt
,str1
);
3635 char *p
= skip_string(param
,tpscnt
,str2
);
3638 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3639 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3642 TALLOC_CTX
*mem_ctx
= talloc_tos();
3645 struct rpc_pipe_client
*cli
= NULL
;
3646 struct dcerpc_binding_handle
*b
= NULL
;
3647 struct policy_handle handle
;
3648 struct spoolss_DevmodeContainer devmode_ctr
;
3649 struct spoolss_JobInfoContainer ctr
;
3650 union spoolss_JobInfo info
;
3651 struct spoolss_SetJobInfo1 info1
;
3653 if (!str1
|| !str2
|| !p
) {
3657 * We use 1 here not 2 as we're checking
3658 * the last byte we want to access is safe.
3660 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3663 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3666 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3673 /* check it's a supported varient */
3674 if ((strcmp(str1
,"WWsTP")) ||
3675 (!check_printjob_info(&desc
,uLevel
,str2
)))
3678 errcode
= NERR_notsupported
;
3682 /* change print job name, data gives the name */
3688 ZERO_STRUCT(handle
);
3690 status
= rpc_pipe_open_interface(conn
,
3691 &ndr_table_spoolss
.syntax_id
,
3693 conn
->sconn
->remote_address
,
3694 conn
->sconn
->msg_ctx
,
3696 if (!NT_STATUS_IS_OK(status
)) {
3697 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3698 nt_errstr(status
)));
3699 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3702 b
= cli
->binding_handle
;
3704 ZERO_STRUCT(devmode_ctr
);
3706 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3713 if (!NT_STATUS_IS_OK(status
)) {
3714 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3717 if (!W_ERROR_IS_OK(werr
)) {
3718 errcode
= W_ERROR_V(werr
);
3722 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3728 if (!W_ERROR_IS_OK(werr
)) {
3729 errcode
= W_ERROR_V(werr
);
3735 info1
.job_id
= info
.info1
.job_id
;
3736 info1
.printer_name
= info
.info1
.printer_name
;
3737 info1
.user_name
= info
.info1
.user_name
;
3738 info1
.document_name
= data
;
3739 info1
.data_type
= info
.info1
.data_type
;
3740 info1
.text_status
= info
.info1
.text_status
;
3741 info1
.status
= info
.info1
.status
;
3742 info1
.priority
= info
.info1
.priority
;
3743 info1
.position
= info
.info1
.position
;
3744 info1
.total_pages
= info
.info1
.total_pages
;
3745 info1
.pages_printed
= info
.info1
.pages_printed
;
3746 info1
.submitted
= info
.info1
.submitted
;
3749 ctr
.info
.info1
= &info1
;
3751 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3757 if (!NT_STATUS_IS_OK(status
)) {
3758 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3761 if (!W_ERROR_IS_OK(werr
)) {
3762 errcode
= W_ERROR_V(werr
);
3766 errcode
= NERR_Success
;
3769 if (b
&& is_valid_policy_hnd(&handle
)) {
3770 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3773 SSVALS(*rparam
,0,errcode
);
3774 SSVAL(*rparam
,2,0); /* converter word */
3780 /****************************************************************************
3781 Get info about the server.
3782 ****************************************************************************/
3784 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3785 connection_struct
*conn
,uint64_t vuid
,
3786 char *param
, int tpscnt
,
3787 char *data
, int tdscnt
,
3788 int mdrcnt
,int mprcnt
,
3789 char **rdata
,char **rparam
,
3790 int *rdata_len
,int *rparam_len
)
3792 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3793 char *str2
= skip_string(param
,tpscnt
,str1
);
3794 char *p
= skip_string(param
,tpscnt
,str2
);
3795 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3801 TALLOC_CTX
*mem_ctx
= talloc_tos();
3802 struct rpc_pipe_client
*cli
= NULL
;
3803 union srvsvc_NetSrvInfo info
;
3805 struct dcerpc_binding_handle
*b
;
3807 if (!str1
|| !str2
|| !p
) {
3811 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3813 /* check it's a supported varient */
3814 if (!prefix_ok(str1
,"WrLh")) {
3820 if (strcmp(str2
,"B16") != 0) {
3826 if (strcmp(str2
,"B16BBDz") != 0) {
3832 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3838 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3844 if (strcmp(str2
,"DN") != 0) {
3850 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3859 *rdata_len
= mdrcnt
;
3860 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3866 p2
= p
+ struct_len
;
3868 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3870 conn
->sconn
->remote_address
,
3871 conn
->sconn
->msg_ctx
,
3873 if (!NT_STATUS_IS_OK(status
)) {
3874 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3875 nt_errstr(status
)));
3876 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3880 b
= cli
->binding_handle
;
3882 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3887 if (!NT_STATUS_IS_OK(status
)) {
3888 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3891 if (!W_ERROR_IS_OK(werr
)) {
3892 errcode
= W_ERROR_V(werr
);
3896 if (info
.info101
== NULL
) {
3897 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3902 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3903 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3907 SCVAL(p
,0,info
.info101
->version_major
);
3908 SCVAL(p
,1,info
.info101
->version_minor
);
3909 SIVAL(p
,2,info
.info101
->server_type
);
3911 if (mdrcnt
== struct_len
) {
3914 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3915 if (mdrcnt
- struct_len
<= 0) {
3919 info
.info101
->comment
,
3920 MIN(mdrcnt
- struct_len
,
3921 MAX_SERVER_STRING_LENGTH
),
3923 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3931 return False
; /* not yet implemented */
3934 errcode
= NERR_Success
;
3938 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3941 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3945 SSVAL(*rparam
,0,errcode
);
3946 SSVAL(*rparam
,2,0); /* converter word */
3947 SSVAL(*rparam
,4,*rdata_len
);
3952 /****************************************************************************
3953 Get info about the server.
3954 ****************************************************************************/
3956 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3957 connection_struct
*conn
,uint64_t vuid
,
3958 char *param
, int tpscnt
,
3959 char *data
, int tdscnt
,
3960 int mdrcnt
,int mprcnt
,
3961 char **rdata
,char **rparam
,
3962 int *rdata_len
,int *rparam_len
)
3964 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3965 char *str2
= skip_string(param
,tpscnt
,str1
);
3966 char *p
= skip_string(param
,tpscnt
,str2
);
3969 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3971 if (!str1
|| !str2
|| !p
) {
3975 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3978 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3983 /* check it's a supported varient */
3984 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3988 *rdata_len
= mdrcnt
+ 1024;
3989 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3994 SSVAL(*rparam
,0,NERR_Success
);
3995 SSVAL(*rparam
,2,0); /* converter word */
3998 endp
= *rdata
+ *rdata_len
;
4000 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
4005 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
4006 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
4007 if (!strupper_m(p2
)) {
4010 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4016 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
4017 strlcpy(p2
,conn
->session_info
->unix_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
4018 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4024 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
4025 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
4026 if (!strupper_m(p2
)) {
4029 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4035 SCVAL(p
,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g 4 in 4.1 */
4036 SCVAL(p
,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g .1 in 4.1 */
4039 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
4040 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
4041 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4047 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
4048 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4049 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4055 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4057 SSVAL(*rparam
,4,*rdata_len
);
4062 /****************************************************************************
4063 get info about a user
4065 struct user_info_11 {
4066 char usri11_name[21]; 0-20
4068 char *usri11_comment; 22-25
4069 char *usri11_usr_comment; 26-29
4070 unsigned short usri11_priv; 30-31
4071 unsigned long usri11_auth_flags; 32-35
4072 long usri11_password_age; 36-39
4073 char *usri11_homedir; 40-43
4074 char *usri11_parms; 44-47
4075 long usri11_last_logon; 48-51
4076 long usri11_last_logoff; 52-55
4077 unsigned short usri11_bad_pw_count; 56-57
4078 unsigned short usri11_num_logons; 58-59
4079 char *usri11_logon_server; 60-63
4080 unsigned short usri11_country_code; 64-65
4081 char *usri11_workstations; 66-69
4082 unsigned long usri11_max_storage; 70-73
4083 unsigned short usri11_units_per_week; 74-75
4084 unsigned char *usri11_logon_hours; 76-79
4085 unsigned short usri11_code_page; 80-81
4090 usri11_name specifies the user name for which information is retrieved
4092 usri11_pad aligns the next data structure element to a word boundary
4094 usri11_comment is a null terminated ASCII comment
4096 usri11_user_comment is a null terminated ASCII comment about the user
4098 usri11_priv specifies the level of the privilege assigned to the user.
4099 The possible values are:
4101 Name Value Description
4102 USER_PRIV_GUEST 0 Guest privilege
4103 USER_PRIV_USER 1 User privilege
4104 USER_PRV_ADMIN 2 Administrator privilege
4106 usri11_auth_flags specifies the account operator privileges. The
4107 possible values are:
4109 Name Value Description
4110 AF_OP_PRINT 0 Print operator
4113 Leach, Naik [Page 28]
4117 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4120 AF_OP_COMM 1 Communications operator
4121 AF_OP_SERVER 2 Server operator
4122 AF_OP_ACCOUNTS 3 Accounts operator
4125 usri11_password_age specifies how many seconds have elapsed since the
4126 password was last changed.
4128 usri11_home_dir points to a null terminated ASCII string that contains
4129 the path name of the user's home directory.
4131 usri11_parms points to a null terminated ASCII string that is set
4132 aside for use by applications.
4134 usri11_last_logon specifies the time when the user last logged on.
4135 This value is stored as the number of seconds elapsed since
4136 00:00:00, January 1, 1970.
4138 usri11_last_logoff specifies the time when the user last logged off.
4139 This value is stored as the number of seconds elapsed since
4140 00:00:00, January 1, 1970. A value of 0 means the last logoff
4143 usri11_bad_pw_count specifies the number of incorrect passwords
4144 entered since the last successful logon.
4146 usri11_log1_num_logons specifies the number of times this user has
4147 logged on. A value of -1 means the number of logons is unknown.
4149 usri11_logon_server points to a null terminated ASCII string that
4150 contains the name of the server to which logon requests are sent.
4151 A null string indicates logon requests should be sent to the
4154 usri11_country_code specifies the country code for the user's language
4157 usri11_workstations points to a null terminated ASCII string that
4158 contains the names of workstations the user may log on from.
4159 There may be up to 8 workstations, with the names separated by
4160 commas. A null strings indicates there are no restrictions.
4162 usri11_max_storage specifies the maximum amount of disk space the user
4163 can occupy. A value of 0xffffffff indicates there are no
4166 usri11_units_per_week specifies the equal number of time units into
4167 which a week is divided. This value must be equal to 168.
4169 usri11_logon_hours points to a 21 byte (168 bits) string that
4170 specifies the time during which the user can log on. Each bit
4171 represents one unique hour in a week. The first bit (bit 0, word
4172 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4176 Leach, Naik [Page 29]
4180 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4183 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4184 are no restrictions.
4186 usri11_code_page specifies the code page for the user's language of
4189 All of the pointers in this data structure need to be treated
4190 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4191 to be ignored. The converter word returned in the parameters section
4192 needs to be subtracted from the lower 16 bits to calculate an offset
4193 into the return buffer where this ASCII string resides.
4195 There is no auxiliary data in the response.
4197 ****************************************************************************/
4199 #define usri11_name 0
4200 #define usri11_pad 21
4201 #define usri11_comment 22
4202 #define usri11_usr_comment 26
4203 #define usri11_full_name 30
4204 #define usri11_priv 34
4205 #define usri11_auth_flags 36
4206 #define usri11_password_age 40
4207 #define usri11_homedir 44
4208 #define usri11_parms 48
4209 #define usri11_last_logon 52
4210 #define usri11_last_logoff 56
4211 #define usri11_bad_pw_count 60
4212 #define usri11_num_logons 62
4213 #define usri11_logon_server 64
4214 #define usri11_country_code 68
4215 #define usri11_workstations 70
4216 #define usri11_max_storage 74
4217 #define usri11_units_per_week 78
4218 #define usri11_logon_hours 80
4219 #define usri11_code_page 84
4220 #define usri11_end 86
4222 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4223 connection_struct
*conn
, uint64_t vuid
,
4224 char *param
, int tpscnt
,
4225 char *data
, int tdscnt
,
4226 int mdrcnt
,int mprcnt
,
4227 char **rdata
,char **rparam
,
4228 int *rdata_len
,int *rparam_len
)
4230 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4231 char *str2
= skip_string(param
,tpscnt
,str1
);
4232 char *UserName
= skip_string(param
,tpscnt
,str2
);
4233 char *p
= skip_string(param
,tpscnt
,UserName
);
4234 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4237 const char *level_string
;
4239 TALLOC_CTX
*mem_ctx
= talloc_tos();
4240 NTSTATUS status
, result
;
4241 struct rpc_pipe_client
*cli
= NULL
;
4242 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4243 struct lsa_String domain_name
;
4244 struct dom_sid2
*domain_sid
;
4245 struct lsa_String names
;
4246 struct samr_Ids rids
;
4247 struct samr_Ids types
;
4248 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4250 union samr_UserInfo
*info
;
4251 struct dcerpc_binding_handle
*b
= NULL
;
4253 if (!str1
|| !str2
|| !UserName
|| !p
) {
4258 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4263 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4265 /* check it's a supported variant */
4266 if (strcmp(str1
,"zWrLh") != 0) {
4270 case 0: level_string
= "B21"; break;
4271 case 1: level_string
= "B21BB16DWzzWz"; break;
4272 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4273 case 10: level_string
= "B21Bzzz"; break;
4274 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4275 default: return False
;
4278 if (strcmp(level_string
,str2
) != 0) {
4282 *rdata_len
= mdrcnt
+ 1024;
4283 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4289 endp
= *rdata
+ *rdata_len
;
4290 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4295 ZERO_STRUCT(connect_handle
);
4296 ZERO_STRUCT(domain_handle
);
4297 ZERO_STRUCT(user_handle
);
4299 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
.syntax_id
,
4301 conn
->sconn
->remote_address
,
4302 conn
->sconn
->msg_ctx
,
4304 if (!NT_STATUS_IS_OK(status
)) {
4305 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4306 nt_errstr(status
)));
4307 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4311 b
= cli
->binding_handle
;
4313 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4315 SAMR_ACCESS_CONNECT_TO_SERVER
|
4316 SAMR_ACCESS_ENUM_DOMAINS
|
4317 SAMR_ACCESS_LOOKUP_DOMAIN
,
4320 if (!NT_STATUS_IS_OK(status
)) {
4321 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4324 if (!NT_STATUS_IS_OK(result
)) {
4325 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4329 init_lsa_String(&domain_name
, get_global_sam_name());
4331 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4336 if (!NT_STATUS_IS_OK(status
)) {
4337 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4340 if (!NT_STATUS_IS_OK(result
)) {
4341 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4345 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4347 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4351 if (!NT_STATUS_IS_OK(status
)) {
4352 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4355 if (!NT_STATUS_IS_OK(result
)) {
4356 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4360 init_lsa_String(&names
, UserName
);
4362 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4369 if (!NT_STATUS_IS_OK(status
)) {
4370 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4373 if (!NT_STATUS_IS_OK(result
)) {
4374 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4378 if (rids
.count
!= 1) {
4379 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4382 if (rids
.count
!= types
.count
) {
4383 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4386 if (types
.ids
[0] != SID_NAME_USER
) {
4387 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4393 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4395 SAMR_USER_ACCESS_GET_LOCALE
|
4396 SAMR_USER_ACCESS_GET_LOGONINFO
|
4397 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4398 SAMR_USER_ACCESS_GET_GROUPS
|
4399 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4400 SEC_STD_READ_CONTROL
,
4404 if (!NT_STATUS_IS_OK(status
)) {
4405 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4408 if (!NT_STATUS_IS_OK(result
)) {
4409 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4413 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4418 if (!NT_STATUS_IS_OK(status
)) {
4419 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4422 if (!NT_STATUS_IS_OK(result
)) {
4423 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4428 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4431 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4436 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4437 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4438 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4443 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4444 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4445 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4450 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4451 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4452 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4453 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4460 const char *homedir
= info
->info21
.home_directory
.string
;
4461 /* modelled after NTAS 3.51 reply */
4462 SSVAL(p
,usri11_priv
,
4463 (get_current_uid(conn
) == sec_initial_uid())?
4464 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4465 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4466 SIVALS(p
,usri11_password_age
,-1); /* password age */
4467 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4468 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4469 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4473 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4474 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4475 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4479 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4480 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4481 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4482 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4483 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4484 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4485 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4489 SSVAL(p
,usri11_country_code
,0); /* country code */
4491 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4492 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4493 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4498 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4499 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4500 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4502 /* a simple way to get logon hours at all times. */
4504 SCVAL(p2
,21,0); /* fix zero termination */
4505 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4510 SSVAL(p
,usri11_code_page
,0); /* code page */
4513 if (uLevel
== 1 || uLevel
== 2) {
4514 memset(p
+22,' ',16); /* password */
4515 SIVALS(p
,38,-1); /* password age */
4517 (get_current_uid(conn
) == sec_initial_uid())?
4518 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4519 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4520 strlcpy(p2
, info
->info21
.home_directory
.string
,
4522 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4526 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4528 SSVAL(p
,52,0); /* flags */
4529 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4530 strlcpy(p2
, info
->info21
.logon_script
.string
,
4532 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4537 SIVAL(p
,58,0); /* auth_flags */
4538 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4539 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4540 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4544 SIVAL(p
,66,0); /* urs_comment */
4545 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4546 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4547 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4551 SIVAL(p
,74,0); /* workstations */
4552 SIVAL(p
,78,0); /* last_logon */
4553 SIVAL(p
,82,0); /* last_logoff */
4554 SIVALS(p
,86,-1); /* acct_expires */
4555 SIVALS(p
,90,-1); /* max_storage */
4556 SSVAL(p
,94,168); /* units_per_week */
4557 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4560 SSVALS(p
,100,-1); /* bad_pw_count */
4561 SSVALS(p
,102,-1); /* num_logons */
4562 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4564 TALLOC_CTX
*ctx
= talloc_tos();
4565 int space_rem
= *rdata_len
- (p2
- *rdata
);
4568 if (space_rem
<= 0) {
4571 tmp
= talloc_strdup(ctx
, "\\\\%L");
4575 tmp
= talloc_sub_basic(ctx
,
4588 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4592 SSVAL(p
,108,49); /* country_code */
4593 SSVAL(p
,110,860); /* code page */
4597 errcode
= NERR_Success
;
4600 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4602 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4603 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4605 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4606 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4608 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4609 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4612 SSVAL(*rparam
,0,errcode
);
4613 SSVAL(*rparam
,2,0); /* converter word */
4614 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4619 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4620 connection_struct
*conn
,uint64_t vuid
,
4621 char *param
, int tpscnt
,
4622 char *data
, int tdscnt
,
4623 int mdrcnt
,int mprcnt
,
4624 char **rdata
,char **rparam
,
4625 int *rdata_len
,int *rparam_len
)
4627 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4628 char *str2
= skip_string(param
,tpscnt
,str1
);
4629 char *p
= skip_string(param
,tpscnt
,str2
);
4631 struct pack_desc desc
;
4633 /* With share level security vuid will always be zero.
4634 Don't depend on vuser being non-null !!. JRA */
4635 struct user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4637 if (!str1
|| !str2
|| !p
) {
4642 DEBUG(3,(" Username of UID %d is %s\n",
4643 (int)vuser
->session_info
->unix_token
->uid
,
4644 vuser
->session_info
->unix_info
->unix_name
));
4647 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4648 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4653 memset((char *)&desc
,'\0',sizeof(desc
));
4655 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4657 /* check it's a supported varient */
4658 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4661 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4665 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4672 desc
.buflen
= mdrcnt
;
4673 desc
.subformat
= NULL
;
4676 if (init_package(&desc
,1,0)) {
4677 PACKI(&desc
,"W",0); /* code */
4678 PACKS(&desc
,"B21",name
); /* eff. name */
4679 PACKS(&desc
,"B",""); /* pad */
4681 (get_current_uid(conn
) == sec_initial_uid())?
4682 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4683 PACKI(&desc
,"D",0); /* auth flags XXX */
4684 PACKI(&desc
,"W",0); /* num logons */
4685 PACKI(&desc
,"W",0); /* bad pw count */
4686 PACKI(&desc
,"D",0); /* last logon */
4687 PACKI(&desc
,"D",-1); /* last logoff */
4688 PACKI(&desc
,"D",-1); /* logoff time */
4689 PACKI(&desc
,"D",-1); /* kickoff time */
4690 PACKI(&desc
,"D",0); /* password age */
4691 PACKI(&desc
,"D",0); /* password can change */
4692 PACKI(&desc
,"D",-1); /* password must change */
4696 fstrcpy(mypath
,"\\\\");
4697 fstrcat(mypath
,get_local_machine_name());
4698 if (!strupper_m(mypath
)) {
4701 PACKS(&desc
,"z",mypath
); /* computer */
4704 PACKS(&desc
,"z",lp_workgroup());/* domain */
4705 PACKS(&desc
,"z", vuser
?
4706 vuser
->session_info
->info
->logon_script
4707 : ""); /* script path */
4708 PACKI(&desc
,"D",0x00000000); /* reserved */
4711 *rdata_len
= desc
.usedlen
;
4713 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4717 SSVALS(*rparam
,0,desc
.errcode
);
4719 SSVAL(*rparam
,4,desc
.neededlen
);
4721 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4726 /****************************************************************************
4727 api_WAccessGetUserPerms
4728 ****************************************************************************/
4730 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4731 connection_struct
*conn
,uint64_t vuid
,
4732 char *param
, int tpscnt
,
4733 char *data
, int tdscnt
,
4734 int mdrcnt
,int mprcnt
,
4735 char **rdata
,char **rparam
,
4736 int *rdata_len
,int *rparam_len
)
4738 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4739 char *str2
= skip_string(param
,tpscnt
,str1
);
4740 char *user
= skip_string(param
,tpscnt
,str2
);
4741 char *resource
= skip_string(param
,tpscnt
,user
);
4743 if (!str1
|| !str2
|| !user
|| !resource
) {
4747 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4750 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4752 /* check it's a supported varient */
4753 if (strcmp(str1
,"zzh") != 0) {
4756 if (strcmp(str2
,"") != 0) {
4761 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4765 SSVALS(*rparam
,0,0); /* errorcode */
4766 SSVAL(*rparam
,2,0); /* converter word */
4767 SSVAL(*rparam
,4,0x7f); /* permission flags */
4772 /****************************************************************************
4773 api_WPrintJobEnumerate
4774 ****************************************************************************/
4776 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4777 connection_struct
*conn
, uint64_t vuid
,
4778 char *param
, int tpscnt
,
4779 char *data
, int tdscnt
,
4780 int mdrcnt
,int mprcnt
,
4781 char **rdata
,char **rparam
,
4782 int *rdata_len
,int *rparam_len
)
4784 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4785 char *str2
= skip_string(param
,tpscnt
,str1
);
4786 char *p
= skip_string(param
,tpscnt
,str2
);
4790 struct pack_desc desc
;
4793 TALLOC_CTX
*mem_ctx
= talloc_tos();
4796 struct rpc_pipe_client
*cli
= NULL
;
4797 struct dcerpc_binding_handle
*b
= NULL
;
4798 struct policy_handle handle
;
4799 struct spoolss_DevmodeContainer devmode_ctr
;
4800 union spoolss_JobInfo info
;
4802 if (!str1
|| !str2
|| !p
) {
4806 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4808 memset((char *)&desc
,'\0',sizeof(desc
));
4809 memset((char *)&status
,'\0',sizeof(status
));
4811 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4813 /* check it's a supported varient */
4814 if (strcmp(str1
,"WWrLh") != 0) {
4817 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4821 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4825 ZERO_STRUCT(handle
);
4827 status
= rpc_pipe_open_interface(conn
,
4828 &ndr_table_spoolss
.syntax_id
,
4830 conn
->sconn
->remote_address
,
4831 conn
->sconn
->msg_ctx
,
4833 if (!NT_STATUS_IS_OK(status
)) {
4834 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4835 nt_errstr(status
)));
4836 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4839 b
= cli
->binding_handle
;
4841 ZERO_STRUCT(devmode_ctr
);
4843 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4850 if (!NT_STATUS_IS_OK(status
)) {
4851 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4854 if (!W_ERROR_IS_OK(werr
)) {
4855 desc
.errcode
= W_ERROR_V(werr
);
4859 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4865 if (!W_ERROR_IS_OK(werr
)) {
4866 desc
.errcode
= W_ERROR_V(werr
);
4871 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4876 desc
.buflen
= mdrcnt
;
4879 * Don't return data but need to get correct length
4880 * init_package will return wrong size if buflen=0
4882 desc
.buflen
= getlen(desc
.format
);
4883 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4886 if (init_package(&desc
,1,0)) {
4887 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4888 *rdata_len
= desc
.usedlen
;
4890 desc
.errcode
= NERR_JobNotFound
;
4894 if (b
&& is_valid_policy_hnd(&handle
)) {
4895 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4899 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4903 SSVALS(*rparam
,0,desc
.errcode
);
4905 SSVAL(*rparam
,4,desc
.neededlen
);
4909 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4914 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4915 connection_struct
*conn
, uint64_t vuid
,
4916 char *param
, int tpscnt
,
4917 char *data
, int tdscnt
,
4918 int mdrcnt
,int mprcnt
,
4919 char **rdata
,char **rparam
,
4920 int *rdata_len
,int *rparam_len
)
4922 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4923 char *str2
= skip_string(param
,tpscnt
,str1
);
4924 char *p
= skip_string(param
,tpscnt
,str2
);
4928 struct pack_desc desc
;
4930 TALLOC_CTX
*mem_ctx
= talloc_tos();
4933 struct rpc_pipe_client
*cli
= NULL
;
4934 struct dcerpc_binding_handle
*b
= NULL
;
4935 struct policy_handle handle
;
4936 struct spoolss_DevmodeContainer devmode_ctr
;
4938 union spoolss_JobInfo
*info
;
4940 if (!str1
|| !str2
|| !p
) {
4944 memset((char *)&desc
,'\0',sizeof(desc
));
4946 p
= skip_string(param
,tpscnt
,p
);
4950 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4952 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4954 /* check it's a supported variant */
4955 if (strcmp(str1
,"zWrLeh") != 0) {
4960 return False
; /* defined only for uLevel 0,1,2 */
4963 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4967 ZERO_STRUCT(handle
);
4969 status
= rpc_pipe_open_interface(conn
,
4970 &ndr_table_spoolss
.syntax_id
,
4972 conn
->sconn
->remote_address
,
4973 conn
->sconn
->msg_ctx
,
4975 if (!NT_STATUS_IS_OK(status
)) {
4976 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4977 nt_errstr(status
)));
4978 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4981 b
= cli
->binding_handle
;
4983 ZERO_STRUCT(devmode_ctr
);
4985 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4992 if (!NT_STATUS_IS_OK(status
)) {
4993 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4996 if (!W_ERROR_IS_OK(werr
)) {
4997 desc
.errcode
= W_ERROR_V(werr
);
5001 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5009 if (!W_ERROR_IS_OK(werr
)) {
5010 desc
.errcode
= W_ERROR_V(werr
);
5015 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5021 desc
.buflen
= mdrcnt
;
5023 if (init_package(&desc
,count
,0)) {
5025 for (i
= 0; i
< count
; i
++) {
5026 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
5027 if (desc
.errcode
== NERR_Success
) {
5033 if (b
&& is_valid_policy_hnd(&handle
)) {
5034 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5037 *rdata_len
= desc
.usedlen
;
5040 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5044 SSVALS(*rparam
,0,desc
.errcode
);
5046 SSVAL(*rparam
,4,succnt
);
5047 SSVAL(*rparam
,6,count
);
5049 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
5054 static int check_printdest_info(struct pack_desc
* desc
,
5055 int uLevel
, char* id
)
5057 desc
->subformat
= NULL
;
5060 desc
->format
= "B9";
5063 desc
->format
= "B9B21WWzW";
5069 desc
->format
= "zzzWWzzzWW";
5072 DEBUG(0,("check_printdest_info: invalid level %d\n",
5076 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
5077 DEBUG(0,("check_printdest_info: invalid string %s\n",
5078 id
? id
: "<NULL>" ));
5084 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
5085 struct pack_desc
* desc
)
5089 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
5090 buf
[sizeof(buf
)-1] = 0;
5091 (void)strupper_m(buf
);
5094 PACKS(desc
,"B9",buf
); /* szName */
5096 PACKS(desc
,"B21",""); /* szUserName */
5097 PACKI(desc
,"W",0); /* uJobId */
5098 PACKI(desc
,"W",0); /* fsStatus */
5099 PACKS(desc
,"z",""); /* pszStatus */
5100 PACKI(desc
,"W",0); /* time */
5104 if (uLevel
== 2 || uLevel
== 3) {
5105 PACKS(desc
,"z",buf
); /* pszPrinterName */
5107 PACKS(desc
,"z",""); /* pszUserName */
5108 PACKS(desc
,"z",""); /* pszLogAddr */
5109 PACKI(desc
,"W",0); /* uJobId */
5110 PACKI(desc
,"W",0); /* fsStatus */
5111 PACKS(desc
,"z",""); /* pszStatus */
5112 PACKS(desc
,"z",""); /* pszComment */
5113 PACKS(desc
,"z","NULL"); /* pszDrivers */
5114 PACKI(desc
,"W",0); /* time */
5115 PACKI(desc
,"W",0); /* pad1 */
5120 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
5121 connection_struct
*conn
, uint64_t vuid
,
5122 char *param
, int tpscnt
,
5123 char *data
, int tdscnt
,
5124 int mdrcnt
,int mprcnt
,
5125 char **rdata
,char **rparam
,
5126 int *rdata_len
,int *rparam_len
)
5128 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5129 char *str2
= skip_string(param
,tpscnt
,str1
);
5130 char *p
= skip_string(param
,tpscnt
,str2
);
5131 char* PrinterName
= p
;
5133 struct pack_desc desc
;
5136 TALLOC_CTX
*mem_ctx
= talloc_tos();
5139 struct rpc_pipe_client
*cli
= NULL
;
5140 struct dcerpc_binding_handle
*b
= NULL
;
5141 struct policy_handle handle
;
5142 struct spoolss_DevmodeContainer devmode_ctr
;
5143 union spoolss_PrinterInfo info
;
5145 if (!str1
|| !str2
|| !p
) {
5149 memset((char *)&desc
,'\0',sizeof(desc
));
5151 p
= skip_string(param
,tpscnt
,p
);
5155 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5157 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
5159 /* check it's a supported varient */
5160 if (strcmp(str1
,"zWrLh") != 0) {
5163 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5167 ZERO_STRUCT(handle
);
5169 status
= rpc_pipe_open_interface(conn
,
5170 &ndr_table_spoolss
.syntax_id
,
5172 conn
->sconn
->remote_address
,
5173 conn
->sconn
->msg_ctx
,
5175 if (!NT_STATUS_IS_OK(status
)) {
5176 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5177 nt_errstr(status
)));
5178 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5181 b
= cli
->binding_handle
;
5183 ZERO_STRUCT(devmode_ctr
);
5185 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5192 if (!NT_STATUS_IS_OK(status
)) {
5194 desc
.errcode
= NERR_DestNotFound
;
5198 if (!W_ERROR_IS_OK(werr
)) {
5200 desc
.errcode
= NERR_DestNotFound
;
5205 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5210 if (!W_ERROR_IS_OK(werr
)) {
5212 desc
.errcode
= NERR_DestNotFound
;
5218 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5223 desc
.buflen
= mdrcnt
;
5226 * Don't return data but need to get correct length
5227 * init_package will return wrong size if buflen=0
5229 desc
.buflen
= getlen(desc
.format
);
5230 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5232 if (init_package(&desc
,1,0)) {
5233 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5237 if (b
&& is_valid_policy_hnd(&handle
)) {
5238 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5241 *rdata_len
= desc
.usedlen
;
5244 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5248 SSVALS(*rparam
,0,desc
.errcode
);
5250 SSVAL(*rparam
,4,desc
.neededlen
);
5252 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5258 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5259 connection_struct
*conn
, uint64_t vuid
,
5260 char *param
, int tpscnt
,
5261 char *data
, int tdscnt
,
5262 int mdrcnt
,int mprcnt
,
5263 char **rdata
,char **rparam
,
5264 int *rdata_len
,int *rparam_len
)
5266 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5267 char *str2
= skip_string(param
,tpscnt
,str1
);
5268 char *p
= skip_string(param
,tpscnt
,str2
);
5272 struct pack_desc desc
;
5274 TALLOC_CTX
*mem_ctx
= talloc_tos();
5277 struct rpc_pipe_client
*cli
= NULL
;
5278 union spoolss_PrinterInfo
*info
;
5281 if (!str1
|| !str2
|| !p
) {
5285 memset((char *)&desc
,'\0',sizeof(desc
));
5287 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5289 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5291 /* check it's a supported varient */
5292 if (strcmp(str1
,"WrLeh") != 0) {
5295 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5301 status
= rpc_pipe_open_interface(conn
,
5302 &ndr_table_spoolss
.syntax_id
,
5304 conn
->sconn
->remote_address
,
5305 conn
->sconn
->msg_ctx
,
5307 if (!NT_STATUS_IS_OK(status
)) {
5308 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5309 nt_errstr(status
)));
5310 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5314 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5316 cli
->srv_name_slash
,
5321 if (!W_ERROR_IS_OK(werr
)) {
5322 desc
.errcode
= W_ERROR_V(werr
);
5324 desc
.errcode
= NERR_DestNotFound
;
5332 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5339 desc
.buflen
= mdrcnt
;
5340 if (init_package(&desc
,queuecnt
,0)) {
5343 for (i
= 0; i
< count
; i
++) {
5344 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5346 if (desc
.errcode
== NERR_Success
) {
5352 *rdata_len
= desc
.usedlen
;
5355 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5359 SSVALS(*rparam
,0,desc
.errcode
);
5361 SSVAL(*rparam
,4,succnt
);
5362 SSVAL(*rparam
,6,queuecnt
);
5364 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5369 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5370 connection_struct
*conn
, uint64_t vuid
,
5371 char *param
, int tpscnt
,
5372 char *data
, int tdscnt
,
5373 int mdrcnt
,int mprcnt
,
5374 char **rdata
,char **rparam
,
5375 int *rdata_len
,int *rparam_len
)
5377 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5378 char *str2
= skip_string(param
,tpscnt
,str1
);
5379 char *p
= skip_string(param
,tpscnt
,str2
);
5382 struct pack_desc desc
;
5384 if (!str1
|| !str2
|| !p
) {
5388 memset((char *)&desc
,'\0',sizeof(desc
));
5390 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5392 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5394 /* check it's a supported varient */
5395 if (strcmp(str1
,"WrLeh") != 0) {
5398 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5403 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5409 desc
.buflen
= mdrcnt
;
5410 if (init_package(&desc
,1,0)) {
5411 PACKS(&desc
,"B41","NULL");
5414 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5416 *rdata_len
= desc
.usedlen
;
5419 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5423 SSVALS(*rparam
,0,desc
.errcode
);
5425 SSVAL(*rparam
,4,succnt
);
5428 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5433 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5434 connection_struct
*conn
, uint64_t vuid
,
5435 char *param
, int tpscnt
,
5436 char *data
, int tdscnt
,
5437 int mdrcnt
,int mprcnt
,
5438 char **rdata
,char **rparam
,
5439 int *rdata_len
,int *rparam_len
)
5441 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5442 char *str2
= skip_string(param
,tpscnt
,str1
);
5443 char *p
= skip_string(param
,tpscnt
,str2
);
5446 struct pack_desc desc
;
5448 if (!str1
|| !str2
|| !p
) {
5451 memset((char *)&desc
,'\0',sizeof(desc
));
5453 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5455 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5457 /* check it's a supported varient */
5458 if (strcmp(str1
,"WrLeh") != 0) {
5461 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5466 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5472 desc
.buflen
= mdrcnt
;
5474 if (init_package(&desc
,1,0)) {
5475 PACKS(&desc
,"B13","lpd");
5478 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5480 *rdata_len
= desc
.usedlen
;
5483 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5487 SSVALS(*rparam
,0,desc
.errcode
);
5489 SSVAL(*rparam
,4,succnt
);
5492 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5497 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5498 connection_struct
*conn
, uint64_t vuid
,
5499 char *param
, int tpscnt
,
5500 char *data
, int tdscnt
,
5501 int mdrcnt
,int mprcnt
,
5502 char **rdata
,char **rparam
,
5503 int *rdata_len
,int *rparam_len
)
5505 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5506 char *str2
= skip_string(param
,tpscnt
,str1
);
5507 char *p
= skip_string(param
,tpscnt
,str2
);
5510 struct pack_desc desc
;
5512 if (!str1
|| !str2
|| !p
) {
5516 memset((char *)&desc
,'\0',sizeof(desc
));
5518 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5520 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5522 /* check it's a supported varient */
5523 if (strcmp(str1
,"WrLeh") != 0) {
5526 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5531 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5536 memset((char *)&desc
,'\0',sizeof(desc
));
5538 desc
.buflen
= mdrcnt
;
5540 if (init_package(&desc
,1,0)) {
5541 PACKS(&desc
,"B13","lp0");
5544 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5546 *rdata_len
= desc
.usedlen
;
5549 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5553 SSVALS(*rparam
,0,desc
.errcode
);
5555 SSVAL(*rparam
,4,succnt
);
5558 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5563 /****************************************************************************
5565 ****************************************************************************/
5567 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5568 connection_struct
*conn
, uint64_t vuid
,
5569 char *param
, int tpscnt
,
5570 char *data
, int tdscnt
,
5571 int mdrcnt
,int mprcnt
,
5572 char **rdata
,char **rparam
,
5573 int *rdata_len
,int *rparam_len
)
5576 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5577 char *str2
= skip_string(param
,tpscnt
,str1
);
5578 char *p
= skip_string(param
,tpscnt
,str2
);
5580 struct pack_desc desc
;
5583 TALLOC_CTX
*mem_ctx
= talloc_tos();
5586 struct rpc_pipe_client
*cli
= NULL
;
5587 struct dcerpc_binding_handle
*b
= NULL
;
5588 struct srvsvc_NetSessInfoCtr info_ctr
;
5589 uint32_t totalentries
, resume_handle
= 0;
5592 if (!str1
|| !str2
|| !p
) {
5598 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5600 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5601 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5602 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5604 /* check it's a supported varient */
5605 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5608 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5612 status
= rpc_pipe_open_interface(conn
,
5613 &ndr_table_srvsvc
.syntax_id
,
5615 conn
->sconn
->remote_address
,
5616 conn
->sconn
->msg_ctx
,
5618 if (!NT_STATUS_IS_OK(status
)) {
5619 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5620 nt_errstr(status
)));
5621 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5624 b
= cli
->binding_handle
;
5627 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5628 if (info_ctr
.ctr
.ctr1
== NULL
) {
5629 desc
.errcode
= W_ERROR_V(WERR_NOMEM
);
5633 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5634 cli
->srv_name_slash
,
5638 (uint32_t)-1, /* max_buffer */
5642 if (!NT_STATUS_IS_OK(status
)) {
5643 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5644 nt_errstr(status
)));
5645 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5649 if (!W_ERROR_IS_OK(werr
)) {
5650 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5652 desc
.errcode
= W_ERROR_V(werr
);
5656 count
= info_ctr
.ctr
.ctr1
->count
;
5660 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5667 desc
.buflen
= mdrcnt
;
5669 if (!init_package(&desc
, count
,0)) {
5673 for(i
=0; i
< count
; i
++) {
5674 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5675 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5676 PACKI(&desc
, "W", 1); /* num conns */
5677 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5678 PACKI(&desc
, "W", 1); /* num users */
5679 PACKI(&desc
, "D", 0); /* session time */
5680 PACKI(&desc
, "D", 0); /* idle time */
5681 PACKI(&desc
, "D", 0); /* flags */
5682 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5685 *rdata_len
= desc
.usedlen
;
5688 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5692 SSVALS(*rparam
,0,desc
.errcode
);
5693 SSVAL(*rparam
,2,0); /* converter */
5694 SSVAL(*rparam
,4, count
); /* count */
5696 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5702 /****************************************************************************
5703 The buffer was too small.
5704 ****************************************************************************/
5706 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5707 connection_struct
*conn
,uint64_t vuid
, char *param
, char *data
,
5708 int mdrcnt
, int mprcnt
,
5709 char **rdata
, char **rparam
,
5710 int *rdata_len
, int *rparam_len
)
5712 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5713 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5720 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5722 DEBUG(3,("Supplied buffer too small in API command\n"));
5727 /****************************************************************************
5728 The request is not supported.
5729 ****************************************************************************/
5731 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5732 connection_struct
*conn
, uint64_t vuid
,
5733 char *param
, int tpscnt
,
5734 char *data
, int tdscnt
,
5735 int mdrcnt
, int mprcnt
,
5736 char **rdata
, char **rparam
,
5737 int *rdata_len
, int *rparam_len
)
5740 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5747 SSVAL(*rparam
,0,NERR_notsupported
);
5748 SSVAL(*rparam
,2,0); /* converter word */
5750 DEBUG(3,("Unsupported API command\n"));
5755 static const struct {
5758 bool (*fn
)(struct smbd_server_connection
*sconn
,
5759 connection_struct
*, uint64_t,
5762 int,int,char **,char **,int *,int *);
5763 bool auth_user
; /* Deny anonymous access? */
5764 } api_commands
[] = {
5765 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5766 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5767 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5768 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5769 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5770 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5771 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5772 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5773 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5774 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5775 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5776 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5777 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5778 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5779 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5780 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5781 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5782 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5783 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5784 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5785 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5786 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5787 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5788 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5789 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5790 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5791 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5792 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5793 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5794 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5795 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5796 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5797 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5798 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5799 {NULL
, -1, api_Unsupported
}
5800 /* The following RAP calls are not implemented by Samba:
5802 RAP_WFileEnum2 - anon not OK
5807 /****************************************************************************
5808 Handle remote api calls.
5809 ****************************************************************************/
5811 void api_reply(connection_struct
*conn
, uint64_t vuid
,
5812 struct smb_request
*req
,
5813 char *data
, char *params
,
5814 int tdscnt
, int tpscnt
,
5815 int mdrcnt
, int mprcnt
)
5819 char *rparam
= NULL
;
5820 const char *name1
= NULL
;
5821 const char *name2
= NULL
;
5828 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5829 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5834 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5837 api_command
= SVAL(params
,0);
5838 /* Is there a string at position params+2 ? */
5839 if (skip_string(params
,tpscnt
,params
+2)) {
5844 name2
= skip_string(params
,tpscnt
,params
+2);
5849 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5853 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5855 for (i
=0;api_commands
[i
].name
;i
++) {
5856 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5857 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5862 /* Check whether this api call can be done anonymously */
5864 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5865 struct user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5867 if (!user
|| security_session_user_level(user
->session_info
, NULL
) < SECURITY_USER
) {
5868 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5873 rdata
= (char *)SMB_MALLOC(1024);
5875 memset(rdata
,'\0',1024);
5878 rparam
= (char *)SMB_MALLOC(1024);
5880 memset(rparam
,'\0',1024);
5883 if(!rdata
|| !rparam
) {
5884 DEBUG(0,("api_reply: malloc fail !\n"));
5887 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5891 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5893 params
,tpscnt
, /* params + length */
5894 data
,tdscnt
, /* data + length */
5896 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5899 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5900 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5902 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5905 /* if we get False back then it's actually unsupported */
5907 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5909 tdscnt
,mdrcnt
,mprcnt
,
5910 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5913 /* If api_Unsupported returns false we can't return anything. */
5915 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5916 rdata
, rdata_len
, False
);