2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "rpc_client/rpc_client.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
34 #include "rpc_client/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
37 #include "../librpc/gen_ndr/rap.h"
38 #include "../lib/util/binsearch.h"
39 #include "../libcli/auth/libcli_auth.h"
40 #include "rpc_client/init_lsa.h"
41 #include "../libcli/security/security.h"
43 #include "passdb/machine_sid.h"
45 #include "rpc_server/rpc_ncacn_np.h"
52 #define NERR_Success 0
53 #define NERR_badpass 86
54 #define NERR_notsupported 50
56 #define NERR_BASE (2100)
57 #define NERR_BufTooSmall (NERR_BASE+23)
58 #define NERR_JobNotFound (NERR_BASE+51)
59 #define NERR_DestNotFound (NERR_BASE+52)
61 #define ACCESS_READ 0x01
62 #define ACCESS_WRITE 0x02
63 #define ACCESS_CREATE 0x04
65 #define SHPWLEN 8 /* share password length */
67 /* Limit size of ipc replies */
69 static char *smb_realloc_limit(void *ptr
, size_t size
)
73 size
= MAX((size
),4*1024);
74 val
= (char *)SMB_REALLOC(ptr
,size
);
76 memset(val
,'\0',size
);
81 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
82 connection_struct
*conn
, uint64_t vuid
,
83 char *param
, int tpscnt
,
84 char *data
, int tdscnt
,
85 int mdrcnt
, int mprcnt
,
86 char **rdata
, char **rparam
,
87 int *rdata_len
, int *rparam_len
);
89 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
90 connection_struct
*conn
, uint64_t vuid
, char *param
, char *data
,
91 int mdrcnt
, int mprcnt
,
92 char **rdata
, char **rparam
,
93 int *rdata_len
, int *rparam_len
);
96 static int CopyExpanded(connection_struct
*conn
,
97 int snum
, char **dst
, char *src
, int *p_space_remaining
)
99 TALLOC_CTX
*ctx
= talloc_tos();
103 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
104 *p_space_remaining
<= 0) {
108 buf
= talloc_strdup(ctx
, src
);
110 *p_space_remaining
= 0;
113 buf
= talloc_string_sub(ctx
, buf
,"%S", lp_servicename(ctx
, snum
));
115 *p_space_remaining
= 0;
118 buf
= talloc_sub_advanced(ctx
,
119 lp_servicename(ctx
, SNUM(conn
)),
120 conn
->session_info
->unix_info
->unix_name
,
122 conn
->session_info
->unix_token
->gid
,
123 conn
->session_info
->unix_info
->sanitized_username
,
124 conn
->session_info
->info
->domain_name
,
127 *p_space_remaining
= 0;
130 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
135 (*p_space_remaining
) -= l
;
139 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
142 if (!src
|| !dst
|| !n
|| !(*dst
)) {
145 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
154 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
156 TALLOC_CTX
*ctx
= talloc_tos();
161 buf
= talloc_strdup(ctx
,s
);
165 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(ctx
, snum
));
169 buf
= talloc_sub_advanced(ctx
,
170 lp_servicename(ctx
, SNUM(conn
)),
171 conn
->session_info
->unix_info
->unix_name
,
173 conn
->session_info
->unix_token
->gid
,
174 conn
->session_info
->unix_info
->sanitized_username
,
175 conn
->session_info
->info
->domain_name
,
180 return strlen(buf
) + 1;
183 /*******************************************************************
184 Check a API string for validity when we only need to check the prefix.
185 ******************************************************************/
187 static bool prefix_ok(const char *str
, const char *prefix
)
189 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
193 const char *format
; /* formatstring for structure */
194 const char *subformat
; /* subformat for structure */
195 char *base
; /* baseaddress of buffer */
196 int buflen
; /* remaining size for fixed part; on init: length of base */
197 int subcount
; /* count of substructures */
198 char *structbuf
; /* pointer into buffer for remaining fixed part */
199 int stringlen
; /* remaining size for variable part */
200 char *stringbuf
; /* pointer into buffer for remaining variable part */
201 int neededlen
; /* total needed size */
202 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
203 const char *curpos
; /* current position; pointer into format or subformat */
207 static int get_counter(const char **p
)
213 if (!isdigit((int)**p
)) {
219 n
= 10 * n
+ (i
- '0');
227 static int getlen(const char *p
)
236 case 'W': /* word (2 byte) */
239 case 'K': /* status word? (2 byte) */
242 case 'N': /* count of substructures (word) at end */
245 case 'D': /* double word (4 byte) */
246 case 'z': /* offset to zero terminated string (4 byte) */
247 case 'l': /* offset to user data (4 byte) */
250 case 'b': /* offset to data (with counter) (4 byte) */
254 case 'B': /* byte (with optional counter) */
255 n
+= get_counter(&p
);
262 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
267 if (!p
->format
|| !p
->base
) {
271 i
= count
* getlen(p
->format
);
273 i
+= subcount
* getlen(p
->subformat
);
275 p
->structbuf
= p
->base
;
279 p
->curpos
= p
->format
;
285 * This is the old error code we used. Aparently
286 * WinNT/2k systems return ERRbuftoosmall (2123) and
287 * OS/2 needs this. I'm leaving this here so we can revert
290 p
->errcode
= ERRmoredata
;
292 p
->errcode
= ERRbuftoosmall
;
295 p
->errcode
= NERR_Success
;
299 p
->stringbuf
= p
->base
+ i
;
301 return (p
->errcode
== NERR_Success
);
304 static int package(struct pack_desc
*p
, ...)
307 int needed
=0, stringneeded
;
308 const char *str
=NULL
;
309 int is_string
=0, stringused
;
316 p
->curpos
= p
->format
;
318 p
->curpos
= p
->subformat
;
323 str
= va_arg(args
,char*);
324 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
333 switch( *p
->curpos
++ ) {
334 case 'W': /* word (2 byte) */
336 temp
= va_arg(args
,int);
337 if (p
->buflen
>= needed
) {
338 SSVAL(p
->structbuf
,0,temp
);
341 case 'K': /* status word? (2 byte) */
343 temp
= va_arg(args
,int);
344 if (p
->buflen
>= needed
) {
345 SSVAL(p
->structbuf
,0,temp
);
348 case 'N': /* count of substructures (word) at end */
350 p
->subcount
= va_arg(args
,int);
351 if (p
->buflen
>= needed
) {
352 SSVAL(p
->structbuf
,0,p
->subcount
);
355 case 'D': /* double word (4 byte) */
357 temp
= va_arg(args
,int);
358 if (p
->buflen
>= needed
) {
359 SIVAL(p
->structbuf
,0,temp
);
362 case 'B': /* byte (with optional counter) */
363 needed
= get_counter(&p
->curpos
);
365 char *s
= va_arg(args
,char*);
366 if (p
->buflen
>= needed
) {
367 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
371 case 'z': /* offset to zero terminated string (4 byte) */
372 str
= va_arg(args
,char*);
373 stringneeded
= (str
? strlen(str
)+1 : 0);
376 case 'l': /* offset to user data (4 byte) */
377 str
= va_arg(args
,char*);
378 stringneeded
= va_arg(args
,int);
381 case 'b': /* offset to data (with counter) (4 byte) */
382 str
= va_arg(args
,char*);
383 stringneeded
= get_counter(&p
->curpos
);
389 if (stringneeded
>= 0) {
391 if (p
->buflen
>= needed
) {
392 stringused
= stringneeded
;
393 if (stringused
> p
->stringlen
) {
394 stringused
= (is_string
? p
->stringlen
: 0);
395 if (p
->errcode
== NERR_Success
) {
396 p
->errcode
= ERRmoredata
;
400 SIVAL(p
->structbuf
,0,0);
402 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
403 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
405 p
->stringbuf
[stringused
-1] = '\0';
407 p
->stringbuf
+= stringused
;
408 p
->stringlen
-= stringused
;
409 p
->usedlen
+= stringused
;
412 p
->neededlen
+= stringneeded
;
415 p
->neededlen
+= needed
;
416 if (p
->buflen
>= needed
) {
417 p
->structbuf
+= needed
;
419 p
->usedlen
+= needed
;
421 if (p
->errcode
== NERR_Success
) {
422 p
->errcode
= ERRmoredata
;
429 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
430 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
432 #define PACK(desc,t,v) package(desc,v)
433 #define PACKl(desc,t,v,l) package(desc,v,l)
436 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
441 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
446 /****************************************************************************
448 ****************************************************************************/
450 static void PackDriverData(struct pack_desc
* desc
)
452 char drivdata
[4+4+32];
453 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
454 SIVAL(drivdata
,4,1000); /* lVersion */
455 memset(drivdata
+8,0,32); /* szDeviceName */
456 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
457 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
460 static int check_printq_info(struct pack_desc
* desc
,
461 unsigned int uLevel
, char *id1
, char *id2
)
463 desc
->subformat
= NULL
;
466 desc
->format
= "B13";
469 desc
->format
= "B13BWWWzzzzzWW";
472 desc
->format
= "B13BWWWzzzzzWN";
473 desc
->subformat
= "WB21BB16B10zWWzDDz";
476 desc
->format
= "zWWWWzzzzWWzzl";
479 desc
->format
= "zWWWWzzzzWNzzl";
480 desc
->subformat
= "WWzWWDDzz";
489 desc
->format
= "WzzzzzzzzN";
490 desc
->subformat
= "z";
493 DEBUG(0,("check_printq_info: invalid level %d\n",
497 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
498 DEBUG(0,("check_printq_info: invalid format %s\n",
499 id1
? id1
: "<NULL>" ));
502 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
503 DEBUG(0,("check_printq_info: invalid subformat %s\n",
504 id2
? id2
: "<NULL>" ));
511 #define RAP_JOB_STATUS_QUEUED 0
512 #define RAP_JOB_STATUS_PAUSED 1
513 #define RAP_JOB_STATUS_SPOOLING 2
514 #define RAP_JOB_STATUS_PRINTING 3
515 #define RAP_JOB_STATUS_PRINTED 4
517 #define RAP_QUEUE_STATUS_PAUSED 1
518 #define RAP_QUEUE_STATUS_ERROR 2
520 /* turn a print job status into a on the wire status
522 static int printj_spoolss_status(int v
)
524 if (v
== JOB_STATUS_QUEUED
)
525 return RAP_JOB_STATUS_QUEUED
;
526 if (v
& JOB_STATUS_PAUSED
)
527 return RAP_JOB_STATUS_PAUSED
;
528 if (v
& JOB_STATUS_SPOOLING
)
529 return RAP_JOB_STATUS_SPOOLING
;
530 if (v
& JOB_STATUS_PRINTING
)
531 return RAP_JOB_STATUS_PRINTING
;
535 /* turn a print queue status into a on the wire status
537 static int printq_spoolss_status(int v
)
539 if (v
== PRINTER_STATUS_OK
)
541 if (v
& PRINTER_STATUS_PAUSED
)
542 return RAP_QUEUE_STATUS_PAUSED
;
543 return RAP_QUEUE_STATUS_ERROR
;
546 static void fill_spoolss_printjob_info(int uLevel
,
547 struct pack_desc
*desc
,
548 struct spoolss_JobInfo2
*info2
,
551 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
553 /* the client expects localtime */
554 t
-= get_time_zone(t
);
556 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
558 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
559 PACKS(desc
,"B",""); /* pad */
560 PACKS(desc
,"B16",""); /* szNotifyName */
561 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
562 PACKS(desc
,"z",""); /* pszParms */
563 PACKI(desc
,"W",n
+1); /* uPosition */
564 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
565 PACKS(desc
,"z",""); /* pszStatus */
566 PACKI(desc
,"D", t
); /* ulSubmitted */
567 PACKI(desc
,"D", info2
->size
); /* ulSize */
568 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
570 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
571 PACKI(desc
,"W", info2
->priority
); /* uPriority */
572 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
573 PACKI(desc
,"W",n
+1); /* uPosition */
574 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
575 PACKI(desc
,"D",t
); /* ulSubmitted */
576 PACKI(desc
,"D", info2
->size
); /* ulSize */
577 PACKS(desc
,"z","Samba"); /* pszComment */
578 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
580 PACKS(desc
,"z",""); /* pszNotifyName */
581 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
582 PACKS(desc
,"z",""); /* pszParms */
583 PACKS(desc
,"z",""); /* pszStatus */
584 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
585 PACKS(desc
,"z","lpd"); /* pszQProcName */
586 PACKS(desc
,"z",""); /* pszQProcParms */
587 PACKS(desc
,"z","NULL"); /* pszDriverName */
588 PackDriverData(desc
); /* pDriverData */
589 PACKS(desc
,"z",""); /* pszPrinterName */
590 } else if (uLevel
== 4) { /* OS2 */
591 PACKS(desc
,"z",""); /* pszSpoolFileName */
592 PACKS(desc
,"z",""); /* pszPortName */
593 PACKS(desc
,"z",""); /* pszStatus */
594 PACKI(desc
,"D",0); /* ulPagesSpooled */
595 PACKI(desc
,"D",0); /* ulPagesSent */
596 PACKI(desc
,"D",0); /* ulPagesPrinted */
597 PACKI(desc
,"D",0); /* ulTimePrinted */
598 PACKI(desc
,"D",0); /* ulExtendJobStatus */
599 PACKI(desc
,"D",0); /* ulStartPage */
600 PACKI(desc
,"D",0); /* ulEndPage */
605 /********************************************************************
606 Respond to the DosPrintQInfo command with a level of 52
607 This is used to get printer driver information for Win9x clients
608 ********************************************************************/
609 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
610 struct pack_desc
* desc
, int count
,
611 const char *printer_name
)
615 trim_string(discard_const_p(char, driver
->driver_path
), "\\print$\\WIN40\\0\\", 0);
616 trim_string(discard_const_p(char, driver
->data_file
), "\\print$\\WIN40\\0\\", 0);
617 trim_string(discard_const_p(char, driver
->help_file
), "\\print$\\WIN40\\0\\", 0);
619 PACKI(desc
, "W", 0x0400); /* don't know */
620 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
621 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
622 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
623 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
625 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
626 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
627 PACKS(desc
,"z", location
); /* share to retrieve files */
629 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
630 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
631 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
633 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
634 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
635 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
636 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
637 DEBUG(3,("Driver Location: %s:\n",location
));
638 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
639 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
640 PACKI(desc
,"N",count
); /* number of files to copy */
642 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
644 trim_string(discard_const_p(char, driver
->dependent_files
[i
]), "\\print$\\WIN40\\0\\", 0);
645 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
646 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
651 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
654 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
656 desc
->errcode
=NERR_Success
;
660 static const char *strip_unc(const char *unc
)
668 if ((p
= strrchr(unc
, '\\')) != NULL
) {
675 static void fill_printq_info(int uLevel
,
676 struct pack_desc
* desc
,
678 union spoolss_JobInfo
*job_info
,
679 struct spoolss_DriverInfo3
*driver_info
,
680 struct spoolss_PrinterInfo2
*printer_info
)
686 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
691 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
694 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
698 if (uLevel
== 1 || uLevel
== 2) {
699 PACKS(desc
,"B",""); /* alignment */
700 PACKI(desc
,"W",5); /* priority */
701 PACKI(desc
,"W",0); /* start time */
702 PACKI(desc
,"W",0); /* until time */
703 PACKS(desc
,"z",""); /* pSepFile */
704 PACKS(desc
,"z","lpd"); /* pPrProc */
705 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
706 PACKS(desc
,"z",""); /* pParms */
707 if (printer_info
->printername
== NULL
) {
708 PACKS(desc
,"z","UNKNOWN PRINTER");
709 PACKI(desc
,"W",LPSTAT_ERROR
);
711 PACKS(desc
,"z", printer_info
->comment
);
712 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
714 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
717 if (uLevel
== 3 || uLevel
== 4) {
718 PACKI(desc
,"W",5); /* uPriority */
719 PACKI(desc
,"W",0); /* uStarttime */
720 PACKI(desc
,"W",0); /* uUntiltime */
721 PACKI(desc
,"W",5); /* pad1 */
722 PACKS(desc
,"z",""); /* pszSepFile */
723 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
724 PACKS(desc
,"z",NULL
); /* pszParms */
725 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
726 /* "don't ask" that it's done this way to fix corrupted
727 Win9X/ME printer comments. */
728 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
729 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
730 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
731 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
732 PackDriverData(desc
); /* pDriverData */
735 if (uLevel
== 2 || uLevel
== 4) {
737 for (i
= 0; i
< count
; i
++) {
738 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
743 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
746 /* This function returns the number of files for a given driver */
747 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
751 /* count the number of files */
752 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
758 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
759 connection_struct
*conn
, uint64_t vuid
,
760 char *param
, int tpscnt
,
761 char *data
, int tdscnt
,
762 int mdrcnt
,int mprcnt
,
763 char **rdata
,char **rparam
,
764 int *rdata_len
,int *rparam_len
)
766 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
767 char *str2
= skip_string(param
,tpscnt
,str1
);
768 char *p
= skip_string(param
,tpscnt
,str2
);
773 struct pack_desc desc
;
776 WERROR werr
= WERR_OK
;
777 TALLOC_CTX
*mem_ctx
= talloc_tos();
779 struct rpc_pipe_client
*cli
= NULL
;
780 struct dcerpc_binding_handle
*b
= NULL
;
781 struct policy_handle handle
;
782 struct spoolss_DevmodeContainer devmode_ctr
;
783 union spoolss_DriverInfo driver_info
;
784 union spoolss_JobInfo
*job_info
= NULL
;
785 union spoolss_PrinterInfo printer_info
;
787 if (!str1
|| !str2
|| !p
) {
790 memset((char *)&desc
,'\0',sizeof(desc
));
792 p
= skip_string(param
,tpscnt
,p
);
796 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
797 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
798 /* str3 may be null here and is checked in check_printq_info(). */
800 /* remove any trailing username */
801 if ((p
= strchr_m(QueueName
,'%')))
804 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
806 /* check it's a supported varient */
807 if (!prefix_ok(str1
,"zWrLh"))
809 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
811 * Patch from Scott Moomaw <scott@bridgewater.edu>
812 * to return the 'invalid info level' error if an
813 * unknown level was requested.
817 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
821 SSVALS(*rparam
,0,ERRunknownlevel
);
829 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
830 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
834 status
= rpc_pipe_open_interface(conn
,
837 conn
->sconn
->remote_address
,
838 conn
->sconn
->msg_ctx
,
840 if (!NT_STATUS_IS_OK(status
)) {
841 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
843 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
846 b
= cli
->binding_handle
;
848 ZERO_STRUCT(devmode_ctr
);
850 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
857 if (!NT_STATUS_IS_OK(status
)) {
858 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
861 if (!W_ERROR_IS_OK(werr
)) {
862 desc
.errcode
= W_ERROR_V(werr
);
866 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
871 if (!W_ERROR_IS_OK(werr
)) {
872 desc
.errcode
= W_ERROR_V(werr
);
877 uint32_t server_major_version
;
878 uint32_t server_minor_version
;
880 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
888 &server_major_version
,
889 &server_minor_version
);
890 if (!W_ERROR_IS_OK(werr
)) {
891 desc
.errcode
= W_ERROR_V(werr
);
895 count
= get_printerdrivernumber(&driver_info
.info3
);
896 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
899 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
907 if (!W_ERROR_IS_OK(werr
)) {
908 desc
.errcode
= W_ERROR_V(werr
);
916 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
921 desc
.buflen
= mdrcnt
;
924 * Don't return data but need to get correct length
925 * init_package will return wrong size if buflen=0
927 desc
.buflen
= getlen(desc
.format
);
928 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
931 if (init_package(&desc
,1,count
)) {
932 desc
.subcount
= count
;
933 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
936 *rdata_len
= desc
.usedlen
;
939 * We must set the return code to ERRbuftoosmall
940 * in order to support lanman style printing with Win NT/2k
943 if (!mdrcnt
&& lp_disable_spoolss())
944 desc
.errcode
= ERRbuftoosmall
;
947 if (b
&& is_valid_policy_hnd(&handle
)) {
948 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
951 *rdata_len
= desc
.usedlen
;
953 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
958 SSVALS(*rparam
,0,desc
.errcode
);
960 SSVAL(*rparam
,4,desc
.neededlen
);
962 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
969 /****************************************************************************
970 View list of all print jobs on all queues.
971 ****************************************************************************/
973 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
974 connection_struct
*conn
, uint64_t vuid
,
975 char *param
, int tpscnt
,
976 char *data
, int tdscnt
,
977 int mdrcnt
, int mprcnt
,
978 char **rdata
, char** rparam
,
979 int *rdata_len
, int *rparam_len
)
981 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
982 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
983 char *p
= skip_string(param
,tpscnt
,output_format1
);
984 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
985 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
987 struct pack_desc desc
;
988 int *subcntarr
= NULL
;
989 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
991 WERROR werr
= WERR_OK
;
992 TALLOC_CTX
*mem_ctx
= talloc_tos();
994 struct rpc_pipe_client
*cli
= NULL
;
995 struct dcerpc_binding_handle
*b
= NULL
;
996 struct spoolss_DevmodeContainer devmode_ctr
;
997 uint32_t num_printers
;
998 union spoolss_PrinterInfo
*printer_info
;
999 union spoolss_DriverInfo
*driver_info
;
1000 union spoolss_JobInfo
**job_info
;
1002 if (!param_format
|| !output_format1
|| !p
) {
1006 memset((char *)&desc
,'\0',sizeof(desc
));
1008 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1010 if (!prefix_ok(param_format
,"WrLeh")) {
1013 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1015 * Patch from Scott Moomaw <scott@bridgewater.edu>
1016 * to return the 'invalid info level' error if an
1017 * unknown level was requested.
1021 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1025 SSVALS(*rparam
,0,ERRunknownlevel
);
1031 status
= rpc_pipe_open_interface(conn
,
1034 conn
->sconn
->remote_address
,
1035 conn
->sconn
->msg_ctx
,
1037 if (!NT_STATUS_IS_OK(status
)) {
1038 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1039 nt_errstr(status
)));
1040 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1043 b
= cli
->binding_handle
;
1045 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1047 cli
->srv_name_slash
,
1052 if (!W_ERROR_IS_OK(werr
)) {
1053 desc
.errcode
= W_ERROR_V(werr
);
1057 queuecnt
= num_printers
;
1059 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1060 if (job_info
== NULL
) {
1064 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1065 if (driver_info
== NULL
) {
1069 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1070 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1075 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1081 desc
.buflen
= mdrcnt
;
1084 for (i
= 0; i
< num_printers
; i
++) {
1087 struct policy_handle handle
;
1088 const char *printername
;
1090 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1091 if (printername
== NULL
) {
1095 ZERO_STRUCT(handle
);
1096 ZERO_STRUCT(devmode_ctr
);
1098 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
1105 if (!NT_STATUS_IS_OK(status
)) {
1106 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1109 if (!W_ERROR_IS_OK(werr
)) {
1110 desc
.errcode
= W_ERROR_V(werr
);
1114 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1122 if (!W_ERROR_IS_OK(werr
)) {
1123 desc
.errcode
= W_ERROR_V(werr
);
1128 uint32_t server_major_version
;
1129 uint32_t server_minor_version
;
1131 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1139 &server_major_version
,
1140 &server_minor_version
);
1141 if (!W_ERROR_IS_OK(werr
)) {
1142 desc
.errcode
= W_ERROR_V(werr
);
1147 subcntarr
[i
] = num_jobs
;
1148 subcnt
+= subcntarr
[i
];
1150 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1153 if (init_package(&desc
,queuecnt
,subcnt
)) {
1154 for (i
= 0; i
< num_printers
; i
++) {
1155 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1156 if (desc
.errcode
== NERR_Success
) {
1163 SAFE_FREE(subcntarr
);
1164 *rdata_len
= desc
.usedlen
;
1166 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1170 SSVALS(*rparam
,0,desc
.errcode
);
1172 SSVAL(*rparam
,4,succnt
);
1173 SSVAL(*rparam
,6,queuecnt
);
1179 SAFE_FREE(subcntarr
);
1184 /****************************************************************************
1185 Get info level for a server list query.
1186 ****************************************************************************/
1188 static bool check_session_info(int uLevel
, char* id
)
1192 if (strcmp(id
,"B16") != 0) {
1197 if (strcmp(id
,"B16BBDz") != 0) {
1207 struct srv_info_struct
{
1215 /*******************************************************************
1216 Get server info lists from the files saved by nmbd. Return the
1218 ******************************************************************/
1220 static int get_session_info(uint32 servertype
,
1221 struct srv_info_struct
**servers
,
1227 bool local_list_only
;
1230 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1232 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1236 /* request for everything is code for request all servers */
1237 if (servertype
== SV_TYPE_ALL
) {
1238 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1241 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1243 DEBUG(4,("Servertype search: %8x\n",servertype
));
1245 for (i
=0;lines
[i
];i
++) {
1247 struct srv_info_struct
*s
;
1248 const char *ptr
= lines
[i
];
1250 TALLOC_CTX
*frame
= NULL
;
1257 if (count
== alloced
) {
1259 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1261 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1265 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1267 s
= &(*servers
)[count
];
1269 frame
= talloc_stackframe();
1271 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1275 fstrcpy(s
->name
, p
);
1278 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1284 s
->comment
[0] = '\0';
1285 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1289 fstrcpy(s
->comment
, p
);
1290 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1292 s
->domain
[0] = '\0';
1293 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1294 /* this allows us to cope with an old nmbd */
1295 fstrcpy(s
->domain
,lp_workgroup());
1297 fstrcpy(s
->domain
, p
);
1301 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1302 DEBUG(4,("r:host file "));
1306 /* Filter the servers/domains we return based on what was asked for. */
1308 /* Check to see if we are being asked for a local list only. */
1309 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1310 DEBUG(4,("r: local list only"));
1314 /* doesn't match up: don't want it */
1315 if (!(servertype
& s
->type
)) {
1316 DEBUG(4,("r:serv type "));
1320 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1321 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1322 DEBUG(4,("s: dom mismatch "));
1326 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1330 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1331 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1334 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1335 s
->name
, s
->type
, s
->comment
, s
->domain
));
1336 s
->server_added
= True
;
1339 DEBUG(4,("%20s %8x %25s %15s\n",
1340 s
->name
, s
->type
, s
->comment
, s
->domain
));
1348 /*******************************************************************
1349 Fill in a server info structure.
1350 ******************************************************************/
1352 static int fill_srv_info(struct srv_info_struct
*service
,
1353 int uLevel
, char **buf
, int *buflen
,
1354 char **stringbuf
, int *stringspace
, char *baseaddr
)
1377 len
= strlen(service
->comment
)+1;
1381 *buflen
= struct_len
;
1383 return struct_len
+ len
;
1388 if (*buflen
< struct_len
) {
1395 p2
= p
+ struct_len
;
1396 l2
= *buflen
- struct_len
;
1404 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1408 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1409 SIVAL(p
,18,service
->type
);
1410 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1411 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1416 *buf
= p
+ struct_len
;
1417 *buflen
-= struct_len
;
1428 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1430 return strcasecmp_m(s1
->name
,s2
->name
);
1433 /****************************************************************************
1434 View list of servers available (or possibly domains). The info is
1435 extracted from lists saved by nmbd on the local host.
1436 ****************************************************************************/
1438 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1439 connection_struct
*conn
, uint64_t vuid
,
1440 char *param
, int tpscnt
,
1441 char *data
, int tdscnt
,
1442 int mdrcnt
, int mprcnt
, char **rdata
,
1443 char **rparam
, int *rdata_len
, int *rparam_len
)
1445 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1446 char *str2
= skip_string(param
,tpscnt
,str1
);
1447 char *p
= skip_string(param
,tpscnt
,str2
);
1448 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1449 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1450 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1452 int data_len
, fixed_len
, string_len
;
1453 int f_len
= 0, s_len
= 0;
1454 struct srv_info_struct
*servers
=NULL
;
1455 int counted
=0,total
=0;
1458 bool domain_request
;
1461 if (!str1
|| !str2
|| !p
) {
1465 /* If someone sets all the bits they don't really mean to set
1466 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1469 if (servertype
== SV_TYPE_ALL
) {
1470 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1473 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1474 any other bit (they may just set this bit on its own) they
1475 want all the locally seen servers. However this bit can be
1476 set on its own so set the requested servers to be
1477 ALL - DOMAIN_ENUM. */
1479 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1480 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1483 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1484 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1488 if (!prefix_ok(str1
,"WrLehD")) {
1491 if (!check_session_info(uLevel
,str2
)) {
1495 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1496 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1497 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1499 if (strcmp(str1
, "WrLehDz") == 0) {
1500 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1503 pull_ascii_fstring(domain
, p
);
1505 fstrcpy(domain
, lp_workgroup());
1508 DEBUG(4, ("domain [%s]\n", domain
));
1510 if (lp_browse_list()) {
1511 total
= get_session_info(servertype
,&servers
,domain
);
1514 data_len
= fixed_len
= string_len
= 0;
1517 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1520 char *lastname
=NULL
;
1522 for (i
=0;i
<total
;i
++) {
1523 struct srv_info_struct
*s
= &servers
[i
];
1525 if (lastname
&& strequal(lastname
,s
->name
)) {
1529 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1530 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1531 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1533 if (data_len
< buf_len
) {
1536 string_len
+= s_len
;
1543 *rdata_len
= fixed_len
+ string_len
;
1544 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1549 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1555 char *lastname
=NULL
;
1556 int count2
= counted
;
1558 for (i
= 0; i
< total
&& count2
;i
++) {
1559 struct srv_info_struct
*s
= &servers
[i
];
1561 if (lastname
&& strequal(lastname
,s
->name
)) {
1565 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1566 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1567 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1573 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1577 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1579 SSVAL(*rparam
,4,counted
);
1580 SSVAL(*rparam
,6,counted
+missed
);
1584 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1585 domain
,uLevel
,counted
,counted
+missed
));
1590 static int srv_name_match(const char *n1
, const char *n2
)
1593 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1595 * In Windows, FirstNameToReturn need not be an exact match:
1596 * the server will return a list of servers that exist on
1597 * the network greater than or equal to the FirstNameToReturn.
1599 int ret
= strcasecmp_m(n1
, n2
);
1608 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1609 connection_struct
*conn
, uint64_t vuid
,
1610 char *param
, int tpscnt
,
1611 char *data
, int tdscnt
,
1612 int mdrcnt
, int mprcnt
, char **rdata
,
1613 char **rparam
, int *rdata_len
, int *rparam_len
)
1615 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1616 char *str2
= skip_string(param
,tpscnt
,str1
);
1617 char *p
= skip_string(param
,tpscnt
,str2
);
1618 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1619 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1620 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1622 int data_len
, fixed_len
, string_len
;
1623 int f_len
= 0, s_len
= 0;
1624 struct srv_info_struct
*servers
=NULL
;
1625 int counted
=0,first
=0,total
=0;
1629 bool domain_request
;
1632 if (!str1
|| !str2
|| !p
) {
1636 /* If someone sets all the bits they don't really mean to set
1637 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1640 if (servertype
== SV_TYPE_ALL
) {
1641 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1644 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1645 any other bit (they may just set this bit on its own) they
1646 want all the locally seen servers. However this bit can be
1647 set on its own so set the requested servers to be
1648 ALL - DOMAIN_ENUM. */
1650 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1651 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1654 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1655 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1659 if (strcmp(str1
, "WrLehDzz") != 0) {
1662 if (!check_session_info(uLevel
,str2
)) {
1666 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1667 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1668 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1670 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1673 pull_ascii_fstring(domain
, p
);
1674 if (domain
[0] == '\0') {
1675 fstrcpy(domain
, lp_workgroup());
1677 p
= skip_string(param
,tpscnt
,p
);
1678 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1681 pull_ascii_fstring(first_name
, p
);
1683 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1684 domain
, first_name
));
1686 if (lp_browse_list()) {
1687 total
= get_session_info(servertype
,&servers
,domain
);
1690 data_len
= fixed_len
= string_len
= 0;
1693 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1695 if (first_name
[0] != '\0') {
1696 struct srv_info_struct
*first_server
= NULL
;
1698 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1699 srv_name_match
, first_server
);
1701 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1703 * The binary search may not find the exact match
1704 * so we need to search backward to find the first match
1706 * This implements the strange matching windows
1707 * implements. (see the comment in srv_name_match().
1711 ret
= strcasecmp_m(first_name
,
1712 servers
[first
-1].name
);
1719 /* we should return no entries */
1725 char *lastname
=NULL
;
1727 for (i
=first
;i
<total
;i
++) {
1728 struct srv_info_struct
*s
= &servers
[i
];
1730 if (lastname
&& strequal(lastname
,s
->name
)) {
1734 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1735 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1736 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1738 if (data_len
< buf_len
) {
1741 string_len
+= s_len
;
1748 *rdata_len
= fixed_len
+ string_len
;
1749 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1754 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1760 char *lastname
=NULL
;
1761 int count2
= counted
;
1763 for (i
= first
; i
< total
&& count2
;i
++) {
1764 struct srv_info_struct
*s
= &servers
[i
];
1766 if (lastname
&& strequal(lastname
,s
->name
)) {
1770 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1771 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1772 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1778 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1782 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1784 SSVAL(*rparam
,4,counted
);
1785 SSVAL(*rparam
,6,counted
+missed
);
1787 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1788 domain
,uLevel
,first
,first_name
,
1789 first
< total
? servers
[first
].name
: "",
1790 counted
,counted
+missed
));
1797 /****************************************************************************
1798 command 0x34 - suspected of being a "Lookup Names" stub api
1799 ****************************************************************************/
1801 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1802 connection_struct
*conn
, uint64_t vuid
,
1803 char *param
, int tpscnt
,
1804 char *data
, int tdscnt
,
1805 int mdrcnt
, int mprcnt
, char **rdata
,
1806 char **rparam
, int *rdata_len
, int *rparam_len
)
1808 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1809 char *str2
= skip_string(param
,tpscnt
,str1
);
1810 char *p
= skip_string(param
,tpscnt
,str2
);
1811 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1812 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1816 if (!str1
|| !str2
|| !p
) {
1820 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1821 str1
, str2
, p
, uLevel
, buf_len
));
1823 if (!prefix_ok(str1
,"zWrLeh")) {
1830 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1835 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1837 SSVAL(*rparam
,4,counted
);
1838 SSVAL(*rparam
,6,counted
+missed
);
1843 /****************************************************************************
1844 get info about a share
1845 ****************************************************************************/
1847 static bool check_share_info(int uLevel
, char* id
)
1851 if (strcmp(id
,"B13") != 0) {
1856 /* Level-2 descriptor is allowed (and ignored) */
1857 if (strcmp(id
,"B13BWz") != 0 &&
1858 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1863 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1868 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1878 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1879 char** buf
, int* buflen
,
1880 char** stringbuf
, int* stringspace
, char* baseaddr
)
1909 len
+= StrlenExpanded(conn
,snum
,lp_comment(talloc_tos(), snum
));
1912 len
+= strlen(lp_path(talloc_tos(), snum
)) + 1;
1915 *buflen
= struct_len
;
1920 return struct_len
+ len
;
1925 if ((*buflen
) < struct_len
) {
1933 p2
= p
+ struct_len
;
1934 l2
= (*buflen
) - struct_len
;
1941 push_ascii(p
,lp_servicename(talloc_tos(), snum
),13, STR_TERMINATE
);
1947 type
= STYPE_DISKTREE
;
1948 if (lp_printable(snum
)) {
1949 type
= STYPE_PRINTQ
;
1951 if (strequal("IPC",lp_fstype(snum
))) {
1954 SSVAL(p
,14,type
); /* device type */
1955 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1956 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(talloc_tos(),snum
),&l2
);
1960 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1961 SSVALS(p
,22,-1); /* max uses */
1962 SSVAL(p
,24,1); /* current uses */
1963 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1964 len
+= CopyAndAdvance(&p2
,lp_path(talloc_tos(),snum
),&l2
);
1965 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1969 memset(p
+40,0,SHPWLEN
+2);
1980 (*buf
) = p
+ struct_len
;
1981 (*buflen
) -= struct_len
;
1983 (*stringspace
) = l2
;
1992 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
1993 connection_struct
*conn
,uint64_t vuid
,
1994 char *param
, int tpscnt
,
1995 char *data
, int tdscnt
,
1996 int mdrcnt
,int mprcnt
,
1997 char **rdata
,char **rparam
,
1998 int *rdata_len
,int *rparam_len
)
2000 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2001 char *str2
= skip_string(param
,tpscnt
,str1
);
2002 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2003 char *netname
= NULL
;
2004 char *p
= skip_string(param
,tpscnt
,netname
);
2005 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2008 if (!str1
|| !str2
|| !netname_in
|| !p
) {
2012 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2013 if (snum
< 0 || !netname
) {
2017 /* check it's a supported varient */
2018 if (!prefix_ok(str1
,"zWrLh")) {
2021 if (!check_share_info(uLevel
,str2
)) {
2025 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2030 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2031 if (*rdata_len
< 0) {
2036 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2040 SSVAL(*rparam
,0,NERR_Success
);
2041 SSVAL(*rparam
,2,0); /* converter word */
2042 SSVAL(*rparam
,4,*rdata_len
);
2047 /****************************************************************************
2048 View the list of available shares.
2050 This function is the server side of the NetShareEnum() RAP call.
2051 It fills the return buffer with share names and share comments.
2052 Note that the return buffer normally (in all known cases) allows only
2053 twelve byte strings for share names (plus one for a nul terminator).
2054 Share names longer than 12 bytes must be skipped.
2055 ****************************************************************************/
2057 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2058 connection_struct
*conn
, uint64_t vuid
,
2059 char *param
, int tpscnt
,
2060 char *data
, int tdscnt
,
2068 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2069 char *str2
= skip_string(param
,tpscnt
,str1
);
2070 char *p
= skip_string(param
,tpscnt
,str2
);
2071 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2072 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2075 int total
=0,counted
=0;
2076 bool missed
= False
;
2078 int data_len
, fixed_len
, string_len
;
2079 int f_len
= 0, s_len
= 0;
2081 if (!str1
|| !str2
|| !p
) {
2085 if (!prefix_ok(str1
,"WrLeh")) {
2088 if (!check_share_info(uLevel
,str2
)) {
2092 /* Ensure all the usershares are loaded. */
2094 load_registry_shares();
2095 count
= load_usershare_shares(NULL
, connections_snum_used
);
2098 data_len
= fixed_len
= string_len
= 0;
2099 for (i
=0;i
<count
;i
++) {
2100 fstring servicename_dos
;
2101 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2104 push_ascii_fstring(servicename_dos
, lp_servicename(talloc_tos(), i
));
2105 /* Maximum name length = 13. */
2106 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2108 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2109 if (data_len
< buf_len
) {
2112 string_len
+= s_len
;
2119 *rdata_len
= fixed_len
+ string_len
;
2120 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2125 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2130 for( i
= 0; i
< count
; i
++ ) {
2131 fstring servicename_dos
;
2132 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2136 push_ascii_fstring(servicename_dos
,
2137 lp_servicename(talloc_tos(), i
));
2138 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2139 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2146 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2150 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2152 SSVAL(*rparam
,4,counted
);
2153 SSVAL(*rparam
,6,total
);
2155 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2156 counted
,total
,uLevel
,
2157 buf_len
,*rdata_len
,mdrcnt
));
2162 /****************************************************************************
2164 ****************************************************************************/
2166 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2167 connection_struct
*conn
,uint64_t vuid
,
2168 char *param
, int tpscnt
,
2169 char *data
, int tdscnt
,
2170 int mdrcnt
,int mprcnt
,
2171 char **rdata
,char **rparam
,
2172 int *rdata_len
,int *rparam_len
)
2174 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2175 char *str2
= skip_string(param
,tpscnt
,str1
);
2176 char *p
= skip_string(param
,tpscnt
,str2
);
2177 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2180 char *pathname
= NULL
;
2181 unsigned int offset
;
2183 size_t converted_size
;
2185 WERROR werr
= WERR_OK
;
2186 TALLOC_CTX
*mem_ctx
= talloc_tos();
2188 struct rpc_pipe_client
*cli
= NULL
;
2189 union srvsvc_NetShareInfo info
;
2190 struct srvsvc_NetShareInfo2 info2
;
2191 struct dcerpc_binding_handle
*b
;
2193 if (!str1
|| !str2
|| !p
) {
2197 /* check it's a supported varient */
2198 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2201 if (!check_share_info(uLevel
,str2
)) {
2208 /* Do we have a string ? */
2209 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2212 pull_ascii_fstring(sharename
,data
);
2218 /* only support disk share adds */
2219 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2223 offset
= IVAL(data
, 16);
2224 if (offset
>= mdrcnt
) {
2225 res
= ERRinvalidparam
;
2229 /* Do we have a string ? */
2230 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2233 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2235 offset
= IVAL(data
, 26);
2237 if (offset
>= mdrcnt
) {
2238 res
= ERRinvalidparam
;
2242 /* Do we have a string ? */
2243 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2247 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2248 offset
? (data
+offset
) : "", &converted_size
))
2250 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2258 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
2260 conn
->sconn
->remote_address
,
2261 conn
->sconn
->msg_ctx
,
2263 if (!NT_STATUS_IS_OK(status
)) {
2264 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2265 nt_errstr(status
)));
2266 res
= W_ERROR_V(ntstatus_to_werror(status
));
2270 b
= cli
->binding_handle
;
2272 info2
.name
= sharename
;
2273 info2
.type
= STYPE_DISKTREE
;
2274 info2
.comment
= comment
;
2275 info2
.permissions
= 0;
2276 info2
.max_users
= 0;
2277 info2
.current_users
= 0;
2278 info2
.path
= pathname
;
2279 info2
.password
= NULL
;
2281 info
.info2
= &info2
;
2283 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2284 cli
->srv_name_slash
,
2289 if (!NT_STATUS_IS_OK(status
)) {
2290 res
= W_ERROR_V(ntstatus_to_werror(status
));
2293 if (!W_ERROR_IS_OK(werr
)) {
2294 res
= W_ERROR_V(werr
);
2299 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2303 SSVAL(*rparam
,0,NERR_Success
);
2304 SSVAL(*rparam
,2,0); /* converter word */
2305 SSVAL(*rparam
,4,*rdata_len
);
2313 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2318 SSVAL(*rparam
,0,res
);
2323 /****************************************************************************
2324 view list of groups available
2325 ****************************************************************************/
2327 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2328 connection_struct
*conn
,uint64_t vuid
,
2329 char *param
, int tpscnt
,
2330 char *data
, int tdscnt
,
2331 int mdrcnt
,int mprcnt
,
2332 char **rdata
,char **rparam
,
2333 int *rdata_len
,int *rparam_len
)
2337 int resume_context
, cli_buf_size
;
2338 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2339 char *str2
= skip_string(param
,tpscnt
,str1
);
2340 char *p
= skip_string(param
,tpscnt
,str2
);
2342 uint32_t num_groups
;
2343 uint32_t resume_handle
;
2344 struct rpc_pipe_client
*samr_pipe
= NULL
;
2345 struct policy_handle samr_handle
, domain_handle
;
2346 NTSTATUS status
, result
;
2347 struct dcerpc_binding_handle
*b
;
2349 if (!str1
|| !str2
|| !p
) {
2353 if (strcmp(str1
,"WrLeh") != 0) {
2358 * W-> resume context (number of users to skip)
2359 * r -> return parameter pointer to receive buffer
2360 * L -> length of receive buffer
2361 * e -> return parameter number of entries
2362 * h -> return parameter total number of users
2365 if (strcmp("B21",str2
) != 0) {
2369 status
= rpc_pipe_open_interface(
2370 talloc_tos(), &ndr_table_samr
,
2371 conn
->session_info
, conn
->sconn
->remote_address
,
2372 conn
->sconn
->msg_ctx
, &samr_pipe
);
2373 if (!NT_STATUS_IS_OK(status
)) {
2374 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2375 nt_errstr(status
)));
2379 b
= samr_pipe
->binding_handle
;
2381 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2382 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2384 if (!NT_STATUS_IS_OK(status
)) {
2385 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2386 nt_errstr(status
)));
2389 if (!NT_STATUS_IS_OK(result
)) {
2390 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2391 nt_errstr(result
)));
2395 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2396 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2397 get_global_sam_sid(), &domain_handle
,
2399 if (!NT_STATUS_IS_OK(status
)) {
2400 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2401 nt_errstr(status
)));
2402 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2405 if (!NT_STATUS_IS_OK(result
)) {
2406 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2407 nt_errstr(result
)));
2408 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2412 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2413 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2414 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2415 "%d\n", resume_context
, cli_buf_size
));
2417 *rdata_len
= cli_buf_size
;
2418 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2425 errflags
= NERR_Success
;
2430 struct samr_SamArray
*sam_entries
;
2431 uint32_t num_entries
;
2433 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2439 if (!NT_STATUS_IS_OK(status
)) {
2440 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2441 "%s\n", nt_errstr(status
)));
2444 if (!NT_STATUS_IS_OK(result
)) {
2446 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2447 "%s\n", nt_errstr(result
)));
2451 if (num_entries
== 0) {
2452 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2453 "no entries -- done\n"));
2457 for(i
=0; i
<num_entries
; i
++) {
2460 name
= sam_entries
->entries
[i
].name
.string
;
2462 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2463 /* set overflow error */
2464 DEBUG(3,("overflow on entry %d group %s\n", i
,
2470 /* truncate the name at 21 chars. */
2472 strlcpy(p
, name
, 21);
2473 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2475 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2480 if (errflags
!= NERR_Success
) {
2484 TALLOC_FREE(sam_entries
);
2487 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2488 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2490 *rdata_len
= PTR_DIFF(p
,*rdata
);
2493 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2497 SSVAL(*rparam
, 0, errflags
);
2498 SSVAL(*rparam
, 2, 0); /* converter word */
2499 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2500 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2505 /*******************************************************************
2506 Get groups that a user is a member of.
2507 ******************************************************************/
2509 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2510 connection_struct
*conn
,uint64_t vuid
,
2511 char *param
, int tpscnt
,
2512 char *data
, int tdscnt
,
2513 int mdrcnt
,int mprcnt
,
2514 char **rdata
,char **rparam
,
2515 int *rdata_len
,int *rparam_len
)
2517 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2518 char *str2
= skip_string(param
,tpscnt
,str1
);
2519 char *UserName
= skip_string(param
,tpscnt
,str2
);
2520 char *p
= skip_string(param
,tpscnt
,UserName
);
2521 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2522 const char *level_string
;
2528 struct rpc_pipe_client
*samr_pipe
= NULL
;
2529 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2530 struct lsa_String name
;
2531 struct lsa_Strings names
;
2532 struct samr_Ids type
, rid
;
2533 struct samr_RidWithAttributeArray
*rids
;
2534 NTSTATUS status
, result
;
2535 struct dcerpc_binding_handle
*b
;
2537 if (!str1
|| !str2
|| !UserName
|| !p
) {
2542 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2547 /* check it's a supported varient */
2549 if ( strcmp(str1
,"zWrLeh") != 0 )
2554 level_string
= "B21";
2560 if (strcmp(level_string
,str2
) != 0)
2563 *rdata_len
= mdrcnt
+ 1024;
2564 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2569 SSVAL(*rparam
,0,NERR_Success
);
2570 SSVAL(*rparam
,2,0); /* converter word */
2573 endp
= *rdata
+ *rdata_len
;
2575 status
= rpc_pipe_open_interface(
2576 talloc_tos(), &ndr_table_samr
,
2577 conn
->session_info
, conn
->sconn
->remote_address
,
2578 conn
->sconn
->msg_ctx
, &samr_pipe
);
2579 if (!NT_STATUS_IS_OK(status
)) {
2580 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2581 nt_errstr(status
)));
2585 b
= samr_pipe
->binding_handle
;
2587 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2588 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2590 if (!NT_STATUS_IS_OK(status
)) {
2591 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2592 nt_errstr(status
)));
2595 if (!NT_STATUS_IS_OK(result
)) {
2596 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2597 nt_errstr(result
)));
2601 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2602 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2603 get_global_sam_sid(), &domain_handle
,
2605 if (!NT_STATUS_IS_OK(status
)) {
2606 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2607 nt_errstr(status
)));
2610 if (!NT_STATUS_IS_OK(result
)) {
2611 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2612 nt_errstr(result
)));
2616 name
.string
= UserName
;
2618 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2619 &domain_handle
, 1, &name
,
2622 if (!NT_STATUS_IS_OK(status
)) {
2623 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2624 nt_errstr(status
)));
2627 if (!NT_STATUS_IS_OK(result
)) {
2628 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2629 nt_errstr(result
)));
2632 if (rid
.count
!= 1) {
2633 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2636 if (type
.count
!= 1) {
2637 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2641 if (type
.ids
[0] != SID_NAME_USER
) {
2642 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2643 sid_type_lookup(type
.ids
[0])));
2647 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2649 SAMR_USER_ACCESS_GET_GROUPS
,
2650 rid
.ids
[0], &user_handle
,
2652 if (!NT_STATUS_IS_OK(status
)) {
2653 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2654 nt_errstr(status
)));
2657 if (!NT_STATUS_IS_OK(result
)) {
2658 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2659 nt_errstr(result
)));
2663 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2664 &user_handle
, &rids
,
2666 if (!NT_STATUS_IS_OK(status
)) {
2667 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2668 nt_errstr(status
)));
2671 if (!NT_STATUS_IS_OK(result
)) {
2672 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2673 nt_errstr(result
)));
2677 for (i
=0; i
<rids
->count
; i
++) {
2679 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2681 1, &rids
->rids
[i
].rid
,
2684 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2685 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2691 *rdata_len
= PTR_DIFF(p
,*rdata
);
2693 SSVAL(*rparam
,4,count
); /* is this right?? */
2694 SSVAL(*rparam
,6,count
); /* is this right?? */
2699 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2701 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2703 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2708 /*******************************************************************
2710 ******************************************************************/
2712 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2713 connection_struct
*conn
, uint64_t vuid
,
2714 char *param
, int tpscnt
,
2715 char *data
, int tdscnt
,
2716 int mdrcnt
,int mprcnt
,
2717 char **rdata
,char **rparam
,
2718 int *rdata_len
,int *rparam_len
)
2723 int i
, resume_context
, cli_buf_size
;
2724 uint32_t resume_handle
;
2726 struct rpc_pipe_client
*samr_pipe
= NULL
;
2727 struct policy_handle samr_handle
, domain_handle
;
2728 NTSTATUS status
, result
;
2730 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2731 char *str2
= skip_string(param
,tpscnt
,str1
);
2732 char *p
= skip_string(param
,tpscnt
,str2
);
2735 struct dcerpc_binding_handle
*b
;
2737 if (!str1
|| !str2
|| !p
) {
2741 if (strcmp(str1
,"WrLeh") != 0)
2744 * W-> resume context (number of users to skip)
2745 * r -> return parameter pointer to receive buffer
2746 * L -> length of receive buffer
2747 * e -> return parameter number of entries
2748 * h -> return parameter total number of users
2751 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2752 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2753 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2754 resume_context
, cli_buf_size
));
2757 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2762 /* check it's a supported varient */
2763 if (strcmp("B21",str2
) != 0)
2766 *rdata_len
= cli_buf_size
;
2767 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2773 endp
= *rdata
+ *rdata_len
;
2775 status
= rpc_pipe_open_interface(
2776 talloc_tos(), &ndr_table_samr
,
2777 conn
->session_info
, conn
->sconn
->remote_address
,
2778 conn
->sconn
->msg_ctx
, &samr_pipe
);
2779 if (!NT_STATUS_IS_OK(status
)) {
2780 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2781 nt_errstr(status
)));
2785 b
= samr_pipe
->binding_handle
;
2787 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2788 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2790 if (!NT_STATUS_IS_OK(status
)) {
2791 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2792 nt_errstr(status
)));
2795 if (!NT_STATUS_IS_OK(result
)) {
2796 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2797 nt_errstr(result
)));
2801 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2802 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2803 get_global_sam_sid(), &domain_handle
,
2805 if (!NT_STATUS_IS_OK(status
)) {
2806 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2807 nt_errstr(status
)));
2808 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2811 if (!NT_STATUS_IS_OK(result
)) {
2812 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2813 nt_errstr(result
)));
2814 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2818 errflags
=NERR_Success
;
2823 struct samr_SamArray
*sam_entries
;
2824 uint32_t num_entries
;
2826 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2833 if (!NT_STATUS_IS_OK(status
)) {
2834 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2835 "%s\n", nt_errstr(status
)));
2838 if (!NT_STATUS_IS_OK(result
)) {
2839 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2840 "%s\n", nt_errstr(result
)));
2844 if (num_entries
== 0) {
2845 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2846 "no entries -- done\n"));
2850 for (i
=0; i
<num_entries
; i
++) {
2853 name
= sam_entries
->entries
[i
].name
.string
;
2855 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2856 &&(strlen(name
)<=21)) {
2857 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2858 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2859 "username %s\n",count_sent
,p
));
2863 /* set overflow error */
2864 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2865 "username %s\n",count_sent
,name
));
2871 if (errflags
!= NERR_Success
) {
2875 TALLOC_FREE(sam_entries
);
2878 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2879 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2881 *rdata_len
= PTR_DIFF(p
,*rdata
);
2883 SSVAL(*rparam
,0,errflags
);
2884 SSVAL(*rparam
,2,0); /* converter word */
2885 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2886 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2891 /****************************************************************************
2892 Get the time of day info.
2893 ****************************************************************************/
2895 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2896 connection_struct
*conn
,uint64_t vuid
,
2897 char *param
, int tpscnt
,
2898 char *data
, int tdscnt
,
2899 int mdrcnt
,int mprcnt
,
2900 char **rdata
,char **rparam
,
2901 int *rdata_len
,int *rparam_len
)
2904 time_t unixdate
= time(NULL
);
2908 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2914 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2919 SSVAL(*rparam
,0,NERR_Success
);
2920 SSVAL(*rparam
,2,0); /* converter word */
2924 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2925 by NT in a "net time" operation,
2926 it seems to ignore the one below */
2928 /* the client expects to get localtime, not GMT, in this bit
2929 (I think, this needs testing) */
2930 t
= localtime(&unixdate
);
2935 SIVAL(p
,4,0); /* msecs ? */
2936 SCVAL(p
,8,t
->tm_hour
);
2937 SCVAL(p
,9,t
->tm_min
);
2938 SCVAL(p
,10,t
->tm_sec
);
2939 SCVAL(p
,11,0); /* hundredths of seconds */
2940 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2941 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2942 SCVAL(p
,16,t
->tm_mday
);
2943 SCVAL(p
,17,t
->tm_mon
+ 1);
2944 SSVAL(p
,18,1900+t
->tm_year
);
2945 SCVAL(p
,20,t
->tm_wday
);
2950 /****************************************************************************
2951 Set the user password (SamOEM version - gets plaintext).
2952 ****************************************************************************/
2954 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
2955 connection_struct
*conn
,uint64_t vuid
,
2956 char *param
, int tpscnt
,
2957 char *data
, int tdscnt
,
2958 int mdrcnt
,int mprcnt
,
2959 char **rdata
,char **rparam
,
2960 int *rdata_len
,int *rparam_len
)
2963 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2965 TALLOC_CTX
*mem_ctx
= talloc_tos();
2966 NTSTATUS status
, result
;
2967 struct rpc_pipe_client
*cli
= NULL
;
2968 struct lsa_AsciiString server
, account
;
2969 struct samr_CryptPassword password
;
2970 struct samr_Password hash
;
2971 int errcode
= NERR_badpass
;
2973 struct dcerpc_binding_handle
*b
;
2976 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2986 SSVAL(*rparam
,0,NERR_badpass
);
2989 * Check the parameter definition is correct.
2992 /* Do we have a string ? */
2993 if (skip_string(param
,tpscnt
,p
) == 0) {
2996 if(!strequal(p
, "zsT")) {
2997 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3000 p
= skip_string(param
, tpscnt
, p
);
3005 /* Do we have a string ? */
3006 if (skip_string(param
,tpscnt
,p
) == 0) {
3009 if(!strequal(p
, "B516B16")) {
3010 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3013 p
= skip_string(param
,tpscnt
,p
);
3017 /* Do we have a string ? */
3018 if (skip_string(param
,tpscnt
,p
) == 0) {
3021 p
+= pull_ascii_fstring(user
,p
);
3023 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3025 if (tdscnt
!= 532) {
3026 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3030 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3031 if (bufsize
!= 532) {
3032 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3036 memcpy(password
.data
, data
, 516);
3037 memcpy(hash
.hash
, data
+516, 16);
3039 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
3041 conn
->sconn
->remote_address
,
3042 conn
->sconn
->msg_ctx
,
3044 if (!NT_STATUS_IS_OK(status
)) {
3045 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3046 nt_errstr(status
)));
3047 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3051 b
= cli
->binding_handle
;
3053 init_lsa_AsciiString(&server
, lp_netbios_name());
3054 init_lsa_AsciiString(&account
, user
);
3056 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3062 if (!NT_STATUS_IS_OK(status
)) {
3063 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3066 if (!NT_STATUS_IS_OK(result
)) {
3067 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3071 errcode
= NERR_Success
;
3073 SSVAL(*rparam
,0,errcode
);
3074 SSVAL(*rparam
,2,0); /* converter word */
3079 /****************************************************************************
3082 ****************************************************************************/
3084 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3085 connection_struct
*conn
,uint64_t vuid
,
3086 char *param
, int tpscnt
,
3087 char *data
, int tdscnt
,
3088 int mdrcnt
,int mprcnt
,
3089 char **rdata
,char **rparam
,
3090 int *rdata_len
,int *rparam_len
)
3092 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3093 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3094 char *str2
= skip_string(param
,tpscnt
,str1
);
3095 char *p
= skip_string(param
,tpscnt
,str2
);
3099 WERROR werr
= WERR_OK
;
3101 TALLOC_CTX
*mem_ctx
= talloc_tos();
3103 struct rpc_pipe_client
*cli
= NULL
;
3104 struct dcerpc_binding_handle
*b
= NULL
;
3105 struct policy_handle handle
;
3106 struct spoolss_DevmodeContainer devmode_ctr
;
3107 enum spoolss_JobControl command
;
3109 if (!str1
|| !str2
|| !p
) {
3113 * We use 1 here not 2 as we're checking
3114 * the last byte we want to access is safe.
3116 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3119 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3122 /* check it's a supported varient */
3123 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3127 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3133 ZERO_STRUCT(handle
);
3135 status
= rpc_pipe_open_interface(conn
,
3138 conn
->sconn
->remote_address
,
3139 conn
->sconn
->msg_ctx
,
3141 if (!NT_STATUS_IS_OK(status
)) {
3142 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3143 nt_errstr(status
)));
3144 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3147 b
= cli
->binding_handle
;
3149 ZERO_STRUCT(devmode_ctr
);
3151 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3155 JOB_ACCESS_ADMINISTER
,
3158 if (!NT_STATUS_IS_OK(status
)) {
3159 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3162 if (!W_ERROR_IS_OK(werr
)) {
3163 errcode
= W_ERROR_V(werr
);
3167 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3168 * and NERR_DestNotFound if share did not exist */
3170 errcode
= NERR_Success
;
3173 case 81: /* delete */
3174 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3176 case 82: /* pause */
3177 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3179 case 83: /* resume */
3180 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3183 errcode
= NERR_notsupported
;
3187 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3190 NULL
, /* unique ptr ctr */
3193 if (!NT_STATUS_IS_OK(status
)) {
3194 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3197 if (!W_ERROR_IS_OK(werr
)) {
3198 errcode
= W_ERROR_V(werr
);
3203 if (b
&& is_valid_policy_hnd(&handle
)) {
3204 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3207 SSVAL(*rparam
,0,errcode
);
3208 SSVAL(*rparam
,2,0); /* converter word */
3213 /****************************************************************************
3214 Purge a print queue - or pause or resume it.
3215 ****************************************************************************/
3217 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3218 connection_struct
*conn
,uint64_t vuid
,
3219 char *param
, int tpscnt
,
3220 char *data
, int tdscnt
,
3221 int mdrcnt
,int mprcnt
,
3222 char **rdata
,char **rparam
,
3223 int *rdata_len
,int *rparam_len
)
3225 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3226 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3227 char *str2
= skip_string(param
,tpscnt
,str1
);
3228 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3229 int errcode
= NERR_notsupported
;
3230 WERROR werr
= WERR_OK
;
3233 TALLOC_CTX
*mem_ctx
= talloc_tos();
3234 struct rpc_pipe_client
*cli
= NULL
;
3235 struct dcerpc_binding_handle
*b
= NULL
;
3236 struct policy_handle handle
;
3237 struct spoolss_SetPrinterInfoCtr info_ctr
;
3238 struct spoolss_DevmodeContainer devmode_ctr
;
3239 struct sec_desc_buf secdesc_ctr
;
3240 enum spoolss_PrinterControl command
;
3242 if (!str1
|| !str2
|| !QueueName
) {
3246 /* check it's a supported varient */
3247 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3251 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3257 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3261 ZERO_STRUCT(handle
);
3263 status
= rpc_pipe_open_interface(conn
,
3266 conn
->sconn
->remote_address
,
3267 conn
->sconn
->msg_ctx
,
3269 if (!NT_STATUS_IS_OK(status
)) {
3270 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3271 nt_errstr(status
)));
3272 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3275 b
= cli
->binding_handle
;
3277 ZERO_STRUCT(devmode_ctr
);
3279 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3283 PRINTER_ACCESS_ADMINISTER
,
3286 if (!NT_STATUS_IS_OK(status
)) {
3287 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3290 if (!W_ERROR_IS_OK(werr
)) {
3291 errcode
= W_ERROR_V(werr
);
3296 case 74: /* Pause queue */
3297 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3299 case 75: /* Resume queue */
3300 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3302 case 103: /* Purge */
3303 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3306 werr
= WERR_NOT_SUPPORTED
;
3310 if (!W_ERROR_IS_OK(werr
)) {
3311 errcode
= W_ERROR_V(werr
);
3315 ZERO_STRUCT(info_ctr
);
3316 ZERO_STRUCT(secdesc_ctr
);
3318 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3325 if (!NT_STATUS_IS_OK(status
)) {
3326 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3329 if (!W_ERROR_IS_OK(werr
)) {
3330 errcode
= W_ERROR_V(werr
);
3334 errcode
= W_ERROR_V(werr
);
3338 if (b
&& is_valid_policy_hnd(&handle
)) {
3339 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3342 SSVAL(*rparam
,0,errcode
);
3343 SSVAL(*rparam
,2,0); /* converter word */
3348 /****************************************************************************
3349 set the property of a print job (undocumented?)
3350 ? function = 0xb -> set name of print job
3351 ? function = 0x6 -> move print job up/down
3352 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3353 or <WWsTP> <WB21BB16B10zWWzDDz>
3354 ****************************************************************************/
3356 static int check_printjob_info(struct pack_desc
* desc
,
3357 int uLevel
, char* id
)
3359 desc
->subformat
= NULL
;
3361 case 0: desc
->format
= "W"; break;
3362 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3363 case 2: desc
->format
= "WWzWWDDzz"; break;
3364 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3365 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3367 DEBUG(0,("check_printjob_info: invalid level %d\n",
3371 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3372 DEBUG(0,("check_printjob_info: invalid format %s\n",
3373 id
? id
: "<NULL>" ));
3379 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3380 connection_struct
*conn
, uint64_t vuid
,
3381 char *param
, int tpscnt
,
3382 char *data
, int tdscnt
,
3383 int mdrcnt
,int mprcnt
,
3384 char **rdata
,char **rparam
,
3385 int *rdata_len
,int *rparam_len
)
3387 struct pack_desc desc
;
3388 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3389 char *str2
= skip_string(param
,tpscnt
,str1
);
3390 char *p
= skip_string(param
,tpscnt
,str2
);
3393 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3394 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3397 TALLOC_CTX
*mem_ctx
= talloc_tos();
3400 struct rpc_pipe_client
*cli
= NULL
;
3401 struct dcerpc_binding_handle
*b
= NULL
;
3402 struct policy_handle handle
;
3403 struct spoolss_DevmodeContainer devmode_ctr
;
3404 struct spoolss_JobInfoContainer ctr
;
3405 union spoolss_JobInfo info
;
3406 struct spoolss_SetJobInfo1 info1
;
3408 if (!str1
|| !str2
|| !p
) {
3412 * We use 1 here not 2 as we're checking
3413 * the last byte we want to access is safe.
3415 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3418 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3421 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3428 /* check it's a supported varient */
3429 if ((strcmp(str1
,"WWsTP")) ||
3430 (!check_printjob_info(&desc
,uLevel
,str2
)))
3433 errcode
= NERR_notsupported
;
3437 /* change print job name, data gives the name */
3443 ZERO_STRUCT(handle
);
3445 status
= rpc_pipe_open_interface(conn
,
3448 conn
->sconn
->remote_address
,
3449 conn
->sconn
->msg_ctx
,
3451 if (!NT_STATUS_IS_OK(status
)) {
3452 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3453 nt_errstr(status
)));
3454 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3457 b
= cli
->binding_handle
;
3459 ZERO_STRUCT(devmode_ctr
);
3461 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3468 if (!NT_STATUS_IS_OK(status
)) {
3469 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3472 if (!W_ERROR_IS_OK(werr
)) {
3473 errcode
= W_ERROR_V(werr
);
3477 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3483 if (!W_ERROR_IS_OK(werr
)) {
3484 errcode
= W_ERROR_V(werr
);
3490 info1
.job_id
= info
.info1
.job_id
;
3491 info1
.printer_name
= info
.info1
.printer_name
;
3492 info1
.user_name
= info
.info1
.user_name
;
3493 info1
.document_name
= data
;
3494 info1
.data_type
= info
.info1
.data_type
;
3495 info1
.text_status
= info
.info1
.text_status
;
3496 info1
.status
= info
.info1
.status
;
3497 info1
.priority
= info
.info1
.priority
;
3498 info1
.position
= info
.info1
.position
;
3499 info1
.total_pages
= info
.info1
.total_pages
;
3500 info1
.pages_printed
= info
.info1
.pages_printed
;
3501 info1
.submitted
= info
.info1
.submitted
;
3504 ctr
.info
.info1
= &info1
;
3506 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3512 if (!NT_STATUS_IS_OK(status
)) {
3513 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3516 if (!W_ERROR_IS_OK(werr
)) {
3517 errcode
= W_ERROR_V(werr
);
3521 errcode
= NERR_Success
;
3524 if (b
&& is_valid_policy_hnd(&handle
)) {
3525 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3528 SSVALS(*rparam
,0,errcode
);
3529 SSVAL(*rparam
,2,0); /* converter word */
3535 /****************************************************************************
3536 Get info about the server.
3537 ****************************************************************************/
3539 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3540 connection_struct
*conn
,uint64_t vuid
,
3541 char *param
, int tpscnt
,
3542 char *data
, int tdscnt
,
3543 int mdrcnt
,int mprcnt
,
3544 char **rdata
,char **rparam
,
3545 int *rdata_len
,int *rparam_len
)
3547 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3548 char *str2
= skip_string(param
,tpscnt
,str1
);
3549 char *p
= skip_string(param
,tpscnt
,str2
);
3550 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3556 TALLOC_CTX
*mem_ctx
= talloc_tos();
3557 struct rpc_pipe_client
*cli
= NULL
;
3558 union srvsvc_NetSrvInfo info
;
3560 struct dcerpc_binding_handle
*b
;
3562 if (!str1
|| !str2
|| !p
) {
3566 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3568 /* check it's a supported varient */
3569 if (!prefix_ok(str1
,"WrLh")) {
3575 if (strcmp(str2
,"B16") != 0) {
3581 if (strcmp(str2
,"B16BBDz") != 0) {
3587 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3593 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3599 if (strcmp(str2
,"DN") != 0) {
3605 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3614 *rdata_len
= mdrcnt
;
3615 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3621 p2
= p
+ struct_len
;
3623 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
3625 conn
->sconn
->remote_address
,
3626 conn
->sconn
->msg_ctx
,
3628 if (!NT_STATUS_IS_OK(status
)) {
3629 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3630 nt_errstr(status
)));
3631 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3635 b
= cli
->binding_handle
;
3637 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3642 if (!NT_STATUS_IS_OK(status
)) {
3643 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3646 if (!W_ERROR_IS_OK(werr
)) {
3647 errcode
= W_ERROR_V(werr
);
3651 if (info
.info101
== NULL
) {
3652 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3657 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3658 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3662 SCVAL(p
,0,info
.info101
->version_major
);
3663 SCVAL(p
,1,info
.info101
->version_minor
);
3664 SIVAL(p
,2,info
.info101
->server_type
);
3666 if (mdrcnt
== struct_len
) {
3669 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3670 if (mdrcnt
- struct_len
<= 0) {
3674 info
.info101
->comment
,
3675 MIN(mdrcnt
- struct_len
,
3676 MAX_SERVER_STRING_LENGTH
),
3678 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3686 return False
; /* not yet implemented */
3689 errcode
= NERR_Success
;
3693 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3696 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3700 SSVAL(*rparam
,0,errcode
);
3701 SSVAL(*rparam
,2,0); /* converter word */
3702 SSVAL(*rparam
,4,*rdata_len
);
3707 /****************************************************************************
3708 Get info about the server.
3709 ****************************************************************************/
3711 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3712 connection_struct
*conn
,uint64_t vuid
,
3713 char *param
, int tpscnt
,
3714 char *data
, int tdscnt
,
3715 int mdrcnt
,int mprcnt
,
3716 char **rdata
,char **rparam
,
3717 int *rdata_len
,int *rparam_len
)
3719 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3720 char *str2
= skip_string(param
,tpscnt
,str1
);
3721 char *p
= skip_string(param
,tpscnt
,str2
);
3724 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3726 if (!str1
|| !str2
|| !p
) {
3730 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3733 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3738 /* check it's a supported varient */
3739 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3743 *rdata_len
= mdrcnt
+ 1024;
3744 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3749 SSVAL(*rparam
,0,NERR_Success
);
3750 SSVAL(*rparam
,2,0); /* converter word */
3753 endp
= *rdata
+ *rdata_len
;
3755 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3760 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3761 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3762 if (!strupper_m(p2
)) {
3765 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3771 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3772 strlcpy(p2
,conn
->session_info
->unix_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3773 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3779 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3780 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3781 if (!strupper_m(p2
)) {
3784 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3790 SCVAL(p
,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g 4 in 4.1 */
3791 SCVAL(p
,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g .1 in 4.1 */
3794 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3795 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3796 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3802 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3803 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3804 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3810 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3812 SSVAL(*rparam
,4,*rdata_len
);
3817 /****************************************************************************
3818 get info about a user
3820 struct user_info_11 {
3821 char usri11_name[21]; 0-20
3823 char *usri11_comment; 22-25
3824 char *usri11_usr_comment; 26-29
3825 unsigned short usri11_priv; 30-31
3826 unsigned long usri11_auth_flags; 32-35
3827 long usri11_password_age; 36-39
3828 char *usri11_homedir; 40-43
3829 char *usri11_parms; 44-47
3830 long usri11_last_logon; 48-51
3831 long usri11_last_logoff; 52-55
3832 unsigned short usri11_bad_pw_count; 56-57
3833 unsigned short usri11_num_logons; 58-59
3834 char *usri11_logon_server; 60-63
3835 unsigned short usri11_country_code; 64-65
3836 char *usri11_workstations; 66-69
3837 unsigned long usri11_max_storage; 70-73
3838 unsigned short usri11_units_per_week; 74-75
3839 unsigned char *usri11_logon_hours; 76-79
3840 unsigned short usri11_code_page; 80-81
3845 usri11_name specifies the user name for which information is retrieved
3847 usri11_pad aligns the next data structure element to a word boundary
3849 usri11_comment is a null terminated ASCII comment
3851 usri11_user_comment is a null terminated ASCII comment about the user
3853 usri11_priv specifies the level of the privilege assigned to the user.
3854 The possible values are:
3856 Name Value Description
3857 USER_PRIV_GUEST 0 Guest privilege
3858 USER_PRIV_USER 1 User privilege
3859 USER_PRV_ADMIN 2 Administrator privilege
3861 usri11_auth_flags specifies the account operator privileges. The
3862 possible values are:
3864 Name Value Description
3865 AF_OP_PRINT 0 Print operator
3868 Leach, Naik [Page 28]
3872 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3875 AF_OP_COMM 1 Communications operator
3876 AF_OP_SERVER 2 Server operator
3877 AF_OP_ACCOUNTS 3 Accounts operator
3880 usri11_password_age specifies how many seconds have elapsed since the
3881 password was last changed.
3883 usri11_home_dir points to a null terminated ASCII string that contains
3884 the path name of the user's home directory.
3886 usri11_parms points to a null terminated ASCII string that is set
3887 aside for use by applications.
3889 usri11_last_logon specifies the time when the user last logged on.
3890 This value is stored as the number of seconds elapsed since
3891 00:00:00, January 1, 1970.
3893 usri11_last_logoff specifies the time when the user last logged off.
3894 This value is stored as the number of seconds elapsed since
3895 00:00:00, January 1, 1970. A value of 0 means the last logoff
3898 usri11_bad_pw_count specifies the number of incorrect passwords
3899 entered since the last successful logon.
3901 usri11_log1_num_logons specifies the number of times this user has
3902 logged on. A value of -1 means the number of logons is unknown.
3904 usri11_logon_server points to a null terminated ASCII string that
3905 contains the name of the server to which logon requests are sent.
3906 A null string indicates logon requests should be sent to the
3909 usri11_country_code specifies the country code for the user's language
3912 usri11_workstations points to a null terminated ASCII string that
3913 contains the names of workstations the user may log on from.
3914 There may be up to 8 workstations, with the names separated by
3915 commas. A null strings indicates there are no restrictions.
3917 usri11_max_storage specifies the maximum amount of disk space the user
3918 can occupy. A value of 0xffffffff indicates there are no
3921 usri11_units_per_week specifies the equal number of time units into
3922 which a week is divided. This value must be equal to 168.
3924 usri11_logon_hours points to a 21 byte (168 bits) string that
3925 specifies the time during which the user can log on. Each bit
3926 represents one unique hour in a week. The first bit (bit 0, word
3927 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3931 Leach, Naik [Page 29]
3935 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3938 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3939 are no restrictions.
3941 usri11_code_page specifies the code page for the user's language of
3944 All of the pointers in this data structure need to be treated
3945 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3946 to be ignored. The converter word returned in the parameters section
3947 needs to be subtracted from the lower 16 bits to calculate an offset
3948 into the return buffer where this ASCII string resides.
3950 There is no auxiliary data in the response.
3952 ****************************************************************************/
3954 #define usri11_name 0
3955 #define usri11_pad 21
3956 #define usri11_comment 22
3957 #define usri11_usr_comment 26
3958 #define usri11_full_name 30
3959 #define usri11_priv 34
3960 #define usri11_auth_flags 36
3961 #define usri11_password_age 40
3962 #define usri11_homedir 44
3963 #define usri11_parms 48
3964 #define usri11_last_logon 52
3965 #define usri11_last_logoff 56
3966 #define usri11_bad_pw_count 60
3967 #define usri11_num_logons 62
3968 #define usri11_logon_server 64
3969 #define usri11_country_code 68
3970 #define usri11_workstations 70
3971 #define usri11_max_storage 74
3972 #define usri11_units_per_week 78
3973 #define usri11_logon_hours 80
3974 #define usri11_code_page 84
3975 #define usri11_end 86
3977 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
3978 connection_struct
*conn
, uint64_t vuid
,
3979 char *param
, int tpscnt
,
3980 char *data
, int tdscnt
,
3981 int mdrcnt
,int mprcnt
,
3982 char **rdata
,char **rparam
,
3983 int *rdata_len
,int *rparam_len
)
3985 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3986 char *str2
= skip_string(param
,tpscnt
,str1
);
3987 char *UserName
= skip_string(param
,tpscnt
,str2
);
3988 char *p
= skip_string(param
,tpscnt
,UserName
);
3989 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3992 const char *level_string
;
3994 TALLOC_CTX
*mem_ctx
= talloc_tos();
3995 NTSTATUS status
, result
;
3996 struct rpc_pipe_client
*cli
= NULL
;
3997 struct policy_handle connect_handle
, domain_handle
, user_handle
;
3998 struct lsa_String domain_name
;
3999 struct dom_sid2
*domain_sid
;
4000 struct lsa_String names
;
4001 struct samr_Ids rids
;
4002 struct samr_Ids types
;
4003 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4005 union samr_UserInfo
*info
;
4006 struct dcerpc_binding_handle
*b
= NULL
;
4008 if (!str1
|| !str2
|| !UserName
|| !p
) {
4013 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4018 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4020 /* check it's a supported variant */
4021 if (strcmp(str1
,"zWrLh") != 0) {
4025 case 0: level_string
= "B21"; break;
4026 case 1: level_string
= "B21BB16DWzzWz"; break;
4027 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4028 case 10: level_string
= "B21Bzzz"; break;
4029 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4030 default: return False
;
4033 if (strcmp(level_string
,str2
) != 0) {
4037 *rdata_len
= mdrcnt
+ 1024;
4038 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4044 endp
= *rdata
+ *rdata_len
;
4045 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4050 ZERO_STRUCT(connect_handle
);
4051 ZERO_STRUCT(domain_handle
);
4052 ZERO_STRUCT(user_handle
);
4054 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
4056 conn
->sconn
->remote_address
,
4057 conn
->sconn
->msg_ctx
,
4059 if (!NT_STATUS_IS_OK(status
)) {
4060 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4061 nt_errstr(status
)));
4062 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4066 b
= cli
->binding_handle
;
4068 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4070 SAMR_ACCESS_CONNECT_TO_SERVER
|
4071 SAMR_ACCESS_ENUM_DOMAINS
|
4072 SAMR_ACCESS_LOOKUP_DOMAIN
,
4075 if (!NT_STATUS_IS_OK(status
)) {
4076 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4079 if (!NT_STATUS_IS_OK(result
)) {
4080 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4084 init_lsa_String(&domain_name
, get_global_sam_name());
4086 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4091 if (!NT_STATUS_IS_OK(status
)) {
4092 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4095 if (!NT_STATUS_IS_OK(result
)) {
4096 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4100 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4102 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4106 if (!NT_STATUS_IS_OK(status
)) {
4107 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4110 if (!NT_STATUS_IS_OK(result
)) {
4111 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4115 init_lsa_String(&names
, UserName
);
4117 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4124 if (!NT_STATUS_IS_OK(status
)) {
4125 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4128 if (!NT_STATUS_IS_OK(result
)) {
4129 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4133 if (rids
.count
!= 1) {
4134 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4137 if (rids
.count
!= types
.count
) {
4138 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4141 if (types
.ids
[0] != SID_NAME_USER
) {
4142 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4148 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4150 SAMR_USER_ACCESS_GET_LOCALE
|
4151 SAMR_USER_ACCESS_GET_LOGONINFO
|
4152 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4153 SAMR_USER_ACCESS_GET_GROUPS
|
4154 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4155 SEC_STD_READ_CONTROL
,
4159 if (!NT_STATUS_IS_OK(status
)) {
4160 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4163 if (!NT_STATUS_IS_OK(result
)) {
4164 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4168 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4173 if (!NT_STATUS_IS_OK(status
)) {
4174 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4177 if (!NT_STATUS_IS_OK(result
)) {
4178 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4183 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4186 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4191 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4192 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4193 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4198 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4199 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4200 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4205 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4206 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4207 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4208 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4215 const char *homedir
= info
->info21
.home_directory
.string
;
4216 /* modelled after NTAS 3.51 reply */
4217 SSVAL(p
,usri11_priv
,
4218 (get_current_uid(conn
) == sec_initial_uid())?
4219 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4220 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4221 SIVALS(p
,usri11_password_age
,-1); /* password age */
4222 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4223 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4224 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4228 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4229 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4230 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4234 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4235 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4236 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4237 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4238 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4239 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4240 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4244 SSVAL(p
,usri11_country_code
,0); /* country code */
4246 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4247 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4248 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4253 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4254 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4255 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4257 /* a simple way to get logon hours at all times. */
4259 SCVAL(p2
,21,0); /* fix zero termination */
4260 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4265 SSVAL(p
,usri11_code_page
,0); /* code page */
4268 if (uLevel
== 1 || uLevel
== 2) {
4269 memset(p
+22,' ',16); /* password */
4270 SIVALS(p
,38,-1); /* password age */
4272 (get_current_uid(conn
) == sec_initial_uid())?
4273 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4274 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4275 strlcpy(p2
, info
->info21
.home_directory
.string
,
4277 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4281 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4283 SSVAL(p
,52,0); /* flags */
4284 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4285 strlcpy(p2
, info
->info21
.logon_script
.string
,
4287 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4292 SIVAL(p
,58,0); /* auth_flags */
4293 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4294 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4295 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4299 SIVAL(p
,66,0); /* urs_comment */
4300 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4301 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4302 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4306 SIVAL(p
,74,0); /* workstations */
4307 SIVAL(p
,78,0); /* last_logon */
4308 SIVAL(p
,82,0); /* last_logoff */
4309 SIVALS(p
,86,-1); /* acct_expires */
4310 SIVALS(p
,90,-1); /* max_storage */
4311 SSVAL(p
,94,168); /* units_per_week */
4312 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4315 SSVALS(p
,100,-1); /* bad_pw_count */
4316 SSVALS(p
,102,-1); /* num_logons */
4317 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4319 TALLOC_CTX
*ctx
= talloc_tos();
4320 int space_rem
= *rdata_len
- (p2
- *rdata
);
4323 if (space_rem
<= 0) {
4326 tmp
= talloc_strdup(ctx
, "\\\\%L");
4330 tmp
= talloc_sub_basic(ctx
,
4343 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4347 SSVAL(p
,108,49); /* country_code */
4348 SSVAL(p
,110,860); /* code page */
4352 errcode
= NERR_Success
;
4355 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4357 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4358 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4360 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4361 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4363 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4364 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4367 SSVAL(*rparam
,0,errcode
);
4368 SSVAL(*rparam
,2,0); /* converter word */
4369 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4374 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4375 connection_struct
*conn
,uint64_t vuid
,
4376 char *param
, int tpscnt
,
4377 char *data
, int tdscnt
,
4378 int mdrcnt
,int mprcnt
,
4379 char **rdata
,char **rparam
,
4380 int *rdata_len
,int *rparam_len
)
4382 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4383 char *str2
= skip_string(param
,tpscnt
,str1
);
4384 char *p
= skip_string(param
,tpscnt
,str2
);
4386 struct pack_desc desc
;
4388 /* With share level security vuid will always be zero.
4389 Don't depend on vuser being non-null !!. JRA */
4390 struct user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4392 if (!str1
|| !str2
|| !p
) {
4397 DEBUG(3,(" Username of UID %d is %s\n",
4398 (int)vuser
->session_info
->unix_token
->uid
,
4399 vuser
->session_info
->unix_info
->unix_name
));
4402 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4403 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4408 memset((char *)&desc
,'\0',sizeof(desc
));
4410 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4412 /* check it's a supported varient */
4413 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4416 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4420 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4427 desc
.buflen
= mdrcnt
;
4428 desc
.subformat
= NULL
;
4431 if (init_package(&desc
,1,0)) {
4432 PACKI(&desc
,"W",0); /* code */
4433 PACKS(&desc
,"B21",name
); /* eff. name */
4434 PACKS(&desc
,"B",""); /* pad */
4436 (get_current_uid(conn
) == sec_initial_uid())?
4437 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4438 PACKI(&desc
,"D",0); /* auth flags XXX */
4439 PACKI(&desc
,"W",0); /* num logons */
4440 PACKI(&desc
,"W",0); /* bad pw count */
4441 PACKI(&desc
,"D",0); /* last logon */
4442 PACKI(&desc
,"D",-1); /* last logoff */
4443 PACKI(&desc
,"D",-1); /* logoff time */
4444 PACKI(&desc
,"D",-1); /* kickoff time */
4445 PACKI(&desc
,"D",0); /* password age */
4446 PACKI(&desc
,"D",0); /* password can change */
4447 PACKI(&desc
,"D",-1); /* password must change */
4451 fstrcpy(mypath
,"\\\\");
4452 fstrcat(mypath
,get_local_machine_name());
4453 if (!strupper_m(mypath
)) {
4456 PACKS(&desc
,"z",mypath
); /* computer */
4459 PACKS(&desc
,"z",lp_workgroup());/* domain */
4460 PACKS(&desc
,"z", vuser
?
4461 vuser
->session_info
->info
->logon_script
4462 : ""); /* script path */
4463 PACKI(&desc
,"D",0x00000000); /* reserved */
4466 *rdata_len
= desc
.usedlen
;
4468 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4472 SSVALS(*rparam
,0,desc
.errcode
);
4474 SSVAL(*rparam
,4,desc
.neededlen
);
4476 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4481 /****************************************************************************
4482 api_WAccessGetUserPerms
4483 ****************************************************************************/
4485 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4486 connection_struct
*conn
,uint64_t vuid
,
4487 char *param
, int tpscnt
,
4488 char *data
, int tdscnt
,
4489 int mdrcnt
,int mprcnt
,
4490 char **rdata
,char **rparam
,
4491 int *rdata_len
,int *rparam_len
)
4493 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4494 char *str2
= skip_string(param
,tpscnt
,str1
);
4495 char *user
= skip_string(param
,tpscnt
,str2
);
4496 char *resource
= skip_string(param
,tpscnt
,user
);
4498 if (!str1
|| !str2
|| !user
|| !resource
) {
4502 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4505 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4507 /* check it's a supported varient */
4508 if (strcmp(str1
,"zzh") != 0) {
4511 if (strcmp(str2
,"") != 0) {
4516 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4520 SSVALS(*rparam
,0,0); /* errorcode */
4521 SSVAL(*rparam
,2,0); /* converter word */
4522 SSVAL(*rparam
,4,0x7f); /* permission flags */
4527 /****************************************************************************
4528 api_WPrintJobEnumerate
4529 ****************************************************************************/
4531 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4532 connection_struct
*conn
, uint64_t vuid
,
4533 char *param
, int tpscnt
,
4534 char *data
, int tdscnt
,
4535 int mdrcnt
,int mprcnt
,
4536 char **rdata
,char **rparam
,
4537 int *rdata_len
,int *rparam_len
)
4539 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4540 char *str2
= skip_string(param
,tpscnt
,str1
);
4541 char *p
= skip_string(param
,tpscnt
,str2
);
4545 struct pack_desc desc
;
4548 TALLOC_CTX
*mem_ctx
= talloc_tos();
4551 struct rpc_pipe_client
*cli
= NULL
;
4552 struct dcerpc_binding_handle
*b
= NULL
;
4553 struct policy_handle handle
;
4554 struct spoolss_DevmodeContainer devmode_ctr
;
4555 union spoolss_JobInfo info
;
4557 if (!str1
|| !str2
|| !p
) {
4561 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4563 memset((char *)&desc
,'\0',sizeof(desc
));
4564 memset((char *)&status
,'\0',sizeof(status
));
4566 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4568 /* check it's a supported varient */
4569 if (strcmp(str1
,"WWrLh") != 0) {
4572 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4576 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4580 ZERO_STRUCT(handle
);
4582 status
= rpc_pipe_open_interface(conn
,
4585 conn
->sconn
->remote_address
,
4586 conn
->sconn
->msg_ctx
,
4588 if (!NT_STATUS_IS_OK(status
)) {
4589 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4590 nt_errstr(status
)));
4591 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4594 b
= cli
->binding_handle
;
4596 ZERO_STRUCT(devmode_ctr
);
4598 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4605 if (!NT_STATUS_IS_OK(status
)) {
4606 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4609 if (!W_ERROR_IS_OK(werr
)) {
4610 desc
.errcode
= W_ERROR_V(werr
);
4614 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4620 if (!W_ERROR_IS_OK(werr
)) {
4621 desc
.errcode
= W_ERROR_V(werr
);
4626 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4631 desc
.buflen
= mdrcnt
;
4634 * Don't return data but need to get correct length
4635 * init_package will return wrong size if buflen=0
4637 desc
.buflen
= getlen(desc
.format
);
4638 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4641 if (init_package(&desc
,1,0)) {
4642 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4643 *rdata_len
= desc
.usedlen
;
4645 desc
.errcode
= NERR_JobNotFound
;
4649 if (b
&& is_valid_policy_hnd(&handle
)) {
4650 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4654 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4658 SSVALS(*rparam
,0,desc
.errcode
);
4660 SSVAL(*rparam
,4,desc
.neededlen
);
4664 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4669 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4670 connection_struct
*conn
, uint64_t vuid
,
4671 char *param
, int tpscnt
,
4672 char *data
, int tdscnt
,
4673 int mdrcnt
,int mprcnt
,
4674 char **rdata
,char **rparam
,
4675 int *rdata_len
,int *rparam_len
)
4677 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4678 char *str2
= skip_string(param
,tpscnt
,str1
);
4679 char *p
= skip_string(param
,tpscnt
,str2
);
4683 struct pack_desc desc
;
4685 TALLOC_CTX
*mem_ctx
= talloc_tos();
4688 struct rpc_pipe_client
*cli
= NULL
;
4689 struct dcerpc_binding_handle
*b
= NULL
;
4690 struct policy_handle handle
;
4691 struct spoolss_DevmodeContainer devmode_ctr
;
4693 union spoolss_JobInfo
*info
;
4695 if (!str1
|| !str2
|| !p
) {
4699 memset((char *)&desc
,'\0',sizeof(desc
));
4701 p
= skip_string(param
,tpscnt
,p
);
4705 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4707 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4709 /* check it's a supported variant */
4710 if (strcmp(str1
,"zWrLeh") != 0) {
4715 return False
; /* defined only for uLevel 0,1,2 */
4718 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4722 ZERO_STRUCT(handle
);
4724 status
= rpc_pipe_open_interface(conn
,
4727 conn
->sconn
->remote_address
,
4728 conn
->sconn
->msg_ctx
,
4730 if (!NT_STATUS_IS_OK(status
)) {
4731 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4732 nt_errstr(status
)));
4733 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4736 b
= cli
->binding_handle
;
4738 ZERO_STRUCT(devmode_ctr
);
4740 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4747 if (!NT_STATUS_IS_OK(status
)) {
4748 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4751 if (!W_ERROR_IS_OK(werr
)) {
4752 desc
.errcode
= W_ERROR_V(werr
);
4756 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4764 if (!W_ERROR_IS_OK(werr
)) {
4765 desc
.errcode
= W_ERROR_V(werr
);
4770 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4776 desc
.buflen
= mdrcnt
;
4778 if (init_package(&desc
,count
,0)) {
4780 for (i
= 0; i
< count
; i
++) {
4781 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4782 if (desc
.errcode
== NERR_Success
) {
4788 if (b
&& is_valid_policy_hnd(&handle
)) {
4789 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4792 *rdata_len
= desc
.usedlen
;
4795 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4799 SSVALS(*rparam
,0,desc
.errcode
);
4801 SSVAL(*rparam
,4,succnt
);
4802 SSVAL(*rparam
,6,count
);
4804 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4809 static int check_printdest_info(struct pack_desc
* desc
,
4810 int uLevel
, char* id
)
4812 desc
->subformat
= NULL
;
4815 desc
->format
= "B9";
4818 desc
->format
= "B9B21WWzW";
4824 desc
->format
= "zzzWWzzzWW";
4827 DEBUG(0,("check_printdest_info: invalid level %d\n",
4831 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4832 DEBUG(0,("check_printdest_info: invalid string %s\n",
4833 id
? id
: "<NULL>" ));
4839 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4840 struct pack_desc
* desc
)
4844 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4845 buf
[sizeof(buf
)-1] = 0;
4846 (void)strupper_m(buf
);
4849 PACKS(desc
,"B9",buf
); /* szName */
4851 PACKS(desc
,"B21",""); /* szUserName */
4852 PACKI(desc
,"W",0); /* uJobId */
4853 PACKI(desc
,"W",0); /* fsStatus */
4854 PACKS(desc
,"z",""); /* pszStatus */
4855 PACKI(desc
,"W",0); /* time */
4859 if (uLevel
== 2 || uLevel
== 3) {
4860 PACKS(desc
,"z",buf
); /* pszPrinterName */
4862 PACKS(desc
,"z",""); /* pszUserName */
4863 PACKS(desc
,"z",""); /* pszLogAddr */
4864 PACKI(desc
,"W",0); /* uJobId */
4865 PACKI(desc
,"W",0); /* fsStatus */
4866 PACKS(desc
,"z",""); /* pszStatus */
4867 PACKS(desc
,"z",""); /* pszComment */
4868 PACKS(desc
,"z","NULL"); /* pszDrivers */
4869 PACKI(desc
,"W",0); /* time */
4870 PACKI(desc
,"W",0); /* pad1 */
4875 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4876 connection_struct
*conn
, uint64_t vuid
,
4877 char *param
, int tpscnt
,
4878 char *data
, int tdscnt
,
4879 int mdrcnt
,int mprcnt
,
4880 char **rdata
,char **rparam
,
4881 int *rdata_len
,int *rparam_len
)
4883 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4884 char *str2
= skip_string(param
,tpscnt
,str1
);
4885 char *p
= skip_string(param
,tpscnt
,str2
);
4886 char* PrinterName
= p
;
4888 struct pack_desc desc
;
4891 TALLOC_CTX
*mem_ctx
= talloc_tos();
4894 struct rpc_pipe_client
*cli
= NULL
;
4895 struct dcerpc_binding_handle
*b
= NULL
;
4896 struct policy_handle handle
;
4897 struct spoolss_DevmodeContainer devmode_ctr
;
4898 union spoolss_PrinterInfo info
;
4900 if (!str1
|| !str2
|| !p
) {
4904 memset((char *)&desc
,'\0',sizeof(desc
));
4906 p
= skip_string(param
,tpscnt
,p
);
4910 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4912 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4914 /* check it's a supported varient */
4915 if (strcmp(str1
,"zWrLh") != 0) {
4918 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4922 ZERO_STRUCT(handle
);
4924 status
= rpc_pipe_open_interface(conn
,
4927 conn
->sconn
->remote_address
,
4928 conn
->sconn
->msg_ctx
,
4930 if (!NT_STATUS_IS_OK(status
)) {
4931 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4932 nt_errstr(status
)));
4933 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4936 b
= cli
->binding_handle
;
4938 ZERO_STRUCT(devmode_ctr
);
4940 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4947 if (!NT_STATUS_IS_OK(status
)) {
4949 desc
.errcode
= NERR_DestNotFound
;
4953 if (!W_ERROR_IS_OK(werr
)) {
4955 desc
.errcode
= NERR_DestNotFound
;
4960 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4965 if (!W_ERROR_IS_OK(werr
)) {
4967 desc
.errcode
= NERR_DestNotFound
;
4973 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4978 desc
.buflen
= mdrcnt
;
4981 * Don't return data but need to get correct length
4982 * init_package will return wrong size if buflen=0
4984 desc
.buflen
= getlen(desc
.format
);
4985 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4987 if (init_package(&desc
,1,0)) {
4988 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
4992 if (b
&& is_valid_policy_hnd(&handle
)) {
4993 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4996 *rdata_len
= desc
.usedlen
;
4999 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5003 SSVALS(*rparam
,0,desc
.errcode
);
5005 SSVAL(*rparam
,4,desc
.neededlen
);
5007 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5013 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5014 connection_struct
*conn
, uint64_t vuid
,
5015 char *param
, int tpscnt
,
5016 char *data
, int tdscnt
,
5017 int mdrcnt
,int mprcnt
,
5018 char **rdata
,char **rparam
,
5019 int *rdata_len
,int *rparam_len
)
5021 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5022 char *str2
= skip_string(param
,tpscnt
,str1
);
5023 char *p
= skip_string(param
,tpscnt
,str2
);
5027 struct pack_desc desc
;
5029 TALLOC_CTX
*mem_ctx
= talloc_tos();
5032 struct rpc_pipe_client
*cli
= NULL
;
5033 union spoolss_PrinterInfo
*info
;
5036 if (!str1
|| !str2
|| !p
) {
5040 memset((char *)&desc
,'\0',sizeof(desc
));
5042 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5044 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5046 /* check it's a supported varient */
5047 if (strcmp(str1
,"WrLeh") != 0) {
5050 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5056 status
= rpc_pipe_open_interface(conn
,
5059 conn
->sconn
->remote_address
,
5060 conn
->sconn
->msg_ctx
,
5062 if (!NT_STATUS_IS_OK(status
)) {
5063 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5064 nt_errstr(status
)));
5065 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5069 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5071 cli
->srv_name_slash
,
5076 if (!W_ERROR_IS_OK(werr
)) {
5077 desc
.errcode
= W_ERROR_V(werr
);
5079 desc
.errcode
= NERR_DestNotFound
;
5087 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5094 desc
.buflen
= mdrcnt
;
5095 if (init_package(&desc
,queuecnt
,0)) {
5098 for (i
= 0; i
< count
; i
++) {
5099 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5101 if (desc
.errcode
== NERR_Success
) {
5107 *rdata_len
= desc
.usedlen
;
5110 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5114 SSVALS(*rparam
,0,desc
.errcode
);
5116 SSVAL(*rparam
,4,succnt
);
5117 SSVAL(*rparam
,6,queuecnt
);
5119 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5124 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5125 connection_struct
*conn
, uint64_t vuid
,
5126 char *param
, int tpscnt
,
5127 char *data
, int tdscnt
,
5128 int mdrcnt
,int mprcnt
,
5129 char **rdata
,char **rparam
,
5130 int *rdata_len
,int *rparam_len
)
5132 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5133 char *str2
= skip_string(param
,tpscnt
,str1
);
5134 char *p
= skip_string(param
,tpscnt
,str2
);
5137 struct pack_desc desc
;
5139 if (!str1
|| !str2
|| !p
) {
5143 memset((char *)&desc
,'\0',sizeof(desc
));
5145 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5147 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5149 /* check it's a supported varient */
5150 if (strcmp(str1
,"WrLeh") != 0) {
5153 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5158 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5164 desc
.buflen
= mdrcnt
;
5165 if (init_package(&desc
,1,0)) {
5166 PACKS(&desc
,"B41","NULL");
5169 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5171 *rdata_len
= desc
.usedlen
;
5174 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5178 SSVALS(*rparam
,0,desc
.errcode
);
5180 SSVAL(*rparam
,4,succnt
);
5183 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5188 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5189 connection_struct
*conn
, uint64_t vuid
,
5190 char *param
, int tpscnt
,
5191 char *data
, int tdscnt
,
5192 int mdrcnt
,int mprcnt
,
5193 char **rdata
,char **rparam
,
5194 int *rdata_len
,int *rparam_len
)
5196 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5197 char *str2
= skip_string(param
,tpscnt
,str1
);
5198 char *p
= skip_string(param
,tpscnt
,str2
);
5201 struct pack_desc desc
;
5203 if (!str1
|| !str2
|| !p
) {
5206 memset((char *)&desc
,'\0',sizeof(desc
));
5208 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5210 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5212 /* check it's a supported varient */
5213 if (strcmp(str1
,"WrLeh") != 0) {
5216 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5221 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5227 desc
.buflen
= mdrcnt
;
5229 if (init_package(&desc
,1,0)) {
5230 PACKS(&desc
,"B13","lpd");
5233 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5235 *rdata_len
= desc
.usedlen
;
5238 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5242 SSVALS(*rparam
,0,desc
.errcode
);
5244 SSVAL(*rparam
,4,succnt
);
5247 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5252 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5253 connection_struct
*conn
, uint64_t vuid
,
5254 char *param
, int tpscnt
,
5255 char *data
, int tdscnt
,
5256 int mdrcnt
,int mprcnt
,
5257 char **rdata
,char **rparam
,
5258 int *rdata_len
,int *rparam_len
)
5260 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5261 char *str2
= skip_string(param
,tpscnt
,str1
);
5262 char *p
= skip_string(param
,tpscnt
,str2
);
5265 struct pack_desc desc
;
5267 if (!str1
|| !str2
|| !p
) {
5271 memset((char *)&desc
,'\0',sizeof(desc
));
5273 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5275 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5277 /* check it's a supported varient */
5278 if (strcmp(str1
,"WrLeh") != 0) {
5281 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5286 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5291 memset((char *)&desc
,'\0',sizeof(desc
));
5293 desc
.buflen
= mdrcnt
;
5295 if (init_package(&desc
,1,0)) {
5296 PACKS(&desc
,"B13","lp0");
5299 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5301 *rdata_len
= desc
.usedlen
;
5304 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5308 SSVALS(*rparam
,0,desc
.errcode
);
5310 SSVAL(*rparam
,4,succnt
);
5313 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5318 /****************************************************************************
5320 ****************************************************************************/
5322 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5323 connection_struct
*conn
, uint64_t vuid
,
5324 char *param
, int tpscnt
,
5325 char *data
, int tdscnt
,
5326 int mdrcnt
,int mprcnt
,
5327 char **rdata
,char **rparam
,
5328 int *rdata_len
,int *rparam_len
)
5331 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5332 char *str2
= skip_string(param
,tpscnt
,str1
);
5333 char *p
= skip_string(param
,tpscnt
,str2
);
5335 struct pack_desc desc
;
5338 TALLOC_CTX
*mem_ctx
= talloc_tos();
5341 struct rpc_pipe_client
*cli
= NULL
;
5342 struct dcerpc_binding_handle
*b
= NULL
;
5343 struct srvsvc_NetSessInfoCtr info_ctr
;
5344 uint32_t totalentries
, resume_handle
= 0;
5347 if (!str1
|| !str2
|| !p
) {
5353 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5355 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5356 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5357 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5359 /* check it's a supported varient */
5360 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5363 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5367 status
= rpc_pipe_open_interface(conn
,
5370 conn
->sconn
->remote_address
,
5371 conn
->sconn
->msg_ctx
,
5373 if (!NT_STATUS_IS_OK(status
)) {
5374 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5375 nt_errstr(status
)));
5376 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5379 b
= cli
->binding_handle
;
5382 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5383 if (info_ctr
.ctr
.ctr1
== NULL
) {
5384 desc
.errcode
= W_ERROR_V(WERR_NOMEM
);
5388 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5389 cli
->srv_name_slash
,
5393 (uint32_t)-1, /* max_buffer */
5397 if (!NT_STATUS_IS_OK(status
)) {
5398 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5399 nt_errstr(status
)));
5400 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5404 if (!W_ERROR_IS_OK(werr
)) {
5405 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5407 desc
.errcode
= W_ERROR_V(werr
);
5411 count
= info_ctr
.ctr
.ctr1
->count
;
5415 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5422 desc
.buflen
= mdrcnt
;
5424 if (!init_package(&desc
, count
,0)) {
5428 for(i
=0; i
< count
; i
++) {
5429 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5430 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5431 PACKI(&desc
, "W", 1); /* num conns */
5432 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5433 PACKI(&desc
, "W", 1); /* num users */
5434 PACKI(&desc
, "D", 0); /* session time */
5435 PACKI(&desc
, "D", 0); /* idle time */
5436 PACKI(&desc
, "D", 0); /* flags */
5437 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5440 *rdata_len
= desc
.usedlen
;
5443 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5447 SSVALS(*rparam
,0,desc
.errcode
);
5448 SSVAL(*rparam
,2,0); /* converter */
5449 SSVAL(*rparam
,4, count
); /* count */
5451 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5457 /****************************************************************************
5458 The buffer was too small.
5459 ****************************************************************************/
5461 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5462 connection_struct
*conn
,uint64_t vuid
, char *param
, char *data
,
5463 int mdrcnt
, int mprcnt
,
5464 char **rdata
, char **rparam
,
5465 int *rdata_len
, int *rparam_len
)
5467 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5468 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5475 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5477 DEBUG(3,("Supplied buffer too small in API command\n"));
5482 /****************************************************************************
5483 The request is not supported.
5484 ****************************************************************************/
5486 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5487 connection_struct
*conn
, uint64_t vuid
,
5488 char *param
, int tpscnt
,
5489 char *data
, int tdscnt
,
5490 int mdrcnt
, int mprcnt
,
5491 char **rdata
, char **rparam
,
5492 int *rdata_len
, int *rparam_len
)
5495 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5502 SSVAL(*rparam
,0,NERR_notsupported
);
5503 SSVAL(*rparam
,2,0); /* converter word */
5505 DEBUG(3,("Unsupported API command\n"));
5510 static const struct {
5513 bool (*fn
)(struct smbd_server_connection
*sconn
,
5514 connection_struct
*, uint64_t,
5517 int,int,char **,char **,int *,int *);
5518 bool auth_user
; /* Deny anonymous access? */
5519 } api_commands
[] = {
5520 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5521 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5522 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5523 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5524 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5525 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5526 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5527 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5528 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5529 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5530 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5531 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5532 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5533 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5534 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5535 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5536 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5537 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5538 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5539 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5540 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5541 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5542 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5543 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5544 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5545 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5546 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5547 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5548 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5549 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5550 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5551 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5552 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5553 {NULL
, -1, api_Unsupported
}
5554 /* The following RAP calls are not implemented by Samba:
5556 RAP_WFileEnum2 - anon not OK
5561 /****************************************************************************
5562 Handle remote api calls.
5563 ****************************************************************************/
5565 void api_reply(connection_struct
*conn
, uint64_t vuid
,
5566 struct smb_request
*req
,
5567 char *data
, char *params
,
5568 int tdscnt
, int tpscnt
,
5569 int mdrcnt
, int mprcnt
)
5573 char *rparam
= NULL
;
5574 const char *name1
= NULL
;
5575 const char *name2
= NULL
;
5582 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5583 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5588 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5591 api_command
= SVAL(params
,0);
5592 /* Is there a string at position params+2 ? */
5593 if (skip_string(params
,tpscnt
,params
+2)) {
5598 name2
= skip_string(params
,tpscnt
,params
+2);
5603 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5607 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5609 for (i
=0;api_commands
[i
].name
;i
++) {
5610 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5611 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5616 /* Check whether this api call can be done anonymously */
5618 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5619 struct user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5621 if (!user
|| security_session_user_level(user
->session_info
, NULL
) < SECURITY_USER
) {
5622 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5627 rdata
= (char *)SMB_MALLOC(1024);
5629 memset(rdata
,'\0',1024);
5632 rparam
= (char *)SMB_MALLOC(1024);
5634 memset(rparam
,'\0',1024);
5637 if(!rdata
|| !rparam
) {
5638 DEBUG(0,("api_reply: malloc fail !\n"));
5641 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5645 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5647 params
,tpscnt
, /* params + length */
5648 data
,tdscnt
, /* data + length */
5650 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5653 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5654 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5656 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5659 /* if we get False back then it's actually unsupported */
5661 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5663 tdscnt
,mdrcnt
,mprcnt
,
5664 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5667 /* If api_Unsupported returns false we can't return anything. */
5669 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5670 rdata
, rdata_len
, False
);