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(connection_struct
*conn
, uint16 vuid
,
76 char *param
, int tpscnt
,
77 char *data
, int tdscnt
,
78 int mdrcnt
, int mprcnt
,
79 char **rdata
, char **rparam
,
80 int *rdata_len
, int *rparam_len
);
82 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
83 int mdrcnt
, int mprcnt
,
84 char **rdata
, char **rparam
,
85 int *rdata_len
, int *rparam_len
);
88 static int CopyExpanded(connection_struct
*conn
,
89 int snum
, char **dst
, char *src
, int *p_space_remaining
)
91 TALLOC_CTX
*ctx
= talloc_tos();
95 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
96 *p_space_remaining
<= 0) {
100 buf
= talloc_strdup(ctx
, src
);
102 *p_space_remaining
= 0;
105 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
107 *p_space_remaining
= 0;
110 buf
= talloc_sub_advanced(ctx
,
111 lp_servicename(SNUM(conn
)),
112 conn
->server_info
->unix_name
,
114 conn
->server_info
->utok
.gid
,
115 conn
->server_info
->sanitized_username
,
116 conn
->server_info
->info3
->base
.domain
.string
,
119 *p_space_remaining
= 0;
122 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
127 (*p_space_remaining
) -= l
;
131 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
134 if (!src
|| !dst
|| !n
|| !(*dst
)) {
137 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
146 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
148 TALLOC_CTX
*ctx
= talloc_tos();
153 buf
= talloc_strdup(ctx
,s
);
157 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
161 buf
= talloc_sub_advanced(ctx
,
162 lp_servicename(SNUM(conn
)),
163 conn
->server_info
->unix_name
,
165 conn
->server_info
->utok
.gid
,
166 conn
->server_info
->sanitized_username
,
167 conn
->server_info
->info3
->base
.domain
.string
,
172 return strlen(buf
) + 1;
175 /*******************************************************************
176 Check a API string for validity when we only need to check the prefix.
177 ******************************************************************/
179 static bool prefix_ok(const char *str
, const char *prefix
)
181 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
185 const char *format
; /* formatstring for structure */
186 const char *subformat
; /* subformat for structure */
187 char *base
; /* baseaddress of buffer */
188 int buflen
; /* remaining size for fixed part; on init: length of base */
189 int subcount
; /* count of substructures */
190 char *structbuf
; /* pointer into buffer for remaining fixed part */
191 int stringlen
; /* remaining size for variable part */
192 char *stringbuf
; /* pointer into buffer for remaining variable part */
193 int neededlen
; /* total needed size */
194 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
195 const char *curpos
; /* current position; pointer into format or subformat */
199 static int get_counter(const char **p
)
205 if (!isdigit((int)**p
)) {
211 n
= 10 * n
+ (i
- '0');
219 static int getlen(const char *p
)
228 case 'W': /* word (2 byte) */
231 case 'K': /* status word? (2 byte) */
234 case 'N': /* count of substructures (word) at end */
237 case 'D': /* double word (4 byte) */
238 case 'z': /* offset to zero terminated string (4 byte) */
239 case 'l': /* offset to user data (4 byte) */
242 case 'b': /* offset to data (with counter) (4 byte) */
246 case 'B': /* byte (with optional counter) */
247 n
+= get_counter(&p
);
254 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
259 if (!p
->format
|| !p
->base
) {
263 i
= count
* getlen(p
->format
);
265 i
+= subcount
* getlen(p
->subformat
);
267 p
->structbuf
= p
->base
;
271 p
->curpos
= p
->format
;
277 * This is the old error code we used. Aparently
278 * WinNT/2k systems return ERRbuftoosmall (2123) and
279 * OS/2 needs this. I'm leaving this here so we can revert
282 p
->errcode
= ERRmoredata
;
284 p
->errcode
= ERRbuftoosmall
;
287 p
->errcode
= NERR_Success
;
291 p
->stringbuf
= p
->base
+ i
;
293 return (p
->errcode
== NERR_Success
);
296 static int package(struct pack_desc
*p
, ...)
299 int needed
=0, stringneeded
;
300 const char *str
=NULL
;
301 int is_string
=0, stringused
;
308 p
->curpos
= p
->format
;
310 p
->curpos
= p
->subformat
;
315 str
= va_arg(args
,char*);
316 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
325 switch( *p
->curpos
++ ) {
326 case 'W': /* word (2 byte) */
328 temp
= va_arg(args
,int);
329 if (p
->buflen
>= needed
) {
330 SSVAL(p
->structbuf
,0,temp
);
333 case 'K': /* status word? (2 byte) */
335 temp
= va_arg(args
,int);
336 if (p
->buflen
>= needed
) {
337 SSVAL(p
->structbuf
,0,temp
);
340 case 'N': /* count of substructures (word) at end */
342 p
->subcount
= va_arg(args
,int);
343 if (p
->buflen
>= needed
) {
344 SSVAL(p
->structbuf
,0,p
->subcount
);
347 case 'D': /* double word (4 byte) */
349 temp
= va_arg(args
,int);
350 if (p
->buflen
>= needed
) {
351 SIVAL(p
->structbuf
,0,temp
);
354 case 'B': /* byte (with optional counter) */
355 needed
= get_counter(&p
->curpos
);
357 char *s
= va_arg(args
,char*);
358 if (p
->buflen
>= needed
) {
359 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
363 case 'z': /* offset to zero terminated string (4 byte) */
364 str
= va_arg(args
,char*);
365 stringneeded
= (str
? strlen(str
)+1 : 0);
368 case 'l': /* offset to user data (4 byte) */
369 str
= va_arg(args
,char*);
370 stringneeded
= va_arg(args
,int);
373 case 'b': /* offset to data (with counter) (4 byte) */
374 str
= va_arg(args
,char*);
375 stringneeded
= get_counter(&p
->curpos
);
381 if (stringneeded
>= 0) {
383 if (p
->buflen
>= needed
) {
384 stringused
= stringneeded
;
385 if (stringused
> p
->stringlen
) {
386 stringused
= (is_string
? p
->stringlen
: 0);
387 if (p
->errcode
== NERR_Success
) {
388 p
->errcode
= ERRmoredata
;
392 SIVAL(p
->structbuf
,0,0);
394 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
395 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
397 p
->stringbuf
[stringused
-1] = '\0';
399 p
->stringbuf
+= stringused
;
400 p
->stringlen
-= stringused
;
401 p
->usedlen
+= stringused
;
404 p
->neededlen
+= stringneeded
;
407 p
->neededlen
+= needed
;
408 if (p
->buflen
>= needed
) {
409 p
->structbuf
+= needed
;
411 p
->usedlen
+= needed
;
413 if (p
->errcode
== NERR_Success
) {
414 p
->errcode
= ERRmoredata
;
421 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
422 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
424 #define PACK(desc,t,v) package(desc,v)
425 #define PACKl(desc,t,v,l) package(desc,v,l)
428 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
433 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
438 /****************************************************************************
440 ****************************************************************************/
442 static void PackDriverData(struct pack_desc
* desc
)
444 char drivdata
[4+4+32];
445 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
446 SIVAL(drivdata
,4,1000); /* lVersion */
447 memset(drivdata
+8,0,32); /* szDeviceName */
448 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
449 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
452 static int check_printq_info(struct pack_desc
* desc
,
453 unsigned int uLevel
, char *id1
, char *id2
)
455 desc
->subformat
= NULL
;
458 desc
->format
= "B13";
461 desc
->format
= "B13BWWWzzzzzWW";
464 desc
->format
= "B13BWWWzzzzzWN";
465 desc
->subformat
= "WB21BB16B10zWWzDDz";
468 desc
->format
= "zWWWWzzzzWWzzl";
471 desc
->format
= "zWWWWzzzzWNzzl";
472 desc
->subformat
= "WWzWWDDzz";
481 desc
->format
= "WzzzzzzzzN";
482 desc
->subformat
= "z";
485 DEBUG(0,("check_printq_info: invalid level %d\n",
489 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
490 DEBUG(0,("check_printq_info: invalid format %s\n",
491 id1
? id1
: "<NULL>" ));
494 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
495 DEBUG(0,("check_printq_info: invalid subformat %s\n",
496 id2
? id2
: "<NULL>" ));
503 #define RAP_JOB_STATUS_QUEUED 0
504 #define RAP_JOB_STATUS_PAUSED 1
505 #define RAP_JOB_STATUS_SPOOLING 2
506 #define RAP_JOB_STATUS_PRINTING 3
507 #define RAP_JOB_STATUS_PRINTED 4
509 #define RAP_QUEUE_STATUS_PAUSED 1
510 #define RAP_QUEUE_STATUS_ERROR 2
512 /* turn a print job status into a on the wire status
514 static int printj_spoolss_status(int v
)
516 if (v
== JOB_STATUS_QUEUED
)
517 return RAP_JOB_STATUS_QUEUED
;
518 if (v
& JOB_STATUS_PAUSED
)
519 return RAP_JOB_STATUS_PAUSED
;
520 if (v
& JOB_STATUS_SPOOLING
)
521 return RAP_JOB_STATUS_SPOOLING
;
522 if (v
& JOB_STATUS_PRINTING
)
523 return RAP_JOB_STATUS_PRINTING
;
527 /* turn a print queue status into a on the wire status
529 static int printq_spoolss_status(int v
)
531 if (v
== PRINTER_STATUS_OK
)
533 if (v
& PRINTER_STATUS_PAUSED
)
534 return RAP_QUEUE_STATUS_PAUSED
;
535 return RAP_QUEUE_STATUS_ERROR
;
538 static void fill_spoolss_printjob_info(int uLevel
,
539 struct pack_desc
*desc
,
540 struct spoolss_JobInfo2
*info2
,
543 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
545 /* the client expects localtime */
546 t
-= get_time_zone(t
);
548 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
550 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
551 PACKS(desc
,"B",""); /* pad */
552 PACKS(desc
,"B16",""); /* szNotifyName */
553 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
554 PACKS(desc
,"z",""); /* pszParms */
555 PACKI(desc
,"W",n
+1); /* uPosition */
556 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
557 PACKS(desc
,"z",""); /* pszStatus */
558 PACKI(desc
,"D", t
); /* ulSubmitted */
559 PACKI(desc
,"D", info2
->size
); /* ulSize */
560 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
562 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
563 PACKI(desc
,"W", info2
->priority
); /* uPriority */
564 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
565 PACKI(desc
,"W",n
+1); /* uPosition */
566 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
567 PACKI(desc
,"D",t
); /* ulSubmitted */
568 PACKI(desc
,"D", info2
->size
); /* ulSize */
569 PACKS(desc
,"z","Samba"); /* pszComment */
570 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
572 PACKS(desc
,"z",""); /* pszNotifyName */
573 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
574 PACKS(desc
,"z",""); /* pszParms */
575 PACKS(desc
,"z",""); /* pszStatus */
576 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
577 PACKS(desc
,"z","lpd"); /* pszQProcName */
578 PACKS(desc
,"z",""); /* pszQProcParms */
579 PACKS(desc
,"z","NULL"); /* pszDriverName */
580 PackDriverData(desc
); /* pDriverData */
581 PACKS(desc
,"z",""); /* pszPrinterName */
582 } else if (uLevel
== 4) { /* OS2 */
583 PACKS(desc
,"z",""); /* pszSpoolFileName */
584 PACKS(desc
,"z",""); /* pszPortName */
585 PACKS(desc
,"z",""); /* pszStatus */
586 PACKI(desc
,"D",0); /* ulPagesSpooled */
587 PACKI(desc
,"D",0); /* ulPagesSent */
588 PACKI(desc
,"D",0); /* ulPagesPrinted */
589 PACKI(desc
,"D",0); /* ulTimePrinted */
590 PACKI(desc
,"D",0); /* ulExtendJobStatus */
591 PACKI(desc
,"D",0); /* ulStartPage */
592 PACKI(desc
,"D",0); /* ulEndPage */
597 /********************************************************************
598 Respond to the DosPrintQInfo command with a level of 52
599 This is used to get printer driver information for Win9x clients
600 ********************************************************************/
601 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
602 struct pack_desc
* desc
, int count
,
603 const char *printer_name
)
607 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
608 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
609 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
611 PACKI(desc
, "W", 0x0400); /* don't know */
612 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
613 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
614 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
615 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
617 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
618 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
619 PACKS(desc
,"z", location
); /* share to retrieve files */
621 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
622 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
623 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
625 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
626 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
627 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
628 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
629 DEBUG(3,("Driver Location: %s:\n",location
));
630 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
631 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
632 PACKI(desc
,"N",count
); /* number of files to copy */
634 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
636 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
637 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
638 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
643 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
646 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
648 desc
->errcode
=NERR_Success
;
652 static const char *strip_unc(const char *unc
)
660 if ((p
= strrchr(unc
, '\\')) != NULL
) {
667 static void fill_printq_info(int uLevel
,
668 struct pack_desc
* desc
,
670 union spoolss_JobInfo
*job_info
,
671 struct spoolss_DriverInfo3
*driver_info
,
672 struct spoolss_PrinterInfo2
*printer_info
)
678 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
683 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
686 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
690 if (uLevel
== 1 || uLevel
== 2) {
691 PACKS(desc
,"B",""); /* alignment */
692 PACKI(desc
,"W",5); /* priority */
693 PACKI(desc
,"W",0); /* start time */
694 PACKI(desc
,"W",0); /* until time */
695 PACKS(desc
,"z",""); /* pSepFile */
696 PACKS(desc
,"z","lpd"); /* pPrProc */
697 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
698 PACKS(desc
,"z",""); /* pParms */
699 if (printer_info
->printername
== NULL
) {
700 PACKS(desc
,"z","UNKNOWN PRINTER");
701 PACKI(desc
,"W",LPSTAT_ERROR
);
703 PACKS(desc
,"z", printer_info
->comment
);
704 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
706 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
709 if (uLevel
== 3 || uLevel
== 4) {
710 PACKI(desc
,"W",5); /* uPriority */
711 PACKI(desc
,"W",0); /* uStarttime */
712 PACKI(desc
,"W",0); /* uUntiltime */
713 PACKI(desc
,"W",5); /* pad1 */
714 PACKS(desc
,"z",""); /* pszSepFile */
715 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
716 PACKS(desc
,"z",NULL
); /* pszParms */
717 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
718 /* "don't ask" that it's done this way to fix corrupted
719 Win9X/ME printer comments. */
720 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
721 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
722 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
723 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
724 PackDriverData(desc
); /* pDriverData */
727 if (uLevel
== 2 || uLevel
== 4) {
729 for (i
= 0; i
< count
; i
++) {
730 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
735 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
738 /* This function returns the number of files for a given driver */
739 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
743 /* count the number of files */
744 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
750 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
751 char *param
, int tpscnt
,
752 char *data
, int tdscnt
,
753 int mdrcnt
,int mprcnt
,
754 char **rdata
,char **rparam
,
755 int *rdata_len
,int *rparam_len
)
757 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
758 char *str2
= skip_string(param
,tpscnt
,str1
);
759 char *p
= skip_string(param
,tpscnt
,str2
);
764 struct pack_desc desc
;
767 WERROR werr
= WERR_OK
;
768 TALLOC_CTX
*mem_ctx
= talloc_tos();
770 struct rpc_pipe_client
*cli
= NULL
;
771 struct policy_handle handle
;
772 struct spoolss_DevmodeContainer devmode_ctr
;
773 union spoolss_DriverInfo driver_info
;
774 union spoolss_JobInfo
*job_info
;
775 union spoolss_PrinterInfo printer_info
;
777 if (!str1
|| !str2
|| !p
) {
780 memset((char *)&desc
,'\0',sizeof(desc
));
782 p
= skip_string(param
,tpscnt
,p
);
786 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
787 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
788 /* str3 may be null here and is checked in check_printq_info(). */
790 /* remove any trailing username */
791 if ((p
= strchr_m(QueueName
,'%')))
794 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
796 /* check it's a supported varient */
797 if (!prefix_ok(str1
,"zWrLh"))
799 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
801 * Patch from Scott Moomaw <scott@bridgewater.edu>
802 * to return the 'invalid info level' error if an
803 * unknown level was requested.
807 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
811 SSVALS(*rparam
,0,ERRunknownlevel
);
819 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
820 if (!NT_STATUS_IS_OK(status
)) {
821 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
823 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
827 ZERO_STRUCT(devmode_ctr
);
829 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
836 if (!NT_STATUS_IS_OK(status
)) {
837 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
840 if (!W_ERROR_IS_OK(werr
)) {
841 desc
.errcode
= W_ERROR_V(werr
);
845 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
850 if (!W_ERROR_IS_OK(werr
)) {
851 desc
.errcode
= W_ERROR_V(werr
);
856 uint32_t server_major_version
;
857 uint32_t server_minor_version
;
859 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
867 &server_major_version
,
868 &server_minor_version
);
869 if (!W_ERROR_IS_OK(werr
)) {
870 desc
.errcode
= W_ERROR_V(werr
);
874 count
= get_printerdrivernumber(&driver_info
.info3
);
875 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
878 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
886 if (!W_ERROR_IS_OK(werr
)) {
887 desc
.errcode
= W_ERROR_V(werr
);
895 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
900 desc
.buflen
= mdrcnt
;
903 * Don't return data but need to get correct length
904 * init_package will return wrong size if buflen=0
906 desc
.buflen
= getlen(desc
.format
);
907 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
910 if (init_package(&desc
,1,count
)) {
911 desc
.subcount
= count
;
912 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
915 *rdata_len
= desc
.usedlen
;
918 * We must set the return code to ERRbuftoosmall
919 * in order to support lanman style printing with Win NT/2k
922 if (!mdrcnt
&& lp_disable_spoolss())
923 desc
.errcode
= ERRbuftoosmall
;
926 if (cli
&& is_valid_policy_hnd(&handle
)) {
927 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
930 *rdata_len
= desc
.usedlen
;
932 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
937 SSVALS(*rparam
,0,desc
.errcode
);
939 SSVAL(*rparam
,4,desc
.neededlen
);
941 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
948 /****************************************************************************
949 View list of all print jobs on all queues.
950 ****************************************************************************/
952 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
953 char *param
, int tpscnt
,
954 char *data
, int tdscnt
,
955 int mdrcnt
, int mprcnt
,
956 char **rdata
, char** rparam
,
957 int *rdata_len
, int *rparam_len
)
959 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
960 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
961 char *p
= skip_string(param
,tpscnt
,output_format1
);
962 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
963 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
965 struct pack_desc desc
;
966 int *subcntarr
= NULL
;
967 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
969 WERROR werr
= WERR_OK
;
970 TALLOC_CTX
*mem_ctx
= talloc_tos();
972 struct rpc_pipe_client
*cli
= NULL
;
973 struct spoolss_DevmodeContainer devmode_ctr
;
974 uint32_t num_printers
;
975 union spoolss_PrinterInfo
*printer_info
;
976 union spoolss_DriverInfo
*driver_info
;
977 union spoolss_JobInfo
**job_info
;
979 if (!param_format
|| !output_format1
|| !p
) {
983 memset((char *)&desc
,'\0',sizeof(desc
));
985 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
987 if (!prefix_ok(param_format
,"WrLeh")) {
990 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
992 * Patch from Scott Moomaw <scott@bridgewater.edu>
993 * to return the 'invalid info level' error if an
994 * unknown level was requested.
998 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1002 SSVALS(*rparam
,0,ERRunknownlevel
);
1008 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
1009 if (!NT_STATUS_IS_OK(status
)) {
1010 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1011 nt_errstr(status
)));
1012 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1016 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1018 cli
->srv_name_slash
,
1023 if (!W_ERROR_IS_OK(werr
)) {
1024 desc
.errcode
= W_ERROR_V(werr
);
1028 queuecnt
= num_printers
;
1030 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1031 if (job_info
== NULL
) {
1035 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1036 if (driver_info
== NULL
) {
1040 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1041 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1046 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1052 desc
.buflen
= mdrcnt
;
1055 for (i
= 0; i
< num_printers
; i
++) {
1058 struct policy_handle handle
;
1059 const char *printername
;
1061 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1062 if (printername
== NULL
) {
1066 ZERO_STRUCT(handle
);
1067 ZERO_STRUCT(devmode_ctr
);
1069 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
1076 if (!NT_STATUS_IS_OK(status
)) {
1077 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1080 if (!W_ERROR_IS_OK(werr
)) {
1081 desc
.errcode
= W_ERROR_V(werr
);
1085 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1093 if (!W_ERROR_IS_OK(werr
)) {
1094 desc
.errcode
= W_ERROR_V(werr
);
1099 uint32_t server_major_version
;
1100 uint32_t server_minor_version
;
1102 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1110 &server_major_version
,
1111 &server_minor_version
);
1112 if (!W_ERROR_IS_OK(werr
)) {
1113 desc
.errcode
= W_ERROR_V(werr
);
1118 subcntarr
[i
] = num_jobs
;
1119 subcnt
+= subcntarr
[i
];
1121 if (cli
&& is_valid_policy_hnd(&handle
)) {
1122 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
1126 if (init_package(&desc
,queuecnt
,subcnt
)) {
1127 for (i
= 0; i
< num_printers
; i
++) {
1128 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1129 if (desc
.errcode
== NERR_Success
) {
1135 SAFE_FREE(subcntarr
);
1137 *rdata_len
= desc
.usedlen
;
1139 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1143 SSVALS(*rparam
,0,desc
.errcode
);
1145 SSVAL(*rparam
,4,succnt
);
1146 SSVAL(*rparam
,6,queuecnt
);
1152 SAFE_FREE(subcntarr
);
1157 /****************************************************************************
1158 Get info level for a server list query.
1159 ****************************************************************************/
1161 static bool check_server_info(int uLevel
, char* id
)
1165 if (strcmp(id
,"B16") != 0) {
1170 if (strcmp(id
,"B16BBDz") != 0) {
1180 struct srv_info_struct
{
1188 /*******************************************************************
1189 Get server info lists from the files saved by nmbd. Return the
1191 ******************************************************************/
1193 static int get_server_info(uint32 servertype
,
1194 struct srv_info_struct
**servers
,
1200 bool local_list_only
;
1203 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1205 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1209 /* request for everything is code for request all servers */
1210 if (servertype
== SV_TYPE_ALL
) {
1211 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1214 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1216 DEBUG(4,("Servertype search: %8x\n",servertype
));
1218 for (i
=0;lines
[i
];i
++) {
1220 struct srv_info_struct
*s
;
1221 const char *ptr
= lines
[i
];
1223 TALLOC_CTX
*frame
= NULL
;
1230 if (count
== alloced
) {
1232 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1234 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1238 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1240 s
= &(*servers
)[count
];
1242 frame
= talloc_stackframe();
1244 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1248 fstrcpy(s
->name
, p
);
1251 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1257 s
->comment
[0] = '\0';
1258 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1262 fstrcpy(s
->comment
, p
);
1263 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1265 s
->domain
[0] = '\0';
1266 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1267 /* this allows us to cope with an old nmbd */
1268 fstrcpy(s
->domain
,lp_workgroup());
1270 fstrcpy(s
->domain
, p
);
1274 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1275 DEBUG(4,("r:host file "));
1279 /* Filter the servers/domains we return based on what was asked for. */
1281 /* Check to see if we are being asked for a local list only. */
1282 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1283 DEBUG(4,("r: local list only"));
1287 /* doesn't match up: don't want it */
1288 if (!(servertype
& s
->type
)) {
1289 DEBUG(4,("r:serv type "));
1293 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1294 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1295 DEBUG(4,("s: dom mismatch "));
1299 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1303 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1304 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1307 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1308 s
->name
, s
->type
, s
->comment
, s
->domain
));
1309 s
->server_added
= True
;
1312 DEBUG(4,("%20s %8x %25s %15s\n",
1313 s
->name
, s
->type
, s
->comment
, s
->domain
));
1321 /*******************************************************************
1322 Fill in a server info structure.
1323 ******************************************************************/
1325 static int fill_srv_info(struct srv_info_struct
*service
,
1326 int uLevel
, char **buf
, int *buflen
,
1327 char **stringbuf
, int *stringspace
, char *baseaddr
)
1350 len
= strlen(service
->comment
)+1;
1354 *buflen
= struct_len
;
1356 return struct_len
+ len
;
1361 if (*buflen
< struct_len
) {
1368 p2
= p
+ struct_len
;
1369 l2
= *buflen
- struct_len
;
1377 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1381 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1382 SIVAL(p
,18,service
->type
);
1383 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1384 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1389 *buf
= p
+ struct_len
;
1390 *buflen
-= struct_len
;
1401 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1403 return StrCaseCmp(s1
->name
,s2
->name
);
1406 /****************************************************************************
1407 View list of servers available (or possibly domains). The info is
1408 extracted from lists saved by nmbd on the local host.
1409 ****************************************************************************/
1411 static bool api_RNetServerEnum2(connection_struct
*conn
, uint16 vuid
,
1412 char *param
, int tpscnt
,
1413 char *data
, int tdscnt
,
1414 int mdrcnt
, int mprcnt
, char **rdata
,
1415 char **rparam
, int *rdata_len
, int *rparam_len
)
1417 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1418 char *str2
= skip_string(param
,tpscnt
,str1
);
1419 char *p
= skip_string(param
,tpscnt
,str2
);
1420 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1421 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1422 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1424 int data_len
, fixed_len
, string_len
;
1425 int f_len
= 0, s_len
= 0;
1426 struct srv_info_struct
*servers
=NULL
;
1427 int counted
=0,total
=0;
1430 bool domain_request
;
1433 if (!str1
|| !str2
|| !p
) {
1437 /* If someone sets all the bits they don't really mean to set
1438 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1441 if (servertype
== SV_TYPE_ALL
) {
1442 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1445 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1446 any other bit (they may just set this bit on its own) they
1447 want all the locally seen servers. However this bit can be
1448 set on its own so set the requested servers to be
1449 ALL - DOMAIN_ENUM. */
1451 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1452 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1455 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1456 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1460 if (!prefix_ok(str1
,"WrLehD")) {
1463 if (!check_server_info(uLevel
,str2
)) {
1467 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1468 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1469 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1471 if (strcmp(str1
, "WrLehDz") == 0) {
1472 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1475 pull_ascii_fstring(domain
, p
);
1477 fstrcpy(domain
, lp_workgroup());
1480 DEBUG(4, ("domain [%s]\n", domain
));
1482 if (lp_browse_list()) {
1483 total
= get_server_info(servertype
,&servers
,domain
);
1486 data_len
= fixed_len
= string_len
= 0;
1489 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1492 char *lastname
=NULL
;
1494 for (i
=0;i
<total
;i
++) {
1495 struct srv_info_struct
*s
= &servers
[i
];
1497 if (lastname
&& strequal(lastname
,s
->name
)) {
1501 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1502 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1503 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1505 if (data_len
< buf_len
) {
1508 string_len
+= s_len
;
1515 *rdata_len
= fixed_len
+ string_len
;
1516 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1521 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1527 char *lastname
=NULL
;
1528 int count2
= counted
;
1530 for (i
= 0; i
< total
&& count2
;i
++) {
1531 struct srv_info_struct
*s
= &servers
[i
];
1533 if (lastname
&& strequal(lastname
,s
->name
)) {
1537 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1538 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1539 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1545 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1549 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1551 SSVAL(*rparam
,4,counted
);
1552 SSVAL(*rparam
,6,counted
+missed
);
1556 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1557 domain
,uLevel
,counted
,counted
+missed
));
1562 static int srv_name_match(const char *n1
, const char *n2
)
1565 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1567 * In Windows, FirstNameToReturn need not be an exact match:
1568 * the server will return a list of servers that exist on
1569 * the network greater than or equal to the FirstNameToReturn.
1571 int ret
= StrCaseCmp(n1
, n2
);
1580 static bool api_RNetServerEnum3(connection_struct
*conn
, uint16 vuid
,
1581 char *param
, int tpscnt
,
1582 char *data
, int tdscnt
,
1583 int mdrcnt
, int mprcnt
, char **rdata
,
1584 char **rparam
, int *rdata_len
, int *rparam_len
)
1586 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1587 char *str2
= skip_string(param
,tpscnt
,str1
);
1588 char *p
= skip_string(param
,tpscnt
,str2
);
1589 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1590 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1591 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1593 int data_len
, fixed_len
, string_len
;
1594 int f_len
= 0, s_len
= 0;
1595 struct srv_info_struct
*servers
=NULL
;
1596 int counted
=0,first
=0,total
=0;
1600 bool domain_request
;
1603 if (!str1
|| !str2
|| !p
) {
1607 /* If someone sets all the bits they don't really mean to set
1608 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1611 if (servertype
== SV_TYPE_ALL
) {
1612 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1615 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1616 any other bit (they may just set this bit on its own) they
1617 want all the locally seen servers. However this bit can be
1618 set on its own so set the requested servers to be
1619 ALL - DOMAIN_ENUM. */
1621 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1622 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1625 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1626 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1630 if (strcmp(str1
, "WrLehDzz") != 0) {
1633 if (!check_server_info(uLevel
,str2
)) {
1637 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1638 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1639 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1641 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1644 pull_ascii_fstring(domain
, p
);
1645 if (domain
[0] == '\0') {
1646 fstrcpy(domain
, lp_workgroup());
1648 p
= skip_string(param
,tpscnt
,p
);
1649 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1652 pull_ascii_fstring(first_name
, p
);
1654 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1655 domain
, first_name
));
1657 if (lp_browse_list()) {
1658 total
= get_server_info(servertype
,&servers
,domain
);
1661 data_len
= fixed_len
= string_len
= 0;
1664 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1666 if (first_name
[0] != '\0') {
1667 struct srv_info_struct
*first_server
= NULL
;
1669 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1670 srv_name_match
, first_server
);
1672 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1674 * The binary search may not find the exact match
1675 * so we need to search backward to find the first match
1677 * This implements the strange matching windows
1678 * implements. (see the comment in srv_name_match().
1682 ret
= StrCaseCmp(first_name
,
1683 servers
[first
-1].name
);
1690 /* we should return no entries */
1696 char *lastname
=NULL
;
1698 for (i
=first
;i
<total
;i
++) {
1699 struct srv_info_struct
*s
= &servers
[i
];
1701 if (lastname
&& strequal(lastname
,s
->name
)) {
1705 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1706 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1707 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1709 if (data_len
< buf_len
) {
1712 string_len
+= s_len
;
1719 *rdata_len
= fixed_len
+ string_len
;
1720 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1725 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1731 char *lastname
=NULL
;
1732 int count2
= counted
;
1734 for (i
= first
; i
< total
&& count2
;i
++) {
1735 struct srv_info_struct
*s
= &servers
[i
];
1737 if (lastname
&& strequal(lastname
,s
->name
)) {
1741 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1742 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1743 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1749 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1753 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1755 SSVAL(*rparam
,4,counted
);
1756 SSVAL(*rparam
,6,counted
+missed
);
1758 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1759 domain
,uLevel
,first
,first_name
,
1760 first
< total
? servers
[first
].name
: "",
1761 counted
,counted
+missed
));
1768 /****************************************************************************
1769 command 0x34 - suspected of being a "Lookup Names" stub api
1770 ****************************************************************************/
1772 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1773 char *param
, int tpscnt
,
1774 char *data
, int tdscnt
,
1775 int mdrcnt
, int mprcnt
, char **rdata
,
1776 char **rparam
, int *rdata_len
, int *rparam_len
)
1778 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1779 char *str2
= skip_string(param
,tpscnt
,str1
);
1780 char *p
= skip_string(param
,tpscnt
,str2
);
1781 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1782 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1786 if (!str1
|| !str2
|| !p
) {
1790 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1791 str1
, str2
, p
, uLevel
, buf_len
));
1793 if (!prefix_ok(str1
,"zWrLeh")) {
1800 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1805 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1807 SSVAL(*rparam
,4,counted
);
1808 SSVAL(*rparam
,6,counted
+missed
);
1813 /****************************************************************************
1814 get info about a share
1815 ****************************************************************************/
1817 static bool check_share_info(int uLevel
, char* id
)
1821 if (strcmp(id
,"B13") != 0) {
1826 /* Level-2 descriptor is allowed (and ignored) */
1827 if (strcmp(id
,"B13BWz") != 0 &&
1828 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1833 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1838 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1848 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1849 char** buf
, int* buflen
,
1850 char** stringbuf
, int* stringspace
, char* baseaddr
)
1879 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1882 len
+= strlen(lp_pathname(snum
)) + 1;
1885 *buflen
= struct_len
;
1890 return struct_len
+ len
;
1895 if ((*buflen
) < struct_len
) {
1903 p2
= p
+ struct_len
;
1904 l2
= (*buflen
) - struct_len
;
1911 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1917 type
= STYPE_DISKTREE
;
1918 if (lp_print_ok(snum
)) {
1919 type
= STYPE_PRINTQ
;
1921 if (strequal("IPC",lp_fstype(snum
))) {
1924 SSVAL(p
,14,type
); /* device type */
1925 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1926 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1930 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1931 SSVALS(p
,22,-1); /* max uses */
1932 SSVAL(p
,24,1); /* current uses */
1933 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1934 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1935 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1939 memset(p
+40,0,SHPWLEN
+2);
1950 (*buf
) = p
+ struct_len
;
1951 (*buflen
) -= struct_len
;
1953 (*stringspace
) = l2
;
1962 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1963 char *param
, int tpscnt
,
1964 char *data
, int tdscnt
,
1965 int mdrcnt
,int mprcnt
,
1966 char **rdata
,char **rparam
,
1967 int *rdata_len
,int *rparam_len
)
1969 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1970 char *str2
= skip_string(param
,tpscnt
,str1
);
1971 char *netname
= skip_string(param
,tpscnt
,str2
);
1972 char *p
= skip_string(param
,tpscnt
,netname
);
1973 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1976 if (!str1
|| !str2
|| !netname
|| !p
) {
1980 snum
= find_service(netname
);
1985 /* check it's a supported varient */
1986 if (!prefix_ok(str1
,"zWrLh")) {
1989 if (!check_share_info(uLevel
,str2
)) {
1993 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1998 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1999 if (*rdata_len
< 0) {
2004 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2008 SSVAL(*rparam
,0,NERR_Success
);
2009 SSVAL(*rparam
,2,0); /* converter word */
2010 SSVAL(*rparam
,4,*rdata_len
);
2015 /****************************************************************************
2016 View the list of available shares.
2018 This function is the server side of the NetShareEnum() RAP call.
2019 It fills the return buffer with share names and share comments.
2020 Note that the return buffer normally (in all known cases) allows only
2021 twelve byte strings for share names (plus one for a nul terminator).
2022 Share names longer than 12 bytes must be skipped.
2023 ****************************************************************************/
2025 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
2026 char *param
, int tpscnt
,
2027 char *data
, int tdscnt
,
2035 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2036 char *str2
= skip_string(param
,tpscnt
,str1
);
2037 char *p
= skip_string(param
,tpscnt
,str2
);
2038 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2039 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2042 int total
=0,counted
=0;
2043 bool missed
= False
;
2045 int data_len
, fixed_len
, string_len
;
2046 int f_len
= 0, s_len
= 0;
2048 if (!str1
|| !str2
|| !p
) {
2052 if (!prefix_ok(str1
,"WrLeh")) {
2055 if (!check_share_info(uLevel
,str2
)) {
2059 /* Ensure all the usershares are loaded. */
2061 load_registry_shares();
2062 count
= load_usershare_shares();
2065 data_len
= fixed_len
= string_len
= 0;
2066 for (i
=0;i
<count
;i
++) {
2067 fstring servicename_dos
;
2068 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2071 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2072 /* Maximum name length = 13. */
2073 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2075 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2076 if (data_len
< buf_len
) {
2079 string_len
+= s_len
;
2086 *rdata_len
= fixed_len
+ string_len
;
2087 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2092 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2097 for( i
= 0; i
< count
; i
++ ) {
2098 fstring servicename_dos
;
2099 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2103 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2104 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2105 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2112 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2116 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2118 SSVAL(*rparam
,4,counted
);
2119 SSVAL(*rparam
,6,total
);
2121 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2122 counted
,total
,uLevel
,
2123 buf_len
,*rdata_len
,mdrcnt
));
2128 /****************************************************************************
2130 ****************************************************************************/
2132 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
2133 char *param
, int tpscnt
,
2134 char *data
, int tdscnt
,
2135 int mdrcnt
,int mprcnt
,
2136 char **rdata
,char **rparam
,
2137 int *rdata_len
,int *rparam_len
)
2139 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2140 char *str2
= skip_string(param
,tpscnt
,str1
);
2141 char *p
= skip_string(param
,tpscnt
,str2
);
2142 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2145 char *pathname
= NULL
;
2146 unsigned int offset
;
2148 size_t converted_size
;
2150 WERROR werr
= WERR_OK
;
2151 TALLOC_CTX
*mem_ctx
= talloc_tos();
2153 struct rpc_pipe_client
*cli
= NULL
;
2154 union srvsvc_NetShareInfo info
;
2155 struct srvsvc_NetShareInfo2 info2
;
2157 if (!str1
|| !str2
|| !p
) {
2161 /* check it's a supported varient */
2162 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2165 if (!check_share_info(uLevel
,str2
)) {
2172 /* Do we have a string ? */
2173 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2176 pull_ascii_fstring(sharename
,data
);
2182 /* only support disk share adds */
2183 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2187 offset
= IVAL(data
, 16);
2188 if (offset
>= mdrcnt
) {
2189 res
= ERRinvalidparam
;
2193 /* Do we have a string ? */
2194 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2197 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2199 offset
= IVAL(data
, 26);
2201 if (offset
>= mdrcnt
) {
2202 res
= ERRinvalidparam
;
2206 /* Do we have a string ? */
2207 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2211 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2212 offset
? (data
+offset
) : "", &converted_size
))
2214 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2222 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2223 rpc_srvsvc_dispatch
, conn
->server_info
,
2225 if (!NT_STATUS_IS_OK(status
)) {
2226 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2227 nt_errstr(status
)));
2228 res
= W_ERROR_V(ntstatus_to_werror(status
));
2232 info2
.name
= sharename
;
2233 info2
.type
= STYPE_DISKTREE
;
2234 info2
.comment
= comment
;
2235 info2
.permissions
= 0;
2236 info2
.max_users
= 0;
2237 info2
.current_users
= 0;
2238 info2
.path
= pathname
;
2239 info2
.password
= NULL
;
2241 info
.info2
= &info2
;
2243 status
= rpccli_srvsvc_NetShareAdd(cli
, mem_ctx
,
2244 cli
->srv_name_slash
,
2249 if (!NT_STATUS_IS_OK(status
)) {
2250 res
= W_ERROR_V(ntstatus_to_werror(status
));
2253 if (!W_ERROR_IS_OK(werr
)) {
2254 res
= W_ERROR_V(werr
);
2259 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2263 SSVAL(*rparam
,0,NERR_Success
);
2264 SSVAL(*rparam
,2,0); /* converter word */
2265 SSVAL(*rparam
,4,*rdata_len
);
2273 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2278 SSVAL(*rparam
,0,res
);
2283 /****************************************************************************
2284 view list of groups available
2285 ****************************************************************************/
2287 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2288 char *param
, int tpscnt
,
2289 char *data
, int tdscnt
,
2290 int mdrcnt
,int mprcnt
,
2291 char **rdata
,char **rparam
,
2292 int *rdata_len
,int *rparam_len
)
2296 int resume_context
, cli_buf_size
;
2297 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2298 char *str2
= skip_string(param
,tpscnt
,str1
);
2299 char *p
= skip_string(param
,tpscnt
,str2
);
2301 uint32_t num_groups
;
2302 uint32_t resume_handle
;
2303 struct rpc_pipe_client
*samr_pipe
;
2304 struct policy_handle samr_handle
, domain_handle
;
2307 if (!str1
|| !str2
|| !p
) {
2311 if (strcmp(str1
,"WrLeh") != 0) {
2316 * W-> resume context (number of users to skip)
2317 * r -> return parameter pointer to receive buffer
2318 * L -> length of receive buffer
2319 * e -> return parameter number of entries
2320 * h -> return parameter total number of users
2323 if (strcmp("B21",str2
) != 0) {
2327 status
= rpc_pipe_open_internal(
2328 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2329 conn
->server_info
, &samr_pipe
);
2330 if (!NT_STATUS_IS_OK(status
)) {
2331 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2332 nt_errstr(status
)));
2336 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2337 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2338 if (!NT_STATUS_IS_OK(status
)) {
2339 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2340 nt_errstr(status
)));
2344 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2345 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2346 get_global_sam_sid(), &domain_handle
);
2347 if (!NT_STATUS_IS_OK(status
)) {
2348 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2349 nt_errstr(status
)));
2350 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2354 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2355 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2356 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2357 "%d\n", resume_context
, cli_buf_size
));
2359 *rdata_len
= cli_buf_size
;
2360 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2367 errflags
= NERR_Success
;
2372 struct samr_SamArray
*sam_entries
;
2373 uint32_t num_entries
;
2375 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2380 if (!NT_STATUS_IS_OK(status
)) {
2381 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2382 "%s\n", nt_errstr(status
)));
2386 if (num_entries
== 0) {
2387 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2388 "no entries -- done\n"));
2392 for(i
=0; i
<num_entries
; i
++) {
2395 name
= sam_entries
->entries
[i
].name
.string
;
2397 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2398 /* set overflow error */
2399 DEBUG(3,("overflow on entry %d group %s\n", i
,
2405 /* truncate the name at 21 chars. */
2407 strlcpy(p
, name
, 21);
2408 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2410 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2415 if (errflags
!= NERR_Success
) {
2419 TALLOC_FREE(sam_entries
);
2422 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2423 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2425 *rdata_len
= PTR_DIFF(p
,*rdata
);
2428 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2432 SSVAL(*rparam
, 0, errflags
);
2433 SSVAL(*rparam
, 2, 0); /* converter word */
2434 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2435 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2440 /*******************************************************************
2441 Get groups that a user is a member of.
2442 ******************************************************************/
2444 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2445 char *param
, int tpscnt
,
2446 char *data
, int tdscnt
,
2447 int mdrcnt
,int mprcnt
,
2448 char **rdata
,char **rparam
,
2449 int *rdata_len
,int *rparam_len
)
2451 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2452 char *str2
= skip_string(param
,tpscnt
,str1
);
2453 char *UserName
= skip_string(param
,tpscnt
,str2
);
2454 char *p
= skip_string(param
,tpscnt
,UserName
);
2455 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2456 const char *level_string
;
2462 struct rpc_pipe_client
*samr_pipe
;
2463 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2464 struct lsa_String name
;
2465 struct lsa_Strings names
;
2466 struct samr_Ids type
, rid
;
2467 struct samr_RidWithAttributeArray
*rids
;
2470 if (!str1
|| !str2
|| !UserName
|| !p
) {
2475 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2480 /* check it's a supported varient */
2482 if ( strcmp(str1
,"zWrLeh") != 0 )
2487 level_string
= "B21";
2493 if (strcmp(level_string
,str2
) != 0)
2496 *rdata_len
= mdrcnt
+ 1024;
2497 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2502 SSVAL(*rparam
,0,NERR_Success
);
2503 SSVAL(*rparam
,2,0); /* converter word */
2506 endp
= *rdata
+ *rdata_len
;
2508 status
= rpc_pipe_open_internal(
2509 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2510 conn
->server_info
, &samr_pipe
);
2511 if (!NT_STATUS_IS_OK(status
)) {
2512 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2513 nt_errstr(status
)));
2517 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2518 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2519 if (!NT_STATUS_IS_OK(status
)) {
2520 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2521 nt_errstr(status
)));
2525 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2526 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2527 get_global_sam_sid(), &domain_handle
);
2528 if (!NT_STATUS_IS_OK(status
)) {
2529 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2530 nt_errstr(status
)));
2534 name
.string
= UserName
;
2536 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2537 &domain_handle
, 1, &name
,
2539 if (!NT_STATUS_IS_OK(status
)) {
2540 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2541 nt_errstr(status
)));
2545 if (type
.ids
[0] != SID_NAME_USER
) {
2546 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2547 sid_type_lookup(type
.ids
[0])));
2551 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2553 SAMR_USER_ACCESS_GET_GROUPS
,
2554 rid
.ids
[0], &user_handle
);
2555 if (!NT_STATUS_IS_OK(status
)) {
2556 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2557 nt_errstr(status
)));
2561 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2562 &user_handle
, &rids
);
2563 if (!NT_STATUS_IS_OK(status
)) {
2564 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2565 nt_errstr(status
)));
2569 for (i
=0; i
<rids
->count
; i
++) {
2571 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2573 1, &rids
->rids
[i
].rid
,
2575 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2576 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2582 *rdata_len
= PTR_DIFF(p
,*rdata
);
2584 SSVAL(*rparam
,4,count
); /* is this right?? */
2585 SSVAL(*rparam
,6,count
); /* is this right?? */
2590 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2592 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2594 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2599 /*******************************************************************
2601 ******************************************************************/
2603 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2604 char *param
, int tpscnt
,
2605 char *data
, int tdscnt
,
2606 int mdrcnt
,int mprcnt
,
2607 char **rdata
,char **rparam
,
2608 int *rdata_len
,int *rparam_len
)
2613 int i
, resume_context
, cli_buf_size
;
2614 uint32_t resume_handle
;
2616 struct rpc_pipe_client
*samr_pipe
;
2617 struct policy_handle samr_handle
, domain_handle
;
2620 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2621 char *str2
= skip_string(param
,tpscnt
,str1
);
2622 char *p
= skip_string(param
,tpscnt
,str2
);
2625 if (!str1
|| !str2
|| !p
) {
2629 if (strcmp(str1
,"WrLeh") != 0)
2632 * W-> resume context (number of users to skip)
2633 * r -> return parameter pointer to receive buffer
2634 * L -> length of receive buffer
2635 * e -> return parameter number of entries
2636 * h -> return parameter total number of users
2639 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2640 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2641 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2642 resume_context
, cli_buf_size
));
2645 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2650 /* check it's a supported varient */
2651 if (strcmp("B21",str2
) != 0)
2654 *rdata_len
= cli_buf_size
;
2655 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2661 endp
= *rdata
+ *rdata_len
;
2663 status
= rpc_pipe_open_internal(
2664 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2665 conn
->server_info
, &samr_pipe
);
2666 if (!NT_STATUS_IS_OK(status
)) {
2667 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2668 nt_errstr(status
)));
2672 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2673 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2674 if (!NT_STATUS_IS_OK(status
)) {
2675 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2676 nt_errstr(status
)));
2680 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2681 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2682 get_global_sam_sid(), &domain_handle
);
2683 if (!NT_STATUS_IS_OK(status
)) {
2684 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2685 nt_errstr(status
)));
2686 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2690 errflags
=NERR_Success
;
2695 struct samr_SamArray
*sam_entries
;
2696 uint32_t num_entries
;
2698 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2704 if (!NT_STATUS_IS_OK(status
)) {
2705 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2706 "%s\n", nt_errstr(status
)));
2710 if (num_entries
== 0) {
2711 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2712 "no entries -- done\n"));
2716 for (i
=0; i
<num_entries
; i
++) {
2719 name
= sam_entries
->entries
[i
].name
.string
;
2721 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2722 &&(strlen(name
)<=21)) {
2723 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2724 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2725 "username %s\n",count_sent
,p
));
2729 /* set overflow error */
2730 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2731 "username %s\n",count_sent
,name
));
2737 if (errflags
!= NERR_Success
) {
2741 TALLOC_FREE(sam_entries
);
2744 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2745 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2747 *rdata_len
= PTR_DIFF(p
,*rdata
);
2749 SSVAL(*rparam
,0,errflags
);
2750 SSVAL(*rparam
,2,0); /* converter word */
2751 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2752 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2757 /****************************************************************************
2758 Get the time of day info.
2759 ****************************************************************************/
2761 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2762 char *param
, int tpscnt
,
2763 char *data
, int tdscnt
,
2764 int mdrcnt
,int mprcnt
,
2765 char **rdata
,char **rparam
,
2766 int *rdata_len
,int *rparam_len
)
2769 time_t unixdate
= time(NULL
);
2773 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2779 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2784 SSVAL(*rparam
,0,NERR_Success
);
2785 SSVAL(*rparam
,2,0); /* converter word */
2789 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2790 by NT in a "net time" operation,
2791 it seems to ignore the one below */
2793 /* the client expects to get localtime, not GMT, in this bit
2794 (I think, this needs testing) */
2795 t
= localtime(&unixdate
);
2800 SIVAL(p
,4,0); /* msecs ? */
2801 SCVAL(p
,8,t
->tm_hour
);
2802 SCVAL(p
,9,t
->tm_min
);
2803 SCVAL(p
,10,t
->tm_sec
);
2804 SCVAL(p
,11,0); /* hundredths of seconds */
2805 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2806 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2807 SCVAL(p
,16,t
->tm_mday
);
2808 SCVAL(p
,17,t
->tm_mon
+ 1);
2809 SSVAL(p
,18,1900+t
->tm_year
);
2810 SCVAL(p
,20,t
->tm_wday
);
2815 /****************************************************************************
2816 Set the user password.
2817 *****************************************************************************/
2819 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2820 char *param
, int tpscnt
,
2821 char *data
, int tdscnt
,
2822 int mdrcnt
,int mprcnt
,
2823 char **rdata
,char **rparam
,
2824 int *rdata_len
,int *rparam_len
)
2826 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2829 fstring pass1
,pass2
;
2830 TALLOC_CTX
*mem_ctx
= talloc_tos();
2832 struct rpc_pipe_client
*cli
= NULL
;
2833 struct policy_handle connect_handle
, domain_handle
, user_handle
;
2834 struct lsa_String domain_name
;
2835 struct dom_sid2
*domain_sid
;
2836 struct lsa_String names
;
2837 struct samr_Ids rids
;
2838 struct samr_Ids types
;
2839 struct samr_Password old_lm_hash
;
2840 struct samr_Password new_lm_hash
;
2841 int errcode
= NERR_badpass
;
2846 /* Skip 2 strings. */
2847 p
= skip_string(param
,tpscnt
,np
);
2848 p
= skip_string(param
,tpscnt
,p
);
2854 /* Do we have a string ? */
2855 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2858 pull_ascii_fstring(user
,p
);
2860 p
= skip_string(param
,tpscnt
,p
);
2865 memset(pass1
,'\0',sizeof(pass1
));
2866 memset(pass2
,'\0',sizeof(pass2
));
2868 * We use 31 here not 32 as we're checking
2869 * the last byte we want to access is safe.
2871 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2875 memcpy(pass2
,p
+16,16);
2877 encrypted
= get_safe_SVAL(param
,tpscnt
,p
+32,0,-1);
2878 if (encrypted
== -1) {
2879 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2883 min_pwd_length
= get_safe_SVAL(param
,tpscnt
,p
+34,0,-1);
2884 if (min_pwd_length
== -1) {
2885 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2890 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2897 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2898 user
, encrypted
, min_pwd_length
));
2900 ZERO_STRUCT(connect_handle
);
2901 ZERO_STRUCT(domain_handle
);
2902 ZERO_STRUCT(user_handle
);
2904 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
2905 rpc_samr_dispatch
, conn
->server_info
,
2907 if (!NT_STATUS_IS_OK(status
)) {
2908 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2909 nt_errstr(status
)));
2910 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2914 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
2916 SAMR_ACCESS_CONNECT_TO_SERVER
|
2917 SAMR_ACCESS_ENUM_DOMAINS
|
2918 SAMR_ACCESS_LOOKUP_DOMAIN
,
2920 if (!NT_STATUS_IS_OK(status
)) {
2921 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2925 init_lsa_String(&domain_name
, get_global_sam_name());
2927 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
2931 if (!NT_STATUS_IS_OK(status
)) {
2932 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2936 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
2938 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2941 if (!NT_STATUS_IS_OK(status
)) {
2942 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2946 init_lsa_String(&names
, user
);
2948 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
2954 if (!NT_STATUS_IS_OK(status
)) {
2955 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2959 if (rids
.count
!= 1) {
2960 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
2963 if (rids
.count
!= types
.count
) {
2964 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2967 if (types
.ids
[0] != SID_NAME_USER
) {
2968 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
2974 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
2976 SAMR_USER_ACCESS_CHANGE_PASSWORD
,
2979 if (!NT_STATUS_IS_OK(status
)) {
2980 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
2984 if (encrypted
== 0) {
2985 E_deshash(pass1
, old_lm_hash
.hash
);
2986 E_deshash(pass2
, new_lm_hash
.hash
);
2988 ZERO_STRUCT(old_lm_hash
);
2989 ZERO_STRUCT(new_lm_hash
);
2990 memcpy(old_lm_hash
.hash
, pass1
, MIN(strlen(pass1
), 16));
2991 memcpy(new_lm_hash
.hash
, pass1
, MIN(strlen(pass2
), 16));
2994 status
= rpccli_samr_ChangePasswordUser(cli
, mem_ctx
,
2996 true, /* lm_present */
2999 false, /* nt_present */
3000 NULL
, /* old_nt_crypted */
3001 NULL
, /* new_nt_crypted */
3002 false, /* cross1_present */
3003 NULL
, /* nt_cross */
3004 false, /* cross2_present */
3005 NULL
); /* lm_cross */
3006 if (!NT_STATUS_IS_OK(status
)) {
3007 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3011 errcode
= NERR_Success
;
3014 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
3015 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
3017 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
3018 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
3020 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
3021 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
3024 memset((char *)pass1
,'\0',sizeof(fstring
));
3025 memset((char *)pass2
,'\0',sizeof(fstring
));
3027 SSVAL(*rparam
,0,errcode
);
3028 SSVAL(*rparam
,2,0); /* converter word */
3032 /****************************************************************************
3033 Set the user password (SamOEM version - gets plaintext).
3034 ****************************************************************************/
3036 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
3037 char *param
, int tpscnt
,
3038 char *data
, int tdscnt
,
3039 int mdrcnt
,int mprcnt
,
3040 char **rdata
,char **rparam
,
3041 int *rdata_len
,int *rparam_len
)
3044 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3046 TALLOC_CTX
*mem_ctx
= talloc_tos();
3048 struct rpc_pipe_client
*cli
= NULL
;
3049 struct lsa_AsciiString server
, account
;
3050 struct samr_CryptPassword password
;
3051 struct samr_Password hash
;
3052 int errcode
= NERR_badpass
;
3056 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3066 SSVAL(*rparam
,0,NERR_badpass
);
3069 * Check the parameter definition is correct.
3072 /* Do we have a string ? */
3073 if (skip_string(param
,tpscnt
,p
) == 0) {
3076 if(!strequal(p
, "zsT")) {
3077 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3080 p
= skip_string(param
, tpscnt
, p
);
3085 /* Do we have a string ? */
3086 if (skip_string(param
,tpscnt
,p
) == 0) {
3089 if(!strequal(p
, "B516B16")) {
3090 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3093 p
= skip_string(param
,tpscnt
,p
);
3097 /* Do we have a string ? */
3098 if (skip_string(param
,tpscnt
,p
) == 0) {
3101 p
+= pull_ascii_fstring(user
,p
);
3103 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3105 if (tdscnt
!= 532) {
3106 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3110 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3111 if (bufsize
!= 532) {
3112 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3116 memcpy(password
.data
, data
, 516);
3117 memcpy(hash
.hash
, data
+516, 16);
3119 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3120 rpc_samr_dispatch
, conn
->server_info
,
3122 if (!NT_STATUS_IS_OK(status
)) {
3123 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3124 nt_errstr(status
)));
3125 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3129 init_lsa_AsciiString(&server
, global_myname());
3130 init_lsa_AsciiString(&account
, user
);
3132 status
= rpccli_samr_OemChangePasswordUser2(cli
, mem_ctx
,
3137 if (!NT_STATUS_IS_OK(status
)) {
3138 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3142 errcode
= NERR_Success
;
3144 SSVAL(*rparam
,0,errcode
);
3145 SSVAL(*rparam
,2,0); /* converter word */
3150 /****************************************************************************
3153 ****************************************************************************/
3155 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
3156 char *param
, int tpscnt
,
3157 char *data
, int tdscnt
,
3158 int mdrcnt
,int mprcnt
,
3159 char **rdata
,char **rparam
,
3160 int *rdata_len
,int *rparam_len
)
3162 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3163 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3164 char *str2
= skip_string(param
,tpscnt
,str1
);
3165 char *p
= skip_string(param
,tpscnt
,str2
);
3169 WERROR werr
= WERR_OK
;
3171 TALLOC_CTX
*mem_ctx
= talloc_tos();
3173 struct rpc_pipe_client
*cli
= NULL
;
3174 struct policy_handle handle
;
3175 struct spoolss_DevmodeContainer devmode_ctr
;
3176 enum spoolss_JobControl command
;
3178 if (!str1
|| !str2
|| !p
) {
3182 * We use 1 here not 2 as we're checking
3183 * the last byte we want to access is safe.
3185 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3188 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3191 /* check it's a supported varient */
3192 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3196 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3202 ZERO_STRUCT(handle
);
3204 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3205 if (!NT_STATUS_IS_OK(status
)) {
3206 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3207 nt_errstr(status
)));
3208 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3212 ZERO_STRUCT(devmode_ctr
);
3214 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3218 JOB_ACCESS_ADMINISTER
,
3221 if (!NT_STATUS_IS_OK(status
)) {
3222 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3225 if (!W_ERROR_IS_OK(werr
)) {
3226 errcode
= W_ERROR_V(werr
);
3230 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3231 * and NERR_DestNotFound if share did not exist */
3233 errcode
= NERR_Success
;
3236 case 81: /* delete */
3237 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3239 case 82: /* pause */
3240 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3242 case 83: /* resume */
3243 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3246 errcode
= NERR_notsupported
;
3250 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3253 NULL
, /* unique ptr ctr */
3256 if (!NT_STATUS_IS_OK(status
)) {
3257 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3260 if (!W_ERROR_IS_OK(werr
)) {
3261 errcode
= W_ERROR_V(werr
);
3266 if (cli
&& is_valid_policy_hnd(&handle
)) {
3267 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3270 SSVAL(*rparam
,0,errcode
);
3271 SSVAL(*rparam
,2,0); /* converter word */
3276 /****************************************************************************
3277 Purge a print queue - or pause or resume it.
3278 ****************************************************************************/
3280 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
3281 char *param
, int tpscnt
,
3282 char *data
, int tdscnt
,
3283 int mdrcnt
,int mprcnt
,
3284 char **rdata
,char **rparam
,
3285 int *rdata_len
,int *rparam_len
)
3287 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3288 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3289 char *str2
= skip_string(param
,tpscnt
,str1
);
3290 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3291 int errcode
= NERR_notsupported
;
3292 WERROR werr
= WERR_OK
;
3295 TALLOC_CTX
*mem_ctx
= talloc_tos();
3296 struct rpc_pipe_client
*cli
= NULL
;
3297 struct policy_handle handle
;
3298 struct spoolss_SetPrinterInfoCtr info_ctr
;
3299 struct spoolss_DevmodeContainer devmode_ctr
;
3300 struct sec_desc_buf secdesc_ctr
;
3301 enum spoolss_PrinterControl command
;
3303 if (!str1
|| !str2
|| !QueueName
) {
3307 /* check it's a supported varient */
3308 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3312 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3318 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3322 ZERO_STRUCT(handle
);
3324 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3325 if (!NT_STATUS_IS_OK(status
)) {
3326 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3327 nt_errstr(status
)));
3328 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3332 ZERO_STRUCT(devmode_ctr
);
3334 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3338 SEC_FLAG_MAXIMUM_ALLOWED
,
3341 if (!NT_STATUS_IS_OK(status
)) {
3342 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3345 if (!W_ERROR_IS_OK(werr
)) {
3346 errcode
= W_ERROR_V(werr
);
3351 case 74: /* Pause queue */
3352 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3354 case 75: /* Resume queue */
3355 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3357 case 103: /* Purge */
3358 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3361 werr
= WERR_NOT_SUPPORTED
;
3365 if (!W_ERROR_IS_OK(werr
)) {
3366 errcode
= W_ERROR_V(werr
);
3370 ZERO_STRUCT(info_ctr
);
3371 ZERO_STRUCT(secdesc_ctr
);
3373 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3380 if (!NT_STATUS_IS_OK(status
)) {
3381 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3384 if (!W_ERROR_IS_OK(werr
)) {
3385 errcode
= W_ERROR_V(werr
);
3389 errcode
= W_ERROR_V(werr
);
3393 if (cli
&& is_valid_policy_hnd(&handle
)) {
3394 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3397 SSVAL(*rparam
,0,errcode
);
3398 SSVAL(*rparam
,2,0); /* converter word */
3403 /****************************************************************************
3404 set the property of a print job (undocumented?)
3405 ? function = 0xb -> set name of print job
3406 ? function = 0x6 -> move print job up/down
3407 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3408 or <WWsTP> <WB21BB16B10zWWzDDz>
3409 ****************************************************************************/
3411 static int check_printjob_info(struct pack_desc
* desc
,
3412 int uLevel
, char* id
)
3414 desc
->subformat
= NULL
;
3416 case 0: desc
->format
= "W"; break;
3417 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3418 case 2: desc
->format
= "WWzWWDDzz"; break;
3419 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3420 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3422 DEBUG(0,("check_printjob_info: invalid level %d\n",
3426 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3427 DEBUG(0,("check_printjob_info: invalid format %s\n",
3428 id
? id
: "<NULL>" ));
3434 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
3435 char *param
, int tpscnt
,
3436 char *data
, int tdscnt
,
3437 int mdrcnt
,int mprcnt
,
3438 char **rdata
,char **rparam
,
3439 int *rdata_len
,int *rparam_len
)
3441 struct pack_desc desc
;
3442 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3443 char *str2
= skip_string(param
,tpscnt
,str1
);
3444 char *p
= skip_string(param
,tpscnt
,str2
);
3447 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3448 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3451 TALLOC_CTX
*mem_ctx
= talloc_tos();
3454 struct rpc_pipe_client
*cli
= NULL
;
3455 struct policy_handle handle
;
3456 struct spoolss_DevmodeContainer devmode_ctr
;
3457 struct spoolss_JobInfoContainer ctr
;
3458 union spoolss_JobInfo info
;
3459 struct spoolss_SetJobInfo1 info1
;
3461 if (!str1
|| !str2
|| !p
) {
3465 * We use 1 here not 2 as we're checking
3466 * the last byte we want to access is safe.
3468 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3471 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3474 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3481 /* check it's a supported varient */
3482 if ((strcmp(str1
,"WWsTP")) ||
3483 (!check_printjob_info(&desc
,uLevel
,str2
)))
3486 errcode
= NERR_notsupported
;
3490 /* change print job name, data gives the name */
3496 ZERO_STRUCT(handle
);
3498 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3499 if (!NT_STATUS_IS_OK(status
)) {
3500 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3501 nt_errstr(status
)));
3502 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3506 ZERO_STRUCT(devmode_ctr
);
3508 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3515 if (!NT_STATUS_IS_OK(status
)) {
3516 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3519 if (!W_ERROR_IS_OK(werr
)) {
3520 errcode
= W_ERROR_V(werr
);
3524 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3530 if (!W_ERROR_IS_OK(werr
)) {
3531 errcode
= W_ERROR_V(werr
);
3537 info1
.job_id
= info
.info1
.job_id
;
3538 info1
.printer_name
= info
.info1
.printer_name
;
3539 info1
.user_name
= info
.info1
.user_name
;
3540 info1
.document_name
= data
;
3541 info1
.data_type
= info
.info1
.data_type
;
3542 info1
.text_status
= info
.info1
.text_status
;
3543 info1
.status
= info
.info1
.status
;
3544 info1
.priority
= info
.info1
.priority
;
3545 info1
.position
= info
.info1
.position
;
3546 info1
.total_pages
= info
.info1
.total_pages
;
3547 info1
.pages_printed
= info
.info1
.pages_printed
;
3548 info1
.submitted
= info
.info1
.submitted
;
3551 ctr
.info
.info1
= &info1
;
3553 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3559 if (!NT_STATUS_IS_OK(status
)) {
3560 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3563 if (!W_ERROR_IS_OK(werr
)) {
3564 errcode
= W_ERROR_V(werr
);
3568 errcode
= NERR_Success
;
3571 if (cli
&& is_valid_policy_hnd(&handle
)) {
3572 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3575 SSVALS(*rparam
,0,errcode
);
3576 SSVAL(*rparam
,2,0); /* converter word */
3582 /****************************************************************************
3583 Get info about the server.
3584 ****************************************************************************/
3586 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3587 char *param
, int tpscnt
,
3588 char *data
, int tdscnt
,
3589 int mdrcnt
,int mprcnt
,
3590 char **rdata
,char **rparam
,
3591 int *rdata_len
,int *rparam_len
)
3593 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3594 char *str2
= skip_string(param
,tpscnt
,str1
);
3595 char *p
= skip_string(param
,tpscnt
,str2
);
3596 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3602 TALLOC_CTX
*mem_ctx
= talloc_tos();
3603 struct rpc_pipe_client
*cli
= NULL
;
3604 union srvsvc_NetSrvInfo info
;
3607 if (!str1
|| !str2
|| !p
) {
3611 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3613 /* check it's a supported varient */
3614 if (!prefix_ok(str1
,"WrLh")) {
3620 if (strcmp(str2
,"B16") != 0) {
3626 if (strcmp(str2
,"B16BBDz") != 0) {
3632 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3638 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3644 if (strcmp(str2
,"DN") != 0) {
3650 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3659 *rdata_len
= mdrcnt
;
3660 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3666 p2
= p
+ struct_len
;
3668 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3669 rpc_srvsvc_dispatch
, conn
->server_info
,
3671 if (!NT_STATUS_IS_OK(status
)) {
3672 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3673 nt_errstr(status
)));
3674 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3678 status
= rpccli_srvsvc_NetSrvGetInfo(cli
, mem_ctx
,
3683 if (!NT_STATUS_IS_OK(status
)) {
3684 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3687 if (!W_ERROR_IS_OK(werr
)) {
3688 errcode
= W_ERROR_V(werr
);
3692 if (info
.info101
== NULL
) {
3693 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3698 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3699 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3703 SCVAL(p
,0,info
.info101
->version_major
);
3704 SCVAL(p
,1,info
.info101
->version_minor
);
3705 SIVAL(p
,2,info
.info101
->server_type
);
3707 if (mdrcnt
== struct_len
) {
3710 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3711 if (mdrcnt
- struct_len
<= 0) {
3715 info
.info101
->comment
,
3716 MIN(mdrcnt
- struct_len
,
3717 MAX_SERVER_STRING_LENGTH
),
3719 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3727 return False
; /* not yet implemented */
3730 errcode
= NERR_Success
;
3734 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3737 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3741 SSVAL(*rparam
,0,errcode
);
3742 SSVAL(*rparam
,2,0); /* converter word */
3743 SSVAL(*rparam
,4,*rdata_len
);
3748 /****************************************************************************
3749 Get info about the server.
3750 ****************************************************************************/
3752 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3753 char *param
, int tpscnt
,
3754 char *data
, int tdscnt
,
3755 int mdrcnt
,int mprcnt
,
3756 char **rdata
,char **rparam
,
3757 int *rdata_len
,int *rparam_len
)
3759 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3760 char *str2
= skip_string(param
,tpscnt
,str1
);
3761 char *p
= skip_string(param
,tpscnt
,str2
);
3764 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3766 if (!str1
|| !str2
|| !p
) {
3770 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3773 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3778 /* check it's a supported varient */
3779 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3783 *rdata_len
= mdrcnt
+ 1024;
3784 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3789 SSVAL(*rparam
,0,NERR_Success
);
3790 SSVAL(*rparam
,2,0); /* converter word */
3793 endp
= *rdata
+ *rdata_len
;
3795 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3800 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3801 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3803 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3809 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3810 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3811 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3817 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3818 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3820 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3826 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3827 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3830 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3831 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3832 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3838 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3839 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3840 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3846 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3848 SSVAL(*rparam
,4,*rdata_len
);
3853 /****************************************************************************
3854 get info about a user
3856 struct user_info_11 {
3857 char usri11_name[21]; 0-20
3859 char *usri11_comment; 22-25
3860 char *usri11_usr_comment; 26-29
3861 unsigned short usri11_priv; 30-31
3862 unsigned long usri11_auth_flags; 32-35
3863 long usri11_password_age; 36-39
3864 char *usri11_homedir; 40-43
3865 char *usri11_parms; 44-47
3866 long usri11_last_logon; 48-51
3867 long usri11_last_logoff; 52-55
3868 unsigned short usri11_bad_pw_count; 56-57
3869 unsigned short usri11_num_logons; 58-59
3870 char *usri11_logon_server; 60-63
3871 unsigned short usri11_country_code; 64-65
3872 char *usri11_workstations; 66-69
3873 unsigned long usri11_max_storage; 70-73
3874 unsigned short usri11_units_per_week; 74-75
3875 unsigned char *usri11_logon_hours; 76-79
3876 unsigned short usri11_code_page; 80-81
3881 usri11_name specifies the user name for which information is retrieved
3883 usri11_pad aligns the next data structure element to a word boundary
3885 usri11_comment is a null terminated ASCII comment
3887 usri11_user_comment is a null terminated ASCII comment about the user
3889 usri11_priv specifies the level of the privilege assigned to the user.
3890 The possible values are:
3892 Name Value Description
3893 USER_PRIV_GUEST 0 Guest privilege
3894 USER_PRIV_USER 1 User privilege
3895 USER_PRV_ADMIN 2 Administrator privilege
3897 usri11_auth_flags specifies the account operator privileges. The
3898 possible values are:
3900 Name Value Description
3901 AF_OP_PRINT 0 Print operator
3904 Leach, Naik [Page 28]
3908 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3911 AF_OP_COMM 1 Communications operator
3912 AF_OP_SERVER 2 Server operator
3913 AF_OP_ACCOUNTS 3 Accounts operator
3916 usri11_password_age specifies how many seconds have elapsed since the
3917 password was last changed.
3919 usri11_home_dir points to a null terminated ASCII string that contains
3920 the path name of the user's home directory.
3922 usri11_parms points to a null terminated ASCII string that is set
3923 aside for use by applications.
3925 usri11_last_logon specifies the time when the user last logged on.
3926 This value is stored as the number of seconds elapsed since
3927 00:00:00, January 1, 1970.
3929 usri11_last_logoff specifies the time when the user last logged off.
3930 This value is stored as the number of seconds elapsed since
3931 00:00:00, January 1, 1970. A value of 0 means the last logoff
3934 usri11_bad_pw_count specifies the number of incorrect passwords
3935 entered since the last successful logon.
3937 usri11_log1_num_logons specifies the number of times this user has
3938 logged on. A value of -1 means the number of logons is unknown.
3940 usri11_logon_server points to a null terminated ASCII string that
3941 contains the name of the server to which logon requests are sent.
3942 A null string indicates logon requests should be sent to the
3945 usri11_country_code specifies the country code for the user's language
3948 usri11_workstations points to a null terminated ASCII string that
3949 contains the names of workstations the user may log on from.
3950 There may be up to 8 workstations, with the names separated by
3951 commas. A null strings indicates there are no restrictions.
3953 usri11_max_storage specifies the maximum amount of disk space the user
3954 can occupy. A value of 0xffffffff indicates there are no
3957 usri11_units_per_week specifies the equal number of time units into
3958 which a week is divided. This value must be equal to 168.
3960 usri11_logon_hours points to a 21 byte (168 bits) string that
3961 specifies the time during which the user can log on. Each bit
3962 represents one unique hour in a week. The first bit (bit 0, word
3963 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3967 Leach, Naik [Page 29]
3971 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3974 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3975 are no restrictions.
3977 usri11_code_page specifies the code page for the user's language of
3980 All of the pointers in this data structure need to be treated
3981 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3982 to be ignored. The converter word returned in the parameters section
3983 needs to be subtracted from the lower 16 bits to calculate an offset
3984 into the return buffer where this ASCII string resides.
3986 There is no auxiliary data in the response.
3988 ****************************************************************************/
3990 #define usri11_name 0
3991 #define usri11_pad 21
3992 #define usri11_comment 22
3993 #define usri11_usr_comment 26
3994 #define usri11_full_name 30
3995 #define usri11_priv 34
3996 #define usri11_auth_flags 36
3997 #define usri11_password_age 40
3998 #define usri11_homedir 44
3999 #define usri11_parms 48
4000 #define usri11_last_logon 52
4001 #define usri11_last_logoff 56
4002 #define usri11_bad_pw_count 60
4003 #define usri11_num_logons 62
4004 #define usri11_logon_server 64
4005 #define usri11_country_code 68
4006 #define usri11_workstations 70
4007 #define usri11_max_storage 74
4008 #define usri11_units_per_week 78
4009 #define usri11_logon_hours 80
4010 #define usri11_code_page 84
4011 #define usri11_end 86
4013 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
4014 char *param
, int tpscnt
,
4015 char *data
, int tdscnt
,
4016 int mdrcnt
,int mprcnt
,
4017 char **rdata
,char **rparam
,
4018 int *rdata_len
,int *rparam_len
)
4020 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4021 char *str2
= skip_string(param
,tpscnt
,str1
);
4022 char *UserName
= skip_string(param
,tpscnt
,str2
);
4023 char *p
= skip_string(param
,tpscnt
,UserName
);
4024 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4027 const char *level_string
;
4029 TALLOC_CTX
*mem_ctx
= talloc_tos();
4031 struct rpc_pipe_client
*cli
= NULL
;
4032 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4033 struct lsa_String domain_name
;
4034 struct dom_sid2
*domain_sid
;
4035 struct lsa_String names
;
4036 struct samr_Ids rids
;
4037 struct samr_Ids types
;
4038 int errcode
= W_ERROR_V(WERR_USER_NOT_FOUND
);
4040 union samr_UserInfo
*info
;
4042 if (!str1
|| !str2
|| !UserName
|| !p
) {
4047 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4052 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4054 /* check it's a supported variant */
4055 if (strcmp(str1
,"zWrLh") != 0) {
4059 case 0: level_string
= "B21"; break;
4060 case 1: level_string
= "B21BB16DWzzWz"; break;
4061 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4062 case 10: level_string
= "B21Bzzz"; break;
4063 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4064 default: return False
;
4067 if (strcmp(level_string
,str2
) != 0) {
4071 *rdata_len
= mdrcnt
+ 1024;
4072 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4078 endp
= *rdata
+ *rdata_len
;
4079 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4084 ZERO_STRUCT(connect_handle
);
4085 ZERO_STRUCT(domain_handle
);
4086 ZERO_STRUCT(user_handle
);
4088 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
4089 rpc_samr_dispatch
, conn
->server_info
,
4091 if (!NT_STATUS_IS_OK(status
)) {
4092 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4093 nt_errstr(status
)));
4094 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4098 status
= rpccli_samr_Connect2(cli
, mem_ctx
,
4100 SAMR_ACCESS_CONNECT_TO_SERVER
|
4101 SAMR_ACCESS_ENUM_DOMAINS
|
4102 SAMR_ACCESS_LOOKUP_DOMAIN
,
4104 if (!NT_STATUS_IS_OK(status
)) {
4105 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4109 init_lsa_String(&domain_name
, get_global_sam_name());
4111 status
= rpccli_samr_LookupDomain(cli
, mem_ctx
,
4115 if (!NT_STATUS_IS_OK(status
)) {
4116 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4120 status
= rpccli_samr_OpenDomain(cli
, mem_ctx
,
4122 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4125 if (!NT_STATUS_IS_OK(status
)) {
4126 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4130 init_lsa_String(&names
, UserName
);
4132 status
= rpccli_samr_LookupNames(cli
, mem_ctx
,
4138 if (!NT_STATUS_IS_OK(status
)) {
4139 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4143 if (rids
.count
!= 1) {
4144 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4147 if (rids
.count
!= types
.count
) {
4148 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4151 if (types
.ids
[0] != SID_NAME_USER
) {
4152 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
4158 status
= rpccli_samr_OpenUser(cli
, mem_ctx
,
4160 SAMR_USER_ACCESS_GET_LOCALE
|
4161 SAMR_USER_ACCESS_GET_LOGONINFO
|
4162 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4163 SAMR_USER_ACCESS_GET_GROUPS
|
4164 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4165 SEC_STD_READ_CONTROL
,
4168 if (!NT_STATUS_IS_OK(status
)) {
4169 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4173 status
= rpccli_samr_QueryUserInfo2(cli
, mem_ctx
,
4177 if (!NT_STATUS_IS_OK(status
)) {
4178 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4183 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4186 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4191 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4192 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4193 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4198 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4199 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4200 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4205 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4206 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4207 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4208 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4215 const char *homedir
= info
->info21
.home_directory
.string
;
4216 /* modelled after NTAS 3.51 reply */
4217 SSVAL(p
,usri11_priv
,
4218 (get_current_uid(conn
) == sec_initial_uid())?
4219 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4220 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4221 SIVALS(p
,usri11_password_age
,-1); /* password age */
4222 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4223 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4224 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4228 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4229 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4230 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4234 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4235 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4236 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4237 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4238 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4239 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4240 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4244 SSVAL(p
,usri11_country_code
,0); /* country code */
4246 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4247 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4248 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4253 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4254 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4255 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4257 /* a simple way to get logon hours at all times. */
4259 SCVAL(p2
,21,0); /* fix zero termination */
4260 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4265 SSVAL(p
,usri11_code_page
,0); /* code page */
4268 if (uLevel
== 1 || uLevel
== 2) {
4269 memset(p
+22,' ',16); /* password */
4270 SIVALS(p
,38,-1); /* password age */
4272 (get_current_uid(conn
) == sec_initial_uid())?
4273 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4274 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4275 strlcpy(p2
, info
->info21
.home_directory
.string
,
4277 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4281 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4283 SSVAL(p
,52,0); /* flags */
4284 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4285 strlcpy(p2
, info
->info21
.logon_script
.string
,
4287 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4292 SIVAL(p
,58,0); /* auth_flags */
4293 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4294 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4295 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4299 SIVAL(p
,66,0); /* urs_comment */
4300 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4301 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4302 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4306 SIVAL(p
,74,0); /* workstations */
4307 SIVAL(p
,78,0); /* last_logon */
4308 SIVAL(p
,82,0); /* last_logoff */
4309 SIVALS(p
,86,-1); /* acct_expires */
4310 SIVALS(p
,90,-1); /* max_storage */
4311 SSVAL(p
,94,168); /* units_per_week */
4312 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4315 SSVALS(p
,100,-1); /* bad_pw_count */
4316 SSVALS(p
,102,-1); /* num_logons */
4317 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4319 TALLOC_CTX
*ctx
= talloc_tos();
4320 int space_rem
= *rdata_len
- (p2
- *rdata
);
4323 if (space_rem
<= 0) {
4326 tmp
= talloc_strdup(ctx
, "\\\\%L");
4330 tmp
= talloc_sub_basic(ctx
,
4343 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4347 SSVAL(p
,108,49); /* country_code */
4348 SSVAL(p
,110,860); /* code page */
4352 errcode
= NERR_Success
;
4355 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4357 if (cli
&& is_valid_policy_hnd(&user_handle
)) {
4358 rpccli_samr_Close(cli
, mem_ctx
, &user_handle
);
4360 if (cli
&& is_valid_policy_hnd(&domain_handle
)) {
4361 rpccli_samr_Close(cli
, mem_ctx
, &domain_handle
);
4363 if (cli
&& is_valid_policy_hnd(&connect_handle
)) {
4364 rpccli_samr_Close(cli
, mem_ctx
, &connect_handle
);
4367 SSVAL(*rparam
,0,errcode
);
4368 SSVAL(*rparam
,2,0); /* converter word */
4369 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4374 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
4375 char *param
, int tpscnt
,
4376 char *data
, int tdscnt
,
4377 int mdrcnt
,int mprcnt
,
4378 char **rdata
,char **rparam
,
4379 int *rdata_len
,int *rparam_len
)
4381 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4382 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4383 char *str2
= skip_string(param
,tpscnt
,str1
);
4384 char *p
= skip_string(param
,tpscnt
,str2
);
4386 struct pack_desc desc
;
4388 /* With share level security vuid will always be zero.
4389 Don't depend on vuser being non-null !!. JRA */
4390 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4392 if (!str1
|| !str2
|| !p
) {
4397 DEBUG(3,(" Username of UID %d is %s\n",
4398 (int)vuser
->server_info
->utok
.uid
,
4399 vuser
->server_info
->unix_name
));
4402 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4403 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4408 memset((char *)&desc
,'\0',sizeof(desc
));
4410 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4412 /* check it's a supported varient */
4413 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4416 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4420 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4427 desc
.buflen
= mdrcnt
;
4428 desc
.subformat
= NULL
;
4431 if (init_package(&desc
,1,0)) {
4432 PACKI(&desc
,"W",0); /* code */
4433 PACKS(&desc
,"B21",name
); /* eff. name */
4434 PACKS(&desc
,"B",""); /* pad */
4436 (get_current_uid(conn
) == sec_initial_uid())?
4437 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4438 PACKI(&desc
,"D",0); /* auth flags XXX */
4439 PACKI(&desc
,"W",0); /* num logons */
4440 PACKI(&desc
,"W",0); /* bad pw count */
4441 PACKI(&desc
,"D",0); /* last logon */
4442 PACKI(&desc
,"D",-1); /* last logoff */
4443 PACKI(&desc
,"D",-1); /* logoff time */
4444 PACKI(&desc
,"D",-1); /* kickoff time */
4445 PACKI(&desc
,"D",0); /* password age */
4446 PACKI(&desc
,"D",0); /* password can change */
4447 PACKI(&desc
,"D",-1); /* password must change */
4451 fstrcpy(mypath
,"\\\\");
4452 fstrcat(mypath
,get_local_machine_name());
4454 PACKS(&desc
,"z",mypath
); /* computer */
4457 PACKS(&desc
,"z",lp_workgroup());/* domain */
4458 PACKS(&desc
,"z", vuser
?
4459 vuser
->server_info
->info3
->base
.logon_script
.string
4460 : ""); /* script path */
4461 PACKI(&desc
,"D",0x00000000); /* reserved */
4464 *rdata_len
= desc
.usedlen
;
4466 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4470 SSVALS(*rparam
,0,desc
.errcode
);
4472 SSVAL(*rparam
,4,desc
.neededlen
);
4474 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4479 /****************************************************************************
4480 api_WAccessGetUserPerms
4481 ****************************************************************************/
4483 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
4484 char *param
, int tpscnt
,
4485 char *data
, int tdscnt
,
4486 int mdrcnt
,int mprcnt
,
4487 char **rdata
,char **rparam
,
4488 int *rdata_len
,int *rparam_len
)
4490 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4491 char *str2
= skip_string(param
,tpscnt
,str1
);
4492 char *user
= skip_string(param
,tpscnt
,str2
);
4493 char *resource
= skip_string(param
,tpscnt
,user
);
4495 if (!str1
|| !str2
|| !user
|| !resource
) {
4499 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4502 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4504 /* check it's a supported varient */
4505 if (strcmp(str1
,"zzh") != 0) {
4508 if (strcmp(str2
,"") != 0) {
4513 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4517 SSVALS(*rparam
,0,0); /* errorcode */
4518 SSVAL(*rparam
,2,0); /* converter word */
4519 SSVAL(*rparam
,4,0x7f); /* permission flags */
4524 /****************************************************************************
4525 api_WPrintJobEnumerate
4526 ****************************************************************************/
4528 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
4529 char *param
, int tpscnt
,
4530 char *data
, int tdscnt
,
4531 int mdrcnt
,int mprcnt
,
4532 char **rdata
,char **rparam
,
4533 int *rdata_len
,int *rparam_len
)
4535 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4536 char *str2
= skip_string(param
,tpscnt
,str1
);
4537 char *p
= skip_string(param
,tpscnt
,str2
);
4541 struct pack_desc desc
;
4544 TALLOC_CTX
*mem_ctx
= talloc_tos();
4547 struct rpc_pipe_client
*cli
= NULL
;
4548 struct policy_handle handle
;
4549 struct spoolss_DevmodeContainer devmode_ctr
;
4550 union spoolss_JobInfo info
;
4552 if (!str1
|| !str2
|| !p
) {
4556 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4558 memset((char *)&desc
,'\0',sizeof(desc
));
4559 memset((char *)&status
,'\0',sizeof(status
));
4561 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4563 /* check it's a supported varient */
4564 if (strcmp(str1
,"WWrLh") != 0) {
4567 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4571 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4575 ZERO_STRUCT(handle
);
4577 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4578 if (!NT_STATUS_IS_OK(status
)) {
4579 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4580 nt_errstr(status
)));
4581 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4585 ZERO_STRUCT(devmode_ctr
);
4587 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4594 if (!NT_STATUS_IS_OK(status
)) {
4595 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4598 if (!W_ERROR_IS_OK(werr
)) {
4599 desc
.errcode
= W_ERROR_V(werr
);
4603 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4609 if (!W_ERROR_IS_OK(werr
)) {
4610 desc
.errcode
= W_ERROR_V(werr
);
4615 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4620 desc
.buflen
= mdrcnt
;
4623 * Don't return data but need to get correct length
4624 * init_package will return wrong size if buflen=0
4626 desc
.buflen
= getlen(desc
.format
);
4627 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4630 if (init_package(&desc
,1,0)) {
4631 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4632 *rdata_len
= desc
.usedlen
;
4634 desc
.errcode
= NERR_JobNotFound
;
4638 if (cli
&& is_valid_policy_hnd(&handle
)) {
4639 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4643 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4647 SSVALS(*rparam
,0,desc
.errcode
);
4649 SSVAL(*rparam
,4,desc
.neededlen
);
4653 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4658 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
4659 char *param
, int tpscnt
,
4660 char *data
, int tdscnt
,
4661 int mdrcnt
,int mprcnt
,
4662 char **rdata
,char **rparam
,
4663 int *rdata_len
,int *rparam_len
)
4665 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4666 char *str2
= skip_string(param
,tpscnt
,str1
);
4667 char *p
= skip_string(param
,tpscnt
,str2
);
4671 struct pack_desc desc
;
4673 TALLOC_CTX
*mem_ctx
= talloc_tos();
4676 struct rpc_pipe_client
*cli
= NULL
;
4677 struct policy_handle handle
;
4678 struct spoolss_DevmodeContainer devmode_ctr
;
4680 union spoolss_JobInfo
*info
;
4682 if (!str1
|| !str2
|| !p
) {
4686 memset((char *)&desc
,'\0',sizeof(desc
));
4688 p
= skip_string(param
,tpscnt
,p
);
4692 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4694 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4696 /* check it's a supported variant */
4697 if (strcmp(str1
,"zWrLeh") != 0) {
4702 return False
; /* defined only for uLevel 0,1,2 */
4705 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4709 ZERO_STRUCT(handle
);
4711 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4712 if (!NT_STATUS_IS_OK(status
)) {
4713 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4714 nt_errstr(status
)));
4715 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4719 ZERO_STRUCT(devmode_ctr
);
4721 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4725 SEC_FLAG_MAXIMUM_ALLOWED
,
4728 if (!NT_STATUS_IS_OK(status
)) {
4729 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4732 if (!W_ERROR_IS_OK(werr
)) {
4733 desc
.errcode
= W_ERROR_V(werr
);
4737 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4745 if (!W_ERROR_IS_OK(werr
)) {
4746 desc
.errcode
= W_ERROR_V(werr
);
4751 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4757 desc
.buflen
= mdrcnt
;
4759 if (init_package(&desc
,count
,0)) {
4761 for (i
= 0; i
< count
; i
++) {
4762 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4763 if (desc
.errcode
== NERR_Success
) {
4769 if (cli
&& is_valid_policy_hnd(&handle
)) {
4770 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4773 *rdata_len
= desc
.usedlen
;
4776 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4780 SSVALS(*rparam
,0,desc
.errcode
);
4782 SSVAL(*rparam
,4,succnt
);
4783 SSVAL(*rparam
,6,count
);
4785 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4790 static int check_printdest_info(struct pack_desc
* desc
,
4791 int uLevel
, char* id
)
4793 desc
->subformat
= NULL
;
4796 desc
->format
= "B9";
4799 desc
->format
= "B9B21WWzW";
4805 desc
->format
= "zzzWWzzzWW";
4808 DEBUG(0,("check_printdest_info: invalid level %d\n",
4812 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4813 DEBUG(0,("check_printdest_info: invalid string %s\n",
4814 id
? id
: "<NULL>" ));
4820 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4821 struct pack_desc
* desc
)
4825 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4826 buf
[sizeof(buf
)-1] = 0;
4830 PACKS(desc
,"B9",buf
); /* szName */
4832 PACKS(desc
,"B21",""); /* szUserName */
4833 PACKI(desc
,"W",0); /* uJobId */
4834 PACKI(desc
,"W",0); /* fsStatus */
4835 PACKS(desc
,"z",""); /* pszStatus */
4836 PACKI(desc
,"W",0); /* time */
4840 if (uLevel
== 2 || uLevel
== 3) {
4841 PACKS(desc
,"z",buf
); /* pszPrinterName */
4843 PACKS(desc
,"z",""); /* pszUserName */
4844 PACKS(desc
,"z",""); /* pszLogAddr */
4845 PACKI(desc
,"W",0); /* uJobId */
4846 PACKI(desc
,"W",0); /* fsStatus */
4847 PACKS(desc
,"z",""); /* pszStatus */
4848 PACKS(desc
,"z",""); /* pszComment */
4849 PACKS(desc
,"z","NULL"); /* pszDrivers */
4850 PACKI(desc
,"W",0); /* time */
4851 PACKI(desc
,"W",0); /* pad1 */
4856 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
4857 char *param
, int tpscnt
,
4858 char *data
, int tdscnt
,
4859 int mdrcnt
,int mprcnt
,
4860 char **rdata
,char **rparam
,
4861 int *rdata_len
,int *rparam_len
)
4863 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4864 char *str2
= skip_string(param
,tpscnt
,str1
);
4865 char *p
= skip_string(param
,tpscnt
,str2
);
4866 char* PrinterName
= p
;
4868 struct pack_desc desc
;
4871 TALLOC_CTX
*mem_ctx
= talloc_tos();
4874 struct rpc_pipe_client
*cli
= NULL
;
4875 struct policy_handle handle
;
4876 struct spoolss_DevmodeContainer devmode_ctr
;
4877 union spoolss_PrinterInfo info
;
4879 if (!str1
|| !str2
|| !p
) {
4883 memset((char *)&desc
,'\0',sizeof(desc
));
4885 p
= skip_string(param
,tpscnt
,p
);
4889 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4891 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4893 /* check it's a supported varient */
4894 if (strcmp(str1
,"zWrLh") != 0) {
4897 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4901 ZERO_STRUCT(handle
);
4903 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4904 if (!NT_STATUS_IS_OK(status
)) {
4905 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4906 nt_errstr(status
)));
4907 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4911 ZERO_STRUCT(devmode_ctr
);
4913 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4917 SEC_FLAG_MAXIMUM_ALLOWED
,
4920 if (!NT_STATUS_IS_OK(status
)) {
4922 desc
.errcode
= NERR_DestNotFound
;
4926 if (!W_ERROR_IS_OK(werr
)) {
4928 desc
.errcode
= NERR_DestNotFound
;
4933 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4938 if (!W_ERROR_IS_OK(werr
)) {
4940 desc
.errcode
= NERR_DestNotFound
;
4946 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4951 desc
.buflen
= mdrcnt
;
4954 * Don't return data but need to get correct length
4955 * init_package will return wrong size if buflen=0
4957 desc
.buflen
= getlen(desc
.format
);
4958 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4960 if (init_package(&desc
,1,0)) {
4961 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
4965 if (cli
&& is_valid_policy_hnd(&handle
)) {
4966 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4969 *rdata_len
= desc
.usedlen
;
4972 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4976 SSVALS(*rparam
,0,desc
.errcode
);
4978 SSVAL(*rparam
,4,desc
.neededlen
);
4980 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4986 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4987 char *param
, int tpscnt
,
4988 char *data
, int tdscnt
,
4989 int mdrcnt
,int mprcnt
,
4990 char **rdata
,char **rparam
,
4991 int *rdata_len
,int *rparam_len
)
4993 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4994 char *str2
= skip_string(param
,tpscnt
,str1
);
4995 char *p
= skip_string(param
,tpscnt
,str2
);
4999 struct pack_desc desc
;
5001 TALLOC_CTX
*mem_ctx
= talloc_tos();
5004 struct rpc_pipe_client
*cli
= NULL
;
5005 union spoolss_PrinterInfo
*info
;
5008 if (!str1
|| !str2
|| !p
) {
5012 memset((char *)&desc
,'\0',sizeof(desc
));
5014 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5016 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5018 /* check it's a supported varient */
5019 if (strcmp(str1
,"WrLeh") != 0) {
5022 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5028 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
5029 if (!NT_STATUS_IS_OK(status
)) {
5030 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5031 nt_errstr(status
)));
5032 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5036 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5038 cli
->srv_name_slash
,
5043 if (!W_ERROR_IS_OK(werr
)) {
5044 desc
.errcode
= W_ERROR_V(werr
);
5046 desc
.errcode
= NERR_DestNotFound
;
5054 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5061 desc
.buflen
= mdrcnt
;
5062 if (init_package(&desc
,queuecnt
,0)) {
5065 for (i
= 0; i
< count
; i
++) {
5066 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5068 if (desc
.errcode
== NERR_Success
) {
5074 *rdata_len
= desc
.usedlen
;
5077 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5081 SSVALS(*rparam
,0,desc
.errcode
);
5083 SSVAL(*rparam
,4,succnt
);
5084 SSVAL(*rparam
,6,queuecnt
);
5086 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5091 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
5092 char *param
, int tpscnt
,
5093 char *data
, int tdscnt
,
5094 int mdrcnt
,int mprcnt
,
5095 char **rdata
,char **rparam
,
5096 int *rdata_len
,int *rparam_len
)
5098 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5099 char *str2
= skip_string(param
,tpscnt
,str1
);
5100 char *p
= skip_string(param
,tpscnt
,str2
);
5103 struct pack_desc desc
;
5105 if (!str1
|| !str2
|| !p
) {
5109 memset((char *)&desc
,'\0',sizeof(desc
));
5111 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5113 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5115 /* check it's a supported varient */
5116 if (strcmp(str1
,"WrLeh") != 0) {
5119 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5124 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5130 desc
.buflen
= mdrcnt
;
5131 if (init_package(&desc
,1,0)) {
5132 PACKS(&desc
,"B41","NULL");
5135 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5137 *rdata_len
= desc
.usedlen
;
5140 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5144 SSVALS(*rparam
,0,desc
.errcode
);
5146 SSVAL(*rparam
,4,succnt
);
5149 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5154 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
5155 char *param
, int tpscnt
,
5156 char *data
, int tdscnt
,
5157 int mdrcnt
,int mprcnt
,
5158 char **rdata
,char **rparam
,
5159 int *rdata_len
,int *rparam_len
)
5161 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5162 char *str2
= skip_string(param
,tpscnt
,str1
);
5163 char *p
= skip_string(param
,tpscnt
,str2
);
5166 struct pack_desc desc
;
5168 if (!str1
|| !str2
|| !p
) {
5171 memset((char *)&desc
,'\0',sizeof(desc
));
5173 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5175 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5177 /* check it's a supported varient */
5178 if (strcmp(str1
,"WrLeh") != 0) {
5181 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5186 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5192 desc
.buflen
= mdrcnt
;
5194 if (init_package(&desc
,1,0)) {
5195 PACKS(&desc
,"B13","lpd");
5198 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5200 *rdata_len
= desc
.usedlen
;
5203 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5207 SSVALS(*rparam
,0,desc
.errcode
);
5209 SSVAL(*rparam
,4,succnt
);
5212 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5217 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
5218 char *param
, int tpscnt
,
5219 char *data
, int tdscnt
,
5220 int mdrcnt
,int mprcnt
,
5221 char **rdata
,char **rparam
,
5222 int *rdata_len
,int *rparam_len
)
5224 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5225 char *str2
= skip_string(param
,tpscnt
,str1
);
5226 char *p
= skip_string(param
,tpscnt
,str2
);
5229 struct pack_desc desc
;
5231 if (!str1
|| !str2
|| !p
) {
5235 memset((char *)&desc
,'\0',sizeof(desc
));
5237 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5239 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5241 /* check it's a supported varient */
5242 if (strcmp(str1
,"WrLeh") != 0) {
5245 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5250 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5255 memset((char *)&desc
,'\0',sizeof(desc
));
5257 desc
.buflen
= mdrcnt
;
5259 if (init_package(&desc
,1,0)) {
5260 PACKS(&desc
,"B13","lp0");
5263 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5265 *rdata_len
= desc
.usedlen
;
5268 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5272 SSVALS(*rparam
,0,desc
.errcode
);
5274 SSVAL(*rparam
,4,succnt
);
5277 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5282 /****************************************************************************
5284 ****************************************************************************/
5286 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
5287 char *param
, int tpscnt
,
5288 char *data
, int tdscnt
,
5289 int mdrcnt
,int mprcnt
,
5290 char **rdata
,char **rparam
,
5291 int *rdata_len
,int *rparam_len
)
5294 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5295 char *str2
= skip_string(param
,tpscnt
,str1
);
5296 char *p
= skip_string(param
,tpscnt
,str2
);
5298 struct pack_desc desc
;
5299 struct sessionid
*session_list
;
5300 int i
, num_sessions
;
5302 if (!str1
|| !str2
|| !p
) {
5306 memset((char *)&desc
,'\0',sizeof(desc
));
5308 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5310 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5311 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5312 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5314 /* check it's a supported varient */
5315 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5318 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5322 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5325 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5330 memset((char *)&desc
,'\0',sizeof(desc
));
5332 desc
.buflen
= mdrcnt
;
5334 if (!init_package(&desc
,num_sessions
,0)) {
5338 for(i
=0; i
<num_sessions
; i
++) {
5339 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5340 PACKS(&desc
, "z", session_list
[i
].username
);
5341 PACKI(&desc
, "W", 1); /* num conns */
5342 PACKI(&desc
, "W", 0); /* num opens */
5343 PACKI(&desc
, "W", 1); /* num users */
5344 PACKI(&desc
, "D", 0); /* session time */
5345 PACKI(&desc
, "D", 0); /* idle time */
5346 PACKI(&desc
, "D", 0); /* flags */
5347 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5350 *rdata_len
= desc
.usedlen
;
5353 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5357 SSVALS(*rparam
,0,desc
.errcode
);
5358 SSVAL(*rparam
,2,0); /* converter */
5359 SSVAL(*rparam
,4,num_sessions
); /* count */
5361 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5367 /****************************************************************************
5368 The buffer was too small.
5369 ****************************************************************************/
5371 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5372 int mdrcnt
, int mprcnt
,
5373 char **rdata
, char **rparam
,
5374 int *rdata_len
, int *rparam_len
)
5376 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5377 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5384 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5386 DEBUG(3,("Supplied buffer too small in API command\n"));
5391 /****************************************************************************
5392 The request is not supported.
5393 ****************************************************************************/
5395 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
5396 char *param
, int tpscnt
,
5397 char *data
, int tdscnt
,
5398 int mdrcnt
, int mprcnt
,
5399 char **rdata
, char **rparam
,
5400 int *rdata_len
, int *rparam_len
)
5403 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5410 SSVAL(*rparam
,0,NERR_notsupported
);
5411 SSVAL(*rparam
,2,0); /* converter word */
5413 DEBUG(3,("Unsupported API command\n"));
5418 static const struct {
5421 bool (*fn
)(connection_struct
*, uint16
,
5424 int,int,char **,char **,int *,int *);
5425 bool auth_user
; /* Deny anonymous access? */
5426 } api_commands
[] = {
5427 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5428 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5429 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5430 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5431 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5432 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5433 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5434 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5435 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5436 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5437 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5438 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5439 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5440 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5441 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5442 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5443 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5444 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5445 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5446 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5447 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5448 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5449 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5450 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5451 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5452 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5453 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5454 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5455 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5456 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5457 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5458 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5459 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5460 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5461 {NULL
, -1, api_Unsupported
}
5462 /* The following RAP calls are not implemented by Samba:
5464 RAP_WFileEnum2 - anon not OK
5469 /****************************************************************************
5470 Handle remote api calls.
5471 ****************************************************************************/
5473 void api_reply(connection_struct
*conn
, uint16 vuid
,
5474 struct smb_request
*req
,
5475 char *data
, char *params
,
5476 int tdscnt
, int tpscnt
,
5477 int mdrcnt
, int mprcnt
)
5479 struct smbd_server_connection
*sconn
= smbd_server_conn
;
5482 char *rparam
= NULL
;
5483 const char *name1
= NULL
;
5484 const char *name2
= NULL
;
5491 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5492 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5497 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5500 api_command
= SVAL(params
,0);
5501 /* Is there a string at position params+2 ? */
5502 if (skip_string(params
,tpscnt
,params
+2)) {
5507 name2
= skip_string(params
,tpscnt
,params
+2);
5512 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5516 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5518 for (i
=0;api_commands
[i
].name
;i
++) {
5519 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5520 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5525 /* Check whether this api call can be done anonymously */
5527 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5528 user_struct
*user
= get_valid_user_struct(sconn
, vuid
);
5530 if (!user
|| user
->server_info
->guest
) {
5531 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5536 rdata
= (char *)SMB_MALLOC(1024);
5538 memset(rdata
,'\0',1024);
5541 rparam
= (char *)SMB_MALLOC(1024);
5543 memset(rparam
,'\0',1024);
5546 if(!rdata
|| !rparam
) {
5547 DEBUG(0,("api_reply: malloc fail !\n"));
5550 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5554 reply
= api_commands
[i
].fn(conn
,
5556 params
,tpscnt
, /* params + length */
5557 data
,tdscnt
, /* data + length */
5559 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5562 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5563 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
5564 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5567 /* if we get False back then it's actually unsupported */
5569 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
5570 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5573 /* If api_Unsupported returns false we can't return anything. */
5575 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5576 rdata
, rdata_len
, False
);