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
,
2239 conn
->sconn
->msg_ctx
,
2241 if (!NT_STATUS_IS_OK(status
)) {
2242 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2243 nt_errstr(status
)));
2244 res
= W_ERROR_V(ntstatus_to_werror(status
));
2248 info2
.name
= sharename
;
2249 info2
.type
= STYPE_DISKTREE
;
2250 info2
.comment
= comment
;
2251 info2
.permissions
= 0;
2252 info2
.max_users
= 0;
2253 info2
.current_users
= 0;
2254 info2
.path
= pathname
;
2255 info2
.password
= NULL
;
2257 info
.info2
= &info2
;
2259 status
= rpccli_srvsvc_NetShareAdd(cli
, mem_ctx
,
2260 cli
->srv_name_slash
,
2265 if (!NT_STATUS_IS_OK(status
)) {
2266 res
= W_ERROR_V(ntstatus_to_werror(status
));
2269 if (!W_ERROR_IS_OK(werr
)) {
2270 res
= W_ERROR_V(werr
);
2275 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2279 SSVAL(*rparam
,0,NERR_Success
);
2280 SSVAL(*rparam
,2,0); /* converter word */
2281 SSVAL(*rparam
,4,*rdata_len
);
2289 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2294 SSVAL(*rparam
,0,res
);
2299 /****************************************************************************
2300 view list of groups available
2301 ****************************************************************************/
2303 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2304 connection_struct
*conn
,uint16 vuid
,
2305 char *param
, int tpscnt
,
2306 char *data
, int tdscnt
,
2307 int mdrcnt
,int mprcnt
,
2308 char **rdata
,char **rparam
,
2309 int *rdata_len
,int *rparam_len
)
2313 int resume_context
, cli_buf_size
;
2314 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2315 char *str2
= skip_string(param
,tpscnt
,str1
);
2316 char *p
= skip_string(param
,tpscnt
,str2
);
2318 uint32_t num_groups
;
2319 uint32_t resume_handle
;
2320 struct rpc_pipe_client
*samr_pipe
;
2321 struct policy_handle samr_handle
, domain_handle
;
2324 if (!str1
|| !str2
|| !p
) {
2328 if (strcmp(str1
,"WrLeh") != 0) {
2333 * W-> resume context (number of users to skip)
2334 * r -> return parameter pointer to receive buffer
2335 * L -> length of receive buffer
2336 * e -> return parameter number of entries
2337 * h -> return parameter total number of users
2340 if (strcmp("B21",str2
) != 0) {
2344 status
= rpc_pipe_open_internal(
2345 talloc_tos(), &ndr_table_samr
.syntax_id
,
2346 conn
->server_info
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2347 if (!NT_STATUS_IS_OK(status
)) {
2348 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2349 nt_errstr(status
)));
2353 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2354 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2355 if (!NT_STATUS_IS_OK(status
)) {
2356 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2357 nt_errstr(status
)));
2361 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2362 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2363 get_global_sam_sid(), &domain_handle
);
2364 if (!NT_STATUS_IS_OK(status
)) {
2365 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2366 nt_errstr(status
)));
2367 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2371 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2372 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2373 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2374 "%d\n", resume_context
, cli_buf_size
));
2376 *rdata_len
= cli_buf_size
;
2377 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2384 errflags
= NERR_Success
;
2389 struct samr_SamArray
*sam_entries
;
2390 uint32_t num_entries
;
2392 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2397 if (!NT_STATUS_IS_OK(status
)) {
2398 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2399 "%s\n", nt_errstr(status
)));
2403 if (num_entries
== 0) {
2404 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2405 "no entries -- done\n"));
2409 for(i
=0; i
<num_entries
; i
++) {
2412 name
= sam_entries
->entries
[i
].name
.string
;
2414 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2415 /* set overflow error */
2416 DEBUG(3,("overflow on entry %d group %s\n", i
,
2422 /* truncate the name at 21 chars. */
2424 strlcpy(p
, name
, 21);
2425 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2427 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2432 if (errflags
!= NERR_Success
) {
2436 TALLOC_FREE(sam_entries
);
2439 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2440 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2442 *rdata_len
= PTR_DIFF(p
,*rdata
);
2445 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2449 SSVAL(*rparam
, 0, errflags
);
2450 SSVAL(*rparam
, 2, 0); /* converter word */
2451 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2452 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2457 /*******************************************************************
2458 Get groups that a user is a member of.
2459 ******************************************************************/
2461 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2462 connection_struct
*conn
,uint16 vuid
,
2463 char *param
, int tpscnt
,
2464 char *data
, int tdscnt
,
2465 int mdrcnt
,int mprcnt
,
2466 char **rdata
,char **rparam
,
2467 int *rdata_len
,int *rparam_len
)
2469 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2470 char *str2
= skip_string(param
,tpscnt
,str1
);
2471 char *UserName
= skip_string(param
,tpscnt
,str2
);
2472 char *p
= skip_string(param
,tpscnt
,UserName
);
2473 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2474 const char *level_string
;
2480 struct rpc_pipe_client
*samr_pipe
;
2481 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2482 struct lsa_String name
;
2483 struct lsa_Strings names
;
2484 struct samr_Ids type
, rid
;
2485 struct samr_RidWithAttributeArray
*rids
;
2488 if (!str1
|| !str2
|| !UserName
|| !p
) {
2493 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2498 /* check it's a supported varient */
2500 if ( strcmp(str1
,"zWrLeh") != 0 )
2505 level_string
= "B21";
2511 if (strcmp(level_string
,str2
) != 0)
2514 *rdata_len
= mdrcnt
+ 1024;
2515 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2520 SSVAL(*rparam
,0,NERR_Success
);
2521 SSVAL(*rparam
,2,0); /* converter word */
2524 endp
= *rdata
+ *rdata_len
;
2526 status
= rpc_pipe_open_internal(
2527 talloc_tos(), &ndr_table_samr
.syntax_id
,
2528 conn
->server_info
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2529 if (!NT_STATUS_IS_OK(status
)) {
2530 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2531 nt_errstr(status
)));
2535 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2536 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2537 if (!NT_STATUS_IS_OK(status
)) {
2538 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2539 nt_errstr(status
)));
2543 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2544 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2545 get_global_sam_sid(), &domain_handle
);
2546 if (!NT_STATUS_IS_OK(status
)) {
2547 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2548 nt_errstr(status
)));
2552 name
.string
= UserName
;
2554 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2555 &domain_handle
, 1, &name
,
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2559 nt_errstr(status
)));
2563 if (type
.ids
[0] != SID_NAME_USER
) {
2564 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2565 sid_type_lookup(type
.ids
[0])));
2569 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2571 SAMR_USER_ACCESS_GET_GROUPS
,
2572 rid
.ids
[0], &user_handle
);
2573 if (!NT_STATUS_IS_OK(status
)) {
2574 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2575 nt_errstr(status
)));
2579 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2580 &user_handle
, &rids
);
2581 if (!NT_STATUS_IS_OK(status
)) {
2582 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2583 nt_errstr(status
)));
2587 for (i
=0; i
<rids
->count
; i
++) {
2589 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2591 1, &rids
->rids
[i
].rid
,
2593 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2594 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2600 *rdata_len
= PTR_DIFF(p
,*rdata
);
2602 SSVAL(*rparam
,4,count
); /* is this right?? */
2603 SSVAL(*rparam
,6,count
); /* is this right?? */
2608 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2610 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2612 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2617 /*******************************************************************
2619 ******************************************************************/
2621 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2622 connection_struct
*conn
, uint16 vuid
,
2623 char *param
, int tpscnt
,
2624 char *data
, int tdscnt
,
2625 int mdrcnt
,int mprcnt
,
2626 char **rdata
,char **rparam
,
2627 int *rdata_len
,int *rparam_len
)
2632 int i
, resume_context
, cli_buf_size
;
2633 uint32_t resume_handle
;
2635 struct rpc_pipe_client
*samr_pipe
;
2636 struct policy_handle samr_handle
, domain_handle
;
2639 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2640 char *str2
= skip_string(param
,tpscnt
,str1
);
2641 char *p
= skip_string(param
,tpscnt
,str2
);
2644 if (!str1
|| !str2
|| !p
) {
2648 if (strcmp(str1
,"WrLeh") != 0)
2651 * W-> resume context (number of users to skip)
2652 * r -> return parameter pointer to receive buffer
2653 * L -> length of receive buffer
2654 * e -> return parameter number of entries
2655 * h -> return parameter total number of users
2658 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2659 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2660 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2661 resume_context
, cli_buf_size
));
2664 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2669 /* check it's a supported varient */
2670 if (strcmp("B21",str2
) != 0)
2673 *rdata_len
= cli_buf_size
;
2674 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2680 endp
= *rdata
+ *rdata_len
;
2682 status
= rpc_pipe_open_internal(
2683 talloc_tos(), &ndr_table_samr
.syntax_id
,
2684 conn
->server_info
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2685 if (!NT_STATUS_IS_OK(status
)) {
2686 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2687 nt_errstr(status
)));
2691 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2692 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2693 if (!NT_STATUS_IS_OK(status
)) {
2694 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2695 nt_errstr(status
)));
2699 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2700 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2701 get_global_sam_sid(), &domain_handle
);
2702 if (!NT_STATUS_IS_OK(status
)) {
2703 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2704 nt_errstr(status
)));
2705 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2709 errflags
=NERR_Success
;
2714 struct samr_SamArray
*sam_entries
;
2715 uint32_t num_entries
;
2717 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2723 if (!NT_STATUS_IS_OK(status
)) {
2724 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2725 "%s\n", nt_errstr(status
)));
2729 if (num_entries
== 0) {
2730 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2731 "no entries -- done\n"));
2735 for (i
=0; i
<num_entries
; i
++) {
2738 name
= sam_entries
->entries
[i
].name
.string
;
2740 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2741 &&(strlen(name
)<=21)) {
2742 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2743 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2744 "username %s\n",count_sent
,p
));
2748 /* set overflow error */
2749 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2750 "username %s\n",count_sent
,name
));
2756 if (errflags
!= NERR_Success
) {
2760 TALLOC_FREE(sam_entries
);
2763 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2764 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2766 *rdata_len
= PTR_DIFF(p
,*rdata
);
2768 SSVAL(*rparam
,0,errflags
);
2769 SSVAL(*rparam
,2,0); /* converter word */
2770 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2771 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2776 /****************************************************************************
2777 Get the time of day info.
2778 ****************************************************************************/
2780 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2781 connection_struct
*conn
,uint16 vuid
,
2782 char *param
, int tpscnt
,
2783 char *data
, int tdscnt
,
2784 int mdrcnt
,int mprcnt
,
2785 char **rdata
,char **rparam
,
2786 int *rdata_len
,int *rparam_len
)
2789 time_t unixdate
= time(NULL
);
2793 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2799 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2804 SSVAL(*rparam
,0,NERR_Success
);
2805 SSVAL(*rparam
,2,0); /* converter word */
2809 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2810 by NT in a "net time" operation,
2811 it seems to ignore the one below */
2813 /* the client expects to get localtime, not GMT, in this bit
2814 (I think, this needs testing) */
2815 t
= localtime(&unixdate
);
2820 SIVAL(p
,4,0); /* msecs ? */
2821 SCVAL(p
,8,t
->tm_hour
);
2822 SCVAL(p
,9,t
->tm_min
);
2823 SCVAL(p
,10,t
->tm_sec
);
2824 SCVAL(p
,11,0); /* hundredths of seconds */
2825 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2826 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2827 SCVAL(p
,16,t
->tm_mday
);
2828 SCVAL(p
,17,t
->tm_mon
+ 1);
2829 SSVAL(p
,18,1900+t
->tm_year
);
2830 SCVAL(p
,20,t
->tm_wday
);
2835 /****************************************************************************
2836 Set the user password.
2837 *****************************************************************************/
2839 static bool api_SetUserPassword(struct smbd_server_connection
*sconn
,
2840 connection_struct
*conn
,uint16 vuid
,
2841 char *param
, int tpscnt
,
2842 char *data
, int tdscnt
,
2843 int mdrcnt
,int mprcnt
,
2844 char **rdata
,char **rparam
,
2845 int *rdata_len
,int *rparam_len
)
2847 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2850 fstring pass1
,pass2
;
2851 TALLOC_CTX
*mem_ctx
= talloc_tos();
2853 struct rpc_pipe_client
*cli
= NULL
;
2854 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2855 struct lsa_String domain_name
;
2856 struct dom_sid2
*domain_sid
;
2857 struct lsa_String names
;
2858 struct samr_Ids rids
;
2859 struct samr_Ids types
;
2860 struct samr_Password old_lm_hash
;
2861 struct samr_Password new_lm_hash
;
2862 int errcode
= NERR_badpass
;
2867 /* Skip 2 strings. */
2868 p
= skip_string(param
,tpscnt
,np
);
2869 p
= skip_string(param
,tpscnt
,p
);
2875 /* Do we have a string ? */
2876 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2879 pull_ascii_fstring(user
,p
);
2881 p
= skip_string(param
,tpscnt
,p
);
2886 memset(pass1
,'\0',sizeof(pass1
));
2887 memset(pass2
,'\0',sizeof(pass2
));
2889 * We use 31 here not 32 as we're checking
2890 * the last byte we want to access is safe.
2892 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2896 memcpy(pass2
,p
+16,16);
2898 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
2899 if (encrypted
== -1) {
2900 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2904 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
2905 if (min_pwd_length
== -1) {
2906 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2911 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2918 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2919 user
, encrypted
, min_pwd_length
));
2921 ZERO_STRUCT(connect_handle
);
2922 ZERO_STRUCT(domain_handle
);
2923 ZERO_STRUCT(user_handle
);
2925 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
2927 conn
->sconn
->msg_ctx
,
2929 if (!NT_STATUS_IS_OK(status
)) {
2930 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2931 nt_errstr(status
)));
2932 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2936 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
2938 SAMR_ACCESS_CONNECT_TO_SERVER
|
2939 SAMR_ACCESS_ENUM_DOMAINS
|
2940 SAMR_ACCESS_LOOKUP_DOMAIN
,
2942 if (!NT_STATUS_IS_OK(status
)) {
2943 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2947 init_lsa_String(&domain_name
, get_global_sam_name());
2949 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
2953 if (!NT_STATUS_IS_OK(status
)) {
2954 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2958 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
2960 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2963 if (!NT_STATUS_IS_OK(status
)) {
2964 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2968 init_lsa_String(&names
, user
);
2970 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
2976 if (!NT_STATUS_IS_OK(status
)) {
2977 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2981 if (rids
.count
!= 1) {
2982 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
2985 if (rids
.count
!= types
.count
) {
2986 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2989 if (types
.ids
[0] != SID_NAME_USER
) {
2990 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2996 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
2998 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
3001 if (!NT_STATUS_IS_OK(status
)) {
3002 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3006 if (encrypted
== 0) {
3007 E_deshash(pass1
, old_lm_hash
.hash
);
3008 E_deshash(pass2
, new_lm_hash
.hash
);
3010 ZERO_STRUCT(old_lm_hash
);
3011 ZERO_STRUCT(new_lm_hash
);
3012 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
3013 memcpy(new_lm_hash
.hash
, pass1
, MIN(strlen(pass2
), 16));
3016 status
= rpccli_samr_ChangePasswordUser(cli
, mem_ctx
,
3018 true, /* lm_present */
3021 false, /* nt_present */
3022 NULL
, /* old_nt_crypted */
3023 NULL
, /* new_nt_crypted */
3024 false, /* cross1_present */
3025 NULL
, /* nt_cross */
3026 false, /* cross2_present */
3027 NULL
); /* lm_cross */
3028 if (!NT_STATUS_IS_OK(status
)) {
3029 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3033 errcode
= NERR_Success
;
3036 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
3037 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
3039 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
3040 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
3042 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
3043 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
3046 memset((char *)pass1
,'\0',sizeof(fstring
));
3047 memset((char *)pass2
,'\0',sizeof(fstring
));
3049 SSVAL(*rparam
,0,errcode
);
3050 SSVAL(*rparam
,2,0); /* converter word */
3054 /****************************************************************************
3055 Set the user password (SamOEM version - gets plaintext).
3056 ****************************************************************************/
3058 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
3059 connection_struct
*conn
,uint16 vuid
,
3060 char *param
, int tpscnt
,
3061 char *data
, int tdscnt
,
3062 int mdrcnt
,int mprcnt
,
3063 char **rdata
,char **rparam
,
3064 int *rdata_len
,int *rparam_len
)
3067 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3069 TALLOC_CTX
*mem_ctx
= talloc_tos();
3071 struct rpc_pipe_client
*cli
= NULL
;
3072 struct lsa_AsciiString server
, account
;
3073 struct samr_CryptPassword password
;
3074 struct samr_Password hash
;
3075 int errcode
= NERR_badpass
;
3079 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3089 SSVAL(*rparam
,0,NERR_badpass
);
3092 * Check the parameter definition is correct.
3095 /* Do we have a string ? */
3096 if (skip_string(param
,tpscnt
,p
) == 0) {
3099 if(!strequal(p
, "zsT")) {
3100 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3103 p
= skip_string(param
, tpscnt
, p
);
3108 /* Do we have a string ? */
3109 if (skip_string(param
,tpscnt
,p
) == 0) {
3112 if(!strequal(p
, "B516B16")) {
3113 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3116 p
= skip_string(param
,tpscnt
,p
);
3120 /* Do we have a string ? */
3121 if (skip_string(param
,tpscnt
,p
) == 0) {
3124 p
+= pull_ascii_fstring(user
,p
);
3126 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3128 if (tdscnt
!= 532) {
3129 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3133 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3134 if (bufsize
!= 532) {
3135 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3139 memcpy(password
.data
, data
, 516);
3140 memcpy(hash
.hash
, data
+516, 16);
3142 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3144 conn
->sconn
->msg_ctx
,
3146 if (!NT_STATUS_IS_OK(status
)) {
3147 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3148 nt_errstr(status
)));
3149 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3153 init_lsa_AsciiString(&server
, global_myname());
3154 init_lsa_AsciiString(&account
, user
);
3156 status
= rpccli_samr_OemChangePasswordUser2(cli
, mem_ctx
,
3161 if (!NT_STATUS_IS_OK(status
)) {
3162 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3166 errcode
= NERR_Success
;
3168 SSVAL(*rparam
,0,errcode
);
3169 SSVAL(*rparam
,2,0); /* converter word */
3174 /****************************************************************************
3177 ****************************************************************************/
3179 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3180 connection_struct
*conn
,uint16 vuid
,
3181 char *param
, int tpscnt
,
3182 char *data
, int tdscnt
,
3183 int mdrcnt
,int mprcnt
,
3184 char **rdata
,char **rparam
,
3185 int *rdata_len
,int *rparam_len
)
3187 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3188 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3189 char *str2
= skip_string(param
,tpscnt
,str1
);
3190 char *p
= skip_string(param
,tpscnt
,str2
);
3194 WERROR werr
= WERR_OK
;
3196 TALLOC_CTX
*mem_ctx
= talloc_tos();
3198 struct rpc_pipe_client
*cli
= NULL
;
3199 struct policy_handle handle
;
3200 struct spoolss_DevmodeContainer devmode_ctr
;
3201 enum spoolss_JobControl command
;
3203 if (!str1
|| !str2
|| !p
) {
3207 * We use 1 here not 2 as we're checking
3208 * the last byte we want to access is safe.
3210 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3213 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3216 /* check it's a supported varient */
3217 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3221 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3227 ZERO_STRUCT(handle
);
3229 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3230 if (!NT_STATUS_IS_OK(status
)) {
3231 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3232 nt_errstr(status
)));
3233 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3237 ZERO_STRUCT(devmode_ctr
);
3239 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3243 JOB_ACCESS_ADMINISTER
,
3246 if (!NT_STATUS_IS_OK(status
)) {
3247 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3250 if (!W_ERROR_IS_OK(werr
)) {
3251 errcode
= W_ERROR_V(werr
);
3255 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3256 * and NERR_DestNotFound if share did not exist */
3258 errcode
= NERR_Success
;
3261 case 81: /* delete */
3262 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3264 case 82: /* pause */
3265 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3267 case 83: /* resume */
3268 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3271 errcode
= NERR_notsupported
;
3275 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3278 NULL
, /* unique ptr ctr */
3281 if (!NT_STATUS_IS_OK(status
)) {
3282 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3285 if (!W_ERROR_IS_OK(werr
)) {
3286 errcode
= W_ERROR_V(werr
);
3291 if (cli
&& is_valid_policy_hnd(&handle
)) {
3292 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3295 SSVAL(*rparam
,0,errcode
);
3296 SSVAL(*rparam
,2,0); /* converter word */
3301 /****************************************************************************
3302 Purge a print queue - or pause or resume it.
3303 ****************************************************************************/
3305 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3306 connection_struct
*conn
,uint16 vuid
,
3307 char *param
, int tpscnt
,
3308 char *data
, int tdscnt
,
3309 int mdrcnt
,int mprcnt
,
3310 char **rdata
,char **rparam
,
3311 int *rdata_len
,int *rparam_len
)
3313 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3314 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3315 char *str2
= skip_string(param
,tpscnt
,str1
);
3316 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3317 int errcode
= NERR_notsupported
;
3318 WERROR werr
= WERR_OK
;
3321 TALLOC_CTX
*mem_ctx
= talloc_tos();
3322 struct rpc_pipe_client
*cli
= NULL
;
3323 struct policy_handle handle
;
3324 struct spoolss_SetPrinterInfoCtr info_ctr
;
3325 struct spoolss_DevmodeContainer devmode_ctr
;
3326 struct sec_desc_buf secdesc_ctr
;
3327 enum spoolss_PrinterControl command
;
3329 if (!str1
|| !str2
|| !QueueName
) {
3333 /* check it's a supported varient */
3334 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3338 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3344 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3348 ZERO_STRUCT(handle
);
3350 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3351 if (!NT_STATUS_IS_OK(status
)) {
3352 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3353 nt_errstr(status
)));
3354 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3358 ZERO_STRUCT(devmode_ctr
);
3360 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3364 SEC_FLAG_MAXIMUM_ALLOWED
,
3367 if (!NT_STATUS_IS_OK(status
)) {
3368 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3371 if (!W_ERROR_IS_OK(werr
)) {
3372 errcode
= W_ERROR_V(werr
);
3377 case 74: /* Pause queue */
3378 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3380 case 75: /* Resume queue */
3381 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3383 case 103: /* Purge */
3384 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3387 werr
= WERR_NOT_SUPPORTED
;
3391 if (!W_ERROR_IS_OK(werr
)) {
3392 errcode
= W_ERROR_V(werr
);
3396 ZERO_STRUCT(info_ctr
);
3397 ZERO_STRUCT(secdesc_ctr
);
3399 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3406 if (!NT_STATUS_IS_OK(status
)) {
3407 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3410 if (!W_ERROR_IS_OK(werr
)) {
3411 errcode
= W_ERROR_V(werr
);
3415 errcode
= W_ERROR_V(werr
);
3419 if (cli
&& is_valid_policy_hnd(&handle
)) {
3420 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3423 SSVAL(*rparam
,0,errcode
);
3424 SSVAL(*rparam
,2,0); /* converter word */
3429 /****************************************************************************
3430 set the property of a print job (undocumented?)
3431 ? function = 0xb -> set name of print job
3432 ? function = 0x6 -> move print job up/down
3433 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3434 or <WWsTP> <WB21BB16B10zWWzDDz>
3435 ****************************************************************************/
3437 static int check_printjob_info(struct pack_desc
* desc
,
3438 int uLevel
, char* id
)
3440 desc
->subformat
= NULL
;
3442 case 0: desc
->format
= "W"; break;
3443 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3444 case 2: desc
->format
= "WWzWWDDzz"; break;
3445 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3446 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3448 DEBUG(0,("check_printjob_info: invalid level %d\n",
3452 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3453 DEBUG(0,("check_printjob_info: invalid format %s\n",
3454 id
? id
: "<NULL>" ));
3460 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3461 connection_struct
*conn
, uint16 vuid
,
3462 char *param
, int tpscnt
,
3463 char *data
, int tdscnt
,
3464 int mdrcnt
,int mprcnt
,
3465 char **rdata
,char **rparam
,
3466 int *rdata_len
,int *rparam_len
)
3468 struct pack_desc desc
;
3469 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3470 char *str2
= skip_string(param
,tpscnt
,str1
);
3471 char *p
= skip_string(param
,tpscnt
,str2
);
3474 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3475 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3478 TALLOC_CTX
*mem_ctx
= talloc_tos();
3481 struct rpc_pipe_client
*cli
= NULL
;
3482 struct policy_handle handle
;
3483 struct spoolss_DevmodeContainer devmode_ctr
;
3484 struct spoolss_JobInfoContainer ctr
;
3485 union spoolss_JobInfo info
;
3486 struct spoolss_SetJobInfo1 info1
;
3488 if (!str1
|| !str2
|| !p
) {
3492 * We use 1 here not 2 as we're checking
3493 * the last byte we want to access is safe.
3495 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3498 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3501 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3508 /* check it's a supported varient */
3509 if ((strcmp(str1
,"WWsTP")) ||
3510 (!check_printjob_info(&desc
,uLevel
,str2
)))
3513 errcode
= NERR_notsupported
;
3517 /* change print job name, data gives the name */
3523 ZERO_STRUCT(handle
);
3525 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3526 if (!NT_STATUS_IS_OK(status
)) {
3527 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3528 nt_errstr(status
)));
3529 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3533 ZERO_STRUCT(devmode_ctr
);
3535 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3542 if (!NT_STATUS_IS_OK(status
)) {
3543 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3546 if (!W_ERROR_IS_OK(werr
)) {
3547 errcode
= W_ERROR_V(werr
);
3551 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3557 if (!W_ERROR_IS_OK(werr
)) {
3558 errcode
= W_ERROR_V(werr
);
3564 info1
.job_id
= info
.info1
.job_id
;
3565 info1
.printer_name
= info
.info1
.printer_name
;
3566 info1
.user_name
= info
.info1
.user_name
;
3567 info1
.document_name
= data
;
3568 info1
.data_type
= info
.info1
.data_type
;
3569 info1
.text_status
= info
.info1
.text_status
;
3570 info1
.status
= info
.info1
.status
;
3571 info1
.priority
= info
.info1
.priority
;
3572 info1
.position
= info
.info1
.position
;
3573 info1
.total_pages
= info
.info1
.total_pages
;
3574 info1
.pages_printed
= info
.info1
.pages_printed
;
3575 info1
.submitted
= info
.info1
.submitted
;
3578 ctr
.info
.info1
= &info1
;
3580 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3586 if (!NT_STATUS_IS_OK(status
)) {
3587 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3590 if (!W_ERROR_IS_OK(werr
)) {
3591 errcode
= W_ERROR_V(werr
);
3595 errcode
= NERR_Success
;
3598 if (cli
&& is_valid_policy_hnd(&handle
)) {
3599 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3602 SSVALS(*rparam
,0,errcode
);
3603 SSVAL(*rparam
,2,0); /* converter word */
3609 /****************************************************************************
3610 Get info about the server.
3611 ****************************************************************************/
3613 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3614 connection_struct
*conn
,uint16 vuid
,
3615 char *param
, int tpscnt
,
3616 char *data
, int tdscnt
,
3617 int mdrcnt
,int mprcnt
,
3618 char **rdata
,char **rparam
,
3619 int *rdata_len
,int *rparam_len
)
3621 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3622 char *str2
= skip_string(param
,tpscnt
,str1
);
3623 char *p
= skip_string(param
,tpscnt
,str2
);
3624 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3630 TALLOC_CTX
*mem_ctx
= talloc_tos();
3631 struct rpc_pipe_client
*cli
= NULL
;
3632 union srvsvc_NetSrvInfo info
;
3635 if (!str1
|| !str2
|| !p
) {
3639 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3641 /* check it's a supported varient */
3642 if (!prefix_ok(str1
,"WrLh")) {
3648 if (strcmp(str2
,"B16") != 0) {
3654 if (strcmp(str2
,"B16BBDz") != 0) {
3660 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3666 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3672 if (strcmp(str2
,"DN") != 0) {
3678 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3687 *rdata_len
= mdrcnt
;
3688 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3694 p2
= p
+ struct_len
;
3696 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3698 conn
->sconn
->msg_ctx
,
3700 if (!NT_STATUS_IS_OK(status
)) {
3701 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3702 nt_errstr(status
)));
3703 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3707 status
= rpccli_srvsvc_NetSrvGetInfo(cli
, mem_ctx
,
3712 if (!NT_STATUS_IS_OK(status
)) {
3713 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3716 if (!W_ERROR_IS_OK(werr
)) {
3717 errcode
= W_ERROR_V(werr
);
3721 if (info
.info101
== NULL
) {
3722 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3727 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3728 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3732 SCVAL(p
,0,info
.info101
->version_major
);
3733 SCVAL(p
,1,info
.info101
->version_minor
);
3734 SIVAL(p
,2,info
.info101
->server_type
);
3736 if (mdrcnt
== struct_len
) {
3739 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3740 if (mdrcnt
- struct_len
<= 0) {
3744 info
.info101
->comment
,
3745 MIN(mdrcnt
- struct_len
,
3746 MAX_SERVER_STRING_LENGTH
),
3748 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3756 return False
; /* not yet implemented */
3759 errcode
= NERR_Success
;
3763 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3766 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3770 SSVAL(*rparam
,0,errcode
);
3771 SSVAL(*rparam
,2,0); /* converter word */
3772 SSVAL(*rparam
,4,*rdata_len
);
3777 /****************************************************************************
3778 Get info about the server.
3779 ****************************************************************************/
3781 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3782 connection_struct
*conn
,uint16 vuid
,
3783 char *param
, int tpscnt
,
3784 char *data
, int tdscnt
,
3785 int mdrcnt
,int mprcnt
,
3786 char **rdata
,char **rparam
,
3787 int *rdata_len
,int *rparam_len
)
3789 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3790 char *str2
= skip_string(param
,tpscnt
,str1
);
3791 char *p
= skip_string(param
,tpscnt
,str2
);
3794 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3796 if (!str1
|| !str2
|| !p
) {
3800 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3803 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3808 /* check it's a supported varient */
3809 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3813 *rdata_len
= mdrcnt
+ 1024;
3814 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3819 SSVAL(*rparam
,0,NERR_Success
);
3820 SSVAL(*rparam
,2,0); /* converter word */
3823 endp
= *rdata
+ *rdata_len
;
3825 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3830 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3831 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3833 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3839 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3840 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3841 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3847 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3848 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3850 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3856 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3857 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3860 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3861 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3862 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3868 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3869 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3870 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3876 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3878 SSVAL(*rparam
,4,*rdata_len
);
3883 /****************************************************************************
3884 get info about a user
3886 struct user_info_11 {
3887 char usri11_name[21]; 0-20
3889 char *usri11_comment; 22-25
3890 char *usri11_usr_comment; 26-29
3891 unsigned short usri11_priv; 30-31
3892 unsigned long usri11_auth_flags; 32-35
3893 long usri11_password_age; 36-39
3894 char *usri11_homedir; 40-43
3895 char *usri11_parms; 44-47
3896 long usri11_last_logon; 48-51
3897 long usri11_last_logoff; 52-55
3898 unsigned short usri11_bad_pw_count; 56-57
3899 unsigned short usri11_num_logons; 58-59
3900 char *usri11_logon_server; 60-63
3901 unsigned short usri11_country_code; 64-65
3902 char *usri11_workstations; 66-69
3903 unsigned long usri11_max_storage; 70-73
3904 unsigned short usri11_units_per_week; 74-75
3905 unsigned char *usri11_logon_hours; 76-79
3906 unsigned short usri11_code_page; 80-81
3911 usri11_name specifies the user name for which information is retrieved
3913 usri11_pad aligns the next data structure element to a word boundary
3915 usri11_comment is a null terminated ASCII comment
3917 usri11_user_comment is a null terminated ASCII comment about the user
3919 usri11_priv specifies the level of the privilege assigned to the user.
3920 The possible values are:
3922 Name Value Description
3923 USER_PRIV_GUEST 0 Guest privilege
3924 USER_PRIV_USER 1 User privilege
3925 USER_PRV_ADMIN 2 Administrator privilege
3927 usri11_auth_flags specifies the account operator privileges. The
3928 possible values are:
3930 Name Value Description
3931 AF_OP_PRINT 0 Print operator
3934 Leach, Naik [Page 28]
3938 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3941 AF_OP_COMM 1 Communications operator
3942 AF_OP_SERVER 2 Server operator
3943 AF_OP_ACCOUNTS 3 Accounts operator
3946 usri11_password_age specifies how many seconds have elapsed since the
3947 password was last changed.
3949 usri11_home_dir points to a null terminated ASCII string that contains
3950 the path name of the user's home directory.
3952 usri11_parms points to a null terminated ASCII string that is set
3953 aside for use by applications.
3955 usri11_last_logon specifies the time when the user last logged on.
3956 This value is stored as the number of seconds elapsed since
3957 00:00:00, January 1, 1970.
3959 usri11_last_logoff specifies the time when the user last logged off.
3960 This value is stored as the number of seconds elapsed since
3961 00:00:00, January 1, 1970. A value of 0 means the last logoff
3964 usri11_bad_pw_count specifies the number of incorrect passwords
3965 entered since the last successful logon.
3967 usri11_log1_num_logons specifies the number of times this user has
3968 logged on. A value of -1 means the number of logons is unknown.
3970 usri11_logon_server points to a null terminated ASCII string that
3971 contains the name of the server to which logon requests are sent.
3972 A null string indicates logon requests should be sent to the
3975 usri11_country_code specifies the country code for the user's language
3978 usri11_workstations points to a null terminated ASCII string that
3979 contains the names of workstations the user may log on from.
3980 There may be up to 8 workstations, with the names separated by
3981 commas. A null strings indicates there are no restrictions.
3983 usri11_max_storage specifies the maximum amount of disk space the user
3984 can occupy. A value of 0xffffffff indicates there are no
3987 usri11_units_per_week specifies the equal number of time units into
3988 which a week is divided. This value must be equal to 168.
3990 usri11_logon_hours points to a 21 byte (168 bits) string that
3991 specifies the time during which the user can log on. Each bit
3992 represents one unique hour in a week. The first bit (bit 0, word
3993 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3997 Leach, Naik [Page 29]
4001 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4004 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4005 are no restrictions.
4007 usri11_code_page specifies the code page for the user's language of
4010 All of the pointers in this data structure need to be treated
4011 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4012 to be ignored. The converter word returned in the parameters section
4013 needs to be subtracted from the lower 16 bits to calculate an offset
4014 into the return buffer where this ASCII string resides.
4016 There is no auxiliary data in the response.
4018 ****************************************************************************/
4020 #define usri11_name 0
4021 #define usri11_pad 21
4022 #define usri11_comment 22
4023 #define usri11_usr_comment 26
4024 #define usri11_full_name 30
4025 #define usri11_priv 34
4026 #define usri11_auth_flags 36
4027 #define usri11_password_age 40
4028 #define usri11_homedir 44
4029 #define usri11_parms 48
4030 #define usri11_last_logon 52
4031 #define usri11_last_logoff 56
4032 #define usri11_bad_pw_count 60
4033 #define usri11_num_logons 62
4034 #define usri11_logon_server 64
4035 #define usri11_country_code 68
4036 #define usri11_workstations 70
4037 #define usri11_max_storage 74
4038 #define usri11_units_per_week 78
4039 #define usri11_logon_hours 80
4040 #define usri11_code_page 84
4041 #define usri11_end 86
4043 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4044 connection_struct
*conn
, uint16 vuid
,
4045 char *param
, int tpscnt
,
4046 char *data
, int tdscnt
,
4047 int mdrcnt
,int mprcnt
,
4048 char **rdata
,char **rparam
,
4049 int *rdata_len
,int *rparam_len
)
4051 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4052 char *str2
= skip_string(param
,tpscnt
,str1
);
4053 char *UserName
= skip_string(param
,tpscnt
,str2
);
4054 char *p
= skip_string(param
,tpscnt
,UserName
);
4055 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4058 const char *level_string
;
4060 TALLOC_CTX
*mem_ctx
= talloc_tos();
4062 struct rpc_pipe_client
*cli
= NULL
;
4063 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4064 struct lsa_String domain_name
;
4065 struct dom_sid2
*domain_sid
;
4066 struct lsa_String names
;
4067 struct samr_Ids rids
;
4068 struct samr_Ids types
;
4069 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4071 union samr_UserInfo
*info
;
4073 if (!str1
|| !str2
|| !UserName
|| !p
) {
4078 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4083 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4085 /* check it's a supported variant */
4086 if (strcmp(str1
,"zWrLh") != 0) {
4090 case 0: level_string
= "B21"; break;
4091 case 1: level_string
= "B21BB16DWzzWz"; break;
4092 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4093 case 10: level_string
= "B21Bzzz"; break;
4094 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4095 default: return False
;
4098 if (strcmp(level_string
,str2
) != 0) {
4102 *rdata_len
= mdrcnt
+ 1024;
4103 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4109 endp
= *rdata
+ *rdata_len
;
4110 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4115 ZERO_STRUCT(connect_handle
);
4116 ZERO_STRUCT(domain_handle
);
4117 ZERO_STRUCT(user_handle
);
4119 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
4121 conn
->sconn
->msg_ctx
,
4123 if (!NT_STATUS_IS_OK(status
)) {
4124 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4125 nt_errstr(status
)));
4126 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4130 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
4132 SAMR_ACCESS_CONNECT_TO_SERVER
|
4133 SAMR_ACCESS_ENUM_DOMAINS
|
4134 SAMR_ACCESS_LOOKUP_DOMAIN
,
4136 if (!NT_STATUS_IS_OK(status
)) {
4137 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4141 init_lsa_String(&domain_name
, get_global_sam_name());
4143 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
4147 if (!NT_STATUS_IS_OK(status
)) {
4148 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4152 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
4154 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4157 if (!NT_STATUS_IS_OK(status
)) {
4158 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4162 init_lsa_String(&names
, UserName
);
4164 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
4170 if (!NT_STATUS_IS_OK(status
)) {
4171 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4175 if (rids
.count
!= 1) {
4176 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4179 if (rids
.count
!= types
.count
) {
4180 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4183 if (types
.ids
[0] != SID_NAME_USER
) {
4184 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4190 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
4192 SAMR_USER_ACCESS_GET_LOCALE
|
4193 SAMR_USER_ACCESS_GET_LOGONINFO
|
4194 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4195 SAMR_USER_ACCESS_GET_GROUPS
|
4196 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4197 SEC_STD_READ_CONTROL
,
4200 if (!NT_STATUS_IS_OK(status
)) {
4201 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4205 status
= rpccli_samr_QueryUserInfo2(cli
, mem_ctx
,
4209 if (!NT_STATUS_IS_OK(status
)) {
4210 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4215 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4218 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4223 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4224 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4225 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4230 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4231 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4232 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4237 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4238 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4239 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4240 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4247 const char *homedir
= info
->info21
.home_directory
.string
;
4248 /* modelled after NTAS 3.51 reply */
4249 SSVAL(p
,usri11_priv
,
4250 (get_current_uid(conn
) == sec_initial_uid())?
4251 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4252 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4253 SIVALS(p
,usri11_password_age
,-1); /* password age */
4254 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4255 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4256 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4260 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4261 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4262 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4266 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4267 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4268 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4269 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4270 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4271 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4272 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4276 SSVAL(p
,usri11_country_code
,0); /* country code */
4278 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4279 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4280 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4285 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4286 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4287 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4289 /* a simple way to get logon hours at all times. */
4291 SCVAL(p2
,21,0); /* fix zero termination */
4292 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4297 SSVAL(p
,usri11_code_page
,0); /* code page */
4300 if (uLevel
== 1 || uLevel
== 2) {
4301 memset(p
+22,' ',16); /* password */
4302 SIVALS(p
,38,-1); /* password age */
4304 (get_current_uid(conn
) == sec_initial_uid())?
4305 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4306 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4307 strlcpy(p2
, info
->info21
.home_directory
.string
,
4309 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4313 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4315 SSVAL(p
,52,0); /* flags */
4316 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4317 strlcpy(p2
, info
->info21
.logon_script
.string
,
4319 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4324 SIVAL(p
,58,0); /* auth_flags */
4325 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4326 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4327 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4331 SIVAL(p
,66,0); /* urs_comment */
4332 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4333 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4334 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4338 SIVAL(p
,74,0); /* workstations */
4339 SIVAL(p
,78,0); /* last_logon */
4340 SIVAL(p
,82,0); /* last_logoff */
4341 SIVALS(p
,86,-1); /* acct_expires */
4342 SIVALS(p
,90,-1); /* max_storage */
4343 SSVAL(p
,94,168); /* units_per_week */
4344 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4347 SSVALS(p
,100,-1); /* bad_pw_count */
4348 SSVALS(p
,102,-1); /* num_logons */
4349 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4351 TALLOC_CTX
*ctx
= talloc_tos();
4352 int space_rem
= *rdata_len
- (p2
- *rdata
);
4355 if (space_rem
<= 0) {
4358 tmp
= talloc_strdup(ctx
, "\\\\%L");
4362 tmp
= talloc_sub_basic(ctx
,
4375 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4379 SSVAL(p
,108,49); /* country_code */
4380 SSVAL(p
,110,860); /* code page */
4384 errcode
= NERR_Success
;
4387 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4389 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
4390 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
4392 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
4393 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
4395 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
4396 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
4399 SSVAL(*rparam
,0,errcode
);
4400 SSVAL(*rparam
,2,0); /* converter word */
4401 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4406 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4407 connection_struct
*conn
,uint16 vuid
,
4408 char *param
, int tpscnt
,
4409 char *data
, int tdscnt
,
4410 int mdrcnt
,int mprcnt
,
4411 char **rdata
,char **rparam
,
4412 int *rdata_len
,int *rparam_len
)
4414 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4415 char *str2
= skip_string(param
,tpscnt
,str1
);
4416 char *p
= skip_string(param
,tpscnt
,str2
);
4418 struct pack_desc desc
;
4420 /* With share level security vuid will always be zero.
4421 Don't depend on vuser being non-null !!. JRA */
4422 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4424 if (!str1
|| !str2
|| !p
) {
4429 DEBUG(3,(" Username of UID %d is %s\n",
4430 (int)vuser
->server_info
->utok
.uid
,
4431 vuser
->server_info
->unix_name
));
4434 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4435 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4440 memset((char *)&desc
,'\0',sizeof(desc
));
4442 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4444 /* check it's a supported varient */
4445 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4448 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4452 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4459 desc
.buflen
= mdrcnt
;
4460 desc
.subformat
= NULL
;
4463 if (init_package(&desc
,1,0)) {
4464 PACKI(&desc
,"W",0); /* code */
4465 PACKS(&desc
,"B21",name
); /* eff. name */
4466 PACKS(&desc
,"B",""); /* pad */
4468 (get_current_uid(conn
) == sec_initial_uid())?
4469 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4470 PACKI(&desc
,"D",0); /* auth flags XXX */
4471 PACKI(&desc
,"W",0); /* num logons */
4472 PACKI(&desc
,"W",0); /* bad pw count */
4473 PACKI(&desc
,"D",0); /* last logon */
4474 PACKI(&desc
,"D",-1); /* last logoff */
4475 PACKI(&desc
,"D",-1); /* logoff time */
4476 PACKI(&desc
,"D",-1); /* kickoff time */
4477 PACKI(&desc
,"D",0); /* password age */
4478 PACKI(&desc
,"D",0); /* password can change */
4479 PACKI(&desc
,"D",-1); /* password must change */
4483 fstrcpy(mypath
,"\\\\");
4484 fstrcat(mypath
,get_local_machine_name());
4486 PACKS(&desc
,"z",mypath
); /* computer */
4489 PACKS(&desc
,"z",lp_workgroup());/* domain */
4490 PACKS(&desc
,"z", vuser
?
4491 vuser
->server_info
->info3
->base
.logon_script
.string
4492 : ""); /* script path */
4493 PACKI(&desc
,"D",0x00000000); /* reserved */
4496 *rdata_len
= desc
.usedlen
;
4498 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4502 SSVALS(*rparam
,0,desc
.errcode
);
4504 SSVAL(*rparam
,4,desc
.neededlen
);
4506 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4511 /****************************************************************************
4512 api_WAccessGetUserPerms
4513 ****************************************************************************/
4515 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4516 connection_struct
*conn
,uint16 vuid
,
4517 char *param
, int tpscnt
,
4518 char *data
, int tdscnt
,
4519 int mdrcnt
,int mprcnt
,
4520 char **rdata
,char **rparam
,
4521 int *rdata_len
,int *rparam_len
)
4523 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4524 char *str2
= skip_string(param
,tpscnt
,str1
);
4525 char *user
= skip_string(param
,tpscnt
,str2
);
4526 char *resource
= skip_string(param
,tpscnt
,user
);
4528 if (!str1
|| !str2
|| !user
|| !resource
) {
4532 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4535 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4537 /* check it's a supported varient */
4538 if (strcmp(str1
,"zzh") != 0) {
4541 if (strcmp(str2
,"") != 0) {
4546 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4550 SSVALS(*rparam
,0,0); /* errorcode */
4551 SSVAL(*rparam
,2,0); /* converter word */
4552 SSVAL(*rparam
,4,0x7f); /* permission flags */
4557 /****************************************************************************
4558 api_WPrintJobEnumerate
4559 ****************************************************************************/
4561 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4562 connection_struct
*conn
, uint16 vuid
,
4563 char *param
, int tpscnt
,
4564 char *data
, int tdscnt
,
4565 int mdrcnt
,int mprcnt
,
4566 char **rdata
,char **rparam
,
4567 int *rdata_len
,int *rparam_len
)
4569 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4570 char *str2
= skip_string(param
,tpscnt
,str1
);
4571 char *p
= skip_string(param
,tpscnt
,str2
);
4575 struct pack_desc desc
;
4578 TALLOC_CTX
*mem_ctx
= talloc_tos();
4581 struct rpc_pipe_client
*cli
= NULL
;
4582 struct policy_handle handle
;
4583 struct spoolss_DevmodeContainer devmode_ctr
;
4584 union spoolss_JobInfo info
;
4586 if (!str1
|| !str2
|| !p
) {
4590 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4592 memset((char *)&desc
,'\0',sizeof(desc
));
4593 memset((char *)&status
,'\0',sizeof(status
));
4595 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4597 /* check it's a supported varient */
4598 if (strcmp(str1
,"WWrLh") != 0) {
4601 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4605 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4609 ZERO_STRUCT(handle
);
4611 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4612 if (!NT_STATUS_IS_OK(status
)) {
4613 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4614 nt_errstr(status
)));
4615 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4619 ZERO_STRUCT(devmode_ctr
);
4621 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4628 if (!NT_STATUS_IS_OK(status
)) {
4629 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4632 if (!W_ERROR_IS_OK(werr
)) {
4633 desc
.errcode
= W_ERROR_V(werr
);
4637 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4643 if (!W_ERROR_IS_OK(werr
)) {
4644 desc
.errcode
= W_ERROR_V(werr
);
4649 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4654 desc
.buflen
= mdrcnt
;
4657 * Don't return data but need to get correct length
4658 * init_package will return wrong size if buflen=0
4660 desc
.buflen
= getlen(desc
.format
);
4661 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4664 if (init_package(&desc
,1,0)) {
4665 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4666 *rdata_len
= desc
.usedlen
;
4668 desc
.errcode
= NERR_JobNotFound
;
4672 if (cli
&& is_valid_policy_hnd(&handle
)) {
4673 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4677 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4681 SSVALS(*rparam
,0,desc
.errcode
);
4683 SSVAL(*rparam
,4,desc
.neededlen
);
4687 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4692 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4693 connection_struct
*conn
, uint16 vuid
,
4694 char *param
, int tpscnt
,
4695 char *data
, int tdscnt
,
4696 int mdrcnt
,int mprcnt
,
4697 char **rdata
,char **rparam
,
4698 int *rdata_len
,int *rparam_len
)
4700 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4701 char *str2
= skip_string(param
,tpscnt
,str1
);
4702 char *p
= skip_string(param
,tpscnt
,str2
);
4706 struct pack_desc desc
;
4708 TALLOC_CTX
*mem_ctx
= talloc_tos();
4711 struct rpc_pipe_client
*cli
= NULL
;
4712 struct policy_handle handle
;
4713 struct spoolss_DevmodeContainer devmode_ctr
;
4715 union spoolss_JobInfo
*info
;
4717 if (!str1
|| !str2
|| !p
) {
4721 memset((char *)&desc
,'\0',sizeof(desc
));
4723 p
= skip_string(param
,tpscnt
,p
);
4727 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4729 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4731 /* check it's a supported variant */
4732 if (strcmp(str1
,"zWrLeh") != 0) {
4737 return False
; /* defined only for uLevel 0,1,2 */
4740 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4744 ZERO_STRUCT(handle
);
4746 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4747 if (!NT_STATUS_IS_OK(status
)) {
4748 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4749 nt_errstr(status
)));
4750 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4754 ZERO_STRUCT(devmode_ctr
);
4756 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4760 SEC_FLAG_MAXIMUM_ALLOWED
,
4763 if (!NT_STATUS_IS_OK(status
)) {
4764 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4767 if (!W_ERROR_IS_OK(werr
)) {
4768 desc
.errcode
= W_ERROR_V(werr
);
4772 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4780 if (!W_ERROR_IS_OK(werr
)) {
4781 desc
.errcode
= W_ERROR_V(werr
);
4786 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4792 desc
.buflen
= mdrcnt
;
4794 if (init_package(&desc
,count
,0)) {
4796 for (i
= 0; i
< count
; i
++) {
4797 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4798 if (desc
.errcode
== NERR_Success
) {
4804 if (cli
&& is_valid_policy_hnd(&handle
)) {
4805 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4808 *rdata_len
= desc
.usedlen
;
4811 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4815 SSVALS(*rparam
,0,desc
.errcode
);
4817 SSVAL(*rparam
,4,succnt
);
4818 SSVAL(*rparam
,6,count
);
4820 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4825 static int check_printdest_info(struct pack_desc
* desc
,
4826 int uLevel
, char* id
)
4828 desc
->subformat
= NULL
;
4831 desc
->format
= "B9";
4834 desc
->format
= "B9B21WWzW";
4840 desc
->format
= "zzzWWzzzWW";
4843 DEBUG(0,("check_printdest_info: invalid level %d\n",
4847 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4848 DEBUG(0,("check_printdest_info: invalid string %s\n",
4849 id
? id
: "<NULL>" ));
4855 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4856 struct pack_desc
* desc
)
4860 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4861 buf
[sizeof(buf
)-1] = 0;
4865 PACKS(desc
,"B9",buf
); /* szName */
4867 PACKS(desc
,"B21",""); /* szUserName */
4868 PACKI(desc
,"W",0); /* uJobId */
4869 PACKI(desc
,"W",0); /* fsStatus */
4870 PACKS(desc
,"z",""); /* pszStatus */
4871 PACKI(desc
,"W",0); /* time */
4875 if (uLevel
== 2 || uLevel
== 3) {
4876 PACKS(desc
,"z",buf
); /* pszPrinterName */
4878 PACKS(desc
,"z",""); /* pszUserName */
4879 PACKS(desc
,"z",""); /* pszLogAddr */
4880 PACKI(desc
,"W",0); /* uJobId */
4881 PACKI(desc
,"W",0); /* fsStatus */
4882 PACKS(desc
,"z",""); /* pszStatus */
4883 PACKS(desc
,"z",""); /* pszComment */
4884 PACKS(desc
,"z","NULL"); /* pszDrivers */
4885 PACKI(desc
,"W",0); /* time */
4886 PACKI(desc
,"W",0); /* pad1 */
4891 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4892 connection_struct
*conn
, uint16 vuid
,
4893 char *param
, int tpscnt
,
4894 char *data
, int tdscnt
,
4895 int mdrcnt
,int mprcnt
,
4896 char **rdata
,char **rparam
,
4897 int *rdata_len
,int *rparam_len
)
4899 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4900 char *str2
= skip_string(param
,tpscnt
,str1
);
4901 char *p
= skip_string(param
,tpscnt
,str2
);
4902 char* PrinterName
= p
;
4904 struct pack_desc desc
;
4907 TALLOC_CTX
*mem_ctx
= talloc_tos();
4910 struct rpc_pipe_client
*cli
= NULL
;
4911 struct policy_handle handle
;
4912 struct spoolss_DevmodeContainer devmode_ctr
;
4913 union spoolss_PrinterInfo info
;
4915 if (!str1
|| !str2
|| !p
) {
4919 memset((char *)&desc
,'\0',sizeof(desc
));
4921 p
= skip_string(param
,tpscnt
,p
);
4925 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4927 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4929 /* check it's a supported varient */
4930 if (strcmp(str1
,"zWrLh") != 0) {
4933 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4937 ZERO_STRUCT(handle
);
4939 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4940 if (!NT_STATUS_IS_OK(status
)) {
4941 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4942 nt_errstr(status
)));
4943 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4947 ZERO_STRUCT(devmode_ctr
);
4949 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4953 SEC_FLAG_MAXIMUM_ALLOWED
,
4956 if (!NT_STATUS_IS_OK(status
)) {
4958 desc
.errcode
= NERR_DestNotFound
;
4962 if (!W_ERROR_IS_OK(werr
)) {
4964 desc
.errcode
= NERR_DestNotFound
;
4969 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4974 if (!W_ERROR_IS_OK(werr
)) {
4976 desc
.errcode
= NERR_DestNotFound
;
4982 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4987 desc
.buflen
= mdrcnt
;
4990 * Don't return data but need to get correct length
4991 * init_package will return wrong size if buflen=0
4993 desc
.buflen
= getlen(desc
.format
);
4994 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4996 if (init_package(&desc
,1,0)) {
4997 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5001 if (cli
&& is_valid_policy_hnd(&handle
)) {
5002 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
5005 *rdata_len
= desc
.usedlen
;
5008 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5012 SSVALS(*rparam
,0,desc
.errcode
);
5014 SSVAL(*rparam
,4,desc
.neededlen
);
5016 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5022 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5023 connection_struct
*conn
, uint16 vuid
,
5024 char *param
, int tpscnt
,
5025 char *data
, int tdscnt
,
5026 int mdrcnt
,int mprcnt
,
5027 char **rdata
,char **rparam
,
5028 int *rdata_len
,int *rparam_len
)
5030 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5031 char *str2
= skip_string(param
,tpscnt
,str1
);
5032 char *p
= skip_string(param
,tpscnt
,str2
);
5036 struct pack_desc desc
;
5038 TALLOC_CTX
*mem_ctx
= talloc_tos();
5041 struct rpc_pipe_client
*cli
= NULL
;
5042 union spoolss_PrinterInfo
*info
;
5045 if (!str1
|| !str2
|| !p
) {
5049 memset((char *)&desc
,'\0',sizeof(desc
));
5051 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5053 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5055 /* check it's a supported varient */
5056 if (strcmp(str1
,"WrLeh") != 0) {
5059 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5065 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
5066 if (!NT_STATUS_IS_OK(status
)) {
5067 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5068 nt_errstr(status
)));
5069 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5073 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5075 cli
->srv_name_slash
,
5080 if (!W_ERROR_IS_OK(werr
)) {
5081 desc
.errcode
= W_ERROR_V(werr
);
5083 desc
.errcode
= NERR_DestNotFound
;
5091 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5098 desc
.buflen
= mdrcnt
;
5099 if (init_package(&desc
,queuecnt
,0)) {
5102 for (i
= 0; i
< count
; i
++) {
5103 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5105 if (desc
.errcode
== NERR_Success
) {
5111 *rdata_len
= desc
.usedlen
;
5114 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5118 SSVALS(*rparam
,0,desc
.errcode
);
5120 SSVAL(*rparam
,4,succnt
);
5121 SSVAL(*rparam
,6,queuecnt
);
5123 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5128 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5129 connection_struct
*conn
, uint16 vuid
,
5130 char *param
, int tpscnt
,
5131 char *data
, int tdscnt
,
5132 int mdrcnt
,int mprcnt
,
5133 char **rdata
,char **rparam
,
5134 int *rdata_len
,int *rparam_len
)
5136 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5137 char *str2
= skip_string(param
,tpscnt
,str1
);
5138 char *p
= skip_string(param
,tpscnt
,str2
);
5141 struct pack_desc desc
;
5143 if (!str1
|| !str2
|| !p
) {
5147 memset((char *)&desc
,'\0',sizeof(desc
));
5149 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5151 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5153 /* check it's a supported varient */
5154 if (strcmp(str1
,"WrLeh") != 0) {
5157 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5162 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5168 desc
.buflen
= mdrcnt
;
5169 if (init_package(&desc
,1,0)) {
5170 PACKS(&desc
,"B41","NULL");
5173 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5175 *rdata_len
= desc
.usedlen
;
5178 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5182 SSVALS(*rparam
,0,desc
.errcode
);
5184 SSVAL(*rparam
,4,succnt
);
5187 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5192 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5193 connection_struct
*conn
, uint16 vuid
,
5194 char *param
, int tpscnt
,
5195 char *data
, int tdscnt
,
5196 int mdrcnt
,int mprcnt
,
5197 char **rdata
,char **rparam
,
5198 int *rdata_len
,int *rparam_len
)
5200 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5201 char *str2
= skip_string(param
,tpscnt
,str1
);
5202 char *p
= skip_string(param
,tpscnt
,str2
);
5205 struct pack_desc desc
;
5207 if (!str1
|| !str2
|| !p
) {
5210 memset((char *)&desc
,'\0',sizeof(desc
));
5212 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5214 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5216 /* check it's a supported varient */
5217 if (strcmp(str1
,"WrLeh") != 0) {
5220 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5225 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5231 desc
.buflen
= mdrcnt
;
5233 if (init_package(&desc
,1,0)) {
5234 PACKS(&desc
,"B13","lpd");
5237 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5239 *rdata_len
= desc
.usedlen
;
5242 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5246 SSVALS(*rparam
,0,desc
.errcode
);
5248 SSVAL(*rparam
,4,succnt
);
5251 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5256 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5257 connection_struct
*conn
, uint16 vuid
,
5258 char *param
, int tpscnt
,
5259 char *data
, int tdscnt
,
5260 int mdrcnt
,int mprcnt
,
5261 char **rdata
,char **rparam
,
5262 int *rdata_len
,int *rparam_len
)
5264 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5265 char *str2
= skip_string(param
,tpscnt
,str1
);
5266 char *p
= skip_string(param
,tpscnt
,str2
);
5269 struct pack_desc desc
;
5271 if (!str1
|| !str2
|| !p
) {
5275 memset((char *)&desc
,'\0',sizeof(desc
));
5277 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5279 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5281 /* check it's a supported varient */
5282 if (strcmp(str1
,"WrLeh") != 0) {
5285 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5290 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5295 memset((char *)&desc
,'\0',sizeof(desc
));
5297 desc
.buflen
= mdrcnt
;
5299 if (init_package(&desc
,1,0)) {
5300 PACKS(&desc
,"B13","lp0");
5303 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5305 *rdata_len
= desc
.usedlen
;
5308 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5312 SSVALS(*rparam
,0,desc
.errcode
);
5314 SSVAL(*rparam
,4,succnt
);
5317 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5322 /****************************************************************************
5324 ****************************************************************************/
5326 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5327 connection_struct
*conn
, uint16 vuid
,
5328 char *param
, int tpscnt
,
5329 char *data
, int tdscnt
,
5330 int mdrcnt
,int mprcnt
,
5331 char **rdata
,char **rparam
,
5332 int *rdata_len
,int *rparam_len
)
5335 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5336 char *str2
= skip_string(param
,tpscnt
,str1
);
5337 char *p
= skip_string(param
,tpscnt
,str2
);
5339 struct pack_desc desc
;
5340 struct sessionid
*session_list
;
5341 int i
, num_sessions
;
5343 if (!str1
|| !str2
|| !p
) {
5347 memset((char *)&desc
,'\0',sizeof(desc
));
5349 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5351 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5352 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5353 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5355 /* check it's a supported varient */
5356 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5359 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5363 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5366 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5371 memset((char *)&desc
,'\0',sizeof(desc
));
5373 desc
.buflen
= mdrcnt
;
5375 if (!init_package(&desc
,num_sessions
,0)) {
5379 for(i
=0; i
<num_sessions
; i
++) {
5380 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5381 PACKS(&desc
, "z", session_list
[i
].username
);
5382 PACKI(&desc
, "W", 1); /* num conns */
5383 PACKI(&desc
, "W", 0); /* num opens */
5384 PACKI(&desc
, "W", 1); /* num users */
5385 PACKI(&desc
, "D", 0); /* session time */
5386 PACKI(&desc
, "D", 0); /* idle time */
5387 PACKI(&desc
, "D", 0); /* flags */
5388 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5391 *rdata_len
= desc
.usedlen
;
5394 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5398 SSVALS(*rparam
,0,desc
.errcode
);
5399 SSVAL(*rparam
,2,0); /* converter */
5400 SSVAL(*rparam
,4,num_sessions
); /* count */
5402 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5408 /****************************************************************************
5409 The buffer was too small.
5410 ****************************************************************************/
5412 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5413 connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5414 int mdrcnt
, int mprcnt
,
5415 char **rdata
, char **rparam
,
5416 int *rdata_len
, int *rparam_len
)
5418 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5419 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5426 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5428 DEBUG(3,("Supplied buffer too small in API command\n"));
5433 /****************************************************************************
5434 The request is not supported.
5435 ****************************************************************************/
5437 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5438 connection_struct
*conn
, uint16 vuid
,
5439 char *param
, int tpscnt
,
5440 char *data
, int tdscnt
,
5441 int mdrcnt
, int mprcnt
,
5442 char **rdata
, char **rparam
,
5443 int *rdata_len
, int *rparam_len
)
5446 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5453 SSVAL(*rparam
,0,NERR_notsupported
);
5454 SSVAL(*rparam
,2,0); /* converter word */
5456 DEBUG(3,("Unsupported API command\n"));
5461 static const struct {
5464 bool (*fn
)(struct smbd_server_connection
*sconn
,
5465 connection_struct
*, uint16
,
5468 int,int,char **,char **,int *,int *);
5469 bool auth_user
; /* Deny anonymous access? */
5470 } api_commands
[] = {
5471 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5472 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5473 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5474 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5475 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5476 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5477 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5478 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5479 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5480 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5481 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5482 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5483 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5484 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5485 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5486 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5487 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5488 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5489 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5490 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5491 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5492 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5493 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5494 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5495 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5496 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5497 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5498 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5499 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5500 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5501 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5502 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5503 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5504 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5505 {NULL
, -1, api_Unsupported
}
5506 /* The following RAP calls are not implemented by Samba:
5508 RAP_WFileEnum2 - anon not OK
5513 /****************************************************************************
5514 Handle remote api calls.
5515 ****************************************************************************/
5517 void api_reply(connection_struct
*conn
, uint16 vuid
,
5518 struct smb_request
*req
,
5519 char *data
, char *params
,
5520 int tdscnt
, int tpscnt
,
5521 int mdrcnt
, int mprcnt
)
5525 char *rparam
= NULL
;
5526 const char *name1
= NULL
;
5527 const char *name2
= NULL
;
5534 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5535 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5540 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5543 api_command
= SVAL(params
,0);
5544 /* Is there a string at position params+2 ? */
5545 if (skip_string(params
,tpscnt
,params
+2)) {
5550 name2
= skip_string(params
,tpscnt
,params
+2);
5555 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5559 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5561 for (i
=0;api_commands
[i
].name
;i
++) {
5562 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5563 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5568 /* Check whether this api call can be done anonymously */
5570 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5571 user_struct
*user
= get_valid_user_struct(req
->sconn
, vuid
);
5573 if (!user
|| user
->server_info
->guest
) {
5574 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5579 rdata
= (char *)SMB_MALLOC(1024);
5581 memset(rdata
,'\0',1024);
5584 rparam
= (char *)SMB_MALLOC(1024);
5586 memset(rparam
,'\0',1024);
5589 if(!rdata
|| !rparam
) {
5590 DEBUG(0,("api_reply: malloc fail !\n"));
5593 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5597 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5599 params
,tpscnt
, /* params + length */
5600 data
,tdscnt
, /* data + length */
5602 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5605 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5606 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5608 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5611 /* if we get False back then it's actually unsupported */
5613 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5615 tdscnt
,mdrcnt
,mprcnt
,
5616 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5619 /* If api_Unsupported returns false we can't return anything. */
5621 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5622 rdata
, rdata_len
, False
);