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/globals.h"
30 #include "../librpc/gen_ndr/ndr_samr_c.h"
31 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
35 #include "../librpc/gen_ndr/srv_samr.h"
36 #include "../librpc/gen_ndr/srv_srvsvc.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 "rpc_server/rpc_ncacn_np.h"
42 #include "../libcli/security/security.h"
50 #define NERR_Success 0
51 #define NERR_badpass 86
52 #define NERR_notsupported 50
54 #define NERR_BASE (2100)
55 #define NERR_BufTooSmall (NERR_BASE+23)
56 #define NERR_JobNotFound (NERR_BASE+51)
57 #define NERR_DestNotFound (NERR_BASE+52)
59 #define ACCESS_READ 0x01
60 #define ACCESS_WRITE 0x02
61 #define ACCESS_CREATE 0x04
63 #define SHPWLEN 8 /* share password length */
65 /* Limit size of ipc replies */
67 static char *smb_realloc_limit(void *ptr
, size_t size
)
71 size
= MAX((size
),4*1024);
72 val
= (char *)SMB_REALLOC(ptr
,size
);
74 memset(val
,'\0',size
);
79 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
80 connection_struct
*conn
, uint16 vuid
,
81 char *param
, int tpscnt
,
82 char *data
, int tdscnt
,
83 int mdrcnt
, int mprcnt
,
84 char **rdata
, char **rparam
,
85 int *rdata_len
, int *rparam_len
);
87 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
88 connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
89 int mdrcnt
, int mprcnt
,
90 char **rdata
, char **rparam
,
91 int *rdata_len
, int *rparam_len
);
94 static int CopyExpanded(connection_struct
*conn
,
95 int snum
, char **dst
, char *src
, int *p_space_remaining
)
97 TALLOC_CTX
*ctx
= talloc_tos();
101 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
102 *p_space_remaining
<= 0) {
106 buf
= talloc_strdup(ctx
, src
);
108 *p_space_remaining
= 0;
111 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
113 *p_space_remaining
= 0;
116 buf
= talloc_sub_advanced(ctx
,
117 lp_servicename(SNUM(conn
)),
118 conn
->session_info
->unix_name
,
120 conn
->session_info
->utok
.gid
,
121 conn
->session_info
->sanitized_username
,
122 conn
->session_info
->info3
->base
.domain
.string
,
125 *p_space_remaining
= 0;
128 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
133 (*p_space_remaining
) -= l
;
137 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
140 if (!src
|| !dst
|| !n
|| !(*dst
)) {
143 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
152 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
154 TALLOC_CTX
*ctx
= talloc_tos();
159 buf
= talloc_strdup(ctx
,s
);
163 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
167 buf
= talloc_sub_advanced(ctx
,
168 lp_servicename(SNUM(conn
)),
169 conn
->session_info
->unix_name
,
171 conn
->session_info
->utok
.gid
,
172 conn
->session_info
->sanitized_username
,
173 conn
->session_info
->info3
->base
.domain
.string
,
178 return strlen(buf
) + 1;
181 /*******************************************************************
182 Check a API string for validity when we only need to check the prefix.
183 ******************************************************************/
185 static bool prefix_ok(const char *str
, const char *prefix
)
187 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
191 const char *format
; /* formatstring for structure */
192 const char *subformat
; /* subformat for structure */
193 char *base
; /* baseaddress of buffer */
194 int buflen
; /* remaining size for fixed part; on init: length of base */
195 int subcount
; /* count of substructures */
196 char *structbuf
; /* pointer into buffer for remaining fixed part */
197 int stringlen
; /* remaining size for variable part */
198 char *stringbuf
; /* pointer into buffer for remaining variable part */
199 int neededlen
; /* total needed size */
200 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
201 const char *curpos
; /* current position; pointer into format or subformat */
205 static int get_counter(const char **p
)
211 if (!isdigit((int)**p
)) {
217 n
= 10 * n
+ (i
- '0');
225 static int getlen(const char *p
)
234 case 'W': /* word (2 byte) */
237 case 'K': /* status word? (2 byte) */
240 case 'N': /* count of substructures (word) at end */
243 case 'D': /* double word (4 byte) */
244 case 'z': /* offset to zero terminated string (4 byte) */
245 case 'l': /* offset to user data (4 byte) */
248 case 'b': /* offset to data (with counter) (4 byte) */
252 case 'B': /* byte (with optional counter) */
253 n
+= get_counter(&p
);
260 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
265 if (!p
->format
|| !p
->base
) {
269 i
= count
* getlen(p
->format
);
271 i
+= subcount
* getlen(p
->subformat
);
273 p
->structbuf
= p
->base
;
277 p
->curpos
= p
->format
;
283 * This is the old error code we used. Aparently
284 * WinNT/2k systems return ERRbuftoosmall (2123) and
285 * OS/2 needs this. I'm leaving this here so we can revert
288 p
->errcode
= ERRmoredata
;
290 p
->errcode
= ERRbuftoosmall
;
293 p
->errcode
= NERR_Success
;
297 p
->stringbuf
= p
->base
+ i
;
299 return (p
->errcode
== NERR_Success
);
302 static int package(struct pack_desc
*p
, ...)
305 int needed
=0, stringneeded
;
306 const char *str
=NULL
;
307 int is_string
=0, stringused
;
314 p
->curpos
= p
->format
;
316 p
->curpos
= p
->subformat
;
321 str
= va_arg(args
,char*);
322 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
331 switch( *p
->curpos
++ ) {
332 case 'W': /* word (2 byte) */
334 temp
= va_arg(args
,int);
335 if (p
->buflen
>= needed
) {
336 SSVAL(p
->structbuf
,0,temp
);
339 case 'K': /* status word? (2 byte) */
341 temp
= va_arg(args
,int);
342 if (p
->buflen
>= needed
) {
343 SSVAL(p
->structbuf
,0,temp
);
346 case 'N': /* count of substructures (word) at end */
348 p
->subcount
= va_arg(args
,int);
349 if (p
->buflen
>= needed
) {
350 SSVAL(p
->structbuf
,0,p
->subcount
);
353 case 'D': /* double word (4 byte) */
355 temp
= va_arg(args
,int);
356 if (p
->buflen
>= needed
) {
357 SIVAL(p
->structbuf
,0,temp
);
360 case 'B': /* byte (with optional counter) */
361 needed
= get_counter(&p
->curpos
);
363 char *s
= va_arg(args
,char*);
364 if (p
->buflen
>= needed
) {
365 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
369 case 'z': /* offset to zero terminated string (4 byte) */
370 str
= va_arg(args
,char*);
371 stringneeded
= (str
? strlen(str
)+1 : 0);
374 case 'l': /* offset to user data (4 byte) */
375 str
= va_arg(args
,char*);
376 stringneeded
= va_arg(args
,int);
379 case 'b': /* offset to data (with counter) (4 byte) */
380 str
= va_arg(args
,char*);
381 stringneeded
= get_counter(&p
->curpos
);
387 if (stringneeded
>= 0) {
389 if (p
->buflen
>= needed
) {
390 stringused
= stringneeded
;
391 if (stringused
> p
->stringlen
) {
392 stringused
= (is_string
? p
->stringlen
: 0);
393 if (p
->errcode
== NERR_Success
) {
394 p
->errcode
= ERRmoredata
;
398 SIVAL(p
->structbuf
,0,0);
400 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
401 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
403 p
->stringbuf
[stringused
-1] = '\0';
405 p
->stringbuf
+= stringused
;
406 p
->stringlen
-= stringused
;
407 p
->usedlen
+= stringused
;
410 p
->neededlen
+= stringneeded
;
413 p
->neededlen
+= needed
;
414 if (p
->buflen
>= needed
) {
415 p
->structbuf
+= needed
;
417 p
->usedlen
+= needed
;
419 if (p
->errcode
== NERR_Success
) {
420 p
->errcode
= ERRmoredata
;
427 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
428 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
430 #define PACK(desc,t,v) package(desc,v)
431 #define PACKl(desc,t,v,l) package(desc,v,l)
434 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
439 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
444 /****************************************************************************
446 ****************************************************************************/
448 static void PackDriverData(struct pack_desc
* desc
)
450 char drivdata
[4+4+32];
451 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
452 SIVAL(drivdata
,4,1000); /* lVersion */
453 memset(drivdata
+8,0,32); /* szDeviceName */
454 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
455 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
458 static int check_printq_info(struct pack_desc
* desc
,
459 unsigned int uLevel
, char *id1
, char *id2
)
461 desc
->subformat
= NULL
;
464 desc
->format
= "B13";
467 desc
->format
= "B13BWWWzzzzzWW";
470 desc
->format
= "B13BWWWzzzzzWN";
471 desc
->subformat
= "WB21BB16B10zWWzDDz";
474 desc
->format
= "zWWWWzzzzWWzzl";
477 desc
->format
= "zWWWWzzzzWNzzl";
478 desc
->subformat
= "WWzWWDDzz";
487 desc
->format
= "WzzzzzzzzN";
488 desc
->subformat
= "z";
491 DEBUG(0,("check_printq_info: invalid level %d\n",
495 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
496 DEBUG(0,("check_printq_info: invalid format %s\n",
497 id1
? id1
: "<NULL>" ));
500 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
501 DEBUG(0,("check_printq_info: invalid subformat %s\n",
502 id2
? id2
: "<NULL>" ));
509 #define RAP_JOB_STATUS_QUEUED 0
510 #define RAP_JOB_STATUS_PAUSED 1
511 #define RAP_JOB_STATUS_SPOOLING 2
512 #define RAP_JOB_STATUS_PRINTING 3
513 #define RAP_JOB_STATUS_PRINTED 4
515 #define RAP_QUEUE_STATUS_PAUSED 1
516 #define RAP_QUEUE_STATUS_ERROR 2
518 /* turn a print job status into a on the wire status
520 static int printj_spoolss_status(int v
)
522 if (v
== JOB_STATUS_QUEUED
)
523 return RAP_JOB_STATUS_QUEUED
;
524 if (v
& JOB_STATUS_PAUSED
)
525 return RAP_JOB_STATUS_PAUSED
;
526 if (v
& JOB_STATUS_SPOOLING
)
527 return RAP_JOB_STATUS_SPOOLING
;
528 if (v
& JOB_STATUS_PRINTING
)
529 return RAP_JOB_STATUS_PRINTING
;
533 /* turn a print queue status into a on the wire status
535 static int printq_spoolss_status(int v
)
537 if (v
== PRINTER_STATUS_OK
)
539 if (v
& PRINTER_STATUS_PAUSED
)
540 return RAP_QUEUE_STATUS_PAUSED
;
541 return RAP_QUEUE_STATUS_ERROR
;
544 static void fill_spoolss_printjob_info(int uLevel
,
545 struct pack_desc
*desc
,
546 struct spoolss_JobInfo2
*info2
,
549 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
551 /* the client expects localtime */
552 t
-= get_time_zone(t
);
554 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
556 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
557 PACKS(desc
,"B",""); /* pad */
558 PACKS(desc
,"B16",""); /* szNotifyName */
559 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
560 PACKS(desc
,"z",""); /* pszParms */
561 PACKI(desc
,"W",n
+1); /* uPosition */
562 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
563 PACKS(desc
,"z",""); /* pszStatus */
564 PACKI(desc
,"D", t
); /* ulSubmitted */
565 PACKI(desc
,"D", info2
->size
); /* ulSize */
566 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
568 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
569 PACKI(desc
,"W", info2
->priority
); /* uPriority */
570 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
571 PACKI(desc
,"W",n
+1); /* uPosition */
572 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
573 PACKI(desc
,"D",t
); /* ulSubmitted */
574 PACKI(desc
,"D", info2
->size
); /* ulSize */
575 PACKS(desc
,"z","Samba"); /* pszComment */
576 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
578 PACKS(desc
,"z",""); /* pszNotifyName */
579 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
580 PACKS(desc
,"z",""); /* pszParms */
581 PACKS(desc
,"z",""); /* pszStatus */
582 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
583 PACKS(desc
,"z","lpd"); /* pszQProcName */
584 PACKS(desc
,"z",""); /* pszQProcParms */
585 PACKS(desc
,"z","NULL"); /* pszDriverName */
586 PackDriverData(desc
); /* pDriverData */
587 PACKS(desc
,"z",""); /* pszPrinterName */
588 } else if (uLevel
== 4) { /* OS2 */
589 PACKS(desc
,"z",""); /* pszSpoolFileName */
590 PACKS(desc
,"z",""); /* pszPortName */
591 PACKS(desc
,"z",""); /* pszStatus */
592 PACKI(desc
,"D",0); /* ulPagesSpooled */
593 PACKI(desc
,"D",0); /* ulPagesSent */
594 PACKI(desc
,"D",0); /* ulPagesPrinted */
595 PACKI(desc
,"D",0); /* ulTimePrinted */
596 PACKI(desc
,"D",0); /* ulExtendJobStatus */
597 PACKI(desc
,"D",0); /* ulStartPage */
598 PACKI(desc
,"D",0); /* ulEndPage */
603 /********************************************************************
604 Respond to the DosPrintQInfo command with a level of 52
605 This is used to get printer driver information for Win9x clients
606 ********************************************************************/
607 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
608 struct pack_desc
* desc
, int count
,
609 const char *printer_name
)
613 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
614 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
615 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
617 PACKI(desc
, "W", 0x0400); /* don't know */
618 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
619 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
620 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
621 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
623 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
624 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
625 PACKS(desc
,"z", location
); /* share to retrieve files */
627 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
628 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
629 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
631 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
632 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
633 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
634 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
635 DEBUG(3,("Driver Location: %s:\n",location
));
636 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
637 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
638 PACKI(desc
,"N",count
); /* number of files to copy */
640 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
642 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
643 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
644 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
649 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
652 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
654 desc
->errcode
=NERR_Success
;
658 static const char *strip_unc(const char *unc
)
666 if ((p
= strrchr(unc
, '\\')) != NULL
) {
673 static void fill_printq_info(int uLevel
,
674 struct pack_desc
* desc
,
676 union spoolss_JobInfo
*job_info
,
677 struct spoolss_DriverInfo3
*driver_info
,
678 struct spoolss_PrinterInfo2
*printer_info
)
684 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
689 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
692 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
696 if (uLevel
== 1 || uLevel
== 2) {
697 PACKS(desc
,"B",""); /* alignment */
698 PACKI(desc
,"W",5); /* priority */
699 PACKI(desc
,"W",0); /* start time */
700 PACKI(desc
,"W",0); /* until time */
701 PACKS(desc
,"z",""); /* pSepFile */
702 PACKS(desc
,"z","lpd"); /* pPrProc */
703 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
704 PACKS(desc
,"z",""); /* pParms */
705 if (printer_info
->printername
== NULL
) {
706 PACKS(desc
,"z","UNKNOWN PRINTER");
707 PACKI(desc
,"W",LPSTAT_ERROR
);
709 PACKS(desc
,"z", printer_info
->comment
);
710 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
712 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
715 if (uLevel
== 3 || uLevel
== 4) {
716 PACKI(desc
,"W",5); /* uPriority */
717 PACKI(desc
,"W",0); /* uStarttime */
718 PACKI(desc
,"W",0); /* uUntiltime */
719 PACKI(desc
,"W",5); /* pad1 */
720 PACKS(desc
,"z",""); /* pszSepFile */
721 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
722 PACKS(desc
,"z",NULL
); /* pszParms */
723 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
724 /* "don't ask" that it's done this way to fix corrupted
725 Win9X/ME printer comments. */
726 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
727 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
728 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
729 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
730 PackDriverData(desc
); /* pDriverData */
733 if (uLevel
== 2 || uLevel
== 4) {
735 for (i
= 0; i
< count
; i
++) {
736 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
741 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
744 /* This function returns the number of files for a given driver */
745 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
749 /* count the number of files */
750 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
756 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
757 connection_struct
*conn
, uint16 vuid
,
758 char *param
, int tpscnt
,
759 char *data
, int tdscnt
,
760 int mdrcnt
,int mprcnt
,
761 char **rdata
,char **rparam
,
762 int *rdata_len
,int *rparam_len
)
764 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
765 char *str2
= skip_string(param
,tpscnt
,str1
);
766 char *p
= skip_string(param
,tpscnt
,str2
);
771 struct pack_desc desc
;
774 WERROR werr
= WERR_OK
;
775 TALLOC_CTX
*mem_ctx
= talloc_tos();
777 struct rpc_pipe_client
*cli
= NULL
;
778 struct dcerpc_binding_handle
*b
= NULL
;
779 struct policy_handle handle
;
780 struct spoolss_DevmodeContainer devmode_ctr
;
781 union spoolss_DriverInfo driver_info
;
782 union spoolss_JobInfo
*job_info
= NULL
;
783 union spoolss_PrinterInfo printer_info
;
785 if (!str1
|| !str2
|| !p
) {
788 memset((char *)&desc
,'\0',sizeof(desc
));
790 p
= skip_string(param
,tpscnt
,p
);
794 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
795 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
796 /* str3 may be null here and is checked in check_printq_info(). */
798 /* remove any trailing username */
799 if ((p
= strchr_m(QueueName
,'%')))
802 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
804 /* check it's a supported varient */
805 if (!prefix_ok(str1
,"zWrLh"))
807 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
809 * Patch from Scott Moomaw <scott@bridgewater.edu>
810 * to return the 'invalid info level' error if an
811 * unknown level was requested.
815 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
819 SSVALS(*rparam
,0,ERRunknownlevel
);
827 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
828 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
832 status
= rpc_pipe_open_interface(conn
,
833 &ndr_table_spoolss
.syntax_id
,
835 &conn
->sconn
->client_id
,
836 conn
->sconn
->msg_ctx
,
838 if (!NT_STATUS_IS_OK(status
)) {
839 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
841 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
844 b
= cli
->binding_handle
;
846 ZERO_STRUCT(devmode_ctr
);
848 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
855 if (!NT_STATUS_IS_OK(status
)) {
856 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
859 if (!W_ERROR_IS_OK(werr
)) {
860 desc
.errcode
= W_ERROR_V(werr
);
864 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
869 if (!W_ERROR_IS_OK(werr
)) {
870 desc
.errcode
= W_ERROR_V(werr
);
875 uint32_t server_major_version
;
876 uint32_t server_minor_version
;
878 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
886 &server_major_version
,
887 &server_minor_version
);
888 if (!W_ERROR_IS_OK(werr
)) {
889 desc
.errcode
= W_ERROR_V(werr
);
893 count
= get_printerdrivernumber(&driver_info
.info3
);
894 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
897 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
905 if (!W_ERROR_IS_OK(werr
)) {
906 desc
.errcode
= W_ERROR_V(werr
);
914 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
919 desc
.buflen
= mdrcnt
;
922 * Don't return data but need to get correct length
923 * init_package will return wrong size if buflen=0
925 desc
.buflen
= getlen(desc
.format
);
926 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
929 if (init_package(&desc
,1,count
)) {
930 desc
.subcount
= count
;
931 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
934 *rdata_len
= desc
.usedlen
;
937 * We must set the return code to ERRbuftoosmall
938 * in order to support lanman style printing with Win NT/2k
941 if (!mdrcnt
&& lp_disable_spoolss())
942 desc
.errcode
= ERRbuftoosmall
;
945 if (b
&& is_valid_policy_hnd(&handle
)) {
946 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
949 *rdata_len
= desc
.usedlen
;
951 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
956 SSVALS(*rparam
,0,desc
.errcode
);
958 SSVAL(*rparam
,4,desc
.neededlen
);
960 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
967 /****************************************************************************
968 View list of all print jobs on all queues.
969 ****************************************************************************/
971 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
972 connection_struct
*conn
, uint16 vuid
,
973 char *param
, int tpscnt
,
974 char *data
, int tdscnt
,
975 int mdrcnt
, int mprcnt
,
976 char **rdata
, char** rparam
,
977 int *rdata_len
, int *rparam_len
)
979 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
980 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
981 char *p
= skip_string(param
,tpscnt
,output_format1
);
982 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
983 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
985 struct pack_desc desc
;
986 int *subcntarr
= NULL
;
987 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
989 WERROR werr
= WERR_OK
;
990 TALLOC_CTX
*mem_ctx
= talloc_tos();
992 struct rpc_pipe_client
*cli
= NULL
;
993 struct dcerpc_binding_handle
*b
= NULL
;
994 struct spoolss_DevmodeContainer devmode_ctr
;
995 uint32_t num_printers
;
996 union spoolss_PrinterInfo
*printer_info
;
997 union spoolss_DriverInfo
*driver_info
;
998 union spoolss_JobInfo
**job_info
;
1000 if (!param_format
|| !output_format1
|| !p
) {
1004 memset((char *)&desc
,'\0',sizeof(desc
));
1006 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1008 if (!prefix_ok(param_format
,"WrLeh")) {
1011 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1013 * Patch from Scott Moomaw <scott@bridgewater.edu>
1014 * to return the 'invalid info level' error if an
1015 * unknown level was requested.
1019 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1023 SSVALS(*rparam
,0,ERRunknownlevel
);
1029 status
= rpc_pipe_open_interface(conn
,
1030 &ndr_table_spoolss
.syntax_id
,
1032 &conn
->sconn
->client_id
,
1033 conn
->sconn
->msg_ctx
,
1035 if (!NT_STATUS_IS_OK(status
)) {
1036 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1037 nt_errstr(status
)));
1038 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1041 b
= cli
->binding_handle
;
1043 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1045 cli
->srv_name_slash
,
1050 if (!W_ERROR_IS_OK(werr
)) {
1051 desc
.errcode
= W_ERROR_V(werr
);
1055 queuecnt
= num_printers
;
1057 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1058 if (job_info
== NULL
) {
1062 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1063 if (driver_info
== NULL
) {
1067 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1068 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1073 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1079 desc
.buflen
= mdrcnt
;
1082 for (i
= 0; i
< num_printers
; i
++) {
1085 struct policy_handle handle
;
1086 const char *printername
;
1088 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1089 if (printername
== NULL
) {
1093 ZERO_STRUCT(handle
);
1094 ZERO_STRUCT(devmode_ctr
);
1096 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
1103 if (!NT_STATUS_IS_OK(status
)) {
1104 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1107 if (!W_ERROR_IS_OK(werr
)) {
1108 desc
.errcode
= W_ERROR_V(werr
);
1112 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1120 if (!W_ERROR_IS_OK(werr
)) {
1121 desc
.errcode
= W_ERROR_V(werr
);
1126 uint32_t server_major_version
;
1127 uint32_t server_minor_version
;
1129 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1137 &server_major_version
,
1138 &server_minor_version
);
1139 if (!W_ERROR_IS_OK(werr
)) {
1140 desc
.errcode
= W_ERROR_V(werr
);
1145 subcntarr
[i
] = num_jobs
;
1146 subcnt
+= subcntarr
[i
];
1148 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1151 if (init_package(&desc
,queuecnt
,subcnt
)) {
1152 for (i
= 0; i
< num_printers
; i
++) {
1153 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1154 if (desc
.errcode
== NERR_Success
) {
1160 SAFE_FREE(subcntarr
);
1162 *rdata_len
= desc
.usedlen
;
1164 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1168 SSVALS(*rparam
,0,desc
.errcode
);
1170 SSVAL(*rparam
,4,succnt
);
1171 SSVAL(*rparam
,6,queuecnt
);
1177 SAFE_FREE(subcntarr
);
1182 /****************************************************************************
1183 Get info level for a server list query.
1184 ****************************************************************************/
1186 static bool check_session_info(int uLevel
, char* id
)
1190 if (strcmp(id
,"B16") != 0) {
1195 if (strcmp(id
,"B16BBDz") != 0) {
1205 struct srv_info_struct
{
1213 /*******************************************************************
1214 Get server info lists from the files saved by nmbd. Return the
1216 ******************************************************************/
1218 static int get_session_info(uint32 servertype
,
1219 struct srv_info_struct
**servers
,
1225 bool local_list_only
;
1228 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1230 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1234 /* request for everything is code for request all servers */
1235 if (servertype
== SV_TYPE_ALL
) {
1236 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1239 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1241 DEBUG(4,("Servertype search: %8x\n",servertype
));
1243 for (i
=0;lines
[i
];i
++) {
1245 struct srv_info_struct
*s
;
1246 const char *ptr
= lines
[i
];
1248 TALLOC_CTX
*frame
= NULL
;
1255 if (count
== alloced
) {
1257 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1259 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1263 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1265 s
= &(*servers
)[count
];
1267 frame
= talloc_stackframe();
1269 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1273 fstrcpy(s
->name
, p
);
1276 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1282 s
->comment
[0] = '\0';
1283 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1287 fstrcpy(s
->comment
, p
);
1288 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1290 s
->domain
[0] = '\0';
1291 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1292 /* this allows us to cope with an old nmbd */
1293 fstrcpy(s
->domain
,lp_workgroup());
1295 fstrcpy(s
->domain
, p
);
1299 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1300 DEBUG(4,("r:host file "));
1304 /* Filter the servers/domains we return based on what was asked for. */
1306 /* Check to see if we are being asked for a local list only. */
1307 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1308 DEBUG(4,("r: local list only"));
1312 /* doesn't match up: don't want it */
1313 if (!(servertype
& s
->type
)) {
1314 DEBUG(4,("r:serv type "));
1318 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1319 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1320 DEBUG(4,("s: dom mismatch "));
1324 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1328 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1329 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1332 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1333 s
->name
, s
->type
, s
->comment
, s
->domain
));
1334 s
->server_added
= True
;
1337 DEBUG(4,("%20s %8x %25s %15s\n",
1338 s
->name
, s
->type
, s
->comment
, s
->domain
));
1346 /*******************************************************************
1347 Fill in a server info structure.
1348 ******************************************************************/
1350 static int fill_srv_info(struct srv_info_struct
*service
,
1351 int uLevel
, char **buf
, int *buflen
,
1352 char **stringbuf
, int *stringspace
, char *baseaddr
)
1375 len
= strlen(service
->comment
)+1;
1379 *buflen
= struct_len
;
1381 return struct_len
+ len
;
1386 if (*buflen
< struct_len
) {
1393 p2
= p
+ struct_len
;
1394 l2
= *buflen
- struct_len
;
1402 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1406 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1407 SIVAL(p
,18,service
->type
);
1408 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1409 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1414 *buf
= p
+ struct_len
;
1415 *buflen
-= struct_len
;
1426 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1428 return StrCaseCmp(s1
->name
,s2
->name
);
1431 /****************************************************************************
1432 View list of servers available (or possibly domains). The info is
1433 extracted from lists saved by nmbd on the local host.
1434 ****************************************************************************/
1436 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1437 connection_struct
*conn
, uint16 vuid
,
1438 char *param
, int tpscnt
,
1439 char *data
, int tdscnt
,
1440 int mdrcnt
, int mprcnt
, char **rdata
,
1441 char **rparam
, int *rdata_len
, int *rparam_len
)
1443 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1444 char *str2
= skip_string(param
,tpscnt
,str1
);
1445 char *p
= skip_string(param
,tpscnt
,str2
);
1446 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1447 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1448 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1450 int data_len
, fixed_len
, string_len
;
1451 int f_len
= 0, s_len
= 0;
1452 struct srv_info_struct
*servers
=NULL
;
1453 int counted
=0,total
=0;
1456 bool domain_request
;
1459 if (!str1
|| !str2
|| !p
) {
1463 /* If someone sets all the bits they don't really mean to set
1464 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1467 if (servertype
== SV_TYPE_ALL
) {
1468 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1471 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1472 any other bit (they may just set this bit on its own) they
1473 want all the locally seen servers. However this bit can be
1474 set on its own so set the requested servers to be
1475 ALL - DOMAIN_ENUM. */
1477 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1478 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1481 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1482 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1486 if (!prefix_ok(str1
,"WrLehD")) {
1489 if (!check_session_info(uLevel
,str2
)) {
1493 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1494 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1495 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1497 if (strcmp(str1
, "WrLehDz") == 0) {
1498 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1501 pull_ascii_fstring(domain
, p
);
1503 fstrcpy(domain
, lp_workgroup());
1506 DEBUG(4, ("domain [%s]\n", domain
));
1508 if (lp_browse_list()) {
1509 total
= get_session_info(servertype
,&servers
,domain
);
1512 data_len
= fixed_len
= string_len
= 0;
1515 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1518 char *lastname
=NULL
;
1520 for (i
=0;i
<total
;i
++) {
1521 struct srv_info_struct
*s
= &servers
[i
];
1523 if (lastname
&& strequal(lastname
,s
->name
)) {
1527 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1528 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1529 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1531 if (data_len
< buf_len
) {
1534 string_len
+= s_len
;
1541 *rdata_len
= fixed_len
+ string_len
;
1542 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1547 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1553 char *lastname
=NULL
;
1554 int count2
= counted
;
1556 for (i
= 0; i
< total
&& count2
;i
++) {
1557 struct srv_info_struct
*s
= &servers
[i
];
1559 if (lastname
&& strequal(lastname
,s
->name
)) {
1563 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1564 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1565 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1571 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1575 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1577 SSVAL(*rparam
,4,counted
);
1578 SSVAL(*rparam
,6,counted
+missed
);
1582 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1583 domain
,uLevel
,counted
,counted
+missed
));
1588 static int srv_name_match(const char *n1
, const char *n2
)
1591 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1593 * In Windows, FirstNameToReturn need not be an exact match:
1594 * the server will return a list of servers that exist on
1595 * the network greater than or equal to the FirstNameToReturn.
1597 int ret
= StrCaseCmp(n1
, n2
);
1606 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1607 connection_struct
*conn
, uint16 vuid
,
1608 char *param
, int tpscnt
,
1609 char *data
, int tdscnt
,
1610 int mdrcnt
, int mprcnt
, char **rdata
,
1611 char **rparam
, int *rdata_len
, int *rparam_len
)
1613 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1614 char *str2
= skip_string(param
,tpscnt
,str1
);
1615 char *p
= skip_string(param
,tpscnt
,str2
);
1616 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1617 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1618 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1620 int data_len
, fixed_len
, string_len
;
1621 int f_len
= 0, s_len
= 0;
1622 struct srv_info_struct
*servers
=NULL
;
1623 int counted
=0,first
=0,total
=0;
1627 bool domain_request
;
1630 if (!str1
|| !str2
|| !p
) {
1634 /* If someone sets all the bits they don't really mean to set
1635 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1638 if (servertype
== SV_TYPE_ALL
) {
1639 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1642 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1643 any other bit (they may just set this bit on its own) they
1644 want all the locally seen servers. However this bit can be
1645 set on its own so set the requested servers to be
1646 ALL - DOMAIN_ENUM. */
1648 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1649 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1652 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1653 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1657 if (strcmp(str1
, "WrLehDzz") != 0) {
1660 if (!check_session_info(uLevel
,str2
)) {
1664 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1665 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1666 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1668 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1671 pull_ascii_fstring(domain
, p
);
1672 if (domain
[0] == '\0') {
1673 fstrcpy(domain
, lp_workgroup());
1675 p
= skip_string(param
,tpscnt
,p
);
1676 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1679 pull_ascii_fstring(first_name
, p
);
1681 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1682 domain
, first_name
));
1684 if (lp_browse_list()) {
1685 total
= get_session_info(servertype
,&servers
,domain
);
1688 data_len
= fixed_len
= string_len
= 0;
1691 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1693 if (first_name
[0] != '\0') {
1694 struct srv_info_struct
*first_server
= NULL
;
1696 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1697 srv_name_match
, first_server
);
1699 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1701 * The binary search may not find the exact match
1702 * so we need to search backward to find the first match
1704 * This implements the strange matching windows
1705 * implements. (see the comment in srv_name_match().
1709 ret
= StrCaseCmp(first_name
,
1710 servers
[first
-1].name
);
1717 /* we should return no entries */
1723 char *lastname
=NULL
;
1725 for (i
=first
;i
<total
;i
++) {
1726 struct srv_info_struct
*s
= &servers
[i
];
1728 if (lastname
&& strequal(lastname
,s
->name
)) {
1732 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1733 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1734 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1736 if (data_len
< buf_len
) {
1739 string_len
+= s_len
;
1746 *rdata_len
= fixed_len
+ string_len
;
1747 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1752 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1758 char *lastname
=NULL
;
1759 int count2
= counted
;
1761 for (i
= first
; i
< total
&& count2
;i
++) {
1762 struct srv_info_struct
*s
= &servers
[i
];
1764 if (lastname
&& strequal(lastname
,s
->name
)) {
1768 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1769 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1770 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1776 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1780 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1782 SSVAL(*rparam
,4,counted
);
1783 SSVAL(*rparam
,6,counted
+missed
);
1785 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1786 domain
,uLevel
,first
,first_name
,
1787 first
< total
? servers
[first
].name
: "",
1788 counted
,counted
+missed
));
1795 /****************************************************************************
1796 command 0x34 - suspected of being a "Lookup Names" stub api
1797 ****************************************************************************/
1799 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1800 connection_struct
*conn
, uint16 vuid
,
1801 char *param
, int tpscnt
,
1802 char *data
, int tdscnt
,
1803 int mdrcnt
, int mprcnt
, char **rdata
,
1804 char **rparam
, int *rdata_len
, int *rparam_len
)
1806 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1807 char *str2
= skip_string(param
,tpscnt
,str1
);
1808 char *p
= skip_string(param
,tpscnt
,str2
);
1809 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1810 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1814 if (!str1
|| !str2
|| !p
) {
1818 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1819 str1
, str2
, p
, uLevel
, buf_len
));
1821 if (!prefix_ok(str1
,"zWrLeh")) {
1828 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1833 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1835 SSVAL(*rparam
,4,counted
);
1836 SSVAL(*rparam
,6,counted
+missed
);
1841 /****************************************************************************
1842 get info about a share
1843 ****************************************************************************/
1845 static bool check_share_info(int uLevel
, char* id
)
1849 if (strcmp(id
,"B13") != 0) {
1854 /* Level-2 descriptor is allowed (and ignored) */
1855 if (strcmp(id
,"B13BWz") != 0 &&
1856 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1861 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1866 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1876 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1877 char** buf
, int* buflen
,
1878 char** stringbuf
, int* stringspace
, char* baseaddr
)
1907 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1910 len
+= strlen(lp_pathname(snum
)) + 1;
1913 *buflen
= struct_len
;
1918 return struct_len
+ len
;
1923 if ((*buflen
) < struct_len
) {
1931 p2
= p
+ struct_len
;
1932 l2
= (*buflen
) - struct_len
;
1939 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1945 type
= STYPE_DISKTREE
;
1946 if (lp_print_ok(snum
)) {
1947 type
= STYPE_PRINTQ
;
1949 if (strequal("IPC",lp_fstype(snum
))) {
1952 SSVAL(p
,14,type
); /* device type */
1953 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1954 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1958 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1959 SSVALS(p
,22,-1); /* max uses */
1960 SSVAL(p
,24,1); /* current uses */
1961 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1962 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1963 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1967 memset(p
+40,0,SHPWLEN
+2);
1978 (*buf
) = p
+ struct_len
;
1979 (*buflen
) -= struct_len
;
1981 (*stringspace
) = l2
;
1990 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
1991 connection_struct
*conn
,uint16 vuid
,
1992 char *param
, int tpscnt
,
1993 char *data
, int tdscnt
,
1994 int mdrcnt
,int mprcnt
,
1995 char **rdata
,char **rparam
,
1996 int *rdata_len
,int *rparam_len
)
1998 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1999 char *str2
= skip_string(param
,tpscnt
,str1
);
2000 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2001 char *netname
= NULL
;
2002 char *p
= skip_string(param
,tpscnt
,netname
);
2003 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2006 if (!str1
|| !str2
|| !netname
|| !p
) {
2010 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2011 if (snum
< 0 || !netname
) {
2015 /* check it's a supported varient */
2016 if (!prefix_ok(str1
,"zWrLh")) {
2019 if (!check_share_info(uLevel
,str2
)) {
2023 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2028 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2029 if (*rdata_len
< 0) {
2034 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2038 SSVAL(*rparam
,0,NERR_Success
);
2039 SSVAL(*rparam
,2,0); /* converter word */
2040 SSVAL(*rparam
,4,*rdata_len
);
2045 /****************************************************************************
2046 View the list of available shares.
2048 This function is the server side of the NetShareEnum() RAP call.
2049 It fills the return buffer with share names and share comments.
2050 Note that the return buffer normally (in all known cases) allows only
2051 twelve byte strings for share names (plus one for a nul terminator).
2052 Share names longer than 12 bytes must be skipped.
2053 ****************************************************************************/
2055 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2056 connection_struct
*conn
, uint16 vuid
,
2057 char *param
, int tpscnt
,
2058 char *data
, int tdscnt
,
2066 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2067 char *str2
= skip_string(param
,tpscnt
,str1
);
2068 char *p
= skip_string(param
,tpscnt
,str2
);
2069 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2070 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2073 int total
=0,counted
=0;
2074 bool missed
= False
;
2076 int data_len
, fixed_len
, string_len
;
2077 int f_len
= 0, s_len
= 0;
2079 if (!str1
|| !str2
|| !p
) {
2083 if (!prefix_ok(str1
,"WrLeh")) {
2086 if (!check_share_info(uLevel
,str2
)) {
2090 /* Ensure all the usershares are loaded. */
2092 load_registry_shares();
2093 count
= load_usershare_shares();
2096 data_len
= fixed_len
= string_len
= 0;
2097 for (i
=0;i
<count
;i
++) {
2098 fstring servicename_dos
;
2099 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2102 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2103 /* Maximum name length = 13. */
2104 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2106 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2107 if (data_len
< buf_len
) {
2110 string_len
+= s_len
;
2117 *rdata_len
= fixed_len
+ string_len
;
2118 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2123 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2128 for( i
= 0; i
< count
; i
++ ) {
2129 fstring servicename_dos
;
2130 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2134 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2135 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2136 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2143 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2147 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2149 SSVAL(*rparam
,4,counted
);
2150 SSVAL(*rparam
,6,total
);
2152 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2153 counted
,total
,uLevel
,
2154 buf_len
,*rdata_len
,mdrcnt
));
2159 /****************************************************************************
2161 ****************************************************************************/
2163 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2164 connection_struct
*conn
,uint16 vuid
,
2165 char *param
, int tpscnt
,
2166 char *data
, int tdscnt
,
2167 int mdrcnt
,int mprcnt
,
2168 char **rdata
,char **rparam
,
2169 int *rdata_len
,int *rparam_len
)
2171 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2172 char *str2
= skip_string(param
,tpscnt
,str1
);
2173 char *p
= skip_string(param
,tpscnt
,str2
);
2174 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2177 char *pathname
= NULL
;
2178 unsigned int offset
;
2180 size_t converted_size
;
2182 WERROR werr
= WERR_OK
;
2183 TALLOC_CTX
*mem_ctx
= talloc_tos();
2185 struct rpc_pipe_client
*cli
= NULL
;
2186 union srvsvc_NetShareInfo info
;
2187 struct srvsvc_NetShareInfo2 info2
;
2188 struct dcerpc_binding_handle
*b
;
2190 if (!str1
|| !str2
|| !p
) {
2194 /* check it's a supported varient */
2195 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2198 if (!check_share_info(uLevel
,str2
)) {
2205 /* Do we have a string ? */
2206 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2209 pull_ascii_fstring(sharename
,data
);
2215 /* only support disk share adds */
2216 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2220 offset
= IVAL(data
, 16);
2221 if (offset
>= mdrcnt
) {
2222 res
= ERRinvalidparam
;
2226 /* Do we have a string ? */
2227 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2230 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2232 offset
= IVAL(data
, 26);
2234 if (offset
>= mdrcnt
) {
2235 res
= ERRinvalidparam
;
2239 /* Do we have a string ? */
2240 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2244 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2245 offset
? (data
+offset
) : "", &converted_size
))
2247 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2255 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2257 &conn
->sconn
->client_id
,
2258 conn
->sconn
->msg_ctx
,
2260 if (!NT_STATUS_IS_OK(status
)) {
2261 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2262 nt_errstr(status
)));
2263 res
= W_ERROR_V(ntstatus_to_werror(status
));
2267 b
= cli
->binding_handle
;
2269 info2
.name
= sharename
;
2270 info2
.type
= STYPE_DISKTREE
;
2271 info2
.comment
= comment
;
2272 info2
.permissions
= 0;
2273 info2
.max_users
= 0;
2274 info2
.current_users
= 0;
2275 info2
.path
= pathname
;
2276 info2
.password
= NULL
;
2278 info
.info2
= &info2
;
2280 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2281 cli
->srv_name_slash
,
2286 if (!NT_STATUS_IS_OK(status
)) {
2287 res
= W_ERROR_V(ntstatus_to_werror(status
));
2290 if (!W_ERROR_IS_OK(werr
)) {
2291 res
= W_ERROR_V(werr
);
2296 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2300 SSVAL(*rparam
,0,NERR_Success
);
2301 SSVAL(*rparam
,2,0); /* converter word */
2302 SSVAL(*rparam
,4,*rdata_len
);
2310 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2315 SSVAL(*rparam
,0,res
);
2320 /****************************************************************************
2321 view list of groups available
2322 ****************************************************************************/
2324 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2325 connection_struct
*conn
,uint16 vuid
,
2326 char *param
, int tpscnt
,
2327 char *data
, int tdscnt
,
2328 int mdrcnt
,int mprcnt
,
2329 char **rdata
,char **rparam
,
2330 int *rdata_len
,int *rparam_len
)
2334 int resume_context
, cli_buf_size
;
2335 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2336 char *str2
= skip_string(param
,tpscnt
,str1
);
2337 char *p
= skip_string(param
,tpscnt
,str2
);
2339 uint32_t num_groups
;
2340 uint32_t resume_handle
;
2341 struct rpc_pipe_client
*samr_pipe
;
2342 struct policy_handle samr_handle
, domain_handle
;
2343 NTSTATUS status
, result
;
2344 struct dcerpc_binding_handle
*b
;
2346 if (!str1
|| !str2
|| !p
) {
2350 if (strcmp(str1
,"WrLeh") != 0) {
2355 * W-> resume context (number of users to skip)
2356 * r -> return parameter pointer to receive buffer
2357 * L -> length of receive buffer
2358 * e -> return parameter number of entries
2359 * h -> return parameter total number of users
2362 if (strcmp("B21",str2
) != 0) {
2366 status
= rpc_pipe_open_internal(
2367 talloc_tos(), &ndr_table_samr
.syntax_id
,
2368 conn
->session_info
, &conn
->sconn
->client_id
,
2369 conn
->sconn
->msg_ctx
, &samr_pipe
);
2370 if (!NT_STATUS_IS_OK(status
)) {
2371 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2372 nt_errstr(status
)));
2376 b
= samr_pipe
->binding_handle
;
2378 status
= dcerpc_samr_Connect2(b
, talloc_tos(), global_myname(),
2379 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2381 if (!NT_STATUS_IS_OK(status
)) {
2382 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2383 nt_errstr(status
)));
2386 if (!NT_STATUS_IS_OK(result
)) {
2387 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2388 nt_errstr(result
)));
2392 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2393 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2394 get_global_sam_sid(), &domain_handle
,
2396 if (!NT_STATUS_IS_OK(status
)) {
2397 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2398 nt_errstr(status
)));
2399 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2402 if (!NT_STATUS_IS_OK(result
)) {
2403 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2404 nt_errstr(result
)));
2405 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2409 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2410 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2411 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2412 "%d\n", resume_context
, cli_buf_size
));
2414 *rdata_len
= cli_buf_size
;
2415 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2422 errflags
= NERR_Success
;
2427 struct samr_SamArray
*sam_entries
;
2428 uint32_t num_entries
;
2430 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2436 if (!NT_STATUS_IS_OK(status
)) {
2437 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2438 "%s\n", nt_errstr(status
)));
2441 if (!NT_STATUS_IS_OK(result
)) {
2443 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2444 "%s\n", nt_errstr(result
)));
2448 if (num_entries
== 0) {
2449 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2450 "no entries -- done\n"));
2454 for(i
=0; i
<num_entries
; i
++) {
2457 name
= sam_entries
->entries
[i
].name
.string
;
2459 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2460 /* set overflow error */
2461 DEBUG(3,("overflow on entry %d group %s\n", i
,
2467 /* truncate the name at 21 chars. */
2469 strlcpy(p
, name
, 21);
2470 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2472 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2477 if (errflags
!= NERR_Success
) {
2481 TALLOC_FREE(sam_entries
);
2484 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2485 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2487 *rdata_len
= PTR_DIFF(p
,*rdata
);
2490 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2494 SSVAL(*rparam
, 0, errflags
);
2495 SSVAL(*rparam
, 2, 0); /* converter word */
2496 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2497 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2502 /*******************************************************************
2503 Get groups that a user is a member of.
2504 ******************************************************************/
2506 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2507 connection_struct
*conn
,uint16 vuid
,
2508 char *param
, int tpscnt
,
2509 char *data
, int tdscnt
,
2510 int mdrcnt
,int mprcnt
,
2511 char **rdata
,char **rparam
,
2512 int *rdata_len
,int *rparam_len
)
2514 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2515 char *str2
= skip_string(param
,tpscnt
,str1
);
2516 char *UserName
= skip_string(param
,tpscnt
,str2
);
2517 char *p
= skip_string(param
,tpscnt
,UserName
);
2518 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2519 const char *level_string
;
2525 struct rpc_pipe_client
*samr_pipe
;
2526 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2527 struct lsa_String name
;
2528 struct lsa_Strings names
;
2529 struct samr_Ids type
, rid
;
2530 struct samr_RidWithAttributeArray
*rids
;
2531 NTSTATUS status
, result
;
2532 struct dcerpc_binding_handle
*b
;
2534 if (!str1
|| !str2
|| !UserName
|| !p
) {
2539 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2544 /* check it's a supported varient */
2546 if ( strcmp(str1
,"zWrLeh") != 0 )
2551 level_string
= "B21";
2557 if (strcmp(level_string
,str2
) != 0)
2560 *rdata_len
= mdrcnt
+ 1024;
2561 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2566 SSVAL(*rparam
,0,NERR_Success
);
2567 SSVAL(*rparam
,2,0); /* converter word */
2570 endp
= *rdata
+ *rdata_len
;
2572 status
= rpc_pipe_open_internal(
2573 talloc_tos(), &ndr_table_samr
.syntax_id
,
2574 conn
->session_info
, &conn
->sconn
->client_id
,
2575 conn
->sconn
->msg_ctx
, &samr_pipe
);
2576 if (!NT_STATUS_IS_OK(status
)) {
2577 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2578 nt_errstr(status
)));
2582 b
= samr_pipe
->binding_handle
;
2584 status
= dcerpc_samr_Connect2(b
, talloc_tos(), global_myname(),
2585 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2587 if (!NT_STATUS_IS_OK(status
)) {
2588 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2589 nt_errstr(status
)));
2592 if (!NT_STATUS_IS_OK(result
)) {
2593 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2594 nt_errstr(result
)));
2598 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2599 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2600 get_global_sam_sid(), &domain_handle
,
2602 if (!NT_STATUS_IS_OK(status
)) {
2603 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2604 nt_errstr(status
)));
2607 if (!NT_STATUS_IS_OK(result
)) {
2608 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2609 nt_errstr(result
)));
2613 name
.string
= UserName
;
2615 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2616 &domain_handle
, 1, &name
,
2619 if (!NT_STATUS_IS_OK(status
)) {
2620 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2621 nt_errstr(status
)));
2624 if (!NT_STATUS_IS_OK(result
)) {
2625 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2626 nt_errstr(result
)));
2630 if (type
.ids
[0] != SID_NAME_USER
) {
2631 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2632 sid_type_lookup(type
.ids
[0])));
2636 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2638 SAMR_USER_ACCESS_GET_GROUPS
,
2639 rid
.ids
[0], &user_handle
,
2641 if (!NT_STATUS_IS_OK(status
)) {
2642 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2643 nt_errstr(status
)));
2646 if (!NT_STATUS_IS_OK(result
)) {
2647 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2648 nt_errstr(result
)));
2652 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2653 &user_handle
, &rids
,
2655 if (!NT_STATUS_IS_OK(status
)) {
2656 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2657 nt_errstr(status
)));
2660 if (!NT_STATUS_IS_OK(result
)) {
2661 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2662 nt_errstr(result
)));
2666 for (i
=0; i
<rids
->count
; i
++) {
2668 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2670 1, &rids
->rids
[i
].rid
,
2673 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2674 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2680 *rdata_len
= PTR_DIFF(p
,*rdata
);
2682 SSVAL(*rparam
,4,count
); /* is this right?? */
2683 SSVAL(*rparam
,6,count
); /* is this right?? */
2688 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2690 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2692 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2697 /*******************************************************************
2699 ******************************************************************/
2701 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2702 connection_struct
*conn
, uint16 vuid
,
2703 char *param
, int tpscnt
,
2704 char *data
, int tdscnt
,
2705 int mdrcnt
,int mprcnt
,
2706 char **rdata
,char **rparam
,
2707 int *rdata_len
,int *rparam_len
)
2712 int i
, resume_context
, cli_buf_size
;
2713 uint32_t resume_handle
;
2715 struct rpc_pipe_client
*samr_pipe
;
2716 struct policy_handle samr_handle
, domain_handle
;
2717 NTSTATUS status
, result
;
2719 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2720 char *str2
= skip_string(param
,tpscnt
,str1
);
2721 char *p
= skip_string(param
,tpscnt
,str2
);
2724 struct dcerpc_binding_handle
*b
;
2726 if (!str1
|| !str2
|| !p
) {
2730 if (strcmp(str1
,"WrLeh") != 0)
2733 * W-> resume context (number of users to skip)
2734 * r -> return parameter pointer to receive buffer
2735 * L -> length of receive buffer
2736 * e -> return parameter number of entries
2737 * h -> return parameter total number of users
2740 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2741 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2742 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2743 resume_context
, cli_buf_size
));
2746 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2751 /* check it's a supported varient */
2752 if (strcmp("B21",str2
) != 0)
2755 *rdata_len
= cli_buf_size
;
2756 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2762 endp
= *rdata
+ *rdata_len
;
2764 status
= rpc_pipe_open_internal(
2765 talloc_tos(), &ndr_table_samr
.syntax_id
,
2766 conn
->session_info
, &conn
->sconn
->client_id
,
2767 conn
->sconn
->msg_ctx
, &samr_pipe
);
2768 if (!NT_STATUS_IS_OK(status
)) {
2769 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2770 nt_errstr(status
)));
2774 b
= samr_pipe
->binding_handle
;
2776 status
= dcerpc_samr_Connect2(b
, talloc_tos(), global_myname(),
2777 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2779 if (!NT_STATUS_IS_OK(status
)) {
2780 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2781 nt_errstr(status
)));
2784 if (!NT_STATUS_IS_OK(result
)) {
2785 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2786 nt_errstr(result
)));
2790 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2791 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2792 get_global_sam_sid(), &domain_handle
,
2794 if (!NT_STATUS_IS_OK(status
)) {
2795 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2796 nt_errstr(status
)));
2797 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2800 if (!NT_STATUS_IS_OK(result
)) {
2801 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2802 nt_errstr(result
)));
2803 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2807 errflags
=NERR_Success
;
2812 struct samr_SamArray
*sam_entries
;
2813 uint32_t num_entries
;
2815 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2822 if (!NT_STATUS_IS_OK(status
)) {
2823 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2824 "%s\n", nt_errstr(status
)));
2827 if (!NT_STATUS_IS_OK(result
)) {
2828 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2829 "%s\n", nt_errstr(result
)));
2833 if (num_entries
== 0) {
2834 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2835 "no entries -- done\n"));
2839 for (i
=0; i
<num_entries
; i
++) {
2842 name
= sam_entries
->entries
[i
].name
.string
;
2844 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2845 &&(strlen(name
)<=21)) {
2846 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2847 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2848 "username %s\n",count_sent
,p
));
2852 /* set overflow error */
2853 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2854 "username %s\n",count_sent
,name
));
2860 if (errflags
!= NERR_Success
) {
2864 TALLOC_FREE(sam_entries
);
2867 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2868 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2870 *rdata_len
= PTR_DIFF(p
,*rdata
);
2872 SSVAL(*rparam
,0,errflags
);
2873 SSVAL(*rparam
,2,0); /* converter word */
2874 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2875 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2880 /****************************************************************************
2881 Get the time of day info.
2882 ****************************************************************************/
2884 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2885 connection_struct
*conn
,uint16 vuid
,
2886 char *param
, int tpscnt
,
2887 char *data
, int tdscnt
,
2888 int mdrcnt
,int mprcnt
,
2889 char **rdata
,char **rparam
,
2890 int *rdata_len
,int *rparam_len
)
2893 time_t unixdate
= time(NULL
);
2897 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2903 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2908 SSVAL(*rparam
,0,NERR_Success
);
2909 SSVAL(*rparam
,2,0); /* converter word */
2913 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2914 by NT in a "net time" operation,
2915 it seems to ignore the one below */
2917 /* the client expects to get localtime, not GMT, in this bit
2918 (I think, this needs testing) */
2919 t
= localtime(&unixdate
);
2924 SIVAL(p
,4,0); /* msecs ? */
2925 SCVAL(p
,8,t
->tm_hour
);
2926 SCVAL(p
,9,t
->tm_min
);
2927 SCVAL(p
,10,t
->tm_sec
);
2928 SCVAL(p
,11,0); /* hundredths of seconds */
2929 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2930 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2931 SCVAL(p
,16,t
->tm_mday
);
2932 SCVAL(p
,17,t
->tm_mon
+ 1);
2933 SSVAL(p
,18,1900+t
->tm_year
);
2934 SCVAL(p
,20,t
->tm_wday
);
2939 /****************************************************************************
2940 Set the user password.
2941 *****************************************************************************/
2943 static bool api_SetUserPassword(struct smbd_server_connection
*sconn
,
2944 connection_struct
*conn
,uint16 vuid
,
2945 char *param
, int tpscnt
,
2946 char *data
, int tdscnt
,
2947 int mdrcnt
,int mprcnt
,
2948 char **rdata
,char **rparam
,
2949 int *rdata_len
,int *rparam_len
)
2951 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2954 fstring pass1
,pass2
;
2955 TALLOC_CTX
*mem_ctx
= talloc_tos();
2956 NTSTATUS status
, result
;
2957 struct rpc_pipe_client
*cli
= NULL
;
2958 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2959 struct lsa_String domain_name
;
2960 struct dom_sid2
*domain_sid
;
2961 struct lsa_String names
;
2962 struct samr_Ids rids
;
2963 struct samr_Ids types
;
2964 struct samr_Password old_lm_hash
;
2965 struct samr_Password new_lm_hash
;
2966 int errcode
= NERR_badpass
;
2970 struct dcerpc_binding_handle
*b
= NULL
;
2972 /* Skip 2 strings. */
2973 p
= skip_string(param
,tpscnt
,np
);
2974 p
= skip_string(param
,tpscnt
,p
);
2980 /* Do we have a string ? */
2981 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2984 pull_ascii_fstring(user
,p
);
2986 p
= skip_string(param
,tpscnt
,p
);
2991 memset(pass1
,'\0',sizeof(pass1
));
2992 memset(pass2
,'\0',sizeof(pass2
));
2994 * We use 31 here not 32 as we're checking
2995 * the last byte we want to access is safe.
2997 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
3001 memcpy(pass2
,p
+16,16);
3003 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
3004 if (encrypted
== -1) {
3005 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3009 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
3010 if (min_pwd_length
== -1) {
3011 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3016 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3023 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
3024 user
, encrypted
, min_pwd_length
));
3026 ZERO_STRUCT(connect_handle
);
3027 ZERO_STRUCT(domain_handle
);
3028 ZERO_STRUCT(user_handle
);
3030 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3032 &conn
->sconn
->client_id
,
3033 conn
->sconn
->msg_ctx
,
3035 if (!NT_STATUS_IS_OK(status
)) {
3036 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
3037 nt_errstr(status
)));
3038 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3042 b
= cli
->binding_handle
;
3044 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
3046 SAMR_ACCESS_CONNECT_TO_SERVER
|
3047 SAMR_ACCESS_ENUM_DOMAINS
|
3048 SAMR_ACCESS_LOOKUP_DOMAIN
,
3051 if (!NT_STATUS_IS_OK(status
)) {
3052 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3055 if (!NT_STATUS_IS_OK(result
)) {
3056 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3060 init_lsa_String(&domain_name
, get_global_sam_name());
3062 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
3067 if (!NT_STATUS_IS_OK(status
)) {
3068 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3071 if (!NT_STATUS_IS_OK(result
)) {
3072 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3076 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
3078 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
3082 if (!NT_STATUS_IS_OK(status
)) {
3083 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3086 if (!NT_STATUS_IS_OK(result
)) {
3087 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3091 init_lsa_String(&names
, user
);
3093 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
3100 if (!NT_STATUS_IS_OK(status
)) {
3101 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3104 if (!NT_STATUS_IS_OK(result
)) {
3105 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3109 if (rids
.count
!= 1) {
3110 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
3113 if (rids
.count
!= types
.count
) {
3114 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3117 if (types
.ids
[0] != SID_NAME_USER
) {
3118 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3124 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
3126 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
3130 if (!NT_STATUS_IS_OK(status
)) {
3131 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3134 if (!NT_STATUS_IS_OK(result
)) {
3135 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3139 if (encrypted
== 0) {
3140 E_deshash(pass1
, old_lm_hash
.hash
);
3141 E_deshash(pass2
, new_lm_hash
.hash
);
3143 ZERO_STRUCT(old_lm_hash
);
3144 ZERO_STRUCT(new_lm_hash
);
3145 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
3146 memcpy(new_lm_hash
.hash
, pass1
, MIN(strlen(pass2
), 16));
3149 status
= dcerpc_samr_ChangePasswordUser(b
, mem_ctx
,
3151 true, /* lm_present */
3154 false, /* nt_present */
3155 NULL
, /* old_nt_crypted */
3156 NULL
, /* new_nt_crypted */
3157 false, /* cross1_present */
3158 NULL
, /* nt_cross */
3159 false, /* cross2_present */
3160 NULL
, /* lm_cross */
3162 if (!NT_STATUS_IS_OK(status
)) {
3163 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3166 if (!NT_STATUS_IS_OK(result
)) {
3167 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3171 errcode
= NERR_Success
;
3174 if (b
&& is_valid_policy_hnd(&user_handle
)) {
3175 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
3177 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
3178 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
3180 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
3181 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
3184 memset((char *)pass1
,'\0',sizeof(fstring
));
3185 memset((char *)pass2
,'\0',sizeof(fstring
));
3187 SSVAL(*rparam
,0,errcode
);
3188 SSVAL(*rparam
,2,0); /* converter word */
3192 /****************************************************************************
3193 Set the user password (SamOEM version - gets plaintext).
3194 ****************************************************************************/
3196 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3197 connection_struct
*conn
,uint16 vuid
,
3198 char *param
, int tpscnt
,
3199 char *data
, int tdscnt
,
3200 int mdrcnt
,int mprcnt
,
3201 char **rdata
,char **rparam
,
3202 int *rdata_len
,int *rparam_len
)
3205 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3207 TALLOC_CTX
*mem_ctx
= talloc_tos();
3208 NTSTATUS status
, result
;
3209 struct rpc_pipe_client
*cli
= NULL
;
3210 struct lsa_AsciiString server
, account
;
3211 struct samr_CryptPassword password
;
3212 struct samr_Password hash
;
3213 int errcode
= NERR_badpass
;
3215 struct dcerpc_binding_handle
*b
;
3218 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3228 SSVAL(*rparam
,0,NERR_badpass
);
3231 * Check the parameter definition is correct.
3234 /* Do we have a string ? */
3235 if (skip_string(param
,tpscnt
,p
) == 0) {
3238 if(!strequal(p
, "zsT")) {
3239 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3242 p
= skip_string(param
, tpscnt
, p
);
3247 /* Do we have a string ? */
3248 if (skip_string(param
,tpscnt
,p
) == 0) {
3251 if(!strequal(p
, "B516B16")) {
3252 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3255 p
= skip_string(param
,tpscnt
,p
);
3259 /* Do we have a string ? */
3260 if (skip_string(param
,tpscnt
,p
) == 0) {
3263 p
+= pull_ascii_fstring(user
,p
);
3265 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3267 if (tdscnt
!= 532) {
3268 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3272 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3273 if (bufsize
!= 532) {
3274 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3278 memcpy(password
.data
, data
, 516);
3279 memcpy(hash
.hash
, data
+516, 16);
3281 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3283 &conn
->sconn
->client_id
,
3284 conn
->sconn
->msg_ctx
,
3286 if (!NT_STATUS_IS_OK(status
)) {
3287 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3288 nt_errstr(status
)));
3289 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3293 b
= cli
->binding_handle
;
3295 init_lsa_AsciiString(&server
, global_myname());
3296 init_lsa_AsciiString(&account
, user
);
3298 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3304 if (!NT_STATUS_IS_OK(status
)) {
3305 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3308 if (!NT_STATUS_IS_OK(result
)) {
3309 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3313 errcode
= NERR_Success
;
3315 SSVAL(*rparam
,0,errcode
);
3316 SSVAL(*rparam
,2,0); /* converter word */
3321 /****************************************************************************
3324 ****************************************************************************/
3326 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3327 connection_struct
*conn
,uint16 vuid
,
3328 char *param
, int tpscnt
,
3329 char *data
, int tdscnt
,
3330 int mdrcnt
,int mprcnt
,
3331 char **rdata
,char **rparam
,
3332 int *rdata_len
,int *rparam_len
)
3334 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3335 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3336 char *str2
= skip_string(param
,tpscnt
,str1
);
3337 char *p
= skip_string(param
,tpscnt
,str2
);
3341 WERROR werr
= WERR_OK
;
3343 TALLOC_CTX
*mem_ctx
= talloc_tos();
3345 struct rpc_pipe_client
*cli
= NULL
;
3346 struct dcerpc_binding_handle
*b
= NULL
;
3347 struct policy_handle handle
;
3348 struct spoolss_DevmodeContainer devmode_ctr
;
3349 enum spoolss_JobControl command
;
3351 if (!str1
|| !str2
|| !p
) {
3355 * We use 1 here not 2 as we're checking
3356 * the last byte we want to access is safe.
3358 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3361 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3364 /* check it's a supported varient */
3365 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3369 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3375 ZERO_STRUCT(handle
);
3377 status
= rpc_pipe_open_interface(conn
,
3378 &ndr_table_spoolss
.syntax_id
,
3380 &conn
->sconn
->client_id
,
3381 conn
->sconn
->msg_ctx
,
3383 if (!NT_STATUS_IS_OK(status
)) {
3384 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3385 nt_errstr(status
)));
3386 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3389 b
= cli
->binding_handle
;
3391 ZERO_STRUCT(devmode_ctr
);
3393 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3397 JOB_ACCESS_ADMINISTER
,
3400 if (!NT_STATUS_IS_OK(status
)) {
3401 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3404 if (!W_ERROR_IS_OK(werr
)) {
3405 errcode
= W_ERROR_V(werr
);
3409 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3410 * and NERR_DestNotFound if share did not exist */
3412 errcode
= NERR_Success
;
3415 case 81: /* delete */
3416 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3418 case 82: /* pause */
3419 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3421 case 83: /* resume */
3422 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3425 errcode
= NERR_notsupported
;
3429 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3432 NULL
, /* unique ptr ctr */
3435 if (!NT_STATUS_IS_OK(status
)) {
3436 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3439 if (!W_ERROR_IS_OK(werr
)) {
3440 errcode
= W_ERROR_V(werr
);
3445 if (b
&& is_valid_policy_hnd(&handle
)) {
3446 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3449 SSVAL(*rparam
,0,errcode
);
3450 SSVAL(*rparam
,2,0); /* converter word */
3455 /****************************************************************************
3456 Purge a print queue - or pause or resume it.
3457 ****************************************************************************/
3459 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3460 connection_struct
*conn
,uint16 vuid
,
3461 char *param
, int tpscnt
,
3462 char *data
, int tdscnt
,
3463 int mdrcnt
,int mprcnt
,
3464 char **rdata
,char **rparam
,
3465 int *rdata_len
,int *rparam_len
)
3467 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3468 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3469 char *str2
= skip_string(param
,tpscnt
,str1
);
3470 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3471 int errcode
= NERR_notsupported
;
3472 WERROR werr
= WERR_OK
;
3475 TALLOC_CTX
*mem_ctx
= talloc_tos();
3476 struct rpc_pipe_client
*cli
= NULL
;
3477 struct dcerpc_binding_handle
*b
= NULL
;
3478 struct policy_handle handle
;
3479 struct spoolss_SetPrinterInfoCtr info_ctr
;
3480 struct spoolss_DevmodeContainer devmode_ctr
;
3481 struct sec_desc_buf secdesc_ctr
;
3482 enum spoolss_PrinterControl command
;
3484 if (!str1
|| !str2
|| !QueueName
) {
3488 /* check it's a supported varient */
3489 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3493 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3499 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3503 ZERO_STRUCT(handle
);
3505 status
= rpc_pipe_open_interface(conn
,
3506 &ndr_table_spoolss
.syntax_id
,
3508 &conn
->sconn
->client_id
,
3509 conn
->sconn
->msg_ctx
,
3511 if (!NT_STATUS_IS_OK(status
)) {
3512 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3513 nt_errstr(status
)));
3514 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3517 b
= cli
->binding_handle
;
3519 ZERO_STRUCT(devmode_ctr
);
3521 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3525 SEC_FLAG_MAXIMUM_ALLOWED
,
3528 if (!NT_STATUS_IS_OK(status
)) {
3529 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3532 if (!W_ERROR_IS_OK(werr
)) {
3533 errcode
= W_ERROR_V(werr
);
3538 case 74: /* Pause queue */
3539 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3541 case 75: /* Resume queue */
3542 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3544 case 103: /* Purge */
3545 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3548 werr
= WERR_NOT_SUPPORTED
;
3552 if (!W_ERROR_IS_OK(werr
)) {
3553 errcode
= W_ERROR_V(werr
);
3557 ZERO_STRUCT(info_ctr
);
3558 ZERO_STRUCT(secdesc_ctr
);
3560 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3567 if (!NT_STATUS_IS_OK(status
)) {
3568 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3571 if (!W_ERROR_IS_OK(werr
)) {
3572 errcode
= W_ERROR_V(werr
);
3576 errcode
= W_ERROR_V(werr
);
3580 if (b
&& is_valid_policy_hnd(&handle
)) {
3581 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3584 SSVAL(*rparam
,0,errcode
);
3585 SSVAL(*rparam
,2,0); /* converter word */
3590 /****************************************************************************
3591 set the property of a print job (undocumented?)
3592 ? function = 0xb -> set name of print job
3593 ? function = 0x6 -> move print job up/down
3594 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3595 or <WWsTP> <WB21BB16B10zWWzDDz>
3596 ****************************************************************************/
3598 static int check_printjob_info(struct pack_desc
* desc
,
3599 int uLevel
, char* id
)
3601 desc
->subformat
= NULL
;
3603 case 0: desc
->format
= "W"; break;
3604 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3605 case 2: desc
->format
= "WWzWWDDzz"; break;
3606 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3607 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3609 DEBUG(0,("check_printjob_info: invalid level %d\n",
3613 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3614 DEBUG(0,("check_printjob_info: invalid format %s\n",
3615 id
? id
: "<NULL>" ));
3621 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3622 connection_struct
*conn
, uint16 vuid
,
3623 char *param
, int tpscnt
,
3624 char *data
, int tdscnt
,
3625 int mdrcnt
,int mprcnt
,
3626 char **rdata
,char **rparam
,
3627 int *rdata_len
,int *rparam_len
)
3629 struct pack_desc desc
;
3630 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3631 char *str2
= skip_string(param
,tpscnt
,str1
);
3632 char *p
= skip_string(param
,tpscnt
,str2
);
3635 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3636 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3639 TALLOC_CTX
*mem_ctx
= talloc_tos();
3642 struct rpc_pipe_client
*cli
= NULL
;
3643 struct dcerpc_binding_handle
*b
= NULL
;
3644 struct policy_handle handle
;
3645 struct spoolss_DevmodeContainer devmode_ctr
;
3646 struct spoolss_JobInfoContainer ctr
;
3647 union spoolss_JobInfo info
;
3648 struct spoolss_SetJobInfo1 info1
;
3650 if (!str1
|| !str2
|| !p
) {
3654 * We use 1 here not 2 as we're checking
3655 * the last byte we want to access is safe.
3657 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3660 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3663 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3670 /* check it's a supported varient */
3671 if ((strcmp(str1
,"WWsTP")) ||
3672 (!check_printjob_info(&desc
,uLevel
,str2
)))
3675 errcode
= NERR_notsupported
;
3679 /* change print job name, data gives the name */
3685 ZERO_STRUCT(handle
);
3687 status
= rpc_pipe_open_interface(conn
,
3688 &ndr_table_spoolss
.syntax_id
,
3690 &conn
->sconn
->client_id
,
3691 conn
->sconn
->msg_ctx
,
3693 if (!NT_STATUS_IS_OK(status
)) {
3694 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3695 nt_errstr(status
)));
3696 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3699 b
= cli
->binding_handle
;
3701 ZERO_STRUCT(devmode_ctr
);
3703 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3710 if (!NT_STATUS_IS_OK(status
)) {
3711 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3714 if (!W_ERROR_IS_OK(werr
)) {
3715 errcode
= W_ERROR_V(werr
);
3719 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3725 if (!W_ERROR_IS_OK(werr
)) {
3726 errcode
= W_ERROR_V(werr
);
3732 info1
.job_id
= info
.info1
.job_id
;
3733 info1
.printer_name
= info
.info1
.printer_name
;
3734 info1
.user_name
= info
.info1
.user_name
;
3735 info1
.document_name
= data
;
3736 info1
.data_type
= info
.info1
.data_type
;
3737 info1
.text_status
= info
.info1
.text_status
;
3738 info1
.status
= info
.info1
.status
;
3739 info1
.priority
= info
.info1
.priority
;
3740 info1
.position
= info
.info1
.position
;
3741 info1
.total_pages
= info
.info1
.total_pages
;
3742 info1
.pages_printed
= info
.info1
.pages_printed
;
3743 info1
.submitted
= info
.info1
.submitted
;
3746 ctr
.info
.info1
= &info1
;
3748 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3754 if (!NT_STATUS_IS_OK(status
)) {
3755 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3758 if (!W_ERROR_IS_OK(werr
)) {
3759 errcode
= W_ERROR_V(werr
);
3763 errcode
= NERR_Success
;
3766 if (b
&& is_valid_policy_hnd(&handle
)) {
3767 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3770 SSVALS(*rparam
,0,errcode
);
3771 SSVAL(*rparam
,2,0); /* converter word */
3777 /****************************************************************************
3778 Get info about the server.
3779 ****************************************************************************/
3781 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3782 connection_struct
*conn
,uint16 vuid
,
3783 char *param
, int tpscnt
,
3784 char *data
, int tdscnt
,
3785 int mdrcnt
,int mprcnt
,
3786 char **rdata
,char **rparam
,
3787 int *rdata_len
,int *rparam_len
)
3789 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3790 char *str2
= skip_string(param
,tpscnt
,str1
);
3791 char *p
= skip_string(param
,tpscnt
,str2
);
3792 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3798 TALLOC_CTX
*mem_ctx
= talloc_tos();
3799 struct rpc_pipe_client
*cli
= NULL
;
3800 union srvsvc_NetSrvInfo info
;
3802 struct dcerpc_binding_handle
*b
;
3804 if (!str1
|| !str2
|| !p
) {
3808 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3810 /* check it's a supported varient */
3811 if (!prefix_ok(str1
,"WrLh")) {
3817 if (strcmp(str2
,"B16") != 0) {
3823 if (strcmp(str2
,"B16BBDz") != 0) {
3829 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3835 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3841 if (strcmp(str2
,"DN") != 0) {
3847 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3856 *rdata_len
= mdrcnt
;
3857 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3863 p2
= p
+ struct_len
;
3865 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3867 &conn
->sconn
->client_id
,
3868 conn
->sconn
->msg_ctx
,
3870 if (!NT_STATUS_IS_OK(status
)) {
3871 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3872 nt_errstr(status
)));
3873 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3877 b
= cli
->binding_handle
;
3879 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3884 if (!NT_STATUS_IS_OK(status
)) {
3885 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3888 if (!W_ERROR_IS_OK(werr
)) {
3889 errcode
= W_ERROR_V(werr
);
3893 if (info
.info101
== NULL
) {
3894 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3899 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3900 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3904 SCVAL(p
,0,info
.info101
->version_major
);
3905 SCVAL(p
,1,info
.info101
->version_minor
);
3906 SIVAL(p
,2,info
.info101
->server_type
);
3908 if (mdrcnt
== struct_len
) {
3911 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3912 if (mdrcnt
- struct_len
<= 0) {
3916 info
.info101
->comment
,
3917 MIN(mdrcnt
- struct_len
,
3918 MAX_SERVER_STRING_LENGTH
),
3920 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3928 return False
; /* not yet implemented */
3931 errcode
= NERR_Success
;
3935 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3938 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3942 SSVAL(*rparam
,0,errcode
);
3943 SSVAL(*rparam
,2,0); /* converter word */
3944 SSVAL(*rparam
,4,*rdata_len
);
3949 /****************************************************************************
3950 Get info about the server.
3951 ****************************************************************************/
3953 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3954 connection_struct
*conn
,uint16 vuid
,
3955 char *param
, int tpscnt
,
3956 char *data
, int tdscnt
,
3957 int mdrcnt
,int mprcnt
,
3958 char **rdata
,char **rparam
,
3959 int *rdata_len
,int *rparam_len
)
3961 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3962 char *str2
= skip_string(param
,tpscnt
,str1
);
3963 char *p
= skip_string(param
,tpscnt
,str2
);
3966 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3968 if (!str1
|| !str2
|| !p
) {
3972 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3975 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3980 /* check it's a supported varient */
3981 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3985 *rdata_len
= mdrcnt
+ 1024;
3986 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3991 SSVAL(*rparam
,0,NERR_Success
);
3992 SSVAL(*rparam
,2,0); /* converter word */
3995 endp
= *rdata
+ *rdata_len
;
3997 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
4002 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
4003 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
4005 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4011 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
4012 strlcpy(p2
,conn
->session_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
4013 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4019 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
4020 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
4022 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4028 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
4029 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
4032 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
4033 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
4034 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4040 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
4041 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4042 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4048 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4050 SSVAL(*rparam
,4,*rdata_len
);
4055 /****************************************************************************
4056 get info about a user
4058 struct user_info_11 {
4059 char usri11_name[21]; 0-20
4061 char *usri11_comment; 22-25
4062 char *usri11_usr_comment; 26-29
4063 unsigned short usri11_priv; 30-31
4064 unsigned long usri11_auth_flags; 32-35
4065 long usri11_password_age; 36-39
4066 char *usri11_homedir; 40-43
4067 char *usri11_parms; 44-47
4068 long usri11_last_logon; 48-51
4069 long usri11_last_logoff; 52-55
4070 unsigned short usri11_bad_pw_count; 56-57
4071 unsigned short usri11_num_logons; 58-59
4072 char *usri11_logon_server; 60-63
4073 unsigned short usri11_country_code; 64-65
4074 char *usri11_workstations; 66-69
4075 unsigned long usri11_max_storage; 70-73
4076 unsigned short usri11_units_per_week; 74-75
4077 unsigned char *usri11_logon_hours; 76-79
4078 unsigned short usri11_code_page; 80-81
4083 usri11_name specifies the user name for which information is retrieved
4085 usri11_pad aligns the next data structure element to a word boundary
4087 usri11_comment is a null terminated ASCII comment
4089 usri11_user_comment is a null terminated ASCII comment about the user
4091 usri11_priv specifies the level of the privilege assigned to the user.
4092 The possible values are:
4094 Name Value Description
4095 USER_PRIV_GUEST 0 Guest privilege
4096 USER_PRIV_USER 1 User privilege
4097 USER_PRV_ADMIN 2 Administrator privilege
4099 usri11_auth_flags specifies the account operator privileges. The
4100 possible values are:
4102 Name Value Description
4103 AF_OP_PRINT 0 Print operator
4106 Leach, Naik [Page 28]
4110 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4113 AF_OP_COMM 1 Communications operator
4114 AF_OP_SERVER 2 Server operator
4115 AF_OP_ACCOUNTS 3 Accounts operator
4118 usri11_password_age specifies how many seconds have elapsed since the
4119 password was last changed.
4121 usri11_home_dir points to a null terminated ASCII string that contains
4122 the path name of the user's home directory.
4124 usri11_parms points to a null terminated ASCII string that is set
4125 aside for use by applications.
4127 usri11_last_logon specifies the time when the user last logged on.
4128 This value is stored as the number of seconds elapsed since
4129 00:00:00, January 1, 1970.
4131 usri11_last_logoff specifies the time when the user last logged off.
4132 This value is stored as the number of seconds elapsed since
4133 00:00:00, January 1, 1970. A value of 0 means the last logoff
4136 usri11_bad_pw_count specifies the number of incorrect passwords
4137 entered since the last successful logon.
4139 usri11_log1_num_logons specifies the number of times this user has
4140 logged on. A value of -1 means the number of logons is unknown.
4142 usri11_logon_server points to a null terminated ASCII string that
4143 contains the name of the server to which logon requests are sent.
4144 A null string indicates logon requests should be sent to the
4147 usri11_country_code specifies the country code for the user's language
4150 usri11_workstations points to a null terminated ASCII string that
4151 contains the names of workstations the user may log on from.
4152 There may be up to 8 workstations, with the names separated by
4153 commas. A null strings indicates there are no restrictions.
4155 usri11_max_storage specifies the maximum amount of disk space the user
4156 can occupy. A value of 0xffffffff indicates there are no
4159 usri11_units_per_week specifies the equal number of time units into
4160 which a week is divided. This value must be equal to 168.
4162 usri11_logon_hours points to a 21 byte (168 bits) string that
4163 specifies the time during which the user can log on. Each bit
4164 represents one unique hour in a week. The first bit (bit 0, word
4165 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4169 Leach, Naik [Page 29]
4173 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4176 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4177 are no restrictions.
4179 usri11_code_page specifies the code page for the user's language of
4182 All of the pointers in this data structure need to be treated
4183 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4184 to be ignored. The converter word returned in the parameters section
4185 needs to be subtracted from the lower 16 bits to calculate an offset
4186 into the return buffer where this ASCII string resides.
4188 There is no auxiliary data in the response.
4190 ****************************************************************************/
4192 #define usri11_name 0
4193 #define usri11_pad 21
4194 #define usri11_comment 22
4195 #define usri11_usr_comment 26
4196 #define usri11_full_name 30
4197 #define usri11_priv 34
4198 #define usri11_auth_flags 36
4199 #define usri11_password_age 40
4200 #define usri11_homedir 44
4201 #define usri11_parms 48
4202 #define usri11_last_logon 52
4203 #define usri11_last_logoff 56
4204 #define usri11_bad_pw_count 60
4205 #define usri11_num_logons 62
4206 #define usri11_logon_server 64
4207 #define usri11_country_code 68
4208 #define usri11_workstations 70
4209 #define usri11_max_storage 74
4210 #define usri11_units_per_week 78
4211 #define usri11_logon_hours 80
4212 #define usri11_code_page 84
4213 #define usri11_end 86
4215 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4216 connection_struct
*conn
, uint16 vuid
,
4217 char *param
, int tpscnt
,
4218 char *data
, int tdscnt
,
4219 int mdrcnt
,int mprcnt
,
4220 char **rdata
,char **rparam
,
4221 int *rdata_len
,int *rparam_len
)
4223 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4224 char *str2
= skip_string(param
,tpscnt
,str1
);
4225 char *UserName
= skip_string(param
,tpscnt
,str2
);
4226 char *p
= skip_string(param
,tpscnt
,UserName
);
4227 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4230 const char *level_string
;
4232 TALLOC_CTX
*mem_ctx
= talloc_tos();
4233 NTSTATUS status
, result
;
4234 struct rpc_pipe_client
*cli
= NULL
;
4235 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4236 struct lsa_String domain_name
;
4237 struct dom_sid2
*domain_sid
;
4238 struct lsa_String names
;
4239 struct samr_Ids rids
;
4240 struct samr_Ids types
;
4241 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4243 union samr_UserInfo
*info
;
4244 struct dcerpc_binding_handle
*b
= NULL
;
4246 if (!str1
|| !str2
|| !UserName
|| !p
) {
4251 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4256 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4258 /* check it's a supported variant */
4259 if (strcmp(str1
,"zWrLh") != 0) {
4263 case 0: level_string
= "B21"; break;
4264 case 1: level_string
= "B21BB16DWzzWz"; break;
4265 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4266 case 10: level_string
= "B21Bzzz"; break;
4267 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4268 default: return False
;
4271 if (strcmp(level_string
,str2
) != 0) {
4275 *rdata_len
= mdrcnt
+ 1024;
4276 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4282 endp
= *rdata
+ *rdata_len
;
4283 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4288 ZERO_STRUCT(connect_handle
);
4289 ZERO_STRUCT(domain_handle
);
4290 ZERO_STRUCT(user_handle
);
4292 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
4294 &conn
->sconn
->client_id
,
4295 conn
->sconn
->msg_ctx
,
4297 if (!NT_STATUS_IS_OK(status
)) {
4298 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4299 nt_errstr(status
)));
4300 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4304 b
= cli
->binding_handle
;
4306 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4308 SAMR_ACCESS_CONNECT_TO_SERVER
|
4309 SAMR_ACCESS_ENUM_DOMAINS
|
4310 SAMR_ACCESS_LOOKUP_DOMAIN
,
4313 if (!NT_STATUS_IS_OK(status
)) {
4314 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4317 if (!NT_STATUS_IS_OK(result
)) {
4318 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4322 init_lsa_String(&domain_name
, get_global_sam_name());
4324 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4329 if (!NT_STATUS_IS_OK(status
)) {
4330 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4333 if (!NT_STATUS_IS_OK(result
)) {
4334 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4338 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4340 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4344 if (!NT_STATUS_IS_OK(status
)) {
4345 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4348 if (!NT_STATUS_IS_OK(result
)) {
4349 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4353 init_lsa_String(&names
, UserName
);
4355 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4362 if (!NT_STATUS_IS_OK(status
)) {
4363 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4366 if (!NT_STATUS_IS_OK(result
)) {
4367 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4371 if (rids
.count
!= 1) {
4372 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4375 if (rids
.count
!= types
.count
) {
4376 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4379 if (types
.ids
[0] != SID_NAME_USER
) {
4380 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4386 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4388 SAMR_USER_ACCESS_GET_LOCALE
|
4389 SAMR_USER_ACCESS_GET_LOGONINFO
|
4390 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4391 SAMR_USER_ACCESS_GET_GROUPS
|
4392 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4393 SEC_STD_READ_CONTROL
,
4397 if (!NT_STATUS_IS_OK(status
)) {
4398 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4401 if (!NT_STATUS_IS_OK(result
)) {
4402 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4406 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4411 if (!NT_STATUS_IS_OK(status
)) {
4412 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4415 if (!NT_STATUS_IS_OK(result
)) {
4416 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4421 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4424 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4429 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4430 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4431 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4436 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4437 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4438 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4443 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4444 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4445 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4446 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4453 const char *homedir
= info
->info21
.home_directory
.string
;
4454 /* modelled after NTAS 3.51 reply */
4455 SSVAL(p
,usri11_priv
,
4456 (get_current_uid(conn
) == sec_initial_uid())?
4457 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4458 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4459 SIVALS(p
,usri11_password_age
,-1); /* password age */
4460 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4461 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4462 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4466 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4467 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4468 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4472 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4473 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4474 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4475 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4476 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4477 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4478 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4482 SSVAL(p
,usri11_country_code
,0); /* country code */
4484 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4485 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4486 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4491 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4492 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4493 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4495 /* a simple way to get logon hours at all times. */
4497 SCVAL(p2
,21,0); /* fix zero termination */
4498 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4503 SSVAL(p
,usri11_code_page
,0); /* code page */
4506 if (uLevel
== 1 || uLevel
== 2) {
4507 memset(p
+22,' ',16); /* password */
4508 SIVALS(p
,38,-1); /* password age */
4510 (get_current_uid(conn
) == sec_initial_uid())?
4511 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4512 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4513 strlcpy(p2
, info
->info21
.home_directory
.string
,
4515 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4519 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4521 SSVAL(p
,52,0); /* flags */
4522 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4523 strlcpy(p2
, info
->info21
.logon_script
.string
,
4525 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4530 SIVAL(p
,58,0); /* auth_flags */
4531 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4532 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4533 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4537 SIVAL(p
,66,0); /* urs_comment */
4538 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4539 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4540 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4544 SIVAL(p
,74,0); /* workstations */
4545 SIVAL(p
,78,0); /* last_logon */
4546 SIVAL(p
,82,0); /* last_logoff */
4547 SIVALS(p
,86,-1); /* acct_expires */
4548 SIVALS(p
,90,-1); /* max_storage */
4549 SSVAL(p
,94,168); /* units_per_week */
4550 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4553 SSVALS(p
,100,-1); /* bad_pw_count */
4554 SSVALS(p
,102,-1); /* num_logons */
4555 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4557 TALLOC_CTX
*ctx
= talloc_tos();
4558 int space_rem
= *rdata_len
- (p2
- *rdata
);
4561 if (space_rem
<= 0) {
4564 tmp
= talloc_strdup(ctx
, "\\\\%L");
4568 tmp
= talloc_sub_basic(ctx
,
4581 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4585 SSVAL(p
,108,49); /* country_code */
4586 SSVAL(p
,110,860); /* code page */
4590 errcode
= NERR_Success
;
4593 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4595 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4596 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4598 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4599 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4601 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4602 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4605 SSVAL(*rparam
,0,errcode
);
4606 SSVAL(*rparam
,2,0); /* converter word */
4607 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4612 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4613 connection_struct
*conn
,uint16 vuid
,
4614 char *param
, int tpscnt
,
4615 char *data
, int tdscnt
,
4616 int mdrcnt
,int mprcnt
,
4617 char **rdata
,char **rparam
,
4618 int *rdata_len
,int *rparam_len
)
4620 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4621 char *str2
= skip_string(param
,tpscnt
,str1
);
4622 char *p
= skip_string(param
,tpscnt
,str2
);
4624 struct pack_desc desc
;
4626 /* With share level security vuid will always be zero.
4627 Don't depend on vuser being non-null !!. JRA */
4628 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4630 if (!str1
|| !str2
|| !p
) {
4635 DEBUG(3,(" Username of UID %d is %s\n",
4636 (int)vuser
->session_info
->utok
.uid
,
4637 vuser
->session_info
->unix_name
));
4640 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4641 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4646 memset((char *)&desc
,'\0',sizeof(desc
));
4648 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4650 /* check it's a supported varient */
4651 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4654 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4658 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4665 desc
.buflen
= mdrcnt
;
4666 desc
.subformat
= NULL
;
4669 if (init_package(&desc
,1,0)) {
4670 PACKI(&desc
,"W",0); /* code */
4671 PACKS(&desc
,"B21",name
); /* eff. name */
4672 PACKS(&desc
,"B",""); /* pad */
4674 (get_current_uid(conn
) == sec_initial_uid())?
4675 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4676 PACKI(&desc
,"D",0); /* auth flags XXX */
4677 PACKI(&desc
,"W",0); /* num logons */
4678 PACKI(&desc
,"W",0); /* bad pw count */
4679 PACKI(&desc
,"D",0); /* last logon */
4680 PACKI(&desc
,"D",-1); /* last logoff */
4681 PACKI(&desc
,"D",-1); /* logoff time */
4682 PACKI(&desc
,"D",-1); /* kickoff time */
4683 PACKI(&desc
,"D",0); /* password age */
4684 PACKI(&desc
,"D",0); /* password can change */
4685 PACKI(&desc
,"D",-1); /* password must change */
4689 fstrcpy(mypath
,"\\\\");
4690 fstrcat(mypath
,get_local_machine_name());
4692 PACKS(&desc
,"z",mypath
); /* computer */
4695 PACKS(&desc
,"z",lp_workgroup());/* domain */
4696 PACKS(&desc
,"z", vuser
?
4697 vuser
->session_info
->info3
->base
.logon_script
.string
4698 : ""); /* script path */
4699 PACKI(&desc
,"D",0x00000000); /* reserved */
4702 *rdata_len
= desc
.usedlen
;
4704 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4708 SSVALS(*rparam
,0,desc
.errcode
);
4710 SSVAL(*rparam
,4,desc
.neededlen
);
4712 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4717 /****************************************************************************
4718 api_WAccessGetUserPerms
4719 ****************************************************************************/
4721 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4722 connection_struct
*conn
,uint16 vuid
,
4723 char *param
, int tpscnt
,
4724 char *data
, int tdscnt
,
4725 int mdrcnt
,int mprcnt
,
4726 char **rdata
,char **rparam
,
4727 int *rdata_len
,int *rparam_len
)
4729 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4730 char *str2
= skip_string(param
,tpscnt
,str1
);
4731 char *user
= skip_string(param
,tpscnt
,str2
);
4732 char *resource
= skip_string(param
,tpscnt
,user
);
4734 if (!str1
|| !str2
|| !user
|| !resource
) {
4738 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4741 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4743 /* check it's a supported varient */
4744 if (strcmp(str1
,"zzh") != 0) {
4747 if (strcmp(str2
,"") != 0) {
4752 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4756 SSVALS(*rparam
,0,0); /* errorcode */
4757 SSVAL(*rparam
,2,0); /* converter word */
4758 SSVAL(*rparam
,4,0x7f); /* permission flags */
4763 /****************************************************************************
4764 api_WPrintJobEnumerate
4765 ****************************************************************************/
4767 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4768 connection_struct
*conn
, uint16 vuid
,
4769 char *param
, int tpscnt
,
4770 char *data
, int tdscnt
,
4771 int mdrcnt
,int mprcnt
,
4772 char **rdata
,char **rparam
,
4773 int *rdata_len
,int *rparam_len
)
4775 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4776 char *str2
= skip_string(param
,tpscnt
,str1
);
4777 char *p
= skip_string(param
,tpscnt
,str2
);
4781 struct pack_desc desc
;
4784 TALLOC_CTX
*mem_ctx
= talloc_tos();
4787 struct rpc_pipe_client
*cli
= NULL
;
4788 struct dcerpc_binding_handle
*b
= NULL
;
4789 struct policy_handle handle
;
4790 struct spoolss_DevmodeContainer devmode_ctr
;
4791 union spoolss_JobInfo info
;
4793 if (!str1
|| !str2
|| !p
) {
4797 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4799 memset((char *)&desc
,'\0',sizeof(desc
));
4800 memset((char *)&status
,'\0',sizeof(status
));
4802 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4804 /* check it's a supported varient */
4805 if (strcmp(str1
,"WWrLh") != 0) {
4808 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4812 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4816 ZERO_STRUCT(handle
);
4818 status
= rpc_pipe_open_interface(conn
,
4819 &ndr_table_spoolss
.syntax_id
,
4821 &conn
->sconn
->client_id
,
4822 conn
->sconn
->msg_ctx
,
4824 if (!NT_STATUS_IS_OK(status
)) {
4825 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4826 nt_errstr(status
)));
4827 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4830 b
= cli
->binding_handle
;
4832 ZERO_STRUCT(devmode_ctr
);
4834 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4841 if (!NT_STATUS_IS_OK(status
)) {
4842 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4845 if (!W_ERROR_IS_OK(werr
)) {
4846 desc
.errcode
= W_ERROR_V(werr
);
4850 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4856 if (!W_ERROR_IS_OK(werr
)) {
4857 desc
.errcode
= W_ERROR_V(werr
);
4862 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4867 desc
.buflen
= mdrcnt
;
4870 * Don't return data but need to get correct length
4871 * init_package will return wrong size if buflen=0
4873 desc
.buflen
= getlen(desc
.format
);
4874 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4877 if (init_package(&desc
,1,0)) {
4878 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4879 *rdata_len
= desc
.usedlen
;
4881 desc
.errcode
= NERR_JobNotFound
;
4885 if (b
&& is_valid_policy_hnd(&handle
)) {
4886 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4890 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4894 SSVALS(*rparam
,0,desc
.errcode
);
4896 SSVAL(*rparam
,4,desc
.neededlen
);
4900 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4905 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4906 connection_struct
*conn
, uint16 vuid
,
4907 char *param
, int tpscnt
,
4908 char *data
, int tdscnt
,
4909 int mdrcnt
,int mprcnt
,
4910 char **rdata
,char **rparam
,
4911 int *rdata_len
,int *rparam_len
)
4913 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4914 char *str2
= skip_string(param
,tpscnt
,str1
);
4915 char *p
= skip_string(param
,tpscnt
,str2
);
4919 struct pack_desc desc
;
4921 TALLOC_CTX
*mem_ctx
= talloc_tos();
4924 struct rpc_pipe_client
*cli
= NULL
;
4925 struct dcerpc_binding_handle
*b
= NULL
;
4926 struct policy_handle handle
;
4927 struct spoolss_DevmodeContainer devmode_ctr
;
4929 union spoolss_JobInfo
*info
;
4931 if (!str1
|| !str2
|| !p
) {
4935 memset((char *)&desc
,'\0',sizeof(desc
));
4937 p
= skip_string(param
,tpscnt
,p
);
4941 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4943 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4945 /* check it's a supported variant */
4946 if (strcmp(str1
,"zWrLeh") != 0) {
4951 return False
; /* defined only for uLevel 0,1,2 */
4954 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4958 ZERO_STRUCT(handle
);
4960 status
= rpc_pipe_open_interface(conn
,
4961 &ndr_table_spoolss
.syntax_id
,
4963 &conn
->sconn
->client_id
,
4964 conn
->sconn
->msg_ctx
,
4966 if (!NT_STATUS_IS_OK(status
)) {
4967 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4968 nt_errstr(status
)));
4969 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4972 b
= cli
->binding_handle
;
4974 ZERO_STRUCT(devmode_ctr
);
4976 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4980 SEC_FLAG_MAXIMUM_ALLOWED
,
4983 if (!NT_STATUS_IS_OK(status
)) {
4984 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4987 if (!W_ERROR_IS_OK(werr
)) {
4988 desc
.errcode
= W_ERROR_V(werr
);
4992 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5000 if (!W_ERROR_IS_OK(werr
)) {
5001 desc
.errcode
= W_ERROR_V(werr
);
5006 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5012 desc
.buflen
= mdrcnt
;
5014 if (init_package(&desc
,count
,0)) {
5016 for (i
= 0; i
< count
; i
++) {
5017 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
5018 if (desc
.errcode
== NERR_Success
) {
5024 if (b
&& is_valid_policy_hnd(&handle
)) {
5025 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5028 *rdata_len
= desc
.usedlen
;
5031 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5035 SSVALS(*rparam
,0,desc
.errcode
);
5037 SSVAL(*rparam
,4,succnt
);
5038 SSVAL(*rparam
,6,count
);
5040 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
5045 static int check_printdest_info(struct pack_desc
* desc
,
5046 int uLevel
, char* id
)
5048 desc
->subformat
= NULL
;
5051 desc
->format
= "B9";
5054 desc
->format
= "B9B21WWzW";
5060 desc
->format
= "zzzWWzzzWW";
5063 DEBUG(0,("check_printdest_info: invalid level %d\n",
5067 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
5068 DEBUG(0,("check_printdest_info: invalid string %s\n",
5069 id
? id
: "<NULL>" ));
5075 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
5076 struct pack_desc
* desc
)
5080 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
5081 buf
[sizeof(buf
)-1] = 0;
5085 PACKS(desc
,"B9",buf
); /* szName */
5087 PACKS(desc
,"B21",""); /* szUserName */
5088 PACKI(desc
,"W",0); /* uJobId */
5089 PACKI(desc
,"W",0); /* fsStatus */
5090 PACKS(desc
,"z",""); /* pszStatus */
5091 PACKI(desc
,"W",0); /* time */
5095 if (uLevel
== 2 || uLevel
== 3) {
5096 PACKS(desc
,"z",buf
); /* pszPrinterName */
5098 PACKS(desc
,"z",""); /* pszUserName */
5099 PACKS(desc
,"z",""); /* pszLogAddr */
5100 PACKI(desc
,"W",0); /* uJobId */
5101 PACKI(desc
,"W",0); /* fsStatus */
5102 PACKS(desc
,"z",""); /* pszStatus */
5103 PACKS(desc
,"z",""); /* pszComment */
5104 PACKS(desc
,"z","NULL"); /* pszDrivers */
5105 PACKI(desc
,"W",0); /* time */
5106 PACKI(desc
,"W",0); /* pad1 */
5111 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
5112 connection_struct
*conn
, uint16 vuid
,
5113 char *param
, int tpscnt
,
5114 char *data
, int tdscnt
,
5115 int mdrcnt
,int mprcnt
,
5116 char **rdata
,char **rparam
,
5117 int *rdata_len
,int *rparam_len
)
5119 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5120 char *str2
= skip_string(param
,tpscnt
,str1
);
5121 char *p
= skip_string(param
,tpscnt
,str2
);
5122 char* PrinterName
= p
;
5124 struct pack_desc desc
;
5127 TALLOC_CTX
*mem_ctx
= talloc_tos();
5130 struct rpc_pipe_client
*cli
= NULL
;
5131 struct dcerpc_binding_handle
*b
= NULL
;
5132 struct policy_handle handle
;
5133 struct spoolss_DevmodeContainer devmode_ctr
;
5134 union spoolss_PrinterInfo info
;
5136 if (!str1
|| !str2
|| !p
) {
5140 memset((char *)&desc
,'\0',sizeof(desc
));
5142 p
= skip_string(param
,tpscnt
,p
);
5146 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5148 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
5150 /* check it's a supported varient */
5151 if (strcmp(str1
,"zWrLh") != 0) {
5154 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5158 ZERO_STRUCT(handle
);
5160 status
= rpc_pipe_open_interface(conn
,
5161 &ndr_table_spoolss
.syntax_id
,
5163 &conn
->sconn
->client_id
,
5164 conn
->sconn
->msg_ctx
,
5166 if (!NT_STATUS_IS_OK(status
)) {
5167 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5168 nt_errstr(status
)));
5169 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5172 b
= cli
->binding_handle
;
5174 ZERO_STRUCT(devmode_ctr
);
5176 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5180 SEC_FLAG_MAXIMUM_ALLOWED
,
5183 if (!NT_STATUS_IS_OK(status
)) {
5185 desc
.errcode
= NERR_DestNotFound
;
5189 if (!W_ERROR_IS_OK(werr
)) {
5191 desc
.errcode
= NERR_DestNotFound
;
5196 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5201 if (!W_ERROR_IS_OK(werr
)) {
5203 desc
.errcode
= NERR_DestNotFound
;
5209 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5214 desc
.buflen
= mdrcnt
;
5217 * Don't return data but need to get correct length
5218 * init_package will return wrong size if buflen=0
5220 desc
.buflen
= getlen(desc
.format
);
5221 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5223 if (init_package(&desc
,1,0)) {
5224 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5228 if (b
&& is_valid_policy_hnd(&handle
)) {
5229 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5232 *rdata_len
= desc
.usedlen
;
5235 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5239 SSVALS(*rparam
,0,desc
.errcode
);
5241 SSVAL(*rparam
,4,desc
.neededlen
);
5243 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5249 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5250 connection_struct
*conn
, uint16 vuid
,
5251 char *param
, int tpscnt
,
5252 char *data
, int tdscnt
,
5253 int mdrcnt
,int mprcnt
,
5254 char **rdata
,char **rparam
,
5255 int *rdata_len
,int *rparam_len
)
5257 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5258 char *str2
= skip_string(param
,tpscnt
,str1
);
5259 char *p
= skip_string(param
,tpscnt
,str2
);
5263 struct pack_desc desc
;
5265 TALLOC_CTX
*mem_ctx
= talloc_tos();
5268 struct rpc_pipe_client
*cli
= NULL
;
5269 union spoolss_PrinterInfo
*info
;
5272 if (!str1
|| !str2
|| !p
) {
5276 memset((char *)&desc
,'\0',sizeof(desc
));
5278 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5280 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5282 /* check it's a supported varient */
5283 if (strcmp(str1
,"WrLeh") != 0) {
5286 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5292 status
= rpc_pipe_open_interface(conn
,
5293 &ndr_table_spoolss
.syntax_id
,
5295 &conn
->sconn
->client_id
,
5296 conn
->sconn
->msg_ctx
,
5298 if (!NT_STATUS_IS_OK(status
)) {
5299 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5300 nt_errstr(status
)));
5301 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5305 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5307 cli
->srv_name_slash
,
5312 if (!W_ERROR_IS_OK(werr
)) {
5313 desc
.errcode
= W_ERROR_V(werr
);
5315 desc
.errcode
= NERR_DestNotFound
;
5323 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5330 desc
.buflen
= mdrcnt
;
5331 if (init_package(&desc
,queuecnt
,0)) {
5334 for (i
= 0; i
< count
; i
++) {
5335 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5337 if (desc
.errcode
== NERR_Success
) {
5343 *rdata_len
= desc
.usedlen
;
5346 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5350 SSVALS(*rparam
,0,desc
.errcode
);
5352 SSVAL(*rparam
,4,succnt
);
5353 SSVAL(*rparam
,6,queuecnt
);
5355 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5360 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5361 connection_struct
*conn
, uint16 vuid
,
5362 char *param
, int tpscnt
,
5363 char *data
, int tdscnt
,
5364 int mdrcnt
,int mprcnt
,
5365 char **rdata
,char **rparam
,
5366 int *rdata_len
,int *rparam_len
)
5368 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5369 char *str2
= skip_string(param
,tpscnt
,str1
);
5370 char *p
= skip_string(param
,tpscnt
,str2
);
5373 struct pack_desc desc
;
5375 if (!str1
|| !str2
|| !p
) {
5379 memset((char *)&desc
,'\0',sizeof(desc
));
5381 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5383 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5385 /* check it's a supported varient */
5386 if (strcmp(str1
,"WrLeh") != 0) {
5389 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5394 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5400 desc
.buflen
= mdrcnt
;
5401 if (init_package(&desc
,1,0)) {
5402 PACKS(&desc
,"B41","NULL");
5405 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5407 *rdata_len
= desc
.usedlen
;
5410 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5414 SSVALS(*rparam
,0,desc
.errcode
);
5416 SSVAL(*rparam
,4,succnt
);
5419 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5424 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5425 connection_struct
*conn
, uint16 vuid
,
5426 char *param
, int tpscnt
,
5427 char *data
, int tdscnt
,
5428 int mdrcnt
,int mprcnt
,
5429 char **rdata
,char **rparam
,
5430 int *rdata_len
,int *rparam_len
)
5432 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5433 char *str2
= skip_string(param
,tpscnt
,str1
);
5434 char *p
= skip_string(param
,tpscnt
,str2
);
5437 struct pack_desc desc
;
5439 if (!str1
|| !str2
|| !p
) {
5442 memset((char *)&desc
,'\0',sizeof(desc
));
5444 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5446 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5448 /* check it's a supported varient */
5449 if (strcmp(str1
,"WrLeh") != 0) {
5452 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5457 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5463 desc
.buflen
= mdrcnt
;
5465 if (init_package(&desc
,1,0)) {
5466 PACKS(&desc
,"B13","lpd");
5469 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5471 *rdata_len
= desc
.usedlen
;
5474 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5478 SSVALS(*rparam
,0,desc
.errcode
);
5480 SSVAL(*rparam
,4,succnt
);
5483 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5488 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5489 connection_struct
*conn
, uint16 vuid
,
5490 char *param
, int tpscnt
,
5491 char *data
, int tdscnt
,
5492 int mdrcnt
,int mprcnt
,
5493 char **rdata
,char **rparam
,
5494 int *rdata_len
,int *rparam_len
)
5496 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5497 char *str2
= skip_string(param
,tpscnt
,str1
);
5498 char *p
= skip_string(param
,tpscnt
,str2
);
5501 struct pack_desc desc
;
5503 if (!str1
|| !str2
|| !p
) {
5507 memset((char *)&desc
,'\0',sizeof(desc
));
5509 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5511 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5513 /* check it's a supported varient */
5514 if (strcmp(str1
,"WrLeh") != 0) {
5517 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5522 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5527 memset((char *)&desc
,'\0',sizeof(desc
));
5529 desc
.buflen
= mdrcnt
;
5531 if (init_package(&desc
,1,0)) {
5532 PACKS(&desc
,"B13","lp0");
5535 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5537 *rdata_len
= desc
.usedlen
;
5540 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5544 SSVALS(*rparam
,0,desc
.errcode
);
5546 SSVAL(*rparam
,4,succnt
);
5549 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5554 /****************************************************************************
5556 ****************************************************************************/
5558 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5559 connection_struct
*conn
, uint16 vuid
,
5560 char *param
, int tpscnt
,
5561 char *data
, int tdscnt
,
5562 int mdrcnt
,int mprcnt
,
5563 char **rdata
,char **rparam
,
5564 int *rdata_len
,int *rparam_len
)
5567 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5568 char *str2
= skip_string(param
,tpscnt
,str1
);
5569 char *p
= skip_string(param
,tpscnt
,str2
);
5571 struct pack_desc desc
;
5574 TALLOC_CTX
*mem_ctx
= talloc_tos();
5577 struct rpc_pipe_client
*cli
= NULL
;
5578 struct dcerpc_binding_handle
*b
= NULL
;
5579 struct srvsvc_NetSessInfoCtr info_ctr
;
5580 uint32_t totalentries
, resume_handle
= 0;
5583 if (!str1
|| !str2
|| !p
) {
5589 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5591 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5592 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5593 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5595 /* check it's a supported varient */
5596 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5599 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5603 status
= rpc_pipe_open_interface(conn
,
5604 &ndr_table_srvsvc
.syntax_id
,
5606 &conn
->sconn
->client_id
,
5607 conn
->sconn
->msg_ctx
,
5609 if (!NT_STATUS_IS_OK(status
)) {
5610 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5611 nt_errstr(status
)));
5612 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5615 b
= cli
->binding_handle
;
5618 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5619 if (info_ctr
.ctr
.ctr1
== NULL
) {
5620 desc
.errcode
= W_ERROR_V(WERR_NOMEM
);
5624 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5625 cli
->srv_name_slash
,
5629 (uint32_t)-1, /* max_buffer */
5633 if (!NT_STATUS_IS_OK(status
)) {
5634 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5635 nt_errstr(status
)));
5636 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5640 if (!W_ERROR_IS_OK(werr
)) {
5641 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5643 desc
.errcode
= W_ERROR_V(werr
);
5647 count
= info_ctr
.ctr
.ctr1
->count
;
5651 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5658 desc
.buflen
= mdrcnt
;
5660 if (!init_package(&desc
, count
,0)) {
5664 for(i
=0; i
< count
; i
++) {
5665 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5666 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5667 PACKI(&desc
, "W", 1); /* num conns */
5668 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5669 PACKI(&desc
, "W", 1); /* num users */
5670 PACKI(&desc
, "D", 0); /* session time */
5671 PACKI(&desc
, "D", 0); /* idle time */
5672 PACKI(&desc
, "D", 0); /* flags */
5673 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5676 *rdata_len
= desc
.usedlen
;
5679 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5683 SSVALS(*rparam
,0,desc
.errcode
);
5684 SSVAL(*rparam
,2,0); /* converter */
5685 SSVAL(*rparam
,4, count
); /* count */
5687 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5693 /****************************************************************************
5694 The buffer was too small.
5695 ****************************************************************************/
5697 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5698 connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5699 int mdrcnt
, int mprcnt
,
5700 char **rdata
, char **rparam
,
5701 int *rdata_len
, int *rparam_len
)
5703 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5704 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5711 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5713 DEBUG(3,("Supplied buffer too small in API command\n"));
5718 /****************************************************************************
5719 The request is not supported.
5720 ****************************************************************************/
5722 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5723 connection_struct
*conn
, uint16 vuid
,
5724 char *param
, int tpscnt
,
5725 char *data
, int tdscnt
,
5726 int mdrcnt
, int mprcnt
,
5727 char **rdata
, char **rparam
,
5728 int *rdata_len
, int *rparam_len
)
5731 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5738 SSVAL(*rparam
,0,NERR_notsupported
);
5739 SSVAL(*rparam
,2,0); /* converter word */
5741 DEBUG(3,("Unsupported API command\n"));
5746 static const struct {
5749 bool (*fn
)(struct smbd_server_connection
*sconn
,
5750 connection_struct
*, uint16
,
5753 int,int,char **,char **,int *,int *);
5754 bool auth_user
; /* Deny anonymous access? */
5755 } api_commands
[] = {
5756 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5757 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5758 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5759 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5760 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5761 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5762 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5763 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5764 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5765 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5766 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5767 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5768 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5769 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5770 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5771 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5772 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5773 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5774 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5775 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5776 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5777 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5778 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5779 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5780 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5781 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5782 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5783 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5784 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5785 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5786 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5787 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5788 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5789 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5790 {NULL
, -1, api_Unsupported
}
5791 /* The following RAP calls are not implemented by Samba:
5793 RAP_WFileEnum2 - anon not OK
5798 /****************************************************************************
5799 Handle remote api calls.
5800 ****************************************************************************/
5802 void api_reply(connection_struct
*conn
, uint16 vuid
,
5803 struct smb_request
*req
,
5804 char *data
, char *params
,
5805 int tdscnt
, int tpscnt
,
5806 int mdrcnt
, int mprcnt
)
5810 char *rparam
= NULL
;
5811 const char *name1
= NULL
;
5812 const char *name2
= NULL
;
5819 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5820 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5825 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5828 api_command
= SVAL(params
,0);
5829 /* Is there a string at position params+2 ? */
5830 if (skip_string(params
,tpscnt
,params
+2)) {
5835 name2
= skip_string(params
,tpscnt
,params
+2);
5840 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5844 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5846 for (i
=0;api_commands
[i
].name
;i
++) {
5847 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5848 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5853 /* Check whether this api call can be done anonymously */
5855 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5856 user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5858 if (!user
|| user
->session_info
->guest
) {
5859 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5864 rdata
= (char *)SMB_MALLOC(1024);
5866 memset(rdata
,'\0',1024);
5869 rparam
= (char *)SMB_MALLOC(1024);
5871 memset(rparam
,'\0',1024);
5874 if(!rdata
|| !rparam
) {
5875 DEBUG(0,("api_reply: malloc fail !\n"));
5878 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5882 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5884 params
,tpscnt
, /* params + length */
5885 data
,tdscnt
, /* data + length */
5887 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5890 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5891 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5893 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5896 /* if we get False back then it's actually unsupported */
5898 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5900 tdscnt
,mdrcnt
,mprcnt
,
5901 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5904 /* If api_Unsupported returns false we can't return anything. */
5906 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5907 rdata
, rdata_len
, False
);