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_t servertype
,
1221 struct srv_info_struct
**servers
,
1227 bool local_list_only
;
1229 char *slist_cache_path
= cache_path(SERVER_LIST
);
1230 if (slist_cache_path
== NULL
) {
1234 lines
= file_lines_load(slist_cache_path
, NULL
, 0, NULL
);
1236 DEBUG(4, ("Can't open %s - %s\n",
1237 slist_cache_path
, strerror(errno
)));
1238 TALLOC_FREE(slist_cache_path
);
1241 TALLOC_FREE(slist_cache_path
);
1243 /* request for everything is code for request all servers */
1244 if (servertype
== SV_TYPE_ALL
) {
1245 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1248 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1250 DEBUG(4,("Servertype search: %8x\n",servertype
));
1252 for (i
=0;lines
[i
];i
++) {
1254 struct srv_info_struct
*s
;
1255 const char *ptr
= lines
[i
];
1257 TALLOC_CTX
*frame
= NULL
;
1264 if (count
== alloced
) {
1266 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1268 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1272 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1274 s
= &(*servers
)[count
];
1276 frame
= talloc_stackframe();
1278 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1282 fstrcpy(s
->name
, p
);
1285 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1291 s
->comment
[0] = '\0';
1292 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1296 fstrcpy(s
->comment
, p
);
1297 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1299 s
->domain
[0] = '\0';
1300 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1301 /* this allows us to cope with an old nmbd */
1302 fstrcpy(s
->domain
,lp_workgroup());
1304 fstrcpy(s
->domain
, p
);
1308 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1309 DEBUG(4,("r:host file "));
1313 /* Filter the servers/domains we return based on what was asked for. */
1315 /* Check to see if we are being asked for a local list only. */
1316 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1317 DEBUG(4,("r: local list only"));
1321 /* doesn't match up: don't want it */
1322 if (!(servertype
& s
->type
)) {
1323 DEBUG(4,("r:serv type "));
1327 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1328 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1329 DEBUG(4,("s: dom mismatch "));
1333 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1337 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1338 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1341 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1342 s
->name
, s
->type
, s
->comment
, s
->domain
));
1343 s
->server_added
= True
;
1346 DEBUG(4,("%20s %8x %25s %15s\n",
1347 s
->name
, s
->type
, s
->comment
, s
->domain
));
1355 /*******************************************************************
1356 Fill in a server info structure.
1357 ******************************************************************/
1359 static int fill_srv_info(struct srv_info_struct
*service
,
1360 int uLevel
, char **buf
, int *buflen
,
1361 char **stringbuf
, int *stringspace
, char *baseaddr
)
1384 len
= strlen(service
->comment
)+1;
1388 *buflen
= struct_len
;
1390 return struct_len
+ len
;
1395 if (*buflen
< struct_len
) {
1402 p2
= p
+ struct_len
;
1403 l2
= *buflen
- struct_len
;
1411 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1415 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1416 SIVAL(p
,18,service
->type
);
1417 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1418 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1423 *buf
= p
+ struct_len
;
1424 *buflen
-= struct_len
;
1435 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1437 return strcasecmp_m(s1
->name
,s2
->name
);
1440 /****************************************************************************
1441 View list of servers available (or possibly domains). The info is
1442 extracted from lists saved by nmbd on the local host.
1443 ****************************************************************************/
1445 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1446 connection_struct
*conn
, uint64_t vuid
,
1447 char *param
, int tpscnt
,
1448 char *data
, int tdscnt
,
1449 int mdrcnt
, int mprcnt
, char **rdata
,
1450 char **rparam
, int *rdata_len
, int *rparam_len
)
1452 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1453 char *str2
= skip_string(param
,tpscnt
,str1
);
1454 char *p
= skip_string(param
,tpscnt
,str2
);
1455 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1456 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1457 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1459 int data_len
, fixed_len
, string_len
;
1460 int f_len
= 0, s_len
= 0;
1461 struct srv_info_struct
*servers
=NULL
;
1462 int counted
=0,total
=0;
1465 bool domain_request
;
1468 if (!str1
|| !str2
|| !p
) {
1472 /* If someone sets all the bits they don't really mean to set
1473 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1476 if (servertype
== SV_TYPE_ALL
) {
1477 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1480 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1481 any other bit (they may just set this bit on its own) they
1482 want all the locally seen servers. However this bit can be
1483 set on its own so set the requested servers to be
1484 ALL - DOMAIN_ENUM. */
1486 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1487 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1490 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1491 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1495 if (!prefix_ok(str1
,"WrLehD")) {
1498 if (!check_session_info(uLevel
,str2
)) {
1502 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1503 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1504 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1506 if (strcmp(str1
, "WrLehDz") == 0) {
1507 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1510 pull_ascii_fstring(domain
, p
);
1512 fstrcpy(domain
, lp_workgroup());
1515 DEBUG(4, ("domain [%s]\n", domain
));
1517 if (lp_browse_list()) {
1518 total
= get_session_info(servertype
,&servers
,domain
);
1521 data_len
= fixed_len
= string_len
= 0;
1524 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1527 char *lastname
=NULL
;
1529 for (i
=0;i
<total
;i
++) {
1530 struct srv_info_struct
*s
= &servers
[i
];
1532 if (lastname
&& strequal(lastname
,s
->name
)) {
1536 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1537 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1538 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1540 if (data_len
< buf_len
) {
1543 string_len
+= s_len
;
1550 *rdata_len
= fixed_len
+ string_len
;
1551 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1556 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1562 char *lastname
=NULL
;
1563 int count2
= counted
;
1565 for (i
= 0; i
< total
&& count2
;i
++) {
1566 struct srv_info_struct
*s
= &servers
[i
];
1568 if (lastname
&& strequal(lastname
,s
->name
)) {
1572 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1573 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1574 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1580 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1584 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1586 SSVAL(*rparam
,4,counted
);
1587 SSVAL(*rparam
,6,counted
+missed
);
1591 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1592 domain
,uLevel
,counted
,counted
+missed
));
1597 static int srv_name_match(const char *n1
, const char *n2
)
1600 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1602 * In Windows, FirstNameToReturn need not be an exact match:
1603 * the server will return a list of servers that exist on
1604 * the network greater than or equal to the FirstNameToReturn.
1606 int ret
= strcasecmp_m(n1
, n2
);
1615 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1616 connection_struct
*conn
, uint64_t vuid
,
1617 char *param
, int tpscnt
,
1618 char *data
, int tdscnt
,
1619 int mdrcnt
, int mprcnt
, char **rdata
,
1620 char **rparam
, int *rdata_len
, int *rparam_len
)
1622 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1623 char *str2
= skip_string(param
,tpscnt
,str1
);
1624 char *p
= skip_string(param
,tpscnt
,str2
);
1625 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1626 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1627 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1629 int data_len
, fixed_len
, string_len
;
1630 int f_len
= 0, s_len
= 0;
1631 struct srv_info_struct
*servers
=NULL
;
1632 int counted
=0,first
=0,total
=0;
1636 bool domain_request
;
1639 if (!str1
|| !str2
|| !p
) {
1643 /* If someone sets all the bits they don't really mean to set
1644 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1647 if (servertype
== SV_TYPE_ALL
) {
1648 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1651 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1652 any other bit (they may just set this bit on its own) they
1653 want all the locally seen servers. However this bit can be
1654 set on its own so set the requested servers to be
1655 ALL - DOMAIN_ENUM. */
1657 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1658 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1661 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1662 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1666 if (strcmp(str1
, "WrLehDzz") != 0) {
1669 if (!check_session_info(uLevel
,str2
)) {
1673 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1674 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1675 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1677 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1680 pull_ascii_fstring(domain
, p
);
1681 if (domain
[0] == '\0') {
1682 fstrcpy(domain
, lp_workgroup());
1684 p
= skip_string(param
,tpscnt
,p
);
1685 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1688 pull_ascii_fstring(first_name
, p
);
1690 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1691 domain
, first_name
));
1693 if (lp_browse_list()) {
1694 total
= get_session_info(servertype
,&servers
,domain
);
1697 data_len
= fixed_len
= string_len
= 0;
1700 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1702 if (first_name
[0] != '\0') {
1703 struct srv_info_struct
*first_server
= NULL
;
1705 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1706 srv_name_match
, first_server
);
1708 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1710 * The binary search may not find the exact match
1711 * so we need to search backward to find the first match
1713 * This implements the strange matching windows
1714 * implements. (see the comment in srv_name_match().
1718 ret
= strcasecmp_m(first_name
,
1719 servers
[first
-1].name
);
1726 /* we should return no entries */
1732 char *lastname
=NULL
;
1734 for (i
=first
;i
<total
;i
++) {
1735 struct srv_info_struct
*s
= &servers
[i
];
1737 if (lastname
&& strequal(lastname
,s
->name
)) {
1741 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1742 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1743 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1745 if (data_len
< buf_len
) {
1748 string_len
+= s_len
;
1755 *rdata_len
= fixed_len
+ string_len
;
1756 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1761 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1767 char *lastname
=NULL
;
1768 int count2
= counted
;
1770 for (i
= first
; i
< total
&& count2
;i
++) {
1771 struct srv_info_struct
*s
= &servers
[i
];
1773 if (lastname
&& strequal(lastname
,s
->name
)) {
1777 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1778 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1779 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1785 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1789 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1791 SSVAL(*rparam
,4,counted
);
1792 SSVAL(*rparam
,6,counted
+missed
);
1794 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1795 domain
,uLevel
,first
,first_name
,
1796 first
< total
? servers
[first
].name
: "",
1797 counted
,counted
+missed
));
1804 /****************************************************************************
1805 command 0x34 - suspected of being a "Lookup Names" stub api
1806 ****************************************************************************/
1808 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1809 connection_struct
*conn
, uint64_t vuid
,
1810 char *param
, int tpscnt
,
1811 char *data
, int tdscnt
,
1812 int mdrcnt
, int mprcnt
, char **rdata
,
1813 char **rparam
, int *rdata_len
, int *rparam_len
)
1815 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1816 char *str2
= skip_string(param
,tpscnt
,str1
);
1817 char *p
= skip_string(param
,tpscnt
,str2
);
1818 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1819 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1823 if (!str1
|| !str2
|| !p
) {
1827 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1828 str1
, str2
, p
, uLevel
, buf_len
));
1830 if (!prefix_ok(str1
,"zWrLeh")) {
1837 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1842 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1844 SSVAL(*rparam
,4,counted
);
1845 SSVAL(*rparam
,6,counted
+missed
);
1850 /****************************************************************************
1851 get info about a share
1852 ****************************************************************************/
1854 static bool check_share_info(int uLevel
, char* id
)
1858 if (strcmp(id
,"B13") != 0) {
1863 /* Level-2 descriptor is allowed (and ignored) */
1864 if (strcmp(id
,"B13BWz") != 0 &&
1865 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1870 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1875 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1885 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1886 char** buf
, int* buflen
,
1887 char** stringbuf
, int* stringspace
, char* baseaddr
)
1916 len
+= StrlenExpanded(conn
,snum
,lp_comment(talloc_tos(), snum
));
1919 len
+= strlen(lp_path(talloc_tos(), snum
)) + 1;
1922 *buflen
= struct_len
;
1927 return struct_len
+ len
;
1932 if ((*buflen
) < struct_len
) {
1940 p2
= p
+ struct_len
;
1941 l2
= (*buflen
) - struct_len
;
1948 push_ascii(p
,lp_servicename(talloc_tos(), snum
),13, STR_TERMINATE
);
1954 type
= STYPE_DISKTREE
;
1955 if (lp_printable(snum
)) {
1956 type
= STYPE_PRINTQ
;
1958 if (strequal("IPC",lp_fstype(snum
))) {
1961 SSVAL(p
,14,type
); /* device type */
1962 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1963 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(talloc_tos(),snum
),&l2
);
1967 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1968 SSVALS(p
,22,-1); /* max uses */
1969 SSVAL(p
,24,1); /* current uses */
1970 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1971 len
+= CopyAndAdvance(&p2
,lp_path(talloc_tos(),snum
),&l2
);
1972 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1976 memset(p
+40,0,SHPWLEN
+2);
1987 (*buf
) = p
+ struct_len
;
1988 (*buflen
) -= struct_len
;
1990 (*stringspace
) = l2
;
1999 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
2000 connection_struct
*conn
,uint64_t vuid
,
2001 char *param
, int tpscnt
,
2002 char *data
, int tdscnt
,
2003 int mdrcnt
,int mprcnt
,
2004 char **rdata
,char **rparam
,
2005 int *rdata_len
,int *rparam_len
)
2007 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2008 char *str2
= skip_string(param
,tpscnt
,str1
);
2009 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2010 char *netname
= NULL
;
2011 char *p
= skip_string(param
,tpscnt
,netname
);
2012 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2015 if (!str1
|| !str2
|| !netname_in
|| !p
) {
2019 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2020 if (snum
< 0 || !netname
) {
2024 /* check it's a supported varient */
2025 if (!prefix_ok(str1
,"zWrLh")) {
2028 if (!check_share_info(uLevel
,str2
)) {
2032 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2037 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2038 if (*rdata_len
< 0) {
2043 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2047 SSVAL(*rparam
,0,NERR_Success
);
2048 SSVAL(*rparam
,2,0); /* converter word */
2049 SSVAL(*rparam
,4,*rdata_len
);
2054 /****************************************************************************
2055 View the list of available shares.
2057 This function is the server side of the NetShareEnum() RAP call.
2058 It fills the return buffer with share names and share comments.
2059 Note that the return buffer normally (in all known cases) allows only
2060 twelve byte strings for share names (plus one for a nul terminator).
2061 Share names longer than 12 bytes must be skipped.
2062 ****************************************************************************/
2064 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2065 connection_struct
*conn
, uint64_t vuid
,
2066 char *param
, int tpscnt
,
2067 char *data
, int tdscnt
,
2075 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2076 char *str2
= skip_string(param
,tpscnt
,str1
);
2077 char *p
= skip_string(param
,tpscnt
,str2
);
2078 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2079 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2082 int total
=0,counted
=0;
2083 bool missed
= False
;
2085 int data_len
, fixed_len
, string_len
;
2086 int f_len
= 0, s_len
= 0;
2088 if (!str1
|| !str2
|| !p
) {
2092 if (!prefix_ok(str1
,"WrLeh")) {
2095 if (!check_share_info(uLevel
,str2
)) {
2099 /* Ensure all the usershares are loaded. */
2101 delete_and_reload_printers(sconn
->ev_ctx
, sconn
->msg_ctx
);
2102 load_registry_shares();
2103 count
= load_usershare_shares(NULL
, connections_snum_used
);
2106 data_len
= fixed_len
= string_len
= 0;
2107 for (i
=0;i
<count
;i
++) {
2108 fstring servicename_dos
;
2109 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2112 push_ascii_fstring(servicename_dos
, lp_servicename(talloc_tos(), i
));
2113 /* Maximum name length = 13. */
2114 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2116 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2117 if (data_len
< buf_len
) {
2120 string_len
+= s_len
;
2127 *rdata_len
= fixed_len
+ string_len
;
2128 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2133 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2138 for( i
= 0; i
< count
; i
++ ) {
2139 fstring servicename_dos
;
2140 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2144 push_ascii_fstring(servicename_dos
,
2145 lp_servicename(talloc_tos(), i
));
2146 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2147 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2154 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2158 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2160 SSVAL(*rparam
,4,counted
);
2161 SSVAL(*rparam
,6,total
);
2163 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2164 counted
,total
,uLevel
,
2165 buf_len
,*rdata_len
,mdrcnt
));
2170 /****************************************************************************
2172 ****************************************************************************/
2174 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2175 connection_struct
*conn
,uint64_t vuid
,
2176 char *param
, int tpscnt
,
2177 char *data
, int tdscnt
,
2178 int mdrcnt
,int mprcnt
,
2179 char **rdata
,char **rparam
,
2180 int *rdata_len
,int *rparam_len
)
2182 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2183 char *str2
= skip_string(param
,tpscnt
,str1
);
2184 char *p
= skip_string(param
,tpscnt
,str2
);
2185 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2188 char *pathname
= NULL
;
2189 unsigned int offset
;
2191 size_t converted_size
;
2193 WERROR werr
= WERR_OK
;
2194 TALLOC_CTX
*mem_ctx
= talloc_tos();
2196 struct rpc_pipe_client
*cli
= NULL
;
2197 union srvsvc_NetShareInfo info
;
2198 struct srvsvc_NetShareInfo2 info2
;
2199 struct dcerpc_binding_handle
*b
;
2201 if (!str1
|| !str2
|| !p
) {
2205 /* check it's a supported varient */
2206 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2209 if (!check_share_info(uLevel
,str2
)) {
2216 /* Do we have a string ? */
2217 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2220 pull_ascii_fstring(sharename
,data
);
2226 /* only support disk share adds */
2227 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2231 offset
= IVAL(data
, 16);
2232 if (offset
>= mdrcnt
) {
2233 res
= ERRinvalidparam
;
2237 /* Do we have a string ? */
2238 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2241 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2243 offset
= IVAL(data
, 26);
2245 if (offset
>= mdrcnt
) {
2246 res
= ERRinvalidparam
;
2250 /* Do we have a string ? */
2251 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2255 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2256 offset
? (data
+offset
) : "", &converted_size
))
2258 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2266 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
2268 conn
->sconn
->remote_address
,
2269 conn
->sconn
->msg_ctx
,
2271 if (!NT_STATUS_IS_OK(status
)) {
2272 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2273 nt_errstr(status
)));
2274 res
= W_ERROR_V(ntstatus_to_werror(status
));
2278 b
= cli
->binding_handle
;
2280 info2
.name
= sharename
;
2281 info2
.type
= STYPE_DISKTREE
;
2282 info2
.comment
= comment
;
2283 info2
.permissions
= 0;
2284 info2
.max_users
= 0;
2285 info2
.current_users
= 0;
2286 info2
.path
= pathname
;
2287 info2
.password
= NULL
;
2289 info
.info2
= &info2
;
2291 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2292 cli
->srv_name_slash
,
2297 if (!NT_STATUS_IS_OK(status
)) {
2298 res
= W_ERROR_V(ntstatus_to_werror(status
));
2301 if (!W_ERROR_IS_OK(werr
)) {
2302 res
= W_ERROR_V(werr
);
2307 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2311 SSVAL(*rparam
,0,NERR_Success
);
2312 SSVAL(*rparam
,2,0); /* converter word */
2313 SSVAL(*rparam
,4,*rdata_len
);
2321 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2326 SSVAL(*rparam
,0,res
);
2331 /****************************************************************************
2332 view list of groups available
2333 ****************************************************************************/
2335 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2336 connection_struct
*conn
,uint64_t vuid
,
2337 char *param
, int tpscnt
,
2338 char *data
, int tdscnt
,
2339 int mdrcnt
,int mprcnt
,
2340 char **rdata
,char **rparam
,
2341 int *rdata_len
,int *rparam_len
)
2345 int resume_context
, cli_buf_size
;
2346 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2347 char *str2
= skip_string(param
,tpscnt
,str1
);
2348 char *p
= skip_string(param
,tpscnt
,str2
);
2350 uint32_t num_groups
;
2351 uint32_t resume_handle
;
2352 struct rpc_pipe_client
*samr_pipe
= NULL
;
2353 struct policy_handle samr_handle
, domain_handle
;
2354 NTSTATUS status
, result
;
2355 struct dcerpc_binding_handle
*b
;
2357 if (!str1
|| !str2
|| !p
) {
2361 if (strcmp(str1
,"WrLeh") != 0) {
2366 * W-> resume context (number of users to skip)
2367 * r -> return parameter pointer to receive buffer
2368 * L -> length of receive buffer
2369 * e -> return parameter number of entries
2370 * h -> return parameter total number of users
2373 if (strcmp("B21",str2
) != 0) {
2377 status
= rpc_pipe_open_interface(
2378 talloc_tos(), &ndr_table_samr
,
2379 conn
->session_info
, conn
->sconn
->remote_address
,
2380 conn
->sconn
->msg_ctx
, &samr_pipe
);
2381 if (!NT_STATUS_IS_OK(status
)) {
2382 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2383 nt_errstr(status
)));
2387 b
= samr_pipe
->binding_handle
;
2389 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2390 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2392 if (!NT_STATUS_IS_OK(status
)) {
2393 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2394 nt_errstr(status
)));
2397 if (!NT_STATUS_IS_OK(result
)) {
2398 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2399 nt_errstr(result
)));
2403 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2404 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2405 get_global_sam_sid(), &domain_handle
,
2407 if (!NT_STATUS_IS_OK(status
)) {
2408 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2409 nt_errstr(status
)));
2410 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2413 if (!NT_STATUS_IS_OK(result
)) {
2414 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2415 nt_errstr(result
)));
2416 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2420 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2421 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2422 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2423 "%d\n", resume_context
, cli_buf_size
));
2425 *rdata_len
= cli_buf_size
;
2426 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2433 errflags
= NERR_Success
;
2438 struct samr_SamArray
*sam_entries
;
2439 uint32_t num_entries
;
2441 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2447 if (!NT_STATUS_IS_OK(status
)) {
2448 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2449 "%s\n", nt_errstr(status
)));
2452 if (!NT_STATUS_IS_OK(result
)) {
2454 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2455 "%s\n", nt_errstr(result
)));
2459 if (num_entries
== 0) {
2460 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2461 "no entries -- done\n"));
2465 for(i
=0; i
<num_entries
; i
++) {
2468 name
= sam_entries
->entries
[i
].name
.string
;
2470 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2471 /* set overflow error */
2472 DEBUG(3,("overflow on entry %d group %s\n", i
,
2478 /* truncate the name at 21 chars. */
2480 strlcpy(p
, name
, 21);
2481 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2483 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2488 if (errflags
!= NERR_Success
) {
2492 TALLOC_FREE(sam_entries
);
2495 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2496 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2498 *rdata_len
= PTR_DIFF(p
,*rdata
);
2501 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2505 SSVAL(*rparam
, 0, errflags
);
2506 SSVAL(*rparam
, 2, 0); /* converter word */
2507 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2508 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2513 /*******************************************************************
2514 Get groups that a user is a member of.
2515 ******************************************************************/
2517 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2518 connection_struct
*conn
,uint64_t vuid
,
2519 char *param
, int tpscnt
,
2520 char *data
, int tdscnt
,
2521 int mdrcnt
,int mprcnt
,
2522 char **rdata
,char **rparam
,
2523 int *rdata_len
,int *rparam_len
)
2525 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2526 char *str2
= skip_string(param
,tpscnt
,str1
);
2527 char *UserName
= skip_string(param
,tpscnt
,str2
);
2528 char *p
= skip_string(param
,tpscnt
,UserName
);
2529 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2530 const char *level_string
;
2536 struct rpc_pipe_client
*samr_pipe
= NULL
;
2537 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2538 struct lsa_String name
;
2539 struct lsa_Strings names
;
2540 struct samr_Ids type
, rid
;
2541 struct samr_RidWithAttributeArray
*rids
;
2542 NTSTATUS status
, result
;
2543 struct dcerpc_binding_handle
*b
;
2545 if (!str1
|| !str2
|| !UserName
|| !p
) {
2550 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2555 /* check it's a supported varient */
2557 if ( strcmp(str1
,"zWrLeh") != 0 )
2562 level_string
= "B21";
2568 if (strcmp(level_string
,str2
) != 0)
2571 *rdata_len
= mdrcnt
+ 1024;
2572 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2577 SSVAL(*rparam
,0,NERR_Success
);
2578 SSVAL(*rparam
,2,0); /* converter word */
2581 endp
= *rdata
+ *rdata_len
;
2583 status
= rpc_pipe_open_interface(
2584 talloc_tos(), &ndr_table_samr
,
2585 conn
->session_info
, conn
->sconn
->remote_address
,
2586 conn
->sconn
->msg_ctx
, &samr_pipe
);
2587 if (!NT_STATUS_IS_OK(status
)) {
2588 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2589 nt_errstr(status
)));
2593 b
= samr_pipe
->binding_handle
;
2595 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2596 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2598 if (!NT_STATUS_IS_OK(status
)) {
2599 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2600 nt_errstr(status
)));
2603 if (!NT_STATUS_IS_OK(result
)) {
2604 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2605 nt_errstr(result
)));
2609 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2610 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2611 get_global_sam_sid(), &domain_handle
,
2613 if (!NT_STATUS_IS_OK(status
)) {
2614 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2615 nt_errstr(status
)));
2618 if (!NT_STATUS_IS_OK(result
)) {
2619 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2620 nt_errstr(result
)));
2624 name
.string
= UserName
;
2626 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2627 &domain_handle
, 1, &name
,
2630 if (!NT_STATUS_IS_OK(status
)) {
2631 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2632 nt_errstr(status
)));
2635 if (!NT_STATUS_IS_OK(result
)) {
2636 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2637 nt_errstr(result
)));
2640 if (rid
.count
!= 1) {
2641 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2644 if (type
.count
!= 1) {
2645 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2649 if (type
.ids
[0] != SID_NAME_USER
) {
2650 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2651 sid_type_lookup(type
.ids
[0])));
2655 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2657 SAMR_USER_ACCESS_GET_GROUPS
,
2658 rid
.ids
[0], &user_handle
,
2660 if (!NT_STATUS_IS_OK(status
)) {
2661 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2662 nt_errstr(status
)));
2665 if (!NT_STATUS_IS_OK(result
)) {
2666 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2667 nt_errstr(result
)));
2671 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2672 &user_handle
, &rids
,
2674 if (!NT_STATUS_IS_OK(status
)) {
2675 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2676 nt_errstr(status
)));
2679 if (!NT_STATUS_IS_OK(result
)) {
2680 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2681 nt_errstr(result
)));
2685 for (i
=0; i
<rids
->count
; i
++) {
2687 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2689 1, &rids
->rids
[i
].rid
,
2692 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2693 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2699 *rdata_len
= PTR_DIFF(p
,*rdata
);
2701 SSVAL(*rparam
,4,count
); /* is this right?? */
2702 SSVAL(*rparam
,6,count
); /* is this right?? */
2707 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2709 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2711 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2716 /*******************************************************************
2718 ******************************************************************/
2720 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2721 connection_struct
*conn
, uint64_t vuid
,
2722 char *param
, int tpscnt
,
2723 char *data
, int tdscnt
,
2724 int mdrcnt
,int mprcnt
,
2725 char **rdata
,char **rparam
,
2726 int *rdata_len
,int *rparam_len
)
2731 int i
, resume_context
, cli_buf_size
;
2732 uint32_t resume_handle
;
2734 struct rpc_pipe_client
*samr_pipe
= NULL
;
2735 struct policy_handle samr_handle
, domain_handle
;
2736 NTSTATUS status
, result
;
2738 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2739 char *str2
= skip_string(param
,tpscnt
,str1
);
2740 char *p
= skip_string(param
,tpscnt
,str2
);
2743 struct dcerpc_binding_handle
*b
;
2745 if (!str1
|| !str2
|| !p
) {
2749 if (strcmp(str1
,"WrLeh") != 0)
2752 * W-> resume context (number of users to skip)
2753 * r -> return parameter pointer to receive buffer
2754 * L -> length of receive buffer
2755 * e -> return parameter number of entries
2756 * h -> return parameter total number of users
2759 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2760 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2761 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2762 resume_context
, cli_buf_size
));
2765 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2770 /* check it's a supported varient */
2771 if (strcmp("B21",str2
) != 0)
2774 *rdata_len
= cli_buf_size
;
2775 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2781 endp
= *rdata
+ *rdata_len
;
2783 status
= rpc_pipe_open_interface(
2784 talloc_tos(), &ndr_table_samr
,
2785 conn
->session_info
, conn
->sconn
->remote_address
,
2786 conn
->sconn
->msg_ctx
, &samr_pipe
);
2787 if (!NT_STATUS_IS_OK(status
)) {
2788 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2789 nt_errstr(status
)));
2793 b
= samr_pipe
->binding_handle
;
2795 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2796 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2798 if (!NT_STATUS_IS_OK(status
)) {
2799 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2800 nt_errstr(status
)));
2803 if (!NT_STATUS_IS_OK(result
)) {
2804 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2805 nt_errstr(result
)));
2809 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2810 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2811 get_global_sam_sid(), &domain_handle
,
2813 if (!NT_STATUS_IS_OK(status
)) {
2814 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2815 nt_errstr(status
)));
2816 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2819 if (!NT_STATUS_IS_OK(result
)) {
2820 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2821 nt_errstr(result
)));
2822 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2826 errflags
=NERR_Success
;
2831 struct samr_SamArray
*sam_entries
;
2832 uint32_t num_entries
;
2834 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2841 if (!NT_STATUS_IS_OK(status
)) {
2842 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2843 "%s\n", nt_errstr(status
)));
2846 if (!NT_STATUS_IS_OK(result
)) {
2847 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2848 "%s\n", nt_errstr(result
)));
2852 if (num_entries
== 0) {
2853 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2854 "no entries -- done\n"));
2858 for (i
=0; i
<num_entries
; i
++) {
2861 name
= sam_entries
->entries
[i
].name
.string
;
2863 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2864 &&(strlen(name
)<=21)) {
2865 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2866 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2867 "username %s\n",count_sent
,p
));
2871 /* set overflow error */
2872 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2873 "username %s\n",count_sent
,name
));
2879 if (errflags
!= NERR_Success
) {
2883 TALLOC_FREE(sam_entries
);
2886 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2887 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2889 *rdata_len
= PTR_DIFF(p
,*rdata
);
2891 SSVAL(*rparam
,0,errflags
);
2892 SSVAL(*rparam
,2,0); /* converter word */
2893 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2894 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2899 /****************************************************************************
2900 Get the time of day info.
2901 ****************************************************************************/
2903 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2904 connection_struct
*conn
,uint64_t vuid
,
2905 char *param
, int tpscnt
,
2906 char *data
, int tdscnt
,
2907 int mdrcnt
,int mprcnt
,
2908 char **rdata
,char **rparam
,
2909 int *rdata_len
,int *rparam_len
)
2912 time_t unixdate
= time(NULL
);
2916 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2922 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2927 SSVAL(*rparam
,0,NERR_Success
);
2928 SSVAL(*rparam
,2,0); /* converter word */
2932 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2933 by NT in a "net time" operation,
2934 it seems to ignore the one below */
2936 /* the client expects to get localtime, not GMT, in this bit
2937 (I think, this needs testing) */
2938 t
= localtime(&unixdate
);
2943 SIVAL(p
,4,0); /* msecs ? */
2944 SCVAL(p
,8,t
->tm_hour
);
2945 SCVAL(p
,9,t
->tm_min
);
2946 SCVAL(p
,10,t
->tm_sec
);
2947 SCVAL(p
,11,0); /* hundredths of seconds */
2948 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2949 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2950 SCVAL(p
,16,t
->tm_mday
);
2951 SCVAL(p
,17,t
->tm_mon
+ 1);
2952 SSVAL(p
,18,1900+t
->tm_year
);
2953 SCVAL(p
,20,t
->tm_wday
);
2958 /****************************************************************************
2959 Set the user password (SamOEM version - gets plaintext).
2960 ****************************************************************************/
2962 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
2963 connection_struct
*conn
,uint64_t vuid
,
2964 char *param
, int tpscnt
,
2965 char *data
, int tdscnt
,
2966 int mdrcnt
,int mprcnt
,
2967 char **rdata
,char **rparam
,
2968 int *rdata_len
,int *rparam_len
)
2971 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2973 TALLOC_CTX
*mem_ctx
= talloc_tos();
2974 NTSTATUS status
, result
;
2975 struct rpc_pipe_client
*cli
= NULL
;
2976 struct lsa_AsciiString server
, account
;
2977 struct samr_CryptPassword password
;
2978 struct samr_Password hash
;
2979 int errcode
= NERR_badpass
;
2981 struct dcerpc_binding_handle
*b
;
2984 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2994 SSVAL(*rparam
,0,NERR_badpass
);
2997 * Check the parameter definition is correct.
3000 /* Do we have a string ? */
3001 if (skip_string(param
,tpscnt
,p
) == 0) {
3004 if(!strequal(p
, "zsT")) {
3005 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3008 p
= skip_string(param
, tpscnt
, p
);
3013 /* Do we have a string ? */
3014 if (skip_string(param
,tpscnt
,p
) == 0) {
3017 if(!strequal(p
, "B516B16")) {
3018 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3021 p
= skip_string(param
,tpscnt
,p
);
3025 /* Do we have a string ? */
3026 if (skip_string(param
,tpscnt
,p
) == 0) {
3029 p
+= pull_ascii_fstring(user
,p
);
3031 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3033 if (tdscnt
!= 532) {
3034 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3038 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3039 if (bufsize
!= 532) {
3040 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3044 memcpy(password
.data
, data
, 516);
3045 memcpy(hash
.hash
, data
+516, 16);
3047 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
3049 conn
->sconn
->remote_address
,
3050 conn
->sconn
->msg_ctx
,
3052 if (!NT_STATUS_IS_OK(status
)) {
3053 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3054 nt_errstr(status
)));
3055 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3059 b
= cli
->binding_handle
;
3061 init_lsa_AsciiString(&server
, lp_netbios_name());
3062 init_lsa_AsciiString(&account
, user
);
3064 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3070 if (!NT_STATUS_IS_OK(status
)) {
3071 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3074 if (!NT_STATUS_IS_OK(result
)) {
3075 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3079 errcode
= NERR_Success
;
3081 SSVAL(*rparam
,0,errcode
);
3082 SSVAL(*rparam
,2,0); /* converter word */
3087 /****************************************************************************
3090 ****************************************************************************/
3092 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3093 connection_struct
*conn
,uint64_t vuid
,
3094 char *param
, int tpscnt
,
3095 char *data
, int tdscnt
,
3096 int mdrcnt
,int mprcnt
,
3097 char **rdata
,char **rparam
,
3098 int *rdata_len
,int *rparam_len
)
3100 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3101 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3102 char *str2
= skip_string(param
,tpscnt
,str1
);
3103 char *p
= skip_string(param
,tpscnt
,str2
);
3107 WERROR werr
= WERR_OK
;
3109 TALLOC_CTX
*mem_ctx
= talloc_tos();
3111 struct rpc_pipe_client
*cli
= NULL
;
3112 struct dcerpc_binding_handle
*b
= NULL
;
3113 struct policy_handle handle
;
3114 struct spoolss_DevmodeContainer devmode_ctr
;
3115 enum spoolss_JobControl command
;
3117 if (!str1
|| !str2
|| !p
) {
3121 * We use 1 here not 2 as we're checking
3122 * the last byte we want to access is safe.
3124 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3127 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3130 /* check it's a supported varient */
3131 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3135 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3141 ZERO_STRUCT(handle
);
3143 status
= rpc_pipe_open_interface(conn
,
3146 conn
->sconn
->remote_address
,
3147 conn
->sconn
->msg_ctx
,
3149 if (!NT_STATUS_IS_OK(status
)) {
3150 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3151 nt_errstr(status
)));
3152 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3155 b
= cli
->binding_handle
;
3157 ZERO_STRUCT(devmode_ctr
);
3159 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3163 JOB_ACCESS_ADMINISTER
,
3166 if (!NT_STATUS_IS_OK(status
)) {
3167 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3170 if (!W_ERROR_IS_OK(werr
)) {
3171 errcode
= W_ERROR_V(werr
);
3175 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3176 * and NERR_DestNotFound if share did not exist */
3178 errcode
= NERR_Success
;
3181 case 81: /* delete */
3182 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3184 case 82: /* pause */
3185 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3187 case 83: /* resume */
3188 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3191 errcode
= NERR_notsupported
;
3195 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3198 NULL
, /* unique ptr ctr */
3201 if (!NT_STATUS_IS_OK(status
)) {
3202 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3205 if (!W_ERROR_IS_OK(werr
)) {
3206 errcode
= W_ERROR_V(werr
);
3211 if (b
&& is_valid_policy_hnd(&handle
)) {
3212 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3215 SSVAL(*rparam
,0,errcode
);
3216 SSVAL(*rparam
,2,0); /* converter word */
3221 /****************************************************************************
3222 Purge a print queue - or pause or resume it.
3223 ****************************************************************************/
3225 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3226 connection_struct
*conn
,uint64_t vuid
,
3227 char *param
, int tpscnt
,
3228 char *data
, int tdscnt
,
3229 int mdrcnt
,int mprcnt
,
3230 char **rdata
,char **rparam
,
3231 int *rdata_len
,int *rparam_len
)
3233 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3234 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3235 char *str2
= skip_string(param
,tpscnt
,str1
);
3236 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3237 int errcode
= NERR_notsupported
;
3238 WERROR werr
= WERR_OK
;
3241 TALLOC_CTX
*mem_ctx
= talloc_tos();
3242 struct rpc_pipe_client
*cli
= NULL
;
3243 struct dcerpc_binding_handle
*b
= NULL
;
3244 struct policy_handle handle
;
3245 struct spoolss_SetPrinterInfoCtr info_ctr
;
3246 struct spoolss_DevmodeContainer devmode_ctr
;
3247 struct sec_desc_buf secdesc_ctr
;
3248 enum spoolss_PrinterControl command
;
3250 if (!str1
|| !str2
|| !QueueName
) {
3254 /* check it's a supported varient */
3255 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3259 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3265 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3269 ZERO_STRUCT(handle
);
3271 status
= rpc_pipe_open_interface(conn
,
3274 conn
->sconn
->remote_address
,
3275 conn
->sconn
->msg_ctx
,
3277 if (!NT_STATUS_IS_OK(status
)) {
3278 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3279 nt_errstr(status
)));
3280 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3283 b
= cli
->binding_handle
;
3285 ZERO_STRUCT(devmode_ctr
);
3287 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3291 PRINTER_ACCESS_ADMINISTER
,
3294 if (!NT_STATUS_IS_OK(status
)) {
3295 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3298 if (!W_ERROR_IS_OK(werr
)) {
3299 errcode
= W_ERROR_V(werr
);
3304 case 74: /* Pause queue */
3305 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3307 case 75: /* Resume queue */
3308 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3310 case 103: /* Purge */
3311 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3314 werr
= WERR_NOT_SUPPORTED
;
3318 if (!W_ERROR_IS_OK(werr
)) {
3319 errcode
= W_ERROR_V(werr
);
3323 ZERO_STRUCT(info_ctr
);
3324 ZERO_STRUCT(secdesc_ctr
);
3326 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3333 if (!NT_STATUS_IS_OK(status
)) {
3334 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3337 if (!W_ERROR_IS_OK(werr
)) {
3338 errcode
= W_ERROR_V(werr
);
3342 errcode
= W_ERROR_V(werr
);
3346 if (b
&& is_valid_policy_hnd(&handle
)) {
3347 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3350 SSVAL(*rparam
,0,errcode
);
3351 SSVAL(*rparam
,2,0); /* converter word */
3356 /****************************************************************************
3357 set the property of a print job (undocumented?)
3358 ? function = 0xb -> set name of print job
3359 ? function = 0x6 -> move print job up/down
3360 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3361 or <WWsTP> <WB21BB16B10zWWzDDz>
3362 ****************************************************************************/
3364 static int check_printjob_info(struct pack_desc
* desc
,
3365 int uLevel
, char* id
)
3367 desc
->subformat
= NULL
;
3369 case 0: desc
->format
= "W"; break;
3370 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3371 case 2: desc
->format
= "WWzWWDDzz"; break;
3372 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3373 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3375 DEBUG(0,("check_printjob_info: invalid level %d\n",
3379 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3380 DEBUG(0,("check_printjob_info: invalid format %s\n",
3381 id
? id
: "<NULL>" ));
3387 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3388 connection_struct
*conn
, uint64_t vuid
,
3389 char *param
, int tpscnt
,
3390 char *data
, int tdscnt
,
3391 int mdrcnt
,int mprcnt
,
3392 char **rdata
,char **rparam
,
3393 int *rdata_len
,int *rparam_len
)
3395 struct pack_desc desc
;
3396 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3397 char *str2
= skip_string(param
,tpscnt
,str1
);
3398 char *p
= skip_string(param
,tpscnt
,str2
);
3401 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3402 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3405 TALLOC_CTX
*mem_ctx
= talloc_tos();
3408 struct rpc_pipe_client
*cli
= NULL
;
3409 struct dcerpc_binding_handle
*b
= NULL
;
3410 struct policy_handle handle
;
3411 struct spoolss_DevmodeContainer devmode_ctr
;
3412 struct spoolss_JobInfoContainer ctr
;
3413 union spoolss_JobInfo info
;
3414 struct spoolss_SetJobInfo1 info1
;
3416 if (!str1
|| !str2
|| !p
) {
3420 * We use 1 here not 2 as we're checking
3421 * the last byte we want to access is safe.
3423 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3426 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3429 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3436 /* check it's a supported varient */
3437 if ((strcmp(str1
,"WWsTP")) ||
3438 (!check_printjob_info(&desc
,uLevel
,str2
)))
3441 errcode
= NERR_notsupported
;
3445 /* change print job name, data gives the name */
3451 ZERO_STRUCT(handle
);
3453 status
= rpc_pipe_open_interface(conn
,
3456 conn
->sconn
->remote_address
,
3457 conn
->sconn
->msg_ctx
,
3459 if (!NT_STATUS_IS_OK(status
)) {
3460 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3461 nt_errstr(status
)));
3462 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3465 b
= cli
->binding_handle
;
3467 ZERO_STRUCT(devmode_ctr
);
3469 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3476 if (!NT_STATUS_IS_OK(status
)) {
3477 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3480 if (!W_ERROR_IS_OK(werr
)) {
3481 errcode
= W_ERROR_V(werr
);
3485 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3491 if (!W_ERROR_IS_OK(werr
)) {
3492 errcode
= W_ERROR_V(werr
);
3498 info1
.job_id
= info
.info1
.job_id
;
3499 info1
.printer_name
= info
.info1
.printer_name
;
3500 info1
.user_name
= info
.info1
.user_name
;
3501 info1
.document_name
= data
;
3502 info1
.data_type
= info
.info1
.data_type
;
3503 info1
.text_status
= info
.info1
.text_status
;
3504 info1
.status
= info
.info1
.status
;
3505 info1
.priority
= info
.info1
.priority
;
3506 info1
.position
= info
.info1
.position
;
3507 info1
.total_pages
= info
.info1
.total_pages
;
3508 info1
.pages_printed
= info
.info1
.pages_printed
;
3509 info1
.submitted
= info
.info1
.submitted
;
3512 ctr
.info
.info1
= &info1
;
3514 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3520 if (!NT_STATUS_IS_OK(status
)) {
3521 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3524 if (!W_ERROR_IS_OK(werr
)) {
3525 errcode
= W_ERROR_V(werr
);
3529 errcode
= NERR_Success
;
3532 if (b
&& is_valid_policy_hnd(&handle
)) {
3533 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3536 SSVALS(*rparam
,0,errcode
);
3537 SSVAL(*rparam
,2,0); /* converter word */
3543 /****************************************************************************
3544 Get info about the server.
3545 ****************************************************************************/
3547 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3548 connection_struct
*conn
,uint64_t vuid
,
3549 char *param
, int tpscnt
,
3550 char *data
, int tdscnt
,
3551 int mdrcnt
,int mprcnt
,
3552 char **rdata
,char **rparam
,
3553 int *rdata_len
,int *rparam_len
)
3555 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3556 char *str2
= skip_string(param
,tpscnt
,str1
);
3557 char *p
= skip_string(param
,tpscnt
,str2
);
3558 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3564 TALLOC_CTX
*mem_ctx
= talloc_tos();
3565 struct rpc_pipe_client
*cli
= NULL
;
3566 union srvsvc_NetSrvInfo info
;
3568 struct dcerpc_binding_handle
*b
;
3570 if (!str1
|| !str2
|| !p
) {
3574 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3576 /* check it's a supported varient */
3577 if (!prefix_ok(str1
,"WrLh")) {
3583 if (strcmp(str2
,"B16") != 0) {
3589 if (strcmp(str2
,"B16BBDz") != 0) {
3595 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3601 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3607 if (strcmp(str2
,"DN") != 0) {
3613 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3622 *rdata_len
= mdrcnt
;
3623 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3629 p2
= p
+ struct_len
;
3631 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
3633 conn
->sconn
->remote_address
,
3634 conn
->sconn
->msg_ctx
,
3636 if (!NT_STATUS_IS_OK(status
)) {
3637 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3638 nt_errstr(status
)));
3639 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3643 b
= cli
->binding_handle
;
3645 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3650 if (!NT_STATUS_IS_OK(status
)) {
3651 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3654 if (!W_ERROR_IS_OK(werr
)) {
3655 errcode
= W_ERROR_V(werr
);
3659 if (info
.info101
== NULL
) {
3660 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3666 status
= srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3667 STR_ASCII
|STR_UPPER
|STR_TERMINATE
, &len
);
3668 if (!NT_STATUS_IS_OK(status
)) {
3669 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3675 SCVAL(p
,0,info
.info101
->version_major
);
3676 SCVAL(p
,1,info
.info101
->version_minor
);
3677 SIVAL(p
,2,info
.info101
->server_type
);
3679 if (mdrcnt
== struct_len
) {
3682 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3683 if (mdrcnt
- struct_len
<= 0) {
3687 info
.info101
->comment
,
3688 MIN(mdrcnt
- struct_len
,
3689 MAX_SERVER_STRING_LENGTH
),
3691 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3699 return False
; /* not yet implemented */
3702 errcode
= NERR_Success
;
3706 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3709 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3713 SSVAL(*rparam
,0,errcode
);
3714 SSVAL(*rparam
,2,0); /* converter word */
3715 SSVAL(*rparam
,4,*rdata_len
);
3720 /****************************************************************************
3721 Get info about the server.
3722 ****************************************************************************/
3724 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3725 connection_struct
*conn
,uint64_t vuid
,
3726 char *param
, int tpscnt
,
3727 char *data
, int tdscnt
,
3728 int mdrcnt
,int mprcnt
,
3729 char **rdata
,char **rparam
,
3730 int *rdata_len
,int *rparam_len
)
3732 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3733 char *str2
= skip_string(param
,tpscnt
,str1
);
3734 char *p
= skip_string(param
,tpscnt
,str2
);
3737 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3739 if (!str1
|| !str2
|| !p
) {
3743 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3746 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3751 /* check it's a supported varient */
3752 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3756 *rdata_len
= mdrcnt
+ 1024;
3757 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3762 SSVAL(*rparam
,0,NERR_Success
);
3763 SSVAL(*rparam
,2,0); /* converter word */
3766 endp
= *rdata
+ *rdata_len
;
3768 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3773 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3774 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3775 if (!strupper_m(p2
)) {
3778 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3784 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3785 strlcpy(p2
,conn
->session_info
->unix_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3786 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3792 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3793 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3794 if (!strupper_m(p2
)) {
3797 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3803 SCVAL(p
,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g 4 in 4.1 */
3804 SCVAL(p
,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g .1 in 4.1 */
3807 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3808 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3809 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3815 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3816 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3817 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3823 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3825 SSVAL(*rparam
,4,*rdata_len
);
3830 /****************************************************************************
3831 get info about a user
3833 struct user_info_11 {
3834 char usri11_name[21]; 0-20
3836 char *usri11_comment; 22-25
3837 char *usri11_usr_comment; 26-29
3838 unsigned short usri11_priv; 30-31
3839 unsigned long usri11_auth_flags; 32-35
3840 long usri11_password_age; 36-39
3841 char *usri11_homedir; 40-43
3842 char *usri11_parms; 44-47
3843 long usri11_last_logon; 48-51
3844 long usri11_last_logoff; 52-55
3845 unsigned short usri11_bad_pw_count; 56-57
3846 unsigned short usri11_num_logons; 58-59
3847 char *usri11_logon_server; 60-63
3848 unsigned short usri11_country_code; 64-65
3849 char *usri11_workstations; 66-69
3850 unsigned long usri11_max_storage; 70-73
3851 unsigned short usri11_units_per_week; 74-75
3852 unsigned char *usri11_logon_hours; 76-79
3853 unsigned short usri11_code_page; 80-81
3858 usri11_name specifies the user name for which information is retrieved
3860 usri11_pad aligns the next data structure element to a word boundary
3862 usri11_comment is a null terminated ASCII comment
3864 usri11_user_comment is a null terminated ASCII comment about the user
3866 usri11_priv specifies the level of the privilege assigned to the user.
3867 The possible values are:
3869 Name Value Description
3870 USER_PRIV_GUEST 0 Guest privilege
3871 USER_PRIV_USER 1 User privilege
3872 USER_PRV_ADMIN 2 Administrator privilege
3874 usri11_auth_flags specifies the account operator privileges. The
3875 possible values are:
3877 Name Value Description
3878 AF_OP_PRINT 0 Print operator
3881 Leach, Naik [Page 28]
3885 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3888 AF_OP_COMM 1 Communications operator
3889 AF_OP_SERVER 2 Server operator
3890 AF_OP_ACCOUNTS 3 Accounts operator
3893 usri11_password_age specifies how many seconds have elapsed since the
3894 password was last changed.
3896 usri11_home_dir points to a null terminated ASCII string that contains
3897 the path name of the user's home directory.
3899 usri11_parms points to a null terminated ASCII string that is set
3900 aside for use by applications.
3902 usri11_last_logon specifies the time when the user last logged on.
3903 This value is stored as the number of seconds elapsed since
3904 00:00:00, January 1, 1970.
3906 usri11_last_logoff specifies the time when the user last logged off.
3907 This value is stored as the number of seconds elapsed since
3908 00:00:00, January 1, 1970. A value of 0 means the last logoff
3911 usri11_bad_pw_count specifies the number of incorrect passwords
3912 entered since the last successful logon.
3914 usri11_log1_num_logons specifies the number of times this user has
3915 logged on. A value of -1 means the number of logons is unknown.
3917 usri11_logon_server points to a null terminated ASCII string that
3918 contains the name of the server to which logon requests are sent.
3919 A null string indicates logon requests should be sent to the
3922 usri11_country_code specifies the country code for the user's language
3925 usri11_workstations points to a null terminated ASCII string that
3926 contains the names of workstations the user may log on from.
3927 There may be up to 8 workstations, with the names separated by
3928 commas. A null strings indicates there are no restrictions.
3930 usri11_max_storage specifies the maximum amount of disk space the user
3931 can occupy. A value of 0xffffffff indicates there are no
3934 usri11_units_per_week specifies the equal number of time units into
3935 which a week is divided. This value must be equal to 168.
3937 usri11_logon_hours points to a 21 byte (168 bits) string that
3938 specifies the time during which the user can log on. Each bit
3939 represents one unique hour in a week. The first bit (bit 0, word
3940 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3944 Leach, Naik [Page 29]
3948 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3951 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3952 are no restrictions.
3954 usri11_code_page specifies the code page for the user's language of
3957 All of the pointers in this data structure need to be treated
3958 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3959 to be ignored. The converter word returned in the parameters section
3960 needs to be subtracted from the lower 16 bits to calculate an offset
3961 into the return buffer where this ASCII string resides.
3963 There is no auxiliary data in the response.
3965 ****************************************************************************/
3967 #define usri11_name 0
3968 #define usri11_pad 21
3969 #define usri11_comment 22
3970 #define usri11_usr_comment 26
3971 #define usri11_full_name 30
3972 #define usri11_priv 34
3973 #define usri11_auth_flags 36
3974 #define usri11_password_age 40
3975 #define usri11_homedir 44
3976 #define usri11_parms 48
3977 #define usri11_last_logon 52
3978 #define usri11_last_logoff 56
3979 #define usri11_bad_pw_count 60
3980 #define usri11_num_logons 62
3981 #define usri11_logon_server 64
3982 #define usri11_country_code 68
3983 #define usri11_workstations 70
3984 #define usri11_max_storage 74
3985 #define usri11_units_per_week 78
3986 #define usri11_logon_hours 80
3987 #define usri11_code_page 84
3988 #define usri11_end 86
3990 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
3991 connection_struct
*conn
, uint64_t vuid
,
3992 char *param
, int tpscnt
,
3993 char *data
, int tdscnt
,
3994 int mdrcnt
,int mprcnt
,
3995 char **rdata
,char **rparam
,
3996 int *rdata_len
,int *rparam_len
)
3998 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3999 char *str2
= skip_string(param
,tpscnt
,str1
);
4000 char *UserName
= skip_string(param
,tpscnt
,str2
);
4001 char *p
= skip_string(param
,tpscnt
,UserName
);
4002 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4005 const char *level_string
;
4007 TALLOC_CTX
*mem_ctx
= talloc_tos();
4008 NTSTATUS status
, result
;
4009 struct rpc_pipe_client
*cli
= NULL
;
4010 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4011 struct lsa_String domain_name
;
4012 struct dom_sid2
*domain_sid
;
4013 struct lsa_String names
;
4014 struct samr_Ids rids
;
4015 struct samr_Ids types
;
4016 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4018 union samr_UserInfo
*info
;
4019 struct dcerpc_binding_handle
*b
= NULL
;
4021 if (!str1
|| !str2
|| !UserName
|| !p
) {
4026 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4031 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4033 /* check it's a supported variant */
4034 if (strcmp(str1
,"zWrLh") != 0) {
4038 case 0: level_string
= "B21"; break;
4039 case 1: level_string
= "B21BB16DWzzWz"; break;
4040 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4041 case 10: level_string
= "B21Bzzz"; break;
4042 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4043 default: return False
;
4046 if (strcmp(level_string
,str2
) != 0) {
4050 *rdata_len
= mdrcnt
+ 1024;
4051 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4057 endp
= *rdata
+ *rdata_len
;
4058 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4063 ZERO_STRUCT(connect_handle
);
4064 ZERO_STRUCT(domain_handle
);
4065 ZERO_STRUCT(user_handle
);
4067 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
4069 conn
->sconn
->remote_address
,
4070 conn
->sconn
->msg_ctx
,
4072 if (!NT_STATUS_IS_OK(status
)) {
4073 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4074 nt_errstr(status
)));
4075 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4079 b
= cli
->binding_handle
;
4081 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4083 SAMR_ACCESS_CONNECT_TO_SERVER
|
4084 SAMR_ACCESS_ENUM_DOMAINS
|
4085 SAMR_ACCESS_LOOKUP_DOMAIN
,
4088 if (!NT_STATUS_IS_OK(status
)) {
4089 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4092 if (!NT_STATUS_IS_OK(result
)) {
4093 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4097 init_lsa_String(&domain_name
, get_global_sam_name());
4099 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4104 if (!NT_STATUS_IS_OK(status
)) {
4105 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4108 if (!NT_STATUS_IS_OK(result
)) {
4109 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4113 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4115 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4119 if (!NT_STATUS_IS_OK(status
)) {
4120 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4123 if (!NT_STATUS_IS_OK(result
)) {
4124 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4128 init_lsa_String(&names
, UserName
);
4130 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4137 if (!NT_STATUS_IS_OK(status
)) {
4138 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4141 if (!NT_STATUS_IS_OK(result
)) {
4142 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4146 if (rids
.count
!= 1) {
4147 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4150 if (rids
.count
!= types
.count
) {
4151 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4154 if (types
.ids
[0] != SID_NAME_USER
) {
4155 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4161 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4163 SAMR_USER_ACCESS_GET_LOCALE
|
4164 SAMR_USER_ACCESS_GET_LOGONINFO
|
4165 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4166 SAMR_USER_ACCESS_GET_GROUPS
|
4167 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4168 SEC_STD_READ_CONTROL
,
4172 if (!NT_STATUS_IS_OK(status
)) {
4173 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4176 if (!NT_STATUS_IS_OK(result
)) {
4177 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4181 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4186 if (!NT_STATUS_IS_OK(status
)) {
4187 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4190 if (!NT_STATUS_IS_OK(result
)) {
4191 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4196 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4199 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4204 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4205 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4206 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4211 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4212 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4213 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4218 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4219 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4220 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4221 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4228 const char *homedir
= info
->info21
.home_directory
.string
;
4229 /* modelled after NTAS 3.51 reply */
4230 SSVAL(p
,usri11_priv
,
4231 (get_current_uid(conn
) == sec_initial_uid())?
4232 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4233 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4234 SIVALS(p
,usri11_password_age
,-1); /* password age */
4235 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4236 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4237 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4241 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4242 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4243 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4247 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4248 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4249 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4250 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4251 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4252 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4253 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4257 SSVAL(p
,usri11_country_code
,0); /* country code */
4259 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4260 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4261 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4266 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4267 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4268 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4270 /* a simple way to get logon hours at all times. */
4272 SCVAL(p2
,21,0); /* fix zero termination */
4273 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4278 SSVAL(p
,usri11_code_page
,0); /* code page */
4281 if (uLevel
== 1 || uLevel
== 2) {
4282 memset(p
+22,' ',16); /* password */
4283 SIVALS(p
,38,-1); /* password age */
4285 (get_current_uid(conn
) == sec_initial_uid())?
4286 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4287 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4288 strlcpy(p2
, info
->info21
.home_directory
.string
,
4290 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4294 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4296 SSVAL(p
,52,0); /* flags */
4297 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4298 strlcpy(p2
, info
->info21
.logon_script
.string
,
4300 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4305 SIVAL(p
,58,0); /* auth_flags */
4306 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4307 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4308 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4312 SIVAL(p
,66,0); /* urs_comment */
4313 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4314 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4315 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4319 SIVAL(p
,74,0); /* workstations */
4320 SIVAL(p
,78,0); /* last_logon */
4321 SIVAL(p
,82,0); /* last_logoff */
4322 SIVALS(p
,86,-1); /* acct_expires */
4323 SIVALS(p
,90,-1); /* max_storage */
4324 SSVAL(p
,94,168); /* units_per_week */
4325 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4328 SSVALS(p
,100,-1); /* bad_pw_count */
4329 SSVALS(p
,102,-1); /* num_logons */
4330 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4332 TALLOC_CTX
*ctx
= talloc_tos();
4333 int space_rem
= *rdata_len
- (p2
- *rdata
);
4336 if (space_rem
<= 0) {
4339 tmp
= talloc_strdup(ctx
, "\\\\%L");
4343 tmp
= talloc_sub_basic(ctx
,
4356 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4360 SSVAL(p
,108,49); /* country_code */
4361 SSVAL(p
,110,860); /* code page */
4365 errcode
= NERR_Success
;
4368 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4370 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4371 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4373 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4374 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4376 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4377 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4380 SSVAL(*rparam
,0,errcode
);
4381 SSVAL(*rparam
,2,0); /* converter word */
4382 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4387 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4388 connection_struct
*conn
,uint64_t vuid
,
4389 char *param
, int tpscnt
,
4390 char *data
, int tdscnt
,
4391 int mdrcnt
,int mprcnt
,
4392 char **rdata
,char **rparam
,
4393 int *rdata_len
,int *rparam_len
)
4395 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4396 char *str2
= skip_string(param
,tpscnt
,str1
);
4397 char *p
= skip_string(param
,tpscnt
,str2
);
4399 struct pack_desc desc
;
4401 /* With share level security vuid will always be zero.
4402 Don't depend on vuser being non-null !!. JRA */
4403 struct user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4405 if (!str1
|| !str2
|| !p
) {
4410 DEBUG(3,(" Username of UID %d is %s\n",
4411 (int)vuser
->session_info
->unix_token
->uid
,
4412 vuser
->session_info
->unix_info
->unix_name
));
4415 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4416 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4421 memset((char *)&desc
,'\0',sizeof(desc
));
4423 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4425 /* check it's a supported varient */
4426 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4429 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4433 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4440 desc
.buflen
= mdrcnt
;
4441 desc
.subformat
= NULL
;
4444 if (init_package(&desc
,1,0)) {
4445 PACKI(&desc
,"W",0); /* code */
4446 PACKS(&desc
,"B21",name
); /* eff. name */
4447 PACKS(&desc
,"B",""); /* pad */
4449 (get_current_uid(conn
) == sec_initial_uid())?
4450 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4451 PACKI(&desc
,"D",0); /* auth flags XXX */
4452 PACKI(&desc
,"W",0); /* num logons */
4453 PACKI(&desc
,"W",0); /* bad pw count */
4454 PACKI(&desc
,"D",0); /* last logon */
4455 PACKI(&desc
,"D",-1); /* last logoff */
4456 PACKI(&desc
,"D",-1); /* logoff time */
4457 PACKI(&desc
,"D",-1); /* kickoff time */
4458 PACKI(&desc
,"D",0); /* password age */
4459 PACKI(&desc
,"D",0); /* password can change */
4460 PACKI(&desc
,"D",-1); /* password must change */
4464 fstrcpy(mypath
,"\\\\");
4465 fstrcat(mypath
,get_local_machine_name());
4466 if (!strupper_m(mypath
)) {
4469 PACKS(&desc
,"z",mypath
); /* computer */
4472 PACKS(&desc
,"z",lp_workgroup());/* domain */
4473 PACKS(&desc
,"z", vuser
?
4474 vuser
->session_info
->info
->logon_script
4475 : ""); /* script path */
4476 PACKI(&desc
,"D",0x00000000); /* reserved */
4479 *rdata_len
= desc
.usedlen
;
4481 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4485 SSVALS(*rparam
,0,desc
.errcode
);
4487 SSVAL(*rparam
,4,desc
.neededlen
);
4489 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4494 /****************************************************************************
4495 api_WAccessGetUserPerms
4496 ****************************************************************************/
4498 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4499 connection_struct
*conn
,uint64_t vuid
,
4500 char *param
, int tpscnt
,
4501 char *data
, int tdscnt
,
4502 int mdrcnt
,int mprcnt
,
4503 char **rdata
,char **rparam
,
4504 int *rdata_len
,int *rparam_len
)
4506 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4507 char *str2
= skip_string(param
,tpscnt
,str1
);
4508 char *user
= skip_string(param
,tpscnt
,str2
);
4509 char *resource
= skip_string(param
,tpscnt
,user
);
4511 if (!str1
|| !str2
|| !user
|| !resource
) {
4515 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4518 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4520 /* check it's a supported varient */
4521 if (strcmp(str1
,"zzh") != 0) {
4524 if (strcmp(str2
,"") != 0) {
4529 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4533 SSVALS(*rparam
,0,0); /* errorcode */
4534 SSVAL(*rparam
,2,0); /* converter word */
4535 SSVAL(*rparam
,4,0x7f); /* permission flags */
4540 /****************************************************************************
4541 api_WPrintJobEnumerate
4542 ****************************************************************************/
4544 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4545 connection_struct
*conn
, uint64_t vuid
,
4546 char *param
, int tpscnt
,
4547 char *data
, int tdscnt
,
4548 int mdrcnt
,int mprcnt
,
4549 char **rdata
,char **rparam
,
4550 int *rdata_len
,int *rparam_len
)
4552 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4553 char *str2
= skip_string(param
,tpscnt
,str1
);
4554 char *p
= skip_string(param
,tpscnt
,str2
);
4558 struct pack_desc desc
;
4561 TALLOC_CTX
*mem_ctx
= talloc_tos();
4564 struct rpc_pipe_client
*cli
= NULL
;
4565 struct dcerpc_binding_handle
*b
= NULL
;
4566 struct policy_handle handle
;
4567 struct spoolss_DevmodeContainer devmode_ctr
;
4568 union spoolss_JobInfo info
;
4570 if (!str1
|| !str2
|| !p
) {
4574 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4576 memset((char *)&desc
,'\0',sizeof(desc
));
4577 memset((char *)&status
,'\0',sizeof(status
));
4579 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4581 /* check it's a supported varient */
4582 if (strcmp(str1
,"WWrLh") != 0) {
4585 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4589 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4593 ZERO_STRUCT(handle
);
4595 status
= rpc_pipe_open_interface(conn
,
4598 conn
->sconn
->remote_address
,
4599 conn
->sconn
->msg_ctx
,
4601 if (!NT_STATUS_IS_OK(status
)) {
4602 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4603 nt_errstr(status
)));
4604 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4607 b
= cli
->binding_handle
;
4609 ZERO_STRUCT(devmode_ctr
);
4611 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4618 if (!NT_STATUS_IS_OK(status
)) {
4619 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4622 if (!W_ERROR_IS_OK(werr
)) {
4623 desc
.errcode
= W_ERROR_V(werr
);
4627 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4633 if (!W_ERROR_IS_OK(werr
)) {
4634 desc
.errcode
= W_ERROR_V(werr
);
4639 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4644 desc
.buflen
= mdrcnt
;
4647 * Don't return data but need to get correct length
4648 * init_package will return wrong size if buflen=0
4650 desc
.buflen
= getlen(desc
.format
);
4651 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4654 if (init_package(&desc
,1,0)) {
4655 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4656 *rdata_len
= desc
.usedlen
;
4658 desc
.errcode
= NERR_JobNotFound
;
4662 if (b
&& is_valid_policy_hnd(&handle
)) {
4663 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4667 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4671 SSVALS(*rparam
,0,desc
.errcode
);
4673 SSVAL(*rparam
,4,desc
.neededlen
);
4677 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4682 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4683 connection_struct
*conn
, uint64_t vuid
,
4684 char *param
, int tpscnt
,
4685 char *data
, int tdscnt
,
4686 int mdrcnt
,int mprcnt
,
4687 char **rdata
,char **rparam
,
4688 int *rdata_len
,int *rparam_len
)
4690 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4691 char *str2
= skip_string(param
,tpscnt
,str1
);
4692 char *p
= skip_string(param
,tpscnt
,str2
);
4696 struct pack_desc desc
;
4698 TALLOC_CTX
*mem_ctx
= talloc_tos();
4701 struct rpc_pipe_client
*cli
= NULL
;
4702 struct dcerpc_binding_handle
*b
= NULL
;
4703 struct policy_handle handle
;
4704 struct spoolss_DevmodeContainer devmode_ctr
;
4706 union spoolss_JobInfo
*info
;
4708 if (!str1
|| !str2
|| !p
) {
4712 memset((char *)&desc
,'\0',sizeof(desc
));
4714 p
= skip_string(param
,tpscnt
,p
);
4718 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4720 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4722 /* check it's a supported variant */
4723 if (strcmp(str1
,"zWrLeh") != 0) {
4728 return False
; /* defined only for uLevel 0,1,2 */
4731 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4735 ZERO_STRUCT(handle
);
4737 status
= rpc_pipe_open_interface(conn
,
4740 conn
->sconn
->remote_address
,
4741 conn
->sconn
->msg_ctx
,
4743 if (!NT_STATUS_IS_OK(status
)) {
4744 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4745 nt_errstr(status
)));
4746 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4749 b
= cli
->binding_handle
;
4751 ZERO_STRUCT(devmode_ctr
);
4753 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4760 if (!NT_STATUS_IS_OK(status
)) {
4761 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4764 if (!W_ERROR_IS_OK(werr
)) {
4765 desc
.errcode
= W_ERROR_V(werr
);
4769 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4777 if (!W_ERROR_IS_OK(werr
)) {
4778 desc
.errcode
= W_ERROR_V(werr
);
4783 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4789 desc
.buflen
= mdrcnt
;
4791 if (init_package(&desc
,count
,0)) {
4793 for (i
= 0; i
< count
; i
++) {
4794 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4795 if (desc
.errcode
== NERR_Success
) {
4801 if (b
&& is_valid_policy_hnd(&handle
)) {
4802 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4805 *rdata_len
= desc
.usedlen
;
4808 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4812 SSVALS(*rparam
,0,desc
.errcode
);
4814 SSVAL(*rparam
,4,succnt
);
4815 SSVAL(*rparam
,6,count
);
4817 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4822 static int check_printdest_info(struct pack_desc
* desc
,
4823 int uLevel
, char* id
)
4825 desc
->subformat
= NULL
;
4828 desc
->format
= "B9";
4831 desc
->format
= "B9B21WWzW";
4837 desc
->format
= "zzzWWzzzWW";
4840 DEBUG(0,("check_printdest_info: invalid level %d\n",
4844 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4845 DEBUG(0,("check_printdest_info: invalid string %s\n",
4846 id
? id
: "<NULL>" ));
4852 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4853 struct pack_desc
* desc
)
4857 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4858 buf
[sizeof(buf
)-1] = 0;
4859 (void)strupper_m(buf
);
4862 PACKS(desc
,"B9",buf
); /* szName */
4864 PACKS(desc
,"B21",""); /* szUserName */
4865 PACKI(desc
,"W",0); /* uJobId */
4866 PACKI(desc
,"W",0); /* fsStatus */
4867 PACKS(desc
,"z",""); /* pszStatus */
4868 PACKI(desc
,"W",0); /* time */
4872 if (uLevel
== 2 || uLevel
== 3) {
4873 PACKS(desc
,"z",buf
); /* pszPrinterName */
4875 PACKS(desc
,"z",""); /* pszUserName */
4876 PACKS(desc
,"z",""); /* pszLogAddr */
4877 PACKI(desc
,"W",0); /* uJobId */
4878 PACKI(desc
,"W",0); /* fsStatus */
4879 PACKS(desc
,"z",""); /* pszStatus */
4880 PACKS(desc
,"z",""); /* pszComment */
4881 PACKS(desc
,"z","NULL"); /* pszDrivers */
4882 PACKI(desc
,"W",0); /* time */
4883 PACKI(desc
,"W",0); /* pad1 */
4888 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4889 connection_struct
*conn
, uint64_t vuid
,
4890 char *param
, int tpscnt
,
4891 char *data
, int tdscnt
,
4892 int mdrcnt
,int mprcnt
,
4893 char **rdata
,char **rparam
,
4894 int *rdata_len
,int *rparam_len
)
4896 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4897 char *str2
= skip_string(param
,tpscnt
,str1
);
4898 char *p
= skip_string(param
,tpscnt
,str2
);
4899 char* PrinterName
= p
;
4901 struct pack_desc desc
;
4904 TALLOC_CTX
*mem_ctx
= talloc_tos();
4907 struct rpc_pipe_client
*cli
= NULL
;
4908 struct dcerpc_binding_handle
*b
= NULL
;
4909 struct policy_handle handle
;
4910 struct spoolss_DevmodeContainer devmode_ctr
;
4911 union spoolss_PrinterInfo info
;
4913 if (!str1
|| !str2
|| !p
) {
4917 memset((char *)&desc
,'\0',sizeof(desc
));
4919 p
= skip_string(param
,tpscnt
,p
);
4923 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4925 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4927 /* check it's a supported varient */
4928 if (strcmp(str1
,"zWrLh") != 0) {
4931 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4935 ZERO_STRUCT(handle
);
4937 status
= rpc_pipe_open_interface(conn
,
4940 conn
->sconn
->remote_address
,
4941 conn
->sconn
->msg_ctx
,
4943 if (!NT_STATUS_IS_OK(status
)) {
4944 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4945 nt_errstr(status
)));
4946 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4949 b
= cli
->binding_handle
;
4951 ZERO_STRUCT(devmode_ctr
);
4953 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4960 if (!NT_STATUS_IS_OK(status
)) {
4962 desc
.errcode
= NERR_DestNotFound
;
4966 if (!W_ERROR_IS_OK(werr
)) {
4968 desc
.errcode
= NERR_DestNotFound
;
4973 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4978 if (!W_ERROR_IS_OK(werr
)) {
4980 desc
.errcode
= NERR_DestNotFound
;
4986 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4991 desc
.buflen
= mdrcnt
;
4994 * Don't return data but need to get correct length
4995 * init_package will return wrong size if buflen=0
4997 desc
.buflen
= getlen(desc
.format
);
4998 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5000 if (init_package(&desc
,1,0)) {
5001 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5005 if (b
&& is_valid_policy_hnd(&handle
)) {
5006 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5009 *rdata_len
= desc
.usedlen
;
5012 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5016 SSVALS(*rparam
,0,desc
.errcode
);
5018 SSVAL(*rparam
,4,desc
.neededlen
);
5020 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5026 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5027 connection_struct
*conn
, uint64_t vuid
,
5028 char *param
, int tpscnt
,
5029 char *data
, int tdscnt
,
5030 int mdrcnt
,int mprcnt
,
5031 char **rdata
,char **rparam
,
5032 int *rdata_len
,int *rparam_len
)
5034 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5035 char *str2
= skip_string(param
,tpscnt
,str1
);
5036 char *p
= skip_string(param
,tpscnt
,str2
);
5040 struct pack_desc desc
;
5042 TALLOC_CTX
*mem_ctx
= talloc_tos();
5045 struct rpc_pipe_client
*cli
= NULL
;
5046 union spoolss_PrinterInfo
*info
;
5049 if (!str1
|| !str2
|| !p
) {
5053 memset((char *)&desc
,'\0',sizeof(desc
));
5055 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5057 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5059 /* check it's a supported varient */
5060 if (strcmp(str1
,"WrLeh") != 0) {
5063 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5069 status
= rpc_pipe_open_interface(conn
,
5072 conn
->sconn
->remote_address
,
5073 conn
->sconn
->msg_ctx
,
5075 if (!NT_STATUS_IS_OK(status
)) {
5076 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5077 nt_errstr(status
)));
5078 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5082 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5084 cli
->srv_name_slash
,
5089 if (!W_ERROR_IS_OK(werr
)) {
5090 desc
.errcode
= W_ERROR_V(werr
);
5092 desc
.errcode
= NERR_DestNotFound
;
5100 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5107 desc
.buflen
= mdrcnt
;
5108 if (init_package(&desc
,queuecnt
,0)) {
5111 for (i
= 0; i
< count
; i
++) {
5112 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5114 if (desc
.errcode
== NERR_Success
) {
5120 *rdata_len
= desc
.usedlen
;
5123 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5127 SSVALS(*rparam
,0,desc
.errcode
);
5129 SSVAL(*rparam
,4,succnt
);
5130 SSVAL(*rparam
,6,queuecnt
);
5132 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5137 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5138 connection_struct
*conn
, uint64_t vuid
,
5139 char *param
, int tpscnt
,
5140 char *data
, int tdscnt
,
5141 int mdrcnt
,int mprcnt
,
5142 char **rdata
,char **rparam
,
5143 int *rdata_len
,int *rparam_len
)
5145 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5146 char *str2
= skip_string(param
,tpscnt
,str1
);
5147 char *p
= skip_string(param
,tpscnt
,str2
);
5150 struct pack_desc desc
;
5152 if (!str1
|| !str2
|| !p
) {
5156 memset((char *)&desc
,'\0',sizeof(desc
));
5158 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5160 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5162 /* check it's a supported varient */
5163 if (strcmp(str1
,"WrLeh") != 0) {
5166 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5171 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5177 desc
.buflen
= mdrcnt
;
5178 if (init_package(&desc
,1,0)) {
5179 PACKS(&desc
,"B41","NULL");
5182 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5184 *rdata_len
= desc
.usedlen
;
5187 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5191 SSVALS(*rparam
,0,desc
.errcode
);
5193 SSVAL(*rparam
,4,succnt
);
5196 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5201 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5202 connection_struct
*conn
, uint64_t vuid
,
5203 char *param
, int tpscnt
,
5204 char *data
, int tdscnt
,
5205 int mdrcnt
,int mprcnt
,
5206 char **rdata
,char **rparam
,
5207 int *rdata_len
,int *rparam_len
)
5209 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5210 char *str2
= skip_string(param
,tpscnt
,str1
);
5211 char *p
= skip_string(param
,tpscnt
,str2
);
5214 struct pack_desc desc
;
5216 if (!str1
|| !str2
|| !p
) {
5219 memset((char *)&desc
,'\0',sizeof(desc
));
5221 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5223 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5225 /* check it's a supported varient */
5226 if (strcmp(str1
,"WrLeh") != 0) {
5229 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5234 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5240 desc
.buflen
= mdrcnt
;
5242 if (init_package(&desc
,1,0)) {
5243 PACKS(&desc
,"B13","lpd");
5246 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5248 *rdata_len
= desc
.usedlen
;
5251 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5255 SSVALS(*rparam
,0,desc
.errcode
);
5257 SSVAL(*rparam
,4,succnt
);
5260 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5265 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5266 connection_struct
*conn
, uint64_t vuid
,
5267 char *param
, int tpscnt
,
5268 char *data
, int tdscnt
,
5269 int mdrcnt
,int mprcnt
,
5270 char **rdata
,char **rparam
,
5271 int *rdata_len
,int *rparam_len
)
5273 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5274 char *str2
= skip_string(param
,tpscnt
,str1
);
5275 char *p
= skip_string(param
,tpscnt
,str2
);
5278 struct pack_desc desc
;
5280 if (!str1
|| !str2
|| !p
) {
5284 memset((char *)&desc
,'\0',sizeof(desc
));
5286 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5288 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5290 /* check it's a supported varient */
5291 if (strcmp(str1
,"WrLeh") != 0) {
5294 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5299 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5304 memset((char *)&desc
,'\0',sizeof(desc
));
5306 desc
.buflen
= mdrcnt
;
5308 if (init_package(&desc
,1,0)) {
5309 PACKS(&desc
,"B13","lp0");
5312 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5314 *rdata_len
= desc
.usedlen
;
5317 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5321 SSVALS(*rparam
,0,desc
.errcode
);
5323 SSVAL(*rparam
,4,succnt
);
5326 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5331 /****************************************************************************
5333 ****************************************************************************/
5335 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5336 connection_struct
*conn
, uint64_t vuid
,
5337 char *param
, int tpscnt
,
5338 char *data
, int tdscnt
,
5339 int mdrcnt
,int mprcnt
,
5340 char **rdata
,char **rparam
,
5341 int *rdata_len
,int *rparam_len
)
5344 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5345 char *str2
= skip_string(param
,tpscnt
,str1
);
5346 char *p
= skip_string(param
,tpscnt
,str2
);
5348 struct pack_desc desc
;
5351 TALLOC_CTX
*mem_ctx
= talloc_tos();
5354 struct rpc_pipe_client
*cli
= NULL
;
5355 struct dcerpc_binding_handle
*b
= NULL
;
5356 struct srvsvc_NetSessInfoCtr info_ctr
;
5357 uint32_t totalentries
, resume_handle
= 0;
5360 if (!str1
|| !str2
|| !p
) {
5366 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5368 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5369 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5370 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5372 /* check it's a supported varient */
5373 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5376 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5380 status
= rpc_pipe_open_interface(conn
,
5383 conn
->sconn
->remote_address
,
5384 conn
->sconn
->msg_ctx
,
5386 if (!NT_STATUS_IS_OK(status
)) {
5387 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5388 nt_errstr(status
)));
5389 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5392 b
= cli
->binding_handle
;
5395 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5396 if (info_ctr
.ctr
.ctr1
== NULL
) {
5397 desc
.errcode
= W_ERROR_V(WERR_NOMEM
);
5401 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5402 cli
->srv_name_slash
,
5406 (uint32_t)-1, /* max_buffer */
5410 if (!NT_STATUS_IS_OK(status
)) {
5411 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5412 nt_errstr(status
)));
5413 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5417 if (!W_ERROR_IS_OK(werr
)) {
5418 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5420 desc
.errcode
= W_ERROR_V(werr
);
5424 count
= info_ctr
.ctr
.ctr1
->count
;
5428 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5435 desc
.buflen
= mdrcnt
;
5437 if (!init_package(&desc
, count
,0)) {
5441 for(i
=0; i
< count
; i
++) {
5442 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5443 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5444 PACKI(&desc
, "W", 1); /* num conns */
5445 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5446 PACKI(&desc
, "W", 1); /* num users */
5447 PACKI(&desc
, "D", 0); /* session time */
5448 PACKI(&desc
, "D", 0); /* idle time */
5449 PACKI(&desc
, "D", 0); /* flags */
5450 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5453 *rdata_len
= desc
.usedlen
;
5456 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5460 SSVALS(*rparam
,0,desc
.errcode
);
5461 SSVAL(*rparam
,2,0); /* converter */
5462 SSVAL(*rparam
,4, count
); /* count */
5464 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5470 /****************************************************************************
5471 The buffer was too small.
5472 ****************************************************************************/
5474 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5475 connection_struct
*conn
,uint64_t vuid
, char *param
, char *data
,
5476 int mdrcnt
, int mprcnt
,
5477 char **rdata
, char **rparam
,
5478 int *rdata_len
, int *rparam_len
)
5480 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5481 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5488 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5490 DEBUG(3,("Supplied buffer too small in API command\n"));
5495 /****************************************************************************
5496 The request is not supported.
5497 ****************************************************************************/
5499 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5500 connection_struct
*conn
, uint64_t vuid
,
5501 char *param
, int tpscnt
,
5502 char *data
, int tdscnt
,
5503 int mdrcnt
, int mprcnt
,
5504 char **rdata
, char **rparam
,
5505 int *rdata_len
, int *rparam_len
)
5508 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5515 SSVAL(*rparam
,0,NERR_notsupported
);
5516 SSVAL(*rparam
,2,0); /* converter word */
5518 DEBUG(3,("Unsupported API command\n"));
5523 static const struct {
5526 bool (*fn
)(struct smbd_server_connection
*sconn
,
5527 connection_struct
*, uint64_t,
5530 int,int,char **,char **,int *,int *);
5531 bool auth_user
; /* Deny anonymous access? */
5532 } api_commands
[] = {
5533 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5534 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5535 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5536 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5537 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5538 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5539 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5540 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5541 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5542 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5543 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5544 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5545 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5546 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5547 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5548 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5549 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5550 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5551 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5552 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5553 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5554 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5555 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5556 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5557 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5558 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5559 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5560 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5561 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5562 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5563 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5564 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5565 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5566 {NULL
, -1, api_Unsupported
}
5567 /* The following RAP calls are not implemented by Samba:
5569 RAP_WFileEnum2 - anon not OK
5574 /****************************************************************************
5575 Handle remote api calls.
5576 ****************************************************************************/
5578 void api_reply(connection_struct
*conn
, uint64_t vuid
,
5579 struct smb_request
*req
,
5580 char *data
, char *params
,
5581 int tdscnt
, int tpscnt
,
5582 int mdrcnt
, int mprcnt
)
5586 char *rparam
= NULL
;
5587 const char *name1
= NULL
;
5588 const char *name2
= NULL
;
5595 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5596 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5601 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5604 api_command
= SVAL(params
,0);
5605 /* Is there a string at position params+2 ? */
5606 if (skip_string(params
,tpscnt
,params
+2)) {
5611 name2
= skip_string(params
,tpscnt
,params
+2);
5616 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5620 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5622 for (i
=0;api_commands
[i
].name
;i
++) {
5623 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5624 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5629 /* Check whether this api call can be done anonymously */
5631 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5632 struct user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5634 if (!user
|| security_session_user_level(user
->session_info
, NULL
) < SECURITY_USER
) {
5635 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5640 rdata
= (char *)SMB_MALLOC(1024);
5642 memset(rdata
,'\0',1024);
5645 rparam
= (char *)SMB_MALLOC(1024);
5647 memset(rparam
,'\0',1024);
5650 if(!rdata
|| !rparam
) {
5651 DEBUG(0,("api_reply: malloc fail !\n"));
5654 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5658 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5660 params
,tpscnt
, /* params + length */
5661 data
,tdscnt
, /* data + length */
5663 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5666 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5667 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5669 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5672 /* if we get False back then it's actually unsupported */
5674 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5676 tdscnt
,mdrcnt
,mprcnt
,
5677 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5680 /* If api_Unsupported returns false we can't return anything. */
5682 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5683 rdata
, rdata_len
, False
);