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 "lib/util/util_file.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "source3/smbd/smbXsrv_session.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_samr_c.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
39 #include "../librpc/gen_ndr/rap.h"
40 #include "../lib/util/binsearch.h"
41 #include "../libcli/auth/libcli_auth.h"
42 #include "rpc_client/init_lsa.h"
43 #include "../libcli/security/security.h"
45 #include "passdb/machine_sid.h"
47 #include "rpc_server/rpc_ncacn_np.h"
48 #include "lib/util/string_wrappers.h"
49 #include "source3/printing/rap_jobid.h"
50 #include "source3/lib/substitute.h"
57 #define NERR_Success 0
58 #define NERR_badpass 86
59 #define NERR_notsupported 50
61 #define NERR_BASE (2100)
62 #define NERR_BufTooSmall (NERR_BASE+23)
63 #define NERR_JobNotFound (NERR_BASE+51)
64 #define NERR_DestNotFound (NERR_BASE+52)
66 #define ACCESS_READ 0x01
67 #define ACCESS_WRITE 0x02
68 #define ACCESS_CREATE 0x04
70 #define SHPWLEN 8 /* share password length */
72 /* Limit size of ipc replies */
74 static char *smb_realloc_limit(void *ptr
, size_t size
)
78 size
= MAX((size
),4*1024);
79 val
= (char *)SMB_REALLOC(ptr
,size
);
81 memset(val
,'\0',size
);
86 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
87 connection_struct
*conn
, uint64_t vuid
,
88 char *param
, int tpscnt
,
89 char *data
, int tdscnt
,
90 int mdrcnt
, int mprcnt
,
91 char **rdata
, char **rparam
,
92 int *rdata_len
, int *rparam_len
);
94 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
95 connection_struct
*conn
, uint64_t vuid
, char *param
, char *data
,
96 int mdrcnt
, int mprcnt
,
97 char **rdata
, char **rparam
,
98 int *rdata_len
, int *rparam_len
);
101 static int CopyExpanded(connection_struct
*conn
,
102 int snum
, char **dst
, char *src
, int *p_space_remaining
)
104 TALLOC_CTX
*ctx
= talloc_tos();
105 const struct loadparm_substitution
*lp_sub
=
106 loadparm_s3_global_substitution();
110 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
111 *p_space_remaining
<= 0) {
115 buf
= talloc_strdup(ctx
, src
);
117 *p_space_remaining
= 0;
120 buf
= talloc_string_sub(ctx
, buf
,"%S", lp_servicename(ctx
, lp_sub
, snum
));
122 *p_space_remaining
= 0;
125 buf
= talloc_sub_full(ctx
,
126 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
127 conn
->session_info
->unix_info
->unix_name
,
129 conn
->session_info
->unix_token
->gid
,
130 conn
->session_info
->unix_info
->sanitized_username
,
131 conn
->session_info
->info
->domain_name
,
134 *p_space_remaining
= 0;
137 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
142 (*p_space_remaining
) -= l
;
146 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
149 if (!src
|| !dst
|| !n
|| !(*dst
)) {
152 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
161 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
163 TALLOC_CTX
*ctx
= talloc_tos();
164 const struct loadparm_substitution
*lp_sub
=
165 loadparm_s3_global_substitution();
170 buf
= talloc_strdup(ctx
,s
);
174 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(ctx
, lp_sub
, snum
));
178 buf
= talloc_sub_full(ctx
,
179 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
180 conn
->session_info
->unix_info
->unix_name
,
182 conn
->session_info
->unix_token
->gid
,
183 conn
->session_info
->unix_info
->sanitized_username
,
184 conn
->session_info
->info
->domain_name
,
189 return strlen(buf
) + 1;
192 /****************************************************************
193 Return an SVAL at a pointer, or failval if beyond the end.
194 ****************************************************************/
196 static int get_safe_SVAL(
197 const char *buf_base
,
204 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0]
205 * and ptr[1], NOT ptr[2].
207 if (!is_offset_safe(buf_base
, buf_len
, ptr
, off
+1)) {
210 return SVAL(ptr
,off
);
213 /****************************************************************
214 Return an IVAL at a pointer, or failval if beyond the end.
215 ****************************************************************/
217 static int get_safe_IVAL(
218 const char *buf_base
,
225 * Note we use off+3 here, not off+4 as IVAL accesses
226 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
228 if (!is_offset_safe(buf_base
, buf_len
, ptr
, off
+3)) {
231 return IVAL(ptr
,off
);
234 /****************************************************************
235 Return a safe pointer into a buffer, or NULL.
236 ****************************************************************/
238 static char *get_safe_ptr(
239 const char *buf_base
,
244 return is_offset_safe(buf_base
, buf_len
, ptr
, off
) ?
248 /*******************************************************************
249 Check a API string for validity when we only need to check the prefix.
250 ******************************************************************/
252 static bool prefix_ok(const char *str
, const char *prefix
)
254 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
258 const char *format
; /* formatstring for structure */
259 const char *subformat
; /* subformat for structure */
260 char *base
; /* baseaddress of buffer */
261 int buflen
; /* remaining size for fixed part; on init: length of base */
262 int subcount
; /* count of substructures */
263 char *structbuf
; /* pointer into buffer for remaining fixed part */
264 int stringlen
; /* remaining size for variable part */
265 char *stringbuf
; /* pointer into buffer for remaining variable part */
266 int neededlen
; /* total needed size */
267 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
268 const char *curpos
; /* current position; pointer into format or subformat */
272 static int get_counter(const char **p
)
278 if (!isdigit((int)**p
)) {
284 n
= 10 * n
+ (i
- '0');
292 static int getlen(const char *p
)
301 case 'W': /* word (2 byte) */
304 case 'K': /* status word? (2 byte) */
307 case 'N': /* count of substructures (word) at end */
310 case 'D': /* double word (4 byte) */
311 case 'z': /* offset to zero terminated string (4 byte) */
312 case 'l': /* offset to user data (4 byte) */
315 case 'b': /* offset to data (with counter) (4 byte) */
319 case 'B': /* byte (with optional counter) */
320 n
+= get_counter(&p
);
327 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
332 if (!p
->format
|| !p
->base
) {
336 i
= count
* getlen(p
->format
);
338 i
+= subcount
* getlen(p
->subformat
);
340 p
->structbuf
= p
->base
;
344 p
->curpos
= p
->format
;
350 * This is the old error code we used. Apparently
351 * WinNT/2k systems return ERRbuftoosmall (2123) and
352 * OS/2 needs this. I'm leaving this here so we can revert
355 p
->errcode
= ERRmoredata
;
357 p
->errcode
= ERRbuftoosmall
;
360 p
->errcode
= NERR_Success
;
364 p
->stringbuf
= p
->base
+ i
;
366 return (p
->errcode
== NERR_Success
);
369 static int package(struct pack_desc
*p
, ...)
372 int needed
=0, stringneeded
;
373 const char *str
=NULL
;
374 int is_string
=0, stringused
;
381 p
->curpos
= p
->format
;
383 p
->curpos
= p
->subformat
;
388 str
= va_arg(args
,char*);
389 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
398 switch( *p
->curpos
++ ) {
399 case 'W': /* word (2 byte) */
401 temp
= va_arg(args
,int);
402 if (p
->buflen
>= needed
) {
403 SSVAL(p
->structbuf
,0,temp
);
406 case 'K': /* status word? (2 byte) */
408 temp
= va_arg(args
,int);
409 if (p
->buflen
>= needed
) {
410 SSVAL(p
->structbuf
,0,temp
);
413 case 'N': /* count of substructures (word) at end */
415 p
->subcount
= va_arg(args
,int);
416 if (p
->buflen
>= needed
) {
417 SSVAL(p
->structbuf
,0,p
->subcount
);
420 case 'D': /* double word (4 byte) */
422 temp
= va_arg(args
,int);
423 if (p
->buflen
>= needed
) {
424 SIVAL(p
->structbuf
,0,temp
);
427 case 'B': /* byte (with optional counter) */
428 needed
= get_counter(&p
->curpos
);
430 char *s
= va_arg(args
,char*);
431 if (p
->buflen
>= needed
) {
432 strlcpy(p
->structbuf
,s
?s
:"",needed
);
436 case 'z': /* offset to zero terminated string (4 byte) */
437 str
= va_arg(args
,char*);
438 stringneeded
= (str
? strlen(str
)+1 : 0);
441 case 'l': /* offset to user data (4 byte) */
442 str
= va_arg(args
,char*);
443 stringneeded
= va_arg(args
,int);
446 case 'b': /* offset to data (with counter) (4 byte) */
447 str
= va_arg(args
,char*);
448 stringneeded
= get_counter(&p
->curpos
);
454 if (stringneeded
>= 0) {
456 if (p
->buflen
>= needed
) {
457 stringused
= stringneeded
;
458 if (stringused
> p
->stringlen
) {
459 stringused
= (is_string
? p
->stringlen
: 0);
460 if (p
->errcode
== NERR_Success
) {
461 p
->errcode
= ERRmoredata
;
465 SIVAL(p
->structbuf
,0,0);
467 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
468 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
470 p
->stringbuf
[stringused
-1] = '\0';
472 p
->stringbuf
+= stringused
;
473 p
->stringlen
-= stringused
;
474 p
->usedlen
+= stringused
;
477 p
->neededlen
+= stringneeded
;
480 p
->neededlen
+= needed
;
481 if (p
->buflen
>= needed
) {
482 p
->structbuf
+= needed
;
484 p
->usedlen
+= needed
;
486 if (p
->errcode
== NERR_Success
) {
487 p
->errcode
= ERRmoredata
;
494 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
495 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
497 #define PACK(desc,t,v) package(desc,v)
498 #define PACKl(desc,t,v,l) package(desc,v,l)
501 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
506 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
511 /****************************************************************************
513 ****************************************************************************/
515 static void PackDriverData(struct pack_desc
* desc
)
517 char drivdata
[4+4+32];
518 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
519 SIVAL(drivdata
,4,1000); /* lVersion */
520 memset(drivdata
+8,0,32); /* szDeviceName */
521 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
522 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
525 static int check_printq_info(struct pack_desc
* desc
,
526 unsigned int uLevel
, char *id1
, char *id2
)
528 desc
->subformat
= NULL
;
531 desc
->format
= "B13";
534 desc
->format
= "B13BWWWzzzzzWW";
537 desc
->format
= "B13BWWWzzzzzWN";
538 desc
->subformat
= "WB21BB16B10zWWzDDz";
541 desc
->format
= "zWWWWzzzzWWzzl";
544 desc
->format
= "zWWWWzzzzWNzzl";
545 desc
->subformat
= "WWzWWDDzz";
554 desc
->format
= "WzzzzzzzzN";
555 desc
->subformat
= "z";
558 DEBUG(0,("check_printq_info: invalid level %d\n",
562 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
563 DEBUG(0,("check_printq_info: invalid format %s\n",
564 id1
? id1
: "<NULL>" ));
567 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
568 DEBUG(0,("check_printq_info: invalid subformat %s\n",
569 id2
? id2
: "<NULL>" ));
576 #define RAP_JOB_STATUS_QUEUED 0
577 #define RAP_JOB_STATUS_PAUSED 1
578 #define RAP_JOB_STATUS_SPOOLING 2
579 #define RAP_JOB_STATUS_PRINTING 3
580 #define RAP_JOB_STATUS_PRINTED 4
582 #define RAP_QUEUE_STATUS_PAUSED 1
583 #define RAP_QUEUE_STATUS_ERROR 2
585 /* turn a print job status into a on the wire status
587 static int printj_spoolss_status(int v
)
589 if (v
== JOB_STATUS_QUEUED
)
590 return RAP_JOB_STATUS_QUEUED
;
591 if (v
& JOB_STATUS_PAUSED
)
592 return RAP_JOB_STATUS_PAUSED
;
593 if (v
& JOB_STATUS_SPOOLING
)
594 return RAP_JOB_STATUS_SPOOLING
;
595 if (v
& JOB_STATUS_PRINTING
)
596 return RAP_JOB_STATUS_PRINTING
;
600 /* turn a print queue status into a on the wire status
602 static int printq_spoolss_status(int v
)
604 if (v
== PRINTER_STATUS_OK
)
606 if (v
& PRINTER_STATUS_PAUSED
)
607 return RAP_QUEUE_STATUS_PAUSED
;
608 return RAP_QUEUE_STATUS_ERROR
;
611 static void fill_spoolss_printjob_info(int uLevel
,
612 struct pack_desc
*desc
,
613 struct spoolss_JobInfo2
*info2
,
616 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
618 /* the client expects localtime */
619 t
-= get_time_zone(t
);
621 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
623 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
624 PACKS(desc
,"B",""); /* pad */
625 PACKS(desc
,"B16",""); /* szNotifyName */
626 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
627 PACKS(desc
,"z",""); /* pszParms */
628 PACKI(desc
,"W",n
+1); /* uPosition */
629 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
630 PACKS(desc
,"z",""); /* pszStatus */
631 PACKI(desc
,"D", t
); /* ulSubmitted */
632 PACKI(desc
,"D", info2
->size
); /* ulSize */
633 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
635 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
636 PACKI(desc
,"W", info2
->priority
); /* uPriority */
637 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
638 PACKI(desc
,"W",n
+1); /* uPosition */
639 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
640 PACKI(desc
,"D",t
); /* ulSubmitted */
641 PACKI(desc
,"D", info2
->size
); /* ulSize */
642 PACKS(desc
,"z","Samba"); /* pszComment */
643 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
645 PACKS(desc
,"z",""); /* pszNotifyName */
646 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
647 PACKS(desc
,"z",""); /* pszParms */
648 PACKS(desc
,"z",""); /* pszStatus */
649 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
650 PACKS(desc
,"z","lpd"); /* pszQProcName */
651 PACKS(desc
,"z",""); /* pszQProcParms */
652 PACKS(desc
,"z","NULL"); /* pszDriverName */
653 PackDriverData(desc
); /* pDriverData */
654 PACKS(desc
,"z",""); /* pszPrinterName */
655 } else if (uLevel
== 4) { /* OS2 */
656 PACKS(desc
,"z",""); /* pszSpoolFileName */
657 PACKS(desc
,"z",""); /* pszPortName */
658 PACKS(desc
,"z",""); /* pszStatus */
659 PACKI(desc
,"D",0); /* ulPagesSpooled */
660 PACKI(desc
,"D",0); /* ulPagesSent */
661 PACKI(desc
,"D",0); /* ulPagesPrinted */
662 PACKI(desc
,"D",0); /* ulTimePrinted */
663 PACKI(desc
,"D",0); /* ulExtendJobStatus */
664 PACKI(desc
,"D",0); /* ulStartPage */
665 PACKI(desc
,"D",0); /* ulEndPage */
670 /********************************************************************
671 Respond to the DosPrintQInfo command with a level of 52
672 This is used to get printer driver information for Win9x clients
673 ********************************************************************/
674 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
675 struct pack_desc
* desc
, int count
,
676 const char *printer_name
)
680 trim_string(discard_const_p(char, driver
->driver_path
), "\\print$\\WIN40\\0\\", 0);
681 trim_string(discard_const_p(char, driver
->data_file
), "\\print$\\WIN40\\0\\", 0);
682 trim_string(discard_const_p(char, driver
->help_file
), "\\print$\\WIN40\\0\\", 0);
684 PACKI(desc
, "W", 0x0400); /* don't know */
685 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
686 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
687 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
688 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
690 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
691 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
692 PACKS(desc
,"z", location
); /* share to retrieve files */
694 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
695 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
696 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
698 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
699 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
700 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
701 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
702 DEBUG(3,("Driver Location: %s:\n",location
));
703 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
704 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
705 PACKI(desc
,"N",count
); /* number of files to copy */
707 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
709 trim_string(discard_const_p(char, driver
->dependent_files
[i
]), "\\print$\\WIN40\\0\\", 0);
710 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
711 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
716 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
719 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
721 desc
->errcode
=NERR_Success
;
725 static const char *strip_unc(const char *unc
)
733 if ((p
= strrchr(unc
, '\\')) != NULL
) {
740 static void fill_printq_info(int uLevel
,
741 struct pack_desc
* desc
,
743 union spoolss_JobInfo
*job_info
,
744 struct spoolss_DriverInfo3
*driver_info
,
745 struct spoolss_PrinterInfo2
*printer_info
)
751 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
756 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
759 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
763 if (uLevel
== 1 || uLevel
== 2) {
764 PACKS(desc
,"B",""); /* alignment */
765 PACKI(desc
,"W",5); /* priority */
766 PACKI(desc
,"W",0); /* start time */
767 PACKI(desc
,"W",0); /* until time */
768 PACKS(desc
,"z",""); /* pSepFile */
769 PACKS(desc
,"z","lpd"); /* pPrProc */
770 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
771 PACKS(desc
,"z",""); /* pParms */
772 if (printer_info
->printername
== NULL
) {
773 PACKS(desc
,"z","UNKNOWN PRINTER");
774 PACKI(desc
,"W",LPSTAT_ERROR
);
776 PACKS(desc
,"z", printer_info
->comment
);
777 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
779 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
782 if (uLevel
== 3 || uLevel
== 4) {
783 PACKI(desc
,"W",5); /* uPriority */
784 PACKI(desc
,"W",0); /* uStarttime */
785 PACKI(desc
,"W",0); /* uUntiltime */
786 PACKI(desc
,"W",5); /* pad1 */
787 PACKS(desc
,"z",""); /* pszSepFile */
788 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
789 PACKS(desc
,"z",NULL
); /* pszParms */
790 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
791 /* "don't ask" that it's done this way to fix corrupted
792 Win9X/ME printer comments. */
793 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
794 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
795 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
796 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
797 PackDriverData(desc
); /* pDriverData */
800 if (uLevel
== 2 || uLevel
== 4) {
802 for (i
= 0; i
< count
; i
++) {
803 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
808 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
811 /* This function returns the number of files for a given driver */
812 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
816 /* count the number of files */
817 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
823 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
824 connection_struct
*conn
, uint64_t vuid
,
825 char *param
, int tpscnt
,
826 char *data
, int tdscnt
,
827 int mdrcnt
,int mprcnt
,
828 char **rdata
,char **rparam
,
829 int *rdata_len
,int *rparam_len
)
831 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
832 char *str2
= skip_string(param
,tpscnt
,str1
);
833 char *p
= skip_string(param
,tpscnt
,str2
);
838 struct pack_desc desc
;
841 WERROR werr
= WERR_OK
;
842 TALLOC_CTX
*mem_ctx
= talloc_tos();
844 struct rpc_pipe_client
*cli
= NULL
;
845 struct dcerpc_binding_handle
*b
= NULL
;
846 struct policy_handle handle
;
847 struct spoolss_DevmodeContainer devmode_ctr
;
848 union spoolss_DriverInfo driver_info
;
849 union spoolss_JobInfo
*job_info
= NULL
;
850 union spoolss_PrinterInfo printer_info
;
852 if (!str1
|| !str2
|| !p
) {
855 memset((char *)&desc
,'\0',sizeof(desc
));
857 p
= skip_string(param
,tpscnt
,p
);
861 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
862 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
863 /* str3 may be null here and is checked in check_printq_info(). */
865 /* remove any trailing username */
866 if ((p
= strchr_m(QueueName
,'%')))
869 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
871 /* check it's a supported variant */
872 if (!prefix_ok(str1
,"zWrLh"))
874 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
876 * Patch from Scott Moomaw <scott@bridgewater.edu>
877 * to return the 'invalid info level' error if an
878 * unknown level was requested.
882 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
886 SSVALS(*rparam
,0,ERRunknownlevel
);
894 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
895 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
899 status
= rpc_pipe_open_interface(mem_ctx
,
902 conn
->sconn
->remote_address
,
903 conn
->sconn
->local_address
,
904 conn
->sconn
->msg_ctx
,
906 if (!NT_STATUS_IS_OK(status
)) {
907 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
909 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
912 b
= cli
->binding_handle
;
914 ZERO_STRUCT(devmode_ctr
);
916 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
923 if (!NT_STATUS_IS_OK(status
)) {
924 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
927 if (!W_ERROR_IS_OK(werr
)) {
928 desc
.errcode
= W_ERROR_V(werr
);
932 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
937 if (!W_ERROR_IS_OK(werr
)) {
938 desc
.errcode
= W_ERROR_V(werr
);
943 uint32_t server_major_version
;
944 uint32_t server_minor_version
;
946 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
954 &server_major_version
,
955 &server_minor_version
);
956 if (!W_ERROR_IS_OK(werr
)) {
957 desc
.errcode
= W_ERROR_V(werr
);
961 count
= get_printerdrivernumber(&driver_info
.info3
);
962 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
965 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
973 if (!W_ERROR_IS_OK(werr
)) {
974 desc
.errcode
= W_ERROR_V(werr
);
982 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
987 desc
.buflen
= mdrcnt
;
990 * Don't return data but need to get correct length
991 * init_package will return wrong size if buflen=0
993 desc
.buflen
= getlen(desc
.format
);
994 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
997 if (init_package(&desc
,1,count
)) {
998 desc
.subcount
= count
;
999 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
1002 *rdata_len
= desc
.usedlen
;
1005 * We must set the return code to ERRbuftoosmall
1006 * in order to support lanman style printing with Win NT/2k
1009 if (!mdrcnt
&& lp_disable_spoolss())
1010 desc
.errcode
= ERRbuftoosmall
;
1013 if (b
&& is_valid_policy_hnd(&handle
)) {
1014 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1017 *rdata_len
= desc
.usedlen
;
1019 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1024 SSVALS(*rparam
,0,desc
.errcode
);
1026 SSVAL(*rparam
,4,desc
.neededlen
);
1028 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
1035 /****************************************************************************
1036 View list of all print jobs on all queues.
1037 ****************************************************************************/
1039 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
1040 connection_struct
*conn
, uint64_t vuid
,
1041 char *param
, int tpscnt
,
1042 char *data
, int tdscnt
,
1043 int mdrcnt
, int mprcnt
,
1044 char **rdata
, char** rparam
,
1045 int *rdata_len
, int *rparam_len
)
1047 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1048 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
1049 char *p
= skip_string(param
,tpscnt
,output_format1
);
1050 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1051 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
1053 struct pack_desc desc
;
1054 int *subcntarr
= NULL
;
1055 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
1057 WERROR werr
= WERR_OK
;
1058 TALLOC_CTX
*mem_ctx
= talloc_tos();
1060 struct rpc_pipe_client
*cli
= NULL
;
1061 struct dcerpc_binding_handle
*b
= NULL
;
1062 struct spoolss_DevmodeContainer devmode_ctr
;
1063 uint32_t num_printers
;
1064 union spoolss_PrinterInfo
*printer_info
;
1065 union spoolss_DriverInfo
*driver_info
;
1066 union spoolss_JobInfo
**job_info
;
1068 if (!param_format
|| !output_format1
|| !p
) {
1072 memset((char *)&desc
,'\0',sizeof(desc
));
1074 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1076 if (!prefix_ok(param_format
,"WrLeh")) {
1079 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1081 * Patch from Scott Moomaw <scott@bridgewater.edu>
1082 * to return the 'invalid info level' error if an
1083 * unknown level was requested.
1087 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1091 SSVALS(*rparam
,0,ERRunknownlevel
);
1097 status
= rpc_pipe_open_interface(mem_ctx
,
1100 conn
->sconn
->remote_address
,
1101 conn
->sconn
->local_address
,
1102 conn
->sconn
->msg_ctx
,
1104 if (!NT_STATUS_IS_OK(status
)) {
1105 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1106 nt_errstr(status
)));
1107 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1110 b
= cli
->binding_handle
;
1112 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1114 cli
->srv_name_slash
,
1119 if (!W_ERROR_IS_OK(werr
)) {
1120 desc
.errcode
= W_ERROR_V(werr
);
1124 queuecnt
= num_printers
;
1126 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1127 if (job_info
== NULL
) {
1131 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1132 if (driver_info
== NULL
) {
1136 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1137 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1142 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1148 desc
.buflen
= mdrcnt
;
1151 for (i
= 0; i
< num_printers
; i
++) {
1154 struct policy_handle handle
;
1155 const char *printername
;
1157 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1158 if (printername
== NULL
) {
1162 ZERO_STRUCT(handle
);
1163 ZERO_STRUCT(devmode_ctr
);
1165 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
1172 if (!NT_STATUS_IS_OK(status
)) {
1173 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1176 if (!W_ERROR_IS_OK(werr
)) {
1177 desc
.errcode
= W_ERROR_V(werr
);
1181 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1189 if (!W_ERROR_IS_OK(werr
)) {
1190 desc
.errcode
= W_ERROR_V(werr
);
1195 uint32_t server_major_version
;
1196 uint32_t server_minor_version
;
1198 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1206 &server_major_version
,
1207 &server_minor_version
);
1208 if (!W_ERROR_IS_OK(werr
)) {
1209 desc
.errcode
= W_ERROR_V(werr
);
1214 subcntarr
[i
] = num_jobs
;
1215 subcnt
+= subcntarr
[i
];
1217 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1220 if (init_package(&desc
,queuecnt
,subcnt
)) {
1221 for (i
= 0; i
< num_printers
; i
++) {
1222 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1223 if (desc
.errcode
== NERR_Success
) {
1230 SAFE_FREE(subcntarr
);
1231 *rdata_len
= desc
.usedlen
;
1233 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1237 SSVALS(*rparam
,0,desc
.errcode
);
1239 SSVAL(*rparam
,4,succnt
);
1240 SSVAL(*rparam
,6,queuecnt
);
1246 SAFE_FREE(subcntarr
);
1251 /****************************************************************************
1252 Get info level for a server list query.
1253 ****************************************************************************/
1255 static bool check_session_info(int uLevel
, char* id
)
1259 if (strcmp(id
,"B16") != 0) {
1264 if (strcmp(id
,"B16BBDz") != 0) {
1274 struct srv_info_struct
{
1282 /*******************************************************************
1283 Get server info lists from the files saved by nmbd. Return the
1285 ******************************************************************/
1287 static int get_session_info(uint32_t servertype
,
1288 struct srv_info_struct
**servers
,
1294 bool local_list_only
;
1296 char *slist_cache_path
= cache_path(talloc_tos(), SERVER_LIST
);
1297 if (slist_cache_path
== NULL
) {
1301 lines
= file_lines_load(slist_cache_path
, NULL
, 0, NULL
);
1303 DEBUG(4, ("Can't open %s - %s\n",
1304 slist_cache_path
, strerror(errno
)));
1305 TALLOC_FREE(slist_cache_path
);
1308 TALLOC_FREE(slist_cache_path
);
1310 /* request for everything is code for request all servers */
1311 if (servertype
== SV_TYPE_ALL
) {
1312 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1315 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1317 DEBUG(4,("Servertype search: %8x\n",servertype
));
1319 for (i
=0;lines
[i
];i
++) {
1321 struct srv_info_struct
*s
;
1322 const char *ptr
= lines
[i
];
1324 TALLOC_CTX
*frame
= NULL
;
1331 if (count
== alloced
) {
1333 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1335 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1339 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1341 s
= &(*servers
)[count
];
1343 frame
= talloc_stackframe();
1345 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1349 fstrcpy(s
->name
, p
);
1352 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1358 s
->comment
[0] = '\0';
1359 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1363 fstrcpy(s
->comment
, p
);
1364 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1366 s
->domain
[0] = '\0';
1367 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1368 /* this allows us to cope with an old nmbd */
1369 fstrcpy(s
->domain
,lp_workgroup());
1371 fstrcpy(s
->domain
, p
);
1375 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1376 DEBUG(4,("r:host file "));
1380 /* Filter the servers/domains we return based on what was asked for. */
1382 /* Check to see if we are being asked for a local list only. */
1383 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1384 DEBUG(4,("r: local list only"));
1388 /* doesn't match up: don't want it */
1389 if (!(servertype
& s
->type
)) {
1390 DEBUG(4,("r:serv type "));
1394 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1395 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1396 DEBUG(4,("s: dom mismatch "));
1400 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1404 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1405 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1408 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1409 s
->name
, s
->type
, s
->comment
, s
->domain
));
1410 s
->server_added
= True
;
1413 DEBUG(4,("%20s %8x %25s %15s\n",
1414 s
->name
, s
->type
, s
->comment
, s
->domain
));
1422 /*******************************************************************
1423 Fill in a server info structure.
1424 ******************************************************************/
1426 static int fill_srv_info(struct srv_info_struct
*service
,
1427 int uLevel
, char **buf
, int *buflen
,
1428 char **stringbuf
, int *stringspace
, char *baseaddr
)
1451 len
= strlen(service
->comment
)+1;
1455 *buflen
= struct_len
;
1457 return struct_len
+ len
;
1462 if (*buflen
< struct_len
) {
1469 p2
= p
+ struct_len
;
1470 l2
= *buflen
- struct_len
;
1478 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1482 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1483 SIVAL(p
,18,service
->type
);
1484 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1485 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1490 *buf
= p
+ struct_len
;
1491 *buflen
-= struct_len
;
1502 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1504 return strcasecmp_m(s1
->name
,s2
->name
);
1507 /****************************************************************************
1508 View list of servers available (or possibly domains). The info is
1509 extracted from lists saved by nmbd on the local host.
1510 ****************************************************************************/
1512 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1513 connection_struct
*conn
, uint64_t vuid
,
1514 char *param
, int tpscnt
,
1515 char *data
, int tdscnt
,
1516 int mdrcnt
, int mprcnt
, char **rdata
,
1517 char **rparam
, int *rdata_len
, int *rparam_len
)
1519 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1520 char *str2
= skip_string(param
,tpscnt
,str1
);
1521 char *p
= skip_string(param
,tpscnt
,str2
);
1522 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1523 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1524 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1526 int data_len
, fixed_len
, string_len
;
1527 int f_len
= 0, s_len
= 0;
1528 struct srv_info_struct
*servers
=NULL
;
1529 int counted
=0,total
=0;
1532 bool domain_request
;
1535 if (!str1
|| !str2
|| !p
) {
1539 /* If someone sets all the bits they don't really mean to set
1540 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1543 if (servertype
== SV_TYPE_ALL
) {
1544 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1547 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1548 any other bit (they may just set this bit on its own) they
1549 want all the locally seen servers. However this bit can be
1550 set on its own so set the requested servers to be
1551 ALL - DOMAIN_ENUM. */
1553 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1554 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1557 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1558 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1562 if (!prefix_ok(str1
,"WrLehD")) {
1565 if (!check_session_info(uLevel
,str2
)) {
1569 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1570 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1571 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1573 if (strcmp(str1
, "WrLehDz") == 0) {
1574 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1577 pull_ascii_fstring(domain
, p
);
1579 fstrcpy(domain
, lp_workgroup());
1582 DEBUG(4, ("domain [%s]\n", domain
));
1584 if (lp_browse_list()) {
1585 total
= get_session_info(servertype
,&servers
,domain
);
1588 data_len
= fixed_len
= string_len
= 0;
1591 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1594 char *lastname
=NULL
;
1596 for (i
=0;i
<total
;i
++) {
1597 struct srv_info_struct
*s
= &servers
[i
];
1599 if (lastname
&& strequal(lastname
,s
->name
)) {
1603 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1604 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1605 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1607 if (data_len
< buf_len
) {
1610 string_len
+= s_len
;
1617 *rdata_len
= fixed_len
+ string_len
;
1618 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1623 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1629 char *lastname
=NULL
;
1630 int count2
= counted
;
1632 for (i
= 0; i
< total
&& count2
;i
++) {
1633 struct srv_info_struct
*s
= &servers
[i
];
1635 if (lastname
&& strequal(lastname
,s
->name
)) {
1639 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1640 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1641 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1647 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1651 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1653 SSVAL(*rparam
,4,counted
);
1654 SSVAL(*rparam
,6,counted
+missed
);
1658 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1659 domain
,uLevel
,counted
,counted
+missed
));
1664 static int srv_name_match(const char *n1
, const char *n2
)
1667 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1669 * In Windows, FirstNameToReturn need not be an exact match:
1670 * the server will return a list of servers that exist on
1671 * the network greater than or equal to the FirstNameToReturn.
1673 int ret
= strcasecmp_m(n1
, n2
);
1682 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1683 connection_struct
*conn
, uint64_t vuid
,
1684 char *param
, int tpscnt
,
1685 char *data
, int tdscnt
,
1686 int mdrcnt
, int mprcnt
, char **rdata
,
1687 char **rparam
, int *rdata_len
, int *rparam_len
)
1689 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1690 char *str2
= skip_string(param
,tpscnt
,str1
);
1691 char *p
= skip_string(param
,tpscnt
,str2
);
1692 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1693 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1694 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1696 int data_len
, fixed_len
, string_len
;
1697 int f_len
= 0, s_len
= 0;
1698 struct srv_info_struct
*servers
=NULL
;
1699 int counted
=0,first
=0,total
=0;
1703 bool domain_request
;
1706 if (!str1
|| !str2
|| !p
) {
1710 /* If someone sets all the bits they don't really mean to set
1711 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1714 if (servertype
== SV_TYPE_ALL
) {
1715 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1718 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1719 any other bit (they may just set this bit on its own) they
1720 want all the locally seen servers. However this bit can be
1721 set on its own so set the requested servers to be
1722 ALL - DOMAIN_ENUM. */
1724 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1725 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1728 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1729 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1733 if (strcmp(str1
, "WrLehDzz") != 0) {
1736 if (!check_session_info(uLevel
,str2
)) {
1740 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1741 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1742 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1744 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1747 pull_ascii_fstring(domain
, p
);
1748 if (domain
[0] == '\0') {
1749 fstrcpy(domain
, lp_workgroup());
1751 p
= skip_string(param
,tpscnt
,p
);
1752 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1755 pull_ascii_fstring(first_name
, p
);
1757 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1758 domain
, first_name
));
1760 if (lp_browse_list()) {
1761 total
= get_session_info(servertype
,&servers
,domain
);
1764 data_len
= fixed_len
= string_len
= 0;
1767 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1769 if (first_name
[0] != '\0') {
1770 struct srv_info_struct
*first_server
= NULL
;
1772 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1773 srv_name_match
, first_server
);
1775 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1777 * The binary search may not find the exact match
1778 * so we need to search backward to find the first match
1780 * This implements the strange matching windows
1781 * implements. (see the comment in srv_name_match().
1785 ret
= strcasecmp_m(first_name
,
1786 servers
[first
-1].name
);
1793 /* we should return no entries */
1799 char *lastname
=NULL
;
1801 for (i
=first
;i
<total
;i
++) {
1802 struct srv_info_struct
*s
= &servers
[i
];
1804 if (lastname
&& strequal(lastname
,s
->name
)) {
1808 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1809 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1810 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1812 if (data_len
< buf_len
) {
1815 string_len
+= s_len
;
1822 *rdata_len
= fixed_len
+ string_len
;
1823 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1828 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1834 char *lastname
=NULL
;
1835 int count2
= counted
;
1837 for (i
= first
; i
< total
&& count2
;i
++) {
1838 struct srv_info_struct
*s
= &servers
[i
];
1840 if (lastname
&& strequal(lastname
,s
->name
)) {
1844 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1845 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1846 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1852 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1856 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1858 SSVAL(*rparam
,4,counted
);
1859 SSVAL(*rparam
,6,counted
+missed
);
1861 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1862 domain
,uLevel
,first
,first_name
,
1863 first
< total
? servers
[first
].name
: "",
1864 counted
,counted
+missed
));
1871 /****************************************************************************
1872 command 0x34 - suspected of being a "Lookup Names" stub api
1873 ****************************************************************************/
1875 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1876 connection_struct
*conn
, uint64_t vuid
,
1877 char *param
, int tpscnt
,
1878 char *data
, int tdscnt
,
1879 int mdrcnt
, int mprcnt
, char **rdata
,
1880 char **rparam
, int *rdata_len
, int *rparam_len
)
1882 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1883 char *str2
= skip_string(param
,tpscnt
,str1
);
1884 char *p
= skip_string(param
,tpscnt
,str2
);
1885 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1886 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1890 if (!str1
|| !str2
|| !p
) {
1894 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1895 str1
, str2
, p
, uLevel
, buf_len
));
1897 if (!prefix_ok(str1
,"zWrLeh")) {
1904 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1909 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1911 SSVAL(*rparam
,4,counted
);
1912 SSVAL(*rparam
,6,counted
+missed
);
1917 /****************************************************************************
1918 get info about a share
1919 ****************************************************************************/
1921 static bool check_share_info(int uLevel
, char* id
)
1925 if (strcmp(id
,"B13") != 0) {
1930 /* Level-2 descriptor is allowed (and ignored) */
1931 if (strcmp(id
,"B13BWz") != 0 &&
1932 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1937 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1942 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1952 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1953 char** buf
, int* buflen
,
1954 char** stringbuf
, int* stringspace
, char* baseaddr
)
1956 const struct loadparm_substitution
*lp_sub
=
1957 loadparm_s3_global_substitution();
1985 len
+= StrlenExpanded(conn
,snum
,lp_comment(talloc_tos(), lp_sub
, snum
));
1988 len
+= strlen(lp_path(talloc_tos(), lp_sub
, snum
)) + 1;
1991 *buflen
= struct_len
;
1996 return struct_len
+ len
;
2001 if ((*buflen
) < struct_len
) {
2009 p2
= p
+ struct_len
;
2010 l2
= (*buflen
) - struct_len
;
2017 push_ascii(p
,lp_servicename(talloc_tos(), lp_sub
, snum
),13, STR_TERMINATE
);
2023 type
= STYPE_DISKTREE
;
2024 if (lp_printable(snum
)) {
2025 type
= STYPE_PRINTQ
;
2027 if (strequal("IPC",lp_fstype(snum
))) {
2030 SSVAL(p
,14,type
); /* device type */
2031 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
2032 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(talloc_tos(), lp_sub
, snum
),&l2
);
2036 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
2037 SSVALS(p
,22,-1); /* max uses */
2038 SSVAL(p
,24,1); /* current uses */
2039 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
2040 len
+= CopyAndAdvance(&p2
,lp_path(talloc_tos(),lp_sub
, snum
),&l2
);
2041 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
2045 memset(p
+40,0,SHPWLEN
+2);
2056 (*buf
) = p
+ struct_len
;
2057 (*buflen
) -= struct_len
;
2059 (*stringspace
) = l2
;
2068 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
2069 connection_struct
*conn
,uint64_t vuid
,
2070 char *param
, int tpscnt
,
2071 char *data
, int tdscnt
,
2072 int mdrcnt
,int mprcnt
,
2073 char **rdata
,char **rparam
,
2074 int *rdata_len
,int *rparam_len
)
2076 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2077 char *str2
= skip_string(param
,tpscnt
,str1
);
2078 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2079 char *netname
= NULL
;
2080 char *p
= skip_string(param
,tpscnt
,netname
);
2081 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2084 if (!str1
|| !str2
|| !netname_in
|| !p
) {
2088 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2089 if (snum
< 0 || !netname
) {
2093 /* check it's a supported variant */
2094 if (!prefix_ok(str1
,"zWrLh")) {
2097 if (!check_share_info(uLevel
,str2
)) {
2101 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2106 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2107 if (*rdata_len
< 0) {
2112 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2116 SSVAL(*rparam
,0,NERR_Success
);
2117 SSVAL(*rparam
,2,0); /* converter word */
2118 SSVAL(*rparam
,4,*rdata_len
);
2123 /****************************************************************************
2124 View the list of available shares.
2126 This function is the server side of the NetShareEnum() RAP call.
2127 It fills the return buffer with share names and share comments.
2128 Note that the return buffer normally (in all known cases) allows only
2129 twelve byte strings for share names (plus one for a nul terminator).
2130 Share names longer than 12 bytes must be skipped.
2131 ****************************************************************************/
2133 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2134 connection_struct
*conn
, uint64_t vuid
,
2135 char *param
, int tpscnt
,
2136 char *data
, int tdscnt
,
2144 const struct loadparm_substitution
*lp_sub
=
2145 loadparm_s3_global_substitution();
2146 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2147 char *str2
= skip_string(param
,tpscnt
,str1
);
2148 char *p
= skip_string(param
,tpscnt
,str2
);
2149 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2150 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2153 int total
=0,counted
=0;
2154 bool missed
= False
;
2156 int data_len
, fixed_len
, string_len
;
2157 int f_len
= 0, s_len
= 0;
2159 if (!str1
|| !str2
|| !p
) {
2163 if (!prefix_ok(str1
,"WrLeh")) {
2166 if (!check_share_info(uLevel
,str2
)) {
2170 /* Ensure all the usershares are loaded. */
2172 delete_and_reload_printers();
2173 load_registry_shares();
2174 count
= load_usershare_shares(NULL
, connections_snum_used
);
2177 data_len
= fixed_len
= string_len
= 0;
2178 for (i
=0;i
<count
;i
++) {
2179 fstring servicename_dos
;
2180 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2183 push_ascii_fstring(servicename_dos
, lp_servicename(talloc_tos(), lp_sub
, i
));
2184 /* Maximum name length = 13. */
2185 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2187 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2188 if (data_len
< buf_len
) {
2191 string_len
+= s_len
;
2198 *rdata_len
= fixed_len
+ string_len
;
2199 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2204 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2209 for( i
= 0; i
< count
; i
++ ) {
2210 fstring servicename_dos
;
2211 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2215 push_ascii_fstring(servicename_dos
,
2216 lp_servicename(talloc_tos(), lp_sub
, i
));
2217 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2218 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2225 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2229 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2231 SSVAL(*rparam
,4,counted
);
2232 SSVAL(*rparam
,6,total
);
2234 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2235 counted
,total
,uLevel
,
2236 buf_len
,*rdata_len
,mdrcnt
));
2241 /****************************************************************************
2243 ****************************************************************************/
2245 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2246 connection_struct
*conn
,uint64_t vuid
,
2247 char *param
, int tpscnt
,
2248 char *data
, int tdscnt
,
2249 int mdrcnt
,int mprcnt
,
2250 char **rdata
,char **rparam
,
2251 int *rdata_len
,int *rparam_len
)
2253 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2254 char *str2
= skip_string(param
,tpscnt
,str1
);
2255 char *p
= skip_string(param
,tpscnt
,str2
);
2256 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2259 char *pathname
= NULL
;
2260 unsigned int offset
;
2262 size_t converted_size
;
2264 WERROR werr
= WERR_OK
;
2265 TALLOC_CTX
*mem_ctx
= talloc_tos();
2267 struct rpc_pipe_client
*cli
= NULL
;
2268 union srvsvc_NetShareInfo info
;
2269 struct srvsvc_NetShareInfo2 info2
;
2270 struct dcerpc_binding_handle
*b
;
2272 if (!str1
|| !str2
|| !p
) {
2276 /* check it's a supported variant */
2277 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2280 if (!check_share_info(uLevel
,str2
)) {
2287 /* Do we have a string ? */
2288 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2291 pull_ascii_fstring(sharename
,data
);
2297 /* only support disk share adds */
2298 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2302 offset
= IVAL(data
, 16);
2303 if (offset
>= mdrcnt
) {
2304 res
= ERRinvalidparam
;
2308 /* Do we have a string ? */
2309 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2312 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2314 offset
= IVAL(data
, 26);
2316 if (offset
>= mdrcnt
) {
2317 res
= ERRinvalidparam
;
2321 /* Do we have a string ? */
2322 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2326 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2327 offset
? (data
+offset
) : "", &converted_size
))
2329 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s\n",
2337 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
2339 conn
->sconn
->remote_address
,
2340 conn
->sconn
->local_address
,
2341 conn
->sconn
->msg_ctx
,
2343 if (!NT_STATUS_IS_OK(status
)) {
2344 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2345 nt_errstr(status
)));
2346 res
= W_ERROR_V(ntstatus_to_werror(status
));
2350 b
= cli
->binding_handle
;
2352 info2
.name
= sharename
;
2353 info2
.type
= STYPE_DISKTREE
;
2354 info2
.comment
= comment
;
2355 info2
.permissions
= 0;
2356 info2
.max_users
= 0;
2357 info2
.current_users
= 0;
2358 info2
.path
= pathname
;
2359 info2
.password
= NULL
;
2361 info
.info2
= &info2
;
2363 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2364 cli
->srv_name_slash
,
2369 if (!NT_STATUS_IS_OK(status
)) {
2370 res
= W_ERROR_V(ntstatus_to_werror(status
));
2373 if (!W_ERROR_IS_OK(werr
)) {
2374 res
= W_ERROR_V(werr
);
2379 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2383 SSVAL(*rparam
,0,NERR_Success
);
2384 SSVAL(*rparam
,2,0); /* converter word */
2385 SSVAL(*rparam
,4,*rdata_len
);
2393 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2398 SSVAL(*rparam
,0,res
);
2403 /****************************************************************************
2404 view list of groups available
2405 ****************************************************************************/
2407 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2408 connection_struct
*conn
,uint64_t vuid
,
2409 char *param
, int tpscnt
,
2410 char *data
, int tdscnt
,
2411 int mdrcnt
,int mprcnt
,
2412 char **rdata
,char **rparam
,
2413 int *rdata_len
,int *rparam_len
)
2417 int resume_context
, cli_buf_size
;
2418 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2419 char *str2
= skip_string(param
,tpscnt
,str1
);
2420 char *p
= skip_string(param
,tpscnt
,str2
);
2422 uint32_t num_groups
;
2423 uint32_t resume_handle
;
2424 struct rpc_pipe_client
*samr_pipe
= NULL
;
2425 struct policy_handle samr_handle
, domain_handle
;
2426 NTSTATUS status
, result
;
2427 struct dcerpc_binding_handle
*b
;
2429 if (!str1
|| !str2
|| !p
) {
2433 if (strcmp(str1
,"WrLeh") != 0) {
2438 * W-> resume context (number of users to skip)
2439 * r -> return parameter pointer to receive buffer
2440 * L -> length of receive buffer
2441 * e -> return parameter number of entries
2442 * h -> return parameter total number of users
2445 if (strcmp("B21",str2
) != 0) {
2449 status
= rpc_pipe_open_interface(
2450 talloc_tos(), &ndr_table_samr
,
2451 conn
->session_info
, conn
->sconn
->remote_address
,
2452 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2453 if (!NT_STATUS_IS_OK(status
)) {
2454 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2455 nt_errstr(status
)));
2459 b
= samr_pipe
->binding_handle
;
2461 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2462 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2464 if (!NT_STATUS_IS_OK(status
)) {
2465 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2466 nt_errstr(status
)));
2469 if (!NT_STATUS_IS_OK(result
)) {
2470 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2471 nt_errstr(result
)));
2475 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2476 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2477 get_global_sam_sid(), &domain_handle
,
2479 if (!NT_STATUS_IS_OK(status
)) {
2480 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2481 nt_errstr(status
)));
2482 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2485 if (!NT_STATUS_IS_OK(result
)) {
2486 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2487 nt_errstr(result
)));
2488 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2492 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2493 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2494 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2495 "%d\n", resume_context
, cli_buf_size
));
2497 *rdata_len
= cli_buf_size
;
2498 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2505 errflags
= NERR_Success
;
2510 struct samr_SamArray
*sam_entries
;
2511 uint32_t num_entries
;
2513 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2519 if (!NT_STATUS_IS_OK(status
)) {
2520 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2521 "%s\n", nt_errstr(status
)));
2524 if (!NT_STATUS_IS_OK(result
)) {
2526 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2527 "%s\n", nt_errstr(result
)));
2531 if (num_entries
== 0) {
2532 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2533 "no entries -- done\n"));
2537 for(i
=0; i
<num_entries
; i
++) {
2540 name
= sam_entries
->entries
[i
].name
.string
;
2542 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2543 /* set overflow error */
2544 DEBUG(3,("overflow on entry %d group %s\n", i
,
2550 /* truncate the name at 21 chars. */
2552 strlcpy(p
, name
, 21);
2553 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2555 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2560 if (errflags
!= NERR_Success
) {
2564 TALLOC_FREE(sam_entries
);
2567 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2568 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2570 *rdata_len
= PTR_DIFF(p
,*rdata
);
2573 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2577 SSVAL(*rparam
, 0, errflags
);
2578 SSVAL(*rparam
, 2, 0); /* converter word */
2579 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2580 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2585 /*******************************************************************
2586 Get groups that a user is a member of.
2587 ******************************************************************/
2589 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2590 connection_struct
*conn
,uint64_t vuid
,
2591 char *param
, int tpscnt
,
2592 char *data
, int tdscnt
,
2593 int mdrcnt
,int mprcnt
,
2594 char **rdata
,char **rparam
,
2595 int *rdata_len
,int *rparam_len
)
2597 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2598 char *str2
= skip_string(param
,tpscnt
,str1
);
2599 char *UserName
= skip_string(param
,tpscnt
,str2
);
2600 char *p
= skip_string(param
,tpscnt
,UserName
);
2601 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2602 const char *level_string
;
2608 struct rpc_pipe_client
*samr_pipe
= NULL
;
2609 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2610 struct lsa_String name
;
2611 struct lsa_Strings names
;
2612 struct samr_Ids type
, rid
;
2613 struct samr_RidWithAttributeArray
*rids
;
2614 NTSTATUS status
, result
;
2615 struct dcerpc_binding_handle
*b
;
2617 if (!str1
|| !str2
|| !UserName
|| !p
) {
2622 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2627 /* check it's a supported variant */
2629 if ( strcmp(str1
,"zWrLeh") != 0 )
2634 level_string
= "B21";
2640 if (strcmp(level_string
,str2
) != 0)
2643 *rdata_len
= mdrcnt
+ 1024;
2644 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2649 SSVAL(*rparam
,0,NERR_Success
);
2650 SSVAL(*rparam
,2,0); /* converter word */
2653 endp
= *rdata
+ *rdata_len
;
2655 status
= rpc_pipe_open_interface(
2656 talloc_tos(), &ndr_table_samr
,
2657 conn
->session_info
, conn
->sconn
->remote_address
,
2658 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2659 if (!NT_STATUS_IS_OK(status
)) {
2660 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2661 nt_errstr(status
)));
2665 b
= samr_pipe
->binding_handle
;
2667 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2668 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2670 if (!NT_STATUS_IS_OK(status
)) {
2671 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2672 nt_errstr(status
)));
2675 if (!NT_STATUS_IS_OK(result
)) {
2676 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2677 nt_errstr(result
)));
2681 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2682 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2683 get_global_sam_sid(), &domain_handle
,
2685 if (!NT_STATUS_IS_OK(status
)) {
2686 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2687 nt_errstr(status
)));
2690 if (!NT_STATUS_IS_OK(result
)) {
2691 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2692 nt_errstr(result
)));
2696 name
.string
= UserName
;
2698 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2699 &domain_handle
, 1, &name
,
2702 if (!NT_STATUS_IS_OK(status
)) {
2703 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2704 nt_errstr(status
)));
2707 if (!NT_STATUS_IS_OK(result
)) {
2708 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2709 nt_errstr(result
)));
2712 if (rid
.count
!= 1) {
2713 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2716 if (type
.count
!= 1) {
2717 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2721 if (type
.ids
[0] != SID_NAME_USER
) {
2722 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2723 sid_type_lookup(type
.ids
[0])));
2727 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2729 SAMR_USER_ACCESS_GET_GROUPS
,
2730 rid
.ids
[0], &user_handle
,
2732 if (!NT_STATUS_IS_OK(status
)) {
2733 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2734 nt_errstr(status
)));
2737 if (!NT_STATUS_IS_OK(result
)) {
2738 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2739 nt_errstr(result
)));
2743 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2744 &user_handle
, &rids
,
2746 if (!NT_STATUS_IS_OK(status
)) {
2747 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2748 nt_errstr(status
)));
2751 if (!NT_STATUS_IS_OK(result
)) {
2752 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2753 nt_errstr(result
)));
2757 for (i
=0; i
<rids
->count
; i
++) {
2759 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2761 1, &rids
->rids
[i
].rid
,
2764 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2765 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2771 *rdata_len
= PTR_DIFF(p
,*rdata
);
2773 SSVAL(*rparam
,4,count
); /* is this right?? */
2774 SSVAL(*rparam
,6,count
); /* is this right?? */
2779 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2781 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2783 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2788 /*******************************************************************
2790 ******************************************************************/
2792 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2793 connection_struct
*conn
, uint64_t vuid
,
2794 char *param
, int tpscnt
,
2795 char *data
, int tdscnt
,
2796 int mdrcnt
,int mprcnt
,
2797 char **rdata
,char **rparam
,
2798 int *rdata_len
,int *rparam_len
)
2803 int i
, resume_context
, cli_buf_size
;
2804 uint32_t resume_handle
;
2806 struct rpc_pipe_client
*samr_pipe
= NULL
;
2807 struct policy_handle samr_handle
, domain_handle
;
2808 NTSTATUS status
, result
;
2810 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2811 char *str2
= skip_string(param
,tpscnt
,str1
);
2812 char *p
= skip_string(param
,tpscnt
,str2
);
2815 struct dcerpc_binding_handle
*b
;
2817 if (!str1
|| !str2
|| !p
) {
2821 if (strcmp(str1
,"WrLeh") != 0)
2824 * W-> resume context (number of users to skip)
2825 * r -> return parameter pointer to receive buffer
2826 * L -> length of receive buffer
2827 * e -> return parameter number of entries
2828 * h -> return parameter total number of users
2831 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2832 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2833 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2834 resume_context
, cli_buf_size
));
2837 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2842 /* check it's a supported variant */
2843 if (strcmp("B21",str2
) != 0)
2846 *rdata_len
= cli_buf_size
;
2847 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2853 endp
= *rdata
+ *rdata_len
;
2855 status
= rpc_pipe_open_interface(
2856 talloc_tos(), &ndr_table_samr
,
2857 conn
->session_info
, conn
->sconn
->remote_address
,
2858 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2859 if (!NT_STATUS_IS_OK(status
)) {
2860 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2861 nt_errstr(status
)));
2865 b
= samr_pipe
->binding_handle
;
2867 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2868 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2870 if (!NT_STATUS_IS_OK(status
)) {
2871 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2872 nt_errstr(status
)));
2875 if (!NT_STATUS_IS_OK(result
)) {
2876 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2877 nt_errstr(result
)));
2881 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2882 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2883 get_global_sam_sid(), &domain_handle
,
2885 if (!NT_STATUS_IS_OK(status
)) {
2886 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2887 nt_errstr(status
)));
2888 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2891 if (!NT_STATUS_IS_OK(result
)) {
2892 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2893 nt_errstr(result
)));
2894 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2898 errflags
=NERR_Success
;
2903 struct samr_SamArray
*sam_entries
;
2904 uint32_t num_entries
;
2906 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2913 if (!NT_STATUS_IS_OK(status
)) {
2914 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2915 "%s\n", nt_errstr(status
)));
2918 if (!NT_STATUS_IS_OK(result
)) {
2919 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2920 "%s\n", nt_errstr(result
)));
2924 if (num_entries
== 0) {
2925 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2926 "no entries -- done\n"));
2930 for (i
=0; i
<num_entries
; i
++) {
2933 name
= sam_entries
->entries
[i
].name
.string
;
2935 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2936 &&(strlen(name
)<=21)) {
2937 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2938 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2939 "username %s\n",count_sent
,p
));
2943 /* set overflow error */
2944 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2945 "username %s\n",count_sent
,name
));
2951 if (errflags
!= NERR_Success
) {
2955 TALLOC_FREE(sam_entries
);
2958 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2959 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2961 *rdata_len
= PTR_DIFF(p
,*rdata
);
2963 SSVAL(*rparam
,0,errflags
);
2964 SSVAL(*rparam
,2,0); /* converter word */
2965 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2966 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2971 /****************************************************************************
2972 Get the time of day info.
2973 ****************************************************************************/
2975 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2976 connection_struct
*conn
,uint64_t vuid
,
2977 char *param
, int tpscnt
,
2978 char *data
, int tdscnt
,
2979 int mdrcnt
,int mprcnt
,
2980 char **rdata
,char **rparam
,
2981 int *rdata_len
,int *rparam_len
)
2984 time_t unixdate
= time(NULL
);
2988 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2994 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2999 SSVAL(*rparam
,0,NERR_Success
);
3000 SSVAL(*rparam
,2,0); /* converter word */
3004 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
3005 by NT in a "net time" operation,
3006 it seems to ignore the one below */
3008 /* the client expects to get localtime, not GMT, in this bit
3009 (I think, this needs testing) */
3010 t
= localtime(&unixdate
);
3015 SIVAL(p
,4,0); /* msecs ? */
3016 SCVAL(p
,8,t
->tm_hour
);
3017 SCVAL(p
,9,t
->tm_min
);
3018 SCVAL(p
,10,t
->tm_sec
);
3019 SCVAL(p
,11,0); /* hundredths of seconds */
3020 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
3021 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
3022 SCVAL(p
,16,t
->tm_mday
);
3023 SCVAL(p
,17,t
->tm_mon
+ 1);
3024 SSVAL(p
,18,1900+t
->tm_year
);
3025 SCVAL(p
,20,t
->tm_wday
);
3030 /****************************************************************************
3031 Set the user password (SamOEM version - gets plaintext).
3032 ****************************************************************************/
3034 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3035 connection_struct
*conn
,uint64_t vuid
,
3036 char *param
, int tpscnt
,
3037 char *data
, int tdscnt
,
3038 int mdrcnt
,int mprcnt
,
3039 char **rdata
,char **rparam
,
3040 int *rdata_len
,int *rparam_len
)
3043 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3045 TALLOC_CTX
*mem_ctx
= talloc_tos();
3046 NTSTATUS status
, result
;
3047 struct rpc_pipe_client
*cli
= NULL
;
3048 struct lsa_AsciiString server
, account
;
3049 struct samr_CryptPassword password
;
3050 struct samr_Password hash
;
3051 int errcode
= NERR_badpass
;
3053 struct dcerpc_binding_handle
*b
;
3056 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3066 SSVAL(*rparam
,0,NERR_badpass
);
3069 * Check the parameter definition is correct.
3072 /* Do we have a string ? */
3073 if (skip_string(param
,tpscnt
,p
) == 0) {
3076 if(!strequal(p
, "zsT")) {
3077 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3080 p
= skip_string(param
, tpscnt
, p
);
3085 /* Do we have a string ? */
3086 if (skip_string(param
,tpscnt
,p
) == 0) {
3089 if(!strequal(p
, "B516B16")) {
3090 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3093 p
= skip_string(param
,tpscnt
,p
);
3097 /* Do we have a string ? */
3098 if (skip_string(param
,tpscnt
,p
) == 0) {
3101 p
+= pull_ascii_fstring(user
,p
);
3103 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3105 if (tdscnt
!= 532) {
3106 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3110 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3111 if (bufsize
!= 532) {
3112 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3116 memcpy(password
.data
, data
, 516);
3117 memcpy(hash
.hash
, data
+516, 16);
3119 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
3121 conn
->sconn
->remote_address
,
3122 conn
->sconn
->local_address
,
3123 conn
->sconn
->msg_ctx
,
3125 if (!NT_STATUS_IS_OK(status
)) {
3126 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3127 nt_errstr(status
)));
3128 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3132 b
= cli
->binding_handle
;
3134 init_lsa_AsciiString(&server
, lp_netbios_name());
3135 init_lsa_AsciiString(&account
, user
);
3137 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3143 if (!NT_STATUS_IS_OK(status
)) {
3144 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3147 if (!NT_STATUS_IS_OK(result
)) {
3148 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3152 errcode
= NERR_Success
;
3154 SSVAL(*rparam
,0,errcode
);
3155 SSVAL(*rparam
,2,0); /* converter word */
3160 /****************************************************************************
3163 ****************************************************************************/
3165 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3166 connection_struct
*conn
,uint64_t vuid
,
3167 char *param
, int tpscnt
,
3168 char *data
, int tdscnt
,
3169 int mdrcnt
,int mprcnt
,
3170 char **rdata
,char **rparam
,
3171 int *rdata_len
,int *rparam_len
)
3173 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3174 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3175 char *str2
= skip_string(param
,tpscnt
,str1
);
3176 char *p
= skip_string(param
,tpscnt
,str2
);
3180 WERROR werr
= WERR_OK
;
3182 TALLOC_CTX
*mem_ctx
= talloc_tos();
3184 struct rpc_pipe_client
*cli
= NULL
;
3185 struct dcerpc_binding_handle
*b
= NULL
;
3186 struct policy_handle handle
;
3187 struct spoolss_DevmodeContainer devmode_ctr
;
3188 enum spoolss_JobControl command
;
3190 if (!str1
|| !str2
|| !p
) {
3194 * We use 1 here not 2 as we're checking
3195 * the last byte we want to access is safe.
3197 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3200 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3203 /* check it's a supported variant */
3204 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3208 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3214 ZERO_STRUCT(handle
);
3216 status
= rpc_pipe_open_interface(mem_ctx
,
3219 conn
->sconn
->remote_address
,
3220 conn
->sconn
->local_address
,
3221 conn
->sconn
->msg_ctx
,
3223 if (!NT_STATUS_IS_OK(status
)) {
3224 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3225 nt_errstr(status
)));
3226 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3229 b
= cli
->binding_handle
;
3231 ZERO_STRUCT(devmode_ctr
);
3233 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3237 JOB_ACCESS_ADMINISTER
,
3240 if (!NT_STATUS_IS_OK(status
)) {
3241 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3244 if (!W_ERROR_IS_OK(werr
)) {
3245 errcode
= W_ERROR_V(werr
);
3249 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3250 * and NERR_DestNotFound if share did not exist */
3252 errcode
= NERR_Success
;
3255 case 81: /* delete */
3256 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3258 case 82: /* pause */
3259 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3261 case 83: /* resume */
3262 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3265 errcode
= NERR_notsupported
;
3269 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3272 NULL
, /* unique ptr ctr */
3275 if (!NT_STATUS_IS_OK(status
)) {
3276 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3279 if (!W_ERROR_IS_OK(werr
)) {
3280 errcode
= W_ERROR_V(werr
);
3285 if (b
&& is_valid_policy_hnd(&handle
)) {
3286 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3289 SSVAL(*rparam
,0,errcode
);
3290 SSVAL(*rparam
,2,0); /* converter word */
3295 /****************************************************************************
3296 Purge a print queue - or pause or resume it.
3297 ****************************************************************************/
3299 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3300 connection_struct
*conn
,uint64_t vuid
,
3301 char *param
, int tpscnt
,
3302 char *data
, int tdscnt
,
3303 int mdrcnt
,int mprcnt
,
3304 char **rdata
,char **rparam
,
3305 int *rdata_len
,int *rparam_len
)
3307 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3308 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3309 char *str2
= skip_string(param
,tpscnt
,str1
);
3310 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3311 int errcode
= NERR_notsupported
;
3312 WERROR werr
= WERR_OK
;
3315 TALLOC_CTX
*mem_ctx
= talloc_tos();
3316 struct rpc_pipe_client
*cli
= NULL
;
3317 struct dcerpc_binding_handle
*b
= NULL
;
3318 struct policy_handle handle
;
3319 struct spoolss_SetPrinterInfoCtr info_ctr
;
3320 struct spoolss_DevmodeContainer devmode_ctr
;
3321 struct sec_desc_buf secdesc_ctr
;
3322 enum spoolss_PrinterControl command
= SPOOLSS_PRINTER_CONTROL_UNPAUSE
;
3324 if (!str1
|| !str2
|| !QueueName
) {
3328 /* check it's a supported variant */
3329 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3333 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3339 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3343 ZERO_STRUCT(handle
);
3345 status
= rpc_pipe_open_interface(mem_ctx
,
3348 conn
->sconn
->remote_address
,
3349 conn
->sconn
->local_address
,
3350 conn
->sconn
->msg_ctx
,
3352 if (!NT_STATUS_IS_OK(status
)) {
3353 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3354 nt_errstr(status
)));
3355 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3358 b
= cli
->binding_handle
;
3360 ZERO_STRUCT(devmode_ctr
);
3362 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3366 PRINTER_ACCESS_ADMINISTER
,
3369 if (!NT_STATUS_IS_OK(status
)) {
3370 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3373 if (!W_ERROR_IS_OK(werr
)) {
3374 errcode
= W_ERROR_V(werr
);
3379 case 74: /* Pause queue */
3380 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3382 case 75: /* Resume queue */
3383 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3385 case 103: /* Purge */
3386 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3389 werr
= WERR_NOT_SUPPORTED
;
3393 if (!W_ERROR_IS_OK(werr
)) {
3394 errcode
= W_ERROR_V(werr
);
3398 ZERO_STRUCT(info_ctr
);
3399 ZERO_STRUCT(secdesc_ctr
);
3401 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3408 if (!NT_STATUS_IS_OK(status
)) {
3409 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3412 if (!W_ERROR_IS_OK(werr
)) {
3413 errcode
= W_ERROR_V(werr
);
3417 errcode
= W_ERROR_V(werr
);
3421 if (b
&& is_valid_policy_hnd(&handle
)) {
3422 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3425 SSVAL(*rparam
,0,errcode
);
3426 SSVAL(*rparam
,2,0); /* converter word */
3431 /****************************************************************************
3432 set the property of a print job (undocumented?)
3433 ? function = 0xb -> set name of print job
3434 ? function = 0x6 -> move print job up/down
3435 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3436 or <WWsTP> <WB21BB16B10zWWzDDz>
3437 ****************************************************************************/
3439 static int check_printjob_info(struct pack_desc
* desc
,
3440 int uLevel
, char* id
)
3442 desc
->subformat
= NULL
;
3444 case 0: desc
->format
= "W"; break;
3445 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3446 case 2: desc
->format
= "WWzWWDDzz"; break;
3447 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3448 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3450 DEBUG(0,("check_printjob_info: invalid level %d\n",
3454 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3455 DEBUG(0,("check_printjob_info: invalid format %s\n",
3456 id
? id
: "<NULL>" ));
3462 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3463 connection_struct
*conn
, uint64_t vuid
,
3464 char *param
, int tpscnt
,
3465 char *data
, int tdscnt
,
3466 int mdrcnt
,int mprcnt
,
3467 char **rdata
,char **rparam
,
3468 int *rdata_len
,int *rparam_len
)
3470 struct pack_desc desc
;
3471 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3472 char *str2
= skip_string(param
,tpscnt
,str1
);
3473 char *p
= skip_string(param
,tpscnt
,str2
);
3476 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3477 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3480 TALLOC_CTX
*mem_ctx
= talloc_tos();
3483 struct rpc_pipe_client
*cli
= NULL
;
3484 struct dcerpc_binding_handle
*b
= NULL
;
3485 struct policy_handle handle
;
3486 struct spoolss_DevmodeContainer devmode_ctr
;
3487 struct spoolss_JobInfoContainer ctr
;
3488 union spoolss_JobInfo info
;
3489 struct spoolss_SetJobInfo1 info1
;
3491 if (!str1
|| !str2
|| !p
) {
3495 * We use 1 here not 2 as we're checking
3496 * the last byte we want to access is safe.
3498 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3501 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3504 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3511 /* check it's a supported variant */
3512 if ((strcmp(str1
,"WWsTP")) ||
3513 (!check_printjob_info(&desc
,uLevel
,str2
)))
3516 errcode
= NERR_notsupported
;
3520 /* change print job name, data gives the name */
3526 ZERO_STRUCT(handle
);
3528 status
= rpc_pipe_open_interface(mem_ctx
,
3531 conn
->sconn
->remote_address
,
3532 conn
->sconn
->local_address
,
3533 conn
->sconn
->msg_ctx
,
3535 if (!NT_STATUS_IS_OK(status
)) {
3536 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3537 nt_errstr(status
)));
3538 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3541 b
= cli
->binding_handle
;
3543 ZERO_STRUCT(devmode_ctr
);
3545 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3552 if (!NT_STATUS_IS_OK(status
)) {
3553 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3556 if (!W_ERROR_IS_OK(werr
)) {
3557 errcode
= W_ERROR_V(werr
);
3561 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3567 if (!W_ERROR_IS_OK(werr
)) {
3568 errcode
= W_ERROR_V(werr
);
3574 info1
.job_id
= info
.info1
.job_id
;
3575 info1
.printer_name
= info
.info1
.printer_name
;
3576 info1
.user_name
= info
.info1
.user_name
;
3577 info1
.document_name
= data
;
3578 info1
.data_type
= info
.info1
.data_type
;
3579 info1
.text_status
= info
.info1
.text_status
;
3580 info1
.status
= info
.info1
.status
;
3581 info1
.priority
= info
.info1
.priority
;
3582 info1
.position
= info
.info1
.position
;
3583 info1
.total_pages
= info
.info1
.total_pages
;
3584 info1
.pages_printed
= info
.info1
.pages_printed
;
3585 info1
.submitted
= info
.info1
.submitted
;
3588 ctr
.info
.info1
= &info1
;
3590 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3596 if (!NT_STATUS_IS_OK(status
)) {
3597 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3600 if (!W_ERROR_IS_OK(werr
)) {
3601 errcode
= W_ERROR_V(werr
);
3605 errcode
= NERR_Success
;
3608 if (b
&& is_valid_policy_hnd(&handle
)) {
3609 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3612 SSVALS(*rparam
,0,errcode
);
3613 SSVAL(*rparam
,2,0); /* converter word */
3619 /****************************************************************************
3620 Get info about the server.
3621 ****************************************************************************/
3623 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3624 connection_struct
*conn
,uint64_t vuid
,
3625 char *param
, int tpscnt
,
3626 char *data
, int tdscnt
,
3627 int mdrcnt
,int mprcnt
,
3628 char **rdata
,char **rparam
,
3629 int *rdata_len
,int *rparam_len
)
3631 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3632 char *str2
= skip_string(param
,tpscnt
,str1
);
3633 char *p
= skip_string(param
,tpscnt
,str2
);
3634 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3640 TALLOC_CTX
*mem_ctx
= talloc_tos();
3641 struct rpc_pipe_client
*cli
= NULL
;
3642 union srvsvc_NetSrvInfo info
;
3644 struct dcerpc_binding_handle
*b
;
3646 if (!str1
|| !str2
|| !p
) {
3650 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3652 /* check it's a supported variant */
3653 if (!prefix_ok(str1
,"WrLh")) {
3659 if (strcmp(str2
,"B16") != 0) {
3665 if (strcmp(str2
,"B16BBDz") != 0) {
3671 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3677 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3683 if (strcmp(str2
,"DN") != 0) {
3689 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3698 *rdata_len
= mdrcnt
;
3699 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3705 p2
= p
+ struct_len
;
3707 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
3709 conn
->sconn
->remote_address
,
3710 conn
->sconn
->local_address
,
3711 conn
->sconn
->msg_ctx
,
3713 if (!NT_STATUS_IS_OK(status
)) {
3714 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3715 nt_errstr(status
)));
3716 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3720 b
= cli
->binding_handle
;
3722 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3727 if (!NT_STATUS_IS_OK(status
)) {
3728 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3731 if (!W_ERROR_IS_OK(werr
)) {
3732 errcode
= W_ERROR_V(werr
);
3736 if (info
.info101
== NULL
) {
3737 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3743 status
= srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3744 STR_ASCII
|STR_UPPER
|STR_TERMINATE
, &len
);
3745 if (!NT_STATUS_IS_OK(status
)) {
3746 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3752 SCVAL(p
,0,info
.info101
->version_major
);
3753 SCVAL(p
,1,info
.info101
->version_minor
);
3754 SIVAL(p
,2,info
.info101
->server_type
);
3756 if (mdrcnt
== struct_len
) {
3759 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3760 if (mdrcnt
- struct_len
<= 0) {
3764 info
.info101
->comment
,
3765 MIN(mdrcnt
- struct_len
,
3766 MAX_SERVER_STRING_LENGTH
),
3768 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3776 return False
; /* not yet implemented */
3779 errcode
= NERR_Success
;
3783 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3786 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3790 SSVAL(*rparam
,0,errcode
);
3791 SSVAL(*rparam
,2,0); /* converter word */
3792 SSVAL(*rparam
,4,*rdata_len
);
3797 /****************************************************************************
3798 Get info about the server.
3799 ****************************************************************************/
3801 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3802 connection_struct
*conn
,uint64_t vuid
,
3803 char *param
, int tpscnt
,
3804 char *data
, int tdscnt
,
3805 int mdrcnt
,int mprcnt
,
3806 char **rdata
,char **rparam
,
3807 int *rdata_len
,int *rparam_len
)
3809 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3810 char *str2
= skip_string(param
,tpscnt
,str1
);
3811 char *p
= skip_string(param
,tpscnt
,str2
);
3814 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3816 if (!str1
|| !str2
|| !p
) {
3820 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3823 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3828 /* check it's a supported variant */
3829 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3833 *rdata_len
= mdrcnt
+ 1024;
3834 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3839 SSVAL(*rparam
,0,NERR_Success
);
3840 SSVAL(*rparam
,2,0); /* converter word */
3843 endp
= *rdata
+ *rdata_len
;
3845 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3850 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3851 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3852 if (!strupper_m(p2
)) {
3855 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3861 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3862 strlcpy(p2
,conn
->session_info
->unix_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3863 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3869 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3870 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3871 if (!strupper_m(p2
)) {
3874 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3880 SCVAL(p
,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g 4 in 4.1 */
3881 SCVAL(p
,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g .1 in 4.1 */
3884 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3885 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3886 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3892 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3893 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3894 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3900 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3902 SSVAL(*rparam
,4,*rdata_len
);
3907 /****************************************************************************
3908 get info about a user
3910 struct user_info_11 {
3911 char usri11_name[21]; 0-20
3913 char *usri11_comment; 22-25
3914 char *usri11_usr_comment; 26-29
3915 unsigned short usri11_priv; 30-31
3916 unsigned long usri11_auth_flags; 32-35
3917 long usri11_password_age; 36-39
3918 char *usri11_homedir; 40-43
3919 char *usri11_parms; 44-47
3920 long usri11_last_logon; 48-51
3921 long usri11_last_logoff; 52-55
3922 unsigned short usri11_bad_pw_count; 56-57
3923 unsigned short usri11_num_logons; 58-59
3924 char *usri11_logon_server; 60-63
3925 unsigned short usri11_country_code; 64-65
3926 char *usri11_workstations; 66-69
3927 unsigned long usri11_max_storage; 70-73
3928 unsigned short usri11_units_per_week; 74-75
3929 unsigned char *usri11_logon_hours; 76-79
3930 unsigned short usri11_code_page; 80-81
3935 usri11_name specifies the user name for which information is retrieved
3937 usri11_pad aligns the next data structure element to a word boundary
3939 usri11_comment is a null terminated ASCII comment
3941 usri11_user_comment is a null terminated ASCII comment about the user
3943 usri11_priv specifies the level of the privilege assigned to the user.
3944 The possible values are:
3946 Name Value Description
3947 USER_PRIV_GUEST 0 Guest privilege
3948 USER_PRIV_USER 1 User privilege
3949 USER_PRV_ADMIN 2 Administrator privilege
3951 usri11_auth_flags specifies the account operator privileges. The
3952 possible values are:
3954 Name Value Description
3955 AF_OP_PRINT 0 Print operator
3958 Leach, Naik [Page 28]
3962 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3965 AF_OP_COMM 1 Communications operator
3966 AF_OP_SERVER 2 Server operator
3967 AF_OP_ACCOUNTS 3 Accounts operator
3970 usri11_password_age specifies how many seconds have elapsed since the
3971 password was last changed.
3973 usri11_home_dir points to a null terminated ASCII string that contains
3974 the path name of the user's home directory.
3976 usri11_parms points to a null terminated ASCII string that is set
3977 aside for use by applications.
3979 usri11_last_logon specifies the time when the user last logged on.
3980 This value is stored as the number of seconds elapsed since
3981 00:00:00, January 1, 1970.
3983 usri11_last_logoff specifies the time when the user last logged off.
3984 This value is stored as the number of seconds elapsed since
3985 00:00:00, January 1, 1970. A value of 0 means the last logoff
3988 usri11_bad_pw_count specifies the number of incorrect passwords
3989 entered since the last successful logon.
3991 usri11_log1_num_logons specifies the number of times this user has
3992 logged on. A value of -1 means the number of logons is unknown.
3994 usri11_logon_server points to a null terminated ASCII string that
3995 contains the name of the server to which logon requests are sent.
3996 A null string indicates logon requests should be sent to the
3999 usri11_country_code specifies the country code for the user's language
4002 usri11_workstations points to a null terminated ASCII string that
4003 contains the names of workstations the user may log on from.
4004 There may be up to 8 workstations, with the names separated by
4005 commas. A null strings indicates there are no restrictions.
4007 usri11_max_storage specifies the maximum amount of disk space the user
4008 can occupy. A value of 0xffffffff indicates there are no
4011 usri11_units_per_week specifies the equal number of time units into
4012 which a week is divided. This value must be equal to 168.
4014 usri11_logon_hours points to a 21 byte (168 bits) string that
4015 specifies the time during which the user can log on. Each bit
4016 represents one unique hour in a week. The first bit (bit 0, word
4017 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4021 Leach, Naik [Page 29]
4025 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4028 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4029 are no restrictions.
4031 usri11_code_page specifies the code page for the user's language of
4034 All of the pointers in this data structure need to be treated
4035 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4036 to be ignored. The converter word returned in the parameters section
4037 needs to be subtracted from the lower 16 bits to calculate an offset
4038 into the return buffer where this ASCII string resides.
4040 There is no auxiliary data in the response.
4042 ****************************************************************************/
4044 #define usri11_name 0
4045 #define usri11_pad 21
4046 #define usri11_comment 22
4047 #define usri11_usr_comment 26
4048 #define usri11_full_name 30
4049 #define usri11_priv 34
4050 #define usri11_auth_flags 36
4051 #define usri11_password_age 40
4052 #define usri11_homedir 44
4053 #define usri11_parms 48
4054 #define usri11_last_logon 52
4055 #define usri11_last_logoff 56
4056 #define usri11_bad_pw_count 60
4057 #define usri11_num_logons 62
4058 #define usri11_logon_server 64
4059 #define usri11_country_code 68
4060 #define usri11_workstations 70
4061 #define usri11_max_storage 74
4062 #define usri11_units_per_week 78
4063 #define usri11_logon_hours 80
4064 #define usri11_code_page 84
4065 #define usri11_end 86
4067 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4068 connection_struct
*conn
, uint64_t vuid
,
4069 char *param
, int tpscnt
,
4070 char *data
, int tdscnt
,
4071 int mdrcnt
,int mprcnt
,
4072 char **rdata
,char **rparam
,
4073 int *rdata_len
,int *rparam_len
)
4075 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4076 char *str2
= skip_string(param
,tpscnt
,str1
);
4077 char *UserName
= skip_string(param
,tpscnt
,str2
);
4078 char *p
= skip_string(param
,tpscnt
,UserName
);
4079 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4082 const char *level_string
;
4084 TALLOC_CTX
*mem_ctx
= talloc_tos();
4085 NTSTATUS status
, result
;
4086 struct rpc_pipe_client
*cli
= NULL
;
4087 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4088 struct lsa_String domain_name
;
4089 struct dom_sid2
*domain_sid
;
4090 struct lsa_String names
;
4091 struct samr_Ids rids
;
4092 struct samr_Ids types
;
4093 int errcode
= W_ERROR_V(WERR_NERR_USERNOTFOUND
);
4095 union samr_UserInfo
*info
;
4096 struct dcerpc_binding_handle
*b
= NULL
;
4098 if (!str1
|| !str2
|| !UserName
|| !p
) {
4103 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4108 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4110 /* check it's a supported variant */
4111 if (strcmp(str1
,"zWrLh") != 0) {
4115 case 0: level_string
= "B21"; break;
4116 case 1: level_string
= "B21BB16DWzzWz"; break;
4117 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4118 case 10: level_string
= "B21Bzzz"; break;
4119 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4120 default: return False
;
4123 if (strcmp(level_string
,str2
) != 0) {
4127 *rdata_len
= mdrcnt
+ 1024;
4128 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4134 endp
= *rdata
+ *rdata_len
;
4135 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4140 ZERO_STRUCT(connect_handle
);
4141 ZERO_STRUCT(domain_handle
);
4142 ZERO_STRUCT(user_handle
);
4144 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
4146 conn
->sconn
->remote_address
,
4147 conn
->sconn
->local_address
,
4148 conn
->sconn
->msg_ctx
,
4150 if (!NT_STATUS_IS_OK(status
)) {
4151 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4152 nt_errstr(status
)));
4153 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4157 b
= cli
->binding_handle
;
4159 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4161 SAMR_ACCESS_CONNECT_TO_SERVER
|
4162 SAMR_ACCESS_ENUM_DOMAINS
|
4163 SAMR_ACCESS_LOOKUP_DOMAIN
,
4166 if (!NT_STATUS_IS_OK(status
)) {
4167 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4170 if (!NT_STATUS_IS_OK(result
)) {
4171 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4175 init_lsa_String(&domain_name
, get_global_sam_name());
4177 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4182 if (!NT_STATUS_IS_OK(status
)) {
4183 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4186 if (!NT_STATUS_IS_OK(result
)) {
4187 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4191 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4193 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4197 if (!NT_STATUS_IS_OK(status
)) {
4198 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4201 if (!NT_STATUS_IS_OK(result
)) {
4202 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4206 init_lsa_String(&names
, UserName
);
4208 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4215 if (!NT_STATUS_IS_OK(status
)) {
4216 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4219 if (!NT_STATUS_IS_OK(result
)) {
4220 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4224 if (rids
.count
!= 1) {
4225 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4228 if (rids
.count
!= types
.count
) {
4229 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4232 if (types
.ids
[0] != SID_NAME_USER
) {
4233 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4239 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4241 SAMR_USER_ACCESS_GET_LOCALE
|
4242 SAMR_USER_ACCESS_GET_LOGONINFO
|
4243 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4244 SAMR_USER_ACCESS_GET_GROUPS
|
4245 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4246 SEC_STD_READ_CONTROL
,
4250 if (!NT_STATUS_IS_OK(status
)) {
4251 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4254 if (!NT_STATUS_IS_OK(result
)) {
4255 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4259 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4264 if (!NT_STATUS_IS_OK(status
)) {
4265 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4268 if (!NT_STATUS_IS_OK(result
)) {
4269 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4274 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4277 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4282 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4283 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4284 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4289 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4290 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4291 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4296 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4297 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4298 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4299 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4306 const char *homedir
= info
->info21
.home_directory
.string
;
4307 /* modelled after NTAS 3.51 reply */
4308 SSVAL(p
,usri11_priv
,
4309 (get_current_uid(conn
) == sec_initial_uid())?
4310 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4311 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4312 SIVALS(p
,usri11_password_age
,-1); /* password age */
4313 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4314 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4315 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4319 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4320 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4321 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4325 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4326 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4327 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4328 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4329 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4330 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4331 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4335 SSVAL(p
,usri11_country_code
,0); /* country code */
4337 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4338 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4339 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4344 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4345 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4346 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4348 /* a simple way to get logon hours at all times. */
4350 SCVAL(p2
,21,0); /* fix zero termination */
4351 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4356 SSVAL(p
,usri11_code_page
,0); /* code page */
4359 if (uLevel
== 1 || uLevel
== 2) {
4360 memset(p
+22,' ',16); /* password */
4361 SIVALS(p
,38,-1); /* password age */
4363 (get_current_uid(conn
) == sec_initial_uid())?
4364 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4365 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4366 strlcpy(p2
, info
->info21
.home_directory
.string
,
4368 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4372 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4374 SSVAL(p
,52,0); /* flags */
4375 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4376 strlcpy(p2
, info
->info21
.logon_script
.string
,
4378 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4383 SIVAL(p
,58,0); /* auth_flags */
4384 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4385 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4386 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4390 SIVAL(p
,66,0); /* urs_comment */
4391 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4392 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4393 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4397 SIVAL(p
,74,0); /* workstations */
4398 SIVAL(p
,78,0); /* last_logon */
4399 SIVAL(p
,82,0); /* last_logoff */
4400 SIVALS(p
,86,-1); /* acct_expires */
4401 SIVALS(p
,90,-1); /* max_storage */
4402 SSVAL(p
,94,168); /* units_per_week */
4403 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4406 SSVALS(p
,100,-1); /* bad_pw_count */
4407 SSVALS(p
,102,-1); /* num_logons */
4408 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4410 TALLOC_CTX
*ctx
= talloc_tos();
4411 int space_rem
= *rdata_len
- (p2
- *rdata
);
4414 if (space_rem
<= 0) {
4417 tmp
= talloc_strdup(ctx
, "\\\\%L");
4421 tmp
= talloc_sub_basic(ctx
,
4434 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4438 SSVAL(p
,108,49); /* country_code */
4439 SSVAL(p
,110,860); /* code page */
4443 errcode
= NERR_Success
;
4446 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4448 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4449 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4451 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4452 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4454 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4455 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4458 SSVAL(*rparam
,0,errcode
);
4459 SSVAL(*rparam
,2,0); /* converter word */
4460 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4465 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4466 connection_struct
*conn
,uint64_t vuid
,
4467 char *param
, int tpscnt
,
4468 char *data
, int tdscnt
,
4469 int mdrcnt
,int mprcnt
,
4470 char **rdata
,char **rparam
,
4471 int *rdata_len
,int *rparam_len
)
4473 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4474 char *str2
= skip_string(param
,tpscnt
,str1
);
4475 char *p
= skip_string(param
,tpscnt
,str2
);
4477 struct pack_desc desc
;
4479 struct auth_session_info
*si
= NULL
;
4482 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
4485 if (!NT_STATUS_IS_OK(status
)) {
4489 if (!str1
|| !str2
|| !p
) {
4493 DBG_INFO("Username of UID %ju is %s\n",
4494 (uintmax_t)si
->unix_token
->uid
,
4495 si
->unix_info
->unix_name
);
4497 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4498 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4503 memset((char *)&desc
,'\0',sizeof(desc
));
4505 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4507 /* check it's a supported variant */
4508 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4511 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4515 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4522 desc
.buflen
= mdrcnt
;
4523 desc
.subformat
= NULL
;
4526 if (init_package(&desc
,1,0)) {
4527 PACKI(&desc
,"W",0); /* code */
4528 PACKS(&desc
,"B21",name
); /* eff. name */
4529 PACKS(&desc
,"B",""); /* pad */
4531 (get_current_uid(conn
) == sec_initial_uid())?
4532 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4533 PACKI(&desc
,"D",0); /* auth flags XXX */
4534 PACKI(&desc
,"W",0); /* num logons */
4535 PACKI(&desc
,"W",0); /* bad pw count */
4536 PACKI(&desc
,"D",0); /* last logon */
4537 PACKI(&desc
,"D",-1); /* last logoff */
4538 PACKI(&desc
,"D",-1); /* logoff time */
4539 PACKI(&desc
,"D",-1); /* kickoff time */
4540 PACKI(&desc
,"D",0); /* password age */
4541 PACKI(&desc
,"D",0); /* password can change */
4542 PACKI(&desc
,"D",-1); /* password must change */
4546 fstrcpy(mypath
,"\\\\");
4547 fstrcat(mypath
,get_local_machine_name());
4548 if (!strupper_m(mypath
)) {
4551 PACKS(&desc
,"z",mypath
); /* computer */
4554 PACKS(&desc
,"z",lp_workgroup());/* domain */
4555 PACKS(&desc
,"z", si
->info
->logon_script
); /* script path */
4556 PACKI(&desc
,"D",0x00000000); /* reserved */
4559 *rdata_len
= desc
.usedlen
;
4561 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4565 SSVALS(*rparam
,0,desc
.errcode
);
4567 SSVAL(*rparam
,4,desc
.neededlen
);
4569 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4574 /****************************************************************************
4575 api_WAccessGetUserPerms
4576 ****************************************************************************/
4578 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4579 connection_struct
*conn
,uint64_t vuid
,
4580 char *param
, int tpscnt
,
4581 char *data
, int tdscnt
,
4582 int mdrcnt
,int mprcnt
,
4583 char **rdata
,char **rparam
,
4584 int *rdata_len
,int *rparam_len
)
4586 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4587 char *str2
= skip_string(param
,tpscnt
,str1
);
4588 char *user
= skip_string(param
,tpscnt
,str2
);
4589 char *resource
= skip_string(param
,tpscnt
,user
);
4591 if (!str1
|| !str2
|| !user
|| !resource
) {
4595 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4598 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4600 /* check it's a supported variant */
4601 if (strcmp(str1
,"zzh") != 0) {
4604 if (strcmp(str2
,"") != 0) {
4609 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4613 SSVALS(*rparam
,0,0); /* errorcode */
4614 SSVAL(*rparam
,2,0); /* converter word */
4615 SSVAL(*rparam
,4,0x7f); /* permission flags */
4620 /****************************************************************************
4621 api_WPrintJobEnumerate
4622 ****************************************************************************/
4624 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4625 connection_struct
*conn
, uint64_t vuid
,
4626 char *param
, int tpscnt
,
4627 char *data
, int tdscnt
,
4628 int mdrcnt
,int mprcnt
,
4629 char **rdata
,char **rparam
,
4630 int *rdata_len
,int *rparam_len
)
4632 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4633 char *str2
= skip_string(param
,tpscnt
,str1
);
4634 char *p
= skip_string(param
,tpscnt
,str2
);
4638 struct pack_desc desc
;
4641 TALLOC_CTX
*mem_ctx
= talloc_tos();
4644 struct rpc_pipe_client
*cli
= NULL
;
4645 struct dcerpc_binding_handle
*b
= NULL
;
4646 struct policy_handle handle
;
4647 struct spoolss_DevmodeContainer devmode_ctr
;
4648 union spoolss_JobInfo info
;
4650 if (!str1
|| !str2
|| !p
) {
4654 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4656 memset((char *)&desc
,'\0',sizeof(desc
));
4657 memset((char *)&status
,'\0',sizeof(status
));
4659 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4661 /* check it's a supported variant */
4662 if (strcmp(str1
,"WWrLh") != 0) {
4665 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4669 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4673 ZERO_STRUCT(handle
);
4675 status
= rpc_pipe_open_interface(mem_ctx
,
4678 conn
->sconn
->remote_address
,
4679 conn
->sconn
->local_address
,
4680 conn
->sconn
->msg_ctx
,
4682 if (!NT_STATUS_IS_OK(status
)) {
4683 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4684 nt_errstr(status
)));
4685 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4688 b
= cli
->binding_handle
;
4690 ZERO_STRUCT(devmode_ctr
);
4692 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4699 if (!NT_STATUS_IS_OK(status
)) {
4700 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4703 if (!W_ERROR_IS_OK(werr
)) {
4704 desc
.errcode
= W_ERROR_V(werr
);
4708 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4714 if (!W_ERROR_IS_OK(werr
)) {
4715 desc
.errcode
= W_ERROR_V(werr
);
4720 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4725 desc
.buflen
= mdrcnt
;
4728 * Don't return data but need to get correct length
4729 * init_package will return wrong size if buflen=0
4731 desc
.buflen
= getlen(desc
.format
);
4732 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4735 if (init_package(&desc
,1,0)) {
4736 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4737 *rdata_len
= desc
.usedlen
;
4739 desc
.errcode
= NERR_JobNotFound
;
4743 if (b
&& is_valid_policy_hnd(&handle
)) {
4744 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4748 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4752 SSVALS(*rparam
,0,desc
.errcode
);
4754 SSVAL(*rparam
,4,desc
.neededlen
);
4758 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4763 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4764 connection_struct
*conn
, uint64_t vuid
,
4765 char *param
, int tpscnt
,
4766 char *data
, int tdscnt
,
4767 int mdrcnt
,int mprcnt
,
4768 char **rdata
,char **rparam
,
4769 int *rdata_len
,int *rparam_len
)
4771 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4772 char *str2
= skip_string(param
,tpscnt
,str1
);
4773 char *p
= skip_string(param
,tpscnt
,str2
);
4777 struct pack_desc desc
;
4779 TALLOC_CTX
*mem_ctx
= talloc_tos();
4782 struct rpc_pipe_client
*cli
= NULL
;
4783 struct dcerpc_binding_handle
*b
= NULL
;
4784 struct policy_handle handle
;
4785 struct spoolss_DevmodeContainer devmode_ctr
;
4787 union spoolss_JobInfo
*info
;
4789 if (!str1
|| !str2
|| !p
) {
4793 memset((char *)&desc
,'\0',sizeof(desc
));
4795 p
= skip_string(param
,tpscnt
,p
);
4799 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4801 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4803 /* check it's a supported variant */
4804 if (strcmp(str1
,"zWrLeh") != 0) {
4809 return False
; /* defined only for uLevel 0,1,2 */
4812 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4816 ZERO_STRUCT(handle
);
4818 status
= rpc_pipe_open_interface(mem_ctx
,
4821 conn
->sconn
->remote_address
,
4822 conn
->sconn
->local_address
,
4823 conn
->sconn
->msg_ctx
,
4825 if (!NT_STATUS_IS_OK(status
)) {
4826 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4827 nt_errstr(status
)));
4828 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4831 b
= cli
->binding_handle
;
4833 ZERO_STRUCT(devmode_ctr
);
4835 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4842 if (!NT_STATUS_IS_OK(status
)) {
4843 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4846 if (!W_ERROR_IS_OK(werr
)) {
4847 desc
.errcode
= W_ERROR_V(werr
);
4851 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4859 if (!W_ERROR_IS_OK(werr
)) {
4860 desc
.errcode
= W_ERROR_V(werr
);
4865 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4871 desc
.buflen
= mdrcnt
;
4873 if (init_package(&desc
,count
,0)) {
4875 for (i
= 0; i
< count
; i
++) {
4876 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4877 if (desc
.errcode
== NERR_Success
) {
4883 if (b
&& is_valid_policy_hnd(&handle
)) {
4884 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4887 *rdata_len
= desc
.usedlen
;
4890 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4894 SSVALS(*rparam
,0,desc
.errcode
);
4896 SSVAL(*rparam
,4,succnt
);
4897 SSVAL(*rparam
,6,count
);
4899 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4904 static int check_printdest_info(struct pack_desc
* desc
,
4905 int uLevel
, char* id
)
4907 desc
->subformat
= NULL
;
4910 desc
->format
= "B9";
4913 desc
->format
= "B9B21WWzW";
4919 desc
->format
= "zzzWWzzzWW";
4922 DEBUG(0,("check_printdest_info: invalid level %d\n",
4926 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4927 DEBUG(0,("check_printdest_info: invalid string %s\n",
4928 id
? id
: "<NULL>" ));
4934 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4935 struct pack_desc
* desc
)
4939 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4940 buf
[sizeof(buf
)-1] = 0;
4941 (void)strupper_m(buf
);
4944 PACKS(desc
,"B9",buf
); /* szName */
4946 PACKS(desc
,"B21",""); /* szUserName */
4947 PACKI(desc
,"W",0); /* uJobId */
4948 PACKI(desc
,"W",0); /* fsStatus */
4949 PACKS(desc
,"z",""); /* pszStatus */
4950 PACKI(desc
,"W",0); /* time */
4954 if (uLevel
== 2 || uLevel
== 3) {
4955 PACKS(desc
,"z",buf
); /* pszPrinterName */
4957 PACKS(desc
,"z",""); /* pszUserName */
4958 PACKS(desc
,"z",""); /* pszLogAddr */
4959 PACKI(desc
,"W",0); /* uJobId */
4960 PACKI(desc
,"W",0); /* fsStatus */
4961 PACKS(desc
,"z",""); /* pszStatus */
4962 PACKS(desc
,"z",""); /* pszComment */
4963 PACKS(desc
,"z","NULL"); /* pszDrivers */
4964 PACKI(desc
,"W",0); /* time */
4965 PACKI(desc
,"W",0); /* pad1 */
4970 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4971 connection_struct
*conn
, uint64_t vuid
,
4972 char *param
, int tpscnt
,
4973 char *data
, int tdscnt
,
4974 int mdrcnt
,int mprcnt
,
4975 char **rdata
,char **rparam
,
4976 int *rdata_len
,int *rparam_len
)
4978 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4979 char *str2
= skip_string(param
,tpscnt
,str1
);
4980 char *p
= skip_string(param
,tpscnt
,str2
);
4981 char* PrinterName
= p
;
4983 struct pack_desc desc
;
4986 TALLOC_CTX
*mem_ctx
= talloc_tos();
4989 struct rpc_pipe_client
*cli
= NULL
;
4990 struct dcerpc_binding_handle
*b
= NULL
;
4991 struct policy_handle handle
;
4992 struct spoolss_DevmodeContainer devmode_ctr
;
4993 union spoolss_PrinterInfo info
;
4995 if (!str1
|| !str2
|| !p
) {
4999 memset((char *)&desc
,'\0',sizeof(desc
));
5001 p
= skip_string(param
,tpscnt
,p
);
5005 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5007 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
5009 /* check it's a supported variant */
5010 if (strcmp(str1
,"zWrLh") != 0) {
5013 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5017 ZERO_STRUCT(handle
);
5019 status
= rpc_pipe_open_interface(mem_ctx
,
5022 conn
->sconn
->remote_address
,
5023 conn
->sconn
->local_address
,
5024 conn
->sconn
->msg_ctx
,
5026 if (!NT_STATUS_IS_OK(status
)) {
5027 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5028 nt_errstr(status
)));
5029 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5032 b
= cli
->binding_handle
;
5034 ZERO_STRUCT(devmode_ctr
);
5036 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5043 if (!NT_STATUS_IS_OK(status
)) {
5045 desc
.errcode
= NERR_DestNotFound
;
5049 if (!W_ERROR_IS_OK(werr
)) {
5051 desc
.errcode
= NERR_DestNotFound
;
5056 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5061 if (!W_ERROR_IS_OK(werr
)) {
5063 desc
.errcode
= NERR_DestNotFound
;
5069 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5074 desc
.buflen
= mdrcnt
;
5077 * Don't return data but need to get correct length
5078 * init_package will return wrong size if buflen=0
5080 desc
.buflen
= getlen(desc
.format
);
5081 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5083 if (init_package(&desc
,1,0)) {
5084 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5088 if (b
&& is_valid_policy_hnd(&handle
)) {
5089 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5092 *rdata_len
= desc
.usedlen
;
5095 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5099 SSVALS(*rparam
,0,desc
.errcode
);
5101 SSVAL(*rparam
,4,desc
.neededlen
);
5103 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5109 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5110 connection_struct
*conn
, uint64_t vuid
,
5111 char *param
, int tpscnt
,
5112 char *data
, int tdscnt
,
5113 int mdrcnt
,int mprcnt
,
5114 char **rdata
,char **rparam
,
5115 int *rdata_len
,int *rparam_len
)
5117 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5118 char *str2
= skip_string(param
,tpscnt
,str1
);
5119 char *p
= skip_string(param
,tpscnt
,str2
);
5123 struct pack_desc desc
;
5125 TALLOC_CTX
*mem_ctx
= talloc_tos();
5128 struct rpc_pipe_client
*cli
= NULL
;
5129 union spoolss_PrinterInfo
*info
;
5132 if (!str1
|| !str2
|| !p
) {
5136 memset((char *)&desc
,'\0',sizeof(desc
));
5138 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5140 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5142 /* check it's a supported variant */
5143 if (strcmp(str1
,"WrLeh") != 0) {
5146 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5152 status
= rpc_pipe_open_interface(mem_ctx
,
5155 conn
->sconn
->remote_address
,
5156 conn
->sconn
->local_address
,
5157 conn
->sconn
->msg_ctx
,
5159 if (!NT_STATUS_IS_OK(status
)) {
5160 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5161 nt_errstr(status
)));
5162 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5166 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5168 cli
->srv_name_slash
,
5173 if (!W_ERROR_IS_OK(werr
)) {
5174 desc
.errcode
= W_ERROR_V(werr
);
5176 desc
.errcode
= NERR_DestNotFound
;
5184 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5191 desc
.buflen
= mdrcnt
;
5192 if (init_package(&desc
,queuecnt
,0)) {
5195 for (i
= 0; i
< count
; i
++) {
5196 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5198 if (desc
.errcode
== NERR_Success
) {
5204 *rdata_len
= desc
.usedlen
;
5207 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5211 SSVALS(*rparam
,0,desc
.errcode
);
5213 SSVAL(*rparam
,4,succnt
);
5214 SSVAL(*rparam
,6,queuecnt
);
5216 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5221 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5222 connection_struct
*conn
, uint64_t vuid
,
5223 char *param
, int tpscnt
,
5224 char *data
, int tdscnt
,
5225 int mdrcnt
,int mprcnt
,
5226 char **rdata
,char **rparam
,
5227 int *rdata_len
,int *rparam_len
)
5229 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5230 char *str2
= skip_string(param
,tpscnt
,str1
);
5231 char *p
= skip_string(param
,tpscnt
,str2
);
5234 struct pack_desc desc
;
5236 if (!str1
|| !str2
|| !p
) {
5240 memset((char *)&desc
,'\0',sizeof(desc
));
5242 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5244 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5246 /* check it's a supported variant */
5247 if (strcmp(str1
,"WrLeh") != 0) {
5250 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5255 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5261 desc
.buflen
= mdrcnt
;
5262 if (init_package(&desc
,1,0)) {
5263 PACKS(&desc
,"B41","NULL");
5266 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5268 *rdata_len
= desc
.usedlen
;
5271 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5275 SSVALS(*rparam
,0,desc
.errcode
);
5277 SSVAL(*rparam
,4,succnt
);
5280 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5285 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5286 connection_struct
*conn
, uint64_t vuid
,
5287 char *param
, int tpscnt
,
5288 char *data
, int tdscnt
,
5289 int mdrcnt
,int mprcnt
,
5290 char **rdata
,char **rparam
,
5291 int *rdata_len
,int *rparam_len
)
5293 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5294 char *str2
= skip_string(param
,tpscnt
,str1
);
5295 char *p
= skip_string(param
,tpscnt
,str2
);
5298 struct pack_desc desc
;
5300 if (!str1
|| !str2
|| !p
) {
5303 memset((char *)&desc
,'\0',sizeof(desc
));
5305 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5307 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5309 /* check it's a supported variant */
5310 if (strcmp(str1
,"WrLeh") != 0) {
5313 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5318 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5324 desc
.buflen
= mdrcnt
;
5326 if (init_package(&desc
,1,0)) {
5327 PACKS(&desc
,"B13","lpd");
5330 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5332 *rdata_len
= desc
.usedlen
;
5335 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5339 SSVALS(*rparam
,0,desc
.errcode
);
5341 SSVAL(*rparam
,4,succnt
);
5344 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5349 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5350 connection_struct
*conn
, uint64_t vuid
,
5351 char *param
, int tpscnt
,
5352 char *data
, int tdscnt
,
5353 int mdrcnt
,int mprcnt
,
5354 char **rdata
,char **rparam
,
5355 int *rdata_len
,int *rparam_len
)
5357 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5358 char *str2
= skip_string(param
,tpscnt
,str1
);
5359 char *p
= skip_string(param
,tpscnt
,str2
);
5362 struct pack_desc desc
;
5364 if (!str1
|| !str2
|| !p
) {
5368 memset((char *)&desc
,'\0',sizeof(desc
));
5370 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5372 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5374 /* check it's a supported variant */
5375 if (strcmp(str1
,"WrLeh") != 0) {
5378 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5383 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5388 memset((char *)&desc
,'\0',sizeof(desc
));
5390 desc
.buflen
= mdrcnt
;
5392 if (init_package(&desc
,1,0)) {
5393 PACKS(&desc
,"B13","lp0");
5396 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5398 *rdata_len
= desc
.usedlen
;
5401 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5405 SSVALS(*rparam
,0,desc
.errcode
);
5407 SSVAL(*rparam
,4,succnt
);
5410 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5415 /****************************************************************************
5417 ****************************************************************************/
5419 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5420 connection_struct
*conn
, uint64_t vuid
,
5421 char *param
, int tpscnt
,
5422 char *data
, int tdscnt
,
5423 int mdrcnt
,int mprcnt
,
5424 char **rdata
,char **rparam
,
5425 int *rdata_len
,int *rparam_len
)
5428 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5429 char *str2
= skip_string(param
,tpscnt
,str1
);
5430 char *p
= skip_string(param
,tpscnt
,str2
);
5432 struct pack_desc desc
;
5435 TALLOC_CTX
*mem_ctx
= talloc_tos();
5438 struct rpc_pipe_client
*cli
= NULL
;
5439 struct dcerpc_binding_handle
*b
= NULL
;
5440 struct srvsvc_NetSessInfoCtr info_ctr
;
5441 uint32_t totalentries
, resume_handle
= 0;
5444 if (!str1
|| !str2
|| !p
) {
5450 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5452 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5453 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5454 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5456 /* check it's a supported variant */
5457 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5460 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5464 status
= rpc_pipe_open_interface(mem_ctx
,
5467 conn
->sconn
->remote_address
,
5468 conn
->sconn
->local_address
,
5469 conn
->sconn
->msg_ctx
,
5471 if (!NT_STATUS_IS_OK(status
)) {
5472 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5473 nt_errstr(status
)));
5474 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5477 b
= cli
->binding_handle
;
5480 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5481 if (info_ctr
.ctr
.ctr1
== NULL
) {
5482 desc
.errcode
= W_ERROR_V(WERR_NOT_ENOUGH_MEMORY
);
5486 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5487 cli
->srv_name_slash
,
5491 (uint32_t)-1, /* max_buffer */
5495 if (!NT_STATUS_IS_OK(status
)) {
5496 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5497 nt_errstr(status
)));
5498 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5502 if (!W_ERROR_IS_OK(werr
)) {
5503 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5505 desc
.errcode
= W_ERROR_V(werr
);
5509 count
= info_ctr
.ctr
.ctr1
->count
;
5513 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5520 desc
.buflen
= mdrcnt
;
5522 if (!init_package(&desc
, count
,0)) {
5526 for(i
=0; i
< count
; i
++) {
5527 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5528 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5529 PACKI(&desc
, "W", 1); /* num conns */
5530 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5531 PACKI(&desc
, "W", 1); /* num users */
5532 PACKI(&desc
, "D", 0); /* session time */
5533 PACKI(&desc
, "D", 0); /* idle time */
5534 PACKI(&desc
, "D", 0); /* flags */
5535 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5538 *rdata_len
= desc
.usedlen
;
5541 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5545 SSVALS(*rparam
,0,desc
.errcode
);
5546 SSVAL(*rparam
,2,0); /* converter */
5547 SSVAL(*rparam
,4, count
); /* count */
5549 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5555 /****************************************************************************
5556 The buffer was too small.
5557 ****************************************************************************/
5559 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5560 connection_struct
*conn
,uint64_t vuid
, char *param
, char *data
,
5561 int mdrcnt
, int mprcnt
,
5562 char **rdata
, char **rparam
,
5563 int *rdata_len
, int *rparam_len
)
5565 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5566 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5573 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5575 DEBUG(3,("Supplied buffer too small in API command\n"));
5580 /****************************************************************************
5581 The request is not supported.
5582 ****************************************************************************/
5584 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5585 connection_struct
*conn
, uint64_t vuid
,
5586 char *param
, int tpscnt
,
5587 char *data
, int tdscnt
,
5588 int mdrcnt
, int mprcnt
,
5589 char **rdata
, char **rparam
,
5590 int *rdata_len
, int *rparam_len
)
5593 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5600 SSVAL(*rparam
,0,NERR_notsupported
);
5601 SSVAL(*rparam
,2,0); /* converter word */
5603 DEBUG(3,("Unsupported API command\n"));
5608 static const struct {
5611 bool (*fn
)(struct smbd_server_connection
*sconn
,
5612 connection_struct
*, uint64_t,
5615 int,int,char **,char **,int *,int *);
5616 bool auth_user
; /* Deny anonymous access? */
5617 } api_commands
[] = {
5619 .name
= "RNetShareEnum",
5620 .id
= RAP_WshareEnum
,
5621 .fn
= api_RNetShareEnum
,
5625 .name
= "RNetShareGetInfo",
5626 .id
= RAP_WshareGetInfo
,
5627 .fn
= api_RNetShareGetInfo
5630 .name
= "RNetShareAdd",
5631 .id
= RAP_WshareAdd
,
5632 .fn
= api_RNetShareAdd
5635 .name
= "RNetSessionEnum",
5636 .id
= RAP_WsessionEnum
,
5637 .fn
= api_RNetSessionEnum
,
5641 .name
= "RNetServerGetInfo",
5642 .id
= RAP_WserverGetInfo
,
5643 .fn
= api_RNetServerGetInfo
5646 .name
= "RNetGroupEnum",
5647 .id
= RAP_WGroupEnum
,
5648 .fn
= api_RNetGroupEnum
, True
5651 .name
= "RNetGroupGetUsers",
5652 .id
= RAP_WGroupGetUsers
,
5653 .fn
= api_RNetGroupGetUsers
,
5656 .name
= "RNetUserEnum",
5657 .id
= RAP_WUserEnum
,
5658 .fn
= api_RNetUserEnum
,
5662 .name
= "RNetUserGetInfo",
5663 .id
= RAP_WUserGetInfo
,
5664 .fn
= api_RNetUserGetInfo
5667 .name
= "NetUserGetGroups",
5668 .id
= RAP_WUserGetGroups
,
5669 .fn
= api_NetUserGetGroups
5672 .name
= "NetWkstaGetInfo",
5673 .id
= RAP_WWkstaGetInfo
,
5674 .fn
= api_NetWkstaGetInfo
5677 .name
= "DosPrintQEnum",
5678 .id
= RAP_WPrintQEnum
,
5679 .fn
= api_DosPrintQEnum
,
5683 .name
= "DosPrintQGetInfo",
5684 .id
= RAP_WPrintQGetInfo
,
5685 .fn
= api_DosPrintQGetInfo
5688 .name
= "WPrintQueuePause",
5689 .id
= RAP_WPrintQPause
,
5690 .fn
= api_WPrintQueueCtrl
5693 .name
= "WPrintQueueResume",
5694 .id
= RAP_WPrintQContinue
,
5695 .fn
= api_WPrintQueueCtrl
5698 .name
= "WPrintJobEnumerate",
5699 .id
= RAP_WPrintJobEnum
,
5700 .fn
= api_WPrintJobEnumerate
5703 .name
= "WPrintJobGetInfo",
5704 .id
= RAP_WPrintJobGetInfo
,
5705 .fn
= api_WPrintJobGetInfo
5708 .name
= "RDosPrintJobDel",
5709 .id
= RAP_WPrintJobDel
,
5710 .fn
= api_RDosPrintJobDel
5713 .name
= "RDosPrintJobPause",
5714 .id
= RAP_WPrintJobPause
,
5715 .fn
= api_RDosPrintJobDel
5718 .name
= "RDosPrintJobResume",
5719 .id
= RAP_WPrintJobContinue
,
5720 .fn
= api_RDosPrintJobDel
5723 .name
= "WPrintDestEnum",
5724 .id
= RAP_WPrintDestEnum
,
5725 .fn
= api_WPrintDestEnum
5728 .name
= "WPrintDestGetInfo",
5729 .id
= RAP_WPrintDestGetInfo
,
5730 .fn
= api_WPrintDestGetInfo
5733 .name
= "NetRemoteTOD",
5734 .id
= RAP_NetRemoteTOD
,
5735 .fn
= api_NetRemoteTOD
5738 .name
= "WPrintQueuePurge",
5739 .id
= RAP_WPrintQPurge
,
5740 .fn
= api_WPrintQueueCtrl
5743 .name
= "NetServerEnum2",
5744 .id
= RAP_NetServerEnum2
,
5745 .fn
= api_RNetServerEnum2
5748 .name
= "NetServerEnum3",
5749 .id
= RAP_NetServerEnum3
,
5750 .fn
= api_RNetServerEnum3
5753 .name
= "WAccessGetUserPerms",
5754 .id
= RAP_WAccessGetUserPerms
,
5755 .fn
= api_WAccessGetUserPerms
5758 .name
= "WWkstaUserLogon",
5759 .id
= RAP_WWkstaUserLogon
,
5760 .fn
= api_WWkstaUserLogon
5763 .name
= "PrintJobInfo",
5764 .id
= RAP_WPrintJobSetInfo
,
5765 .fn
= api_PrintJobInfo
5768 .name
= "WPrintDriverEnum",
5769 .id
= RAP_WPrintDriverEnum
,
5770 .fn
= api_WPrintDriverEnum
5773 .name
= "WPrintQProcEnum",
5774 .id
= RAP_WPrintQProcessorEnum
,
5775 .fn
= api_WPrintQProcEnum
5778 .name
= "WPrintPortEnum",
5779 .id
= RAP_WPrintPortEnum
,
5780 .fn
= api_WPrintPortEnum
5783 .name
= "SamOEMChangePassword",
5784 .id
= RAP_SamOEMChgPasswordUser2_P
,
5785 .fn
= api_SamOEMChangePassword
5790 .fn
= api_Unsupported
}
5792 * The following RAP calls are not implemented by Samba:
5793 * RAP_WFileEnum2 - anon not OK
5798 /****************************************************************************
5799 Handle remote api calls.
5800 ****************************************************************************/
5802 void api_reply(connection_struct
*conn
, uint64_t vuid
,
5803 struct smb_request
*req
,
5804 char *data
, char *params
,
5805 int tdscnt
, int tpscnt
,
5806 int mdrcnt
, int mprcnt
)
5810 char *rparam
= NULL
;
5811 const char *name1
= NULL
;
5812 const char *name2
= NULL
;
5819 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5820 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5825 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5828 api_command
= SVAL(params
,0);
5829 /* Is there a string at position params+2 ? */
5830 if (skip_string(params
,tpscnt
,params
+2)) {
5835 name2
= skip_string(params
,tpscnt
,params
+2);
5840 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5844 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5846 for (i
=0;api_commands
[i
].name
;i
++) {
5847 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5848 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5853 /* Check whether this api call can be done anonymously */
5855 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5856 struct auth_session_info
*si
= NULL
;
5859 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
5862 if (!NT_STATUS_IS_OK(status
)) {
5863 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5867 if (security_session_user_level(si
, NULL
) < SECURITY_USER
) {
5868 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5873 rdata
= (char *)SMB_MALLOC(1024);
5875 memset(rdata
,'\0',1024);
5878 rparam
= (char *)SMB_MALLOC(1024);
5880 memset(rparam
,'\0',1024);
5883 if(!rdata
|| !rparam
) {
5884 DEBUG(0,("api_reply: malloc fail !\n"));
5887 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5891 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5893 params
,tpscnt
, /* params + length */
5894 data
,tdscnt
, /* data + length */
5896 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5899 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5900 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5902 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5905 /* if we get False back then it's actually unsupported */
5907 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5909 tdscnt
,mdrcnt
,mprcnt
,
5910 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5913 /* If api_Unsupported returns false we can't return anything. */
5915 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5916 rdata
, rdata_len
, False
);