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"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/printing/rap_jobid.h"
48 #include "source3/lib/substitute.h"
55 #define NERR_Success 0
56 #define NERR_badpass 86
57 #define NERR_notsupported 50
59 #define NERR_BASE (2100)
60 #define NERR_BufTooSmall (NERR_BASE+23)
61 #define NERR_JobNotFound (NERR_BASE+51)
62 #define NERR_DestNotFound (NERR_BASE+52)
64 #define ACCESS_READ 0x01
65 #define ACCESS_WRITE 0x02
66 #define ACCESS_CREATE 0x04
68 #define SHPWLEN 8 /* share password length */
70 /* Limit size of ipc replies */
72 static char *smb_realloc_limit(void *ptr
, size_t size
)
76 size
= MAX((size
),4*1024);
77 val
= (char *)SMB_REALLOC(ptr
,size
);
79 memset(val
,'\0',size
);
84 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
85 connection_struct
*conn
, uint64_t vuid
,
86 char *param
, int tpscnt
,
87 char *data
, int tdscnt
,
88 int mdrcnt
, int mprcnt
,
89 char **rdata
, char **rparam
,
90 int *rdata_len
, int *rparam_len
);
92 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
93 connection_struct
*conn
, uint64_t vuid
, char *param
, char *data
,
94 int mdrcnt
, int mprcnt
,
95 char **rdata
, char **rparam
,
96 int *rdata_len
, int *rparam_len
);
99 static int CopyExpanded(connection_struct
*conn
,
100 int snum
, char **dst
, char *src
, int *p_space_remaining
)
102 TALLOC_CTX
*ctx
= talloc_tos();
103 const struct loadparm_substitution
*lp_sub
=
104 loadparm_s3_global_substitution();
108 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
109 *p_space_remaining
<= 0) {
113 buf
= talloc_strdup(ctx
, src
);
115 *p_space_remaining
= 0;
118 buf
= talloc_string_sub(ctx
, buf
,"%S", lp_servicename(ctx
, lp_sub
, snum
));
120 *p_space_remaining
= 0;
123 buf
= talloc_sub_full(ctx
,
124 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
125 conn
->session_info
->unix_info
->unix_name
,
127 conn
->session_info
->unix_token
->gid
,
128 conn
->session_info
->unix_info
->sanitized_username
,
129 conn
->session_info
->info
->domain_name
,
132 *p_space_remaining
= 0;
135 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
140 (*p_space_remaining
) -= l
;
144 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
147 if (!src
|| !dst
|| !n
|| !(*dst
)) {
150 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
159 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
161 TALLOC_CTX
*ctx
= talloc_tos();
162 const struct loadparm_substitution
*lp_sub
=
163 loadparm_s3_global_substitution();
168 buf
= talloc_strdup(ctx
,s
);
172 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(ctx
, lp_sub
, snum
));
176 buf
= talloc_sub_full(ctx
,
177 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
178 conn
->session_info
->unix_info
->unix_name
,
180 conn
->session_info
->unix_token
->gid
,
181 conn
->session_info
->unix_info
->sanitized_username
,
182 conn
->session_info
->info
->domain_name
,
187 return strlen(buf
) + 1;
190 /****************************************************************
191 Return an SVAL at a pointer, or failval if beyond the end.
192 ****************************************************************/
194 static int get_safe_SVAL(
195 const char *buf_base
,
202 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0]
203 * and ptr[1], NOT ptr[2].
205 if (!is_offset_safe(buf_base
, buf_len
, ptr
, off
+1)) {
208 return SVAL(ptr
,off
);
211 /****************************************************************
212 Return an IVAL at a pointer, or failval if beyond the end.
213 ****************************************************************/
215 static int get_safe_IVAL(
216 const char *buf_base
,
223 * Note we use off+3 here, not off+4 as IVAL accesses
224 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
226 if (!is_offset_safe(buf_base
, buf_len
, ptr
, off
+3)) {
229 return IVAL(ptr
,off
);
232 /****************************************************************
233 Return a safe pointer into a buffer, or NULL.
234 ****************************************************************/
236 static char *get_safe_ptr(
237 const char *buf_base
,
242 return is_offset_safe(buf_base
, buf_len
, ptr
, off
) ?
246 /*******************************************************************
247 Check a API string for validity when we only need to check the prefix.
248 ******************************************************************/
250 static bool prefix_ok(const char *str
, const char *prefix
)
252 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
256 const char *format
; /* formatstring for structure */
257 const char *subformat
; /* subformat for structure */
258 char *base
; /* baseaddress of buffer */
259 int buflen
; /* remaining size for fixed part; on init: length of base */
260 int subcount
; /* count of substructures */
261 char *structbuf
; /* pointer into buffer for remaining fixed part */
262 int stringlen
; /* remaining size for variable part */
263 char *stringbuf
; /* pointer into buffer for remaining variable part */
264 int neededlen
; /* total needed size */
265 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
266 const char *curpos
; /* current position; pointer into format or subformat */
270 static int get_counter(const char **p
)
276 if (!isdigit((int)**p
)) {
282 n
= 10 * n
+ (i
- '0');
290 static int getlen(const char *p
)
299 case 'W': /* word (2 byte) */
302 case 'K': /* status word? (2 byte) */
305 case 'N': /* count of substructures (word) at end */
308 case 'D': /* double word (4 byte) */
309 case 'z': /* offset to zero terminated string (4 byte) */
310 case 'l': /* offset to user data (4 byte) */
313 case 'b': /* offset to data (with counter) (4 byte) */
317 case 'B': /* byte (with optional counter) */
318 n
+= get_counter(&p
);
325 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
330 if (!p
->format
|| !p
->base
) {
334 i
= count
* getlen(p
->format
);
336 i
+= subcount
* getlen(p
->subformat
);
338 p
->structbuf
= p
->base
;
342 p
->curpos
= p
->format
;
348 * This is the old error code we used. Aparently
349 * WinNT/2k systems return ERRbuftoosmall (2123) and
350 * OS/2 needs this. I'm leaving this here so we can revert
353 p
->errcode
= ERRmoredata
;
355 p
->errcode
= ERRbuftoosmall
;
358 p
->errcode
= NERR_Success
;
362 p
->stringbuf
= p
->base
+ i
;
364 return (p
->errcode
== NERR_Success
);
367 static int package(struct pack_desc
*p
, ...)
370 int needed
=0, stringneeded
;
371 const char *str
=NULL
;
372 int is_string
=0, stringused
;
379 p
->curpos
= p
->format
;
381 p
->curpos
= p
->subformat
;
386 str
= va_arg(args
,char*);
387 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
396 switch( *p
->curpos
++ ) {
397 case 'W': /* word (2 byte) */
399 temp
= va_arg(args
,int);
400 if (p
->buflen
>= needed
) {
401 SSVAL(p
->structbuf
,0,temp
);
404 case 'K': /* status word? (2 byte) */
406 temp
= va_arg(args
,int);
407 if (p
->buflen
>= needed
) {
408 SSVAL(p
->structbuf
,0,temp
);
411 case 'N': /* count of substructures (word) at end */
413 p
->subcount
= va_arg(args
,int);
414 if (p
->buflen
>= needed
) {
415 SSVAL(p
->structbuf
,0,p
->subcount
);
418 case 'D': /* double word (4 byte) */
420 temp
= va_arg(args
,int);
421 if (p
->buflen
>= needed
) {
422 SIVAL(p
->structbuf
,0,temp
);
425 case 'B': /* byte (with optional counter) */
426 needed
= get_counter(&p
->curpos
);
428 char *s
= va_arg(args
,char*);
429 if (p
->buflen
>= needed
) {
430 strlcpy(p
->structbuf
,s
?s
:"",needed
);
434 case 'z': /* offset to zero terminated string (4 byte) */
435 str
= va_arg(args
,char*);
436 stringneeded
= (str
? strlen(str
)+1 : 0);
439 case 'l': /* offset to user data (4 byte) */
440 str
= va_arg(args
,char*);
441 stringneeded
= va_arg(args
,int);
444 case 'b': /* offset to data (with counter) (4 byte) */
445 str
= va_arg(args
,char*);
446 stringneeded
= get_counter(&p
->curpos
);
452 if (stringneeded
>= 0) {
454 if (p
->buflen
>= needed
) {
455 stringused
= stringneeded
;
456 if (stringused
> p
->stringlen
) {
457 stringused
= (is_string
? p
->stringlen
: 0);
458 if (p
->errcode
== NERR_Success
) {
459 p
->errcode
= ERRmoredata
;
463 SIVAL(p
->structbuf
,0,0);
465 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
466 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
468 p
->stringbuf
[stringused
-1] = '\0';
470 p
->stringbuf
+= stringused
;
471 p
->stringlen
-= stringused
;
472 p
->usedlen
+= stringused
;
475 p
->neededlen
+= stringneeded
;
478 p
->neededlen
+= needed
;
479 if (p
->buflen
>= needed
) {
480 p
->structbuf
+= needed
;
482 p
->usedlen
+= needed
;
484 if (p
->errcode
== NERR_Success
) {
485 p
->errcode
= ERRmoredata
;
492 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
493 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
495 #define PACK(desc,t,v) package(desc,v)
496 #define PACKl(desc,t,v,l) package(desc,v,l)
499 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
504 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
509 /****************************************************************************
511 ****************************************************************************/
513 static void PackDriverData(struct pack_desc
* desc
)
515 char drivdata
[4+4+32];
516 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
517 SIVAL(drivdata
,4,1000); /* lVersion */
518 memset(drivdata
+8,0,32); /* szDeviceName */
519 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
520 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
523 static int check_printq_info(struct pack_desc
* desc
,
524 unsigned int uLevel
, char *id1
, char *id2
)
526 desc
->subformat
= NULL
;
529 desc
->format
= "B13";
532 desc
->format
= "B13BWWWzzzzzWW";
535 desc
->format
= "B13BWWWzzzzzWN";
536 desc
->subformat
= "WB21BB16B10zWWzDDz";
539 desc
->format
= "zWWWWzzzzWWzzl";
542 desc
->format
= "zWWWWzzzzWNzzl";
543 desc
->subformat
= "WWzWWDDzz";
552 desc
->format
= "WzzzzzzzzN";
553 desc
->subformat
= "z";
556 DEBUG(0,("check_printq_info: invalid level %d\n",
560 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
561 DEBUG(0,("check_printq_info: invalid format %s\n",
562 id1
? id1
: "<NULL>" ));
565 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
566 DEBUG(0,("check_printq_info: invalid subformat %s\n",
567 id2
? id2
: "<NULL>" ));
574 #define RAP_JOB_STATUS_QUEUED 0
575 #define RAP_JOB_STATUS_PAUSED 1
576 #define RAP_JOB_STATUS_SPOOLING 2
577 #define RAP_JOB_STATUS_PRINTING 3
578 #define RAP_JOB_STATUS_PRINTED 4
580 #define RAP_QUEUE_STATUS_PAUSED 1
581 #define RAP_QUEUE_STATUS_ERROR 2
583 /* turn a print job status into a on the wire status
585 static int printj_spoolss_status(int v
)
587 if (v
== JOB_STATUS_QUEUED
)
588 return RAP_JOB_STATUS_QUEUED
;
589 if (v
& JOB_STATUS_PAUSED
)
590 return RAP_JOB_STATUS_PAUSED
;
591 if (v
& JOB_STATUS_SPOOLING
)
592 return RAP_JOB_STATUS_SPOOLING
;
593 if (v
& JOB_STATUS_PRINTING
)
594 return RAP_JOB_STATUS_PRINTING
;
598 /* turn a print queue status into a on the wire status
600 static int printq_spoolss_status(int v
)
602 if (v
== PRINTER_STATUS_OK
)
604 if (v
& PRINTER_STATUS_PAUSED
)
605 return RAP_QUEUE_STATUS_PAUSED
;
606 return RAP_QUEUE_STATUS_ERROR
;
609 static void fill_spoolss_printjob_info(int uLevel
,
610 struct pack_desc
*desc
,
611 struct spoolss_JobInfo2
*info2
,
614 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
616 /* the client expects localtime */
617 t
-= get_time_zone(t
);
619 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
621 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
622 PACKS(desc
,"B",""); /* pad */
623 PACKS(desc
,"B16",""); /* szNotifyName */
624 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
625 PACKS(desc
,"z",""); /* pszParms */
626 PACKI(desc
,"W",n
+1); /* uPosition */
627 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
628 PACKS(desc
,"z",""); /* pszStatus */
629 PACKI(desc
,"D", t
); /* ulSubmitted */
630 PACKI(desc
,"D", info2
->size
); /* ulSize */
631 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
633 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
634 PACKI(desc
,"W", info2
->priority
); /* uPriority */
635 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
636 PACKI(desc
,"W",n
+1); /* uPosition */
637 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
638 PACKI(desc
,"D",t
); /* ulSubmitted */
639 PACKI(desc
,"D", info2
->size
); /* ulSize */
640 PACKS(desc
,"z","Samba"); /* pszComment */
641 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
643 PACKS(desc
,"z",""); /* pszNotifyName */
644 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
645 PACKS(desc
,"z",""); /* pszParms */
646 PACKS(desc
,"z",""); /* pszStatus */
647 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
648 PACKS(desc
,"z","lpd"); /* pszQProcName */
649 PACKS(desc
,"z",""); /* pszQProcParms */
650 PACKS(desc
,"z","NULL"); /* pszDriverName */
651 PackDriverData(desc
); /* pDriverData */
652 PACKS(desc
,"z",""); /* pszPrinterName */
653 } else if (uLevel
== 4) { /* OS2 */
654 PACKS(desc
,"z",""); /* pszSpoolFileName */
655 PACKS(desc
,"z",""); /* pszPortName */
656 PACKS(desc
,"z",""); /* pszStatus */
657 PACKI(desc
,"D",0); /* ulPagesSpooled */
658 PACKI(desc
,"D",0); /* ulPagesSent */
659 PACKI(desc
,"D",0); /* ulPagesPrinted */
660 PACKI(desc
,"D",0); /* ulTimePrinted */
661 PACKI(desc
,"D",0); /* ulExtendJobStatus */
662 PACKI(desc
,"D",0); /* ulStartPage */
663 PACKI(desc
,"D",0); /* ulEndPage */
668 /********************************************************************
669 Respond to the DosPrintQInfo command with a level of 52
670 This is used to get printer driver information for Win9x clients
671 ********************************************************************/
672 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
673 struct pack_desc
* desc
, int count
,
674 const char *printer_name
)
678 trim_string(discard_const_p(char, driver
->driver_path
), "\\print$\\WIN40\\0\\", 0);
679 trim_string(discard_const_p(char, driver
->data_file
), "\\print$\\WIN40\\0\\", 0);
680 trim_string(discard_const_p(char, driver
->help_file
), "\\print$\\WIN40\\0\\", 0);
682 PACKI(desc
, "W", 0x0400); /* don't know */
683 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
684 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
685 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
686 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
688 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
689 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
690 PACKS(desc
,"z", location
); /* share to retrieve files */
692 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
693 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
694 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
696 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
697 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
698 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
699 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
700 DEBUG(3,("Driver Location: %s:\n",location
));
701 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
702 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
703 PACKI(desc
,"N",count
); /* number of files to copy */
705 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
707 trim_string(discard_const_p(char, driver
->dependent_files
[i
]), "\\print$\\WIN40\\0\\", 0);
708 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
709 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
714 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
717 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
719 desc
->errcode
=NERR_Success
;
723 static const char *strip_unc(const char *unc
)
731 if ((p
= strrchr(unc
, '\\')) != NULL
) {
738 static void fill_printq_info(int uLevel
,
739 struct pack_desc
* desc
,
741 union spoolss_JobInfo
*job_info
,
742 struct spoolss_DriverInfo3
*driver_info
,
743 struct spoolss_PrinterInfo2
*printer_info
)
749 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
754 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
757 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
761 if (uLevel
== 1 || uLevel
== 2) {
762 PACKS(desc
,"B",""); /* alignment */
763 PACKI(desc
,"W",5); /* priority */
764 PACKI(desc
,"W",0); /* start time */
765 PACKI(desc
,"W",0); /* until time */
766 PACKS(desc
,"z",""); /* pSepFile */
767 PACKS(desc
,"z","lpd"); /* pPrProc */
768 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
769 PACKS(desc
,"z",""); /* pParms */
770 if (printer_info
->printername
== NULL
) {
771 PACKS(desc
,"z","UNKNOWN PRINTER");
772 PACKI(desc
,"W",LPSTAT_ERROR
);
774 PACKS(desc
,"z", printer_info
->comment
);
775 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
777 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
780 if (uLevel
== 3 || uLevel
== 4) {
781 PACKI(desc
,"W",5); /* uPriority */
782 PACKI(desc
,"W",0); /* uStarttime */
783 PACKI(desc
,"W",0); /* uUntiltime */
784 PACKI(desc
,"W",5); /* pad1 */
785 PACKS(desc
,"z",""); /* pszSepFile */
786 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
787 PACKS(desc
,"z",NULL
); /* pszParms */
788 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
789 /* "don't ask" that it's done this way to fix corrupted
790 Win9X/ME printer comments. */
791 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
792 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
793 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
794 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
795 PackDriverData(desc
); /* pDriverData */
798 if (uLevel
== 2 || uLevel
== 4) {
800 for (i
= 0; i
< count
; i
++) {
801 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
806 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
809 /* This function returns the number of files for a given driver */
810 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
814 /* count the number of files */
815 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
821 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
822 connection_struct
*conn
, uint64_t vuid
,
823 char *param
, int tpscnt
,
824 char *data
, int tdscnt
,
825 int mdrcnt
,int mprcnt
,
826 char **rdata
,char **rparam
,
827 int *rdata_len
,int *rparam_len
)
829 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
830 char *str2
= skip_string(param
,tpscnt
,str1
);
831 char *p
= skip_string(param
,tpscnt
,str2
);
836 struct pack_desc desc
;
839 WERROR werr
= WERR_OK
;
840 TALLOC_CTX
*mem_ctx
= talloc_tos();
842 struct rpc_pipe_client
*cli
= NULL
;
843 struct dcerpc_binding_handle
*b
= NULL
;
844 struct policy_handle handle
;
845 struct spoolss_DevmodeContainer devmode_ctr
;
846 union spoolss_DriverInfo driver_info
;
847 union spoolss_JobInfo
*job_info
= NULL
;
848 union spoolss_PrinterInfo printer_info
;
850 if (!str1
|| !str2
|| !p
) {
853 memset((char *)&desc
,'\0',sizeof(desc
));
855 p
= skip_string(param
,tpscnt
,p
);
859 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
860 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
861 /* str3 may be null here and is checked in check_printq_info(). */
863 /* remove any trailing username */
864 if ((p
= strchr_m(QueueName
,'%')))
867 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
869 /* check it's a supported varient */
870 if (!prefix_ok(str1
,"zWrLh"))
872 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
874 * Patch from Scott Moomaw <scott@bridgewater.edu>
875 * to return the 'invalid info level' error if an
876 * unknown level was requested.
880 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
884 SSVALS(*rparam
,0,ERRunknownlevel
);
892 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
893 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
897 status
= rpc_pipe_open_interface(mem_ctx
,
900 conn
->sconn
->remote_address
,
901 conn
->sconn
->local_address
,
902 conn
->sconn
->msg_ctx
,
904 if (!NT_STATUS_IS_OK(status
)) {
905 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
907 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
910 b
= cli
->binding_handle
;
912 ZERO_STRUCT(devmode_ctr
);
914 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
921 if (!NT_STATUS_IS_OK(status
)) {
922 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
925 if (!W_ERROR_IS_OK(werr
)) {
926 desc
.errcode
= W_ERROR_V(werr
);
930 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
935 if (!W_ERROR_IS_OK(werr
)) {
936 desc
.errcode
= W_ERROR_V(werr
);
941 uint32_t server_major_version
;
942 uint32_t server_minor_version
;
944 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
952 &server_major_version
,
953 &server_minor_version
);
954 if (!W_ERROR_IS_OK(werr
)) {
955 desc
.errcode
= W_ERROR_V(werr
);
959 count
= get_printerdrivernumber(&driver_info
.info3
);
960 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
963 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
971 if (!W_ERROR_IS_OK(werr
)) {
972 desc
.errcode
= W_ERROR_V(werr
);
980 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
985 desc
.buflen
= mdrcnt
;
988 * Don't return data but need to get correct length
989 * init_package will return wrong size if buflen=0
991 desc
.buflen
= getlen(desc
.format
);
992 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
995 if (init_package(&desc
,1,count
)) {
996 desc
.subcount
= count
;
997 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
1000 *rdata_len
= desc
.usedlen
;
1003 * We must set the return code to ERRbuftoosmall
1004 * in order to support lanman style printing with Win NT/2k
1007 if (!mdrcnt
&& lp_disable_spoolss())
1008 desc
.errcode
= ERRbuftoosmall
;
1011 if (b
&& is_valid_policy_hnd(&handle
)) {
1012 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1015 *rdata_len
= desc
.usedlen
;
1017 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1022 SSVALS(*rparam
,0,desc
.errcode
);
1024 SSVAL(*rparam
,4,desc
.neededlen
);
1026 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
1033 /****************************************************************************
1034 View list of all print jobs on all queues.
1035 ****************************************************************************/
1037 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
1038 connection_struct
*conn
, uint64_t vuid
,
1039 char *param
, int tpscnt
,
1040 char *data
, int tdscnt
,
1041 int mdrcnt
, int mprcnt
,
1042 char **rdata
, char** rparam
,
1043 int *rdata_len
, int *rparam_len
)
1045 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1046 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
1047 char *p
= skip_string(param
,tpscnt
,output_format1
);
1048 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1049 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
1051 struct pack_desc desc
;
1052 int *subcntarr
= NULL
;
1053 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
1055 WERROR werr
= WERR_OK
;
1056 TALLOC_CTX
*mem_ctx
= talloc_tos();
1058 struct rpc_pipe_client
*cli
= NULL
;
1059 struct dcerpc_binding_handle
*b
= NULL
;
1060 struct spoolss_DevmodeContainer devmode_ctr
;
1061 uint32_t num_printers
;
1062 union spoolss_PrinterInfo
*printer_info
;
1063 union spoolss_DriverInfo
*driver_info
;
1064 union spoolss_JobInfo
**job_info
;
1066 if (!param_format
|| !output_format1
|| !p
) {
1070 memset((char *)&desc
,'\0',sizeof(desc
));
1072 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1074 if (!prefix_ok(param_format
,"WrLeh")) {
1077 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1079 * Patch from Scott Moomaw <scott@bridgewater.edu>
1080 * to return the 'invalid info level' error if an
1081 * unknown level was requested.
1085 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1089 SSVALS(*rparam
,0,ERRunknownlevel
);
1095 status
= rpc_pipe_open_interface(mem_ctx
,
1098 conn
->sconn
->remote_address
,
1099 conn
->sconn
->local_address
,
1100 conn
->sconn
->msg_ctx
,
1102 if (!NT_STATUS_IS_OK(status
)) {
1103 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1104 nt_errstr(status
)));
1105 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1108 b
= cli
->binding_handle
;
1110 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1112 cli
->srv_name_slash
,
1117 if (!W_ERROR_IS_OK(werr
)) {
1118 desc
.errcode
= W_ERROR_V(werr
);
1122 queuecnt
= num_printers
;
1124 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1125 if (job_info
== NULL
) {
1129 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1130 if (driver_info
== NULL
) {
1134 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1135 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1140 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1146 desc
.buflen
= mdrcnt
;
1149 for (i
= 0; i
< num_printers
; i
++) {
1152 struct policy_handle handle
;
1153 const char *printername
;
1155 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1156 if (printername
== NULL
) {
1160 ZERO_STRUCT(handle
);
1161 ZERO_STRUCT(devmode_ctr
);
1163 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
1170 if (!NT_STATUS_IS_OK(status
)) {
1171 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1174 if (!W_ERROR_IS_OK(werr
)) {
1175 desc
.errcode
= W_ERROR_V(werr
);
1179 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1187 if (!W_ERROR_IS_OK(werr
)) {
1188 desc
.errcode
= W_ERROR_V(werr
);
1193 uint32_t server_major_version
;
1194 uint32_t server_minor_version
;
1196 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1204 &server_major_version
,
1205 &server_minor_version
);
1206 if (!W_ERROR_IS_OK(werr
)) {
1207 desc
.errcode
= W_ERROR_V(werr
);
1212 subcntarr
[i
] = num_jobs
;
1213 subcnt
+= subcntarr
[i
];
1215 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1218 if (init_package(&desc
,queuecnt
,subcnt
)) {
1219 for (i
= 0; i
< num_printers
; i
++) {
1220 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1221 if (desc
.errcode
== NERR_Success
) {
1228 SAFE_FREE(subcntarr
);
1229 *rdata_len
= desc
.usedlen
;
1231 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1235 SSVALS(*rparam
,0,desc
.errcode
);
1237 SSVAL(*rparam
,4,succnt
);
1238 SSVAL(*rparam
,6,queuecnt
);
1244 SAFE_FREE(subcntarr
);
1249 /****************************************************************************
1250 Get info level for a server list query.
1251 ****************************************************************************/
1253 static bool check_session_info(int uLevel
, char* id
)
1257 if (strcmp(id
,"B16") != 0) {
1262 if (strcmp(id
,"B16BBDz") != 0) {
1272 struct srv_info_struct
{
1280 /*******************************************************************
1281 Get server info lists from the files saved by nmbd. Return the
1283 ******************************************************************/
1285 static int get_session_info(uint32_t servertype
,
1286 struct srv_info_struct
**servers
,
1292 bool local_list_only
;
1294 char *slist_cache_path
= cache_path(talloc_tos(), SERVER_LIST
);
1295 if (slist_cache_path
== NULL
) {
1299 lines
= file_lines_load(slist_cache_path
, NULL
, 0, NULL
);
1301 DEBUG(4, ("Can't open %s - %s\n",
1302 slist_cache_path
, strerror(errno
)));
1303 TALLOC_FREE(slist_cache_path
);
1306 TALLOC_FREE(slist_cache_path
);
1308 /* request for everything is code for request all servers */
1309 if (servertype
== SV_TYPE_ALL
) {
1310 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1313 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1315 DEBUG(4,("Servertype search: %8x\n",servertype
));
1317 for (i
=0;lines
[i
];i
++) {
1319 struct srv_info_struct
*s
;
1320 const char *ptr
= lines
[i
];
1322 TALLOC_CTX
*frame
= NULL
;
1329 if (count
== alloced
) {
1331 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1333 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1337 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1339 s
= &(*servers
)[count
];
1341 frame
= talloc_stackframe();
1343 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1347 fstrcpy(s
->name
, p
);
1350 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1356 s
->comment
[0] = '\0';
1357 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1361 fstrcpy(s
->comment
, p
);
1362 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1364 s
->domain
[0] = '\0';
1365 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1366 /* this allows us to cope with an old nmbd */
1367 fstrcpy(s
->domain
,lp_workgroup());
1369 fstrcpy(s
->domain
, p
);
1373 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1374 DEBUG(4,("r:host file "));
1378 /* Filter the servers/domains we return based on what was asked for. */
1380 /* Check to see if we are being asked for a local list only. */
1381 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1382 DEBUG(4,("r: local list only"));
1386 /* doesn't match up: don't want it */
1387 if (!(servertype
& s
->type
)) {
1388 DEBUG(4,("r:serv type "));
1392 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1393 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1394 DEBUG(4,("s: dom mismatch "));
1398 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1402 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1403 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1406 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1407 s
->name
, s
->type
, s
->comment
, s
->domain
));
1408 s
->server_added
= True
;
1411 DEBUG(4,("%20s %8x %25s %15s\n",
1412 s
->name
, s
->type
, s
->comment
, s
->domain
));
1420 /*******************************************************************
1421 Fill in a server info structure.
1422 ******************************************************************/
1424 static int fill_srv_info(struct srv_info_struct
*service
,
1425 int uLevel
, char **buf
, int *buflen
,
1426 char **stringbuf
, int *stringspace
, char *baseaddr
)
1449 len
= strlen(service
->comment
)+1;
1453 *buflen
= struct_len
;
1455 return struct_len
+ len
;
1460 if (*buflen
< struct_len
) {
1467 p2
= p
+ struct_len
;
1468 l2
= *buflen
- struct_len
;
1476 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1480 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1481 SIVAL(p
,18,service
->type
);
1482 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1483 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1488 *buf
= p
+ struct_len
;
1489 *buflen
-= struct_len
;
1500 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1502 return strcasecmp_m(s1
->name
,s2
->name
);
1505 /****************************************************************************
1506 View list of servers available (or possibly domains). The info is
1507 extracted from lists saved by nmbd on the local host.
1508 ****************************************************************************/
1510 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1511 connection_struct
*conn
, uint64_t vuid
,
1512 char *param
, int tpscnt
,
1513 char *data
, int tdscnt
,
1514 int mdrcnt
, int mprcnt
, char **rdata
,
1515 char **rparam
, int *rdata_len
, int *rparam_len
)
1517 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1518 char *str2
= skip_string(param
,tpscnt
,str1
);
1519 char *p
= skip_string(param
,tpscnt
,str2
);
1520 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1521 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1522 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1524 int data_len
, fixed_len
, string_len
;
1525 int f_len
= 0, s_len
= 0;
1526 struct srv_info_struct
*servers
=NULL
;
1527 int counted
=0,total
=0;
1530 bool domain_request
;
1533 if (!str1
|| !str2
|| !p
) {
1537 /* If someone sets all the bits they don't really mean to set
1538 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1541 if (servertype
== SV_TYPE_ALL
) {
1542 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1545 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1546 any other bit (they may just set this bit on its own) they
1547 want all the locally seen servers. However this bit can be
1548 set on its own so set the requested servers to be
1549 ALL - DOMAIN_ENUM. */
1551 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1552 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1555 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1556 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1560 if (!prefix_ok(str1
,"WrLehD")) {
1563 if (!check_session_info(uLevel
,str2
)) {
1567 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1568 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1569 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1571 if (strcmp(str1
, "WrLehDz") == 0) {
1572 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1575 pull_ascii_fstring(domain
, p
);
1577 fstrcpy(domain
, lp_workgroup());
1580 DEBUG(4, ("domain [%s]\n", domain
));
1582 if (lp_browse_list()) {
1583 total
= get_session_info(servertype
,&servers
,domain
);
1586 data_len
= fixed_len
= string_len
= 0;
1589 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1592 char *lastname
=NULL
;
1594 for (i
=0;i
<total
;i
++) {
1595 struct srv_info_struct
*s
= &servers
[i
];
1597 if (lastname
&& strequal(lastname
,s
->name
)) {
1601 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1602 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1603 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1605 if (data_len
< buf_len
) {
1608 string_len
+= s_len
;
1615 *rdata_len
= fixed_len
+ string_len
;
1616 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1621 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1627 char *lastname
=NULL
;
1628 int count2
= counted
;
1630 for (i
= 0; i
< total
&& count2
;i
++) {
1631 struct srv_info_struct
*s
= &servers
[i
];
1633 if (lastname
&& strequal(lastname
,s
->name
)) {
1637 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1638 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1639 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1645 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1649 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1651 SSVAL(*rparam
,4,counted
);
1652 SSVAL(*rparam
,6,counted
+missed
);
1656 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1657 domain
,uLevel
,counted
,counted
+missed
));
1662 static int srv_name_match(const char *n1
, const char *n2
)
1665 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1667 * In Windows, FirstNameToReturn need not be an exact match:
1668 * the server will return a list of servers that exist on
1669 * the network greater than or equal to the FirstNameToReturn.
1671 int ret
= strcasecmp_m(n1
, n2
);
1680 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1681 connection_struct
*conn
, uint64_t vuid
,
1682 char *param
, int tpscnt
,
1683 char *data
, int tdscnt
,
1684 int mdrcnt
, int mprcnt
, char **rdata
,
1685 char **rparam
, int *rdata_len
, int *rparam_len
)
1687 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1688 char *str2
= skip_string(param
,tpscnt
,str1
);
1689 char *p
= skip_string(param
,tpscnt
,str2
);
1690 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1691 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1692 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1694 int data_len
, fixed_len
, string_len
;
1695 int f_len
= 0, s_len
= 0;
1696 struct srv_info_struct
*servers
=NULL
;
1697 int counted
=0,first
=0,total
=0;
1701 bool domain_request
;
1704 if (!str1
|| !str2
|| !p
) {
1708 /* If someone sets all the bits they don't really mean to set
1709 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1712 if (servertype
== SV_TYPE_ALL
) {
1713 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1716 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1717 any other bit (they may just set this bit on its own) they
1718 want all the locally seen servers. However this bit can be
1719 set on its own so set the requested servers to be
1720 ALL - DOMAIN_ENUM. */
1722 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1723 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1726 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1727 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1731 if (strcmp(str1
, "WrLehDzz") != 0) {
1734 if (!check_session_info(uLevel
,str2
)) {
1738 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1739 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1740 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1742 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1745 pull_ascii_fstring(domain
, p
);
1746 if (domain
[0] == '\0') {
1747 fstrcpy(domain
, lp_workgroup());
1749 p
= skip_string(param
,tpscnt
,p
);
1750 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1753 pull_ascii_fstring(first_name
, p
);
1755 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1756 domain
, first_name
));
1758 if (lp_browse_list()) {
1759 total
= get_session_info(servertype
,&servers
,domain
);
1762 data_len
= fixed_len
= string_len
= 0;
1765 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1767 if (first_name
[0] != '\0') {
1768 struct srv_info_struct
*first_server
= NULL
;
1770 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1771 srv_name_match
, first_server
);
1773 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1775 * The binary search may not find the exact match
1776 * so we need to search backward to find the first match
1778 * This implements the strange matching windows
1779 * implements. (see the comment in srv_name_match().
1783 ret
= strcasecmp_m(first_name
,
1784 servers
[first
-1].name
);
1791 /* we should return no entries */
1797 char *lastname
=NULL
;
1799 for (i
=first
;i
<total
;i
++) {
1800 struct srv_info_struct
*s
= &servers
[i
];
1802 if (lastname
&& strequal(lastname
,s
->name
)) {
1806 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1807 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1808 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1810 if (data_len
< buf_len
) {
1813 string_len
+= s_len
;
1820 *rdata_len
= fixed_len
+ string_len
;
1821 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1826 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1832 char *lastname
=NULL
;
1833 int count2
= counted
;
1835 for (i
= first
; i
< total
&& count2
;i
++) {
1836 struct srv_info_struct
*s
= &servers
[i
];
1838 if (lastname
&& strequal(lastname
,s
->name
)) {
1842 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1843 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1844 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1850 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1854 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1856 SSVAL(*rparam
,4,counted
);
1857 SSVAL(*rparam
,6,counted
+missed
);
1859 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1860 domain
,uLevel
,first
,first_name
,
1861 first
< total
? servers
[first
].name
: "",
1862 counted
,counted
+missed
));
1869 /****************************************************************************
1870 command 0x34 - suspected of being a "Lookup Names" stub api
1871 ****************************************************************************/
1873 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1874 connection_struct
*conn
, uint64_t vuid
,
1875 char *param
, int tpscnt
,
1876 char *data
, int tdscnt
,
1877 int mdrcnt
, int mprcnt
, char **rdata
,
1878 char **rparam
, int *rdata_len
, int *rparam_len
)
1880 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1881 char *str2
= skip_string(param
,tpscnt
,str1
);
1882 char *p
= skip_string(param
,tpscnt
,str2
);
1883 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1884 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1888 if (!str1
|| !str2
|| !p
) {
1892 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1893 str1
, str2
, p
, uLevel
, buf_len
));
1895 if (!prefix_ok(str1
,"zWrLeh")) {
1902 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1907 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1909 SSVAL(*rparam
,4,counted
);
1910 SSVAL(*rparam
,6,counted
+missed
);
1915 /****************************************************************************
1916 get info about a share
1917 ****************************************************************************/
1919 static bool check_share_info(int uLevel
, char* id
)
1923 if (strcmp(id
,"B13") != 0) {
1928 /* Level-2 descriptor is allowed (and ignored) */
1929 if (strcmp(id
,"B13BWz") != 0 &&
1930 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1935 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1940 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1950 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1951 char** buf
, int* buflen
,
1952 char** stringbuf
, int* stringspace
, char* baseaddr
)
1954 const struct loadparm_substitution
*lp_sub
=
1955 loadparm_s3_global_substitution();
1983 len
+= StrlenExpanded(conn
,snum
,lp_comment(talloc_tos(), lp_sub
, snum
));
1986 len
+= strlen(lp_path(talloc_tos(), lp_sub
, snum
)) + 1;
1989 *buflen
= struct_len
;
1994 return struct_len
+ len
;
1999 if ((*buflen
) < struct_len
) {
2007 p2
= p
+ struct_len
;
2008 l2
= (*buflen
) - struct_len
;
2015 push_ascii(p
,lp_servicename(talloc_tos(), lp_sub
, snum
),13, STR_TERMINATE
);
2021 type
= STYPE_DISKTREE
;
2022 if (lp_printable(snum
)) {
2023 type
= STYPE_PRINTQ
;
2025 if (strequal("IPC",lp_fstype(snum
))) {
2028 SSVAL(p
,14,type
); /* device type */
2029 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
2030 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(talloc_tos(), lp_sub
, snum
),&l2
);
2034 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
2035 SSVALS(p
,22,-1); /* max uses */
2036 SSVAL(p
,24,1); /* current uses */
2037 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
2038 len
+= CopyAndAdvance(&p2
,lp_path(talloc_tos(),lp_sub
, snum
),&l2
);
2039 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
2043 memset(p
+40,0,SHPWLEN
+2);
2054 (*buf
) = p
+ struct_len
;
2055 (*buflen
) -= struct_len
;
2057 (*stringspace
) = l2
;
2066 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
2067 connection_struct
*conn
,uint64_t vuid
,
2068 char *param
, int tpscnt
,
2069 char *data
, int tdscnt
,
2070 int mdrcnt
,int mprcnt
,
2071 char **rdata
,char **rparam
,
2072 int *rdata_len
,int *rparam_len
)
2074 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2075 char *str2
= skip_string(param
,tpscnt
,str1
);
2076 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2077 char *netname
= NULL
;
2078 char *p
= skip_string(param
,tpscnt
,netname
);
2079 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2082 if (!str1
|| !str2
|| !netname_in
|| !p
) {
2086 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2087 if (snum
< 0 || !netname
) {
2091 /* check it's a supported varient */
2092 if (!prefix_ok(str1
,"zWrLh")) {
2095 if (!check_share_info(uLevel
,str2
)) {
2099 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2104 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2105 if (*rdata_len
< 0) {
2110 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2114 SSVAL(*rparam
,0,NERR_Success
);
2115 SSVAL(*rparam
,2,0); /* converter word */
2116 SSVAL(*rparam
,4,*rdata_len
);
2121 /****************************************************************************
2122 View the list of available shares.
2124 This function is the server side of the NetShareEnum() RAP call.
2125 It fills the return buffer with share names and share comments.
2126 Note that the return buffer normally (in all known cases) allows only
2127 twelve byte strings for share names (plus one for a nul terminator).
2128 Share names longer than 12 bytes must be skipped.
2129 ****************************************************************************/
2131 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2132 connection_struct
*conn
, uint64_t vuid
,
2133 char *param
, int tpscnt
,
2134 char *data
, int tdscnt
,
2142 const struct loadparm_substitution
*lp_sub
=
2143 loadparm_s3_global_substitution();
2144 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2145 char *str2
= skip_string(param
,tpscnt
,str1
);
2146 char *p
= skip_string(param
,tpscnt
,str2
);
2147 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2148 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2151 int total
=0,counted
=0;
2152 bool missed
= False
;
2154 int data_len
, fixed_len
, string_len
;
2155 int f_len
= 0, s_len
= 0;
2157 if (!str1
|| !str2
|| !p
) {
2161 if (!prefix_ok(str1
,"WrLeh")) {
2164 if (!check_share_info(uLevel
,str2
)) {
2168 /* Ensure all the usershares are loaded. */
2170 delete_and_reload_printers();
2171 load_registry_shares();
2172 count
= load_usershare_shares(NULL
, connections_snum_used
);
2175 data_len
= fixed_len
= string_len
= 0;
2176 for (i
=0;i
<count
;i
++) {
2177 fstring servicename_dos
;
2178 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2181 push_ascii_fstring(servicename_dos
, lp_servicename(talloc_tos(), lp_sub
, i
));
2182 /* Maximum name length = 13. */
2183 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2185 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2186 if (data_len
< buf_len
) {
2189 string_len
+= s_len
;
2196 *rdata_len
= fixed_len
+ string_len
;
2197 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2202 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2207 for( i
= 0; i
< count
; i
++ ) {
2208 fstring servicename_dos
;
2209 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2213 push_ascii_fstring(servicename_dos
,
2214 lp_servicename(talloc_tos(), lp_sub
, i
));
2215 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2216 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2223 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2227 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2229 SSVAL(*rparam
,4,counted
);
2230 SSVAL(*rparam
,6,total
);
2232 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2233 counted
,total
,uLevel
,
2234 buf_len
,*rdata_len
,mdrcnt
));
2239 /****************************************************************************
2241 ****************************************************************************/
2243 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2244 connection_struct
*conn
,uint64_t vuid
,
2245 char *param
, int tpscnt
,
2246 char *data
, int tdscnt
,
2247 int mdrcnt
,int mprcnt
,
2248 char **rdata
,char **rparam
,
2249 int *rdata_len
,int *rparam_len
)
2251 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2252 char *str2
= skip_string(param
,tpscnt
,str1
);
2253 char *p
= skip_string(param
,tpscnt
,str2
);
2254 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2257 char *pathname
= NULL
;
2258 unsigned int offset
;
2260 size_t converted_size
;
2262 WERROR werr
= WERR_OK
;
2263 TALLOC_CTX
*mem_ctx
= talloc_tos();
2265 struct rpc_pipe_client
*cli
= NULL
;
2266 union srvsvc_NetShareInfo info
;
2267 struct srvsvc_NetShareInfo2 info2
;
2268 struct dcerpc_binding_handle
*b
;
2270 if (!str1
|| !str2
|| !p
) {
2274 /* check it's a supported varient */
2275 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2278 if (!check_share_info(uLevel
,str2
)) {
2285 /* Do we have a string ? */
2286 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2289 pull_ascii_fstring(sharename
,data
);
2295 /* only support disk share adds */
2296 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2300 offset
= IVAL(data
, 16);
2301 if (offset
>= mdrcnt
) {
2302 res
= ERRinvalidparam
;
2306 /* Do we have a string ? */
2307 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2310 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2312 offset
= IVAL(data
, 26);
2314 if (offset
>= mdrcnt
) {
2315 res
= ERRinvalidparam
;
2319 /* Do we have a string ? */
2320 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2324 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2325 offset
? (data
+offset
) : "", &converted_size
))
2327 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2335 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
2337 conn
->sconn
->remote_address
,
2338 conn
->sconn
->local_address
,
2339 conn
->sconn
->msg_ctx
,
2341 if (!NT_STATUS_IS_OK(status
)) {
2342 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2343 nt_errstr(status
)));
2344 res
= W_ERROR_V(ntstatus_to_werror(status
));
2348 b
= cli
->binding_handle
;
2350 info2
.name
= sharename
;
2351 info2
.type
= STYPE_DISKTREE
;
2352 info2
.comment
= comment
;
2353 info2
.permissions
= 0;
2354 info2
.max_users
= 0;
2355 info2
.current_users
= 0;
2356 info2
.path
= pathname
;
2357 info2
.password
= NULL
;
2359 info
.info2
= &info2
;
2361 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2362 cli
->srv_name_slash
,
2367 if (!NT_STATUS_IS_OK(status
)) {
2368 res
= W_ERROR_V(ntstatus_to_werror(status
));
2371 if (!W_ERROR_IS_OK(werr
)) {
2372 res
= W_ERROR_V(werr
);
2377 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2381 SSVAL(*rparam
,0,NERR_Success
);
2382 SSVAL(*rparam
,2,0); /* converter word */
2383 SSVAL(*rparam
,4,*rdata_len
);
2391 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2396 SSVAL(*rparam
,0,res
);
2401 /****************************************************************************
2402 view list of groups available
2403 ****************************************************************************/
2405 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2406 connection_struct
*conn
,uint64_t vuid
,
2407 char *param
, int tpscnt
,
2408 char *data
, int tdscnt
,
2409 int mdrcnt
,int mprcnt
,
2410 char **rdata
,char **rparam
,
2411 int *rdata_len
,int *rparam_len
)
2415 int resume_context
, cli_buf_size
;
2416 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2417 char *str2
= skip_string(param
,tpscnt
,str1
);
2418 char *p
= skip_string(param
,tpscnt
,str2
);
2420 uint32_t num_groups
;
2421 uint32_t resume_handle
;
2422 struct rpc_pipe_client
*samr_pipe
= NULL
;
2423 struct policy_handle samr_handle
, domain_handle
;
2424 NTSTATUS status
, result
;
2425 struct dcerpc_binding_handle
*b
;
2427 if (!str1
|| !str2
|| !p
) {
2431 if (strcmp(str1
,"WrLeh") != 0) {
2436 * W-> resume context (number of users to skip)
2437 * r -> return parameter pointer to receive buffer
2438 * L -> length of receive buffer
2439 * e -> return parameter number of entries
2440 * h -> return parameter total number of users
2443 if (strcmp("B21",str2
) != 0) {
2447 status
= rpc_pipe_open_interface(
2448 talloc_tos(), &ndr_table_samr
,
2449 conn
->session_info
, conn
->sconn
->remote_address
,
2450 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2451 if (!NT_STATUS_IS_OK(status
)) {
2452 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2453 nt_errstr(status
)));
2457 b
= samr_pipe
->binding_handle
;
2459 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2460 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2462 if (!NT_STATUS_IS_OK(status
)) {
2463 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2464 nt_errstr(status
)));
2467 if (!NT_STATUS_IS_OK(result
)) {
2468 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2469 nt_errstr(result
)));
2473 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2474 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2475 get_global_sam_sid(), &domain_handle
,
2477 if (!NT_STATUS_IS_OK(status
)) {
2478 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2479 nt_errstr(status
)));
2480 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2483 if (!NT_STATUS_IS_OK(result
)) {
2484 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2485 nt_errstr(result
)));
2486 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2490 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2491 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2492 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2493 "%d\n", resume_context
, cli_buf_size
));
2495 *rdata_len
= cli_buf_size
;
2496 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2503 errflags
= NERR_Success
;
2508 struct samr_SamArray
*sam_entries
;
2509 uint32_t num_entries
;
2511 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2517 if (!NT_STATUS_IS_OK(status
)) {
2518 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2519 "%s\n", nt_errstr(status
)));
2522 if (!NT_STATUS_IS_OK(result
)) {
2524 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2525 "%s\n", nt_errstr(result
)));
2529 if (num_entries
== 0) {
2530 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2531 "no entries -- done\n"));
2535 for(i
=0; i
<num_entries
; i
++) {
2538 name
= sam_entries
->entries
[i
].name
.string
;
2540 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2541 /* set overflow error */
2542 DEBUG(3,("overflow on entry %d group %s\n", i
,
2548 /* truncate the name at 21 chars. */
2550 strlcpy(p
, name
, 21);
2551 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2553 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2558 if (errflags
!= NERR_Success
) {
2562 TALLOC_FREE(sam_entries
);
2565 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2566 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2568 *rdata_len
= PTR_DIFF(p
,*rdata
);
2571 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2575 SSVAL(*rparam
, 0, errflags
);
2576 SSVAL(*rparam
, 2, 0); /* converter word */
2577 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2578 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2583 /*******************************************************************
2584 Get groups that a user is a member of.
2585 ******************************************************************/
2587 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2588 connection_struct
*conn
,uint64_t vuid
,
2589 char *param
, int tpscnt
,
2590 char *data
, int tdscnt
,
2591 int mdrcnt
,int mprcnt
,
2592 char **rdata
,char **rparam
,
2593 int *rdata_len
,int *rparam_len
)
2595 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2596 char *str2
= skip_string(param
,tpscnt
,str1
);
2597 char *UserName
= skip_string(param
,tpscnt
,str2
);
2598 char *p
= skip_string(param
,tpscnt
,UserName
);
2599 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2600 const char *level_string
;
2606 struct rpc_pipe_client
*samr_pipe
= NULL
;
2607 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2608 struct lsa_String name
;
2609 struct lsa_Strings names
;
2610 struct samr_Ids type
, rid
;
2611 struct samr_RidWithAttributeArray
*rids
;
2612 NTSTATUS status
, result
;
2613 struct dcerpc_binding_handle
*b
;
2615 if (!str1
|| !str2
|| !UserName
|| !p
) {
2620 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2625 /* check it's a supported varient */
2627 if ( strcmp(str1
,"zWrLeh") != 0 )
2632 level_string
= "B21";
2638 if (strcmp(level_string
,str2
) != 0)
2641 *rdata_len
= mdrcnt
+ 1024;
2642 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2647 SSVAL(*rparam
,0,NERR_Success
);
2648 SSVAL(*rparam
,2,0); /* converter word */
2651 endp
= *rdata
+ *rdata_len
;
2653 status
= rpc_pipe_open_interface(
2654 talloc_tos(), &ndr_table_samr
,
2655 conn
->session_info
, conn
->sconn
->remote_address
,
2656 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2657 if (!NT_STATUS_IS_OK(status
)) {
2658 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2659 nt_errstr(status
)));
2663 b
= samr_pipe
->binding_handle
;
2665 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2666 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2668 if (!NT_STATUS_IS_OK(status
)) {
2669 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2670 nt_errstr(status
)));
2673 if (!NT_STATUS_IS_OK(result
)) {
2674 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2675 nt_errstr(result
)));
2679 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2680 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2681 get_global_sam_sid(), &domain_handle
,
2683 if (!NT_STATUS_IS_OK(status
)) {
2684 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2685 nt_errstr(status
)));
2688 if (!NT_STATUS_IS_OK(result
)) {
2689 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2690 nt_errstr(result
)));
2694 name
.string
= UserName
;
2696 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2697 &domain_handle
, 1, &name
,
2700 if (!NT_STATUS_IS_OK(status
)) {
2701 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2702 nt_errstr(status
)));
2705 if (!NT_STATUS_IS_OK(result
)) {
2706 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2707 nt_errstr(result
)));
2710 if (rid
.count
!= 1) {
2711 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2714 if (type
.count
!= 1) {
2715 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2719 if (type
.ids
[0] != SID_NAME_USER
) {
2720 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2721 sid_type_lookup(type
.ids
[0])));
2725 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2727 SAMR_USER_ACCESS_GET_GROUPS
,
2728 rid
.ids
[0], &user_handle
,
2730 if (!NT_STATUS_IS_OK(status
)) {
2731 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2732 nt_errstr(status
)));
2735 if (!NT_STATUS_IS_OK(result
)) {
2736 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2737 nt_errstr(result
)));
2741 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2742 &user_handle
, &rids
,
2744 if (!NT_STATUS_IS_OK(status
)) {
2745 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2746 nt_errstr(status
)));
2749 if (!NT_STATUS_IS_OK(result
)) {
2750 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2751 nt_errstr(result
)));
2755 for (i
=0; i
<rids
->count
; i
++) {
2757 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2759 1, &rids
->rids
[i
].rid
,
2762 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2763 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2769 *rdata_len
= PTR_DIFF(p
,*rdata
);
2771 SSVAL(*rparam
,4,count
); /* is this right?? */
2772 SSVAL(*rparam
,6,count
); /* is this right?? */
2777 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2779 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2781 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2786 /*******************************************************************
2788 ******************************************************************/
2790 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2791 connection_struct
*conn
, uint64_t vuid
,
2792 char *param
, int tpscnt
,
2793 char *data
, int tdscnt
,
2794 int mdrcnt
,int mprcnt
,
2795 char **rdata
,char **rparam
,
2796 int *rdata_len
,int *rparam_len
)
2801 int i
, resume_context
, cli_buf_size
;
2802 uint32_t resume_handle
;
2804 struct rpc_pipe_client
*samr_pipe
= NULL
;
2805 struct policy_handle samr_handle
, domain_handle
;
2806 NTSTATUS status
, result
;
2808 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2809 char *str2
= skip_string(param
,tpscnt
,str1
);
2810 char *p
= skip_string(param
,tpscnt
,str2
);
2813 struct dcerpc_binding_handle
*b
;
2815 if (!str1
|| !str2
|| !p
) {
2819 if (strcmp(str1
,"WrLeh") != 0)
2822 * W-> resume context (number of users to skip)
2823 * r -> return parameter pointer to receive buffer
2824 * L -> length of receive buffer
2825 * e -> return parameter number of entries
2826 * h -> return parameter total number of users
2829 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2830 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2831 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2832 resume_context
, cli_buf_size
));
2835 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2840 /* check it's a supported varient */
2841 if (strcmp("B21",str2
) != 0)
2844 *rdata_len
= cli_buf_size
;
2845 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2851 endp
= *rdata
+ *rdata_len
;
2853 status
= rpc_pipe_open_interface(
2854 talloc_tos(), &ndr_table_samr
,
2855 conn
->session_info
, conn
->sconn
->remote_address
,
2856 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2857 if (!NT_STATUS_IS_OK(status
)) {
2858 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2859 nt_errstr(status
)));
2863 b
= samr_pipe
->binding_handle
;
2865 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2866 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2868 if (!NT_STATUS_IS_OK(status
)) {
2869 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2870 nt_errstr(status
)));
2873 if (!NT_STATUS_IS_OK(result
)) {
2874 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2875 nt_errstr(result
)));
2879 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2880 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2881 get_global_sam_sid(), &domain_handle
,
2883 if (!NT_STATUS_IS_OK(status
)) {
2884 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2885 nt_errstr(status
)));
2886 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2889 if (!NT_STATUS_IS_OK(result
)) {
2890 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2891 nt_errstr(result
)));
2892 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2896 errflags
=NERR_Success
;
2901 struct samr_SamArray
*sam_entries
;
2902 uint32_t num_entries
;
2904 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2911 if (!NT_STATUS_IS_OK(status
)) {
2912 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2913 "%s\n", nt_errstr(status
)));
2916 if (!NT_STATUS_IS_OK(result
)) {
2917 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2918 "%s\n", nt_errstr(result
)));
2922 if (num_entries
== 0) {
2923 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2924 "no entries -- done\n"));
2928 for (i
=0; i
<num_entries
; i
++) {
2931 name
= sam_entries
->entries
[i
].name
.string
;
2933 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2934 &&(strlen(name
)<=21)) {
2935 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2936 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2937 "username %s\n",count_sent
,p
));
2941 /* set overflow error */
2942 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2943 "username %s\n",count_sent
,name
));
2949 if (errflags
!= NERR_Success
) {
2953 TALLOC_FREE(sam_entries
);
2956 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2957 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2959 *rdata_len
= PTR_DIFF(p
,*rdata
);
2961 SSVAL(*rparam
,0,errflags
);
2962 SSVAL(*rparam
,2,0); /* converter word */
2963 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2964 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2969 /****************************************************************************
2970 Get the time of day info.
2971 ****************************************************************************/
2973 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2974 connection_struct
*conn
,uint64_t vuid
,
2975 char *param
, int tpscnt
,
2976 char *data
, int tdscnt
,
2977 int mdrcnt
,int mprcnt
,
2978 char **rdata
,char **rparam
,
2979 int *rdata_len
,int *rparam_len
)
2982 time_t unixdate
= time(NULL
);
2986 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2992 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2997 SSVAL(*rparam
,0,NERR_Success
);
2998 SSVAL(*rparam
,2,0); /* converter word */
3002 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
3003 by NT in a "net time" operation,
3004 it seems to ignore the one below */
3006 /* the client expects to get localtime, not GMT, in this bit
3007 (I think, this needs testing) */
3008 t
= localtime(&unixdate
);
3013 SIVAL(p
,4,0); /* msecs ? */
3014 SCVAL(p
,8,t
->tm_hour
);
3015 SCVAL(p
,9,t
->tm_min
);
3016 SCVAL(p
,10,t
->tm_sec
);
3017 SCVAL(p
,11,0); /* hundredths of seconds */
3018 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
3019 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
3020 SCVAL(p
,16,t
->tm_mday
);
3021 SCVAL(p
,17,t
->tm_mon
+ 1);
3022 SSVAL(p
,18,1900+t
->tm_year
);
3023 SCVAL(p
,20,t
->tm_wday
);
3028 /****************************************************************************
3029 Set the user password (SamOEM version - gets plaintext).
3030 ****************************************************************************/
3032 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3033 connection_struct
*conn
,uint64_t vuid
,
3034 char *param
, int tpscnt
,
3035 char *data
, int tdscnt
,
3036 int mdrcnt
,int mprcnt
,
3037 char **rdata
,char **rparam
,
3038 int *rdata_len
,int *rparam_len
)
3041 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3043 TALLOC_CTX
*mem_ctx
= talloc_tos();
3044 NTSTATUS status
, result
;
3045 struct rpc_pipe_client
*cli
= NULL
;
3046 struct lsa_AsciiString server
, account
;
3047 struct samr_CryptPassword password
;
3048 struct samr_Password hash
;
3049 int errcode
= NERR_badpass
;
3051 struct dcerpc_binding_handle
*b
;
3054 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3064 SSVAL(*rparam
,0,NERR_badpass
);
3067 * Check the parameter definition is correct.
3070 /* Do we have a string ? */
3071 if (skip_string(param
,tpscnt
,p
) == 0) {
3074 if(!strequal(p
, "zsT")) {
3075 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3078 p
= skip_string(param
, tpscnt
, p
);
3083 /* Do we have a string ? */
3084 if (skip_string(param
,tpscnt
,p
) == 0) {
3087 if(!strequal(p
, "B516B16")) {
3088 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3091 p
= skip_string(param
,tpscnt
,p
);
3095 /* Do we have a string ? */
3096 if (skip_string(param
,tpscnt
,p
) == 0) {
3099 p
+= pull_ascii_fstring(user
,p
);
3101 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3103 if (tdscnt
!= 532) {
3104 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3108 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3109 if (bufsize
!= 532) {
3110 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3114 memcpy(password
.data
, data
, 516);
3115 memcpy(hash
.hash
, data
+516, 16);
3117 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
3119 conn
->sconn
->remote_address
,
3120 conn
->sconn
->local_address
,
3121 conn
->sconn
->msg_ctx
,
3123 if (!NT_STATUS_IS_OK(status
)) {
3124 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3125 nt_errstr(status
)));
3126 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3130 b
= cli
->binding_handle
;
3132 init_lsa_AsciiString(&server
, lp_netbios_name());
3133 init_lsa_AsciiString(&account
, user
);
3135 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3141 if (!NT_STATUS_IS_OK(status
)) {
3142 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3145 if (!NT_STATUS_IS_OK(result
)) {
3146 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3150 errcode
= NERR_Success
;
3152 SSVAL(*rparam
,0,errcode
);
3153 SSVAL(*rparam
,2,0); /* converter word */
3158 /****************************************************************************
3161 ****************************************************************************/
3163 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3164 connection_struct
*conn
,uint64_t vuid
,
3165 char *param
, int tpscnt
,
3166 char *data
, int tdscnt
,
3167 int mdrcnt
,int mprcnt
,
3168 char **rdata
,char **rparam
,
3169 int *rdata_len
,int *rparam_len
)
3171 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3172 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3173 char *str2
= skip_string(param
,tpscnt
,str1
);
3174 char *p
= skip_string(param
,tpscnt
,str2
);
3178 WERROR werr
= WERR_OK
;
3180 TALLOC_CTX
*mem_ctx
= talloc_tos();
3182 struct rpc_pipe_client
*cli
= NULL
;
3183 struct dcerpc_binding_handle
*b
= NULL
;
3184 struct policy_handle handle
;
3185 struct spoolss_DevmodeContainer devmode_ctr
;
3186 enum spoolss_JobControl command
;
3188 if (!str1
|| !str2
|| !p
) {
3192 * We use 1 here not 2 as we're checking
3193 * the last byte we want to access is safe.
3195 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3198 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3201 /* check it's a supported varient */
3202 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3206 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3212 ZERO_STRUCT(handle
);
3214 status
= rpc_pipe_open_interface(mem_ctx
,
3217 conn
->sconn
->remote_address
,
3218 conn
->sconn
->local_address
,
3219 conn
->sconn
->msg_ctx
,
3221 if (!NT_STATUS_IS_OK(status
)) {
3222 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3223 nt_errstr(status
)));
3224 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3227 b
= cli
->binding_handle
;
3229 ZERO_STRUCT(devmode_ctr
);
3231 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3235 JOB_ACCESS_ADMINISTER
,
3238 if (!NT_STATUS_IS_OK(status
)) {
3239 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3242 if (!W_ERROR_IS_OK(werr
)) {
3243 errcode
= W_ERROR_V(werr
);
3247 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3248 * and NERR_DestNotFound if share did not exist */
3250 errcode
= NERR_Success
;
3253 case 81: /* delete */
3254 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3256 case 82: /* pause */
3257 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3259 case 83: /* resume */
3260 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3263 errcode
= NERR_notsupported
;
3267 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3270 NULL
, /* unique ptr ctr */
3273 if (!NT_STATUS_IS_OK(status
)) {
3274 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3277 if (!W_ERROR_IS_OK(werr
)) {
3278 errcode
= W_ERROR_V(werr
);
3283 if (b
&& is_valid_policy_hnd(&handle
)) {
3284 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3287 SSVAL(*rparam
,0,errcode
);
3288 SSVAL(*rparam
,2,0); /* converter word */
3293 /****************************************************************************
3294 Purge a print queue - or pause or resume it.
3295 ****************************************************************************/
3297 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3298 connection_struct
*conn
,uint64_t vuid
,
3299 char *param
, int tpscnt
,
3300 char *data
, int tdscnt
,
3301 int mdrcnt
,int mprcnt
,
3302 char **rdata
,char **rparam
,
3303 int *rdata_len
,int *rparam_len
)
3305 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3306 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3307 char *str2
= skip_string(param
,tpscnt
,str1
);
3308 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3309 int errcode
= NERR_notsupported
;
3310 WERROR werr
= WERR_OK
;
3313 TALLOC_CTX
*mem_ctx
= talloc_tos();
3314 struct rpc_pipe_client
*cli
= NULL
;
3315 struct dcerpc_binding_handle
*b
= NULL
;
3316 struct policy_handle handle
;
3317 struct spoolss_SetPrinterInfoCtr info_ctr
;
3318 struct spoolss_DevmodeContainer devmode_ctr
;
3319 struct sec_desc_buf secdesc_ctr
;
3320 enum spoolss_PrinterControl command
= SPOOLSS_PRINTER_CONTROL_UNPAUSE
;
3322 if (!str1
|| !str2
|| !QueueName
) {
3326 /* check it's a supported varient */
3327 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3331 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3337 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3341 ZERO_STRUCT(handle
);
3343 status
= rpc_pipe_open_interface(mem_ctx
,
3346 conn
->sconn
->remote_address
,
3347 conn
->sconn
->local_address
,
3348 conn
->sconn
->msg_ctx
,
3350 if (!NT_STATUS_IS_OK(status
)) {
3351 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3352 nt_errstr(status
)));
3353 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3356 b
= cli
->binding_handle
;
3358 ZERO_STRUCT(devmode_ctr
);
3360 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3364 PRINTER_ACCESS_ADMINISTER
,
3367 if (!NT_STATUS_IS_OK(status
)) {
3368 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3371 if (!W_ERROR_IS_OK(werr
)) {
3372 errcode
= W_ERROR_V(werr
);
3377 case 74: /* Pause queue */
3378 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3380 case 75: /* Resume queue */
3381 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3383 case 103: /* Purge */
3384 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3387 werr
= WERR_NOT_SUPPORTED
;
3391 if (!W_ERROR_IS_OK(werr
)) {
3392 errcode
= W_ERROR_V(werr
);
3396 ZERO_STRUCT(info_ctr
);
3397 ZERO_STRUCT(secdesc_ctr
);
3399 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3406 if (!NT_STATUS_IS_OK(status
)) {
3407 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3410 if (!W_ERROR_IS_OK(werr
)) {
3411 errcode
= W_ERROR_V(werr
);
3415 errcode
= W_ERROR_V(werr
);
3419 if (b
&& is_valid_policy_hnd(&handle
)) {
3420 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3423 SSVAL(*rparam
,0,errcode
);
3424 SSVAL(*rparam
,2,0); /* converter word */
3429 /****************************************************************************
3430 set the property of a print job (undocumented?)
3431 ? function = 0xb -> set name of print job
3432 ? function = 0x6 -> move print job up/down
3433 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3434 or <WWsTP> <WB21BB16B10zWWzDDz>
3435 ****************************************************************************/
3437 static int check_printjob_info(struct pack_desc
* desc
,
3438 int uLevel
, char* id
)
3440 desc
->subformat
= NULL
;
3442 case 0: desc
->format
= "W"; break;
3443 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3444 case 2: desc
->format
= "WWzWWDDzz"; break;
3445 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3446 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3448 DEBUG(0,("check_printjob_info: invalid level %d\n",
3452 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3453 DEBUG(0,("check_printjob_info: invalid format %s\n",
3454 id
? id
: "<NULL>" ));
3460 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3461 connection_struct
*conn
, uint64_t vuid
,
3462 char *param
, int tpscnt
,
3463 char *data
, int tdscnt
,
3464 int mdrcnt
,int mprcnt
,
3465 char **rdata
,char **rparam
,
3466 int *rdata_len
,int *rparam_len
)
3468 struct pack_desc desc
;
3469 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3470 char *str2
= skip_string(param
,tpscnt
,str1
);
3471 char *p
= skip_string(param
,tpscnt
,str2
);
3474 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3475 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3478 TALLOC_CTX
*mem_ctx
= talloc_tos();
3481 struct rpc_pipe_client
*cli
= NULL
;
3482 struct dcerpc_binding_handle
*b
= NULL
;
3483 struct policy_handle handle
;
3484 struct spoolss_DevmodeContainer devmode_ctr
;
3485 struct spoolss_JobInfoContainer ctr
;
3486 union spoolss_JobInfo info
;
3487 struct spoolss_SetJobInfo1 info1
;
3489 if (!str1
|| !str2
|| !p
) {
3493 * We use 1 here not 2 as we're checking
3494 * the last byte we want to access is safe.
3496 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3499 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3502 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3509 /* check it's a supported varient */
3510 if ((strcmp(str1
,"WWsTP")) ||
3511 (!check_printjob_info(&desc
,uLevel
,str2
)))
3514 errcode
= NERR_notsupported
;
3518 /* change print job name, data gives the name */
3524 ZERO_STRUCT(handle
);
3526 status
= rpc_pipe_open_interface(mem_ctx
,
3529 conn
->sconn
->remote_address
,
3530 conn
->sconn
->local_address
,
3531 conn
->sconn
->msg_ctx
,
3533 if (!NT_STATUS_IS_OK(status
)) {
3534 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3535 nt_errstr(status
)));
3536 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3539 b
= cli
->binding_handle
;
3541 ZERO_STRUCT(devmode_ctr
);
3543 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3550 if (!NT_STATUS_IS_OK(status
)) {
3551 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3554 if (!W_ERROR_IS_OK(werr
)) {
3555 errcode
= W_ERROR_V(werr
);
3559 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3565 if (!W_ERROR_IS_OK(werr
)) {
3566 errcode
= W_ERROR_V(werr
);
3572 info1
.job_id
= info
.info1
.job_id
;
3573 info1
.printer_name
= info
.info1
.printer_name
;
3574 info1
.user_name
= info
.info1
.user_name
;
3575 info1
.document_name
= data
;
3576 info1
.data_type
= info
.info1
.data_type
;
3577 info1
.text_status
= info
.info1
.text_status
;
3578 info1
.status
= info
.info1
.status
;
3579 info1
.priority
= info
.info1
.priority
;
3580 info1
.position
= info
.info1
.position
;
3581 info1
.total_pages
= info
.info1
.total_pages
;
3582 info1
.pages_printed
= info
.info1
.pages_printed
;
3583 info1
.submitted
= info
.info1
.submitted
;
3586 ctr
.info
.info1
= &info1
;
3588 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3594 if (!NT_STATUS_IS_OK(status
)) {
3595 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3598 if (!W_ERROR_IS_OK(werr
)) {
3599 errcode
= W_ERROR_V(werr
);
3603 errcode
= NERR_Success
;
3606 if (b
&& is_valid_policy_hnd(&handle
)) {
3607 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3610 SSVALS(*rparam
,0,errcode
);
3611 SSVAL(*rparam
,2,0); /* converter word */
3617 /****************************************************************************
3618 Get info about the server.
3619 ****************************************************************************/
3621 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3622 connection_struct
*conn
,uint64_t vuid
,
3623 char *param
, int tpscnt
,
3624 char *data
, int tdscnt
,
3625 int mdrcnt
,int mprcnt
,
3626 char **rdata
,char **rparam
,
3627 int *rdata_len
,int *rparam_len
)
3629 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3630 char *str2
= skip_string(param
,tpscnt
,str1
);
3631 char *p
= skip_string(param
,tpscnt
,str2
);
3632 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3638 TALLOC_CTX
*mem_ctx
= talloc_tos();
3639 struct rpc_pipe_client
*cli
= NULL
;
3640 union srvsvc_NetSrvInfo info
;
3642 struct dcerpc_binding_handle
*b
;
3644 if (!str1
|| !str2
|| !p
) {
3648 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3650 /* check it's a supported varient */
3651 if (!prefix_ok(str1
,"WrLh")) {
3657 if (strcmp(str2
,"B16") != 0) {
3663 if (strcmp(str2
,"B16BBDz") != 0) {
3669 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3675 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3681 if (strcmp(str2
,"DN") != 0) {
3687 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3696 *rdata_len
= mdrcnt
;
3697 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3703 p2
= p
+ struct_len
;
3705 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
3707 conn
->sconn
->remote_address
,
3708 conn
->sconn
->local_address
,
3709 conn
->sconn
->msg_ctx
,
3711 if (!NT_STATUS_IS_OK(status
)) {
3712 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3713 nt_errstr(status
)));
3714 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3718 b
= cli
->binding_handle
;
3720 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3725 if (!NT_STATUS_IS_OK(status
)) {
3726 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3729 if (!W_ERROR_IS_OK(werr
)) {
3730 errcode
= W_ERROR_V(werr
);
3734 if (info
.info101
== NULL
) {
3735 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3741 status
= srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3742 STR_ASCII
|STR_UPPER
|STR_TERMINATE
, &len
);
3743 if (!NT_STATUS_IS_OK(status
)) {
3744 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3750 SCVAL(p
,0,info
.info101
->version_major
);
3751 SCVAL(p
,1,info
.info101
->version_minor
);
3752 SIVAL(p
,2,info
.info101
->server_type
);
3754 if (mdrcnt
== struct_len
) {
3757 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3758 if (mdrcnt
- struct_len
<= 0) {
3762 info
.info101
->comment
,
3763 MIN(mdrcnt
- struct_len
,
3764 MAX_SERVER_STRING_LENGTH
),
3766 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3774 return False
; /* not yet implemented */
3777 errcode
= NERR_Success
;
3781 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3784 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3788 SSVAL(*rparam
,0,errcode
);
3789 SSVAL(*rparam
,2,0); /* converter word */
3790 SSVAL(*rparam
,4,*rdata_len
);
3795 /****************************************************************************
3796 Get info about the server.
3797 ****************************************************************************/
3799 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3800 connection_struct
*conn
,uint64_t vuid
,
3801 char *param
, int tpscnt
,
3802 char *data
, int tdscnt
,
3803 int mdrcnt
,int mprcnt
,
3804 char **rdata
,char **rparam
,
3805 int *rdata_len
,int *rparam_len
)
3807 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3808 char *str2
= skip_string(param
,tpscnt
,str1
);
3809 char *p
= skip_string(param
,tpscnt
,str2
);
3812 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3814 if (!str1
|| !str2
|| !p
) {
3818 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3821 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3826 /* check it's a supported varient */
3827 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3831 *rdata_len
= mdrcnt
+ 1024;
3832 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3837 SSVAL(*rparam
,0,NERR_Success
);
3838 SSVAL(*rparam
,2,0); /* converter word */
3841 endp
= *rdata
+ *rdata_len
;
3843 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3848 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3849 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3850 if (!strupper_m(p2
)) {
3853 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3859 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3860 strlcpy(p2
,conn
->session_info
->unix_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3861 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3867 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3868 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3869 if (!strupper_m(p2
)) {
3872 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3878 SCVAL(p
,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g 4 in 4.1 */
3879 SCVAL(p
,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g .1 in 4.1 */
3882 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3883 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3884 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3890 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3891 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3892 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3898 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3900 SSVAL(*rparam
,4,*rdata_len
);
3905 /****************************************************************************
3906 get info about a user
3908 struct user_info_11 {
3909 char usri11_name[21]; 0-20
3911 char *usri11_comment; 22-25
3912 char *usri11_usr_comment; 26-29
3913 unsigned short usri11_priv; 30-31
3914 unsigned long usri11_auth_flags; 32-35
3915 long usri11_password_age; 36-39
3916 char *usri11_homedir; 40-43
3917 char *usri11_parms; 44-47
3918 long usri11_last_logon; 48-51
3919 long usri11_last_logoff; 52-55
3920 unsigned short usri11_bad_pw_count; 56-57
3921 unsigned short usri11_num_logons; 58-59
3922 char *usri11_logon_server; 60-63
3923 unsigned short usri11_country_code; 64-65
3924 char *usri11_workstations; 66-69
3925 unsigned long usri11_max_storage; 70-73
3926 unsigned short usri11_units_per_week; 74-75
3927 unsigned char *usri11_logon_hours; 76-79
3928 unsigned short usri11_code_page; 80-81
3933 usri11_name specifies the user name for which information is retrieved
3935 usri11_pad aligns the next data structure element to a word boundary
3937 usri11_comment is a null terminated ASCII comment
3939 usri11_user_comment is a null terminated ASCII comment about the user
3941 usri11_priv specifies the level of the privilege assigned to the user.
3942 The possible values are:
3944 Name Value Description
3945 USER_PRIV_GUEST 0 Guest privilege
3946 USER_PRIV_USER 1 User privilege
3947 USER_PRV_ADMIN 2 Administrator privilege
3949 usri11_auth_flags specifies the account operator privileges. The
3950 possible values are:
3952 Name Value Description
3953 AF_OP_PRINT 0 Print operator
3956 Leach, Naik [Page 28]
3960 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3963 AF_OP_COMM 1 Communications operator
3964 AF_OP_SERVER 2 Server operator
3965 AF_OP_ACCOUNTS 3 Accounts operator
3968 usri11_password_age specifies how many seconds have elapsed since the
3969 password was last changed.
3971 usri11_home_dir points to a null terminated ASCII string that contains
3972 the path name of the user's home directory.
3974 usri11_parms points to a null terminated ASCII string that is set
3975 aside for use by applications.
3977 usri11_last_logon specifies the time when the user last logged on.
3978 This value is stored as the number of seconds elapsed since
3979 00:00:00, January 1, 1970.
3981 usri11_last_logoff specifies the time when the user last logged off.
3982 This value is stored as the number of seconds elapsed since
3983 00:00:00, January 1, 1970. A value of 0 means the last logoff
3986 usri11_bad_pw_count specifies the number of incorrect passwords
3987 entered since the last successful logon.
3989 usri11_log1_num_logons specifies the number of times this user has
3990 logged on. A value of -1 means the number of logons is unknown.
3992 usri11_logon_server points to a null terminated ASCII string that
3993 contains the name of the server to which logon requests are sent.
3994 A null string indicates logon requests should be sent to the
3997 usri11_country_code specifies the country code for the user's language
4000 usri11_workstations points to a null terminated ASCII string that
4001 contains the names of workstations the user may log on from.
4002 There may be up to 8 workstations, with the names separated by
4003 commas. A null strings indicates there are no restrictions.
4005 usri11_max_storage specifies the maximum amount of disk space the user
4006 can occupy. A value of 0xffffffff indicates there are no
4009 usri11_units_per_week specifies the equal number of time units into
4010 which a week is divided. This value must be equal to 168.
4012 usri11_logon_hours points to a 21 byte (168 bits) string that
4013 specifies the time during which the user can log on. Each bit
4014 represents one unique hour in a week. The first bit (bit 0, word
4015 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4019 Leach, Naik [Page 29]
4023 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4026 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4027 are no restrictions.
4029 usri11_code_page specifies the code page for the user's language of
4032 All of the pointers in this data structure need to be treated
4033 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4034 to be ignored. The converter word returned in the parameters section
4035 needs to be subtracted from the lower 16 bits to calculate an offset
4036 into the return buffer where this ASCII string resides.
4038 There is no auxiliary data in the response.
4040 ****************************************************************************/
4042 #define usri11_name 0
4043 #define usri11_pad 21
4044 #define usri11_comment 22
4045 #define usri11_usr_comment 26
4046 #define usri11_full_name 30
4047 #define usri11_priv 34
4048 #define usri11_auth_flags 36
4049 #define usri11_password_age 40
4050 #define usri11_homedir 44
4051 #define usri11_parms 48
4052 #define usri11_last_logon 52
4053 #define usri11_last_logoff 56
4054 #define usri11_bad_pw_count 60
4055 #define usri11_num_logons 62
4056 #define usri11_logon_server 64
4057 #define usri11_country_code 68
4058 #define usri11_workstations 70
4059 #define usri11_max_storage 74
4060 #define usri11_units_per_week 78
4061 #define usri11_logon_hours 80
4062 #define usri11_code_page 84
4063 #define usri11_end 86
4065 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4066 connection_struct
*conn
, uint64_t vuid
,
4067 char *param
, int tpscnt
,
4068 char *data
, int tdscnt
,
4069 int mdrcnt
,int mprcnt
,
4070 char **rdata
,char **rparam
,
4071 int *rdata_len
,int *rparam_len
)
4073 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4074 char *str2
= skip_string(param
,tpscnt
,str1
);
4075 char *UserName
= skip_string(param
,tpscnt
,str2
);
4076 char *p
= skip_string(param
,tpscnt
,UserName
);
4077 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4080 const char *level_string
;
4082 TALLOC_CTX
*mem_ctx
= talloc_tos();
4083 NTSTATUS status
, result
;
4084 struct rpc_pipe_client
*cli
= NULL
;
4085 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4086 struct lsa_String domain_name
;
4087 struct dom_sid2
*domain_sid
;
4088 struct lsa_String names
;
4089 struct samr_Ids rids
;
4090 struct samr_Ids types
;
4091 int errcode
= W_ERROR_V(WERR_NERR_USERNOTFOUND
);
4093 union samr_UserInfo
*info
;
4094 struct dcerpc_binding_handle
*b
= NULL
;
4096 if (!str1
|| !str2
|| !UserName
|| !p
) {
4101 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4106 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4108 /* check it's a supported variant */
4109 if (strcmp(str1
,"zWrLh") != 0) {
4113 case 0: level_string
= "B21"; break;
4114 case 1: level_string
= "B21BB16DWzzWz"; break;
4115 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4116 case 10: level_string
= "B21Bzzz"; break;
4117 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4118 default: return False
;
4121 if (strcmp(level_string
,str2
) != 0) {
4125 *rdata_len
= mdrcnt
+ 1024;
4126 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4132 endp
= *rdata
+ *rdata_len
;
4133 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4138 ZERO_STRUCT(connect_handle
);
4139 ZERO_STRUCT(domain_handle
);
4140 ZERO_STRUCT(user_handle
);
4142 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
4144 conn
->sconn
->remote_address
,
4145 conn
->sconn
->local_address
,
4146 conn
->sconn
->msg_ctx
,
4148 if (!NT_STATUS_IS_OK(status
)) {
4149 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4150 nt_errstr(status
)));
4151 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4155 b
= cli
->binding_handle
;
4157 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4159 SAMR_ACCESS_CONNECT_TO_SERVER
|
4160 SAMR_ACCESS_ENUM_DOMAINS
|
4161 SAMR_ACCESS_LOOKUP_DOMAIN
,
4164 if (!NT_STATUS_IS_OK(status
)) {
4165 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4168 if (!NT_STATUS_IS_OK(result
)) {
4169 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4173 init_lsa_String(&domain_name
, get_global_sam_name());
4175 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4180 if (!NT_STATUS_IS_OK(status
)) {
4181 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4184 if (!NT_STATUS_IS_OK(result
)) {
4185 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4189 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4191 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4195 if (!NT_STATUS_IS_OK(status
)) {
4196 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4199 if (!NT_STATUS_IS_OK(result
)) {
4200 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4204 init_lsa_String(&names
, UserName
);
4206 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4213 if (!NT_STATUS_IS_OK(status
)) {
4214 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4217 if (!NT_STATUS_IS_OK(result
)) {
4218 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4222 if (rids
.count
!= 1) {
4223 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4226 if (rids
.count
!= types
.count
) {
4227 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4230 if (types
.ids
[0] != SID_NAME_USER
) {
4231 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4237 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4239 SAMR_USER_ACCESS_GET_LOCALE
|
4240 SAMR_USER_ACCESS_GET_LOGONINFO
|
4241 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4242 SAMR_USER_ACCESS_GET_GROUPS
|
4243 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4244 SEC_STD_READ_CONTROL
,
4248 if (!NT_STATUS_IS_OK(status
)) {
4249 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4252 if (!NT_STATUS_IS_OK(result
)) {
4253 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4257 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4262 if (!NT_STATUS_IS_OK(status
)) {
4263 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4266 if (!NT_STATUS_IS_OK(result
)) {
4267 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4272 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4275 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4280 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4281 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4282 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4287 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4288 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4289 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4294 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4295 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4296 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4297 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4304 const char *homedir
= info
->info21
.home_directory
.string
;
4305 /* modelled after NTAS 3.51 reply */
4306 SSVAL(p
,usri11_priv
,
4307 (get_current_uid(conn
) == sec_initial_uid())?
4308 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4309 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4310 SIVALS(p
,usri11_password_age
,-1); /* password age */
4311 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4312 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4313 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4317 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4318 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4319 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4323 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4324 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4325 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4326 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4327 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4328 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4329 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4333 SSVAL(p
,usri11_country_code
,0); /* country code */
4335 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4336 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4337 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4342 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4343 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4344 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4346 /* a simple way to get logon hours at all times. */
4348 SCVAL(p2
,21,0); /* fix zero termination */
4349 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4354 SSVAL(p
,usri11_code_page
,0); /* code page */
4357 if (uLevel
== 1 || uLevel
== 2) {
4358 memset(p
+22,' ',16); /* password */
4359 SIVALS(p
,38,-1); /* password age */
4361 (get_current_uid(conn
) == sec_initial_uid())?
4362 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4363 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4364 strlcpy(p2
, info
->info21
.home_directory
.string
,
4366 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4370 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4372 SSVAL(p
,52,0); /* flags */
4373 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4374 strlcpy(p2
, info
->info21
.logon_script
.string
,
4376 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4381 SIVAL(p
,58,0); /* auth_flags */
4382 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4383 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4384 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4388 SIVAL(p
,66,0); /* urs_comment */
4389 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4390 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4391 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4395 SIVAL(p
,74,0); /* workstations */
4396 SIVAL(p
,78,0); /* last_logon */
4397 SIVAL(p
,82,0); /* last_logoff */
4398 SIVALS(p
,86,-1); /* acct_expires */
4399 SIVALS(p
,90,-1); /* max_storage */
4400 SSVAL(p
,94,168); /* units_per_week */
4401 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4404 SSVALS(p
,100,-1); /* bad_pw_count */
4405 SSVALS(p
,102,-1); /* num_logons */
4406 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4408 TALLOC_CTX
*ctx
= talloc_tos();
4409 int space_rem
= *rdata_len
- (p2
- *rdata
);
4412 if (space_rem
<= 0) {
4415 tmp
= talloc_strdup(ctx
, "\\\\%L");
4419 tmp
= talloc_sub_basic(ctx
,
4432 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4436 SSVAL(p
,108,49); /* country_code */
4437 SSVAL(p
,110,860); /* code page */
4441 errcode
= NERR_Success
;
4444 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4446 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4447 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4449 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4450 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4452 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4453 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4456 SSVAL(*rparam
,0,errcode
);
4457 SSVAL(*rparam
,2,0); /* converter word */
4458 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4463 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4464 connection_struct
*conn
,uint64_t vuid
,
4465 char *param
, int tpscnt
,
4466 char *data
, int tdscnt
,
4467 int mdrcnt
,int mprcnt
,
4468 char **rdata
,char **rparam
,
4469 int *rdata_len
,int *rparam_len
)
4471 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4472 char *str2
= skip_string(param
,tpscnt
,str1
);
4473 char *p
= skip_string(param
,tpscnt
,str2
);
4475 struct pack_desc desc
;
4477 struct auth_session_info
*si
= NULL
;
4480 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
4483 if (!NT_STATUS_IS_OK(status
)) {
4487 if (!str1
|| !str2
|| !p
) {
4491 DBG_INFO("Username of UID %ju is %s\n",
4492 (uintmax_t)si
->unix_token
->uid
,
4493 si
->unix_info
->unix_name
);
4495 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4496 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4501 memset((char *)&desc
,'\0',sizeof(desc
));
4503 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4505 /* check it's a supported varient */
4506 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4509 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4513 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4520 desc
.buflen
= mdrcnt
;
4521 desc
.subformat
= NULL
;
4524 if (init_package(&desc
,1,0)) {
4525 PACKI(&desc
,"W",0); /* code */
4526 PACKS(&desc
,"B21",name
); /* eff. name */
4527 PACKS(&desc
,"B",""); /* pad */
4529 (get_current_uid(conn
) == sec_initial_uid())?
4530 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4531 PACKI(&desc
,"D",0); /* auth flags XXX */
4532 PACKI(&desc
,"W",0); /* num logons */
4533 PACKI(&desc
,"W",0); /* bad pw count */
4534 PACKI(&desc
,"D",0); /* last logon */
4535 PACKI(&desc
,"D",-1); /* last logoff */
4536 PACKI(&desc
,"D",-1); /* logoff time */
4537 PACKI(&desc
,"D",-1); /* kickoff time */
4538 PACKI(&desc
,"D",0); /* password age */
4539 PACKI(&desc
,"D",0); /* password can change */
4540 PACKI(&desc
,"D",-1); /* password must change */
4544 fstrcpy(mypath
,"\\\\");
4545 fstrcat(mypath
,get_local_machine_name());
4546 if (!strupper_m(mypath
)) {
4549 PACKS(&desc
,"z",mypath
); /* computer */
4552 PACKS(&desc
,"z",lp_workgroup());/* domain */
4553 PACKS(&desc
,"z", si
->info
->logon_script
); /* script path */
4554 PACKI(&desc
,"D",0x00000000); /* reserved */
4557 *rdata_len
= desc
.usedlen
;
4559 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4563 SSVALS(*rparam
,0,desc
.errcode
);
4565 SSVAL(*rparam
,4,desc
.neededlen
);
4567 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4572 /****************************************************************************
4573 api_WAccessGetUserPerms
4574 ****************************************************************************/
4576 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4577 connection_struct
*conn
,uint64_t vuid
,
4578 char *param
, int tpscnt
,
4579 char *data
, int tdscnt
,
4580 int mdrcnt
,int mprcnt
,
4581 char **rdata
,char **rparam
,
4582 int *rdata_len
,int *rparam_len
)
4584 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4585 char *str2
= skip_string(param
,tpscnt
,str1
);
4586 char *user
= skip_string(param
,tpscnt
,str2
);
4587 char *resource
= skip_string(param
,tpscnt
,user
);
4589 if (!str1
|| !str2
|| !user
|| !resource
) {
4593 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4596 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4598 /* check it's a supported varient */
4599 if (strcmp(str1
,"zzh") != 0) {
4602 if (strcmp(str2
,"") != 0) {
4607 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4611 SSVALS(*rparam
,0,0); /* errorcode */
4612 SSVAL(*rparam
,2,0); /* converter word */
4613 SSVAL(*rparam
,4,0x7f); /* permission flags */
4618 /****************************************************************************
4619 api_WPrintJobEnumerate
4620 ****************************************************************************/
4622 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4623 connection_struct
*conn
, uint64_t vuid
,
4624 char *param
, int tpscnt
,
4625 char *data
, int tdscnt
,
4626 int mdrcnt
,int mprcnt
,
4627 char **rdata
,char **rparam
,
4628 int *rdata_len
,int *rparam_len
)
4630 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4631 char *str2
= skip_string(param
,tpscnt
,str1
);
4632 char *p
= skip_string(param
,tpscnt
,str2
);
4636 struct pack_desc desc
;
4639 TALLOC_CTX
*mem_ctx
= talloc_tos();
4642 struct rpc_pipe_client
*cli
= NULL
;
4643 struct dcerpc_binding_handle
*b
= NULL
;
4644 struct policy_handle handle
;
4645 struct spoolss_DevmodeContainer devmode_ctr
;
4646 union spoolss_JobInfo info
;
4648 if (!str1
|| !str2
|| !p
) {
4652 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4654 memset((char *)&desc
,'\0',sizeof(desc
));
4655 memset((char *)&status
,'\0',sizeof(status
));
4657 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4659 /* check it's a supported varient */
4660 if (strcmp(str1
,"WWrLh") != 0) {
4663 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4667 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4671 ZERO_STRUCT(handle
);
4673 status
= rpc_pipe_open_interface(mem_ctx
,
4676 conn
->sconn
->remote_address
,
4677 conn
->sconn
->local_address
,
4678 conn
->sconn
->msg_ctx
,
4680 if (!NT_STATUS_IS_OK(status
)) {
4681 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4682 nt_errstr(status
)));
4683 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4686 b
= cli
->binding_handle
;
4688 ZERO_STRUCT(devmode_ctr
);
4690 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4697 if (!NT_STATUS_IS_OK(status
)) {
4698 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4701 if (!W_ERROR_IS_OK(werr
)) {
4702 desc
.errcode
= W_ERROR_V(werr
);
4706 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4712 if (!W_ERROR_IS_OK(werr
)) {
4713 desc
.errcode
= W_ERROR_V(werr
);
4718 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4723 desc
.buflen
= mdrcnt
;
4726 * Don't return data but need to get correct length
4727 * init_package will return wrong size if buflen=0
4729 desc
.buflen
= getlen(desc
.format
);
4730 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4733 if (init_package(&desc
,1,0)) {
4734 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4735 *rdata_len
= desc
.usedlen
;
4737 desc
.errcode
= NERR_JobNotFound
;
4741 if (b
&& is_valid_policy_hnd(&handle
)) {
4742 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4746 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4750 SSVALS(*rparam
,0,desc
.errcode
);
4752 SSVAL(*rparam
,4,desc
.neededlen
);
4756 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4761 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4762 connection_struct
*conn
, uint64_t vuid
,
4763 char *param
, int tpscnt
,
4764 char *data
, int tdscnt
,
4765 int mdrcnt
,int mprcnt
,
4766 char **rdata
,char **rparam
,
4767 int *rdata_len
,int *rparam_len
)
4769 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4770 char *str2
= skip_string(param
,tpscnt
,str1
);
4771 char *p
= skip_string(param
,tpscnt
,str2
);
4775 struct pack_desc desc
;
4777 TALLOC_CTX
*mem_ctx
= talloc_tos();
4780 struct rpc_pipe_client
*cli
= NULL
;
4781 struct dcerpc_binding_handle
*b
= NULL
;
4782 struct policy_handle handle
;
4783 struct spoolss_DevmodeContainer devmode_ctr
;
4785 union spoolss_JobInfo
*info
;
4787 if (!str1
|| !str2
|| !p
) {
4791 memset((char *)&desc
,'\0',sizeof(desc
));
4793 p
= skip_string(param
,tpscnt
,p
);
4797 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4799 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4801 /* check it's a supported variant */
4802 if (strcmp(str1
,"zWrLeh") != 0) {
4807 return False
; /* defined only for uLevel 0,1,2 */
4810 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4814 ZERO_STRUCT(handle
);
4816 status
= rpc_pipe_open_interface(mem_ctx
,
4819 conn
->sconn
->remote_address
,
4820 conn
->sconn
->local_address
,
4821 conn
->sconn
->msg_ctx
,
4823 if (!NT_STATUS_IS_OK(status
)) {
4824 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4825 nt_errstr(status
)));
4826 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4829 b
= cli
->binding_handle
;
4831 ZERO_STRUCT(devmode_ctr
);
4833 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4840 if (!NT_STATUS_IS_OK(status
)) {
4841 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4844 if (!W_ERROR_IS_OK(werr
)) {
4845 desc
.errcode
= W_ERROR_V(werr
);
4849 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4857 if (!W_ERROR_IS_OK(werr
)) {
4858 desc
.errcode
= W_ERROR_V(werr
);
4863 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4869 desc
.buflen
= mdrcnt
;
4871 if (init_package(&desc
,count
,0)) {
4873 for (i
= 0; i
< count
; i
++) {
4874 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4875 if (desc
.errcode
== NERR_Success
) {
4881 if (b
&& is_valid_policy_hnd(&handle
)) {
4882 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4885 *rdata_len
= desc
.usedlen
;
4888 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4892 SSVALS(*rparam
,0,desc
.errcode
);
4894 SSVAL(*rparam
,4,succnt
);
4895 SSVAL(*rparam
,6,count
);
4897 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4902 static int check_printdest_info(struct pack_desc
* desc
,
4903 int uLevel
, char* id
)
4905 desc
->subformat
= NULL
;
4908 desc
->format
= "B9";
4911 desc
->format
= "B9B21WWzW";
4917 desc
->format
= "zzzWWzzzWW";
4920 DEBUG(0,("check_printdest_info: invalid level %d\n",
4924 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4925 DEBUG(0,("check_printdest_info: invalid string %s\n",
4926 id
? id
: "<NULL>" ));
4932 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4933 struct pack_desc
* desc
)
4937 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4938 buf
[sizeof(buf
)-1] = 0;
4939 (void)strupper_m(buf
);
4942 PACKS(desc
,"B9",buf
); /* szName */
4944 PACKS(desc
,"B21",""); /* szUserName */
4945 PACKI(desc
,"W",0); /* uJobId */
4946 PACKI(desc
,"W",0); /* fsStatus */
4947 PACKS(desc
,"z",""); /* pszStatus */
4948 PACKI(desc
,"W",0); /* time */
4952 if (uLevel
== 2 || uLevel
== 3) {
4953 PACKS(desc
,"z",buf
); /* pszPrinterName */
4955 PACKS(desc
,"z",""); /* pszUserName */
4956 PACKS(desc
,"z",""); /* pszLogAddr */
4957 PACKI(desc
,"W",0); /* uJobId */
4958 PACKI(desc
,"W",0); /* fsStatus */
4959 PACKS(desc
,"z",""); /* pszStatus */
4960 PACKS(desc
,"z",""); /* pszComment */
4961 PACKS(desc
,"z","NULL"); /* pszDrivers */
4962 PACKI(desc
,"W",0); /* time */
4963 PACKI(desc
,"W",0); /* pad1 */
4968 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4969 connection_struct
*conn
, uint64_t vuid
,
4970 char *param
, int tpscnt
,
4971 char *data
, int tdscnt
,
4972 int mdrcnt
,int mprcnt
,
4973 char **rdata
,char **rparam
,
4974 int *rdata_len
,int *rparam_len
)
4976 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4977 char *str2
= skip_string(param
,tpscnt
,str1
);
4978 char *p
= skip_string(param
,tpscnt
,str2
);
4979 char* PrinterName
= p
;
4981 struct pack_desc desc
;
4984 TALLOC_CTX
*mem_ctx
= talloc_tos();
4987 struct rpc_pipe_client
*cli
= NULL
;
4988 struct dcerpc_binding_handle
*b
= NULL
;
4989 struct policy_handle handle
;
4990 struct spoolss_DevmodeContainer devmode_ctr
;
4991 union spoolss_PrinterInfo info
;
4993 if (!str1
|| !str2
|| !p
) {
4997 memset((char *)&desc
,'\0',sizeof(desc
));
4999 p
= skip_string(param
,tpscnt
,p
);
5003 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5005 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
5007 /* check it's a supported varient */
5008 if (strcmp(str1
,"zWrLh") != 0) {
5011 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5015 ZERO_STRUCT(handle
);
5017 status
= rpc_pipe_open_interface(mem_ctx
,
5020 conn
->sconn
->remote_address
,
5021 conn
->sconn
->local_address
,
5022 conn
->sconn
->msg_ctx
,
5024 if (!NT_STATUS_IS_OK(status
)) {
5025 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5026 nt_errstr(status
)));
5027 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5030 b
= cli
->binding_handle
;
5032 ZERO_STRUCT(devmode_ctr
);
5034 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5041 if (!NT_STATUS_IS_OK(status
)) {
5043 desc
.errcode
= NERR_DestNotFound
;
5047 if (!W_ERROR_IS_OK(werr
)) {
5049 desc
.errcode
= NERR_DestNotFound
;
5054 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5059 if (!W_ERROR_IS_OK(werr
)) {
5061 desc
.errcode
= NERR_DestNotFound
;
5067 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5072 desc
.buflen
= mdrcnt
;
5075 * Don't return data but need to get correct length
5076 * init_package will return wrong size if buflen=0
5078 desc
.buflen
= getlen(desc
.format
);
5079 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5081 if (init_package(&desc
,1,0)) {
5082 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5086 if (b
&& is_valid_policy_hnd(&handle
)) {
5087 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5090 *rdata_len
= desc
.usedlen
;
5093 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5097 SSVALS(*rparam
,0,desc
.errcode
);
5099 SSVAL(*rparam
,4,desc
.neededlen
);
5101 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5107 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5108 connection_struct
*conn
, uint64_t vuid
,
5109 char *param
, int tpscnt
,
5110 char *data
, int tdscnt
,
5111 int mdrcnt
,int mprcnt
,
5112 char **rdata
,char **rparam
,
5113 int *rdata_len
,int *rparam_len
)
5115 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5116 char *str2
= skip_string(param
,tpscnt
,str1
);
5117 char *p
= skip_string(param
,tpscnt
,str2
);
5121 struct pack_desc desc
;
5123 TALLOC_CTX
*mem_ctx
= talloc_tos();
5126 struct rpc_pipe_client
*cli
= NULL
;
5127 union spoolss_PrinterInfo
*info
;
5130 if (!str1
|| !str2
|| !p
) {
5134 memset((char *)&desc
,'\0',sizeof(desc
));
5136 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5138 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5140 /* check it's a supported varient */
5141 if (strcmp(str1
,"WrLeh") != 0) {
5144 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5150 status
= rpc_pipe_open_interface(mem_ctx
,
5153 conn
->sconn
->remote_address
,
5154 conn
->sconn
->local_address
,
5155 conn
->sconn
->msg_ctx
,
5157 if (!NT_STATUS_IS_OK(status
)) {
5158 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5159 nt_errstr(status
)));
5160 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5164 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5166 cli
->srv_name_slash
,
5171 if (!W_ERROR_IS_OK(werr
)) {
5172 desc
.errcode
= W_ERROR_V(werr
);
5174 desc
.errcode
= NERR_DestNotFound
;
5182 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5189 desc
.buflen
= mdrcnt
;
5190 if (init_package(&desc
,queuecnt
,0)) {
5193 for (i
= 0; i
< count
; i
++) {
5194 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5196 if (desc
.errcode
== NERR_Success
) {
5202 *rdata_len
= desc
.usedlen
;
5205 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5209 SSVALS(*rparam
,0,desc
.errcode
);
5211 SSVAL(*rparam
,4,succnt
);
5212 SSVAL(*rparam
,6,queuecnt
);
5214 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5219 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5220 connection_struct
*conn
, uint64_t vuid
,
5221 char *param
, int tpscnt
,
5222 char *data
, int tdscnt
,
5223 int mdrcnt
,int mprcnt
,
5224 char **rdata
,char **rparam
,
5225 int *rdata_len
,int *rparam_len
)
5227 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5228 char *str2
= skip_string(param
,tpscnt
,str1
);
5229 char *p
= skip_string(param
,tpscnt
,str2
);
5232 struct pack_desc desc
;
5234 if (!str1
|| !str2
|| !p
) {
5238 memset((char *)&desc
,'\0',sizeof(desc
));
5240 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5242 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5244 /* check it's a supported varient */
5245 if (strcmp(str1
,"WrLeh") != 0) {
5248 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5253 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5259 desc
.buflen
= mdrcnt
;
5260 if (init_package(&desc
,1,0)) {
5261 PACKS(&desc
,"B41","NULL");
5264 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5266 *rdata_len
= desc
.usedlen
;
5269 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5273 SSVALS(*rparam
,0,desc
.errcode
);
5275 SSVAL(*rparam
,4,succnt
);
5278 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5283 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5284 connection_struct
*conn
, uint64_t vuid
,
5285 char *param
, int tpscnt
,
5286 char *data
, int tdscnt
,
5287 int mdrcnt
,int mprcnt
,
5288 char **rdata
,char **rparam
,
5289 int *rdata_len
,int *rparam_len
)
5291 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5292 char *str2
= skip_string(param
,tpscnt
,str1
);
5293 char *p
= skip_string(param
,tpscnt
,str2
);
5296 struct pack_desc desc
;
5298 if (!str1
|| !str2
|| !p
) {
5301 memset((char *)&desc
,'\0',sizeof(desc
));
5303 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5305 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5307 /* check it's a supported varient */
5308 if (strcmp(str1
,"WrLeh") != 0) {
5311 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5316 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5322 desc
.buflen
= mdrcnt
;
5324 if (init_package(&desc
,1,0)) {
5325 PACKS(&desc
,"B13","lpd");
5328 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5330 *rdata_len
= desc
.usedlen
;
5333 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5337 SSVALS(*rparam
,0,desc
.errcode
);
5339 SSVAL(*rparam
,4,succnt
);
5342 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5347 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5348 connection_struct
*conn
, uint64_t vuid
,
5349 char *param
, int tpscnt
,
5350 char *data
, int tdscnt
,
5351 int mdrcnt
,int mprcnt
,
5352 char **rdata
,char **rparam
,
5353 int *rdata_len
,int *rparam_len
)
5355 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5356 char *str2
= skip_string(param
,tpscnt
,str1
);
5357 char *p
= skip_string(param
,tpscnt
,str2
);
5360 struct pack_desc desc
;
5362 if (!str1
|| !str2
|| !p
) {
5366 memset((char *)&desc
,'\0',sizeof(desc
));
5368 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5370 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5372 /* check it's a supported varient */
5373 if (strcmp(str1
,"WrLeh") != 0) {
5376 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5381 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5386 memset((char *)&desc
,'\0',sizeof(desc
));
5388 desc
.buflen
= mdrcnt
;
5390 if (init_package(&desc
,1,0)) {
5391 PACKS(&desc
,"B13","lp0");
5394 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5396 *rdata_len
= desc
.usedlen
;
5399 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5403 SSVALS(*rparam
,0,desc
.errcode
);
5405 SSVAL(*rparam
,4,succnt
);
5408 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5413 /****************************************************************************
5415 ****************************************************************************/
5417 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5418 connection_struct
*conn
, uint64_t vuid
,
5419 char *param
, int tpscnt
,
5420 char *data
, int tdscnt
,
5421 int mdrcnt
,int mprcnt
,
5422 char **rdata
,char **rparam
,
5423 int *rdata_len
,int *rparam_len
)
5426 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5427 char *str2
= skip_string(param
,tpscnt
,str1
);
5428 char *p
= skip_string(param
,tpscnt
,str2
);
5430 struct pack_desc desc
;
5433 TALLOC_CTX
*mem_ctx
= talloc_tos();
5436 struct rpc_pipe_client
*cli
= NULL
;
5437 struct dcerpc_binding_handle
*b
= NULL
;
5438 struct srvsvc_NetSessInfoCtr info_ctr
;
5439 uint32_t totalentries
, resume_handle
= 0;
5442 if (!str1
|| !str2
|| !p
) {
5448 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5450 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5451 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5452 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5454 /* check it's a supported varient */
5455 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5458 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5462 status
= rpc_pipe_open_interface(mem_ctx
,
5465 conn
->sconn
->remote_address
,
5466 conn
->sconn
->local_address
,
5467 conn
->sconn
->msg_ctx
,
5469 if (!NT_STATUS_IS_OK(status
)) {
5470 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5471 nt_errstr(status
)));
5472 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5475 b
= cli
->binding_handle
;
5478 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5479 if (info_ctr
.ctr
.ctr1
== NULL
) {
5480 desc
.errcode
= W_ERROR_V(WERR_NOT_ENOUGH_MEMORY
);
5484 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5485 cli
->srv_name_slash
,
5489 (uint32_t)-1, /* max_buffer */
5493 if (!NT_STATUS_IS_OK(status
)) {
5494 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5495 nt_errstr(status
)));
5496 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5500 if (!W_ERROR_IS_OK(werr
)) {
5501 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5503 desc
.errcode
= W_ERROR_V(werr
);
5507 count
= info_ctr
.ctr
.ctr1
->count
;
5511 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5518 desc
.buflen
= mdrcnt
;
5520 if (!init_package(&desc
, count
,0)) {
5524 for(i
=0; i
< count
; i
++) {
5525 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5526 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5527 PACKI(&desc
, "W", 1); /* num conns */
5528 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5529 PACKI(&desc
, "W", 1); /* num users */
5530 PACKI(&desc
, "D", 0); /* session time */
5531 PACKI(&desc
, "D", 0); /* idle time */
5532 PACKI(&desc
, "D", 0); /* flags */
5533 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5536 *rdata_len
= desc
.usedlen
;
5539 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5543 SSVALS(*rparam
,0,desc
.errcode
);
5544 SSVAL(*rparam
,2,0); /* converter */
5545 SSVAL(*rparam
,4, count
); /* count */
5547 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5553 /****************************************************************************
5554 The buffer was too small.
5555 ****************************************************************************/
5557 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5558 connection_struct
*conn
,uint64_t vuid
, char *param
, char *data
,
5559 int mdrcnt
, int mprcnt
,
5560 char **rdata
, char **rparam
,
5561 int *rdata_len
, int *rparam_len
)
5563 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5564 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5571 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5573 DEBUG(3,("Supplied buffer too small in API command\n"));
5578 /****************************************************************************
5579 The request is not supported.
5580 ****************************************************************************/
5582 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5583 connection_struct
*conn
, uint64_t vuid
,
5584 char *param
, int tpscnt
,
5585 char *data
, int tdscnt
,
5586 int mdrcnt
, int mprcnt
,
5587 char **rdata
, char **rparam
,
5588 int *rdata_len
, int *rparam_len
)
5591 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5598 SSVAL(*rparam
,0,NERR_notsupported
);
5599 SSVAL(*rparam
,2,0); /* converter word */
5601 DEBUG(3,("Unsupported API command\n"));
5606 static const struct {
5609 bool (*fn
)(struct smbd_server_connection
*sconn
,
5610 connection_struct
*, uint64_t,
5613 int,int,char **,char **,int *,int *);
5614 bool auth_user
; /* Deny anonymous access? */
5615 } api_commands
[] = {
5617 .name
= "RNetShareEnum",
5618 .id
= RAP_WshareEnum
,
5619 .fn
= api_RNetShareEnum
,
5623 .name
= "RNetShareGetInfo",
5624 .id
= RAP_WshareGetInfo
,
5625 .fn
= api_RNetShareGetInfo
5628 .name
= "RNetShareAdd",
5629 .id
= RAP_WshareAdd
,
5630 .fn
= api_RNetShareAdd
5633 .name
= "RNetSessionEnum",
5634 .id
= RAP_WsessionEnum
,
5635 .fn
= api_RNetSessionEnum
,
5639 .name
= "RNetServerGetInfo",
5640 .id
= RAP_WserverGetInfo
,
5641 .fn
= api_RNetServerGetInfo
5644 .name
= "RNetGroupEnum",
5645 .id
= RAP_WGroupEnum
,
5646 .fn
= api_RNetGroupEnum
, True
5649 .name
= "RNetGroupGetUsers",
5650 .id
= RAP_WGroupGetUsers
,
5651 .fn
= api_RNetGroupGetUsers
,
5654 .name
= "RNetUserEnum",
5655 .id
= RAP_WUserEnum
,
5656 .fn
= api_RNetUserEnum
,
5660 .name
= "RNetUserGetInfo",
5661 .id
= RAP_WUserGetInfo
,
5662 .fn
= api_RNetUserGetInfo
5665 .name
= "NetUserGetGroups",
5666 .id
= RAP_WUserGetGroups
,
5667 .fn
= api_NetUserGetGroups
5670 .name
= "NetWkstaGetInfo",
5671 .id
= RAP_WWkstaGetInfo
,
5672 .fn
= api_NetWkstaGetInfo
5675 .name
= "DosPrintQEnum",
5676 .id
= RAP_WPrintQEnum
,
5677 .fn
= api_DosPrintQEnum
,
5681 .name
= "DosPrintQGetInfo",
5682 .id
= RAP_WPrintQGetInfo
,
5683 .fn
= api_DosPrintQGetInfo
5686 .name
= "WPrintQueuePause",
5687 .id
= RAP_WPrintQPause
,
5688 .fn
= api_WPrintQueueCtrl
5691 .name
= "WPrintQueueResume",
5692 .id
= RAP_WPrintQContinue
,
5693 .fn
= api_WPrintQueueCtrl
5696 .name
= "WPrintJobEnumerate",
5697 .id
= RAP_WPrintJobEnum
,
5698 .fn
= api_WPrintJobEnumerate
5701 .name
= "WPrintJobGetInfo",
5702 .id
= RAP_WPrintJobGetInfo
,
5703 .fn
= api_WPrintJobGetInfo
5706 .name
= "RDosPrintJobDel",
5707 .id
= RAP_WPrintJobDel
,
5708 .fn
= api_RDosPrintJobDel
5711 .name
= "RDosPrintJobPause",
5712 .id
= RAP_WPrintJobPause
,
5713 .fn
= api_RDosPrintJobDel
5716 .name
= "RDosPrintJobResume",
5717 .id
= RAP_WPrintJobContinue
,
5718 .fn
= api_RDosPrintJobDel
5721 .name
= "WPrintDestEnum",
5722 .id
= RAP_WPrintDestEnum
,
5723 .fn
= api_WPrintDestEnum
5726 .name
= "WPrintDestGetInfo",
5727 .id
= RAP_WPrintDestGetInfo
,
5728 .fn
= api_WPrintDestGetInfo
5731 .name
= "NetRemoteTOD",
5732 .id
= RAP_NetRemoteTOD
,
5733 .fn
= api_NetRemoteTOD
5736 .name
= "WPrintQueuePurge",
5737 .id
= RAP_WPrintQPurge
,
5738 .fn
= api_WPrintQueueCtrl
5741 .name
= "NetServerEnum2",
5742 .id
= RAP_NetServerEnum2
,
5743 .fn
= api_RNetServerEnum2
5746 .name
= "NetServerEnum3",
5747 .id
= RAP_NetServerEnum3
,
5748 .fn
= api_RNetServerEnum3
5751 .name
= "WAccessGetUserPerms",
5752 .id
= RAP_WAccessGetUserPerms
,
5753 .fn
= api_WAccessGetUserPerms
5756 .name
= "WWkstaUserLogon",
5757 .id
= RAP_WWkstaUserLogon
,
5758 .fn
= api_WWkstaUserLogon
5761 .name
= "PrintJobInfo",
5762 .id
= RAP_WPrintJobSetInfo
,
5763 .fn
= api_PrintJobInfo
5766 .name
= "WPrintDriverEnum",
5767 .id
= RAP_WPrintDriverEnum
,
5768 .fn
= api_WPrintDriverEnum
5771 .name
= "WPrintQProcEnum",
5772 .id
= RAP_WPrintQProcessorEnum
,
5773 .fn
= api_WPrintQProcEnum
5776 .name
= "WPrintPortEnum",
5777 .id
= RAP_WPrintPortEnum
,
5778 .fn
= api_WPrintPortEnum
5781 .name
= "SamOEMChangePassword",
5782 .id
= RAP_SamOEMChgPasswordUser2_P
,
5783 .fn
= api_SamOEMChangePassword
5788 .fn
= api_Unsupported
}
5790 * The following RAP calls are not implemented by Samba:
5791 * RAP_WFileEnum2 - anon not OK
5796 /****************************************************************************
5797 Handle remote api calls.
5798 ****************************************************************************/
5800 void api_reply(connection_struct
*conn
, uint64_t vuid
,
5801 struct smb_request
*req
,
5802 char *data
, char *params
,
5803 int tdscnt
, int tpscnt
,
5804 int mdrcnt
, int mprcnt
)
5808 char *rparam
= NULL
;
5809 const char *name1
= NULL
;
5810 const char *name2
= NULL
;
5817 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5818 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5823 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5826 api_command
= SVAL(params
,0);
5827 /* Is there a string at position params+2 ? */
5828 if (skip_string(params
,tpscnt
,params
+2)) {
5833 name2
= skip_string(params
,tpscnt
,params
+2);
5838 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5842 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5844 for (i
=0;api_commands
[i
].name
;i
++) {
5845 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5846 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5851 /* Check whether this api call can be done anonymously */
5853 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5854 struct auth_session_info
*si
= NULL
;
5857 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
5860 if (!NT_STATUS_IS_OK(status
)) {
5861 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5865 if (security_session_user_level(si
, NULL
) < SECURITY_USER
) {
5866 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5871 rdata
= (char *)SMB_MALLOC(1024);
5873 memset(rdata
,'\0',1024);
5876 rparam
= (char *)SMB_MALLOC(1024);
5878 memset(rparam
,'\0',1024);
5881 if(!rdata
|| !rparam
) {
5882 DEBUG(0,("api_reply: malloc fail !\n"));
5885 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5889 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5891 params
,tpscnt
, /* params + length */
5892 data
,tdscnt
, /* data + length */
5894 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5897 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5898 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5900 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5903 /* if we get False back then it's actually unsupported */
5905 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5907 tdscnt
,mdrcnt
,mprcnt
,
5908 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5911 /* If api_Unsupported returns false we can't return anything. */
5913 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5914 rdata
, rdata_len
, False
);