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/cli_samr.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "../librpc/gen_ndr/cli_srvsvc.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"
49 #define NERR_Success 0
50 #define NERR_badpass 86
51 #define NERR_notsupported 50
53 #define NERR_BASE (2100)
54 #define NERR_BufTooSmall (NERR_BASE+23)
55 #define NERR_JobNotFound (NERR_BASE+51)
56 #define NERR_DestNotFound (NERR_BASE+52)
58 #define ACCESS_READ 0x01
59 #define ACCESS_WRITE 0x02
60 #define ACCESS_CREATE 0x04
62 #define SHPWLEN 8 /* share password length */
64 /* Limit size of ipc replies */
66 static char *smb_realloc_limit(void *ptr
, size_t size
)
70 size
= MAX((size
),4*1024);
71 val
= (char *)SMB_REALLOC(ptr
,size
);
73 memset(val
,'\0',size
);
78 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
79 connection_struct
*conn
, uint16 vuid
,
80 char *param
, int tpscnt
,
81 char *data
, int tdscnt
,
82 int mdrcnt
, int mprcnt
,
83 char **rdata
, char **rparam
,
84 int *rdata_len
, int *rparam_len
);
86 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
87 connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
88 int mdrcnt
, int mprcnt
,
89 char **rdata
, char **rparam
,
90 int *rdata_len
, int *rparam_len
);
93 static int CopyExpanded(connection_struct
*conn
,
94 int snum
, char **dst
, char *src
, int *p_space_remaining
)
96 TALLOC_CTX
*ctx
= talloc_tos();
100 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
101 *p_space_remaining
<= 0) {
105 buf
= talloc_strdup(ctx
, src
);
107 *p_space_remaining
= 0;
110 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
112 *p_space_remaining
= 0;
115 buf
= talloc_sub_advanced(ctx
,
116 lp_servicename(SNUM(conn
)),
117 conn
->server_info
->unix_name
,
119 conn
->server_info
->utok
.gid
,
120 conn
->server_info
->sanitized_username
,
121 conn
->server_info
->info3
->base
.domain
.string
,
124 *p_space_remaining
= 0;
127 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
132 (*p_space_remaining
) -= l
;
136 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
139 if (!src
|| !dst
|| !n
|| !(*dst
)) {
142 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
151 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
153 TALLOC_CTX
*ctx
= talloc_tos();
158 buf
= talloc_strdup(ctx
,s
);
162 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
166 buf
= talloc_sub_advanced(ctx
,
167 lp_servicename(SNUM(conn
)),
168 conn
->server_info
->unix_name
,
170 conn
->server_info
->utok
.gid
,
171 conn
->server_info
->sanitized_username
,
172 conn
->server_info
->info3
->base
.domain
.string
,
177 return strlen(buf
) + 1;
180 /*******************************************************************
181 Check a API string for validity when we only need to check the prefix.
182 ******************************************************************/
184 static bool prefix_ok(const char *str
, const char *prefix
)
186 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
190 const char *format
; /* formatstring for structure */
191 const char *subformat
; /* subformat for structure */
192 char *base
; /* baseaddress of buffer */
193 int buflen
; /* remaining size for fixed part; on init: length of base */
194 int subcount
; /* count of substructures */
195 char *structbuf
; /* pointer into buffer for remaining fixed part */
196 int stringlen
; /* remaining size for variable part */
197 char *stringbuf
; /* pointer into buffer for remaining variable part */
198 int neededlen
; /* total needed size */
199 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
200 const char *curpos
; /* current position; pointer into format or subformat */
204 static int get_counter(const char **p
)
210 if (!isdigit((int)**p
)) {
216 n
= 10 * n
+ (i
- '0');
224 static int getlen(const char *p
)
233 case 'W': /* word (2 byte) */
236 case 'K': /* status word? (2 byte) */
239 case 'N': /* count of substructures (word) at end */
242 case 'D': /* double word (4 byte) */
243 case 'z': /* offset to zero terminated string (4 byte) */
244 case 'l': /* offset to user data (4 byte) */
247 case 'b': /* offset to data (with counter) (4 byte) */
251 case 'B': /* byte (with optional counter) */
252 n
+= get_counter(&p
);
259 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
264 if (!p
->format
|| !p
->base
) {
268 i
= count
* getlen(p
->format
);
270 i
+= subcount
* getlen(p
->subformat
);
272 p
->structbuf
= p
->base
;
276 p
->curpos
= p
->format
;
282 * This is the old error code we used. Aparently
283 * WinNT/2k systems return ERRbuftoosmall (2123) and
284 * OS/2 needs this. I'm leaving this here so we can revert
287 p
->errcode
= ERRmoredata
;
289 p
->errcode
= ERRbuftoosmall
;
292 p
->errcode
= NERR_Success
;
296 p
->stringbuf
= p
->base
+ i
;
298 return (p
->errcode
== NERR_Success
);
301 static int package(struct pack_desc
*p
, ...)
304 int needed
=0, stringneeded
;
305 const char *str
=NULL
;
306 int is_string
=0, stringused
;
313 p
->curpos
= p
->format
;
315 p
->curpos
= p
->subformat
;
320 str
= va_arg(args
,char*);
321 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
330 switch( *p
->curpos
++ ) {
331 case 'W': /* word (2 byte) */
333 temp
= va_arg(args
,int);
334 if (p
->buflen
>= needed
) {
335 SSVAL(p
->structbuf
,0,temp
);
338 case 'K': /* status word? (2 byte) */
340 temp
= va_arg(args
,int);
341 if (p
->buflen
>= needed
) {
342 SSVAL(p
->structbuf
,0,temp
);
345 case 'N': /* count of substructures (word) at end */
347 p
->subcount
= va_arg(args
,int);
348 if (p
->buflen
>= needed
) {
349 SSVAL(p
->structbuf
,0,p
->subcount
);
352 case 'D': /* double word (4 byte) */
354 temp
= va_arg(args
,int);
355 if (p
->buflen
>= needed
) {
356 SIVAL(p
->structbuf
,0,temp
);
359 case 'B': /* byte (with optional counter) */
360 needed
= get_counter(&p
->curpos
);
362 char *s
= va_arg(args
,char*);
363 if (p
->buflen
>= needed
) {
364 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
368 case 'z': /* offset to zero terminated string (4 byte) */
369 str
= va_arg(args
,char*);
370 stringneeded
= (str
? strlen(str
)+1 : 0);
373 case 'l': /* offset to user data (4 byte) */
374 str
= va_arg(args
,char*);
375 stringneeded
= va_arg(args
,int);
378 case 'b': /* offset to data (with counter) (4 byte) */
379 str
= va_arg(args
,char*);
380 stringneeded
= get_counter(&p
->curpos
);
386 if (stringneeded
>= 0) {
388 if (p
->buflen
>= needed
) {
389 stringused
= stringneeded
;
390 if (stringused
> p
->stringlen
) {
391 stringused
= (is_string
? p
->stringlen
: 0);
392 if (p
->errcode
== NERR_Success
) {
393 p
->errcode
= ERRmoredata
;
397 SIVAL(p
->structbuf
,0,0);
399 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
400 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
402 p
->stringbuf
[stringused
-1] = '\0';
404 p
->stringbuf
+= stringused
;
405 p
->stringlen
-= stringused
;
406 p
->usedlen
+= stringused
;
409 p
->neededlen
+= stringneeded
;
412 p
->neededlen
+= needed
;
413 if (p
->buflen
>= needed
) {
414 p
->structbuf
+= needed
;
416 p
->usedlen
+= needed
;
418 if (p
->errcode
== NERR_Success
) {
419 p
->errcode
= ERRmoredata
;
426 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
427 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
429 #define PACK(desc,t,v) package(desc,v)
430 #define PACKl(desc,t,v,l) package(desc,v,l)
433 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
438 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
443 /****************************************************************************
445 ****************************************************************************/
447 static void PackDriverData(struct pack_desc
* desc
)
449 char drivdata
[4+4+32];
450 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
451 SIVAL(drivdata
,4,1000); /* lVersion */
452 memset(drivdata
+8,0,32); /* szDeviceName */
453 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
454 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
457 static int check_printq_info(struct pack_desc
* desc
,
458 unsigned int uLevel
, char *id1
, char *id2
)
460 desc
->subformat
= NULL
;
463 desc
->format
= "B13";
466 desc
->format
= "B13BWWWzzzzzWW";
469 desc
->format
= "B13BWWWzzzzzWN";
470 desc
->subformat
= "WB21BB16B10zWWzDDz";
473 desc
->format
= "zWWWWzzzzWWzzl";
476 desc
->format
= "zWWWWzzzzWNzzl";
477 desc
->subformat
= "WWzWWDDzz";
486 desc
->format
= "WzzzzzzzzN";
487 desc
->subformat
= "z";
490 DEBUG(0,("check_printq_info: invalid level %d\n",
494 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
495 DEBUG(0,("check_printq_info: invalid format %s\n",
496 id1
? id1
: "<NULL>" ));
499 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
500 DEBUG(0,("check_printq_info: invalid subformat %s\n",
501 id2
? id2
: "<NULL>" ));
508 #define RAP_JOB_STATUS_QUEUED 0
509 #define RAP_JOB_STATUS_PAUSED 1
510 #define RAP_JOB_STATUS_SPOOLING 2
511 #define RAP_JOB_STATUS_PRINTING 3
512 #define RAP_JOB_STATUS_PRINTED 4
514 #define RAP_QUEUE_STATUS_PAUSED 1
515 #define RAP_QUEUE_STATUS_ERROR 2
517 /* turn a print job status into a on the wire status
519 static int printj_spoolss_status(int v
)
521 if (v
== JOB_STATUS_QUEUED
)
522 return RAP_JOB_STATUS_QUEUED
;
523 if (v
& JOB_STATUS_PAUSED
)
524 return RAP_JOB_STATUS_PAUSED
;
525 if (v
& JOB_STATUS_SPOOLING
)
526 return RAP_JOB_STATUS_SPOOLING
;
527 if (v
& JOB_STATUS_PRINTING
)
528 return RAP_JOB_STATUS_PRINTING
;
532 /* turn a print queue status into a on the wire status
534 static int printq_spoolss_status(int v
)
536 if (v
== PRINTER_STATUS_OK
)
538 if (v
& PRINTER_STATUS_PAUSED
)
539 return RAP_QUEUE_STATUS_PAUSED
;
540 return RAP_QUEUE_STATUS_ERROR
;
543 static void fill_spoolss_printjob_info(int uLevel
,
544 struct pack_desc
*desc
,
545 struct spoolss_JobInfo2
*info2
,
548 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
550 /* the client expects localtime */
551 t
-= get_time_zone(t
);
553 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
555 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
556 PACKS(desc
,"B",""); /* pad */
557 PACKS(desc
,"B16",""); /* szNotifyName */
558 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
559 PACKS(desc
,"z",""); /* pszParms */
560 PACKI(desc
,"W",n
+1); /* uPosition */
561 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
562 PACKS(desc
,"z",""); /* pszStatus */
563 PACKI(desc
,"D", t
); /* ulSubmitted */
564 PACKI(desc
,"D", info2
->size
); /* ulSize */
565 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
567 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
568 PACKI(desc
,"W", info2
->priority
); /* uPriority */
569 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
570 PACKI(desc
,"W",n
+1); /* uPosition */
571 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
572 PACKI(desc
,"D",t
); /* ulSubmitted */
573 PACKI(desc
,"D", info2
->size
); /* ulSize */
574 PACKS(desc
,"z","Samba"); /* pszComment */
575 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
577 PACKS(desc
,"z",""); /* pszNotifyName */
578 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
579 PACKS(desc
,"z",""); /* pszParms */
580 PACKS(desc
,"z",""); /* pszStatus */
581 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
582 PACKS(desc
,"z","lpd"); /* pszQProcName */
583 PACKS(desc
,"z",""); /* pszQProcParms */
584 PACKS(desc
,"z","NULL"); /* pszDriverName */
585 PackDriverData(desc
); /* pDriverData */
586 PACKS(desc
,"z",""); /* pszPrinterName */
587 } else if (uLevel
== 4) { /* OS2 */
588 PACKS(desc
,"z",""); /* pszSpoolFileName */
589 PACKS(desc
,"z",""); /* pszPortName */
590 PACKS(desc
,"z",""); /* pszStatus */
591 PACKI(desc
,"D",0); /* ulPagesSpooled */
592 PACKI(desc
,"D",0); /* ulPagesSent */
593 PACKI(desc
,"D",0); /* ulPagesPrinted */
594 PACKI(desc
,"D",0); /* ulTimePrinted */
595 PACKI(desc
,"D",0); /* ulExtendJobStatus */
596 PACKI(desc
,"D",0); /* ulStartPage */
597 PACKI(desc
,"D",0); /* ulEndPage */
602 /********************************************************************
603 Respond to the DosPrintQInfo command with a level of 52
604 This is used to get printer driver information for Win9x clients
605 ********************************************************************/
606 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
607 struct pack_desc
* desc
, int count
,
608 const char *printer_name
)
612 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
613 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
614 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
616 PACKI(desc
, "W", 0x0400); /* don't know */
617 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
618 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
619 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
620 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
622 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
623 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
624 PACKS(desc
,"z", location
); /* share to retrieve files */
626 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
627 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
628 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
630 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
631 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
632 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
633 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
634 DEBUG(3,("Driver Location: %s:\n",location
));
635 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
636 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
637 PACKI(desc
,"N",count
); /* number of files to copy */
639 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
641 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
642 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
643 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
648 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
651 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
653 desc
->errcode
=NERR_Success
;
657 static const char *strip_unc(const char *unc
)
665 if ((p
= strrchr(unc
, '\\')) != NULL
) {
672 static void fill_printq_info(int uLevel
,
673 struct pack_desc
* desc
,
675 union spoolss_JobInfo
*job_info
,
676 struct spoolss_DriverInfo3
*driver_info
,
677 struct spoolss_PrinterInfo2
*printer_info
)
683 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
688 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
691 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
695 if (uLevel
== 1 || uLevel
== 2) {
696 PACKS(desc
,"B",""); /* alignment */
697 PACKI(desc
,"W",5); /* priority */
698 PACKI(desc
,"W",0); /* start time */
699 PACKI(desc
,"W",0); /* until time */
700 PACKS(desc
,"z",""); /* pSepFile */
701 PACKS(desc
,"z","lpd"); /* pPrProc */
702 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
703 PACKS(desc
,"z",""); /* pParms */
704 if (printer_info
->printername
== NULL
) {
705 PACKS(desc
,"z","UNKNOWN PRINTER");
706 PACKI(desc
,"W",LPSTAT_ERROR
);
708 PACKS(desc
,"z", printer_info
->comment
);
709 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
711 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
714 if (uLevel
== 3 || uLevel
== 4) {
715 PACKI(desc
,"W",5); /* uPriority */
716 PACKI(desc
,"W",0); /* uStarttime */
717 PACKI(desc
,"W",0); /* uUntiltime */
718 PACKI(desc
,"W",5); /* pad1 */
719 PACKS(desc
,"z",""); /* pszSepFile */
720 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
721 PACKS(desc
,"z",NULL
); /* pszParms */
722 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
723 /* "don't ask" that it's done this way to fix corrupted
724 Win9X/ME printer comments. */
725 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
726 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
727 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
728 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
729 PackDriverData(desc
); /* pDriverData */
732 if (uLevel
== 2 || uLevel
== 4) {
734 for (i
= 0; i
< count
; i
++) {
735 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
740 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
743 /* This function returns the number of files for a given driver */
744 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
748 /* count the number of files */
749 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
755 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
756 connection_struct
*conn
, uint16 vuid
,
757 char *param
, int tpscnt
,
758 char *data
, int tdscnt
,
759 int mdrcnt
,int mprcnt
,
760 char **rdata
,char **rparam
,
761 int *rdata_len
,int *rparam_len
)
763 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
764 char *str2
= skip_string(param
,tpscnt
,str1
);
765 char *p
= skip_string(param
,tpscnt
,str2
);
770 struct pack_desc desc
;
773 WERROR werr
= WERR_OK
;
774 TALLOC_CTX
*mem_ctx
= talloc_tos();
776 struct rpc_pipe_client
*cli
= NULL
;
777 struct policy_handle handle
;
778 struct spoolss_DevmodeContainer devmode_ctr
;
779 union spoolss_DriverInfo driver_info
;
780 union spoolss_JobInfo
*job_info
= NULL
;
781 union spoolss_PrinterInfo printer_info
;
783 if (!str1
|| !str2
|| !p
) {
786 memset((char *)&desc
,'\0',sizeof(desc
));
788 p
= skip_string(param
,tpscnt
,p
);
792 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
793 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
794 /* str3 may be null here and is checked in check_printq_info(). */
796 /* remove any trailing username */
797 if ((p
= strchr_m(QueueName
,'%')))
800 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
802 /* check it's a supported varient */
803 if (!prefix_ok(str1
,"zWrLh"))
805 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
807 * Patch from Scott Moomaw <scott@bridgewater.edu>
808 * to return the 'invalid info level' error if an
809 * unknown level was requested.
813 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
817 SSVALS(*rparam
,0,ERRunknownlevel
);
825 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
826 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
830 status
= rpc_pipe_open_interface(conn
,
831 &ndr_table_spoolss
.syntax_id
,
833 &conn
->sconn
->client_id
,
834 conn
->sconn
->msg_ctx
,
836 if (!NT_STATUS_IS_OK(status
)) {
837 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
839 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
843 ZERO_STRUCT(devmode_ctr
);
845 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
852 if (!NT_STATUS_IS_OK(status
)) {
853 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
856 if (!W_ERROR_IS_OK(werr
)) {
857 desc
.errcode
= W_ERROR_V(werr
);
861 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
866 if (!W_ERROR_IS_OK(werr
)) {
867 desc
.errcode
= W_ERROR_V(werr
);
872 uint32_t server_major_version
;
873 uint32_t server_minor_version
;
875 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
883 &server_major_version
,
884 &server_minor_version
);
885 if (!W_ERROR_IS_OK(werr
)) {
886 desc
.errcode
= W_ERROR_V(werr
);
890 count
= get_printerdrivernumber(&driver_info
.info3
);
891 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
894 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
902 if (!W_ERROR_IS_OK(werr
)) {
903 desc
.errcode
= W_ERROR_V(werr
);
911 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
916 desc
.buflen
= mdrcnt
;
919 * Don't return data but need to get correct length
920 * init_package will return wrong size if buflen=0
922 desc
.buflen
= getlen(desc
.format
);
923 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
926 if (init_package(&desc
,1,count
)) {
927 desc
.subcount
= count
;
928 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
931 *rdata_len
= desc
.usedlen
;
934 * We must set the return code to ERRbuftoosmall
935 * in order to support lanman style printing with Win NT/2k
938 if (!mdrcnt
&& lp_disable_spoolss())
939 desc
.errcode
= ERRbuftoosmall
;
942 if (cli
&& is_valid_policy_hnd(&handle
)) {
943 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
946 *rdata_len
= desc
.usedlen
;
948 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
953 SSVALS(*rparam
,0,desc
.errcode
);
955 SSVAL(*rparam
,4,desc
.neededlen
);
957 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
964 /****************************************************************************
965 View list of all print jobs on all queues.
966 ****************************************************************************/
968 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
969 connection_struct
*conn
, uint16 vuid
,
970 char *param
, int tpscnt
,
971 char *data
, int tdscnt
,
972 int mdrcnt
, int mprcnt
,
973 char **rdata
, char** rparam
,
974 int *rdata_len
, int *rparam_len
)
976 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
977 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
978 char *p
= skip_string(param
,tpscnt
,output_format1
);
979 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
980 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
982 struct pack_desc desc
;
983 int *subcntarr
= NULL
;
984 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
986 WERROR werr
= WERR_OK
;
987 TALLOC_CTX
*mem_ctx
= talloc_tos();
989 struct rpc_pipe_client
*cli
= NULL
;
990 struct spoolss_DevmodeContainer devmode_ctr
;
991 uint32_t num_printers
;
992 union spoolss_PrinterInfo
*printer_info
;
993 union spoolss_DriverInfo
*driver_info
;
994 union spoolss_JobInfo
**job_info
;
996 if (!param_format
|| !output_format1
|| !p
) {
1000 memset((char *)&desc
,'\0',sizeof(desc
));
1002 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1004 if (!prefix_ok(param_format
,"WrLeh")) {
1007 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1009 * Patch from Scott Moomaw <scott@bridgewater.edu>
1010 * to return the 'invalid info level' error if an
1011 * unknown level was requested.
1015 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1019 SSVALS(*rparam
,0,ERRunknownlevel
);
1025 status
= rpc_pipe_open_interface(conn
,
1026 &ndr_table_spoolss
.syntax_id
,
1028 &conn
->sconn
->client_id
,
1029 conn
->sconn
->msg_ctx
,
1031 if (!NT_STATUS_IS_OK(status
)) {
1032 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1033 nt_errstr(status
)));
1034 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1038 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1040 cli
->srv_name_slash
,
1045 if (!W_ERROR_IS_OK(werr
)) {
1046 desc
.errcode
= W_ERROR_V(werr
);
1050 queuecnt
= num_printers
;
1052 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1053 if (job_info
== NULL
) {
1057 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1058 if (driver_info
== NULL
) {
1062 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1063 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1068 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1074 desc
.buflen
= mdrcnt
;
1077 for (i
= 0; i
< num_printers
; i
++) {
1080 struct policy_handle handle
;
1081 const char *printername
;
1083 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1084 if (printername
== NULL
) {
1088 ZERO_STRUCT(handle
);
1089 ZERO_STRUCT(devmode_ctr
);
1091 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
1098 if (!NT_STATUS_IS_OK(status
)) {
1099 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1102 if (!W_ERROR_IS_OK(werr
)) {
1103 desc
.errcode
= W_ERROR_V(werr
);
1107 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1115 if (!W_ERROR_IS_OK(werr
)) {
1116 desc
.errcode
= W_ERROR_V(werr
);
1121 uint32_t server_major_version
;
1122 uint32_t server_minor_version
;
1124 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1132 &server_major_version
,
1133 &server_minor_version
);
1134 if (!W_ERROR_IS_OK(werr
)) {
1135 desc
.errcode
= W_ERROR_V(werr
);
1140 subcntarr
[i
] = num_jobs
;
1141 subcnt
+= subcntarr
[i
];
1143 if (cli
&& is_valid_policy_hnd(&handle
)) {
1144 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
1148 if (init_package(&desc
,queuecnt
,subcnt
)) {
1149 for (i
= 0; i
< num_printers
; i
++) {
1150 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1151 if (desc
.errcode
== NERR_Success
) {
1157 SAFE_FREE(subcntarr
);
1159 *rdata_len
= desc
.usedlen
;
1161 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1165 SSVALS(*rparam
,0,desc
.errcode
);
1167 SSVAL(*rparam
,4,succnt
);
1168 SSVAL(*rparam
,6,queuecnt
);
1174 SAFE_FREE(subcntarr
);
1179 /****************************************************************************
1180 Get info level for a server list query.
1181 ****************************************************************************/
1183 static bool check_server_info(int uLevel
, char* id
)
1187 if (strcmp(id
,"B16") != 0) {
1192 if (strcmp(id
,"B16BBDz") != 0) {
1202 struct srv_info_struct
{
1210 /*******************************************************************
1211 Get server info lists from the files saved by nmbd. Return the
1213 ******************************************************************/
1215 static int get_server_info(uint32 servertype
,
1216 struct srv_info_struct
**servers
,
1222 bool local_list_only
;
1225 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1227 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1231 /* request for everything is code for request all servers */
1232 if (servertype
== SV_TYPE_ALL
) {
1233 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1236 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1238 DEBUG(4,("Servertype search: %8x\n",servertype
));
1240 for (i
=0;lines
[i
];i
++) {
1242 struct srv_info_struct
*s
;
1243 const char *ptr
= lines
[i
];
1245 TALLOC_CTX
*frame
= NULL
;
1252 if (count
== alloced
) {
1254 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1256 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1260 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1262 s
= &(*servers
)[count
];
1264 frame
= talloc_stackframe();
1266 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1270 fstrcpy(s
->name
, p
);
1273 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1279 s
->comment
[0] = '\0';
1280 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1284 fstrcpy(s
->comment
, p
);
1285 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1287 s
->domain
[0] = '\0';
1288 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1289 /* this allows us to cope with an old nmbd */
1290 fstrcpy(s
->domain
,lp_workgroup());
1292 fstrcpy(s
->domain
, p
);
1296 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1297 DEBUG(4,("r:host file "));
1301 /* Filter the servers/domains we return based on what was asked for. */
1303 /* Check to see if we are being asked for a local list only. */
1304 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1305 DEBUG(4,("r: local list only"));
1309 /* doesn't match up: don't want it */
1310 if (!(servertype
& s
->type
)) {
1311 DEBUG(4,("r:serv type "));
1315 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1316 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1317 DEBUG(4,("s: dom mismatch "));
1321 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1325 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1326 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1329 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1330 s
->name
, s
->type
, s
->comment
, s
->domain
));
1331 s
->server_added
= True
;
1334 DEBUG(4,("%20s %8x %25s %15s\n",
1335 s
->name
, s
->type
, s
->comment
, s
->domain
));
1343 /*******************************************************************
1344 Fill in a server info structure.
1345 ******************************************************************/
1347 static int fill_srv_info(struct srv_info_struct
*service
,
1348 int uLevel
, char **buf
, int *buflen
,
1349 char **stringbuf
, int *stringspace
, char *baseaddr
)
1372 len
= strlen(service
->comment
)+1;
1376 *buflen
= struct_len
;
1378 return struct_len
+ len
;
1383 if (*buflen
< struct_len
) {
1390 p2
= p
+ struct_len
;
1391 l2
= *buflen
- struct_len
;
1399 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1403 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1404 SIVAL(p
,18,service
->type
);
1405 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1406 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1411 *buf
= p
+ struct_len
;
1412 *buflen
-= struct_len
;
1423 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1425 return StrCaseCmp(s1
->name
,s2
->name
);
1428 /****************************************************************************
1429 View list of servers available (or possibly domains). The info is
1430 extracted from lists saved by nmbd on the local host.
1431 ****************************************************************************/
1433 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1434 connection_struct
*conn
, uint16 vuid
,
1435 char *param
, int tpscnt
,
1436 char *data
, int tdscnt
,
1437 int mdrcnt
, int mprcnt
, char **rdata
,
1438 char **rparam
, int *rdata_len
, int *rparam_len
)
1440 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1441 char *str2
= skip_string(param
,tpscnt
,str1
);
1442 char *p
= skip_string(param
,tpscnt
,str2
);
1443 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1444 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1445 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1447 int data_len
, fixed_len
, string_len
;
1448 int f_len
= 0, s_len
= 0;
1449 struct srv_info_struct
*servers
=NULL
;
1450 int counted
=0,total
=0;
1453 bool domain_request
;
1456 if (!str1
|| !str2
|| !p
) {
1460 /* If someone sets all the bits they don't really mean to set
1461 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1464 if (servertype
== SV_TYPE_ALL
) {
1465 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1468 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1469 any other bit (they may just set this bit on its own) they
1470 want all the locally seen servers. However this bit can be
1471 set on its own so set the requested servers to be
1472 ALL - DOMAIN_ENUM. */
1474 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1475 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1478 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1479 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1483 if (!prefix_ok(str1
,"WrLehD")) {
1486 if (!check_server_info(uLevel
,str2
)) {
1490 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1491 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1492 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1494 if (strcmp(str1
, "WrLehDz") == 0) {
1495 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1498 pull_ascii_fstring(domain
, p
);
1500 fstrcpy(domain
, lp_workgroup());
1503 DEBUG(4, ("domain [%s]\n", domain
));
1505 if (lp_browse_list()) {
1506 total
= get_server_info(servertype
,&servers
,domain
);
1509 data_len
= fixed_len
= string_len
= 0;
1512 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1515 char *lastname
=NULL
;
1517 for (i
=0;i
<total
;i
++) {
1518 struct srv_info_struct
*s
= &servers
[i
];
1520 if (lastname
&& strequal(lastname
,s
->name
)) {
1524 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1525 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1526 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1528 if (data_len
< buf_len
) {
1531 string_len
+= s_len
;
1538 *rdata_len
= fixed_len
+ string_len
;
1539 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1544 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1550 char *lastname
=NULL
;
1551 int count2
= counted
;
1553 for (i
= 0; i
< total
&& count2
;i
++) {
1554 struct srv_info_struct
*s
= &servers
[i
];
1556 if (lastname
&& strequal(lastname
,s
->name
)) {
1560 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1561 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1562 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1568 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1572 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1574 SSVAL(*rparam
,4,counted
);
1575 SSVAL(*rparam
,6,counted
+missed
);
1579 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1580 domain
,uLevel
,counted
,counted
+missed
));
1585 static int srv_name_match(const char *n1
, const char *n2
)
1588 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1590 * In Windows, FirstNameToReturn need not be an exact match:
1591 * the server will return a list of servers that exist on
1592 * the network greater than or equal to the FirstNameToReturn.
1594 int ret
= StrCaseCmp(n1
, n2
);
1603 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1604 connection_struct
*conn
, uint16 vuid
,
1605 char *param
, int tpscnt
,
1606 char *data
, int tdscnt
,
1607 int mdrcnt
, int mprcnt
, char **rdata
,
1608 char **rparam
, int *rdata_len
, int *rparam_len
)
1610 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1611 char *str2
= skip_string(param
,tpscnt
,str1
);
1612 char *p
= skip_string(param
,tpscnt
,str2
);
1613 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1614 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1615 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1617 int data_len
, fixed_len
, string_len
;
1618 int f_len
= 0, s_len
= 0;
1619 struct srv_info_struct
*servers
=NULL
;
1620 int counted
=0,first
=0,total
=0;
1624 bool domain_request
;
1627 if (!str1
|| !str2
|| !p
) {
1631 /* If someone sets all the bits they don't really mean to set
1632 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1635 if (servertype
== SV_TYPE_ALL
) {
1636 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1639 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1640 any other bit (they may just set this bit on its own) they
1641 want all the locally seen servers. However this bit can be
1642 set on its own so set the requested servers to be
1643 ALL - DOMAIN_ENUM. */
1645 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1646 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1649 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1650 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1654 if (strcmp(str1
, "WrLehDzz") != 0) {
1657 if (!check_server_info(uLevel
,str2
)) {
1661 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1662 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1663 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1665 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1668 pull_ascii_fstring(domain
, p
);
1669 if (domain
[0] == '\0') {
1670 fstrcpy(domain
, lp_workgroup());
1672 p
= skip_string(param
,tpscnt
,p
);
1673 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1676 pull_ascii_fstring(first_name
, p
);
1678 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1679 domain
, first_name
));
1681 if (lp_browse_list()) {
1682 total
= get_server_info(servertype
,&servers
,domain
);
1685 data_len
= fixed_len
= string_len
= 0;
1688 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1690 if (first_name
[0] != '\0') {
1691 struct srv_info_struct
*first_server
= NULL
;
1693 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1694 srv_name_match
, first_server
);
1696 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1698 * The binary search may not find the exact match
1699 * so we need to search backward to find the first match
1701 * This implements the strange matching windows
1702 * implements. (see the comment in srv_name_match().
1706 ret
= StrCaseCmp(first_name
,
1707 servers
[first
-1].name
);
1714 /* we should return no entries */
1720 char *lastname
=NULL
;
1722 for (i
=first
;i
<total
;i
++) {
1723 struct srv_info_struct
*s
= &servers
[i
];
1725 if (lastname
&& strequal(lastname
,s
->name
)) {
1729 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1730 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1731 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1733 if (data_len
< buf_len
) {
1736 string_len
+= s_len
;
1743 *rdata_len
= fixed_len
+ string_len
;
1744 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1749 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1755 char *lastname
=NULL
;
1756 int count2
= counted
;
1758 for (i
= first
; i
< total
&& count2
;i
++) {
1759 struct srv_info_struct
*s
= &servers
[i
];
1761 if (lastname
&& strequal(lastname
,s
->name
)) {
1765 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1766 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1767 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1773 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1777 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1779 SSVAL(*rparam
,4,counted
);
1780 SSVAL(*rparam
,6,counted
+missed
);
1782 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1783 domain
,uLevel
,first
,first_name
,
1784 first
< total
? servers
[first
].name
: "",
1785 counted
,counted
+missed
));
1792 /****************************************************************************
1793 command 0x34 - suspected of being a "Lookup Names" stub api
1794 ****************************************************************************/
1796 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1797 connection_struct
*conn
, uint16 vuid
,
1798 char *param
, int tpscnt
,
1799 char *data
, int tdscnt
,
1800 int mdrcnt
, int mprcnt
, char **rdata
,
1801 char **rparam
, int *rdata_len
, int *rparam_len
)
1803 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1804 char *str2
= skip_string(param
,tpscnt
,str1
);
1805 char *p
= skip_string(param
,tpscnt
,str2
);
1806 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1807 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1811 if (!str1
|| !str2
|| !p
) {
1815 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1816 str1
, str2
, p
, uLevel
, buf_len
));
1818 if (!prefix_ok(str1
,"zWrLeh")) {
1825 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1830 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1832 SSVAL(*rparam
,4,counted
);
1833 SSVAL(*rparam
,6,counted
+missed
);
1838 /****************************************************************************
1839 get info about a share
1840 ****************************************************************************/
1842 static bool check_share_info(int uLevel
, char* id
)
1846 if (strcmp(id
,"B13") != 0) {
1851 /* Level-2 descriptor is allowed (and ignored) */
1852 if (strcmp(id
,"B13BWz") != 0 &&
1853 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1858 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1863 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1873 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1874 char** buf
, int* buflen
,
1875 char** stringbuf
, int* stringspace
, char* baseaddr
)
1904 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1907 len
+= strlen(lp_pathname(snum
)) + 1;
1910 *buflen
= struct_len
;
1915 return struct_len
+ len
;
1920 if ((*buflen
) < struct_len
) {
1928 p2
= p
+ struct_len
;
1929 l2
= (*buflen
) - struct_len
;
1936 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1942 type
= STYPE_DISKTREE
;
1943 if (lp_print_ok(snum
)) {
1944 type
= STYPE_PRINTQ
;
1946 if (strequal("IPC",lp_fstype(snum
))) {
1949 SSVAL(p
,14,type
); /* device type */
1950 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1951 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1955 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1956 SSVALS(p
,22,-1); /* max uses */
1957 SSVAL(p
,24,1); /* current uses */
1958 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1959 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1960 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1964 memset(p
+40,0,SHPWLEN
+2);
1975 (*buf
) = p
+ struct_len
;
1976 (*buflen
) -= struct_len
;
1978 (*stringspace
) = l2
;
1987 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
1988 connection_struct
*conn
,uint16 vuid
,
1989 char *param
, int tpscnt
,
1990 char *data
, int tdscnt
,
1991 int mdrcnt
,int mprcnt
,
1992 char **rdata
,char **rparam
,
1993 int *rdata_len
,int *rparam_len
)
1995 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1996 char *str2
= skip_string(param
,tpscnt
,str1
);
1997 char *netname_in
= skip_string(param
,tpscnt
,str2
);
1998 char *netname
= NULL
;
1999 char *p
= skip_string(param
,tpscnt
,netname
);
2000 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2003 if (!str1
|| !str2
|| !netname
|| !p
) {
2007 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2008 if (snum
< 0 || !netname
) {
2012 /* check it's a supported varient */
2013 if (!prefix_ok(str1
,"zWrLh")) {
2016 if (!check_share_info(uLevel
,str2
)) {
2020 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2025 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2026 if (*rdata_len
< 0) {
2031 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2035 SSVAL(*rparam
,0,NERR_Success
);
2036 SSVAL(*rparam
,2,0); /* converter word */
2037 SSVAL(*rparam
,4,*rdata_len
);
2042 /****************************************************************************
2043 View the list of available shares.
2045 This function is the server side of the NetShareEnum() RAP call.
2046 It fills the return buffer with share names and share comments.
2047 Note that the return buffer normally (in all known cases) allows only
2048 twelve byte strings for share names (plus one for a nul terminator).
2049 Share names longer than 12 bytes must be skipped.
2050 ****************************************************************************/
2052 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2053 connection_struct
*conn
, uint16 vuid
,
2054 char *param
, int tpscnt
,
2055 char *data
, int tdscnt
,
2063 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2064 char *str2
= skip_string(param
,tpscnt
,str1
);
2065 char *p
= skip_string(param
,tpscnt
,str2
);
2066 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2067 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2070 int total
=0,counted
=0;
2071 bool missed
= False
;
2073 int data_len
, fixed_len
, string_len
;
2074 int f_len
= 0, s_len
= 0;
2076 if (!str1
|| !str2
|| !p
) {
2080 if (!prefix_ok(str1
,"WrLeh")) {
2083 if (!check_share_info(uLevel
,str2
)) {
2087 /* Ensure all the usershares are loaded. */
2089 load_registry_shares();
2090 count
= load_usershare_shares();
2093 data_len
= fixed_len
= string_len
= 0;
2094 for (i
=0;i
<count
;i
++) {
2095 fstring servicename_dos
;
2096 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2099 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2100 /* Maximum name length = 13. */
2101 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2103 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2104 if (data_len
< buf_len
) {
2107 string_len
+= s_len
;
2114 *rdata_len
= fixed_len
+ string_len
;
2115 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2120 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2125 for( i
= 0; i
< count
; i
++ ) {
2126 fstring servicename_dos
;
2127 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2131 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2132 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2133 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2140 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2144 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2146 SSVAL(*rparam
,4,counted
);
2147 SSVAL(*rparam
,6,total
);
2149 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2150 counted
,total
,uLevel
,
2151 buf_len
,*rdata_len
,mdrcnt
));
2156 /****************************************************************************
2158 ****************************************************************************/
2160 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2161 connection_struct
*conn
,uint16 vuid
,
2162 char *param
, int tpscnt
,
2163 char *data
, int tdscnt
,
2164 int mdrcnt
,int mprcnt
,
2165 char **rdata
,char **rparam
,
2166 int *rdata_len
,int *rparam_len
)
2168 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2169 char *str2
= skip_string(param
,tpscnt
,str1
);
2170 char *p
= skip_string(param
,tpscnt
,str2
);
2171 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2174 char *pathname
= NULL
;
2175 unsigned int offset
;
2177 size_t converted_size
;
2179 WERROR werr
= WERR_OK
;
2180 TALLOC_CTX
*mem_ctx
= talloc_tos();
2182 struct rpc_pipe_client
*cli
= NULL
;
2183 union srvsvc_NetShareInfo info
;
2184 struct srvsvc_NetShareInfo2 info2
;
2186 if (!str1
|| !str2
|| !p
) {
2190 /* check it's a supported varient */
2191 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2194 if (!check_share_info(uLevel
,str2
)) {
2201 /* Do we have a string ? */
2202 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2205 pull_ascii_fstring(sharename
,data
);
2211 /* only support disk share adds */
2212 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2216 offset
= IVAL(data
, 16);
2217 if (offset
>= mdrcnt
) {
2218 res
= ERRinvalidparam
;
2222 /* Do we have a string ? */
2223 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2226 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2228 offset
= IVAL(data
, 26);
2230 if (offset
>= mdrcnt
) {
2231 res
= ERRinvalidparam
;
2235 /* Do we have a string ? */
2236 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2240 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2241 offset
? (data
+offset
) : "", &converted_size
))
2243 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2251 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2253 &conn
->sconn
->client_id
,
2254 conn
->sconn
->msg_ctx
,
2256 if (!NT_STATUS_IS_OK(status
)) {
2257 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2258 nt_errstr(status
)));
2259 res
= W_ERROR_V(ntstatus_to_werror(status
));
2263 info2
.name
= sharename
;
2264 info2
.type
= STYPE_DISKTREE
;
2265 info2
.comment
= comment
;
2266 info2
.permissions
= 0;
2267 info2
.max_users
= 0;
2268 info2
.current_users
= 0;
2269 info2
.path
= pathname
;
2270 info2
.password
= NULL
;
2272 info
.info2
= &info2
;
2274 status
= rpccli_srvsvc_NetShareAdd(cli
, mem_ctx
,
2275 cli
->srv_name_slash
,
2280 if (!NT_STATUS_IS_OK(status
)) {
2281 res
= W_ERROR_V(ntstatus_to_werror(status
));
2284 if (!W_ERROR_IS_OK(werr
)) {
2285 res
= W_ERROR_V(werr
);
2290 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2294 SSVAL(*rparam
,0,NERR_Success
);
2295 SSVAL(*rparam
,2,0); /* converter word */
2296 SSVAL(*rparam
,4,*rdata_len
);
2304 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2309 SSVAL(*rparam
,0,res
);
2314 /****************************************************************************
2315 view list of groups available
2316 ****************************************************************************/
2318 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2319 connection_struct
*conn
,uint16 vuid
,
2320 char *param
, int tpscnt
,
2321 char *data
, int tdscnt
,
2322 int mdrcnt
,int mprcnt
,
2323 char **rdata
,char **rparam
,
2324 int *rdata_len
,int *rparam_len
)
2328 int resume_context
, cli_buf_size
;
2329 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2330 char *str2
= skip_string(param
,tpscnt
,str1
);
2331 char *p
= skip_string(param
,tpscnt
,str2
);
2333 uint32_t num_groups
;
2334 uint32_t resume_handle
;
2335 struct rpc_pipe_client
*samr_pipe
;
2336 struct policy_handle samr_handle
, domain_handle
;
2339 if (!str1
|| !str2
|| !p
) {
2343 if (strcmp(str1
,"WrLeh") != 0) {
2348 * W-> resume context (number of users to skip)
2349 * r -> return parameter pointer to receive buffer
2350 * L -> length of receive buffer
2351 * e -> return parameter number of entries
2352 * h -> return parameter total number of users
2355 if (strcmp("B21",str2
) != 0) {
2359 status
= rpc_pipe_open_internal(
2360 talloc_tos(), &ndr_table_samr
.syntax_id
,
2361 conn
->server_info
, &conn
->sconn
->client_id
,
2362 conn
->sconn
->msg_ctx
, &samr_pipe
);
2363 if (!NT_STATUS_IS_OK(status
)) {
2364 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2365 nt_errstr(status
)));
2369 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2370 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2371 if (!NT_STATUS_IS_OK(status
)) {
2372 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2373 nt_errstr(status
)));
2377 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2378 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2379 get_global_sam_sid(), &domain_handle
);
2380 if (!NT_STATUS_IS_OK(status
)) {
2381 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2382 nt_errstr(status
)));
2383 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2387 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2388 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2389 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2390 "%d\n", resume_context
, cli_buf_size
));
2392 *rdata_len
= cli_buf_size
;
2393 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2400 errflags
= NERR_Success
;
2405 struct samr_SamArray
*sam_entries
;
2406 uint32_t num_entries
;
2408 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2413 if (!NT_STATUS_IS_OK(status
)) {
2414 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2415 "%s\n", nt_errstr(status
)));
2419 if (num_entries
== 0) {
2420 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2421 "no entries -- done\n"));
2425 for(i
=0; i
<num_entries
; i
++) {
2428 name
= sam_entries
->entries
[i
].name
.string
;
2430 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2431 /* set overflow error */
2432 DEBUG(3,("overflow on entry %d group %s\n", i
,
2438 /* truncate the name at 21 chars. */
2440 strlcpy(p
, name
, 21);
2441 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2443 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2448 if (errflags
!= NERR_Success
) {
2452 TALLOC_FREE(sam_entries
);
2455 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2456 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2458 *rdata_len
= PTR_DIFF(p
,*rdata
);
2461 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2465 SSVAL(*rparam
, 0, errflags
);
2466 SSVAL(*rparam
, 2, 0); /* converter word */
2467 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2468 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2473 /*******************************************************************
2474 Get groups that a user is a member of.
2475 ******************************************************************/
2477 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2478 connection_struct
*conn
,uint16 vuid
,
2479 char *param
, int tpscnt
,
2480 char *data
, int tdscnt
,
2481 int mdrcnt
,int mprcnt
,
2482 char **rdata
,char **rparam
,
2483 int *rdata_len
,int *rparam_len
)
2485 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2486 char *str2
= skip_string(param
,tpscnt
,str1
);
2487 char *UserName
= skip_string(param
,tpscnt
,str2
);
2488 char *p
= skip_string(param
,tpscnt
,UserName
);
2489 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2490 const char *level_string
;
2496 struct rpc_pipe_client
*samr_pipe
;
2497 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2498 struct lsa_String name
;
2499 struct lsa_Strings names
;
2500 struct samr_Ids type
, rid
;
2501 struct samr_RidWithAttributeArray
*rids
;
2504 if (!str1
|| !str2
|| !UserName
|| !p
) {
2509 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2514 /* check it's a supported varient */
2516 if ( strcmp(str1
,"zWrLeh") != 0 )
2521 level_string
= "B21";
2527 if (strcmp(level_string
,str2
) != 0)
2530 *rdata_len
= mdrcnt
+ 1024;
2531 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2536 SSVAL(*rparam
,0,NERR_Success
);
2537 SSVAL(*rparam
,2,0); /* converter word */
2540 endp
= *rdata
+ *rdata_len
;
2542 status
= rpc_pipe_open_internal(
2543 talloc_tos(), &ndr_table_samr
.syntax_id
,
2544 conn
->server_info
, &conn
->sconn
->client_id
,
2545 conn
->sconn
->msg_ctx
, &samr_pipe
);
2546 if (!NT_STATUS_IS_OK(status
)) {
2547 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2548 nt_errstr(status
)));
2552 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2553 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2554 if (!NT_STATUS_IS_OK(status
)) {
2555 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2556 nt_errstr(status
)));
2560 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2561 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2562 get_global_sam_sid(), &domain_handle
);
2563 if (!NT_STATUS_IS_OK(status
)) {
2564 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2565 nt_errstr(status
)));
2569 name
.string
= UserName
;
2571 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2572 &domain_handle
, 1, &name
,
2574 if (!NT_STATUS_IS_OK(status
)) {
2575 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2576 nt_errstr(status
)));
2580 if (type
.ids
[0] != SID_NAME_USER
) {
2581 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2582 sid_type_lookup(type
.ids
[0])));
2586 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2588 SAMR_USER_ACCESS_GET_GROUPS
,
2589 rid
.ids
[0], &user_handle
);
2590 if (!NT_STATUS_IS_OK(status
)) {
2591 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2592 nt_errstr(status
)));
2596 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2597 &user_handle
, &rids
);
2598 if (!NT_STATUS_IS_OK(status
)) {
2599 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2600 nt_errstr(status
)));
2604 for (i
=0; i
<rids
->count
; i
++) {
2606 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2608 1, &rids
->rids
[i
].rid
,
2610 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2611 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2617 *rdata_len
= PTR_DIFF(p
,*rdata
);
2619 SSVAL(*rparam
,4,count
); /* is this right?? */
2620 SSVAL(*rparam
,6,count
); /* is this right?? */
2625 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2627 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2629 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2634 /*******************************************************************
2636 ******************************************************************/
2638 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2639 connection_struct
*conn
, uint16 vuid
,
2640 char *param
, int tpscnt
,
2641 char *data
, int tdscnt
,
2642 int mdrcnt
,int mprcnt
,
2643 char **rdata
,char **rparam
,
2644 int *rdata_len
,int *rparam_len
)
2649 int i
, resume_context
, cli_buf_size
;
2650 uint32_t resume_handle
;
2652 struct rpc_pipe_client
*samr_pipe
;
2653 struct policy_handle samr_handle
, domain_handle
;
2656 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2657 char *str2
= skip_string(param
,tpscnt
,str1
);
2658 char *p
= skip_string(param
,tpscnt
,str2
);
2661 if (!str1
|| !str2
|| !p
) {
2665 if (strcmp(str1
,"WrLeh") != 0)
2668 * W-> resume context (number of users to skip)
2669 * r -> return parameter pointer to receive buffer
2670 * L -> length of receive buffer
2671 * e -> return parameter number of entries
2672 * h -> return parameter total number of users
2675 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2676 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2677 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2678 resume_context
, cli_buf_size
));
2681 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2686 /* check it's a supported varient */
2687 if (strcmp("B21",str2
) != 0)
2690 *rdata_len
= cli_buf_size
;
2691 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2697 endp
= *rdata
+ *rdata_len
;
2699 status
= rpc_pipe_open_internal(
2700 talloc_tos(), &ndr_table_samr
.syntax_id
,
2701 conn
->server_info
, &conn
->sconn
->client_id
,
2702 conn
->sconn
->msg_ctx
, &samr_pipe
);
2703 if (!NT_STATUS_IS_OK(status
)) {
2704 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2705 nt_errstr(status
)));
2709 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2710 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2711 if (!NT_STATUS_IS_OK(status
)) {
2712 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2713 nt_errstr(status
)));
2717 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2718 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2719 get_global_sam_sid(), &domain_handle
);
2720 if (!NT_STATUS_IS_OK(status
)) {
2721 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2722 nt_errstr(status
)));
2723 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2727 errflags
=NERR_Success
;
2732 struct samr_SamArray
*sam_entries
;
2733 uint32_t num_entries
;
2735 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2741 if (!NT_STATUS_IS_OK(status
)) {
2742 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2743 "%s\n", nt_errstr(status
)));
2747 if (num_entries
== 0) {
2748 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2749 "no entries -- done\n"));
2753 for (i
=0; i
<num_entries
; i
++) {
2756 name
= sam_entries
->entries
[i
].name
.string
;
2758 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2759 &&(strlen(name
)<=21)) {
2760 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2761 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2762 "username %s\n",count_sent
,p
));
2766 /* set overflow error */
2767 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2768 "username %s\n",count_sent
,name
));
2774 if (errflags
!= NERR_Success
) {
2778 TALLOC_FREE(sam_entries
);
2781 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2782 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2784 *rdata_len
= PTR_DIFF(p
,*rdata
);
2786 SSVAL(*rparam
,0,errflags
);
2787 SSVAL(*rparam
,2,0); /* converter word */
2788 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2789 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2794 /****************************************************************************
2795 Get the time of day info.
2796 ****************************************************************************/
2798 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2799 connection_struct
*conn
,uint16 vuid
,
2800 char *param
, int tpscnt
,
2801 char *data
, int tdscnt
,
2802 int mdrcnt
,int mprcnt
,
2803 char **rdata
,char **rparam
,
2804 int *rdata_len
,int *rparam_len
)
2807 time_t unixdate
= time(NULL
);
2811 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2817 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2822 SSVAL(*rparam
,0,NERR_Success
);
2823 SSVAL(*rparam
,2,0); /* converter word */
2827 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2828 by NT in a "net time" operation,
2829 it seems to ignore the one below */
2831 /* the client expects to get localtime, not GMT, in this bit
2832 (I think, this needs testing) */
2833 t
= localtime(&unixdate
);
2838 SIVAL(p
,4,0); /* msecs ? */
2839 SCVAL(p
,8,t
->tm_hour
);
2840 SCVAL(p
,9,t
->tm_min
);
2841 SCVAL(p
,10,t
->tm_sec
);
2842 SCVAL(p
,11,0); /* hundredths of seconds */
2843 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2844 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2845 SCVAL(p
,16,t
->tm_mday
);
2846 SCVAL(p
,17,t
->tm_mon
+ 1);
2847 SSVAL(p
,18,1900+t
->tm_year
);
2848 SCVAL(p
,20,t
->tm_wday
);
2853 /****************************************************************************
2854 Set the user password.
2855 *****************************************************************************/
2857 static bool api_SetUserPassword(struct smbd_server_connection
*sconn
,
2858 connection_struct
*conn
,uint16 vuid
,
2859 char *param
, int tpscnt
,
2860 char *data
, int tdscnt
,
2861 int mdrcnt
,int mprcnt
,
2862 char **rdata
,char **rparam
,
2863 int *rdata_len
,int *rparam_len
)
2865 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2868 fstring pass1
,pass2
;
2869 TALLOC_CTX
*mem_ctx
= talloc_tos();
2871 struct rpc_pipe_client
*cli
= NULL
;
2872 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2873 struct lsa_String domain_name
;
2874 struct dom_sid2
*domain_sid
;
2875 struct lsa_String names
;
2876 struct samr_Ids rids
;
2877 struct samr_Ids types
;
2878 struct samr_Password old_lm_hash
;
2879 struct samr_Password new_lm_hash
;
2880 int errcode
= NERR_badpass
;
2885 /* Skip 2 strings. */
2886 p
= skip_string(param
,tpscnt
,np
);
2887 p
= skip_string(param
,tpscnt
,p
);
2893 /* Do we have a string ? */
2894 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2897 pull_ascii_fstring(user
,p
);
2899 p
= skip_string(param
,tpscnt
,p
);
2904 memset(pass1
,'\0',sizeof(pass1
));
2905 memset(pass2
,'\0',sizeof(pass2
));
2907 * We use 31 here not 32 as we're checking
2908 * the last byte we want to access is safe.
2910 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2914 memcpy(pass2
,p
+16,16);
2916 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
2917 if (encrypted
== -1) {
2918 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2922 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
2923 if (min_pwd_length
== -1) {
2924 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2929 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2936 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2937 user
, encrypted
, min_pwd_length
));
2939 ZERO_STRUCT(connect_handle
);
2940 ZERO_STRUCT(domain_handle
);
2941 ZERO_STRUCT(user_handle
);
2943 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
2945 &conn
->sconn
->client_id
,
2946 conn
->sconn
->msg_ctx
,
2948 if (!NT_STATUS_IS_OK(status
)) {
2949 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2950 nt_errstr(status
)));
2951 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2955 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
2957 SAMR_ACCESS_CONNECT_TO_SERVER
|
2958 SAMR_ACCESS_ENUM_DOMAINS
|
2959 SAMR_ACCESS_LOOKUP_DOMAIN
,
2961 if (!NT_STATUS_IS_OK(status
)) {
2962 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2966 init_lsa_String(&domain_name
, get_global_sam_name());
2968 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
2972 if (!NT_STATUS_IS_OK(status
)) {
2973 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2977 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
2979 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2982 if (!NT_STATUS_IS_OK(status
)) {
2983 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2987 init_lsa_String(&names
, user
);
2989 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
2995 if (!NT_STATUS_IS_OK(status
)) {
2996 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3000 if (rids
.count
!= 1) {
3001 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
3004 if (rids
.count
!= types
.count
) {
3005 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3008 if (types
.ids
[0] != SID_NAME_USER
) {
3009 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3015 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
3017 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
3020 if (!NT_STATUS_IS_OK(status
)) {
3021 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3025 if (encrypted
== 0) {
3026 E_deshash(pass1
, old_lm_hash
.hash
);
3027 E_deshash(pass2
, new_lm_hash
.hash
);
3029 ZERO_STRUCT(old_lm_hash
);
3030 ZERO_STRUCT(new_lm_hash
);
3031 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
3032 memcpy(new_lm_hash
.hash
, pass1
, MIN(strlen(pass2
), 16));
3035 status
= rpccli_samr_ChangePasswordUser(cli
, mem_ctx
,
3037 true, /* lm_present */
3040 false, /* nt_present */
3041 NULL
, /* old_nt_crypted */
3042 NULL
, /* new_nt_crypted */
3043 false, /* cross1_present */
3044 NULL
, /* nt_cross */
3045 false, /* cross2_present */
3046 NULL
); /* lm_cross */
3047 if (!NT_STATUS_IS_OK(status
)) {
3048 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3052 errcode
= NERR_Success
;
3055 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
3056 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
3058 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
3059 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
3061 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
3062 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
3065 memset((char *)pass1
,'\0',sizeof(fstring
));
3066 memset((char *)pass2
,'\0',sizeof(fstring
));
3068 SSVAL(*rparam
,0,errcode
);
3069 SSVAL(*rparam
,2,0); /* converter word */
3073 /****************************************************************************
3074 Set the user password (SamOEM version - gets plaintext).
3075 ****************************************************************************/
3077 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3078 connection_struct
*conn
,uint16 vuid
,
3079 char *param
, int tpscnt
,
3080 char *data
, int tdscnt
,
3081 int mdrcnt
,int mprcnt
,
3082 char **rdata
,char **rparam
,
3083 int *rdata_len
,int *rparam_len
)
3086 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3088 TALLOC_CTX
*mem_ctx
= talloc_tos();
3090 struct rpc_pipe_client
*cli
= NULL
;
3091 struct lsa_AsciiString server
, account
;
3092 struct samr_CryptPassword password
;
3093 struct samr_Password hash
;
3094 int errcode
= NERR_badpass
;
3098 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3108 SSVAL(*rparam
,0,NERR_badpass
);
3111 * Check the parameter definition is correct.
3114 /* Do we have a string ? */
3115 if (skip_string(param
,tpscnt
,p
) == 0) {
3118 if(!strequal(p
, "zsT")) {
3119 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3122 p
= skip_string(param
, tpscnt
, p
);
3127 /* Do we have a string ? */
3128 if (skip_string(param
,tpscnt
,p
) == 0) {
3131 if(!strequal(p
, "B516B16")) {
3132 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3135 p
= skip_string(param
,tpscnt
,p
);
3139 /* Do we have a string ? */
3140 if (skip_string(param
,tpscnt
,p
) == 0) {
3143 p
+= pull_ascii_fstring(user
,p
);
3145 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3147 if (tdscnt
!= 532) {
3148 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3152 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3153 if (bufsize
!= 532) {
3154 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3158 memcpy(password
.data
, data
, 516);
3159 memcpy(hash
.hash
, data
+516, 16);
3161 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3163 &conn
->sconn
->client_id
,
3164 conn
->sconn
->msg_ctx
,
3166 if (!NT_STATUS_IS_OK(status
)) {
3167 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3168 nt_errstr(status
)));
3169 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3173 init_lsa_AsciiString(&server
, global_myname());
3174 init_lsa_AsciiString(&account
, user
);
3176 status
= rpccli_samr_OemChangePasswordUser2(cli
, mem_ctx
,
3181 if (!NT_STATUS_IS_OK(status
)) {
3182 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3186 errcode
= NERR_Success
;
3188 SSVAL(*rparam
,0,errcode
);
3189 SSVAL(*rparam
,2,0); /* converter word */
3194 /****************************************************************************
3197 ****************************************************************************/
3199 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3200 connection_struct
*conn
,uint16 vuid
,
3201 char *param
, int tpscnt
,
3202 char *data
, int tdscnt
,
3203 int mdrcnt
,int mprcnt
,
3204 char **rdata
,char **rparam
,
3205 int *rdata_len
,int *rparam_len
)
3207 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3208 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3209 char *str2
= skip_string(param
,tpscnt
,str1
);
3210 char *p
= skip_string(param
,tpscnt
,str2
);
3214 WERROR werr
= WERR_OK
;
3216 TALLOC_CTX
*mem_ctx
= talloc_tos();
3218 struct rpc_pipe_client
*cli
= NULL
;
3219 struct policy_handle handle
;
3220 struct spoolss_DevmodeContainer devmode_ctr
;
3221 enum spoolss_JobControl command
;
3223 if (!str1
|| !str2
|| !p
) {
3227 * We use 1 here not 2 as we're checking
3228 * the last byte we want to access is safe.
3230 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3233 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3236 /* check it's a supported varient */
3237 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3241 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3247 ZERO_STRUCT(handle
);
3249 status
= rpc_pipe_open_interface(conn
,
3250 &ndr_table_spoolss
.syntax_id
,
3252 &conn
->sconn
->client_id
,
3253 conn
->sconn
->msg_ctx
,
3255 if (!NT_STATUS_IS_OK(status
)) {
3256 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3257 nt_errstr(status
)));
3258 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3262 ZERO_STRUCT(devmode_ctr
);
3264 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3268 JOB_ACCESS_ADMINISTER
,
3271 if (!NT_STATUS_IS_OK(status
)) {
3272 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3275 if (!W_ERROR_IS_OK(werr
)) {
3276 errcode
= W_ERROR_V(werr
);
3280 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3281 * and NERR_DestNotFound if share did not exist */
3283 errcode
= NERR_Success
;
3286 case 81: /* delete */
3287 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3289 case 82: /* pause */
3290 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3292 case 83: /* resume */
3293 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3296 errcode
= NERR_notsupported
;
3300 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3303 NULL
, /* unique ptr ctr */
3306 if (!NT_STATUS_IS_OK(status
)) {
3307 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3310 if (!W_ERROR_IS_OK(werr
)) {
3311 errcode
= W_ERROR_V(werr
);
3316 if (cli
&& is_valid_policy_hnd(&handle
)) {
3317 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3320 SSVAL(*rparam
,0,errcode
);
3321 SSVAL(*rparam
,2,0); /* converter word */
3326 /****************************************************************************
3327 Purge a print queue - or pause or resume it.
3328 ****************************************************************************/
3330 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3331 connection_struct
*conn
,uint16 vuid
,
3332 char *param
, int tpscnt
,
3333 char *data
, int tdscnt
,
3334 int mdrcnt
,int mprcnt
,
3335 char **rdata
,char **rparam
,
3336 int *rdata_len
,int *rparam_len
)
3338 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3339 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3340 char *str2
= skip_string(param
,tpscnt
,str1
);
3341 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3342 int errcode
= NERR_notsupported
;
3343 WERROR werr
= WERR_OK
;
3346 TALLOC_CTX
*mem_ctx
= talloc_tos();
3347 struct rpc_pipe_client
*cli
= NULL
;
3348 struct policy_handle handle
;
3349 struct spoolss_SetPrinterInfoCtr info_ctr
;
3350 struct spoolss_DevmodeContainer devmode_ctr
;
3351 struct sec_desc_buf secdesc_ctr
;
3352 enum spoolss_PrinterControl command
;
3354 if (!str1
|| !str2
|| !QueueName
) {
3358 /* check it's a supported varient */
3359 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3363 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3369 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3373 ZERO_STRUCT(handle
);
3375 status
= rpc_pipe_open_interface(conn
,
3376 &ndr_table_spoolss
.syntax_id
,
3378 &conn
->sconn
->client_id
,
3379 conn
->sconn
->msg_ctx
,
3381 if (!NT_STATUS_IS_OK(status
)) {
3382 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3383 nt_errstr(status
)));
3384 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3388 ZERO_STRUCT(devmode_ctr
);
3390 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3394 SEC_FLAG_MAXIMUM_ALLOWED
,
3397 if (!NT_STATUS_IS_OK(status
)) {
3398 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3401 if (!W_ERROR_IS_OK(werr
)) {
3402 errcode
= W_ERROR_V(werr
);
3407 case 74: /* Pause queue */
3408 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3410 case 75: /* Resume queue */
3411 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3413 case 103: /* Purge */
3414 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3417 werr
= WERR_NOT_SUPPORTED
;
3421 if (!W_ERROR_IS_OK(werr
)) {
3422 errcode
= W_ERROR_V(werr
);
3426 ZERO_STRUCT(info_ctr
);
3427 ZERO_STRUCT(secdesc_ctr
);
3429 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3436 if (!NT_STATUS_IS_OK(status
)) {
3437 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3440 if (!W_ERROR_IS_OK(werr
)) {
3441 errcode
= W_ERROR_V(werr
);
3445 errcode
= W_ERROR_V(werr
);
3449 if (cli
&& is_valid_policy_hnd(&handle
)) {
3450 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3453 SSVAL(*rparam
,0,errcode
);
3454 SSVAL(*rparam
,2,0); /* converter word */
3459 /****************************************************************************
3460 set the property of a print job (undocumented?)
3461 ? function = 0xb -> set name of print job
3462 ? function = 0x6 -> move print job up/down
3463 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3464 or <WWsTP> <WB21BB16B10zWWzDDz>
3465 ****************************************************************************/
3467 static int check_printjob_info(struct pack_desc
* desc
,
3468 int uLevel
, char* id
)
3470 desc
->subformat
= NULL
;
3472 case 0: desc
->format
= "W"; break;
3473 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3474 case 2: desc
->format
= "WWzWWDDzz"; break;
3475 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3476 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3478 DEBUG(0,("check_printjob_info: invalid level %d\n",
3482 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3483 DEBUG(0,("check_printjob_info: invalid format %s\n",
3484 id
? id
: "<NULL>" ));
3490 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3491 connection_struct
*conn
, uint16 vuid
,
3492 char *param
, int tpscnt
,
3493 char *data
, int tdscnt
,
3494 int mdrcnt
,int mprcnt
,
3495 char **rdata
,char **rparam
,
3496 int *rdata_len
,int *rparam_len
)
3498 struct pack_desc desc
;
3499 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3500 char *str2
= skip_string(param
,tpscnt
,str1
);
3501 char *p
= skip_string(param
,tpscnt
,str2
);
3504 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3505 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3508 TALLOC_CTX
*mem_ctx
= talloc_tos();
3511 struct rpc_pipe_client
*cli
= NULL
;
3512 struct policy_handle handle
;
3513 struct spoolss_DevmodeContainer devmode_ctr
;
3514 struct spoolss_JobInfoContainer ctr
;
3515 union spoolss_JobInfo info
;
3516 struct spoolss_SetJobInfo1 info1
;
3518 if (!str1
|| !str2
|| !p
) {
3522 * We use 1 here not 2 as we're checking
3523 * the last byte we want to access is safe.
3525 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3528 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3531 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3538 /* check it's a supported varient */
3539 if ((strcmp(str1
,"WWsTP")) ||
3540 (!check_printjob_info(&desc
,uLevel
,str2
)))
3543 errcode
= NERR_notsupported
;
3547 /* change print job name, data gives the name */
3553 ZERO_STRUCT(handle
);
3555 status
= rpc_pipe_open_interface(conn
,
3556 &ndr_table_spoolss
.syntax_id
,
3558 &conn
->sconn
->client_id
,
3559 conn
->sconn
->msg_ctx
,
3561 if (!NT_STATUS_IS_OK(status
)) {
3562 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3563 nt_errstr(status
)));
3564 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3568 ZERO_STRUCT(devmode_ctr
);
3570 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3577 if (!NT_STATUS_IS_OK(status
)) {
3578 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3581 if (!W_ERROR_IS_OK(werr
)) {
3582 errcode
= W_ERROR_V(werr
);
3586 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3592 if (!W_ERROR_IS_OK(werr
)) {
3593 errcode
= W_ERROR_V(werr
);
3599 info1
.job_id
= info
.info1
.job_id
;
3600 info1
.printer_name
= info
.info1
.printer_name
;
3601 info1
.user_name
= info
.info1
.user_name
;
3602 info1
.document_name
= data
;
3603 info1
.data_type
= info
.info1
.data_type
;
3604 info1
.text_status
= info
.info1
.text_status
;
3605 info1
.status
= info
.info1
.status
;
3606 info1
.priority
= info
.info1
.priority
;
3607 info1
.position
= info
.info1
.position
;
3608 info1
.total_pages
= info
.info1
.total_pages
;
3609 info1
.pages_printed
= info
.info1
.pages_printed
;
3610 info1
.submitted
= info
.info1
.submitted
;
3613 ctr
.info
.info1
= &info1
;
3615 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3621 if (!NT_STATUS_IS_OK(status
)) {
3622 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3625 if (!W_ERROR_IS_OK(werr
)) {
3626 errcode
= W_ERROR_V(werr
);
3630 errcode
= NERR_Success
;
3633 if (cli
&& is_valid_policy_hnd(&handle
)) {
3634 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3637 SSVALS(*rparam
,0,errcode
);
3638 SSVAL(*rparam
,2,0); /* converter word */
3644 /****************************************************************************
3645 Get info about the server.
3646 ****************************************************************************/
3648 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3649 connection_struct
*conn
,uint16 vuid
,
3650 char *param
, int tpscnt
,
3651 char *data
, int tdscnt
,
3652 int mdrcnt
,int mprcnt
,
3653 char **rdata
,char **rparam
,
3654 int *rdata_len
,int *rparam_len
)
3656 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3657 char *str2
= skip_string(param
,tpscnt
,str1
);
3658 char *p
= skip_string(param
,tpscnt
,str2
);
3659 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3665 TALLOC_CTX
*mem_ctx
= talloc_tos();
3666 struct rpc_pipe_client
*cli
= NULL
;
3667 union srvsvc_NetSrvInfo info
;
3670 if (!str1
|| !str2
|| !p
) {
3674 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3676 /* check it's a supported varient */
3677 if (!prefix_ok(str1
,"WrLh")) {
3683 if (strcmp(str2
,"B16") != 0) {
3689 if (strcmp(str2
,"B16BBDz") != 0) {
3695 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3701 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3707 if (strcmp(str2
,"DN") != 0) {
3713 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3722 *rdata_len
= mdrcnt
;
3723 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3729 p2
= p
+ struct_len
;
3731 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3733 &conn
->sconn
->client_id
,
3734 conn
->sconn
->msg_ctx
,
3736 if (!NT_STATUS_IS_OK(status
)) {
3737 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3738 nt_errstr(status
)));
3739 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3743 status
= rpccli_srvsvc_NetSrvGetInfo(cli
, mem_ctx
,
3748 if (!NT_STATUS_IS_OK(status
)) {
3749 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3752 if (!W_ERROR_IS_OK(werr
)) {
3753 errcode
= W_ERROR_V(werr
);
3757 if (info
.info101
== NULL
) {
3758 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3763 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3764 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3768 SCVAL(p
,0,info
.info101
->version_major
);
3769 SCVAL(p
,1,info
.info101
->version_minor
);
3770 SIVAL(p
,2,info
.info101
->server_type
);
3772 if (mdrcnt
== struct_len
) {
3775 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3776 if (mdrcnt
- struct_len
<= 0) {
3780 info
.info101
->comment
,
3781 MIN(mdrcnt
- struct_len
,
3782 MAX_SERVER_STRING_LENGTH
),
3784 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3792 return False
; /* not yet implemented */
3795 errcode
= NERR_Success
;
3799 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3802 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3806 SSVAL(*rparam
,0,errcode
);
3807 SSVAL(*rparam
,2,0); /* converter word */
3808 SSVAL(*rparam
,4,*rdata_len
);
3813 /****************************************************************************
3814 Get info about the server.
3815 ****************************************************************************/
3817 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3818 connection_struct
*conn
,uint16 vuid
,
3819 char *param
, int tpscnt
,
3820 char *data
, int tdscnt
,
3821 int mdrcnt
,int mprcnt
,
3822 char **rdata
,char **rparam
,
3823 int *rdata_len
,int *rparam_len
)
3825 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3826 char *str2
= skip_string(param
,tpscnt
,str1
);
3827 char *p
= skip_string(param
,tpscnt
,str2
);
3830 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3832 if (!str1
|| !str2
|| !p
) {
3836 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3839 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3844 /* check it's a supported varient */
3845 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3849 *rdata_len
= mdrcnt
+ 1024;
3850 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3855 SSVAL(*rparam
,0,NERR_Success
);
3856 SSVAL(*rparam
,2,0); /* converter word */
3859 endp
= *rdata
+ *rdata_len
;
3861 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3866 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3867 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3869 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3875 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3876 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3877 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3883 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3884 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3886 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3892 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3893 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3896 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3897 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3898 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3904 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3905 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3906 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3912 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3914 SSVAL(*rparam
,4,*rdata_len
);
3919 /****************************************************************************
3920 get info about a user
3922 struct user_info_11 {
3923 char usri11_name[21]; 0-20
3925 char *usri11_comment; 22-25
3926 char *usri11_usr_comment; 26-29
3927 unsigned short usri11_priv; 30-31
3928 unsigned long usri11_auth_flags; 32-35
3929 long usri11_password_age; 36-39
3930 char *usri11_homedir; 40-43
3931 char *usri11_parms; 44-47
3932 long usri11_last_logon; 48-51
3933 long usri11_last_logoff; 52-55
3934 unsigned short usri11_bad_pw_count; 56-57
3935 unsigned short usri11_num_logons; 58-59
3936 char *usri11_logon_server; 60-63
3937 unsigned short usri11_country_code; 64-65
3938 char *usri11_workstations; 66-69
3939 unsigned long usri11_max_storage; 70-73
3940 unsigned short usri11_units_per_week; 74-75
3941 unsigned char *usri11_logon_hours; 76-79
3942 unsigned short usri11_code_page; 80-81
3947 usri11_name specifies the user name for which information is retrieved
3949 usri11_pad aligns the next data structure element to a word boundary
3951 usri11_comment is a null terminated ASCII comment
3953 usri11_user_comment is a null terminated ASCII comment about the user
3955 usri11_priv specifies the level of the privilege assigned to the user.
3956 The possible values are:
3958 Name Value Description
3959 USER_PRIV_GUEST 0 Guest privilege
3960 USER_PRIV_USER 1 User privilege
3961 USER_PRV_ADMIN 2 Administrator privilege
3963 usri11_auth_flags specifies the account operator privileges. The
3964 possible values are:
3966 Name Value Description
3967 AF_OP_PRINT 0 Print operator
3970 Leach, Naik [Page 28]
3974 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3977 AF_OP_COMM 1 Communications operator
3978 AF_OP_SERVER 2 Server operator
3979 AF_OP_ACCOUNTS 3 Accounts operator
3982 usri11_password_age specifies how many seconds have elapsed since the
3983 password was last changed.
3985 usri11_home_dir points to a null terminated ASCII string that contains
3986 the path name of the user's home directory.
3988 usri11_parms points to a null terminated ASCII string that is set
3989 aside for use by applications.
3991 usri11_last_logon specifies the time when the user last logged on.
3992 This value is stored as the number of seconds elapsed since
3993 00:00:00, January 1, 1970.
3995 usri11_last_logoff specifies the time when the user last logged off.
3996 This value is stored as the number of seconds elapsed since
3997 00:00:00, January 1, 1970. A value of 0 means the last logoff
4000 usri11_bad_pw_count specifies the number of incorrect passwords
4001 entered since the last successful logon.
4003 usri11_log1_num_logons specifies the number of times this user has
4004 logged on. A value of -1 means the number of logons is unknown.
4006 usri11_logon_server points to a null terminated ASCII string that
4007 contains the name of the server to which logon requests are sent.
4008 A null string indicates logon requests should be sent to the
4011 usri11_country_code specifies the country code for the user's language
4014 usri11_workstations points to a null terminated ASCII string that
4015 contains the names of workstations the user may log on from.
4016 There may be up to 8 workstations, with the names separated by
4017 commas. A null strings indicates there are no restrictions.
4019 usri11_max_storage specifies the maximum amount of disk space the user
4020 can occupy. A value of 0xffffffff indicates there are no
4023 usri11_units_per_week specifies the equal number of time units into
4024 which a week is divided. This value must be equal to 168.
4026 usri11_logon_hours points to a 21 byte (168 bits) string that
4027 specifies the time during which the user can log on. Each bit
4028 represents one unique hour in a week. The first bit (bit 0, word
4029 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4033 Leach, Naik [Page 29]
4037 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4040 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4041 are no restrictions.
4043 usri11_code_page specifies the code page for the user's language of
4046 All of the pointers in this data structure need to be treated
4047 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4048 to be ignored. The converter word returned in the parameters section
4049 needs to be subtracted from the lower 16 bits to calculate an offset
4050 into the return buffer where this ASCII string resides.
4052 There is no auxiliary data in the response.
4054 ****************************************************************************/
4056 #define usri11_name 0
4057 #define usri11_pad 21
4058 #define usri11_comment 22
4059 #define usri11_usr_comment 26
4060 #define usri11_full_name 30
4061 #define usri11_priv 34
4062 #define usri11_auth_flags 36
4063 #define usri11_password_age 40
4064 #define usri11_homedir 44
4065 #define usri11_parms 48
4066 #define usri11_last_logon 52
4067 #define usri11_last_logoff 56
4068 #define usri11_bad_pw_count 60
4069 #define usri11_num_logons 62
4070 #define usri11_logon_server 64
4071 #define usri11_country_code 68
4072 #define usri11_workstations 70
4073 #define usri11_max_storage 74
4074 #define usri11_units_per_week 78
4075 #define usri11_logon_hours 80
4076 #define usri11_code_page 84
4077 #define usri11_end 86
4079 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4080 connection_struct
*conn
, uint16 vuid
,
4081 char *param
, int tpscnt
,
4082 char *data
, int tdscnt
,
4083 int mdrcnt
,int mprcnt
,
4084 char **rdata
,char **rparam
,
4085 int *rdata_len
,int *rparam_len
)
4087 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4088 char *str2
= skip_string(param
,tpscnt
,str1
);
4089 char *UserName
= skip_string(param
,tpscnt
,str2
);
4090 char *p
= skip_string(param
,tpscnt
,UserName
);
4091 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4094 const char *level_string
;
4096 TALLOC_CTX
*mem_ctx
= talloc_tos();
4098 struct rpc_pipe_client
*cli
= NULL
;
4099 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4100 struct lsa_String domain_name
;
4101 struct dom_sid2
*domain_sid
;
4102 struct lsa_String names
;
4103 struct samr_Ids rids
;
4104 struct samr_Ids types
;
4105 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4107 union samr_UserInfo
*info
;
4109 if (!str1
|| !str2
|| !UserName
|| !p
) {
4114 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4119 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4121 /* check it's a supported variant */
4122 if (strcmp(str1
,"zWrLh") != 0) {
4126 case 0: level_string
= "B21"; break;
4127 case 1: level_string
= "B21BB16DWzzWz"; break;
4128 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4129 case 10: level_string
= "B21Bzzz"; break;
4130 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4131 default: return False
;
4134 if (strcmp(level_string
,str2
) != 0) {
4138 *rdata_len
= mdrcnt
+ 1024;
4139 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4145 endp
= *rdata
+ *rdata_len
;
4146 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4151 ZERO_STRUCT(connect_handle
);
4152 ZERO_STRUCT(domain_handle
);
4153 ZERO_STRUCT(user_handle
);
4155 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
4157 &conn
->sconn
->client_id
,
4158 conn
->sconn
->msg_ctx
,
4160 if (!NT_STATUS_IS_OK(status
)) {
4161 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4162 nt_errstr(status
)));
4163 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4167 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
4169 SAMR_ACCESS_CONNECT_TO_SERVER
|
4170 SAMR_ACCESS_ENUM_DOMAINS
|
4171 SAMR_ACCESS_LOOKUP_DOMAIN
,
4173 if (!NT_STATUS_IS_OK(status
)) {
4174 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4178 init_lsa_String(&domain_name
, get_global_sam_name());
4180 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
4184 if (!NT_STATUS_IS_OK(status
)) {
4185 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4189 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
4191 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4194 if (!NT_STATUS_IS_OK(status
)) {
4195 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4199 init_lsa_String(&names
, UserName
);
4201 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
4207 if (!NT_STATUS_IS_OK(status
)) {
4208 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4212 if (rids
.count
!= 1) {
4213 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4216 if (rids
.count
!= types
.count
) {
4217 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4220 if (types
.ids
[0] != SID_NAME_USER
) {
4221 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4227 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
4229 SAMR_USER_ACCESS_GET_LOCALE
|
4230 SAMR_USER_ACCESS_GET_LOGONINFO
|
4231 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4232 SAMR_USER_ACCESS_GET_GROUPS
|
4233 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4234 SEC_STD_READ_CONTROL
,
4237 if (!NT_STATUS_IS_OK(status
)) {
4238 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4242 status
= rpccli_samr_QueryUserInfo2(cli
, mem_ctx
,
4246 if (!NT_STATUS_IS_OK(status
)) {
4247 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4252 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4255 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4260 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4261 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4262 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4267 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4268 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4269 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4274 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4275 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4276 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4277 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4284 const char *homedir
= info
->info21
.home_directory
.string
;
4285 /* modelled after NTAS 3.51 reply */
4286 SSVAL(p
,usri11_priv
,
4287 (get_current_uid(conn
) == sec_initial_uid())?
4288 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4289 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4290 SIVALS(p
,usri11_password_age
,-1); /* password age */
4291 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4292 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4293 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4297 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4298 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4299 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4303 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4304 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4305 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4306 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4307 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4308 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4309 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4313 SSVAL(p
,usri11_country_code
,0); /* country code */
4315 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4316 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4317 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4322 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4323 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4324 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4326 /* a simple way to get logon hours at all times. */
4328 SCVAL(p2
,21,0); /* fix zero termination */
4329 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4334 SSVAL(p
,usri11_code_page
,0); /* code page */
4337 if (uLevel
== 1 || uLevel
== 2) {
4338 memset(p
+22,' ',16); /* password */
4339 SIVALS(p
,38,-1); /* password age */
4341 (get_current_uid(conn
) == sec_initial_uid())?
4342 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4343 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4344 strlcpy(p2
, info
->info21
.home_directory
.string
,
4346 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4350 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4352 SSVAL(p
,52,0); /* flags */
4353 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4354 strlcpy(p2
, info
->info21
.logon_script
.string
,
4356 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4361 SIVAL(p
,58,0); /* auth_flags */
4362 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4363 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4364 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4368 SIVAL(p
,66,0); /* urs_comment */
4369 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4370 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4371 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4375 SIVAL(p
,74,0); /* workstations */
4376 SIVAL(p
,78,0); /* last_logon */
4377 SIVAL(p
,82,0); /* last_logoff */
4378 SIVALS(p
,86,-1); /* acct_expires */
4379 SIVALS(p
,90,-1); /* max_storage */
4380 SSVAL(p
,94,168); /* units_per_week */
4381 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4384 SSVALS(p
,100,-1); /* bad_pw_count */
4385 SSVALS(p
,102,-1); /* num_logons */
4386 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4388 TALLOC_CTX
*ctx
= talloc_tos();
4389 int space_rem
= *rdata_len
- (p2
- *rdata
);
4392 if (space_rem
<= 0) {
4395 tmp
= talloc_strdup(ctx
, "\\\\%L");
4399 tmp
= talloc_sub_basic(ctx
,
4412 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4416 SSVAL(p
,108,49); /* country_code */
4417 SSVAL(p
,110,860); /* code page */
4421 errcode
= NERR_Success
;
4424 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4426 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
4427 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
4429 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
4430 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
4432 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
4433 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
4436 SSVAL(*rparam
,0,errcode
);
4437 SSVAL(*rparam
,2,0); /* converter word */
4438 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4443 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4444 connection_struct
*conn
,uint16 vuid
,
4445 char *param
, int tpscnt
,
4446 char *data
, int tdscnt
,
4447 int mdrcnt
,int mprcnt
,
4448 char **rdata
,char **rparam
,
4449 int *rdata_len
,int *rparam_len
)
4451 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4452 char *str2
= skip_string(param
,tpscnt
,str1
);
4453 char *p
= skip_string(param
,tpscnt
,str2
);
4455 struct pack_desc desc
;
4457 /* With share level security vuid will always be zero.
4458 Don't depend on vuser being non-null !!. JRA */
4459 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4461 if (!str1
|| !str2
|| !p
) {
4466 DEBUG(3,(" Username of UID %d is %s\n",
4467 (int)vuser
->server_info
->utok
.uid
,
4468 vuser
->server_info
->unix_name
));
4471 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4472 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4477 memset((char *)&desc
,'\0',sizeof(desc
));
4479 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4481 /* check it's a supported varient */
4482 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4485 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4489 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4496 desc
.buflen
= mdrcnt
;
4497 desc
.subformat
= NULL
;
4500 if (init_package(&desc
,1,0)) {
4501 PACKI(&desc
,"W",0); /* code */
4502 PACKS(&desc
,"B21",name
); /* eff. name */
4503 PACKS(&desc
,"B",""); /* pad */
4505 (get_current_uid(conn
) == sec_initial_uid())?
4506 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4507 PACKI(&desc
,"D",0); /* auth flags XXX */
4508 PACKI(&desc
,"W",0); /* num logons */
4509 PACKI(&desc
,"W",0); /* bad pw count */
4510 PACKI(&desc
,"D",0); /* last logon */
4511 PACKI(&desc
,"D",-1); /* last logoff */
4512 PACKI(&desc
,"D",-1); /* logoff time */
4513 PACKI(&desc
,"D",-1); /* kickoff time */
4514 PACKI(&desc
,"D",0); /* password age */
4515 PACKI(&desc
,"D",0); /* password can change */
4516 PACKI(&desc
,"D",-1); /* password must change */
4520 fstrcpy(mypath
,"\\\\");
4521 fstrcat(mypath
,get_local_machine_name());
4523 PACKS(&desc
,"z",mypath
); /* computer */
4526 PACKS(&desc
,"z",lp_workgroup());/* domain */
4527 PACKS(&desc
,"z", vuser
?
4528 vuser
->server_info
->info3
->base
.logon_script
.string
4529 : ""); /* script path */
4530 PACKI(&desc
,"D",0x00000000); /* reserved */
4533 *rdata_len
= desc
.usedlen
;
4535 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4539 SSVALS(*rparam
,0,desc
.errcode
);
4541 SSVAL(*rparam
,4,desc
.neededlen
);
4543 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4548 /****************************************************************************
4549 api_WAccessGetUserPerms
4550 ****************************************************************************/
4552 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4553 connection_struct
*conn
,uint16 vuid
,
4554 char *param
, int tpscnt
,
4555 char *data
, int tdscnt
,
4556 int mdrcnt
,int mprcnt
,
4557 char **rdata
,char **rparam
,
4558 int *rdata_len
,int *rparam_len
)
4560 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4561 char *str2
= skip_string(param
,tpscnt
,str1
);
4562 char *user
= skip_string(param
,tpscnt
,str2
);
4563 char *resource
= skip_string(param
,tpscnt
,user
);
4565 if (!str1
|| !str2
|| !user
|| !resource
) {
4569 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4572 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4574 /* check it's a supported varient */
4575 if (strcmp(str1
,"zzh") != 0) {
4578 if (strcmp(str2
,"") != 0) {
4583 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4587 SSVALS(*rparam
,0,0); /* errorcode */
4588 SSVAL(*rparam
,2,0); /* converter word */
4589 SSVAL(*rparam
,4,0x7f); /* permission flags */
4594 /****************************************************************************
4595 api_WPrintJobEnumerate
4596 ****************************************************************************/
4598 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4599 connection_struct
*conn
, uint16 vuid
,
4600 char *param
, int tpscnt
,
4601 char *data
, int tdscnt
,
4602 int mdrcnt
,int mprcnt
,
4603 char **rdata
,char **rparam
,
4604 int *rdata_len
,int *rparam_len
)
4606 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4607 char *str2
= skip_string(param
,tpscnt
,str1
);
4608 char *p
= skip_string(param
,tpscnt
,str2
);
4612 struct pack_desc desc
;
4615 TALLOC_CTX
*mem_ctx
= talloc_tos();
4618 struct rpc_pipe_client
*cli
= NULL
;
4619 struct policy_handle handle
;
4620 struct spoolss_DevmodeContainer devmode_ctr
;
4621 union spoolss_JobInfo info
;
4623 if (!str1
|| !str2
|| !p
) {
4627 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4629 memset((char *)&desc
,'\0',sizeof(desc
));
4630 memset((char *)&status
,'\0',sizeof(status
));
4632 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4634 /* check it's a supported varient */
4635 if (strcmp(str1
,"WWrLh") != 0) {
4638 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4642 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4646 ZERO_STRUCT(handle
);
4648 status
= rpc_pipe_open_interface(conn
,
4649 &ndr_table_spoolss
.syntax_id
,
4651 &conn
->sconn
->client_id
,
4652 conn
->sconn
->msg_ctx
,
4654 if (!NT_STATUS_IS_OK(status
)) {
4655 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4656 nt_errstr(status
)));
4657 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4661 ZERO_STRUCT(devmode_ctr
);
4663 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4670 if (!NT_STATUS_IS_OK(status
)) {
4671 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4674 if (!W_ERROR_IS_OK(werr
)) {
4675 desc
.errcode
= W_ERROR_V(werr
);
4679 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4685 if (!W_ERROR_IS_OK(werr
)) {
4686 desc
.errcode
= W_ERROR_V(werr
);
4691 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4696 desc
.buflen
= mdrcnt
;
4699 * Don't return data but need to get correct length
4700 * init_package will return wrong size if buflen=0
4702 desc
.buflen
= getlen(desc
.format
);
4703 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4706 if (init_package(&desc
,1,0)) {
4707 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4708 *rdata_len
= desc
.usedlen
;
4710 desc
.errcode
= NERR_JobNotFound
;
4714 if (cli
&& is_valid_policy_hnd(&handle
)) {
4715 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4719 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4723 SSVALS(*rparam
,0,desc
.errcode
);
4725 SSVAL(*rparam
,4,desc
.neededlen
);
4729 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4734 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4735 connection_struct
*conn
, uint16 vuid
,
4736 char *param
, int tpscnt
,
4737 char *data
, int tdscnt
,
4738 int mdrcnt
,int mprcnt
,
4739 char **rdata
,char **rparam
,
4740 int *rdata_len
,int *rparam_len
)
4742 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4743 char *str2
= skip_string(param
,tpscnt
,str1
);
4744 char *p
= skip_string(param
,tpscnt
,str2
);
4748 struct pack_desc desc
;
4750 TALLOC_CTX
*mem_ctx
= talloc_tos();
4753 struct rpc_pipe_client
*cli
= NULL
;
4754 struct policy_handle handle
;
4755 struct spoolss_DevmodeContainer devmode_ctr
;
4757 union spoolss_JobInfo
*info
;
4759 if (!str1
|| !str2
|| !p
) {
4763 memset((char *)&desc
,'\0',sizeof(desc
));
4765 p
= skip_string(param
,tpscnt
,p
);
4769 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4771 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4773 /* check it's a supported variant */
4774 if (strcmp(str1
,"zWrLeh") != 0) {
4779 return False
; /* defined only for uLevel 0,1,2 */
4782 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4786 ZERO_STRUCT(handle
);
4788 status
= rpc_pipe_open_interface(conn
,
4789 &ndr_table_spoolss
.syntax_id
,
4791 &conn
->sconn
->client_id
,
4792 conn
->sconn
->msg_ctx
,
4794 if (!NT_STATUS_IS_OK(status
)) {
4795 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4796 nt_errstr(status
)));
4797 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4801 ZERO_STRUCT(devmode_ctr
);
4803 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4807 SEC_FLAG_MAXIMUM_ALLOWED
,
4810 if (!NT_STATUS_IS_OK(status
)) {
4811 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4814 if (!W_ERROR_IS_OK(werr
)) {
4815 desc
.errcode
= W_ERROR_V(werr
);
4819 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4827 if (!W_ERROR_IS_OK(werr
)) {
4828 desc
.errcode
= W_ERROR_V(werr
);
4833 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4839 desc
.buflen
= mdrcnt
;
4841 if (init_package(&desc
,count
,0)) {
4843 for (i
= 0; i
< count
; i
++) {
4844 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4845 if (desc
.errcode
== NERR_Success
) {
4851 if (cli
&& is_valid_policy_hnd(&handle
)) {
4852 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4855 *rdata_len
= desc
.usedlen
;
4858 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4862 SSVALS(*rparam
,0,desc
.errcode
);
4864 SSVAL(*rparam
,4,succnt
);
4865 SSVAL(*rparam
,6,count
);
4867 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4872 static int check_printdest_info(struct pack_desc
* desc
,
4873 int uLevel
, char* id
)
4875 desc
->subformat
= NULL
;
4878 desc
->format
= "B9";
4881 desc
->format
= "B9B21WWzW";
4887 desc
->format
= "zzzWWzzzWW";
4890 DEBUG(0,("check_printdest_info: invalid level %d\n",
4894 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4895 DEBUG(0,("check_printdest_info: invalid string %s\n",
4896 id
? id
: "<NULL>" ));
4902 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4903 struct pack_desc
* desc
)
4907 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4908 buf
[sizeof(buf
)-1] = 0;
4912 PACKS(desc
,"B9",buf
); /* szName */
4914 PACKS(desc
,"B21",""); /* szUserName */
4915 PACKI(desc
,"W",0); /* uJobId */
4916 PACKI(desc
,"W",0); /* fsStatus */
4917 PACKS(desc
,"z",""); /* pszStatus */
4918 PACKI(desc
,"W",0); /* time */
4922 if (uLevel
== 2 || uLevel
== 3) {
4923 PACKS(desc
,"z",buf
); /* pszPrinterName */
4925 PACKS(desc
,"z",""); /* pszUserName */
4926 PACKS(desc
,"z",""); /* pszLogAddr */
4927 PACKI(desc
,"W",0); /* uJobId */
4928 PACKI(desc
,"W",0); /* fsStatus */
4929 PACKS(desc
,"z",""); /* pszStatus */
4930 PACKS(desc
,"z",""); /* pszComment */
4931 PACKS(desc
,"z","NULL"); /* pszDrivers */
4932 PACKI(desc
,"W",0); /* time */
4933 PACKI(desc
,"W",0); /* pad1 */
4938 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4939 connection_struct
*conn
, uint16 vuid
,
4940 char *param
, int tpscnt
,
4941 char *data
, int tdscnt
,
4942 int mdrcnt
,int mprcnt
,
4943 char **rdata
,char **rparam
,
4944 int *rdata_len
,int *rparam_len
)
4946 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4947 char *str2
= skip_string(param
,tpscnt
,str1
);
4948 char *p
= skip_string(param
,tpscnt
,str2
);
4949 char* PrinterName
= p
;
4951 struct pack_desc desc
;
4954 TALLOC_CTX
*mem_ctx
= talloc_tos();
4957 struct rpc_pipe_client
*cli
= NULL
;
4958 struct policy_handle handle
;
4959 struct spoolss_DevmodeContainer devmode_ctr
;
4960 union spoolss_PrinterInfo info
;
4962 if (!str1
|| !str2
|| !p
) {
4966 memset((char *)&desc
,'\0',sizeof(desc
));
4968 p
= skip_string(param
,tpscnt
,p
);
4972 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4974 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4976 /* check it's a supported varient */
4977 if (strcmp(str1
,"zWrLh") != 0) {
4980 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4984 ZERO_STRUCT(handle
);
4986 status
= rpc_pipe_open_interface(conn
,
4987 &ndr_table_spoolss
.syntax_id
,
4989 &conn
->sconn
->client_id
,
4990 conn
->sconn
->msg_ctx
,
4992 if (!NT_STATUS_IS_OK(status
)) {
4993 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4994 nt_errstr(status
)));
4995 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4999 ZERO_STRUCT(devmode_ctr
);
5001 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
5005 SEC_FLAG_MAXIMUM_ALLOWED
,
5008 if (!NT_STATUS_IS_OK(status
)) {
5010 desc
.errcode
= NERR_DestNotFound
;
5014 if (!W_ERROR_IS_OK(werr
)) {
5016 desc
.errcode
= NERR_DestNotFound
;
5021 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5026 if (!W_ERROR_IS_OK(werr
)) {
5028 desc
.errcode
= NERR_DestNotFound
;
5034 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5039 desc
.buflen
= mdrcnt
;
5042 * Don't return data but need to get correct length
5043 * init_package will return wrong size if buflen=0
5045 desc
.buflen
= getlen(desc
.format
);
5046 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5048 if (init_package(&desc
,1,0)) {
5049 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5053 if (cli
&& is_valid_policy_hnd(&handle
)) {
5054 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
5057 *rdata_len
= desc
.usedlen
;
5060 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5064 SSVALS(*rparam
,0,desc
.errcode
);
5066 SSVAL(*rparam
,4,desc
.neededlen
);
5068 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5074 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5075 connection_struct
*conn
, uint16 vuid
,
5076 char *param
, int tpscnt
,
5077 char *data
, int tdscnt
,
5078 int mdrcnt
,int mprcnt
,
5079 char **rdata
,char **rparam
,
5080 int *rdata_len
,int *rparam_len
)
5082 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5083 char *str2
= skip_string(param
,tpscnt
,str1
);
5084 char *p
= skip_string(param
,tpscnt
,str2
);
5088 struct pack_desc desc
;
5090 TALLOC_CTX
*mem_ctx
= talloc_tos();
5093 struct rpc_pipe_client
*cli
= NULL
;
5094 union spoolss_PrinterInfo
*info
;
5097 if (!str1
|| !str2
|| !p
) {
5101 memset((char *)&desc
,'\0',sizeof(desc
));
5103 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5105 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5107 /* check it's a supported varient */
5108 if (strcmp(str1
,"WrLeh") != 0) {
5111 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5117 status
= rpc_pipe_open_interface(conn
,
5118 &ndr_table_spoolss
.syntax_id
,
5120 &conn
->sconn
->client_id
,
5121 conn
->sconn
->msg_ctx
,
5123 if (!NT_STATUS_IS_OK(status
)) {
5124 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5125 nt_errstr(status
)));
5126 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5130 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5132 cli
->srv_name_slash
,
5137 if (!W_ERROR_IS_OK(werr
)) {
5138 desc
.errcode
= W_ERROR_V(werr
);
5140 desc
.errcode
= NERR_DestNotFound
;
5148 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5155 desc
.buflen
= mdrcnt
;
5156 if (init_package(&desc
,queuecnt
,0)) {
5159 for (i
= 0; i
< count
; i
++) {
5160 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5162 if (desc
.errcode
== NERR_Success
) {
5168 *rdata_len
= desc
.usedlen
;
5171 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5175 SSVALS(*rparam
,0,desc
.errcode
);
5177 SSVAL(*rparam
,4,succnt
);
5178 SSVAL(*rparam
,6,queuecnt
);
5180 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5185 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5186 connection_struct
*conn
, uint16 vuid
,
5187 char *param
, int tpscnt
,
5188 char *data
, int tdscnt
,
5189 int mdrcnt
,int mprcnt
,
5190 char **rdata
,char **rparam
,
5191 int *rdata_len
,int *rparam_len
)
5193 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5194 char *str2
= skip_string(param
,tpscnt
,str1
);
5195 char *p
= skip_string(param
,tpscnt
,str2
);
5198 struct pack_desc desc
;
5200 if (!str1
|| !str2
|| !p
) {
5204 memset((char *)&desc
,'\0',sizeof(desc
));
5206 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5208 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5210 /* check it's a supported varient */
5211 if (strcmp(str1
,"WrLeh") != 0) {
5214 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5219 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5225 desc
.buflen
= mdrcnt
;
5226 if (init_package(&desc
,1,0)) {
5227 PACKS(&desc
,"B41","NULL");
5230 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5232 *rdata_len
= desc
.usedlen
;
5235 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5239 SSVALS(*rparam
,0,desc
.errcode
);
5241 SSVAL(*rparam
,4,succnt
);
5244 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5249 static bool api_WPrintQProcEnum(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
);
5262 struct pack_desc desc
;
5264 if (!str1
|| !str2
|| !p
) {
5267 memset((char *)&desc
,'\0',sizeof(desc
));
5269 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5271 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5273 /* check it's a supported varient */
5274 if (strcmp(str1
,"WrLeh") != 0) {
5277 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5282 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5288 desc
.buflen
= mdrcnt
;
5290 if (init_package(&desc
,1,0)) {
5291 PACKS(&desc
,"B13","lpd");
5294 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5296 *rdata_len
= desc
.usedlen
;
5299 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5303 SSVALS(*rparam
,0,desc
.errcode
);
5305 SSVAL(*rparam
,4,succnt
);
5308 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5313 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5314 connection_struct
*conn
, uint16 vuid
,
5315 char *param
, int tpscnt
,
5316 char *data
, int tdscnt
,
5317 int mdrcnt
,int mprcnt
,
5318 char **rdata
,char **rparam
,
5319 int *rdata_len
,int *rparam_len
)
5321 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5322 char *str2
= skip_string(param
,tpscnt
,str1
);
5323 char *p
= skip_string(param
,tpscnt
,str2
);
5326 struct pack_desc desc
;
5328 if (!str1
|| !str2
|| !p
) {
5332 memset((char *)&desc
,'\0',sizeof(desc
));
5334 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5336 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5338 /* check it's a supported varient */
5339 if (strcmp(str1
,"WrLeh") != 0) {
5342 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5347 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5352 memset((char *)&desc
,'\0',sizeof(desc
));
5354 desc
.buflen
= mdrcnt
;
5356 if (init_package(&desc
,1,0)) {
5357 PACKS(&desc
,"B13","lp0");
5360 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5362 *rdata_len
= desc
.usedlen
;
5365 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5369 SSVALS(*rparam
,0,desc
.errcode
);
5371 SSVAL(*rparam
,4,succnt
);
5374 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5379 /****************************************************************************
5381 ****************************************************************************/
5383 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5384 connection_struct
*conn
, uint16 vuid
,
5385 char *param
, int tpscnt
,
5386 char *data
, int tdscnt
,
5387 int mdrcnt
,int mprcnt
,
5388 char **rdata
,char **rparam
,
5389 int *rdata_len
,int *rparam_len
)
5392 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5393 char *str2
= skip_string(param
,tpscnt
,str1
);
5394 char *p
= skip_string(param
,tpscnt
,str2
);
5396 struct pack_desc desc
;
5397 struct sessionid
*session_list
;
5398 int i
, num_sessions
;
5400 if (!str1
|| !str2
|| !p
) {
5404 memset((char *)&desc
,'\0',sizeof(desc
));
5406 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5408 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5409 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5410 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5412 /* check it's a supported varient */
5413 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5416 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5420 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5423 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5428 memset((char *)&desc
,'\0',sizeof(desc
));
5430 desc
.buflen
= mdrcnt
;
5432 if (!init_package(&desc
,num_sessions
,0)) {
5436 for(i
=0; i
<num_sessions
; i
++) {
5437 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5438 PACKS(&desc
, "z", session_list
[i
].username
);
5439 PACKI(&desc
, "W", 1); /* num conns */
5440 PACKI(&desc
, "W", 0); /* num opens */
5441 PACKI(&desc
, "W", 1); /* num users */
5442 PACKI(&desc
, "D", 0); /* session time */
5443 PACKI(&desc
, "D", 0); /* idle time */
5444 PACKI(&desc
, "D", 0); /* flags */
5445 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5448 *rdata_len
= desc
.usedlen
;
5451 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5455 SSVALS(*rparam
,0,desc
.errcode
);
5456 SSVAL(*rparam
,2,0); /* converter */
5457 SSVAL(*rparam
,4,num_sessions
); /* count */
5459 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5465 /****************************************************************************
5466 The buffer was too small.
5467 ****************************************************************************/
5469 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5470 connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5471 int mdrcnt
, int mprcnt
,
5472 char **rdata
, char **rparam
,
5473 int *rdata_len
, int *rparam_len
)
5475 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5476 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5483 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5485 DEBUG(3,("Supplied buffer too small in API command\n"));
5490 /****************************************************************************
5491 The request is not supported.
5492 ****************************************************************************/
5494 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5495 connection_struct
*conn
, uint16 vuid
,
5496 char *param
, int tpscnt
,
5497 char *data
, int tdscnt
,
5498 int mdrcnt
, int mprcnt
,
5499 char **rdata
, char **rparam
,
5500 int *rdata_len
, int *rparam_len
)
5503 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5510 SSVAL(*rparam
,0,NERR_notsupported
);
5511 SSVAL(*rparam
,2,0); /* converter word */
5513 DEBUG(3,("Unsupported API command\n"));
5518 static const struct {
5521 bool (*fn
)(struct smbd_server_connection
*sconn
,
5522 connection_struct
*, uint16
,
5525 int,int,char **,char **,int *,int *);
5526 bool auth_user
; /* Deny anonymous access? */
5527 } api_commands
[] = {
5528 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5529 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5530 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5531 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5532 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5533 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5534 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5535 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5536 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5537 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5538 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5539 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5540 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5541 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5542 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5543 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5544 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5545 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5546 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5547 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5548 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5549 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5550 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5551 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5552 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5553 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5554 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5555 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5556 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5557 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5558 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5559 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5560 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5561 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5562 {NULL
, -1, api_Unsupported
}
5563 /* The following RAP calls are not implemented by Samba:
5565 RAP_WFileEnum2 - anon not OK
5570 /****************************************************************************
5571 Handle remote api calls.
5572 ****************************************************************************/
5574 void api_reply(connection_struct
*conn
, uint16 vuid
,
5575 struct smb_request
*req
,
5576 char *data
, char *params
,
5577 int tdscnt
, int tpscnt
,
5578 int mdrcnt
, int mprcnt
)
5582 char *rparam
= NULL
;
5583 const char *name1
= NULL
;
5584 const char *name2
= NULL
;
5591 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5592 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5597 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5600 api_command
= SVAL(params
,0);
5601 /* Is there a string at position params+2 ? */
5602 if (skip_string(params
,tpscnt
,params
+2)) {
5607 name2
= skip_string(params
,tpscnt
,params
+2);
5612 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5616 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5618 for (i
=0;api_commands
[i
].name
;i
++) {
5619 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5620 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5625 /* Check whether this api call can be done anonymously */
5627 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5628 user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5630 if (!user
|| user
->server_info
->guest
) {
5631 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5636 rdata
= (char *)SMB_MALLOC(1024);
5638 memset(rdata
,'\0',1024);
5641 rparam
= (char *)SMB_MALLOC(1024);
5643 memset(rparam
,'\0',1024);
5646 if(!rdata
|| !rparam
) {
5647 DEBUG(0,("api_reply: malloc fail !\n"));
5650 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5654 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5656 params
,tpscnt
, /* params + length */
5657 data
,tdscnt
, /* data + length */
5659 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5662 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5663 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5665 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5668 /* if we get False back then it's actually unsupported */
5670 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5672 tdscnt
,mdrcnt
,mprcnt
,
5673 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5676 /* If api_Unsupported returns false we can't return anything. */
5678 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5679 rdata
, rdata_len
, False
);