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
, uint16 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
, uint16 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(snum
));
115 *p_space_remaining
= 0;
118 buf
= talloc_sub_advanced(ctx
,
119 lp_servicename(SNUM(conn
)),
120 conn
->session_info
->unix_name
,
122 conn
->session_info
->utok
.gid
,
123 conn
->session_info
->sanitized_username
,
124 conn
->session_info
->info3
->base
.domain
.string
,
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(snum
));
169 buf
= talloc_sub_advanced(ctx
,
170 lp_servicename(SNUM(conn
)),
171 conn
->session_info
->unix_name
,
173 conn
->session_info
->utok
.gid
,
174 conn
->session_info
->sanitized_username
,
175 conn
->session_info
->info3
->base
.domain
.string
,
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((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
616 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
617 trim_string((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((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
, uint16 vuid
,
760 char *param
, int tpscnt
,
761 char *data
, int tdscnt
,
762 int mdrcnt
,int mprcnt
,
763 char **rdata
,char **rparam
,
764 int *rdata_len
,int *rparam_len
)
766 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
767 char *str2
= skip_string(param
,tpscnt
,str1
);
768 char *p
= skip_string(param
,tpscnt
,str2
);
773 struct pack_desc desc
;
776 WERROR werr
= WERR_OK
;
777 TALLOC_CTX
*mem_ctx
= talloc_tos();
779 struct rpc_pipe_client
*cli
= NULL
;
780 struct dcerpc_binding_handle
*b
= NULL
;
781 struct policy_handle handle
;
782 struct spoolss_DevmodeContainer devmode_ctr
;
783 union spoolss_DriverInfo driver_info
;
784 union spoolss_JobInfo
*job_info
= NULL
;
785 union spoolss_PrinterInfo printer_info
;
787 if (!str1
|| !str2
|| !p
) {
790 memset((char *)&desc
,'\0',sizeof(desc
));
792 p
= skip_string(param
,tpscnt
,p
);
796 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
797 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
798 /* str3 may be null here and is checked in check_printq_info(). */
800 /* remove any trailing username */
801 if ((p
= strchr_m(QueueName
,'%')))
804 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
806 /* check it's a supported varient */
807 if (!prefix_ok(str1
,"zWrLh"))
809 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
811 * Patch from Scott Moomaw <scott@bridgewater.edu>
812 * to return the 'invalid info level' error if an
813 * unknown level was requested.
817 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
821 SSVALS(*rparam
,0,ERRunknownlevel
);
829 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
830 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
834 status
= rpc_pipe_open_interface(conn
,
835 &ndr_table_spoolss
.syntax_id
,
837 &conn
->sconn
->client_id
,
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
, uint16 vuid
,
975 char *param
, int tpscnt
,
976 char *data
, int tdscnt
,
977 int mdrcnt
, int mprcnt
,
978 char **rdata
, char** rparam
,
979 int *rdata_len
, int *rparam_len
)
981 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
982 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
983 char *p
= skip_string(param
,tpscnt
,output_format1
);
984 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
985 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
987 struct pack_desc desc
;
988 int *subcntarr
= NULL
;
989 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
991 WERROR werr
= WERR_OK
;
992 TALLOC_CTX
*mem_ctx
= talloc_tos();
994 struct rpc_pipe_client
*cli
= NULL
;
995 struct dcerpc_binding_handle
*b
= NULL
;
996 struct spoolss_DevmodeContainer devmode_ctr
;
997 uint32_t num_printers
;
998 union spoolss_PrinterInfo
*printer_info
;
999 union spoolss_DriverInfo
*driver_info
;
1000 union spoolss_JobInfo
**job_info
;
1002 if (!param_format
|| !output_format1
|| !p
) {
1006 memset((char *)&desc
,'\0',sizeof(desc
));
1008 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1010 if (!prefix_ok(param_format
,"WrLeh")) {
1013 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1015 * Patch from Scott Moomaw <scott@bridgewater.edu>
1016 * to return the 'invalid info level' error if an
1017 * unknown level was requested.
1021 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1025 SSVALS(*rparam
,0,ERRunknownlevel
);
1031 status
= rpc_pipe_open_interface(conn
,
1032 &ndr_table_spoolss
.syntax_id
,
1034 &conn
->sconn
->client_id
,
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
) {
1162 SAFE_FREE(subcntarr
);
1164 *rdata_len
= desc
.usedlen
;
1166 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1170 SSVALS(*rparam
,0,desc
.errcode
);
1172 SSVAL(*rparam
,4,succnt
);
1173 SSVAL(*rparam
,6,queuecnt
);
1179 SAFE_FREE(subcntarr
);
1184 /****************************************************************************
1185 Get info level for a server list query.
1186 ****************************************************************************/
1188 static bool check_session_info(int uLevel
, char* id
)
1192 if (strcmp(id
,"B16") != 0) {
1197 if (strcmp(id
,"B16BBDz") != 0) {
1207 struct srv_info_struct
{
1215 /*******************************************************************
1216 Get server info lists from the files saved by nmbd. Return the
1218 ******************************************************************/
1220 static int get_session_info(uint32 servertype
,
1221 struct srv_info_struct
**servers
,
1227 bool local_list_only
;
1230 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1232 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1236 /* request for everything is code for request all servers */
1237 if (servertype
== SV_TYPE_ALL
) {
1238 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1241 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1243 DEBUG(4,("Servertype search: %8x\n",servertype
));
1245 for (i
=0;lines
[i
];i
++) {
1247 struct srv_info_struct
*s
;
1248 const char *ptr
= lines
[i
];
1250 TALLOC_CTX
*frame
= NULL
;
1257 if (count
== alloced
) {
1259 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1261 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1265 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1267 s
= &(*servers
)[count
];
1269 frame
= talloc_stackframe();
1271 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1275 fstrcpy(s
->name
, p
);
1278 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1284 s
->comment
[0] = '\0';
1285 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1289 fstrcpy(s
->comment
, p
);
1290 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1292 s
->domain
[0] = '\0';
1293 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1294 /* this allows us to cope with an old nmbd */
1295 fstrcpy(s
->domain
,lp_workgroup());
1297 fstrcpy(s
->domain
, p
);
1301 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1302 DEBUG(4,("r:host file "));
1306 /* Filter the servers/domains we return based on what was asked for. */
1308 /* Check to see if we are being asked for a local list only. */
1309 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1310 DEBUG(4,("r: local list only"));
1314 /* doesn't match up: don't want it */
1315 if (!(servertype
& s
->type
)) {
1316 DEBUG(4,("r:serv type "));
1320 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1321 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1322 DEBUG(4,("s: dom mismatch "));
1326 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1330 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1331 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1334 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1335 s
->name
, s
->type
, s
->comment
, s
->domain
));
1336 s
->server_added
= True
;
1339 DEBUG(4,("%20s %8x %25s %15s\n",
1340 s
->name
, s
->type
, s
->comment
, s
->domain
));
1348 /*******************************************************************
1349 Fill in a server info structure.
1350 ******************************************************************/
1352 static int fill_srv_info(struct srv_info_struct
*service
,
1353 int uLevel
, char **buf
, int *buflen
,
1354 char **stringbuf
, int *stringspace
, char *baseaddr
)
1377 len
= strlen(service
->comment
)+1;
1381 *buflen
= struct_len
;
1383 return struct_len
+ len
;
1388 if (*buflen
< struct_len
) {
1395 p2
= p
+ struct_len
;
1396 l2
= *buflen
- struct_len
;
1404 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1408 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1409 SIVAL(p
,18,service
->type
);
1410 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1411 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1416 *buf
= p
+ struct_len
;
1417 *buflen
-= struct_len
;
1428 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1430 return StrCaseCmp(s1
->name
,s2
->name
);
1433 /****************************************************************************
1434 View list of servers available (or possibly domains). The info is
1435 extracted from lists saved by nmbd on the local host.
1436 ****************************************************************************/
1438 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1439 connection_struct
*conn
, uint16 vuid
,
1440 char *param
, int tpscnt
,
1441 char *data
, int tdscnt
,
1442 int mdrcnt
, int mprcnt
, char **rdata
,
1443 char **rparam
, int *rdata_len
, int *rparam_len
)
1445 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1446 char *str2
= skip_string(param
,tpscnt
,str1
);
1447 char *p
= skip_string(param
,tpscnt
,str2
);
1448 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1449 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1450 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1452 int data_len
, fixed_len
, string_len
;
1453 int f_len
= 0, s_len
= 0;
1454 struct srv_info_struct
*servers
=NULL
;
1455 int counted
=0,total
=0;
1458 bool domain_request
;
1461 if (!str1
|| !str2
|| !p
) {
1465 /* If someone sets all the bits they don't really mean to set
1466 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1469 if (servertype
== SV_TYPE_ALL
) {
1470 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1473 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1474 any other bit (they may just set this bit on its own) they
1475 want all the locally seen servers. However this bit can be
1476 set on its own so set the requested servers to be
1477 ALL - DOMAIN_ENUM. */
1479 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1480 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1483 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1484 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1488 if (!prefix_ok(str1
,"WrLehD")) {
1491 if (!check_session_info(uLevel
,str2
)) {
1495 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1496 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1497 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1499 if (strcmp(str1
, "WrLehDz") == 0) {
1500 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1503 pull_ascii_fstring(domain
, p
);
1505 fstrcpy(domain
, lp_workgroup());
1508 DEBUG(4, ("domain [%s]\n", domain
));
1510 if (lp_browse_list()) {
1511 total
= get_session_info(servertype
,&servers
,domain
);
1514 data_len
= fixed_len
= string_len
= 0;
1517 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1520 char *lastname
=NULL
;
1522 for (i
=0;i
<total
;i
++) {
1523 struct srv_info_struct
*s
= &servers
[i
];
1525 if (lastname
&& strequal(lastname
,s
->name
)) {
1529 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1530 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1531 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1533 if (data_len
< buf_len
) {
1536 string_len
+= s_len
;
1543 *rdata_len
= fixed_len
+ string_len
;
1544 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1549 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1555 char *lastname
=NULL
;
1556 int count2
= counted
;
1558 for (i
= 0; i
< total
&& count2
;i
++) {
1559 struct srv_info_struct
*s
= &servers
[i
];
1561 if (lastname
&& strequal(lastname
,s
->name
)) {
1565 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1566 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1567 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1573 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1577 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1579 SSVAL(*rparam
,4,counted
);
1580 SSVAL(*rparam
,6,counted
+missed
);
1584 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1585 domain
,uLevel
,counted
,counted
+missed
));
1590 static int srv_name_match(const char *n1
, const char *n2
)
1593 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1595 * In Windows, FirstNameToReturn need not be an exact match:
1596 * the server will return a list of servers that exist on
1597 * the network greater than or equal to the FirstNameToReturn.
1599 int ret
= StrCaseCmp(n1
, n2
);
1608 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1609 connection_struct
*conn
, uint16 vuid
,
1610 char *param
, int tpscnt
,
1611 char *data
, int tdscnt
,
1612 int mdrcnt
, int mprcnt
, char **rdata
,
1613 char **rparam
, int *rdata_len
, int *rparam_len
)
1615 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1616 char *str2
= skip_string(param
,tpscnt
,str1
);
1617 char *p
= skip_string(param
,tpscnt
,str2
);
1618 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1619 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1620 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1622 int data_len
, fixed_len
, string_len
;
1623 int f_len
= 0, s_len
= 0;
1624 struct srv_info_struct
*servers
=NULL
;
1625 int counted
=0,first
=0,total
=0;
1629 bool domain_request
;
1632 if (!str1
|| !str2
|| !p
) {
1636 /* If someone sets all the bits they don't really mean to set
1637 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1640 if (servertype
== SV_TYPE_ALL
) {
1641 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1644 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1645 any other bit (they may just set this bit on its own) they
1646 want all the locally seen servers. However this bit can be
1647 set on its own so set the requested servers to be
1648 ALL - DOMAIN_ENUM. */
1650 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1651 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1654 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1655 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1659 if (strcmp(str1
, "WrLehDzz") != 0) {
1662 if (!check_session_info(uLevel
,str2
)) {
1666 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1667 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1668 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1670 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1673 pull_ascii_fstring(domain
, p
);
1674 if (domain
[0] == '\0') {
1675 fstrcpy(domain
, lp_workgroup());
1677 p
= skip_string(param
,tpscnt
,p
);
1678 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1681 pull_ascii_fstring(first_name
, p
);
1683 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1684 domain
, first_name
));
1686 if (lp_browse_list()) {
1687 total
= get_session_info(servertype
,&servers
,domain
);
1690 data_len
= fixed_len
= string_len
= 0;
1693 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1695 if (first_name
[0] != '\0') {
1696 struct srv_info_struct
*first_server
= NULL
;
1698 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1699 srv_name_match
, first_server
);
1701 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1703 * The binary search may not find the exact match
1704 * so we need to search backward to find the first match
1706 * This implements the strange matching windows
1707 * implements. (see the comment in srv_name_match().
1711 ret
= StrCaseCmp(first_name
,
1712 servers
[first
-1].name
);
1719 /* we should return no entries */
1725 char *lastname
=NULL
;
1727 for (i
=first
;i
<total
;i
++) {
1728 struct srv_info_struct
*s
= &servers
[i
];
1730 if (lastname
&& strequal(lastname
,s
->name
)) {
1734 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1735 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1736 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1738 if (data_len
< buf_len
) {
1741 string_len
+= s_len
;
1748 *rdata_len
= fixed_len
+ string_len
;
1749 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1754 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1760 char *lastname
=NULL
;
1761 int count2
= counted
;
1763 for (i
= first
; i
< total
&& count2
;i
++) {
1764 struct srv_info_struct
*s
= &servers
[i
];
1766 if (lastname
&& strequal(lastname
,s
->name
)) {
1770 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1771 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1772 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1778 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1782 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1784 SSVAL(*rparam
,4,counted
);
1785 SSVAL(*rparam
,6,counted
+missed
);
1787 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1788 domain
,uLevel
,first
,first_name
,
1789 first
< total
? servers
[first
].name
: "",
1790 counted
,counted
+missed
));
1797 /****************************************************************************
1798 command 0x34 - suspected of being a "Lookup Names" stub api
1799 ****************************************************************************/
1801 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1802 connection_struct
*conn
, uint16 vuid
,
1803 char *param
, int tpscnt
,
1804 char *data
, int tdscnt
,
1805 int mdrcnt
, int mprcnt
, char **rdata
,
1806 char **rparam
, int *rdata_len
, int *rparam_len
)
1808 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1809 char *str2
= skip_string(param
,tpscnt
,str1
);
1810 char *p
= skip_string(param
,tpscnt
,str2
);
1811 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1812 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1816 if (!str1
|| !str2
|| !p
) {
1820 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1821 str1
, str2
, p
, uLevel
, buf_len
));
1823 if (!prefix_ok(str1
,"zWrLeh")) {
1830 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1835 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1837 SSVAL(*rparam
,4,counted
);
1838 SSVAL(*rparam
,6,counted
+missed
);
1843 /****************************************************************************
1844 get info about a share
1845 ****************************************************************************/
1847 static bool check_share_info(int uLevel
, char* id
)
1851 if (strcmp(id
,"B13") != 0) {
1856 /* Level-2 descriptor is allowed (and ignored) */
1857 if (strcmp(id
,"B13BWz") != 0 &&
1858 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1863 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1868 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1878 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1879 char** buf
, int* buflen
,
1880 char** stringbuf
, int* stringspace
, char* baseaddr
)
1909 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1912 len
+= strlen(lp_pathname(snum
)) + 1;
1915 *buflen
= struct_len
;
1920 return struct_len
+ len
;
1925 if ((*buflen
) < struct_len
) {
1933 p2
= p
+ struct_len
;
1934 l2
= (*buflen
) - struct_len
;
1941 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1947 type
= STYPE_DISKTREE
;
1948 if (lp_print_ok(snum
)) {
1949 type
= STYPE_PRINTQ
;
1951 if (strequal("IPC",lp_fstype(snum
))) {
1954 SSVAL(p
,14,type
); /* device type */
1955 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1956 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1960 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1961 SSVALS(p
,22,-1); /* max uses */
1962 SSVAL(p
,24,1); /* current uses */
1963 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1964 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1965 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1969 memset(p
+40,0,SHPWLEN
+2);
1980 (*buf
) = p
+ struct_len
;
1981 (*buflen
) -= struct_len
;
1983 (*stringspace
) = l2
;
1992 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
1993 connection_struct
*conn
,uint16 vuid
,
1994 char *param
, int tpscnt
,
1995 char *data
, int tdscnt
,
1996 int mdrcnt
,int mprcnt
,
1997 char **rdata
,char **rparam
,
1998 int *rdata_len
,int *rparam_len
)
2000 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2001 char *str2
= skip_string(param
,tpscnt
,str1
);
2002 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2003 char *netname
= NULL
;
2004 char *p
= skip_string(param
,tpscnt
,netname
);
2005 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2008 if (!str1
|| !str2
|| !netname
|| !p
) {
2012 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2013 if (snum
< 0 || !netname
) {
2017 /* check it's a supported varient */
2018 if (!prefix_ok(str1
,"zWrLh")) {
2021 if (!check_share_info(uLevel
,str2
)) {
2025 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2030 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2031 if (*rdata_len
< 0) {
2036 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2040 SSVAL(*rparam
,0,NERR_Success
);
2041 SSVAL(*rparam
,2,0); /* converter word */
2042 SSVAL(*rparam
,4,*rdata_len
);
2047 /****************************************************************************
2048 View the list of available shares.
2050 This function is the server side of the NetShareEnum() RAP call.
2051 It fills the return buffer with share names and share comments.
2052 Note that the return buffer normally (in all known cases) allows only
2053 twelve byte strings for share names (plus one for a nul terminator).
2054 Share names longer than 12 bytes must be skipped.
2055 ****************************************************************************/
2057 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2058 connection_struct
*conn
, uint16 vuid
,
2059 char *param
, int tpscnt
,
2060 char *data
, int tdscnt
,
2068 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2069 char *str2
= skip_string(param
,tpscnt
,str1
);
2070 char *p
= skip_string(param
,tpscnt
,str2
);
2071 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2072 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2075 int total
=0,counted
=0;
2076 bool missed
= False
;
2078 int data_len
, fixed_len
, string_len
;
2079 int f_len
= 0, s_len
= 0;
2081 if (!str1
|| !str2
|| !p
) {
2085 if (!prefix_ok(str1
,"WrLeh")) {
2088 if (!check_share_info(uLevel
,str2
)) {
2092 /* Ensure all the usershares are loaded. */
2094 load_registry_shares();
2095 count
= load_usershare_shares();
2098 data_len
= fixed_len
= string_len
= 0;
2099 for (i
=0;i
<count
;i
++) {
2100 fstring servicename_dos
;
2101 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2104 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2105 /* Maximum name length = 13. */
2106 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2108 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2109 if (data_len
< buf_len
) {
2112 string_len
+= s_len
;
2119 *rdata_len
= fixed_len
+ string_len
;
2120 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2125 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2130 for( i
= 0; i
< count
; i
++ ) {
2131 fstring servicename_dos
;
2132 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2136 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2137 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2138 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2145 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2149 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2151 SSVAL(*rparam
,4,counted
);
2152 SSVAL(*rparam
,6,total
);
2154 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2155 counted
,total
,uLevel
,
2156 buf_len
,*rdata_len
,mdrcnt
));
2161 /****************************************************************************
2163 ****************************************************************************/
2165 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2166 connection_struct
*conn
,uint16 vuid
,
2167 char *param
, int tpscnt
,
2168 char *data
, int tdscnt
,
2169 int mdrcnt
,int mprcnt
,
2170 char **rdata
,char **rparam
,
2171 int *rdata_len
,int *rparam_len
)
2173 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2174 char *str2
= skip_string(param
,tpscnt
,str1
);
2175 char *p
= skip_string(param
,tpscnt
,str2
);
2176 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2179 char *pathname
= NULL
;
2180 unsigned int offset
;
2182 size_t converted_size
;
2184 WERROR werr
= WERR_OK
;
2185 TALLOC_CTX
*mem_ctx
= talloc_tos();
2187 struct rpc_pipe_client
*cli
= NULL
;
2188 union srvsvc_NetShareInfo info
;
2189 struct srvsvc_NetShareInfo2 info2
;
2190 struct dcerpc_binding_handle
*b
;
2192 if (!str1
|| !str2
|| !p
) {
2196 /* check it's a supported varient */
2197 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2200 if (!check_share_info(uLevel
,str2
)) {
2207 /* Do we have a string ? */
2208 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2211 pull_ascii_fstring(sharename
,data
);
2217 /* only support disk share adds */
2218 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2222 offset
= IVAL(data
, 16);
2223 if (offset
>= mdrcnt
) {
2224 res
= ERRinvalidparam
;
2228 /* Do we have a string ? */
2229 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2232 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2234 offset
= IVAL(data
, 26);
2236 if (offset
>= mdrcnt
) {
2237 res
= ERRinvalidparam
;
2241 /* Do we have a string ? */
2242 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2246 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2247 offset
? (data
+offset
) : "", &converted_size
))
2249 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2257 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2259 &conn
->sconn
->client_id
,
2260 conn
->sconn
->msg_ctx
,
2262 if (!NT_STATUS_IS_OK(status
)) {
2263 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2264 nt_errstr(status
)));
2265 res
= W_ERROR_V(ntstatus_to_werror(status
));
2269 b
= cli
->binding_handle
;
2271 info2
.name
= sharename
;
2272 info2
.type
= STYPE_DISKTREE
;
2273 info2
.comment
= comment
;
2274 info2
.permissions
= 0;
2275 info2
.max_users
= 0;
2276 info2
.current_users
= 0;
2277 info2
.path
= pathname
;
2278 info2
.password
= NULL
;
2280 info
.info2
= &info2
;
2282 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2283 cli
->srv_name_slash
,
2288 if (!NT_STATUS_IS_OK(status
)) {
2289 res
= W_ERROR_V(ntstatus_to_werror(status
));
2292 if (!W_ERROR_IS_OK(werr
)) {
2293 res
= W_ERROR_V(werr
);
2298 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2302 SSVAL(*rparam
,0,NERR_Success
);
2303 SSVAL(*rparam
,2,0); /* converter word */
2304 SSVAL(*rparam
,4,*rdata_len
);
2312 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2317 SSVAL(*rparam
,0,res
);
2322 /****************************************************************************
2323 view list of groups available
2324 ****************************************************************************/
2326 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2327 connection_struct
*conn
,uint16 vuid
,
2328 char *param
, int tpscnt
,
2329 char *data
, int tdscnt
,
2330 int mdrcnt
,int mprcnt
,
2331 char **rdata
,char **rparam
,
2332 int *rdata_len
,int *rparam_len
)
2336 int resume_context
, cli_buf_size
;
2337 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2338 char *str2
= skip_string(param
,tpscnt
,str1
);
2339 char *p
= skip_string(param
,tpscnt
,str2
);
2341 uint32_t num_groups
;
2342 uint32_t resume_handle
;
2343 struct rpc_pipe_client
*samr_pipe
;
2344 struct policy_handle samr_handle
, domain_handle
;
2345 NTSTATUS status
, result
;
2346 struct dcerpc_binding_handle
*b
;
2348 if (!str1
|| !str2
|| !p
) {
2352 if (strcmp(str1
,"WrLeh") != 0) {
2357 * W-> resume context (number of users to skip)
2358 * r -> return parameter pointer to receive buffer
2359 * L -> length of receive buffer
2360 * e -> return parameter number of entries
2361 * h -> return parameter total number of users
2364 if (strcmp("B21",str2
) != 0) {
2368 status
= rpc_pipe_open_interface(
2369 talloc_tos(), &ndr_table_samr
.syntax_id
,
2370 conn
->session_info
, &conn
->sconn
->client_id
,
2371 conn
->sconn
->msg_ctx
, &samr_pipe
);
2372 if (!NT_STATUS_IS_OK(status
)) {
2373 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2374 nt_errstr(status
)));
2378 b
= samr_pipe
->binding_handle
;
2380 status
= dcerpc_samr_Connect2(b
, talloc_tos(), global_myname(),
2381 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2383 if (!NT_STATUS_IS_OK(status
)) {
2384 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2385 nt_errstr(status
)));
2388 if (!NT_STATUS_IS_OK(result
)) {
2389 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2390 nt_errstr(result
)));
2394 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2395 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2396 get_global_sam_sid(), &domain_handle
,
2398 if (!NT_STATUS_IS_OK(status
)) {
2399 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2400 nt_errstr(status
)));
2401 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2404 if (!NT_STATUS_IS_OK(result
)) {
2405 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2406 nt_errstr(result
)));
2407 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2411 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2412 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2413 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2414 "%d\n", resume_context
, cli_buf_size
));
2416 *rdata_len
= cli_buf_size
;
2417 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2424 errflags
= NERR_Success
;
2429 struct samr_SamArray
*sam_entries
;
2430 uint32_t num_entries
;
2432 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2438 if (!NT_STATUS_IS_OK(status
)) {
2439 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2440 "%s\n", nt_errstr(status
)));
2443 if (!NT_STATUS_IS_OK(result
)) {
2445 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2446 "%s\n", nt_errstr(result
)));
2450 if (num_entries
== 0) {
2451 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2452 "no entries -- done\n"));
2456 for(i
=0; i
<num_entries
; i
++) {
2459 name
= sam_entries
->entries
[i
].name
.string
;
2461 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2462 /* set overflow error */
2463 DEBUG(3,("overflow on entry %d group %s\n", i
,
2469 /* truncate the name at 21 chars. */
2471 strlcpy(p
, name
, 21);
2472 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2474 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2479 if (errflags
!= NERR_Success
) {
2483 TALLOC_FREE(sam_entries
);
2486 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2487 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2489 *rdata_len
= PTR_DIFF(p
,*rdata
);
2492 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2496 SSVAL(*rparam
, 0, errflags
);
2497 SSVAL(*rparam
, 2, 0); /* converter word */
2498 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2499 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2504 /*******************************************************************
2505 Get groups that a user is a member of.
2506 ******************************************************************/
2508 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2509 connection_struct
*conn
,uint16 vuid
,
2510 char *param
, int tpscnt
,
2511 char *data
, int tdscnt
,
2512 int mdrcnt
,int mprcnt
,
2513 char **rdata
,char **rparam
,
2514 int *rdata_len
,int *rparam_len
)
2516 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2517 char *str2
= skip_string(param
,tpscnt
,str1
);
2518 char *UserName
= skip_string(param
,tpscnt
,str2
);
2519 char *p
= skip_string(param
,tpscnt
,UserName
);
2520 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2521 const char *level_string
;
2527 struct rpc_pipe_client
*samr_pipe
;
2528 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2529 struct lsa_String name
;
2530 struct lsa_Strings names
;
2531 struct samr_Ids type
, rid
;
2532 struct samr_RidWithAttributeArray
*rids
;
2533 NTSTATUS status
, result
;
2534 struct dcerpc_binding_handle
*b
;
2536 if (!str1
|| !str2
|| !UserName
|| !p
) {
2541 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2546 /* check it's a supported varient */
2548 if ( strcmp(str1
,"zWrLeh") != 0 )
2553 level_string
= "B21";
2559 if (strcmp(level_string
,str2
) != 0)
2562 *rdata_len
= mdrcnt
+ 1024;
2563 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2568 SSVAL(*rparam
,0,NERR_Success
);
2569 SSVAL(*rparam
,2,0); /* converter word */
2572 endp
= *rdata
+ *rdata_len
;
2574 status
= rpc_pipe_open_interface(
2575 talloc_tos(), &ndr_table_samr
.syntax_id
,
2576 conn
->session_info
, &conn
->sconn
->client_id
,
2577 conn
->sconn
->msg_ctx
, &samr_pipe
);
2578 if (!NT_STATUS_IS_OK(status
)) {
2579 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2580 nt_errstr(status
)));
2584 b
= samr_pipe
->binding_handle
;
2586 status
= dcerpc_samr_Connect2(b
, talloc_tos(), global_myname(),
2587 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2589 if (!NT_STATUS_IS_OK(status
)) {
2590 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2591 nt_errstr(status
)));
2594 if (!NT_STATUS_IS_OK(result
)) {
2595 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2596 nt_errstr(result
)));
2600 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2601 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2602 get_global_sam_sid(), &domain_handle
,
2604 if (!NT_STATUS_IS_OK(status
)) {
2605 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2606 nt_errstr(status
)));
2609 if (!NT_STATUS_IS_OK(result
)) {
2610 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2611 nt_errstr(result
)));
2615 name
.string
= UserName
;
2617 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2618 &domain_handle
, 1, &name
,
2621 if (!NT_STATUS_IS_OK(status
)) {
2622 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2623 nt_errstr(status
)));
2626 if (!NT_STATUS_IS_OK(result
)) {
2627 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2628 nt_errstr(result
)));
2632 if (type
.ids
[0] != SID_NAME_USER
) {
2633 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2634 sid_type_lookup(type
.ids
[0])));
2638 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2640 SAMR_USER_ACCESS_GET_GROUPS
,
2641 rid
.ids
[0], &user_handle
,
2643 if (!NT_STATUS_IS_OK(status
)) {
2644 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2645 nt_errstr(status
)));
2648 if (!NT_STATUS_IS_OK(result
)) {
2649 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2650 nt_errstr(result
)));
2654 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2655 &user_handle
, &rids
,
2657 if (!NT_STATUS_IS_OK(status
)) {
2658 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2659 nt_errstr(status
)));
2662 if (!NT_STATUS_IS_OK(result
)) {
2663 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2664 nt_errstr(result
)));
2668 for (i
=0; i
<rids
->count
; i
++) {
2670 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2672 1, &rids
->rids
[i
].rid
,
2675 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2676 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2682 *rdata_len
= PTR_DIFF(p
,*rdata
);
2684 SSVAL(*rparam
,4,count
); /* is this right?? */
2685 SSVAL(*rparam
,6,count
); /* is this right?? */
2690 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2692 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2694 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2699 /*******************************************************************
2701 ******************************************************************/
2703 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2704 connection_struct
*conn
, uint16 vuid
,
2705 char *param
, int tpscnt
,
2706 char *data
, int tdscnt
,
2707 int mdrcnt
,int mprcnt
,
2708 char **rdata
,char **rparam
,
2709 int *rdata_len
,int *rparam_len
)
2714 int i
, resume_context
, cli_buf_size
;
2715 uint32_t resume_handle
;
2717 struct rpc_pipe_client
*samr_pipe
;
2718 struct policy_handle samr_handle
, domain_handle
;
2719 NTSTATUS status
, result
;
2721 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2722 char *str2
= skip_string(param
,tpscnt
,str1
);
2723 char *p
= skip_string(param
,tpscnt
,str2
);
2726 struct dcerpc_binding_handle
*b
;
2728 if (!str1
|| !str2
|| !p
) {
2732 if (strcmp(str1
,"WrLeh") != 0)
2735 * W-> resume context (number of users to skip)
2736 * r -> return parameter pointer to receive buffer
2737 * L -> length of receive buffer
2738 * e -> return parameter number of entries
2739 * h -> return parameter total number of users
2742 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2743 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2744 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2745 resume_context
, cli_buf_size
));
2748 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2753 /* check it's a supported varient */
2754 if (strcmp("B21",str2
) != 0)
2757 *rdata_len
= cli_buf_size
;
2758 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2764 endp
= *rdata
+ *rdata_len
;
2766 status
= rpc_pipe_open_interface(
2767 talloc_tos(), &ndr_table_samr
.syntax_id
,
2768 conn
->session_info
, &conn
->sconn
->client_id
,
2769 conn
->sconn
->msg_ctx
, &samr_pipe
);
2770 if (!NT_STATUS_IS_OK(status
)) {
2771 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2772 nt_errstr(status
)));
2776 b
= samr_pipe
->binding_handle
;
2778 status
= dcerpc_samr_Connect2(b
, talloc_tos(), global_myname(),
2779 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2781 if (!NT_STATUS_IS_OK(status
)) {
2782 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2783 nt_errstr(status
)));
2786 if (!NT_STATUS_IS_OK(result
)) {
2787 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2788 nt_errstr(result
)));
2792 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2793 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2794 get_global_sam_sid(), &domain_handle
,
2796 if (!NT_STATUS_IS_OK(status
)) {
2797 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2798 nt_errstr(status
)));
2799 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2802 if (!NT_STATUS_IS_OK(result
)) {
2803 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2804 nt_errstr(result
)));
2805 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2809 errflags
=NERR_Success
;
2814 struct samr_SamArray
*sam_entries
;
2815 uint32_t num_entries
;
2817 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2824 if (!NT_STATUS_IS_OK(status
)) {
2825 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2826 "%s\n", nt_errstr(status
)));
2829 if (!NT_STATUS_IS_OK(result
)) {
2830 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2831 "%s\n", nt_errstr(result
)));
2835 if (num_entries
== 0) {
2836 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2837 "no entries -- done\n"));
2841 for (i
=0; i
<num_entries
; i
++) {
2844 name
= sam_entries
->entries
[i
].name
.string
;
2846 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2847 &&(strlen(name
)<=21)) {
2848 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2849 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2850 "username %s\n",count_sent
,p
));
2854 /* set overflow error */
2855 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2856 "username %s\n",count_sent
,name
));
2862 if (errflags
!= NERR_Success
) {
2866 TALLOC_FREE(sam_entries
);
2869 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2870 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2872 *rdata_len
= PTR_DIFF(p
,*rdata
);
2874 SSVAL(*rparam
,0,errflags
);
2875 SSVAL(*rparam
,2,0); /* converter word */
2876 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2877 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2882 /****************************************************************************
2883 Get the time of day info.
2884 ****************************************************************************/
2886 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2887 connection_struct
*conn
,uint16 vuid
,
2888 char *param
, int tpscnt
,
2889 char *data
, int tdscnt
,
2890 int mdrcnt
,int mprcnt
,
2891 char **rdata
,char **rparam
,
2892 int *rdata_len
,int *rparam_len
)
2895 time_t unixdate
= time(NULL
);
2899 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2905 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2910 SSVAL(*rparam
,0,NERR_Success
);
2911 SSVAL(*rparam
,2,0); /* converter word */
2915 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2916 by NT in a "net time" operation,
2917 it seems to ignore the one below */
2919 /* the client expects to get localtime, not GMT, in this bit
2920 (I think, this needs testing) */
2921 t
= localtime(&unixdate
);
2926 SIVAL(p
,4,0); /* msecs ? */
2927 SCVAL(p
,8,t
->tm_hour
);
2928 SCVAL(p
,9,t
->tm_min
);
2929 SCVAL(p
,10,t
->tm_sec
);
2930 SCVAL(p
,11,0); /* hundredths of seconds */
2931 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2932 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2933 SCVAL(p
,16,t
->tm_mday
);
2934 SCVAL(p
,17,t
->tm_mon
+ 1);
2935 SSVAL(p
,18,1900+t
->tm_year
);
2936 SCVAL(p
,20,t
->tm_wday
);
2941 /****************************************************************************
2942 Set the user password.
2943 *****************************************************************************/
2945 static bool api_SetUserPassword(struct smbd_server_connection
*sconn
,
2946 connection_struct
*conn
,uint16 vuid
,
2947 char *param
, int tpscnt
,
2948 char *data
, int tdscnt
,
2949 int mdrcnt
,int mprcnt
,
2950 char **rdata
,char **rparam
,
2951 int *rdata_len
,int *rparam_len
)
2953 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2956 fstring pass1
,pass2
;
2957 TALLOC_CTX
*mem_ctx
= talloc_tos();
2958 NTSTATUS status
, result
;
2959 struct rpc_pipe_client
*cli
= NULL
;
2960 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2961 struct lsa_String domain_name
;
2962 struct dom_sid2
*domain_sid
;
2963 struct lsa_String names
;
2964 struct samr_Ids rids
;
2965 struct samr_Ids types
;
2966 struct samr_Password old_lm_hash
;
2967 struct samr_Password new_lm_hash
;
2968 int errcode
= NERR_badpass
;
2972 struct dcerpc_binding_handle
*b
= NULL
;
2974 /* Skip 2 strings. */
2975 p
= skip_string(param
,tpscnt
,np
);
2976 p
= skip_string(param
,tpscnt
,p
);
2982 /* Do we have a string ? */
2983 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2986 pull_ascii_fstring(user
,p
);
2988 p
= skip_string(param
,tpscnt
,p
);
2993 memset(pass1
,'\0',sizeof(pass1
));
2994 memset(pass2
,'\0',sizeof(pass2
));
2996 * We use 31 here not 32 as we're checking
2997 * the last byte we want to access is safe.
2999 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
3003 memcpy(pass2
,p
+16,16);
3005 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
3006 if (encrypted
== -1) {
3007 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3011 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
3012 if (min_pwd_length
== -1) {
3013 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3018 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3025 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
3026 user
, encrypted
, min_pwd_length
));
3028 ZERO_STRUCT(connect_handle
);
3029 ZERO_STRUCT(domain_handle
);
3030 ZERO_STRUCT(user_handle
);
3032 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
.syntax_id
,
3034 &conn
->sconn
->client_id
,
3035 conn
->sconn
->msg_ctx
,
3037 if (!NT_STATUS_IS_OK(status
)) {
3038 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
3039 nt_errstr(status
)));
3040 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3044 b
= cli
->binding_handle
;
3046 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
3048 SAMR_ACCESS_CONNECT_TO_SERVER
|
3049 SAMR_ACCESS_ENUM_DOMAINS
|
3050 SAMR_ACCESS_LOOKUP_DOMAIN
,
3053 if (!NT_STATUS_IS_OK(status
)) {
3054 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3057 if (!NT_STATUS_IS_OK(result
)) {
3058 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3062 init_lsa_String(&domain_name
, get_global_sam_name());
3064 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
3069 if (!NT_STATUS_IS_OK(status
)) {
3070 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3073 if (!NT_STATUS_IS_OK(result
)) {
3074 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3078 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
3080 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
3084 if (!NT_STATUS_IS_OK(status
)) {
3085 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3088 if (!NT_STATUS_IS_OK(result
)) {
3089 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3093 init_lsa_String(&names
, user
);
3095 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
3102 if (!NT_STATUS_IS_OK(status
)) {
3103 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3106 if (!NT_STATUS_IS_OK(result
)) {
3107 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3111 if (rids
.count
!= 1) {
3112 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
3115 if (rids
.count
!= types
.count
) {
3116 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3119 if (types
.ids
[0] != SID_NAME_USER
) {
3120 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3126 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
3128 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
3132 if (!NT_STATUS_IS_OK(status
)) {
3133 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3136 if (!NT_STATUS_IS_OK(result
)) {
3137 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3141 if (encrypted
== 0) {
3142 E_deshash(pass1
, old_lm_hash
.hash
);
3143 E_deshash(pass2
, new_lm_hash
.hash
);
3145 ZERO_STRUCT(old_lm_hash
);
3146 ZERO_STRUCT(new_lm_hash
);
3147 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
3148 memcpy(new_lm_hash
.hash
, pass1
, MIN(strlen(pass2
), 16));
3151 status
= dcerpc_samr_ChangePasswordUser(b
, mem_ctx
,
3153 true, /* lm_present */
3156 false, /* nt_present */
3157 NULL
, /* old_nt_crypted */
3158 NULL
, /* new_nt_crypted */
3159 false, /* cross1_present */
3160 NULL
, /* nt_cross */
3161 false, /* cross2_present */
3162 NULL
, /* lm_cross */
3164 if (!NT_STATUS_IS_OK(status
)) {
3165 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3168 if (!NT_STATUS_IS_OK(result
)) {
3169 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3173 errcode
= NERR_Success
;
3176 if (b
&& is_valid_policy_hnd(&user_handle
)) {
3177 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
3179 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
3180 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
3182 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
3183 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
3186 memset((char *)pass1
,'\0',sizeof(fstring
));
3187 memset((char *)pass2
,'\0',sizeof(fstring
));
3189 SSVAL(*rparam
,0,errcode
);
3190 SSVAL(*rparam
,2,0); /* converter word */
3194 /****************************************************************************
3195 Set the user password (SamOEM version - gets plaintext).
3196 ****************************************************************************/
3198 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3199 connection_struct
*conn
,uint16 vuid
,
3200 char *param
, int tpscnt
,
3201 char *data
, int tdscnt
,
3202 int mdrcnt
,int mprcnt
,
3203 char **rdata
,char **rparam
,
3204 int *rdata_len
,int *rparam_len
)
3207 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3209 TALLOC_CTX
*mem_ctx
= talloc_tos();
3210 NTSTATUS status
, result
;
3211 struct rpc_pipe_client
*cli
= NULL
;
3212 struct lsa_AsciiString server
, account
;
3213 struct samr_CryptPassword password
;
3214 struct samr_Password hash
;
3215 int errcode
= NERR_badpass
;
3217 struct dcerpc_binding_handle
*b
;
3220 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3230 SSVAL(*rparam
,0,NERR_badpass
);
3233 * Check the parameter definition is correct.
3236 /* Do we have a string ? */
3237 if (skip_string(param
,tpscnt
,p
) == 0) {
3240 if(!strequal(p
, "zsT")) {
3241 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3244 p
= skip_string(param
, tpscnt
, p
);
3249 /* Do we have a string ? */
3250 if (skip_string(param
,tpscnt
,p
) == 0) {
3253 if(!strequal(p
, "B516B16")) {
3254 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3257 p
= skip_string(param
,tpscnt
,p
);
3261 /* Do we have a string ? */
3262 if (skip_string(param
,tpscnt
,p
) == 0) {
3265 p
+= pull_ascii_fstring(user
,p
);
3267 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3269 if (tdscnt
!= 532) {
3270 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3274 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3275 if (bufsize
!= 532) {
3276 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3280 memcpy(password
.data
, data
, 516);
3281 memcpy(hash
.hash
, data
+516, 16);
3283 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
.syntax_id
,
3285 &conn
->sconn
->client_id
,
3286 conn
->sconn
->msg_ctx
,
3288 if (!NT_STATUS_IS_OK(status
)) {
3289 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3290 nt_errstr(status
)));
3291 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3295 b
= cli
->binding_handle
;
3297 init_lsa_AsciiString(&server
, global_myname());
3298 init_lsa_AsciiString(&account
, user
);
3300 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3306 if (!NT_STATUS_IS_OK(status
)) {
3307 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3310 if (!NT_STATUS_IS_OK(result
)) {
3311 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3315 errcode
= NERR_Success
;
3317 SSVAL(*rparam
,0,errcode
);
3318 SSVAL(*rparam
,2,0); /* converter word */
3323 /****************************************************************************
3326 ****************************************************************************/
3328 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3329 connection_struct
*conn
,uint16 vuid
,
3330 char *param
, int tpscnt
,
3331 char *data
, int tdscnt
,
3332 int mdrcnt
,int mprcnt
,
3333 char **rdata
,char **rparam
,
3334 int *rdata_len
,int *rparam_len
)
3336 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3337 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3338 char *str2
= skip_string(param
,tpscnt
,str1
);
3339 char *p
= skip_string(param
,tpscnt
,str2
);
3343 WERROR werr
= WERR_OK
;
3345 TALLOC_CTX
*mem_ctx
= talloc_tos();
3347 struct rpc_pipe_client
*cli
= NULL
;
3348 struct dcerpc_binding_handle
*b
= NULL
;
3349 struct policy_handle handle
;
3350 struct spoolss_DevmodeContainer devmode_ctr
;
3351 enum spoolss_JobControl command
;
3353 if (!str1
|| !str2
|| !p
) {
3357 * We use 1 here not 2 as we're checking
3358 * the last byte we want to access is safe.
3360 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3363 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3366 /* check it's a supported varient */
3367 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3371 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3377 ZERO_STRUCT(handle
);
3379 status
= rpc_pipe_open_interface(conn
,
3380 &ndr_table_spoolss
.syntax_id
,
3382 &conn
->sconn
->client_id
,
3383 conn
->sconn
->msg_ctx
,
3385 if (!NT_STATUS_IS_OK(status
)) {
3386 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3387 nt_errstr(status
)));
3388 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3391 b
= cli
->binding_handle
;
3393 ZERO_STRUCT(devmode_ctr
);
3395 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3399 JOB_ACCESS_ADMINISTER
,
3402 if (!NT_STATUS_IS_OK(status
)) {
3403 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3406 if (!W_ERROR_IS_OK(werr
)) {
3407 errcode
= W_ERROR_V(werr
);
3411 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3412 * and NERR_DestNotFound if share did not exist */
3414 errcode
= NERR_Success
;
3417 case 81: /* delete */
3418 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3420 case 82: /* pause */
3421 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3423 case 83: /* resume */
3424 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3427 errcode
= NERR_notsupported
;
3431 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3434 NULL
, /* unique ptr ctr */
3437 if (!NT_STATUS_IS_OK(status
)) {
3438 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3441 if (!W_ERROR_IS_OK(werr
)) {
3442 errcode
= W_ERROR_V(werr
);
3447 if (b
&& is_valid_policy_hnd(&handle
)) {
3448 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3451 SSVAL(*rparam
,0,errcode
);
3452 SSVAL(*rparam
,2,0); /* converter word */
3457 /****************************************************************************
3458 Purge a print queue - or pause or resume it.
3459 ****************************************************************************/
3461 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3462 connection_struct
*conn
,uint16 vuid
,
3463 char *param
, int tpscnt
,
3464 char *data
, int tdscnt
,
3465 int mdrcnt
,int mprcnt
,
3466 char **rdata
,char **rparam
,
3467 int *rdata_len
,int *rparam_len
)
3469 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3470 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3471 char *str2
= skip_string(param
,tpscnt
,str1
);
3472 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3473 int errcode
= NERR_notsupported
;
3474 WERROR werr
= WERR_OK
;
3477 TALLOC_CTX
*mem_ctx
= talloc_tos();
3478 struct rpc_pipe_client
*cli
= NULL
;
3479 struct dcerpc_binding_handle
*b
= NULL
;
3480 struct policy_handle handle
;
3481 struct spoolss_SetPrinterInfoCtr info_ctr
;
3482 struct spoolss_DevmodeContainer devmode_ctr
;
3483 struct sec_desc_buf secdesc_ctr
;
3484 enum spoolss_PrinterControl command
;
3486 if (!str1
|| !str2
|| !QueueName
) {
3490 /* check it's a supported varient */
3491 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3495 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3501 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3505 ZERO_STRUCT(handle
);
3507 status
= rpc_pipe_open_interface(conn
,
3508 &ndr_table_spoolss
.syntax_id
,
3510 &conn
->sconn
->client_id
,
3511 conn
->sconn
->msg_ctx
,
3513 if (!NT_STATUS_IS_OK(status
)) {
3514 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3515 nt_errstr(status
)));
3516 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3519 b
= cli
->binding_handle
;
3521 ZERO_STRUCT(devmode_ctr
);
3523 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3527 SEC_FLAG_MAXIMUM_ALLOWED
,
3530 if (!NT_STATUS_IS_OK(status
)) {
3531 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3534 if (!W_ERROR_IS_OK(werr
)) {
3535 errcode
= W_ERROR_V(werr
);
3540 case 74: /* Pause queue */
3541 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3543 case 75: /* Resume queue */
3544 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3546 case 103: /* Purge */
3547 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3550 werr
= WERR_NOT_SUPPORTED
;
3554 if (!W_ERROR_IS_OK(werr
)) {
3555 errcode
= W_ERROR_V(werr
);
3559 ZERO_STRUCT(info_ctr
);
3560 ZERO_STRUCT(secdesc_ctr
);
3562 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3569 if (!NT_STATUS_IS_OK(status
)) {
3570 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3573 if (!W_ERROR_IS_OK(werr
)) {
3574 errcode
= W_ERROR_V(werr
);
3578 errcode
= W_ERROR_V(werr
);
3582 if (b
&& is_valid_policy_hnd(&handle
)) {
3583 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3586 SSVAL(*rparam
,0,errcode
);
3587 SSVAL(*rparam
,2,0); /* converter word */
3592 /****************************************************************************
3593 set the property of a print job (undocumented?)
3594 ? function = 0xb -> set name of print job
3595 ? function = 0x6 -> move print job up/down
3596 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3597 or <WWsTP> <WB21BB16B10zWWzDDz>
3598 ****************************************************************************/
3600 static int check_printjob_info(struct pack_desc
* desc
,
3601 int uLevel
, char* id
)
3603 desc
->subformat
= NULL
;
3605 case 0: desc
->format
= "W"; break;
3606 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3607 case 2: desc
->format
= "WWzWWDDzz"; break;
3608 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3609 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3611 DEBUG(0,("check_printjob_info: invalid level %d\n",
3615 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3616 DEBUG(0,("check_printjob_info: invalid format %s\n",
3617 id
? id
: "<NULL>" ));
3623 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3624 connection_struct
*conn
, uint16 vuid
,
3625 char *param
, int tpscnt
,
3626 char *data
, int tdscnt
,
3627 int mdrcnt
,int mprcnt
,
3628 char **rdata
,char **rparam
,
3629 int *rdata_len
,int *rparam_len
)
3631 struct pack_desc desc
;
3632 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3633 char *str2
= skip_string(param
,tpscnt
,str1
);
3634 char *p
= skip_string(param
,tpscnt
,str2
);
3637 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3638 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3641 TALLOC_CTX
*mem_ctx
= talloc_tos();
3644 struct rpc_pipe_client
*cli
= NULL
;
3645 struct dcerpc_binding_handle
*b
= NULL
;
3646 struct policy_handle handle
;
3647 struct spoolss_DevmodeContainer devmode_ctr
;
3648 struct spoolss_JobInfoContainer ctr
;
3649 union spoolss_JobInfo info
;
3650 struct spoolss_SetJobInfo1 info1
;
3652 if (!str1
|| !str2
|| !p
) {
3656 * We use 1 here not 2 as we're checking
3657 * the last byte we want to access is safe.
3659 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3662 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3665 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3672 /* check it's a supported varient */
3673 if ((strcmp(str1
,"WWsTP")) ||
3674 (!check_printjob_info(&desc
,uLevel
,str2
)))
3677 errcode
= NERR_notsupported
;
3681 /* change print job name, data gives the name */
3687 ZERO_STRUCT(handle
);
3689 status
= rpc_pipe_open_interface(conn
,
3690 &ndr_table_spoolss
.syntax_id
,
3692 &conn
->sconn
->client_id
,
3693 conn
->sconn
->msg_ctx
,
3695 if (!NT_STATUS_IS_OK(status
)) {
3696 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3697 nt_errstr(status
)));
3698 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3701 b
= cli
->binding_handle
;
3703 ZERO_STRUCT(devmode_ctr
);
3705 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3712 if (!NT_STATUS_IS_OK(status
)) {
3713 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3716 if (!W_ERROR_IS_OK(werr
)) {
3717 errcode
= W_ERROR_V(werr
);
3721 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3727 if (!W_ERROR_IS_OK(werr
)) {
3728 errcode
= W_ERROR_V(werr
);
3734 info1
.job_id
= info
.info1
.job_id
;
3735 info1
.printer_name
= info
.info1
.printer_name
;
3736 info1
.user_name
= info
.info1
.user_name
;
3737 info1
.document_name
= data
;
3738 info1
.data_type
= info
.info1
.data_type
;
3739 info1
.text_status
= info
.info1
.text_status
;
3740 info1
.status
= info
.info1
.status
;
3741 info1
.priority
= info
.info1
.priority
;
3742 info1
.position
= info
.info1
.position
;
3743 info1
.total_pages
= info
.info1
.total_pages
;
3744 info1
.pages_printed
= info
.info1
.pages_printed
;
3745 info1
.submitted
= info
.info1
.submitted
;
3748 ctr
.info
.info1
= &info1
;
3750 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3756 if (!NT_STATUS_IS_OK(status
)) {
3757 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3760 if (!W_ERROR_IS_OK(werr
)) {
3761 errcode
= W_ERROR_V(werr
);
3765 errcode
= NERR_Success
;
3768 if (b
&& is_valid_policy_hnd(&handle
)) {
3769 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3772 SSVALS(*rparam
,0,errcode
);
3773 SSVAL(*rparam
,2,0); /* converter word */
3779 /****************************************************************************
3780 Get info about the server.
3781 ****************************************************************************/
3783 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3784 connection_struct
*conn
,uint16 vuid
,
3785 char *param
, int tpscnt
,
3786 char *data
, int tdscnt
,
3787 int mdrcnt
,int mprcnt
,
3788 char **rdata
,char **rparam
,
3789 int *rdata_len
,int *rparam_len
)
3791 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3792 char *str2
= skip_string(param
,tpscnt
,str1
);
3793 char *p
= skip_string(param
,tpscnt
,str2
);
3794 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3800 TALLOC_CTX
*mem_ctx
= talloc_tos();
3801 struct rpc_pipe_client
*cli
= NULL
;
3802 union srvsvc_NetSrvInfo info
;
3804 struct dcerpc_binding_handle
*b
;
3806 if (!str1
|| !str2
|| !p
) {
3810 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3812 /* check it's a supported varient */
3813 if (!prefix_ok(str1
,"WrLh")) {
3819 if (strcmp(str2
,"B16") != 0) {
3825 if (strcmp(str2
,"B16BBDz") != 0) {
3831 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3837 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3843 if (strcmp(str2
,"DN") != 0) {
3849 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3858 *rdata_len
= mdrcnt
;
3859 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3865 p2
= p
+ struct_len
;
3867 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3869 &conn
->sconn
->client_id
,
3870 conn
->sconn
->msg_ctx
,
3872 if (!NT_STATUS_IS_OK(status
)) {
3873 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3874 nt_errstr(status
)));
3875 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3879 b
= cli
->binding_handle
;
3881 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3886 if (!NT_STATUS_IS_OK(status
)) {
3887 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3890 if (!W_ERROR_IS_OK(werr
)) {
3891 errcode
= W_ERROR_V(werr
);
3895 if (info
.info101
== NULL
) {
3896 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3901 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3902 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3906 SCVAL(p
,0,info
.info101
->version_major
);
3907 SCVAL(p
,1,info
.info101
->version_minor
);
3908 SIVAL(p
,2,info
.info101
->server_type
);
3910 if (mdrcnt
== struct_len
) {
3913 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3914 if (mdrcnt
- struct_len
<= 0) {
3918 info
.info101
->comment
,
3919 MIN(mdrcnt
- struct_len
,
3920 MAX_SERVER_STRING_LENGTH
),
3922 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3930 return False
; /* not yet implemented */
3933 errcode
= NERR_Success
;
3937 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3940 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3944 SSVAL(*rparam
,0,errcode
);
3945 SSVAL(*rparam
,2,0); /* converter word */
3946 SSVAL(*rparam
,4,*rdata_len
);
3951 /****************************************************************************
3952 Get info about the server.
3953 ****************************************************************************/
3955 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3956 connection_struct
*conn
,uint16 vuid
,
3957 char *param
, int tpscnt
,
3958 char *data
, int tdscnt
,
3959 int mdrcnt
,int mprcnt
,
3960 char **rdata
,char **rparam
,
3961 int *rdata_len
,int *rparam_len
)
3963 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3964 char *str2
= skip_string(param
,tpscnt
,str1
);
3965 char *p
= skip_string(param
,tpscnt
,str2
);
3968 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3970 if (!str1
|| !str2
|| !p
) {
3974 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3977 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3982 /* check it's a supported varient */
3983 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3987 *rdata_len
= mdrcnt
+ 1024;
3988 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3993 SSVAL(*rparam
,0,NERR_Success
);
3994 SSVAL(*rparam
,2,0); /* converter word */
3997 endp
= *rdata
+ *rdata_len
;
3999 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
4004 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
4005 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
4007 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4013 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
4014 strlcpy(p2
,conn
->session_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
4015 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4021 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
4022 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
4024 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4030 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
4031 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
4034 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
4035 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
4036 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4042 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
4043 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4044 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4050 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4052 SSVAL(*rparam
,4,*rdata_len
);
4057 /****************************************************************************
4058 get info about a user
4060 struct user_info_11 {
4061 char usri11_name[21]; 0-20
4063 char *usri11_comment; 22-25
4064 char *usri11_usr_comment; 26-29
4065 unsigned short usri11_priv; 30-31
4066 unsigned long usri11_auth_flags; 32-35
4067 long usri11_password_age; 36-39
4068 char *usri11_homedir; 40-43
4069 char *usri11_parms; 44-47
4070 long usri11_last_logon; 48-51
4071 long usri11_last_logoff; 52-55
4072 unsigned short usri11_bad_pw_count; 56-57
4073 unsigned short usri11_num_logons; 58-59
4074 char *usri11_logon_server; 60-63
4075 unsigned short usri11_country_code; 64-65
4076 char *usri11_workstations; 66-69
4077 unsigned long usri11_max_storage; 70-73
4078 unsigned short usri11_units_per_week; 74-75
4079 unsigned char *usri11_logon_hours; 76-79
4080 unsigned short usri11_code_page; 80-81
4085 usri11_name specifies the user name for which information is retrieved
4087 usri11_pad aligns the next data structure element to a word boundary
4089 usri11_comment is a null terminated ASCII comment
4091 usri11_user_comment is a null terminated ASCII comment about the user
4093 usri11_priv specifies the level of the privilege assigned to the user.
4094 The possible values are:
4096 Name Value Description
4097 USER_PRIV_GUEST 0 Guest privilege
4098 USER_PRIV_USER 1 User privilege
4099 USER_PRV_ADMIN 2 Administrator privilege
4101 usri11_auth_flags specifies the account operator privileges. The
4102 possible values are:
4104 Name Value Description
4105 AF_OP_PRINT 0 Print operator
4108 Leach, Naik [Page 28]
4112 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4115 AF_OP_COMM 1 Communications operator
4116 AF_OP_SERVER 2 Server operator
4117 AF_OP_ACCOUNTS 3 Accounts operator
4120 usri11_password_age specifies how many seconds have elapsed since the
4121 password was last changed.
4123 usri11_home_dir points to a null terminated ASCII string that contains
4124 the path name of the user's home directory.
4126 usri11_parms points to a null terminated ASCII string that is set
4127 aside for use by applications.
4129 usri11_last_logon specifies the time when the user last logged on.
4130 This value is stored as the number of seconds elapsed since
4131 00:00:00, January 1, 1970.
4133 usri11_last_logoff specifies the time when the user last logged off.
4134 This value is stored as the number of seconds elapsed since
4135 00:00:00, January 1, 1970. A value of 0 means the last logoff
4138 usri11_bad_pw_count specifies the number of incorrect passwords
4139 entered since the last successful logon.
4141 usri11_log1_num_logons specifies the number of times this user has
4142 logged on. A value of -1 means the number of logons is unknown.
4144 usri11_logon_server points to a null terminated ASCII string that
4145 contains the name of the server to which logon requests are sent.
4146 A null string indicates logon requests should be sent to the
4149 usri11_country_code specifies the country code for the user's language
4152 usri11_workstations points to a null terminated ASCII string that
4153 contains the names of workstations the user may log on from.
4154 There may be up to 8 workstations, with the names separated by
4155 commas. A null strings indicates there are no restrictions.
4157 usri11_max_storage specifies the maximum amount of disk space the user
4158 can occupy. A value of 0xffffffff indicates there are no
4161 usri11_units_per_week specifies the equal number of time units into
4162 which a week is divided. This value must be equal to 168.
4164 usri11_logon_hours points to a 21 byte (168 bits) string that
4165 specifies the time during which the user can log on. Each bit
4166 represents one unique hour in a week. The first bit (bit 0, word
4167 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4171 Leach, Naik [Page 29]
4175 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4178 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4179 are no restrictions.
4181 usri11_code_page specifies the code page for the user's language of
4184 All of the pointers in this data structure need to be treated
4185 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4186 to be ignored. The converter word returned in the parameters section
4187 needs to be subtracted from the lower 16 bits to calculate an offset
4188 into the return buffer where this ASCII string resides.
4190 There is no auxiliary data in the response.
4192 ****************************************************************************/
4194 #define usri11_name 0
4195 #define usri11_pad 21
4196 #define usri11_comment 22
4197 #define usri11_usr_comment 26
4198 #define usri11_full_name 30
4199 #define usri11_priv 34
4200 #define usri11_auth_flags 36
4201 #define usri11_password_age 40
4202 #define usri11_homedir 44
4203 #define usri11_parms 48
4204 #define usri11_last_logon 52
4205 #define usri11_last_logoff 56
4206 #define usri11_bad_pw_count 60
4207 #define usri11_num_logons 62
4208 #define usri11_logon_server 64
4209 #define usri11_country_code 68
4210 #define usri11_workstations 70
4211 #define usri11_max_storage 74
4212 #define usri11_units_per_week 78
4213 #define usri11_logon_hours 80
4214 #define usri11_code_page 84
4215 #define usri11_end 86
4217 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4218 connection_struct
*conn
, uint16 vuid
,
4219 char *param
, int tpscnt
,
4220 char *data
, int tdscnt
,
4221 int mdrcnt
,int mprcnt
,
4222 char **rdata
,char **rparam
,
4223 int *rdata_len
,int *rparam_len
)
4225 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4226 char *str2
= skip_string(param
,tpscnt
,str1
);
4227 char *UserName
= skip_string(param
,tpscnt
,str2
);
4228 char *p
= skip_string(param
,tpscnt
,UserName
);
4229 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4232 const char *level_string
;
4234 TALLOC_CTX
*mem_ctx
= talloc_tos();
4235 NTSTATUS status
, result
;
4236 struct rpc_pipe_client
*cli
= NULL
;
4237 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4238 struct lsa_String domain_name
;
4239 struct dom_sid2
*domain_sid
;
4240 struct lsa_String names
;
4241 struct samr_Ids rids
;
4242 struct samr_Ids types
;
4243 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4245 union samr_UserInfo
*info
;
4246 struct dcerpc_binding_handle
*b
= NULL
;
4248 if (!str1
|| !str2
|| !UserName
|| !p
) {
4253 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4258 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4260 /* check it's a supported variant */
4261 if (strcmp(str1
,"zWrLh") != 0) {
4265 case 0: level_string
= "B21"; break;
4266 case 1: level_string
= "B21BB16DWzzWz"; break;
4267 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4268 case 10: level_string
= "B21Bzzz"; break;
4269 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4270 default: return False
;
4273 if (strcmp(level_string
,str2
) != 0) {
4277 *rdata_len
= mdrcnt
+ 1024;
4278 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4284 endp
= *rdata
+ *rdata_len
;
4285 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4290 ZERO_STRUCT(connect_handle
);
4291 ZERO_STRUCT(domain_handle
);
4292 ZERO_STRUCT(user_handle
);
4294 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
.syntax_id
,
4296 &conn
->sconn
->client_id
,
4297 conn
->sconn
->msg_ctx
,
4299 if (!NT_STATUS_IS_OK(status
)) {
4300 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4301 nt_errstr(status
)));
4302 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4306 b
= cli
->binding_handle
;
4308 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4310 SAMR_ACCESS_CONNECT_TO_SERVER
|
4311 SAMR_ACCESS_ENUM_DOMAINS
|
4312 SAMR_ACCESS_LOOKUP_DOMAIN
,
4315 if (!NT_STATUS_IS_OK(status
)) {
4316 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4319 if (!NT_STATUS_IS_OK(result
)) {
4320 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4324 init_lsa_String(&domain_name
, get_global_sam_name());
4326 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4331 if (!NT_STATUS_IS_OK(status
)) {
4332 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4335 if (!NT_STATUS_IS_OK(result
)) {
4336 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4340 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4342 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4346 if (!NT_STATUS_IS_OK(status
)) {
4347 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4350 if (!NT_STATUS_IS_OK(result
)) {
4351 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4355 init_lsa_String(&names
, UserName
);
4357 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4364 if (!NT_STATUS_IS_OK(status
)) {
4365 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4368 if (!NT_STATUS_IS_OK(result
)) {
4369 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4373 if (rids
.count
!= 1) {
4374 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4377 if (rids
.count
!= types
.count
) {
4378 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4381 if (types
.ids
[0] != SID_NAME_USER
) {
4382 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4388 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4390 SAMR_USER_ACCESS_GET_LOCALE
|
4391 SAMR_USER_ACCESS_GET_LOGONINFO
|
4392 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4393 SAMR_USER_ACCESS_GET_GROUPS
|
4394 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4395 SEC_STD_READ_CONTROL
,
4399 if (!NT_STATUS_IS_OK(status
)) {
4400 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4403 if (!NT_STATUS_IS_OK(result
)) {
4404 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4408 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4413 if (!NT_STATUS_IS_OK(status
)) {
4414 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4417 if (!NT_STATUS_IS_OK(result
)) {
4418 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4423 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4426 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4431 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4432 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4433 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4438 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4439 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4440 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4445 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4446 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4447 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4448 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4455 const char *homedir
= info
->info21
.home_directory
.string
;
4456 /* modelled after NTAS 3.51 reply */
4457 SSVAL(p
,usri11_priv
,
4458 (get_current_uid(conn
) == sec_initial_uid())?
4459 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4460 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4461 SIVALS(p
,usri11_password_age
,-1); /* password age */
4462 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4463 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4464 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4468 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4469 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4470 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4474 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4475 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4476 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4477 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4478 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4479 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4480 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4484 SSVAL(p
,usri11_country_code
,0); /* country code */
4486 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4487 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4488 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4493 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4494 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4495 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4497 /* a simple way to get logon hours at all times. */
4499 SCVAL(p2
,21,0); /* fix zero termination */
4500 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4505 SSVAL(p
,usri11_code_page
,0); /* code page */
4508 if (uLevel
== 1 || uLevel
== 2) {
4509 memset(p
+22,' ',16); /* password */
4510 SIVALS(p
,38,-1); /* password age */
4512 (get_current_uid(conn
) == sec_initial_uid())?
4513 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4514 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4515 strlcpy(p2
, info
->info21
.home_directory
.string
,
4517 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4521 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4523 SSVAL(p
,52,0); /* flags */
4524 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4525 strlcpy(p2
, info
->info21
.logon_script
.string
,
4527 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4532 SIVAL(p
,58,0); /* auth_flags */
4533 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4534 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4535 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4539 SIVAL(p
,66,0); /* urs_comment */
4540 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4541 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4542 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4546 SIVAL(p
,74,0); /* workstations */
4547 SIVAL(p
,78,0); /* last_logon */
4548 SIVAL(p
,82,0); /* last_logoff */
4549 SIVALS(p
,86,-1); /* acct_expires */
4550 SIVALS(p
,90,-1); /* max_storage */
4551 SSVAL(p
,94,168); /* units_per_week */
4552 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4555 SSVALS(p
,100,-1); /* bad_pw_count */
4556 SSVALS(p
,102,-1); /* num_logons */
4557 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4559 TALLOC_CTX
*ctx
= talloc_tos();
4560 int space_rem
= *rdata_len
- (p2
- *rdata
);
4563 if (space_rem
<= 0) {
4566 tmp
= talloc_strdup(ctx
, "\\\\%L");
4570 tmp
= talloc_sub_basic(ctx
,
4583 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4587 SSVAL(p
,108,49); /* country_code */
4588 SSVAL(p
,110,860); /* code page */
4592 errcode
= NERR_Success
;
4595 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4597 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4598 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4600 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4601 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4603 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4604 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4607 SSVAL(*rparam
,0,errcode
);
4608 SSVAL(*rparam
,2,0); /* converter word */
4609 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4614 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4615 connection_struct
*conn
,uint16 vuid
,
4616 char *param
, int tpscnt
,
4617 char *data
, int tdscnt
,
4618 int mdrcnt
,int mprcnt
,
4619 char **rdata
,char **rparam
,
4620 int *rdata_len
,int *rparam_len
)
4622 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4623 char *str2
= skip_string(param
,tpscnt
,str1
);
4624 char *p
= skip_string(param
,tpscnt
,str2
);
4626 struct pack_desc desc
;
4628 /* With share level security vuid will always be zero.
4629 Don't depend on vuser being non-null !!. JRA */
4630 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4632 if (!str1
|| !str2
|| !p
) {
4637 DEBUG(3,(" Username of UID %d is %s\n",
4638 (int)vuser
->session_info
->utok
.uid
,
4639 vuser
->session_info
->unix_name
));
4642 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4643 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4648 memset((char *)&desc
,'\0',sizeof(desc
));
4650 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4652 /* check it's a supported varient */
4653 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4656 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4660 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4667 desc
.buflen
= mdrcnt
;
4668 desc
.subformat
= NULL
;
4671 if (init_package(&desc
,1,0)) {
4672 PACKI(&desc
,"W",0); /* code */
4673 PACKS(&desc
,"B21",name
); /* eff. name */
4674 PACKS(&desc
,"B",""); /* pad */
4676 (get_current_uid(conn
) == sec_initial_uid())?
4677 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4678 PACKI(&desc
,"D",0); /* auth flags XXX */
4679 PACKI(&desc
,"W",0); /* num logons */
4680 PACKI(&desc
,"W",0); /* bad pw count */
4681 PACKI(&desc
,"D",0); /* last logon */
4682 PACKI(&desc
,"D",-1); /* last logoff */
4683 PACKI(&desc
,"D",-1); /* logoff time */
4684 PACKI(&desc
,"D",-1); /* kickoff time */
4685 PACKI(&desc
,"D",0); /* password age */
4686 PACKI(&desc
,"D",0); /* password can change */
4687 PACKI(&desc
,"D",-1); /* password must change */
4691 fstrcpy(mypath
,"\\\\");
4692 fstrcat(mypath
,get_local_machine_name());
4694 PACKS(&desc
,"z",mypath
); /* computer */
4697 PACKS(&desc
,"z",lp_workgroup());/* domain */
4698 PACKS(&desc
,"z", vuser
?
4699 vuser
->session_info
->info3
->base
.logon_script
.string
4700 : ""); /* script path */
4701 PACKI(&desc
,"D",0x00000000); /* reserved */
4704 *rdata_len
= desc
.usedlen
;
4706 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4710 SSVALS(*rparam
,0,desc
.errcode
);
4712 SSVAL(*rparam
,4,desc
.neededlen
);
4714 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4719 /****************************************************************************
4720 api_WAccessGetUserPerms
4721 ****************************************************************************/
4723 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4724 connection_struct
*conn
,uint16 vuid
,
4725 char *param
, int tpscnt
,
4726 char *data
, int tdscnt
,
4727 int mdrcnt
,int mprcnt
,
4728 char **rdata
,char **rparam
,
4729 int *rdata_len
,int *rparam_len
)
4731 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4732 char *str2
= skip_string(param
,tpscnt
,str1
);
4733 char *user
= skip_string(param
,tpscnt
,str2
);
4734 char *resource
= skip_string(param
,tpscnt
,user
);
4736 if (!str1
|| !str2
|| !user
|| !resource
) {
4740 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4743 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4745 /* check it's a supported varient */
4746 if (strcmp(str1
,"zzh") != 0) {
4749 if (strcmp(str2
,"") != 0) {
4754 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4758 SSVALS(*rparam
,0,0); /* errorcode */
4759 SSVAL(*rparam
,2,0); /* converter word */
4760 SSVAL(*rparam
,4,0x7f); /* permission flags */
4765 /****************************************************************************
4766 api_WPrintJobEnumerate
4767 ****************************************************************************/
4769 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4770 connection_struct
*conn
, uint16 vuid
,
4771 char *param
, int tpscnt
,
4772 char *data
, int tdscnt
,
4773 int mdrcnt
,int mprcnt
,
4774 char **rdata
,char **rparam
,
4775 int *rdata_len
,int *rparam_len
)
4777 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4778 char *str2
= skip_string(param
,tpscnt
,str1
);
4779 char *p
= skip_string(param
,tpscnt
,str2
);
4783 struct pack_desc desc
;
4786 TALLOC_CTX
*mem_ctx
= talloc_tos();
4789 struct rpc_pipe_client
*cli
= NULL
;
4790 struct dcerpc_binding_handle
*b
= NULL
;
4791 struct policy_handle handle
;
4792 struct spoolss_DevmodeContainer devmode_ctr
;
4793 union spoolss_JobInfo info
;
4795 if (!str1
|| !str2
|| !p
) {
4799 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4801 memset((char *)&desc
,'\0',sizeof(desc
));
4802 memset((char *)&status
,'\0',sizeof(status
));
4804 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4806 /* check it's a supported varient */
4807 if (strcmp(str1
,"WWrLh") != 0) {
4810 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4814 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4818 ZERO_STRUCT(handle
);
4820 status
= rpc_pipe_open_interface(conn
,
4821 &ndr_table_spoolss
.syntax_id
,
4823 &conn
->sconn
->client_id
,
4824 conn
->sconn
->msg_ctx
,
4826 if (!NT_STATUS_IS_OK(status
)) {
4827 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4828 nt_errstr(status
)));
4829 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4832 b
= cli
->binding_handle
;
4834 ZERO_STRUCT(devmode_ctr
);
4836 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4843 if (!NT_STATUS_IS_OK(status
)) {
4844 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4847 if (!W_ERROR_IS_OK(werr
)) {
4848 desc
.errcode
= W_ERROR_V(werr
);
4852 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4858 if (!W_ERROR_IS_OK(werr
)) {
4859 desc
.errcode
= W_ERROR_V(werr
);
4864 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4869 desc
.buflen
= mdrcnt
;
4872 * Don't return data but need to get correct length
4873 * init_package will return wrong size if buflen=0
4875 desc
.buflen
= getlen(desc
.format
);
4876 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4879 if (init_package(&desc
,1,0)) {
4880 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4881 *rdata_len
= desc
.usedlen
;
4883 desc
.errcode
= NERR_JobNotFound
;
4887 if (b
&& is_valid_policy_hnd(&handle
)) {
4888 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4892 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4896 SSVALS(*rparam
,0,desc
.errcode
);
4898 SSVAL(*rparam
,4,desc
.neededlen
);
4902 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4907 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4908 connection_struct
*conn
, uint16 vuid
,
4909 char *param
, int tpscnt
,
4910 char *data
, int tdscnt
,
4911 int mdrcnt
,int mprcnt
,
4912 char **rdata
,char **rparam
,
4913 int *rdata_len
,int *rparam_len
)
4915 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4916 char *str2
= skip_string(param
,tpscnt
,str1
);
4917 char *p
= skip_string(param
,tpscnt
,str2
);
4921 struct pack_desc desc
;
4923 TALLOC_CTX
*mem_ctx
= talloc_tos();
4926 struct rpc_pipe_client
*cli
= NULL
;
4927 struct dcerpc_binding_handle
*b
= NULL
;
4928 struct policy_handle handle
;
4929 struct spoolss_DevmodeContainer devmode_ctr
;
4931 union spoolss_JobInfo
*info
;
4933 if (!str1
|| !str2
|| !p
) {
4937 memset((char *)&desc
,'\0',sizeof(desc
));
4939 p
= skip_string(param
,tpscnt
,p
);
4943 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4945 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4947 /* check it's a supported variant */
4948 if (strcmp(str1
,"zWrLeh") != 0) {
4953 return False
; /* defined only for uLevel 0,1,2 */
4956 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4960 ZERO_STRUCT(handle
);
4962 status
= rpc_pipe_open_interface(conn
,
4963 &ndr_table_spoolss
.syntax_id
,
4965 &conn
->sconn
->client_id
,
4966 conn
->sconn
->msg_ctx
,
4968 if (!NT_STATUS_IS_OK(status
)) {
4969 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4970 nt_errstr(status
)));
4971 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4974 b
= cli
->binding_handle
;
4976 ZERO_STRUCT(devmode_ctr
);
4978 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4982 SEC_FLAG_MAXIMUM_ALLOWED
,
4985 if (!NT_STATUS_IS_OK(status
)) {
4986 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4989 if (!W_ERROR_IS_OK(werr
)) {
4990 desc
.errcode
= W_ERROR_V(werr
);
4994 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5002 if (!W_ERROR_IS_OK(werr
)) {
5003 desc
.errcode
= W_ERROR_V(werr
);
5008 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5014 desc
.buflen
= mdrcnt
;
5016 if (init_package(&desc
,count
,0)) {
5018 for (i
= 0; i
< count
; i
++) {
5019 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
5020 if (desc
.errcode
== NERR_Success
) {
5026 if (b
&& is_valid_policy_hnd(&handle
)) {
5027 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5030 *rdata_len
= desc
.usedlen
;
5033 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5037 SSVALS(*rparam
,0,desc
.errcode
);
5039 SSVAL(*rparam
,4,succnt
);
5040 SSVAL(*rparam
,6,count
);
5042 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
5047 static int check_printdest_info(struct pack_desc
* desc
,
5048 int uLevel
, char* id
)
5050 desc
->subformat
= NULL
;
5053 desc
->format
= "B9";
5056 desc
->format
= "B9B21WWzW";
5062 desc
->format
= "zzzWWzzzWW";
5065 DEBUG(0,("check_printdest_info: invalid level %d\n",
5069 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
5070 DEBUG(0,("check_printdest_info: invalid string %s\n",
5071 id
? id
: "<NULL>" ));
5077 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
5078 struct pack_desc
* desc
)
5082 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
5083 buf
[sizeof(buf
)-1] = 0;
5087 PACKS(desc
,"B9",buf
); /* szName */
5089 PACKS(desc
,"B21",""); /* szUserName */
5090 PACKI(desc
,"W",0); /* uJobId */
5091 PACKI(desc
,"W",0); /* fsStatus */
5092 PACKS(desc
,"z",""); /* pszStatus */
5093 PACKI(desc
,"W",0); /* time */
5097 if (uLevel
== 2 || uLevel
== 3) {
5098 PACKS(desc
,"z",buf
); /* pszPrinterName */
5100 PACKS(desc
,"z",""); /* pszUserName */
5101 PACKS(desc
,"z",""); /* pszLogAddr */
5102 PACKI(desc
,"W",0); /* uJobId */
5103 PACKI(desc
,"W",0); /* fsStatus */
5104 PACKS(desc
,"z",""); /* pszStatus */
5105 PACKS(desc
,"z",""); /* pszComment */
5106 PACKS(desc
,"z","NULL"); /* pszDrivers */
5107 PACKI(desc
,"W",0); /* time */
5108 PACKI(desc
,"W",0); /* pad1 */
5113 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
5114 connection_struct
*conn
, uint16 vuid
,
5115 char *param
, int tpscnt
,
5116 char *data
, int tdscnt
,
5117 int mdrcnt
,int mprcnt
,
5118 char **rdata
,char **rparam
,
5119 int *rdata_len
,int *rparam_len
)
5121 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5122 char *str2
= skip_string(param
,tpscnt
,str1
);
5123 char *p
= skip_string(param
,tpscnt
,str2
);
5124 char* PrinterName
= p
;
5126 struct pack_desc desc
;
5129 TALLOC_CTX
*mem_ctx
= talloc_tos();
5132 struct rpc_pipe_client
*cli
= NULL
;
5133 struct dcerpc_binding_handle
*b
= NULL
;
5134 struct policy_handle handle
;
5135 struct spoolss_DevmodeContainer devmode_ctr
;
5136 union spoolss_PrinterInfo info
;
5138 if (!str1
|| !str2
|| !p
) {
5142 memset((char *)&desc
,'\0',sizeof(desc
));
5144 p
= skip_string(param
,tpscnt
,p
);
5148 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5150 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
5152 /* check it's a supported varient */
5153 if (strcmp(str1
,"zWrLh") != 0) {
5156 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5160 ZERO_STRUCT(handle
);
5162 status
= rpc_pipe_open_interface(conn
,
5163 &ndr_table_spoolss
.syntax_id
,
5165 &conn
->sconn
->client_id
,
5166 conn
->sconn
->msg_ctx
,
5168 if (!NT_STATUS_IS_OK(status
)) {
5169 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5170 nt_errstr(status
)));
5171 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5174 b
= cli
->binding_handle
;
5176 ZERO_STRUCT(devmode_ctr
);
5178 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5182 SEC_FLAG_MAXIMUM_ALLOWED
,
5185 if (!NT_STATUS_IS_OK(status
)) {
5187 desc
.errcode
= NERR_DestNotFound
;
5191 if (!W_ERROR_IS_OK(werr
)) {
5193 desc
.errcode
= NERR_DestNotFound
;
5198 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5203 if (!W_ERROR_IS_OK(werr
)) {
5205 desc
.errcode
= NERR_DestNotFound
;
5211 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5216 desc
.buflen
= mdrcnt
;
5219 * Don't return data but need to get correct length
5220 * init_package will return wrong size if buflen=0
5222 desc
.buflen
= getlen(desc
.format
);
5223 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5225 if (init_package(&desc
,1,0)) {
5226 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5230 if (b
&& is_valid_policy_hnd(&handle
)) {
5231 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5234 *rdata_len
= desc
.usedlen
;
5237 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5241 SSVALS(*rparam
,0,desc
.errcode
);
5243 SSVAL(*rparam
,4,desc
.neededlen
);
5245 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5251 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5252 connection_struct
*conn
, uint16 vuid
,
5253 char *param
, int tpscnt
,
5254 char *data
, int tdscnt
,
5255 int mdrcnt
,int mprcnt
,
5256 char **rdata
,char **rparam
,
5257 int *rdata_len
,int *rparam_len
)
5259 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5260 char *str2
= skip_string(param
,tpscnt
,str1
);
5261 char *p
= skip_string(param
,tpscnt
,str2
);
5265 struct pack_desc desc
;
5267 TALLOC_CTX
*mem_ctx
= talloc_tos();
5270 struct rpc_pipe_client
*cli
= NULL
;
5271 union spoolss_PrinterInfo
*info
;
5274 if (!str1
|| !str2
|| !p
) {
5278 memset((char *)&desc
,'\0',sizeof(desc
));
5280 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5282 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5284 /* check it's a supported varient */
5285 if (strcmp(str1
,"WrLeh") != 0) {
5288 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5294 status
= rpc_pipe_open_interface(conn
,
5295 &ndr_table_spoolss
.syntax_id
,
5297 &conn
->sconn
->client_id
,
5298 conn
->sconn
->msg_ctx
,
5300 if (!NT_STATUS_IS_OK(status
)) {
5301 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5302 nt_errstr(status
)));
5303 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5307 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5309 cli
->srv_name_slash
,
5314 if (!W_ERROR_IS_OK(werr
)) {
5315 desc
.errcode
= W_ERROR_V(werr
);
5317 desc
.errcode
= NERR_DestNotFound
;
5325 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5332 desc
.buflen
= mdrcnt
;
5333 if (init_package(&desc
,queuecnt
,0)) {
5336 for (i
= 0; i
< count
; i
++) {
5337 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5339 if (desc
.errcode
== NERR_Success
) {
5345 *rdata_len
= desc
.usedlen
;
5348 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5352 SSVALS(*rparam
,0,desc
.errcode
);
5354 SSVAL(*rparam
,4,succnt
);
5355 SSVAL(*rparam
,6,queuecnt
);
5357 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5362 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5363 connection_struct
*conn
, uint16 vuid
,
5364 char *param
, int tpscnt
,
5365 char *data
, int tdscnt
,
5366 int mdrcnt
,int mprcnt
,
5367 char **rdata
,char **rparam
,
5368 int *rdata_len
,int *rparam_len
)
5370 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5371 char *str2
= skip_string(param
,tpscnt
,str1
);
5372 char *p
= skip_string(param
,tpscnt
,str2
);
5375 struct pack_desc desc
;
5377 if (!str1
|| !str2
|| !p
) {
5381 memset((char *)&desc
,'\0',sizeof(desc
));
5383 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5385 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5387 /* check it's a supported varient */
5388 if (strcmp(str1
,"WrLeh") != 0) {
5391 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5396 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5402 desc
.buflen
= mdrcnt
;
5403 if (init_package(&desc
,1,0)) {
5404 PACKS(&desc
,"B41","NULL");
5407 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5409 *rdata_len
= desc
.usedlen
;
5412 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5416 SSVALS(*rparam
,0,desc
.errcode
);
5418 SSVAL(*rparam
,4,succnt
);
5421 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5426 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5427 connection_struct
*conn
, uint16 vuid
,
5428 char *param
, int tpscnt
,
5429 char *data
, int tdscnt
,
5430 int mdrcnt
,int mprcnt
,
5431 char **rdata
,char **rparam
,
5432 int *rdata_len
,int *rparam_len
)
5434 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5435 char *str2
= skip_string(param
,tpscnt
,str1
);
5436 char *p
= skip_string(param
,tpscnt
,str2
);
5439 struct pack_desc desc
;
5441 if (!str1
|| !str2
|| !p
) {
5444 memset((char *)&desc
,'\0',sizeof(desc
));
5446 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5448 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5450 /* check it's a supported varient */
5451 if (strcmp(str1
,"WrLeh") != 0) {
5454 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5459 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5465 desc
.buflen
= mdrcnt
;
5467 if (init_package(&desc
,1,0)) {
5468 PACKS(&desc
,"B13","lpd");
5471 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5473 *rdata_len
= desc
.usedlen
;
5476 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5480 SSVALS(*rparam
,0,desc
.errcode
);
5482 SSVAL(*rparam
,4,succnt
);
5485 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5490 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5491 connection_struct
*conn
, uint16 vuid
,
5492 char *param
, int tpscnt
,
5493 char *data
, int tdscnt
,
5494 int mdrcnt
,int mprcnt
,
5495 char **rdata
,char **rparam
,
5496 int *rdata_len
,int *rparam_len
)
5498 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5499 char *str2
= skip_string(param
,tpscnt
,str1
);
5500 char *p
= skip_string(param
,tpscnt
,str2
);
5503 struct pack_desc desc
;
5505 if (!str1
|| !str2
|| !p
) {
5509 memset((char *)&desc
,'\0',sizeof(desc
));
5511 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5513 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5515 /* check it's a supported varient */
5516 if (strcmp(str1
,"WrLeh") != 0) {
5519 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5524 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5529 memset((char *)&desc
,'\0',sizeof(desc
));
5531 desc
.buflen
= mdrcnt
;
5533 if (init_package(&desc
,1,0)) {
5534 PACKS(&desc
,"B13","lp0");
5537 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5539 *rdata_len
= desc
.usedlen
;
5542 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5546 SSVALS(*rparam
,0,desc
.errcode
);
5548 SSVAL(*rparam
,4,succnt
);
5551 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5556 /****************************************************************************
5558 ****************************************************************************/
5560 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5561 connection_struct
*conn
, uint16 vuid
,
5562 char *param
, int tpscnt
,
5563 char *data
, int tdscnt
,
5564 int mdrcnt
,int mprcnt
,
5565 char **rdata
,char **rparam
,
5566 int *rdata_len
,int *rparam_len
)
5569 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5570 char *str2
= skip_string(param
,tpscnt
,str1
);
5571 char *p
= skip_string(param
,tpscnt
,str2
);
5573 struct pack_desc desc
;
5576 TALLOC_CTX
*mem_ctx
= talloc_tos();
5579 struct rpc_pipe_client
*cli
= NULL
;
5580 struct dcerpc_binding_handle
*b
= NULL
;
5581 struct srvsvc_NetSessInfoCtr info_ctr
;
5582 uint32_t totalentries
, resume_handle
= 0;
5585 if (!str1
|| !str2
|| !p
) {
5591 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5593 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5594 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5595 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5597 /* check it's a supported varient */
5598 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5601 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5605 status
= rpc_pipe_open_interface(conn
,
5606 &ndr_table_srvsvc
.syntax_id
,
5608 &conn
->sconn
->client_id
,
5609 conn
->sconn
->msg_ctx
,
5611 if (!NT_STATUS_IS_OK(status
)) {
5612 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5613 nt_errstr(status
)));
5614 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5617 b
= cli
->binding_handle
;
5620 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5621 if (info_ctr
.ctr
.ctr1
== NULL
) {
5622 desc
.errcode
= W_ERROR_V(WERR_NOMEM
);
5626 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5627 cli
->srv_name_slash
,
5631 (uint32_t)-1, /* max_buffer */
5635 if (!NT_STATUS_IS_OK(status
)) {
5636 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5637 nt_errstr(status
)));
5638 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5642 if (!W_ERROR_IS_OK(werr
)) {
5643 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5645 desc
.errcode
= W_ERROR_V(werr
);
5649 count
= info_ctr
.ctr
.ctr1
->count
;
5653 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5660 desc
.buflen
= mdrcnt
;
5662 if (!init_package(&desc
, count
,0)) {
5666 for(i
=0; i
< count
; i
++) {
5667 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5668 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5669 PACKI(&desc
, "W", 1); /* num conns */
5670 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5671 PACKI(&desc
, "W", 1); /* num users */
5672 PACKI(&desc
, "D", 0); /* session time */
5673 PACKI(&desc
, "D", 0); /* idle time */
5674 PACKI(&desc
, "D", 0); /* flags */
5675 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5678 *rdata_len
= desc
.usedlen
;
5681 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5685 SSVALS(*rparam
,0,desc
.errcode
);
5686 SSVAL(*rparam
,2,0); /* converter */
5687 SSVAL(*rparam
,4, count
); /* count */
5689 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5695 /****************************************************************************
5696 The buffer was too small.
5697 ****************************************************************************/
5699 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5700 connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5701 int mdrcnt
, int mprcnt
,
5702 char **rdata
, char **rparam
,
5703 int *rdata_len
, int *rparam_len
)
5705 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5706 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5713 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5715 DEBUG(3,("Supplied buffer too small in API command\n"));
5720 /****************************************************************************
5721 The request is not supported.
5722 ****************************************************************************/
5724 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5725 connection_struct
*conn
, uint16 vuid
,
5726 char *param
, int tpscnt
,
5727 char *data
, int tdscnt
,
5728 int mdrcnt
, int mprcnt
,
5729 char **rdata
, char **rparam
,
5730 int *rdata_len
, int *rparam_len
)
5733 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5740 SSVAL(*rparam
,0,NERR_notsupported
);
5741 SSVAL(*rparam
,2,0); /* converter word */
5743 DEBUG(3,("Unsupported API command\n"));
5748 static const struct {
5751 bool (*fn
)(struct smbd_server_connection
*sconn
,
5752 connection_struct
*, uint16
,
5755 int,int,char **,char **,int *,int *);
5756 bool auth_user
; /* Deny anonymous access? */
5757 } api_commands
[] = {
5758 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5759 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5760 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5761 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5762 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5763 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5764 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5765 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5766 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5767 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5768 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5769 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5770 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5771 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5772 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5773 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5774 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5775 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5776 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5777 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5778 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5779 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5780 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5781 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5782 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5783 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5784 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5785 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5786 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5787 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5788 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5789 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5790 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5791 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5792 {NULL
, -1, api_Unsupported
}
5793 /* The following RAP calls are not implemented by Samba:
5795 RAP_WFileEnum2 - anon not OK
5800 /****************************************************************************
5801 Handle remote api calls.
5802 ****************************************************************************/
5804 void api_reply(connection_struct
*conn
, uint16 vuid
,
5805 struct smb_request
*req
,
5806 char *data
, char *params
,
5807 int tdscnt
, int tpscnt
,
5808 int mdrcnt
, int mprcnt
)
5812 char *rparam
= NULL
;
5813 const char *name1
= NULL
;
5814 const char *name2
= NULL
;
5821 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5822 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5827 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5830 api_command
= SVAL(params
,0);
5831 /* Is there a string at position params+2 ? */
5832 if (skip_string(params
,tpscnt
,params
+2)) {
5837 name2
= skip_string(params
,tpscnt
,params
+2);
5842 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5846 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5848 for (i
=0;api_commands
[i
].name
;i
++) {
5849 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5850 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5855 /* Check whether this api call can be done anonymously */
5857 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5858 user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5860 if (!user
|| user
->session_info
->guest
) {
5861 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5866 rdata
= (char *)SMB_MALLOC(1024);
5868 memset(rdata
,'\0',1024);
5871 rparam
= (char *)SMB_MALLOC(1024);
5873 memset(rparam
,'\0',1024);
5876 if(!rdata
|| !rparam
) {
5877 DEBUG(0,("api_reply: malloc fail !\n"));
5880 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5884 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5886 params
,tpscnt
, /* params + length */
5887 data
,tdscnt
, /* data + length */
5889 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5892 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5893 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5895 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5898 /* if we get False back then it's actually unsupported */
5900 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5902 tdscnt
,mdrcnt
,mprcnt
,
5903 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5906 /* If api_Unsupported returns false we can't return anything. */
5908 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5909 rdata
, rdata_len
, False
);