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"
46 #define NERR_Success 0
47 #define NERR_badpass 86
48 #define NERR_notsupported 50
50 #define NERR_BASE (2100)
51 #define NERR_BufTooSmall (NERR_BASE+23)
52 #define NERR_JobNotFound (NERR_BASE+51)
53 #define NERR_DestNotFound (NERR_BASE+52)
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
61 /* Limit size of ipc replies */
63 static char *smb_realloc_limit(void *ptr
, size_t size
)
67 size
= MAX((size
),4*1024);
68 val
= (char *)SMB_REALLOC(ptr
,size
);
70 memset(val
,'\0',size
);
75 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
76 connection_struct
*conn
, uint16 vuid
,
77 char *param
, int tpscnt
,
78 char *data
, int tdscnt
,
79 int mdrcnt
, int mprcnt
,
80 char **rdata
, char **rparam
,
81 int *rdata_len
, int *rparam_len
);
83 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
84 connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
85 int mdrcnt
, int mprcnt
,
86 char **rdata
, char **rparam
,
87 int *rdata_len
, int *rparam_len
);
90 static int CopyExpanded(connection_struct
*conn
,
91 int snum
, char **dst
, char *src
, int *p_space_remaining
)
93 TALLOC_CTX
*ctx
= talloc_tos();
97 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
98 *p_space_remaining
<= 0) {
102 buf
= talloc_strdup(ctx
, src
);
104 *p_space_remaining
= 0;
107 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
109 *p_space_remaining
= 0;
112 buf
= talloc_sub_advanced(ctx
,
113 lp_servicename(SNUM(conn
)),
114 conn
->server_info
->unix_name
,
116 conn
->server_info
->utok
.gid
,
117 conn
->server_info
->sanitized_username
,
118 conn
->server_info
->info3
->base
.domain
.string
,
121 *p_space_remaining
= 0;
124 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
129 (*p_space_remaining
) -= l
;
133 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
136 if (!src
|| !dst
|| !n
|| !(*dst
)) {
139 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
148 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
150 TALLOC_CTX
*ctx
= talloc_tos();
155 buf
= talloc_strdup(ctx
,s
);
159 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
163 buf
= talloc_sub_advanced(ctx
,
164 lp_servicename(SNUM(conn
)),
165 conn
->server_info
->unix_name
,
167 conn
->server_info
->utok
.gid
,
168 conn
->server_info
->sanitized_username
,
169 conn
->server_info
->info3
->base
.domain
.string
,
174 return strlen(buf
) + 1;
177 /*******************************************************************
178 Check a API string for validity when we only need to check the prefix.
179 ******************************************************************/
181 static bool prefix_ok(const char *str
, const char *prefix
)
183 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
187 const char *format
; /* formatstring for structure */
188 const char *subformat
; /* subformat for structure */
189 char *base
; /* baseaddress of buffer */
190 int buflen
; /* remaining size for fixed part; on init: length of base */
191 int subcount
; /* count of substructures */
192 char *structbuf
; /* pointer into buffer for remaining fixed part */
193 int stringlen
; /* remaining size for variable part */
194 char *stringbuf
; /* pointer into buffer for remaining variable part */
195 int neededlen
; /* total needed size */
196 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
197 const char *curpos
; /* current position; pointer into format or subformat */
201 static int get_counter(const char **p
)
207 if (!isdigit((int)**p
)) {
213 n
= 10 * n
+ (i
- '0');
221 static int getlen(const char *p
)
230 case 'W': /* word (2 byte) */
233 case 'K': /* status word? (2 byte) */
236 case 'N': /* count of substructures (word) at end */
239 case 'D': /* double word (4 byte) */
240 case 'z': /* offset to zero terminated string (4 byte) */
241 case 'l': /* offset to user data (4 byte) */
244 case 'b': /* offset to data (with counter) (4 byte) */
248 case 'B': /* byte (with optional counter) */
249 n
+= get_counter(&p
);
256 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
261 if (!p
->format
|| !p
->base
) {
265 i
= count
* getlen(p
->format
);
267 i
+= subcount
* getlen(p
->subformat
);
269 p
->structbuf
= p
->base
;
273 p
->curpos
= p
->format
;
279 * This is the old error code we used. Aparently
280 * WinNT/2k systems return ERRbuftoosmall (2123) and
281 * OS/2 needs this. I'm leaving this here so we can revert
284 p
->errcode
= ERRmoredata
;
286 p
->errcode
= ERRbuftoosmall
;
289 p
->errcode
= NERR_Success
;
293 p
->stringbuf
= p
->base
+ i
;
295 return (p
->errcode
== NERR_Success
);
298 static int package(struct pack_desc
*p
, ...)
301 int needed
=0, stringneeded
;
302 const char *str
=NULL
;
303 int is_string
=0, stringused
;
310 p
->curpos
= p
->format
;
312 p
->curpos
= p
->subformat
;
317 str
= va_arg(args
,char*);
318 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
327 switch( *p
->curpos
++ ) {
328 case 'W': /* word (2 byte) */
330 temp
= va_arg(args
,int);
331 if (p
->buflen
>= needed
) {
332 SSVAL(p
->structbuf
,0,temp
);
335 case 'K': /* status word? (2 byte) */
337 temp
= va_arg(args
,int);
338 if (p
->buflen
>= needed
) {
339 SSVAL(p
->structbuf
,0,temp
);
342 case 'N': /* count of substructures (word) at end */
344 p
->subcount
= va_arg(args
,int);
345 if (p
->buflen
>= needed
) {
346 SSVAL(p
->structbuf
,0,p
->subcount
);
349 case 'D': /* double word (4 byte) */
351 temp
= va_arg(args
,int);
352 if (p
->buflen
>= needed
) {
353 SIVAL(p
->structbuf
,0,temp
);
356 case 'B': /* byte (with optional counter) */
357 needed
= get_counter(&p
->curpos
);
359 char *s
= va_arg(args
,char*);
360 if (p
->buflen
>= needed
) {
361 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
365 case 'z': /* offset to zero terminated string (4 byte) */
366 str
= va_arg(args
,char*);
367 stringneeded
= (str
? strlen(str
)+1 : 0);
370 case 'l': /* offset to user data (4 byte) */
371 str
= va_arg(args
,char*);
372 stringneeded
= va_arg(args
,int);
375 case 'b': /* offset to data (with counter) (4 byte) */
376 str
= va_arg(args
,char*);
377 stringneeded
= get_counter(&p
->curpos
);
383 if (stringneeded
>= 0) {
385 if (p
->buflen
>= needed
) {
386 stringused
= stringneeded
;
387 if (stringused
> p
->stringlen
) {
388 stringused
= (is_string
? p
->stringlen
: 0);
389 if (p
->errcode
== NERR_Success
) {
390 p
->errcode
= ERRmoredata
;
394 SIVAL(p
->structbuf
,0,0);
396 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
397 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
399 p
->stringbuf
[stringused
-1] = '\0';
401 p
->stringbuf
+= stringused
;
402 p
->stringlen
-= stringused
;
403 p
->usedlen
+= stringused
;
406 p
->neededlen
+= stringneeded
;
409 p
->neededlen
+= needed
;
410 if (p
->buflen
>= needed
) {
411 p
->structbuf
+= needed
;
413 p
->usedlen
+= needed
;
415 if (p
->errcode
== NERR_Success
) {
416 p
->errcode
= ERRmoredata
;
423 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
424 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
426 #define PACK(desc,t,v) package(desc,v)
427 #define PACKl(desc,t,v,l) package(desc,v,l)
430 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
435 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
440 /****************************************************************************
442 ****************************************************************************/
444 static void PackDriverData(struct pack_desc
* desc
)
446 char drivdata
[4+4+32];
447 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
448 SIVAL(drivdata
,4,1000); /* lVersion */
449 memset(drivdata
+8,0,32); /* szDeviceName */
450 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
451 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
454 static int check_printq_info(struct pack_desc
* desc
,
455 unsigned int uLevel
, char *id1
, char *id2
)
457 desc
->subformat
= NULL
;
460 desc
->format
= "B13";
463 desc
->format
= "B13BWWWzzzzzWW";
466 desc
->format
= "B13BWWWzzzzzWN";
467 desc
->subformat
= "WB21BB16B10zWWzDDz";
470 desc
->format
= "zWWWWzzzzWWzzl";
473 desc
->format
= "zWWWWzzzzWNzzl";
474 desc
->subformat
= "WWzWWDDzz";
483 desc
->format
= "WzzzzzzzzN";
484 desc
->subformat
= "z";
487 DEBUG(0,("check_printq_info: invalid level %d\n",
491 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
492 DEBUG(0,("check_printq_info: invalid format %s\n",
493 id1
? id1
: "<NULL>" ));
496 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
497 DEBUG(0,("check_printq_info: invalid subformat %s\n",
498 id2
? id2
: "<NULL>" ));
505 #define RAP_JOB_STATUS_QUEUED 0
506 #define RAP_JOB_STATUS_PAUSED 1
507 #define RAP_JOB_STATUS_SPOOLING 2
508 #define RAP_JOB_STATUS_PRINTING 3
509 #define RAP_JOB_STATUS_PRINTED 4
511 #define RAP_QUEUE_STATUS_PAUSED 1
512 #define RAP_QUEUE_STATUS_ERROR 2
514 /* turn a print job status into a on the wire status
516 static int printj_spoolss_status(int v
)
518 if (v
== JOB_STATUS_QUEUED
)
519 return RAP_JOB_STATUS_QUEUED
;
520 if (v
& JOB_STATUS_PAUSED
)
521 return RAP_JOB_STATUS_PAUSED
;
522 if (v
& JOB_STATUS_SPOOLING
)
523 return RAP_JOB_STATUS_SPOOLING
;
524 if (v
& JOB_STATUS_PRINTING
)
525 return RAP_JOB_STATUS_PRINTING
;
529 /* turn a print queue status into a on the wire status
531 static int printq_spoolss_status(int v
)
533 if (v
== PRINTER_STATUS_OK
)
535 if (v
& PRINTER_STATUS_PAUSED
)
536 return RAP_QUEUE_STATUS_PAUSED
;
537 return RAP_QUEUE_STATUS_ERROR
;
540 static void fill_spoolss_printjob_info(int uLevel
,
541 struct pack_desc
*desc
,
542 struct spoolss_JobInfo2
*info2
,
545 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
547 /* the client expects localtime */
548 t
-= get_time_zone(t
);
550 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
552 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
553 PACKS(desc
,"B",""); /* pad */
554 PACKS(desc
,"B16",""); /* szNotifyName */
555 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
556 PACKS(desc
,"z",""); /* pszParms */
557 PACKI(desc
,"W",n
+1); /* uPosition */
558 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
559 PACKS(desc
,"z",""); /* pszStatus */
560 PACKI(desc
,"D", t
); /* ulSubmitted */
561 PACKI(desc
,"D", info2
->size
); /* ulSize */
562 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
564 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
565 PACKI(desc
,"W", info2
->priority
); /* uPriority */
566 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
567 PACKI(desc
,"W",n
+1); /* uPosition */
568 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
569 PACKI(desc
,"D",t
); /* ulSubmitted */
570 PACKI(desc
,"D", info2
->size
); /* ulSize */
571 PACKS(desc
,"z","Samba"); /* pszComment */
572 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
574 PACKS(desc
,"z",""); /* pszNotifyName */
575 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
576 PACKS(desc
,"z",""); /* pszParms */
577 PACKS(desc
,"z",""); /* pszStatus */
578 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
579 PACKS(desc
,"z","lpd"); /* pszQProcName */
580 PACKS(desc
,"z",""); /* pszQProcParms */
581 PACKS(desc
,"z","NULL"); /* pszDriverName */
582 PackDriverData(desc
); /* pDriverData */
583 PACKS(desc
,"z",""); /* pszPrinterName */
584 } else if (uLevel
== 4) { /* OS2 */
585 PACKS(desc
,"z",""); /* pszSpoolFileName */
586 PACKS(desc
,"z",""); /* pszPortName */
587 PACKS(desc
,"z",""); /* pszStatus */
588 PACKI(desc
,"D",0); /* ulPagesSpooled */
589 PACKI(desc
,"D",0); /* ulPagesSent */
590 PACKI(desc
,"D",0); /* ulPagesPrinted */
591 PACKI(desc
,"D",0); /* ulTimePrinted */
592 PACKI(desc
,"D",0); /* ulExtendJobStatus */
593 PACKI(desc
,"D",0); /* ulStartPage */
594 PACKI(desc
,"D",0); /* ulEndPage */
599 /********************************************************************
600 Respond to the DosPrintQInfo command with a level of 52
601 This is used to get printer driver information for Win9x clients
602 ********************************************************************/
603 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
604 struct pack_desc
* desc
, int count
,
605 const char *printer_name
)
609 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
610 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
611 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
613 PACKI(desc
, "W", 0x0400); /* don't know */
614 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
615 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
616 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
617 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
619 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
620 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
621 PACKS(desc
,"z", location
); /* share to retrieve files */
623 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
624 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
625 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
627 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
628 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
629 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
630 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
631 DEBUG(3,("Driver Location: %s:\n",location
));
632 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
633 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
634 PACKI(desc
,"N",count
); /* number of files to copy */
636 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
638 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
639 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
640 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
645 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
648 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
650 desc
->errcode
=NERR_Success
;
654 static const char *strip_unc(const char *unc
)
662 if ((p
= strrchr(unc
, '\\')) != NULL
) {
669 static void fill_printq_info(int uLevel
,
670 struct pack_desc
* desc
,
672 union spoolss_JobInfo
*job_info
,
673 struct spoolss_DriverInfo3
*driver_info
,
674 struct spoolss_PrinterInfo2
*printer_info
)
680 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
685 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
688 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
692 if (uLevel
== 1 || uLevel
== 2) {
693 PACKS(desc
,"B",""); /* alignment */
694 PACKI(desc
,"W",5); /* priority */
695 PACKI(desc
,"W",0); /* start time */
696 PACKI(desc
,"W",0); /* until time */
697 PACKS(desc
,"z",""); /* pSepFile */
698 PACKS(desc
,"z","lpd"); /* pPrProc */
699 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
700 PACKS(desc
,"z",""); /* pParms */
701 if (printer_info
->printername
== NULL
) {
702 PACKS(desc
,"z","UNKNOWN PRINTER");
703 PACKI(desc
,"W",LPSTAT_ERROR
);
705 PACKS(desc
,"z", printer_info
->comment
);
706 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
708 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
711 if (uLevel
== 3 || uLevel
== 4) {
712 PACKI(desc
,"W",5); /* uPriority */
713 PACKI(desc
,"W",0); /* uStarttime */
714 PACKI(desc
,"W",0); /* uUntiltime */
715 PACKI(desc
,"W",5); /* pad1 */
716 PACKS(desc
,"z",""); /* pszSepFile */
717 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
718 PACKS(desc
,"z",NULL
); /* pszParms */
719 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
720 /* "don't ask" that it's done this way to fix corrupted
721 Win9X/ME printer comments. */
722 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
723 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
724 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
725 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
726 PackDriverData(desc
); /* pDriverData */
729 if (uLevel
== 2 || uLevel
== 4) {
731 for (i
= 0; i
< count
; i
++) {
732 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
737 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
740 /* This function returns the number of files for a given driver */
741 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
745 /* count the number of files */
746 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
752 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
753 connection_struct
*conn
, uint16 vuid
,
754 char *param
, int tpscnt
,
755 char *data
, int tdscnt
,
756 int mdrcnt
,int mprcnt
,
757 char **rdata
,char **rparam
,
758 int *rdata_len
,int *rparam_len
)
760 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
761 char *str2
= skip_string(param
,tpscnt
,str1
);
762 char *p
= skip_string(param
,tpscnt
,str2
);
767 struct pack_desc desc
;
770 WERROR werr
= WERR_OK
;
771 TALLOC_CTX
*mem_ctx
= talloc_tos();
773 struct rpc_pipe_client
*cli
= NULL
;
774 struct policy_handle handle
;
775 struct spoolss_DevmodeContainer devmode_ctr
;
776 union spoolss_DriverInfo driver_info
;
777 union spoolss_JobInfo
*job_info
= NULL
;
778 union spoolss_PrinterInfo printer_info
;
780 if (!str1
|| !str2
|| !p
) {
783 memset((char *)&desc
,'\0',sizeof(desc
));
785 p
= skip_string(param
,tpscnt
,p
);
789 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
790 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
791 /* str3 may be null here and is checked in check_printq_info(). */
793 /* remove any trailing username */
794 if ((p
= strchr_m(QueueName
,'%')))
797 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
799 /* check it's a supported varient */
800 if (!prefix_ok(str1
,"zWrLh"))
802 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
804 * Patch from Scott Moomaw <scott@bridgewater.edu>
805 * to return the 'invalid info level' error if an
806 * unknown level was requested.
810 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
814 SSVALS(*rparam
,0,ERRunknownlevel
);
822 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
823 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
827 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
828 if (!NT_STATUS_IS_OK(status
)) {
829 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
831 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
835 ZERO_STRUCT(devmode_ctr
);
837 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
844 if (!NT_STATUS_IS_OK(status
)) {
845 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
848 if (!W_ERROR_IS_OK(werr
)) {
849 desc
.errcode
= W_ERROR_V(werr
);
853 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
858 if (!W_ERROR_IS_OK(werr
)) {
859 desc
.errcode
= W_ERROR_V(werr
);
864 uint32_t server_major_version
;
865 uint32_t server_minor_version
;
867 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
875 &server_major_version
,
876 &server_minor_version
);
877 if (!W_ERROR_IS_OK(werr
)) {
878 desc
.errcode
= W_ERROR_V(werr
);
882 count
= get_printerdrivernumber(&driver_info
.info3
);
883 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
886 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
894 if (!W_ERROR_IS_OK(werr
)) {
895 desc
.errcode
= W_ERROR_V(werr
);
903 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
908 desc
.buflen
= mdrcnt
;
911 * Don't return data but need to get correct length
912 * init_package will return wrong size if buflen=0
914 desc
.buflen
= getlen(desc
.format
);
915 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
918 if (init_package(&desc
,1,count
)) {
919 desc
.subcount
= count
;
920 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
923 *rdata_len
= desc
.usedlen
;
926 * We must set the return code to ERRbuftoosmall
927 * in order to support lanman style printing with Win NT/2k
930 if (!mdrcnt
&& lp_disable_spoolss())
931 desc
.errcode
= ERRbuftoosmall
;
934 if (cli
&& is_valid_policy_hnd(&handle
)) {
935 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
938 *rdata_len
= desc
.usedlen
;
940 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
945 SSVALS(*rparam
,0,desc
.errcode
);
947 SSVAL(*rparam
,4,desc
.neededlen
);
949 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
956 /****************************************************************************
957 View list of all print jobs on all queues.
958 ****************************************************************************/
960 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
961 connection_struct
*conn
, uint16 vuid
,
962 char *param
, int tpscnt
,
963 char *data
, int tdscnt
,
964 int mdrcnt
, int mprcnt
,
965 char **rdata
, char** rparam
,
966 int *rdata_len
, int *rparam_len
)
968 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
969 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
970 char *p
= skip_string(param
,tpscnt
,output_format1
);
971 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
972 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
974 struct pack_desc desc
;
975 int *subcntarr
= NULL
;
976 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
978 WERROR werr
= WERR_OK
;
979 TALLOC_CTX
*mem_ctx
= talloc_tos();
981 struct rpc_pipe_client
*cli
= NULL
;
982 struct spoolss_DevmodeContainer devmode_ctr
;
983 uint32_t num_printers
;
984 union spoolss_PrinterInfo
*printer_info
;
985 union spoolss_DriverInfo
*driver_info
;
986 union spoolss_JobInfo
**job_info
;
988 if (!param_format
|| !output_format1
|| !p
) {
992 memset((char *)&desc
,'\0',sizeof(desc
));
994 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
996 if (!prefix_ok(param_format
,"WrLeh")) {
999 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1001 * Patch from Scott Moomaw <scott@bridgewater.edu>
1002 * to return the 'invalid info level' error if an
1003 * unknown level was requested.
1007 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1011 SSVALS(*rparam
,0,ERRunknownlevel
);
1017 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
1018 if (!NT_STATUS_IS_OK(status
)) {
1019 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1020 nt_errstr(status
)));
1021 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1025 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1027 cli
->srv_name_slash
,
1032 if (!W_ERROR_IS_OK(werr
)) {
1033 desc
.errcode
= W_ERROR_V(werr
);
1037 queuecnt
= num_printers
;
1039 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1040 if (job_info
== NULL
) {
1044 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1045 if (driver_info
== NULL
) {
1049 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1050 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1055 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1061 desc
.buflen
= mdrcnt
;
1064 for (i
= 0; i
< num_printers
; i
++) {
1067 struct policy_handle handle
;
1068 const char *printername
;
1070 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1071 if (printername
== NULL
) {
1075 ZERO_STRUCT(handle
);
1076 ZERO_STRUCT(devmode_ctr
);
1078 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
1085 if (!NT_STATUS_IS_OK(status
)) {
1086 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1089 if (!W_ERROR_IS_OK(werr
)) {
1090 desc
.errcode
= W_ERROR_V(werr
);
1094 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1102 if (!W_ERROR_IS_OK(werr
)) {
1103 desc
.errcode
= W_ERROR_V(werr
);
1108 uint32_t server_major_version
;
1109 uint32_t server_minor_version
;
1111 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1119 &server_major_version
,
1120 &server_minor_version
);
1121 if (!W_ERROR_IS_OK(werr
)) {
1122 desc
.errcode
= W_ERROR_V(werr
);
1127 subcntarr
[i
] = num_jobs
;
1128 subcnt
+= subcntarr
[i
];
1130 if (cli
&& is_valid_policy_hnd(&handle
)) {
1131 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
1135 if (init_package(&desc
,queuecnt
,subcnt
)) {
1136 for (i
= 0; i
< num_printers
; i
++) {
1137 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1138 if (desc
.errcode
== NERR_Success
) {
1144 SAFE_FREE(subcntarr
);
1146 *rdata_len
= desc
.usedlen
;
1148 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1152 SSVALS(*rparam
,0,desc
.errcode
);
1154 SSVAL(*rparam
,4,succnt
);
1155 SSVAL(*rparam
,6,queuecnt
);
1161 SAFE_FREE(subcntarr
);
1166 /****************************************************************************
1167 Get info level for a server list query.
1168 ****************************************************************************/
1170 static bool check_server_info(int uLevel
, char* id
)
1174 if (strcmp(id
,"B16") != 0) {
1179 if (strcmp(id
,"B16BBDz") != 0) {
1189 struct srv_info_struct
{
1197 /*******************************************************************
1198 Get server info lists from the files saved by nmbd. Return the
1200 ******************************************************************/
1202 static int get_server_info(uint32 servertype
,
1203 struct srv_info_struct
**servers
,
1209 bool local_list_only
;
1212 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1214 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1218 /* request for everything is code for request all servers */
1219 if (servertype
== SV_TYPE_ALL
) {
1220 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1223 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1225 DEBUG(4,("Servertype search: %8x\n",servertype
));
1227 for (i
=0;lines
[i
];i
++) {
1229 struct srv_info_struct
*s
;
1230 const char *ptr
= lines
[i
];
1232 TALLOC_CTX
*frame
= NULL
;
1239 if (count
== alloced
) {
1241 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1243 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1247 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1249 s
= &(*servers
)[count
];
1251 frame
= talloc_stackframe();
1253 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1257 fstrcpy(s
->name
, p
);
1260 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1266 s
->comment
[0] = '\0';
1267 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1271 fstrcpy(s
->comment
, p
);
1272 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1274 s
->domain
[0] = '\0';
1275 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1276 /* this allows us to cope with an old nmbd */
1277 fstrcpy(s
->domain
,lp_workgroup());
1279 fstrcpy(s
->domain
, p
);
1283 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1284 DEBUG(4,("r:host file "));
1288 /* Filter the servers/domains we return based on what was asked for. */
1290 /* Check to see if we are being asked for a local list only. */
1291 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1292 DEBUG(4,("r: local list only"));
1296 /* doesn't match up: don't want it */
1297 if (!(servertype
& s
->type
)) {
1298 DEBUG(4,("r:serv type "));
1302 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1303 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1304 DEBUG(4,("s: dom mismatch "));
1308 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1312 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1313 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1316 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1317 s
->name
, s
->type
, s
->comment
, s
->domain
));
1318 s
->server_added
= True
;
1321 DEBUG(4,("%20s %8x %25s %15s\n",
1322 s
->name
, s
->type
, s
->comment
, s
->domain
));
1330 /*******************************************************************
1331 Fill in a server info structure.
1332 ******************************************************************/
1334 static int fill_srv_info(struct srv_info_struct
*service
,
1335 int uLevel
, char **buf
, int *buflen
,
1336 char **stringbuf
, int *stringspace
, char *baseaddr
)
1359 len
= strlen(service
->comment
)+1;
1363 *buflen
= struct_len
;
1365 return struct_len
+ len
;
1370 if (*buflen
< struct_len
) {
1377 p2
= p
+ struct_len
;
1378 l2
= *buflen
- struct_len
;
1386 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1390 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1391 SIVAL(p
,18,service
->type
);
1392 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1393 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1398 *buf
= p
+ struct_len
;
1399 *buflen
-= struct_len
;
1410 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1412 return StrCaseCmp(s1
->name
,s2
->name
);
1415 /****************************************************************************
1416 View list of servers available (or possibly domains). The info is
1417 extracted from lists saved by nmbd on the local host.
1418 ****************************************************************************/
1420 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1421 connection_struct
*conn
, uint16 vuid
,
1422 char *param
, int tpscnt
,
1423 char *data
, int tdscnt
,
1424 int mdrcnt
, int mprcnt
, char **rdata
,
1425 char **rparam
, int *rdata_len
, int *rparam_len
)
1427 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1428 char *str2
= skip_string(param
,tpscnt
,str1
);
1429 char *p
= skip_string(param
,tpscnt
,str2
);
1430 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1431 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1432 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1434 int data_len
, fixed_len
, string_len
;
1435 int f_len
= 0, s_len
= 0;
1436 struct srv_info_struct
*servers
=NULL
;
1437 int counted
=0,total
=0;
1440 bool domain_request
;
1443 if (!str1
|| !str2
|| !p
) {
1447 /* If someone sets all the bits they don't really mean to set
1448 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1451 if (servertype
== SV_TYPE_ALL
) {
1452 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1455 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1456 any other bit (they may just set this bit on its own) they
1457 want all the locally seen servers. However this bit can be
1458 set on its own so set the requested servers to be
1459 ALL - DOMAIN_ENUM. */
1461 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1462 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1465 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1466 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1470 if (!prefix_ok(str1
,"WrLehD")) {
1473 if (!check_server_info(uLevel
,str2
)) {
1477 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1478 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1479 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1481 if (strcmp(str1
, "WrLehDz") == 0) {
1482 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1485 pull_ascii_fstring(domain
, p
);
1487 fstrcpy(domain
, lp_workgroup());
1490 DEBUG(4, ("domain [%s]\n", domain
));
1492 if (lp_browse_list()) {
1493 total
= get_server_info(servertype
,&servers
,domain
);
1496 data_len
= fixed_len
= string_len
= 0;
1499 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1502 char *lastname
=NULL
;
1504 for (i
=0;i
<total
;i
++) {
1505 struct srv_info_struct
*s
= &servers
[i
];
1507 if (lastname
&& strequal(lastname
,s
->name
)) {
1511 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1512 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1513 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1515 if (data_len
< buf_len
) {
1518 string_len
+= s_len
;
1525 *rdata_len
= fixed_len
+ string_len
;
1526 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1531 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1537 char *lastname
=NULL
;
1538 int count2
= counted
;
1540 for (i
= 0; i
< total
&& count2
;i
++) {
1541 struct srv_info_struct
*s
= &servers
[i
];
1543 if (lastname
&& strequal(lastname
,s
->name
)) {
1547 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1548 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1549 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1555 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1559 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1561 SSVAL(*rparam
,4,counted
);
1562 SSVAL(*rparam
,6,counted
+missed
);
1566 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1567 domain
,uLevel
,counted
,counted
+missed
));
1572 static int srv_name_match(const char *n1
, const char *n2
)
1575 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1577 * In Windows, FirstNameToReturn need not be an exact match:
1578 * the server will return a list of servers that exist on
1579 * the network greater than or equal to the FirstNameToReturn.
1581 int ret
= StrCaseCmp(n1
, n2
);
1590 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1591 connection_struct
*conn
, uint16 vuid
,
1592 char *param
, int tpscnt
,
1593 char *data
, int tdscnt
,
1594 int mdrcnt
, int mprcnt
, char **rdata
,
1595 char **rparam
, int *rdata_len
, int *rparam_len
)
1597 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1598 char *str2
= skip_string(param
,tpscnt
,str1
);
1599 char *p
= skip_string(param
,tpscnt
,str2
);
1600 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1601 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1602 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1604 int data_len
, fixed_len
, string_len
;
1605 int f_len
= 0, s_len
= 0;
1606 struct srv_info_struct
*servers
=NULL
;
1607 int counted
=0,first
=0,total
=0;
1611 bool domain_request
;
1614 if (!str1
|| !str2
|| !p
) {
1618 /* If someone sets all the bits they don't really mean to set
1619 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1622 if (servertype
== SV_TYPE_ALL
) {
1623 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1626 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1627 any other bit (they may just set this bit on its own) they
1628 want all the locally seen servers. However this bit can be
1629 set on its own so set the requested servers to be
1630 ALL - DOMAIN_ENUM. */
1632 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1633 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1636 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1637 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1641 if (strcmp(str1
, "WrLehDzz") != 0) {
1644 if (!check_server_info(uLevel
,str2
)) {
1648 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1649 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1650 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1652 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1655 pull_ascii_fstring(domain
, p
);
1656 if (domain
[0] == '\0') {
1657 fstrcpy(domain
, lp_workgroup());
1659 p
= skip_string(param
,tpscnt
,p
);
1660 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1663 pull_ascii_fstring(first_name
, p
);
1665 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1666 domain
, first_name
));
1668 if (lp_browse_list()) {
1669 total
= get_server_info(servertype
,&servers
,domain
);
1672 data_len
= fixed_len
= string_len
= 0;
1675 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1677 if (first_name
[0] != '\0') {
1678 struct srv_info_struct
*first_server
= NULL
;
1680 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1681 srv_name_match
, first_server
);
1683 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1685 * The binary search may not find the exact match
1686 * so we need to search backward to find the first match
1688 * This implements the strange matching windows
1689 * implements. (see the comment in srv_name_match().
1693 ret
= StrCaseCmp(first_name
,
1694 servers
[first
-1].name
);
1701 /* we should return no entries */
1707 char *lastname
=NULL
;
1709 for (i
=first
;i
<total
;i
++) {
1710 struct srv_info_struct
*s
= &servers
[i
];
1712 if (lastname
&& strequal(lastname
,s
->name
)) {
1716 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1717 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1718 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1720 if (data_len
< buf_len
) {
1723 string_len
+= s_len
;
1730 *rdata_len
= fixed_len
+ string_len
;
1731 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1736 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1742 char *lastname
=NULL
;
1743 int count2
= counted
;
1745 for (i
= first
; i
< total
&& count2
;i
++) {
1746 struct srv_info_struct
*s
= &servers
[i
];
1748 if (lastname
&& strequal(lastname
,s
->name
)) {
1752 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1753 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1754 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1760 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1764 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1766 SSVAL(*rparam
,4,counted
);
1767 SSVAL(*rparam
,6,counted
+missed
);
1769 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1770 domain
,uLevel
,first
,first_name
,
1771 first
< total
? servers
[first
].name
: "",
1772 counted
,counted
+missed
));
1779 /****************************************************************************
1780 command 0x34 - suspected of being a "Lookup Names" stub api
1781 ****************************************************************************/
1783 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1784 connection_struct
*conn
, uint16 vuid
,
1785 char *param
, int tpscnt
,
1786 char *data
, int tdscnt
,
1787 int mdrcnt
, int mprcnt
, char **rdata
,
1788 char **rparam
, int *rdata_len
, int *rparam_len
)
1790 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1791 char *str2
= skip_string(param
,tpscnt
,str1
);
1792 char *p
= skip_string(param
,tpscnt
,str2
);
1793 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1794 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1798 if (!str1
|| !str2
|| !p
) {
1802 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1803 str1
, str2
, p
, uLevel
, buf_len
));
1805 if (!prefix_ok(str1
,"zWrLeh")) {
1812 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1817 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1819 SSVAL(*rparam
,4,counted
);
1820 SSVAL(*rparam
,6,counted
+missed
);
1825 /****************************************************************************
1826 get info about a share
1827 ****************************************************************************/
1829 static bool check_share_info(int uLevel
, char* id
)
1833 if (strcmp(id
,"B13") != 0) {
1838 /* Level-2 descriptor is allowed (and ignored) */
1839 if (strcmp(id
,"B13BWz") != 0 &&
1840 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1845 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1850 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1860 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1861 char** buf
, int* buflen
,
1862 char** stringbuf
, int* stringspace
, char* baseaddr
)
1891 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1894 len
+= strlen(lp_pathname(snum
)) + 1;
1897 *buflen
= struct_len
;
1902 return struct_len
+ len
;
1907 if ((*buflen
) < struct_len
) {
1915 p2
= p
+ struct_len
;
1916 l2
= (*buflen
) - struct_len
;
1923 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1929 type
= STYPE_DISKTREE
;
1930 if (lp_print_ok(snum
)) {
1931 type
= STYPE_PRINTQ
;
1933 if (strequal("IPC",lp_fstype(snum
))) {
1936 SSVAL(p
,14,type
); /* device type */
1937 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1938 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1942 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1943 SSVALS(p
,22,-1); /* max uses */
1944 SSVAL(p
,24,1); /* current uses */
1945 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1946 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1947 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1951 memset(p
+40,0,SHPWLEN
+2);
1962 (*buf
) = p
+ struct_len
;
1963 (*buflen
) -= struct_len
;
1965 (*stringspace
) = l2
;
1974 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
1975 connection_struct
*conn
,uint16 vuid
,
1976 char *param
, int tpscnt
,
1977 char *data
, int tdscnt
,
1978 int mdrcnt
,int mprcnt
,
1979 char **rdata
,char **rparam
,
1980 int *rdata_len
,int *rparam_len
)
1982 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1983 char *str2
= skip_string(param
,tpscnt
,str1
);
1984 char *netname
= skip_string(param
,tpscnt
,str2
);
1985 char *p
= skip_string(param
,tpscnt
,netname
);
1986 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1989 if (!str1
|| !str2
|| !netname
|| !p
) {
1993 snum
= find_service(netname
);
1998 /* check it's a supported varient */
1999 if (!prefix_ok(str1
,"zWrLh")) {
2002 if (!check_share_info(uLevel
,str2
)) {
2006 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2011 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2012 if (*rdata_len
< 0) {
2017 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2021 SSVAL(*rparam
,0,NERR_Success
);
2022 SSVAL(*rparam
,2,0); /* converter word */
2023 SSVAL(*rparam
,4,*rdata_len
);
2028 /****************************************************************************
2029 View the list of available shares.
2031 This function is the server side of the NetShareEnum() RAP call.
2032 It fills the return buffer with share names and share comments.
2033 Note that the return buffer normally (in all known cases) allows only
2034 twelve byte strings for share names (plus one for a nul terminator).
2035 Share names longer than 12 bytes must be skipped.
2036 ****************************************************************************/
2038 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2039 connection_struct
*conn
, uint16 vuid
,
2040 char *param
, int tpscnt
,
2041 char *data
, int tdscnt
,
2049 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2050 char *str2
= skip_string(param
,tpscnt
,str1
);
2051 char *p
= skip_string(param
,tpscnt
,str2
);
2052 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2053 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2056 int total
=0,counted
=0;
2057 bool missed
= False
;
2059 int data_len
, fixed_len
, string_len
;
2060 int f_len
= 0, s_len
= 0;
2062 if (!str1
|| !str2
|| !p
) {
2066 if (!prefix_ok(str1
,"WrLeh")) {
2069 if (!check_share_info(uLevel
,str2
)) {
2073 /* Ensure all the usershares are loaded. */
2075 load_registry_shares();
2076 count
= load_usershare_shares();
2079 data_len
= fixed_len
= string_len
= 0;
2080 for (i
=0;i
<count
;i
++) {
2081 fstring servicename_dos
;
2082 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2085 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2086 /* Maximum name length = 13. */
2087 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2089 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2090 if (data_len
< buf_len
) {
2093 string_len
+= s_len
;
2100 *rdata_len
= fixed_len
+ string_len
;
2101 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2106 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2111 for( i
= 0; i
< count
; i
++ ) {
2112 fstring servicename_dos
;
2113 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2117 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2118 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2119 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2126 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2130 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2132 SSVAL(*rparam
,4,counted
);
2133 SSVAL(*rparam
,6,total
);
2135 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2136 counted
,total
,uLevel
,
2137 buf_len
,*rdata_len
,mdrcnt
));
2142 /****************************************************************************
2144 ****************************************************************************/
2146 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2147 connection_struct
*conn
,uint16 vuid
,
2148 char *param
, int tpscnt
,
2149 char *data
, int tdscnt
,
2150 int mdrcnt
,int mprcnt
,
2151 char **rdata
,char **rparam
,
2152 int *rdata_len
,int *rparam_len
)
2154 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2155 char *str2
= skip_string(param
,tpscnt
,str1
);
2156 char *p
= skip_string(param
,tpscnt
,str2
);
2157 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2160 char *pathname
= NULL
;
2161 unsigned int offset
;
2163 size_t converted_size
;
2165 WERROR werr
= WERR_OK
;
2166 TALLOC_CTX
*mem_ctx
= talloc_tos();
2168 struct rpc_pipe_client
*cli
= NULL
;
2169 union srvsvc_NetShareInfo info
;
2170 struct srvsvc_NetShareInfo2 info2
;
2172 if (!str1
|| !str2
|| !p
) {
2176 /* check it's a supported varient */
2177 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2180 if (!check_share_info(uLevel
,str2
)) {
2187 /* Do we have a string ? */
2188 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2191 pull_ascii_fstring(sharename
,data
);
2197 /* only support disk share adds */
2198 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2202 offset
= IVAL(data
, 16);
2203 if (offset
>= mdrcnt
) {
2204 res
= ERRinvalidparam
;
2208 /* Do we have a string ? */
2209 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2212 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2214 offset
= IVAL(data
, 26);
2216 if (offset
>= mdrcnt
) {
2217 res
= ERRinvalidparam
;
2221 /* Do we have a string ? */
2222 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2226 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2227 offset
? (data
+offset
) : "", &converted_size
))
2229 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2237 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2240 if (!NT_STATUS_IS_OK(status
)) {
2241 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2242 nt_errstr(status
)));
2243 res
= W_ERROR_V(ntstatus_to_werror(status
));
2247 info2
.name
= sharename
;
2248 info2
.type
= STYPE_DISKTREE
;
2249 info2
.comment
= comment
;
2250 info2
.permissions
= 0;
2251 info2
.max_users
= 0;
2252 info2
.current_users
= 0;
2253 info2
.path
= pathname
;
2254 info2
.password
= NULL
;
2256 info
.info2
= &info2
;
2258 status
= rpccli_srvsvc_NetShareAdd(cli
, mem_ctx
,
2259 cli
->srv_name_slash
,
2264 if (!NT_STATUS_IS_OK(status
)) {
2265 res
= W_ERROR_V(ntstatus_to_werror(status
));
2268 if (!W_ERROR_IS_OK(werr
)) {
2269 res
= W_ERROR_V(werr
);
2274 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2278 SSVAL(*rparam
,0,NERR_Success
);
2279 SSVAL(*rparam
,2,0); /* converter word */
2280 SSVAL(*rparam
,4,*rdata_len
);
2288 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2293 SSVAL(*rparam
,0,res
);
2298 /****************************************************************************
2299 view list of groups available
2300 ****************************************************************************/
2302 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2303 connection_struct
*conn
,uint16 vuid
,
2304 char *param
, int tpscnt
,
2305 char *data
, int tdscnt
,
2306 int mdrcnt
,int mprcnt
,
2307 char **rdata
,char **rparam
,
2308 int *rdata_len
,int *rparam_len
)
2312 int resume_context
, cli_buf_size
;
2313 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2314 char *str2
= skip_string(param
,tpscnt
,str1
);
2315 char *p
= skip_string(param
,tpscnt
,str2
);
2317 uint32_t num_groups
;
2318 uint32_t resume_handle
;
2319 struct rpc_pipe_client
*samr_pipe
;
2320 struct policy_handle samr_handle
, domain_handle
;
2323 if (!str1
|| !str2
|| !p
) {
2327 if (strcmp(str1
,"WrLeh") != 0) {
2332 * W-> resume context (number of users to skip)
2333 * r -> return parameter pointer to receive buffer
2334 * L -> length of receive buffer
2335 * e -> return parameter number of entries
2336 * h -> return parameter total number of users
2339 if (strcmp("B21",str2
) != 0) {
2343 status
= rpc_pipe_open_internal(
2344 talloc_tos(), &ndr_table_samr
.syntax_id
,
2345 conn
->server_info
, &samr_pipe
);
2346 if (!NT_STATUS_IS_OK(status
)) {
2347 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2348 nt_errstr(status
)));
2352 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2353 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2354 if (!NT_STATUS_IS_OK(status
)) {
2355 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2356 nt_errstr(status
)));
2360 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2361 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2362 get_global_sam_sid(), &domain_handle
);
2363 if (!NT_STATUS_IS_OK(status
)) {
2364 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2365 nt_errstr(status
)));
2366 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2370 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2371 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2372 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2373 "%d\n", resume_context
, cli_buf_size
));
2375 *rdata_len
= cli_buf_size
;
2376 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2383 errflags
= NERR_Success
;
2388 struct samr_SamArray
*sam_entries
;
2389 uint32_t num_entries
;
2391 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2396 if (!NT_STATUS_IS_OK(status
)) {
2397 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2398 "%s\n", nt_errstr(status
)));
2402 if (num_entries
== 0) {
2403 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2404 "no entries -- done\n"));
2408 for(i
=0; i
<num_entries
; i
++) {
2411 name
= sam_entries
->entries
[i
].name
.string
;
2413 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2414 /* set overflow error */
2415 DEBUG(3,("overflow on entry %d group %s\n", i
,
2421 /* truncate the name at 21 chars. */
2423 strlcpy(p
, name
, 21);
2424 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2426 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2431 if (errflags
!= NERR_Success
) {
2435 TALLOC_FREE(sam_entries
);
2438 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2439 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2441 *rdata_len
= PTR_DIFF(p
,*rdata
);
2444 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2448 SSVAL(*rparam
, 0, errflags
);
2449 SSVAL(*rparam
, 2, 0); /* converter word */
2450 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2451 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2456 /*******************************************************************
2457 Get groups that a user is a member of.
2458 ******************************************************************/
2460 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2461 connection_struct
*conn
,uint16 vuid
,
2462 char *param
, int tpscnt
,
2463 char *data
, int tdscnt
,
2464 int mdrcnt
,int mprcnt
,
2465 char **rdata
,char **rparam
,
2466 int *rdata_len
,int *rparam_len
)
2468 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2469 char *str2
= skip_string(param
,tpscnt
,str1
);
2470 char *UserName
= skip_string(param
,tpscnt
,str2
);
2471 char *p
= skip_string(param
,tpscnt
,UserName
);
2472 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2473 const char *level_string
;
2479 struct rpc_pipe_client
*samr_pipe
;
2480 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2481 struct lsa_String name
;
2482 struct lsa_Strings names
;
2483 struct samr_Ids type
, rid
;
2484 struct samr_RidWithAttributeArray
*rids
;
2487 if (!str1
|| !str2
|| !UserName
|| !p
) {
2492 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2497 /* check it's a supported varient */
2499 if ( strcmp(str1
,"zWrLeh") != 0 )
2504 level_string
= "B21";
2510 if (strcmp(level_string
,str2
) != 0)
2513 *rdata_len
= mdrcnt
+ 1024;
2514 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2519 SSVAL(*rparam
,0,NERR_Success
);
2520 SSVAL(*rparam
,2,0); /* converter word */
2523 endp
= *rdata
+ *rdata_len
;
2525 status
= rpc_pipe_open_internal(
2526 talloc_tos(), &ndr_table_samr
.syntax_id
,
2527 conn
->server_info
, &samr_pipe
);
2528 if (!NT_STATUS_IS_OK(status
)) {
2529 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2530 nt_errstr(status
)));
2534 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2535 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2536 if (!NT_STATUS_IS_OK(status
)) {
2537 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2538 nt_errstr(status
)));
2542 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2543 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2544 get_global_sam_sid(), &domain_handle
);
2545 if (!NT_STATUS_IS_OK(status
)) {
2546 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2547 nt_errstr(status
)));
2551 name
.string
= UserName
;
2553 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2554 &domain_handle
, 1, &name
,
2556 if (!NT_STATUS_IS_OK(status
)) {
2557 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2558 nt_errstr(status
)));
2562 if (type
.ids
[0] != SID_NAME_USER
) {
2563 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2564 sid_type_lookup(type
.ids
[0])));
2568 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2570 SAMR_USER_ACCESS_GET_GROUPS
,
2571 rid
.ids
[0], &user_handle
);
2572 if (!NT_STATUS_IS_OK(status
)) {
2573 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2574 nt_errstr(status
)));
2578 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2579 &user_handle
, &rids
);
2580 if (!NT_STATUS_IS_OK(status
)) {
2581 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2582 nt_errstr(status
)));
2586 for (i
=0; i
<rids
->count
; i
++) {
2588 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2590 1, &rids
->rids
[i
].rid
,
2592 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2593 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2599 *rdata_len
= PTR_DIFF(p
,*rdata
);
2601 SSVAL(*rparam
,4,count
); /* is this right?? */
2602 SSVAL(*rparam
,6,count
); /* is this right?? */
2607 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2609 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2611 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2616 /*******************************************************************
2618 ******************************************************************/
2620 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2621 connection_struct
*conn
, uint16 vuid
,
2622 char *param
, int tpscnt
,
2623 char *data
, int tdscnt
,
2624 int mdrcnt
,int mprcnt
,
2625 char **rdata
,char **rparam
,
2626 int *rdata_len
,int *rparam_len
)
2631 int i
, resume_context
, cli_buf_size
;
2632 uint32_t resume_handle
;
2634 struct rpc_pipe_client
*samr_pipe
;
2635 struct policy_handle samr_handle
, domain_handle
;
2638 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2639 char *str2
= skip_string(param
,tpscnt
,str1
);
2640 char *p
= skip_string(param
,tpscnt
,str2
);
2643 if (!str1
|| !str2
|| !p
) {
2647 if (strcmp(str1
,"WrLeh") != 0)
2650 * W-> resume context (number of users to skip)
2651 * r -> return parameter pointer to receive buffer
2652 * L -> length of receive buffer
2653 * e -> return parameter number of entries
2654 * h -> return parameter total number of users
2657 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2658 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2659 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2660 resume_context
, cli_buf_size
));
2663 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2668 /* check it's a supported varient */
2669 if (strcmp("B21",str2
) != 0)
2672 *rdata_len
= cli_buf_size
;
2673 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2679 endp
= *rdata
+ *rdata_len
;
2681 status
= rpc_pipe_open_internal(
2682 talloc_tos(), &ndr_table_samr
.syntax_id
,
2683 conn
->server_info
, &samr_pipe
);
2684 if (!NT_STATUS_IS_OK(status
)) {
2685 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2686 nt_errstr(status
)));
2690 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2691 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2692 if (!NT_STATUS_IS_OK(status
)) {
2693 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2694 nt_errstr(status
)));
2698 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2699 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2700 get_global_sam_sid(), &domain_handle
);
2701 if (!NT_STATUS_IS_OK(status
)) {
2702 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2703 nt_errstr(status
)));
2704 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2708 errflags
=NERR_Success
;
2713 struct samr_SamArray
*sam_entries
;
2714 uint32_t num_entries
;
2716 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2722 if (!NT_STATUS_IS_OK(status
)) {
2723 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2724 "%s\n", nt_errstr(status
)));
2728 if (num_entries
== 0) {
2729 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2730 "no entries -- done\n"));
2734 for (i
=0; i
<num_entries
; i
++) {
2737 name
= sam_entries
->entries
[i
].name
.string
;
2739 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2740 &&(strlen(name
)<=21)) {
2741 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2742 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2743 "username %s\n",count_sent
,p
));
2747 /* set overflow error */
2748 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2749 "username %s\n",count_sent
,name
));
2755 if (errflags
!= NERR_Success
) {
2759 TALLOC_FREE(sam_entries
);
2762 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2763 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2765 *rdata_len
= PTR_DIFF(p
,*rdata
);
2767 SSVAL(*rparam
,0,errflags
);
2768 SSVAL(*rparam
,2,0); /* converter word */
2769 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2770 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2775 /****************************************************************************
2776 Get the time of day info.
2777 ****************************************************************************/
2779 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2780 connection_struct
*conn
,uint16 vuid
,
2781 char *param
, int tpscnt
,
2782 char *data
, int tdscnt
,
2783 int mdrcnt
,int mprcnt
,
2784 char **rdata
,char **rparam
,
2785 int *rdata_len
,int *rparam_len
)
2788 time_t unixdate
= time(NULL
);
2792 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2798 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2803 SSVAL(*rparam
,0,NERR_Success
);
2804 SSVAL(*rparam
,2,0); /* converter word */
2808 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2809 by NT in a "net time" operation,
2810 it seems to ignore the one below */
2812 /* the client expects to get localtime, not GMT, in this bit
2813 (I think, this needs testing) */
2814 t
= localtime(&unixdate
);
2819 SIVAL(p
,4,0); /* msecs ? */
2820 SCVAL(p
,8,t
->tm_hour
);
2821 SCVAL(p
,9,t
->tm_min
);
2822 SCVAL(p
,10,t
->tm_sec
);
2823 SCVAL(p
,11,0); /* hundredths of seconds */
2824 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2825 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2826 SCVAL(p
,16,t
->tm_mday
);
2827 SCVAL(p
,17,t
->tm_mon
+ 1);
2828 SSVAL(p
,18,1900+t
->tm_year
);
2829 SCVAL(p
,20,t
->tm_wday
);
2834 /****************************************************************************
2835 Set the user password.
2836 *****************************************************************************/
2838 static bool api_SetUserPassword(struct smbd_server_connection
*sconn
,
2839 connection_struct
*conn
,uint16 vuid
,
2840 char *param
, int tpscnt
,
2841 char *data
, int tdscnt
,
2842 int mdrcnt
,int mprcnt
,
2843 char **rdata
,char **rparam
,
2844 int *rdata_len
,int *rparam_len
)
2846 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2849 fstring pass1
,pass2
;
2850 TALLOC_CTX
*mem_ctx
= talloc_tos();
2852 struct rpc_pipe_client
*cli
= NULL
;
2853 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2854 struct lsa_String domain_name
;
2855 struct dom_sid2
*domain_sid
;
2856 struct lsa_String names
;
2857 struct samr_Ids rids
;
2858 struct samr_Ids types
;
2859 struct samr_Password old_lm_hash
;
2860 struct samr_Password new_lm_hash
;
2861 int errcode
= NERR_badpass
;
2866 /* Skip 2 strings. */
2867 p
= skip_string(param
,tpscnt
,np
);
2868 p
= skip_string(param
,tpscnt
,p
);
2874 /* Do we have a string ? */
2875 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2878 pull_ascii_fstring(user
,p
);
2880 p
= skip_string(param
,tpscnt
,p
);
2885 memset(pass1
,'\0',sizeof(pass1
));
2886 memset(pass2
,'\0',sizeof(pass2
));
2888 * We use 31 here not 32 as we're checking
2889 * the last byte we want to access is safe.
2891 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2895 memcpy(pass2
,p
+16,16);
2897 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
2898 if (encrypted
== -1) {
2899 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2903 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
2904 if (min_pwd_length
== -1) {
2905 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2910 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2917 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2918 user
, encrypted
, min_pwd_length
));
2920 ZERO_STRUCT(connect_handle
);
2921 ZERO_STRUCT(domain_handle
);
2922 ZERO_STRUCT(user_handle
);
2924 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
2927 if (!NT_STATUS_IS_OK(status
)) {
2928 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2929 nt_errstr(status
)));
2930 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2934 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
2936 SAMR_ACCESS_CONNECT_TO_SERVER
|
2937 SAMR_ACCESS_ENUM_DOMAINS
|
2938 SAMR_ACCESS_LOOKUP_DOMAIN
,
2940 if (!NT_STATUS_IS_OK(status
)) {
2941 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2945 init_lsa_String(&domain_name
, get_global_sam_name());
2947 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
2951 if (!NT_STATUS_IS_OK(status
)) {
2952 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2956 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
2958 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2961 if (!NT_STATUS_IS_OK(status
)) {
2962 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2966 init_lsa_String(&names
, user
);
2968 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
2974 if (!NT_STATUS_IS_OK(status
)) {
2975 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2979 if (rids
.count
!= 1) {
2980 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
2983 if (rids
.count
!= types
.count
) {
2984 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2987 if (types
.ids
[0] != SID_NAME_USER
) {
2988 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2994 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
2996 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
2999 if (!NT_STATUS_IS_OK(status
)) {
3000 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3004 if (encrypted
== 0) {
3005 E_deshash(pass1
, old_lm_hash
.hash
);
3006 E_deshash(pass2
, new_lm_hash
.hash
);
3008 ZERO_STRUCT(old_lm_hash
);
3009 ZERO_STRUCT(new_lm_hash
);
3010 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
3011 memcpy(new_lm_hash
.hash
, pass1
, MIN(strlen(pass2
), 16));
3014 status
= rpccli_samr_ChangePasswordUser(cli
, mem_ctx
,
3016 true, /* lm_present */
3019 false, /* nt_present */
3020 NULL
, /* old_nt_crypted */
3021 NULL
, /* new_nt_crypted */
3022 false, /* cross1_present */
3023 NULL
, /* nt_cross */
3024 false, /* cross2_present */
3025 NULL
); /* lm_cross */
3026 if (!NT_STATUS_IS_OK(status
)) {
3027 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3031 errcode
= NERR_Success
;
3034 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
3035 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
3037 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
3038 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
3040 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
3041 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
3044 memset((char *)pass1
,'\0',sizeof(fstring
));
3045 memset((char *)pass2
,'\0',sizeof(fstring
));
3047 SSVAL(*rparam
,0,errcode
);
3048 SSVAL(*rparam
,2,0); /* converter word */
3052 /****************************************************************************
3053 Set the user password (SamOEM version - gets plaintext).
3054 ****************************************************************************/
3056 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3057 connection_struct
*conn
,uint16 vuid
,
3058 char *param
, int tpscnt
,
3059 char *data
, int tdscnt
,
3060 int mdrcnt
,int mprcnt
,
3061 char **rdata
,char **rparam
,
3062 int *rdata_len
,int *rparam_len
)
3065 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3067 TALLOC_CTX
*mem_ctx
= talloc_tos();
3069 struct rpc_pipe_client
*cli
= NULL
;
3070 struct lsa_AsciiString server
, account
;
3071 struct samr_CryptPassword password
;
3072 struct samr_Password hash
;
3073 int errcode
= NERR_badpass
;
3077 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3087 SSVAL(*rparam
,0,NERR_badpass
);
3090 * Check the parameter definition is correct.
3093 /* Do we have a string ? */
3094 if (skip_string(param
,tpscnt
,p
) == 0) {
3097 if(!strequal(p
, "zsT")) {
3098 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3101 p
= skip_string(param
, tpscnt
, p
);
3106 /* Do we have a string ? */
3107 if (skip_string(param
,tpscnt
,p
) == 0) {
3110 if(!strequal(p
, "B516B16")) {
3111 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3114 p
= skip_string(param
,tpscnt
,p
);
3118 /* Do we have a string ? */
3119 if (skip_string(param
,tpscnt
,p
) == 0) {
3122 p
+= pull_ascii_fstring(user
,p
);
3124 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3126 if (tdscnt
!= 532) {
3127 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3131 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3132 if (bufsize
!= 532) {
3133 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3137 memcpy(password
.data
, data
, 516);
3138 memcpy(hash
.hash
, data
+516, 16);
3140 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3143 if (!NT_STATUS_IS_OK(status
)) {
3144 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3145 nt_errstr(status
)));
3146 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3150 init_lsa_AsciiString(&server
, global_myname());
3151 init_lsa_AsciiString(&account
, user
);
3153 status
= rpccli_samr_OemChangePasswordUser2(cli
, mem_ctx
,
3158 if (!NT_STATUS_IS_OK(status
)) {
3159 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3163 errcode
= NERR_Success
;
3165 SSVAL(*rparam
,0,errcode
);
3166 SSVAL(*rparam
,2,0); /* converter word */
3171 /****************************************************************************
3174 ****************************************************************************/
3176 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3177 connection_struct
*conn
,uint16 vuid
,
3178 char *param
, int tpscnt
,
3179 char *data
, int tdscnt
,
3180 int mdrcnt
,int mprcnt
,
3181 char **rdata
,char **rparam
,
3182 int *rdata_len
,int *rparam_len
)
3184 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3185 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3186 char *str2
= skip_string(param
,tpscnt
,str1
);
3187 char *p
= skip_string(param
,tpscnt
,str2
);
3191 WERROR werr
= WERR_OK
;
3193 TALLOC_CTX
*mem_ctx
= talloc_tos();
3195 struct rpc_pipe_client
*cli
= NULL
;
3196 struct policy_handle handle
;
3197 struct spoolss_DevmodeContainer devmode_ctr
;
3198 enum spoolss_JobControl command
;
3200 if (!str1
|| !str2
|| !p
) {
3204 * We use 1 here not 2 as we're checking
3205 * the last byte we want to access is safe.
3207 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3210 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3213 /* check it's a supported varient */
3214 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3218 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3224 ZERO_STRUCT(handle
);
3226 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3227 if (!NT_STATUS_IS_OK(status
)) {
3228 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3229 nt_errstr(status
)));
3230 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3234 ZERO_STRUCT(devmode_ctr
);
3236 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3240 JOB_ACCESS_ADMINISTER
,
3243 if (!NT_STATUS_IS_OK(status
)) {
3244 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3247 if (!W_ERROR_IS_OK(werr
)) {
3248 errcode
= W_ERROR_V(werr
);
3252 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3253 * and NERR_DestNotFound if share did not exist */
3255 errcode
= NERR_Success
;
3258 case 81: /* delete */
3259 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3261 case 82: /* pause */
3262 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3264 case 83: /* resume */
3265 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3268 errcode
= NERR_notsupported
;
3272 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3275 NULL
, /* unique ptr ctr */
3278 if (!NT_STATUS_IS_OK(status
)) {
3279 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3282 if (!W_ERROR_IS_OK(werr
)) {
3283 errcode
= W_ERROR_V(werr
);
3288 if (cli
&& is_valid_policy_hnd(&handle
)) {
3289 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3292 SSVAL(*rparam
,0,errcode
);
3293 SSVAL(*rparam
,2,0); /* converter word */
3298 /****************************************************************************
3299 Purge a print queue - or pause or resume it.
3300 ****************************************************************************/
3302 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3303 connection_struct
*conn
,uint16 vuid
,
3304 char *param
, int tpscnt
,
3305 char *data
, int tdscnt
,
3306 int mdrcnt
,int mprcnt
,
3307 char **rdata
,char **rparam
,
3308 int *rdata_len
,int *rparam_len
)
3310 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3311 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3312 char *str2
= skip_string(param
,tpscnt
,str1
);
3313 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3314 int errcode
= NERR_notsupported
;
3315 WERROR werr
= WERR_OK
;
3318 TALLOC_CTX
*mem_ctx
= talloc_tos();
3319 struct rpc_pipe_client
*cli
= NULL
;
3320 struct policy_handle handle
;
3321 struct spoolss_SetPrinterInfoCtr info_ctr
;
3322 struct spoolss_DevmodeContainer devmode_ctr
;
3323 struct sec_desc_buf secdesc_ctr
;
3324 enum spoolss_PrinterControl command
;
3326 if (!str1
|| !str2
|| !QueueName
) {
3330 /* check it's a supported varient */
3331 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3335 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3341 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3345 ZERO_STRUCT(handle
);
3347 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3348 if (!NT_STATUS_IS_OK(status
)) {
3349 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3350 nt_errstr(status
)));
3351 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3355 ZERO_STRUCT(devmode_ctr
);
3357 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3361 SEC_FLAG_MAXIMUM_ALLOWED
,
3364 if (!NT_STATUS_IS_OK(status
)) {
3365 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3368 if (!W_ERROR_IS_OK(werr
)) {
3369 errcode
= W_ERROR_V(werr
);
3374 case 74: /* Pause queue */
3375 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3377 case 75: /* Resume queue */
3378 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3380 case 103: /* Purge */
3381 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3384 werr
= WERR_NOT_SUPPORTED
;
3388 if (!W_ERROR_IS_OK(werr
)) {
3389 errcode
= W_ERROR_V(werr
);
3393 ZERO_STRUCT(info_ctr
);
3394 ZERO_STRUCT(secdesc_ctr
);
3396 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3403 if (!NT_STATUS_IS_OK(status
)) {
3404 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3407 if (!W_ERROR_IS_OK(werr
)) {
3408 errcode
= W_ERROR_V(werr
);
3412 errcode
= W_ERROR_V(werr
);
3416 if (cli
&& is_valid_policy_hnd(&handle
)) {
3417 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3420 SSVAL(*rparam
,0,errcode
);
3421 SSVAL(*rparam
,2,0); /* converter word */
3426 /****************************************************************************
3427 set the property of a print job (undocumented?)
3428 ? function = 0xb -> set name of print job
3429 ? function = 0x6 -> move print job up/down
3430 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3431 or <WWsTP> <WB21BB16B10zWWzDDz>
3432 ****************************************************************************/
3434 static int check_printjob_info(struct pack_desc
* desc
,
3435 int uLevel
, char* id
)
3437 desc
->subformat
= NULL
;
3439 case 0: desc
->format
= "W"; break;
3440 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3441 case 2: desc
->format
= "WWzWWDDzz"; break;
3442 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3443 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3445 DEBUG(0,("check_printjob_info: invalid level %d\n",
3449 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3450 DEBUG(0,("check_printjob_info: invalid format %s\n",
3451 id
? id
: "<NULL>" ));
3457 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3458 connection_struct
*conn
, uint16 vuid
,
3459 char *param
, int tpscnt
,
3460 char *data
, int tdscnt
,
3461 int mdrcnt
,int mprcnt
,
3462 char **rdata
,char **rparam
,
3463 int *rdata_len
,int *rparam_len
)
3465 struct pack_desc desc
;
3466 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3467 char *str2
= skip_string(param
,tpscnt
,str1
);
3468 char *p
= skip_string(param
,tpscnt
,str2
);
3471 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3472 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3475 TALLOC_CTX
*mem_ctx
= talloc_tos();
3478 struct rpc_pipe_client
*cli
= NULL
;
3479 struct policy_handle handle
;
3480 struct spoolss_DevmodeContainer devmode_ctr
;
3481 struct spoolss_JobInfoContainer ctr
;
3482 union spoolss_JobInfo info
;
3483 struct spoolss_SetJobInfo1 info1
;
3485 if (!str1
|| !str2
|| !p
) {
3489 * We use 1 here not 2 as we're checking
3490 * the last byte we want to access is safe.
3492 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3495 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3498 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3505 /* check it's a supported varient */
3506 if ((strcmp(str1
,"WWsTP")) ||
3507 (!check_printjob_info(&desc
,uLevel
,str2
)))
3510 errcode
= NERR_notsupported
;
3514 /* change print job name, data gives the name */
3520 ZERO_STRUCT(handle
);
3522 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3523 if (!NT_STATUS_IS_OK(status
)) {
3524 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3525 nt_errstr(status
)));
3526 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3530 ZERO_STRUCT(devmode_ctr
);
3532 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3539 if (!NT_STATUS_IS_OK(status
)) {
3540 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3543 if (!W_ERROR_IS_OK(werr
)) {
3544 errcode
= W_ERROR_V(werr
);
3548 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3554 if (!W_ERROR_IS_OK(werr
)) {
3555 errcode
= W_ERROR_V(werr
);
3561 info1
.job_id
= info
.info1
.job_id
;
3562 info1
.printer_name
= info
.info1
.printer_name
;
3563 info1
.user_name
= info
.info1
.user_name
;
3564 info1
.document_name
= data
;
3565 info1
.data_type
= info
.info1
.data_type
;
3566 info1
.text_status
= info
.info1
.text_status
;
3567 info1
.status
= info
.info1
.status
;
3568 info1
.priority
= info
.info1
.priority
;
3569 info1
.position
= info
.info1
.position
;
3570 info1
.total_pages
= info
.info1
.total_pages
;
3571 info1
.pages_printed
= info
.info1
.pages_printed
;
3572 info1
.submitted
= info
.info1
.submitted
;
3575 ctr
.info
.info1
= &info1
;
3577 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3583 if (!NT_STATUS_IS_OK(status
)) {
3584 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3587 if (!W_ERROR_IS_OK(werr
)) {
3588 errcode
= W_ERROR_V(werr
);
3592 errcode
= NERR_Success
;
3595 if (cli
&& is_valid_policy_hnd(&handle
)) {
3596 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3599 SSVALS(*rparam
,0,errcode
);
3600 SSVAL(*rparam
,2,0); /* converter word */
3606 /****************************************************************************
3607 Get info about the server.
3608 ****************************************************************************/
3610 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3611 connection_struct
*conn
,uint16 vuid
,
3612 char *param
, int tpscnt
,
3613 char *data
, int tdscnt
,
3614 int mdrcnt
,int mprcnt
,
3615 char **rdata
,char **rparam
,
3616 int *rdata_len
,int *rparam_len
)
3618 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3619 char *str2
= skip_string(param
,tpscnt
,str1
);
3620 char *p
= skip_string(param
,tpscnt
,str2
);
3621 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3627 TALLOC_CTX
*mem_ctx
= talloc_tos();
3628 struct rpc_pipe_client
*cli
= NULL
;
3629 union srvsvc_NetSrvInfo info
;
3632 if (!str1
|| !str2
|| !p
) {
3636 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3638 /* check it's a supported varient */
3639 if (!prefix_ok(str1
,"WrLh")) {
3645 if (strcmp(str2
,"B16") != 0) {
3651 if (strcmp(str2
,"B16BBDz") != 0) {
3657 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3663 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3669 if (strcmp(str2
,"DN") != 0) {
3675 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3684 *rdata_len
= mdrcnt
;
3685 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3691 p2
= p
+ struct_len
;
3693 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3696 if (!NT_STATUS_IS_OK(status
)) {
3697 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3698 nt_errstr(status
)));
3699 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3703 status
= rpccli_srvsvc_NetSrvGetInfo(cli
, mem_ctx
,
3708 if (!NT_STATUS_IS_OK(status
)) {
3709 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3712 if (!W_ERROR_IS_OK(werr
)) {
3713 errcode
= W_ERROR_V(werr
);
3717 if (info
.info101
== NULL
) {
3718 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3723 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3724 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3728 SCVAL(p
,0,info
.info101
->version_major
);
3729 SCVAL(p
,1,info
.info101
->version_minor
);
3730 SIVAL(p
,2,info
.info101
->server_type
);
3732 if (mdrcnt
== struct_len
) {
3735 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3736 if (mdrcnt
- struct_len
<= 0) {
3740 info
.info101
->comment
,
3741 MIN(mdrcnt
- struct_len
,
3742 MAX_SERVER_STRING_LENGTH
),
3744 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3752 return False
; /* not yet implemented */
3755 errcode
= NERR_Success
;
3759 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3762 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3766 SSVAL(*rparam
,0,errcode
);
3767 SSVAL(*rparam
,2,0); /* converter word */
3768 SSVAL(*rparam
,4,*rdata_len
);
3773 /****************************************************************************
3774 Get info about the server.
3775 ****************************************************************************/
3777 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3778 connection_struct
*conn
,uint16 vuid
,
3779 char *param
, int tpscnt
,
3780 char *data
, int tdscnt
,
3781 int mdrcnt
,int mprcnt
,
3782 char **rdata
,char **rparam
,
3783 int *rdata_len
,int *rparam_len
)
3785 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3786 char *str2
= skip_string(param
,tpscnt
,str1
);
3787 char *p
= skip_string(param
,tpscnt
,str2
);
3790 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3792 if (!str1
|| !str2
|| !p
) {
3796 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3799 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3804 /* check it's a supported varient */
3805 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3809 *rdata_len
= mdrcnt
+ 1024;
3810 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3815 SSVAL(*rparam
,0,NERR_Success
);
3816 SSVAL(*rparam
,2,0); /* converter word */
3819 endp
= *rdata
+ *rdata_len
;
3821 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3826 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3827 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3829 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3835 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3836 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3837 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3843 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3844 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3846 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3852 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3853 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3856 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3857 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3858 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3864 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3865 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3866 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3872 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3874 SSVAL(*rparam
,4,*rdata_len
);
3879 /****************************************************************************
3880 get info about a user
3882 struct user_info_11 {
3883 char usri11_name[21]; 0-20
3885 char *usri11_comment; 22-25
3886 char *usri11_usr_comment; 26-29
3887 unsigned short usri11_priv; 30-31
3888 unsigned long usri11_auth_flags; 32-35
3889 long usri11_password_age; 36-39
3890 char *usri11_homedir; 40-43
3891 char *usri11_parms; 44-47
3892 long usri11_last_logon; 48-51
3893 long usri11_last_logoff; 52-55
3894 unsigned short usri11_bad_pw_count; 56-57
3895 unsigned short usri11_num_logons; 58-59
3896 char *usri11_logon_server; 60-63
3897 unsigned short usri11_country_code; 64-65
3898 char *usri11_workstations; 66-69
3899 unsigned long usri11_max_storage; 70-73
3900 unsigned short usri11_units_per_week; 74-75
3901 unsigned char *usri11_logon_hours; 76-79
3902 unsigned short usri11_code_page; 80-81
3907 usri11_name specifies the user name for which information is retrieved
3909 usri11_pad aligns the next data structure element to a word boundary
3911 usri11_comment is a null terminated ASCII comment
3913 usri11_user_comment is a null terminated ASCII comment about the user
3915 usri11_priv specifies the level of the privilege assigned to the user.
3916 The possible values are:
3918 Name Value Description
3919 USER_PRIV_GUEST 0 Guest privilege
3920 USER_PRIV_USER 1 User privilege
3921 USER_PRV_ADMIN 2 Administrator privilege
3923 usri11_auth_flags specifies the account operator privileges. The
3924 possible values are:
3926 Name Value Description
3927 AF_OP_PRINT 0 Print operator
3930 Leach, Naik [Page 28]
3934 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3937 AF_OP_COMM 1 Communications operator
3938 AF_OP_SERVER 2 Server operator
3939 AF_OP_ACCOUNTS 3 Accounts operator
3942 usri11_password_age specifies how many seconds have elapsed since the
3943 password was last changed.
3945 usri11_home_dir points to a null terminated ASCII string that contains
3946 the path name of the user's home directory.
3948 usri11_parms points to a null terminated ASCII string that is set
3949 aside for use by applications.
3951 usri11_last_logon specifies the time when the user last logged on.
3952 This value is stored as the number of seconds elapsed since
3953 00:00:00, January 1, 1970.
3955 usri11_last_logoff specifies the time when the user last logged off.
3956 This value is stored as the number of seconds elapsed since
3957 00:00:00, January 1, 1970. A value of 0 means the last logoff
3960 usri11_bad_pw_count specifies the number of incorrect passwords
3961 entered since the last successful logon.
3963 usri11_log1_num_logons specifies the number of times this user has
3964 logged on. A value of -1 means the number of logons is unknown.
3966 usri11_logon_server points to a null terminated ASCII string that
3967 contains the name of the server to which logon requests are sent.
3968 A null string indicates logon requests should be sent to the
3971 usri11_country_code specifies the country code for the user's language
3974 usri11_workstations points to a null terminated ASCII string that
3975 contains the names of workstations the user may log on from.
3976 There may be up to 8 workstations, with the names separated by
3977 commas. A null strings indicates there are no restrictions.
3979 usri11_max_storage specifies the maximum amount of disk space the user
3980 can occupy. A value of 0xffffffff indicates there are no
3983 usri11_units_per_week specifies the equal number of time units into
3984 which a week is divided. This value must be equal to 168.
3986 usri11_logon_hours points to a 21 byte (168 bits) string that
3987 specifies the time during which the user can log on. Each bit
3988 represents one unique hour in a week. The first bit (bit 0, word
3989 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3993 Leach, Naik [Page 29]
3997 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4000 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4001 are no restrictions.
4003 usri11_code_page specifies the code page for the user's language of
4006 All of the pointers in this data structure need to be treated
4007 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4008 to be ignored. The converter word returned in the parameters section
4009 needs to be subtracted from the lower 16 bits to calculate an offset
4010 into the return buffer where this ASCII string resides.
4012 There is no auxiliary data in the response.
4014 ****************************************************************************/
4016 #define usri11_name 0
4017 #define usri11_pad 21
4018 #define usri11_comment 22
4019 #define usri11_usr_comment 26
4020 #define usri11_full_name 30
4021 #define usri11_priv 34
4022 #define usri11_auth_flags 36
4023 #define usri11_password_age 40
4024 #define usri11_homedir 44
4025 #define usri11_parms 48
4026 #define usri11_last_logon 52
4027 #define usri11_last_logoff 56
4028 #define usri11_bad_pw_count 60
4029 #define usri11_num_logons 62
4030 #define usri11_logon_server 64
4031 #define usri11_country_code 68
4032 #define usri11_workstations 70
4033 #define usri11_max_storage 74
4034 #define usri11_units_per_week 78
4035 #define usri11_logon_hours 80
4036 #define usri11_code_page 84
4037 #define usri11_end 86
4039 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4040 connection_struct
*conn
, uint16 vuid
,
4041 char *param
, int tpscnt
,
4042 char *data
, int tdscnt
,
4043 int mdrcnt
,int mprcnt
,
4044 char **rdata
,char **rparam
,
4045 int *rdata_len
,int *rparam_len
)
4047 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4048 char *str2
= skip_string(param
,tpscnt
,str1
);
4049 char *UserName
= skip_string(param
,tpscnt
,str2
);
4050 char *p
= skip_string(param
,tpscnt
,UserName
);
4051 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4054 const char *level_string
;
4056 TALLOC_CTX
*mem_ctx
= talloc_tos();
4058 struct rpc_pipe_client
*cli
= NULL
;
4059 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4060 struct lsa_String domain_name
;
4061 struct dom_sid2
*domain_sid
;
4062 struct lsa_String names
;
4063 struct samr_Ids rids
;
4064 struct samr_Ids types
;
4065 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4067 union samr_UserInfo
*info
;
4069 if (!str1
|| !str2
|| !UserName
|| !p
) {
4074 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4079 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4081 /* check it's a supported variant */
4082 if (strcmp(str1
,"zWrLh") != 0) {
4086 case 0: level_string
= "B21"; break;
4087 case 1: level_string
= "B21BB16DWzzWz"; break;
4088 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4089 case 10: level_string
= "B21Bzzz"; break;
4090 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4091 default: return False
;
4094 if (strcmp(level_string
,str2
) != 0) {
4098 *rdata_len
= mdrcnt
+ 1024;
4099 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4105 endp
= *rdata
+ *rdata_len
;
4106 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4111 ZERO_STRUCT(connect_handle
);
4112 ZERO_STRUCT(domain_handle
);
4113 ZERO_STRUCT(user_handle
);
4115 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
4118 if (!NT_STATUS_IS_OK(status
)) {
4119 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4120 nt_errstr(status
)));
4121 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4125 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
4127 SAMR_ACCESS_CONNECT_TO_SERVER
|
4128 SAMR_ACCESS_ENUM_DOMAINS
|
4129 SAMR_ACCESS_LOOKUP_DOMAIN
,
4131 if (!NT_STATUS_IS_OK(status
)) {
4132 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4136 init_lsa_String(&domain_name
, get_global_sam_name());
4138 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
4142 if (!NT_STATUS_IS_OK(status
)) {
4143 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4147 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
4149 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4152 if (!NT_STATUS_IS_OK(status
)) {
4153 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4157 init_lsa_String(&names
, UserName
);
4159 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
4165 if (!NT_STATUS_IS_OK(status
)) {
4166 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4170 if (rids
.count
!= 1) {
4171 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4174 if (rids
.count
!= types
.count
) {
4175 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4178 if (types
.ids
[0] != SID_NAME_USER
) {
4179 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4185 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
4187 SAMR_USER_ACCESS_GET_LOCALE
|
4188 SAMR_USER_ACCESS_GET_LOGONINFO
|
4189 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4190 SAMR_USER_ACCESS_GET_GROUPS
|
4191 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4192 SEC_STD_READ_CONTROL
,
4195 if (!NT_STATUS_IS_OK(status
)) {
4196 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4200 status
= rpccli_samr_QueryUserInfo2(cli
, mem_ctx
,
4204 if (!NT_STATUS_IS_OK(status
)) {
4205 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4210 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4213 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4218 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4219 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4220 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4225 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4226 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4227 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4232 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4233 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4234 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4235 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4242 const char *homedir
= info
->info21
.home_directory
.string
;
4243 /* modelled after NTAS 3.51 reply */
4244 SSVAL(p
,usri11_priv
,
4245 (get_current_uid(conn
) == sec_initial_uid())?
4246 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4247 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4248 SIVALS(p
,usri11_password_age
,-1); /* password age */
4249 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4250 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4251 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4255 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4256 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4257 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4261 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4262 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4263 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4264 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4265 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4266 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4267 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4271 SSVAL(p
,usri11_country_code
,0); /* country code */
4273 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4274 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4275 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4280 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4281 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4282 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4284 /* a simple way to get logon hours at all times. */
4286 SCVAL(p2
,21,0); /* fix zero termination */
4287 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4292 SSVAL(p
,usri11_code_page
,0); /* code page */
4295 if (uLevel
== 1 || uLevel
== 2) {
4296 memset(p
+22,' ',16); /* password */
4297 SIVALS(p
,38,-1); /* password age */
4299 (get_current_uid(conn
) == sec_initial_uid())?
4300 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4301 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4302 strlcpy(p2
, info
->info21
.home_directory
.string
,
4304 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4308 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4310 SSVAL(p
,52,0); /* flags */
4311 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4312 strlcpy(p2
, info
->info21
.logon_script
.string
,
4314 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4319 SIVAL(p
,58,0); /* auth_flags */
4320 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4321 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4322 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4326 SIVAL(p
,66,0); /* urs_comment */
4327 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4328 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4329 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4333 SIVAL(p
,74,0); /* workstations */
4334 SIVAL(p
,78,0); /* last_logon */
4335 SIVAL(p
,82,0); /* last_logoff */
4336 SIVALS(p
,86,-1); /* acct_expires */
4337 SIVALS(p
,90,-1); /* max_storage */
4338 SSVAL(p
,94,168); /* units_per_week */
4339 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4342 SSVALS(p
,100,-1); /* bad_pw_count */
4343 SSVALS(p
,102,-1); /* num_logons */
4344 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4346 TALLOC_CTX
*ctx
= talloc_tos();
4347 int space_rem
= *rdata_len
- (p2
- *rdata
);
4350 if (space_rem
<= 0) {
4353 tmp
= talloc_strdup(ctx
, "\\\\%L");
4357 tmp
= talloc_sub_basic(ctx
,
4370 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4374 SSVAL(p
,108,49); /* country_code */
4375 SSVAL(p
,110,860); /* code page */
4379 errcode
= NERR_Success
;
4382 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4384 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
4385 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
4387 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
4388 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
4390 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
4391 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
4394 SSVAL(*rparam
,0,errcode
);
4395 SSVAL(*rparam
,2,0); /* converter word */
4396 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4401 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4402 connection_struct
*conn
,uint16 vuid
,
4403 char *param
, int tpscnt
,
4404 char *data
, int tdscnt
,
4405 int mdrcnt
,int mprcnt
,
4406 char **rdata
,char **rparam
,
4407 int *rdata_len
,int *rparam_len
)
4409 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4410 char *str2
= skip_string(param
,tpscnt
,str1
);
4411 char *p
= skip_string(param
,tpscnt
,str2
);
4413 struct pack_desc desc
;
4415 /* With share level security vuid will always be zero.
4416 Don't depend on vuser being non-null !!. JRA */
4417 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4419 if (!str1
|| !str2
|| !p
) {
4424 DEBUG(3,(" Username of UID %d is %s\n",
4425 (int)vuser
->server_info
->utok
.uid
,
4426 vuser
->server_info
->unix_name
));
4429 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4430 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4435 memset((char *)&desc
,'\0',sizeof(desc
));
4437 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4439 /* check it's a supported varient */
4440 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4443 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4447 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4454 desc
.buflen
= mdrcnt
;
4455 desc
.subformat
= NULL
;
4458 if (init_package(&desc
,1,0)) {
4459 PACKI(&desc
,"W",0); /* code */
4460 PACKS(&desc
,"B21",name
); /* eff. name */
4461 PACKS(&desc
,"B",""); /* pad */
4463 (get_current_uid(conn
) == sec_initial_uid())?
4464 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4465 PACKI(&desc
,"D",0); /* auth flags XXX */
4466 PACKI(&desc
,"W",0); /* num logons */
4467 PACKI(&desc
,"W",0); /* bad pw count */
4468 PACKI(&desc
,"D",0); /* last logon */
4469 PACKI(&desc
,"D",-1); /* last logoff */
4470 PACKI(&desc
,"D",-1); /* logoff time */
4471 PACKI(&desc
,"D",-1); /* kickoff time */
4472 PACKI(&desc
,"D",0); /* password age */
4473 PACKI(&desc
,"D",0); /* password can change */
4474 PACKI(&desc
,"D",-1); /* password must change */
4478 fstrcpy(mypath
,"\\\\");
4479 fstrcat(mypath
,get_local_machine_name());
4481 PACKS(&desc
,"z",mypath
); /* computer */
4484 PACKS(&desc
,"z",lp_workgroup());/* domain */
4485 PACKS(&desc
,"z", vuser
?
4486 vuser
->server_info
->info3
->base
.logon_script
.string
4487 : ""); /* script path */
4488 PACKI(&desc
,"D",0x00000000); /* reserved */
4491 *rdata_len
= desc
.usedlen
;
4493 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4497 SSVALS(*rparam
,0,desc
.errcode
);
4499 SSVAL(*rparam
,4,desc
.neededlen
);
4501 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4506 /****************************************************************************
4507 api_WAccessGetUserPerms
4508 ****************************************************************************/
4510 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4511 connection_struct
*conn
,uint16 vuid
,
4512 char *param
, int tpscnt
,
4513 char *data
, int tdscnt
,
4514 int mdrcnt
,int mprcnt
,
4515 char **rdata
,char **rparam
,
4516 int *rdata_len
,int *rparam_len
)
4518 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4519 char *str2
= skip_string(param
,tpscnt
,str1
);
4520 char *user
= skip_string(param
,tpscnt
,str2
);
4521 char *resource
= skip_string(param
,tpscnt
,user
);
4523 if (!str1
|| !str2
|| !user
|| !resource
) {
4527 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4530 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4532 /* check it's a supported varient */
4533 if (strcmp(str1
,"zzh") != 0) {
4536 if (strcmp(str2
,"") != 0) {
4541 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4545 SSVALS(*rparam
,0,0); /* errorcode */
4546 SSVAL(*rparam
,2,0); /* converter word */
4547 SSVAL(*rparam
,4,0x7f); /* permission flags */
4552 /****************************************************************************
4553 api_WPrintJobEnumerate
4554 ****************************************************************************/
4556 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4557 connection_struct
*conn
, uint16 vuid
,
4558 char *param
, int tpscnt
,
4559 char *data
, int tdscnt
,
4560 int mdrcnt
,int mprcnt
,
4561 char **rdata
,char **rparam
,
4562 int *rdata_len
,int *rparam_len
)
4564 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4565 char *str2
= skip_string(param
,tpscnt
,str1
);
4566 char *p
= skip_string(param
,tpscnt
,str2
);
4570 struct pack_desc desc
;
4573 TALLOC_CTX
*mem_ctx
= talloc_tos();
4576 struct rpc_pipe_client
*cli
= NULL
;
4577 struct policy_handle handle
;
4578 struct spoolss_DevmodeContainer devmode_ctr
;
4579 union spoolss_JobInfo info
;
4581 if (!str1
|| !str2
|| !p
) {
4585 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4587 memset((char *)&desc
,'\0',sizeof(desc
));
4588 memset((char *)&status
,'\0',sizeof(status
));
4590 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4592 /* check it's a supported varient */
4593 if (strcmp(str1
,"WWrLh") != 0) {
4596 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4600 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4604 ZERO_STRUCT(handle
);
4606 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4607 if (!NT_STATUS_IS_OK(status
)) {
4608 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4609 nt_errstr(status
)));
4610 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4614 ZERO_STRUCT(devmode_ctr
);
4616 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4623 if (!NT_STATUS_IS_OK(status
)) {
4624 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4627 if (!W_ERROR_IS_OK(werr
)) {
4628 desc
.errcode
= W_ERROR_V(werr
);
4632 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4638 if (!W_ERROR_IS_OK(werr
)) {
4639 desc
.errcode
= W_ERROR_V(werr
);
4644 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4649 desc
.buflen
= mdrcnt
;
4652 * Don't return data but need to get correct length
4653 * init_package will return wrong size if buflen=0
4655 desc
.buflen
= getlen(desc
.format
);
4656 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4659 if (init_package(&desc
,1,0)) {
4660 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4661 *rdata_len
= desc
.usedlen
;
4663 desc
.errcode
= NERR_JobNotFound
;
4667 if (cli
&& is_valid_policy_hnd(&handle
)) {
4668 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4672 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4676 SSVALS(*rparam
,0,desc
.errcode
);
4678 SSVAL(*rparam
,4,desc
.neededlen
);
4682 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4687 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4688 connection_struct
*conn
, uint16 vuid
,
4689 char *param
, int tpscnt
,
4690 char *data
, int tdscnt
,
4691 int mdrcnt
,int mprcnt
,
4692 char **rdata
,char **rparam
,
4693 int *rdata_len
,int *rparam_len
)
4695 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4696 char *str2
= skip_string(param
,tpscnt
,str1
);
4697 char *p
= skip_string(param
,tpscnt
,str2
);
4701 struct pack_desc desc
;
4703 TALLOC_CTX
*mem_ctx
= talloc_tos();
4706 struct rpc_pipe_client
*cli
= NULL
;
4707 struct policy_handle handle
;
4708 struct spoolss_DevmodeContainer devmode_ctr
;
4710 union spoolss_JobInfo
*info
;
4712 if (!str1
|| !str2
|| !p
) {
4716 memset((char *)&desc
,'\0',sizeof(desc
));
4718 p
= skip_string(param
,tpscnt
,p
);
4722 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4724 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4726 /* check it's a supported variant */
4727 if (strcmp(str1
,"zWrLeh") != 0) {
4732 return False
; /* defined only for uLevel 0,1,2 */
4735 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4739 ZERO_STRUCT(handle
);
4741 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4742 if (!NT_STATUS_IS_OK(status
)) {
4743 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4744 nt_errstr(status
)));
4745 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4749 ZERO_STRUCT(devmode_ctr
);
4751 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4755 SEC_FLAG_MAXIMUM_ALLOWED
,
4758 if (!NT_STATUS_IS_OK(status
)) {
4759 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4762 if (!W_ERROR_IS_OK(werr
)) {
4763 desc
.errcode
= W_ERROR_V(werr
);
4767 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4775 if (!W_ERROR_IS_OK(werr
)) {
4776 desc
.errcode
= W_ERROR_V(werr
);
4781 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4787 desc
.buflen
= mdrcnt
;
4789 if (init_package(&desc
,count
,0)) {
4791 for (i
= 0; i
< count
; i
++) {
4792 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4793 if (desc
.errcode
== NERR_Success
) {
4799 if (cli
&& is_valid_policy_hnd(&handle
)) {
4800 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4803 *rdata_len
= desc
.usedlen
;
4806 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4810 SSVALS(*rparam
,0,desc
.errcode
);
4812 SSVAL(*rparam
,4,succnt
);
4813 SSVAL(*rparam
,6,count
);
4815 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4820 static int check_printdest_info(struct pack_desc
* desc
,
4821 int uLevel
, char* id
)
4823 desc
->subformat
= NULL
;
4826 desc
->format
= "B9";
4829 desc
->format
= "B9B21WWzW";
4835 desc
->format
= "zzzWWzzzWW";
4838 DEBUG(0,("check_printdest_info: invalid level %d\n",
4842 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4843 DEBUG(0,("check_printdest_info: invalid string %s\n",
4844 id
? id
: "<NULL>" ));
4850 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4851 struct pack_desc
* desc
)
4855 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4856 buf
[sizeof(buf
)-1] = 0;
4860 PACKS(desc
,"B9",buf
); /* szName */
4862 PACKS(desc
,"B21",""); /* szUserName */
4863 PACKI(desc
,"W",0); /* uJobId */
4864 PACKI(desc
,"W",0); /* fsStatus */
4865 PACKS(desc
,"z",""); /* pszStatus */
4866 PACKI(desc
,"W",0); /* time */
4870 if (uLevel
== 2 || uLevel
== 3) {
4871 PACKS(desc
,"z",buf
); /* pszPrinterName */
4873 PACKS(desc
,"z",""); /* pszUserName */
4874 PACKS(desc
,"z",""); /* pszLogAddr */
4875 PACKI(desc
,"W",0); /* uJobId */
4876 PACKI(desc
,"W",0); /* fsStatus */
4877 PACKS(desc
,"z",""); /* pszStatus */
4878 PACKS(desc
,"z",""); /* pszComment */
4879 PACKS(desc
,"z","NULL"); /* pszDrivers */
4880 PACKI(desc
,"W",0); /* time */
4881 PACKI(desc
,"W",0); /* pad1 */
4886 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4887 connection_struct
*conn
, uint16 vuid
,
4888 char *param
, int tpscnt
,
4889 char *data
, int tdscnt
,
4890 int mdrcnt
,int mprcnt
,
4891 char **rdata
,char **rparam
,
4892 int *rdata_len
,int *rparam_len
)
4894 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4895 char *str2
= skip_string(param
,tpscnt
,str1
);
4896 char *p
= skip_string(param
,tpscnt
,str2
);
4897 char* PrinterName
= p
;
4899 struct pack_desc desc
;
4902 TALLOC_CTX
*mem_ctx
= talloc_tos();
4905 struct rpc_pipe_client
*cli
= NULL
;
4906 struct policy_handle handle
;
4907 struct spoolss_DevmodeContainer devmode_ctr
;
4908 union spoolss_PrinterInfo info
;
4910 if (!str1
|| !str2
|| !p
) {
4914 memset((char *)&desc
,'\0',sizeof(desc
));
4916 p
= skip_string(param
,tpscnt
,p
);
4920 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4922 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4924 /* check it's a supported varient */
4925 if (strcmp(str1
,"zWrLh") != 0) {
4928 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4932 ZERO_STRUCT(handle
);
4934 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4935 if (!NT_STATUS_IS_OK(status
)) {
4936 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4937 nt_errstr(status
)));
4938 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4942 ZERO_STRUCT(devmode_ctr
);
4944 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4948 SEC_FLAG_MAXIMUM_ALLOWED
,
4951 if (!NT_STATUS_IS_OK(status
)) {
4953 desc
.errcode
= NERR_DestNotFound
;
4957 if (!W_ERROR_IS_OK(werr
)) {
4959 desc
.errcode
= NERR_DestNotFound
;
4964 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4969 if (!W_ERROR_IS_OK(werr
)) {
4971 desc
.errcode
= NERR_DestNotFound
;
4977 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4982 desc
.buflen
= mdrcnt
;
4985 * Don't return data but need to get correct length
4986 * init_package will return wrong size if buflen=0
4988 desc
.buflen
= getlen(desc
.format
);
4989 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4991 if (init_package(&desc
,1,0)) {
4992 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
4996 if (cli
&& is_valid_policy_hnd(&handle
)) {
4997 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
5000 *rdata_len
= desc
.usedlen
;
5003 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5007 SSVALS(*rparam
,0,desc
.errcode
);
5009 SSVAL(*rparam
,4,desc
.neededlen
);
5011 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5017 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5018 connection_struct
*conn
, uint16 vuid
,
5019 char *param
, int tpscnt
,
5020 char *data
, int tdscnt
,
5021 int mdrcnt
,int mprcnt
,
5022 char **rdata
,char **rparam
,
5023 int *rdata_len
,int *rparam_len
)
5025 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5026 char *str2
= skip_string(param
,tpscnt
,str1
);
5027 char *p
= skip_string(param
,tpscnt
,str2
);
5031 struct pack_desc desc
;
5033 TALLOC_CTX
*mem_ctx
= talloc_tos();
5036 struct rpc_pipe_client
*cli
= NULL
;
5037 union spoolss_PrinterInfo
*info
;
5040 if (!str1
|| !str2
|| !p
) {
5044 memset((char *)&desc
,'\0',sizeof(desc
));
5046 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5048 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5050 /* check it's a supported varient */
5051 if (strcmp(str1
,"WrLeh") != 0) {
5054 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5060 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
5061 if (!NT_STATUS_IS_OK(status
)) {
5062 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5063 nt_errstr(status
)));
5064 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5068 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5070 cli
->srv_name_slash
,
5075 if (!W_ERROR_IS_OK(werr
)) {
5076 desc
.errcode
= W_ERROR_V(werr
);
5078 desc
.errcode
= NERR_DestNotFound
;
5086 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5093 desc
.buflen
= mdrcnt
;
5094 if (init_package(&desc
,queuecnt
,0)) {
5097 for (i
= 0; i
< count
; i
++) {
5098 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5100 if (desc
.errcode
== NERR_Success
) {
5106 *rdata_len
= desc
.usedlen
;
5109 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5113 SSVALS(*rparam
,0,desc
.errcode
);
5115 SSVAL(*rparam
,4,succnt
);
5116 SSVAL(*rparam
,6,queuecnt
);
5118 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5123 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5124 connection_struct
*conn
, uint16 vuid
,
5125 char *param
, int tpscnt
,
5126 char *data
, int tdscnt
,
5127 int mdrcnt
,int mprcnt
,
5128 char **rdata
,char **rparam
,
5129 int *rdata_len
,int *rparam_len
)
5131 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5132 char *str2
= skip_string(param
,tpscnt
,str1
);
5133 char *p
= skip_string(param
,tpscnt
,str2
);
5136 struct pack_desc desc
;
5138 if (!str1
|| !str2
|| !p
) {
5142 memset((char *)&desc
,'\0',sizeof(desc
));
5144 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5146 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5148 /* check it's a supported varient */
5149 if (strcmp(str1
,"WrLeh") != 0) {
5152 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5157 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5163 desc
.buflen
= mdrcnt
;
5164 if (init_package(&desc
,1,0)) {
5165 PACKS(&desc
,"B41","NULL");
5168 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5170 *rdata_len
= desc
.usedlen
;
5173 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5177 SSVALS(*rparam
,0,desc
.errcode
);
5179 SSVAL(*rparam
,4,succnt
);
5182 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5187 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5188 connection_struct
*conn
, uint16 vuid
,
5189 char *param
, int tpscnt
,
5190 char *data
, int tdscnt
,
5191 int mdrcnt
,int mprcnt
,
5192 char **rdata
,char **rparam
,
5193 int *rdata_len
,int *rparam_len
)
5195 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5196 char *str2
= skip_string(param
,tpscnt
,str1
);
5197 char *p
= skip_string(param
,tpscnt
,str2
);
5200 struct pack_desc desc
;
5202 if (!str1
|| !str2
|| !p
) {
5205 memset((char *)&desc
,'\0',sizeof(desc
));
5207 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5209 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5211 /* check it's a supported varient */
5212 if (strcmp(str1
,"WrLeh") != 0) {
5215 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5220 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5226 desc
.buflen
= mdrcnt
;
5228 if (init_package(&desc
,1,0)) {
5229 PACKS(&desc
,"B13","lpd");
5232 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5234 *rdata_len
= desc
.usedlen
;
5237 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5241 SSVALS(*rparam
,0,desc
.errcode
);
5243 SSVAL(*rparam
,4,succnt
);
5246 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5251 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5252 connection_struct
*conn
, uint16 vuid
,
5253 char *param
, int tpscnt
,
5254 char *data
, int tdscnt
,
5255 int mdrcnt
,int mprcnt
,
5256 char **rdata
,char **rparam
,
5257 int *rdata_len
,int *rparam_len
)
5259 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5260 char *str2
= skip_string(param
,tpscnt
,str1
);
5261 char *p
= skip_string(param
,tpscnt
,str2
);
5264 struct pack_desc desc
;
5266 if (!str1
|| !str2
|| !p
) {
5270 memset((char *)&desc
,'\0',sizeof(desc
));
5272 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5274 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5276 /* check it's a supported varient */
5277 if (strcmp(str1
,"WrLeh") != 0) {
5280 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5285 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5290 memset((char *)&desc
,'\0',sizeof(desc
));
5292 desc
.buflen
= mdrcnt
;
5294 if (init_package(&desc
,1,0)) {
5295 PACKS(&desc
,"B13","lp0");
5298 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5300 *rdata_len
= desc
.usedlen
;
5303 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5307 SSVALS(*rparam
,0,desc
.errcode
);
5309 SSVAL(*rparam
,4,succnt
);
5312 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5317 /****************************************************************************
5319 ****************************************************************************/
5321 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5322 connection_struct
*conn
, uint16 vuid
,
5323 char *param
, int tpscnt
,
5324 char *data
, int tdscnt
,
5325 int mdrcnt
,int mprcnt
,
5326 char **rdata
,char **rparam
,
5327 int *rdata_len
,int *rparam_len
)
5330 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5331 char *str2
= skip_string(param
,tpscnt
,str1
);
5332 char *p
= skip_string(param
,tpscnt
,str2
);
5334 struct pack_desc desc
;
5335 struct sessionid
*session_list
;
5336 int i
, num_sessions
;
5338 if (!str1
|| !str2
|| !p
) {
5342 memset((char *)&desc
,'\0',sizeof(desc
));
5344 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5346 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5347 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5348 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5350 /* check it's a supported varient */
5351 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5354 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5358 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5361 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5366 memset((char *)&desc
,'\0',sizeof(desc
));
5368 desc
.buflen
= mdrcnt
;
5370 if (!init_package(&desc
,num_sessions
,0)) {
5374 for(i
=0; i
<num_sessions
; i
++) {
5375 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5376 PACKS(&desc
, "z", session_list
[i
].username
);
5377 PACKI(&desc
, "W", 1); /* num conns */
5378 PACKI(&desc
, "W", 0); /* num opens */
5379 PACKI(&desc
, "W", 1); /* num users */
5380 PACKI(&desc
, "D", 0); /* session time */
5381 PACKI(&desc
, "D", 0); /* idle time */
5382 PACKI(&desc
, "D", 0); /* flags */
5383 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5386 *rdata_len
= desc
.usedlen
;
5389 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5393 SSVALS(*rparam
,0,desc
.errcode
);
5394 SSVAL(*rparam
,2,0); /* converter */
5395 SSVAL(*rparam
,4,num_sessions
); /* count */
5397 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5403 /****************************************************************************
5404 The buffer was too small.
5405 ****************************************************************************/
5407 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5408 connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5409 int mdrcnt
, int mprcnt
,
5410 char **rdata
, char **rparam
,
5411 int *rdata_len
, int *rparam_len
)
5413 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5414 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5421 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5423 DEBUG(3,("Supplied buffer too small in API command\n"));
5428 /****************************************************************************
5429 The request is not supported.
5430 ****************************************************************************/
5432 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5433 connection_struct
*conn
, uint16 vuid
,
5434 char *param
, int tpscnt
,
5435 char *data
, int tdscnt
,
5436 int mdrcnt
, int mprcnt
,
5437 char **rdata
, char **rparam
,
5438 int *rdata_len
, int *rparam_len
)
5441 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5448 SSVAL(*rparam
,0,NERR_notsupported
);
5449 SSVAL(*rparam
,2,0); /* converter word */
5451 DEBUG(3,("Unsupported API command\n"));
5456 static const struct {
5459 bool (*fn
)(struct smbd_server_connection
*sconn
,
5460 connection_struct
*, uint16
,
5463 int,int,char **,char **,int *,int *);
5464 bool auth_user
; /* Deny anonymous access? */
5465 } api_commands
[] = {
5466 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5467 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5468 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5469 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5470 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5471 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5472 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5473 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5474 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5475 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5476 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5477 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5478 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5479 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5480 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5481 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5482 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5483 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5484 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5485 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5486 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5487 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5488 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5489 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5490 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5491 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5492 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5493 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5494 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5495 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5496 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5497 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5498 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5499 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5500 {NULL
, -1, api_Unsupported
}
5501 /* The following RAP calls are not implemented by Samba:
5503 RAP_WFileEnum2 - anon not OK
5508 /****************************************************************************
5509 Handle remote api calls.
5510 ****************************************************************************/
5512 void api_reply(connection_struct
*conn
, uint16 vuid
,
5513 struct smb_request
*req
,
5514 char *data
, char *params
,
5515 int tdscnt
, int tpscnt
,
5516 int mdrcnt
, int mprcnt
)
5520 char *rparam
= NULL
;
5521 const char *name1
= NULL
;
5522 const char *name2
= NULL
;
5529 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5530 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5535 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5538 api_command
= SVAL(params
,0);
5539 /* Is there a string at position params+2 ? */
5540 if (skip_string(params
,tpscnt
,params
+2)) {
5545 name2
= skip_string(params
,tpscnt
,params
+2);
5550 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5554 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5556 for (i
=0;api_commands
[i
].name
;i
++) {
5557 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5558 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5563 /* Check whether this api call can be done anonymously */
5565 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5566 user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5568 if (!user
|| user
->server_info
->guest
) {
5569 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5574 rdata
= (char *)SMB_MALLOC(1024);
5576 memset(rdata
,'\0',1024);
5579 rparam
= (char *)SMB_MALLOC(1024);
5581 memset(rparam
,'\0',1024);
5584 if(!rdata
|| !rparam
) {
5585 DEBUG(0,("api_reply: malloc fail !\n"));
5588 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5592 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5594 params
,tpscnt
, /* params + length */
5595 data
,tdscnt
, /* data + length */
5597 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5600 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5601 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5603 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5606 /* if we get False back then it's actually unsupported */
5608 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5610 tdscnt
,mdrcnt
,mprcnt
,
5611 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5614 /* If api_Unsupported returns false we can't return anything. */
5616 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5617 rdata
, rdata_len
, False
);