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"
45 #define NERR_Success 0
46 #define NERR_badpass 86
47 #define NERR_notsupported 50
49 #define NERR_BASE (2100)
50 #define NERR_BufTooSmall (NERR_BASE+23)
51 #define NERR_JobNotFound (NERR_BASE+51)
52 #define NERR_DestNotFound (NERR_BASE+52)
54 #define ACCESS_READ 0x01
55 #define ACCESS_WRITE 0x02
56 #define ACCESS_CREATE 0x04
58 #define SHPWLEN 8 /* share password length */
60 /* Limit size of ipc replies */
62 static char *smb_realloc_limit(void *ptr
, size_t size
)
66 size
= MAX((size
),4*1024);
67 val
= (char *)SMB_REALLOC(ptr
,size
);
69 memset(val
,'\0',size
);
74 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
75 char *param
, int tpscnt
,
76 char *data
, int tdscnt
,
77 int mdrcnt
, int mprcnt
,
78 char **rdata
, char **rparam
,
79 int *rdata_len
, int *rparam_len
);
81 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
82 int mdrcnt
, int mprcnt
,
83 char **rdata
, char **rparam
,
84 int *rdata_len
, int *rparam_len
);
87 static int CopyExpanded(connection_struct
*conn
,
88 int snum
, char **dst
, char *src
, int *p_space_remaining
)
90 TALLOC_CTX
*ctx
= talloc_tos();
94 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
95 *p_space_remaining
<= 0) {
99 buf
= talloc_strdup(ctx
, src
);
101 *p_space_remaining
= 0;
104 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
106 *p_space_remaining
= 0;
109 buf
= talloc_sub_advanced(ctx
,
110 lp_servicename(SNUM(conn
)),
111 conn
->server_info
->unix_name
,
113 conn
->server_info
->utok
.gid
,
114 conn
->server_info
->sanitized_username
,
115 pdb_get_domain(conn
->server_info
->sam_account
),
118 *p_space_remaining
= 0;
121 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
126 (*p_space_remaining
) -= l
;
130 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
133 if (!src
|| !dst
|| !n
|| !(*dst
)) {
136 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
145 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
147 TALLOC_CTX
*ctx
= talloc_tos();
152 buf
= talloc_strdup(ctx
,s
);
156 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
160 buf
= talloc_sub_advanced(ctx
,
161 lp_servicename(SNUM(conn
)),
162 conn
->server_info
->unix_name
,
164 conn
->server_info
->utok
.gid
,
165 conn
->server_info
->sanitized_username
,
166 pdb_get_domain(conn
->server_info
->sam_account
),
171 return strlen(buf
) + 1;
174 /*******************************************************************
175 Check a API string for validity when we only need to check the prefix.
176 ******************************************************************/
178 static bool prefix_ok(const char *str
, const char *prefix
)
180 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
184 const char *format
; /* formatstring for structure */
185 const char *subformat
; /* subformat for structure */
186 char *base
; /* baseaddress of buffer */
187 int buflen
; /* remaining size for fixed part; on init: length of base */
188 int subcount
; /* count of substructures */
189 char *structbuf
; /* pointer into buffer for remaining fixed part */
190 int stringlen
; /* remaining size for variable part */
191 char *stringbuf
; /* pointer into buffer for remaining variable part */
192 int neededlen
; /* total needed size */
193 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
194 const char *curpos
; /* current position; pointer into format or subformat */
198 static int get_counter(const char **p
)
204 if (!isdigit((int)**p
)) {
210 n
= 10 * n
+ (i
- '0');
218 static int getlen(const char *p
)
227 case 'W': /* word (2 byte) */
230 case 'K': /* status word? (2 byte) */
233 case 'N': /* count of substructures (word) at end */
236 case 'D': /* double word (4 byte) */
237 case 'z': /* offset to zero terminated string (4 byte) */
238 case 'l': /* offset to user data (4 byte) */
241 case 'b': /* offset to data (with counter) (4 byte) */
245 case 'B': /* byte (with optional counter) */
246 n
+= get_counter(&p
);
253 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
258 if (!p
->format
|| !p
->base
) {
262 i
= count
* getlen(p
->format
);
264 i
+= subcount
* getlen(p
->subformat
);
266 p
->structbuf
= p
->base
;
270 p
->curpos
= p
->format
;
276 * This is the old error code we used. Aparently
277 * WinNT/2k systems return ERRbuftoosmall (2123) and
278 * OS/2 needs this. I'm leaving this here so we can revert
281 p
->errcode
= ERRmoredata
;
283 p
->errcode
= ERRbuftoosmall
;
286 p
->errcode
= NERR_Success
;
290 p
->stringbuf
= p
->base
+ i
;
292 return (p
->errcode
== NERR_Success
);
295 static int package(struct pack_desc
*p
, ...)
298 int needed
=0, stringneeded
;
299 const char *str
=NULL
;
300 int is_string
=0, stringused
;
307 p
->curpos
= p
->format
;
309 p
->curpos
= p
->subformat
;
314 str
= va_arg(args
,char*);
315 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
324 switch( *p
->curpos
++ ) {
325 case 'W': /* word (2 byte) */
327 temp
= va_arg(args
,int);
328 if (p
->buflen
>= needed
) {
329 SSVAL(p
->structbuf
,0,temp
);
332 case 'K': /* status word? (2 byte) */
334 temp
= va_arg(args
,int);
335 if (p
->buflen
>= needed
) {
336 SSVAL(p
->structbuf
,0,temp
);
339 case 'N': /* count of substructures (word) at end */
341 p
->subcount
= va_arg(args
,int);
342 if (p
->buflen
>= needed
) {
343 SSVAL(p
->structbuf
,0,p
->subcount
);
346 case 'D': /* double word (4 byte) */
348 temp
= va_arg(args
,int);
349 if (p
->buflen
>= needed
) {
350 SIVAL(p
->structbuf
,0,temp
);
353 case 'B': /* byte (with optional counter) */
354 needed
= get_counter(&p
->curpos
);
356 char *s
= va_arg(args
,char*);
357 if (p
->buflen
>= needed
) {
358 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
362 case 'z': /* offset to zero terminated string (4 byte) */
363 str
= va_arg(args
,char*);
364 stringneeded
= (str
? strlen(str
)+1 : 0);
367 case 'l': /* offset to user data (4 byte) */
368 str
= va_arg(args
,char*);
369 stringneeded
= va_arg(args
,int);
372 case 'b': /* offset to data (with counter) (4 byte) */
373 str
= va_arg(args
,char*);
374 stringneeded
= get_counter(&p
->curpos
);
380 if (stringneeded
>= 0) {
382 if (p
->buflen
>= needed
) {
383 stringused
= stringneeded
;
384 if (stringused
> p
->stringlen
) {
385 stringused
= (is_string
? p
->stringlen
: 0);
386 if (p
->errcode
== NERR_Success
) {
387 p
->errcode
= ERRmoredata
;
391 SIVAL(p
->structbuf
,0,0);
393 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
394 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
396 p
->stringbuf
[stringused
-1] = '\0';
398 p
->stringbuf
+= stringused
;
399 p
->stringlen
-= stringused
;
400 p
->usedlen
+= stringused
;
403 p
->neededlen
+= stringneeded
;
406 p
->neededlen
+= needed
;
407 if (p
->buflen
>= needed
) {
408 p
->structbuf
+= needed
;
410 p
->usedlen
+= needed
;
412 if (p
->errcode
== NERR_Success
) {
413 p
->errcode
= ERRmoredata
;
420 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
421 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
423 #define PACK(desc,t,v) package(desc,v)
424 #define PACKl(desc,t,v,l) package(desc,v,l)
427 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
432 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
437 /****************************************************************************
439 ****************************************************************************/
441 static void PackDriverData(struct pack_desc
* desc
)
443 char drivdata
[4+4+32];
444 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
445 SIVAL(drivdata
,4,1000); /* lVersion */
446 memset(drivdata
+8,0,32); /* szDeviceName */
447 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
448 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
451 static int check_printq_info(struct pack_desc
* desc
,
452 unsigned int uLevel
, char *id1
, char *id2
)
454 desc
->subformat
= NULL
;
457 desc
->format
= "B13";
460 desc
->format
= "B13BWWWzzzzzWW";
463 desc
->format
= "B13BWWWzzzzzWN";
464 desc
->subformat
= "WB21BB16B10zWWzDDz";
467 desc
->format
= "zWWWWzzzzWWzzl";
470 desc
->format
= "zWWWWzzzzWNzzl";
471 desc
->subformat
= "WWzWWDDzz";
480 desc
->format
= "WzzzzzzzzN";
481 desc
->subformat
= "z";
484 DEBUG(0,("check_printq_info: invalid level %d\n",
488 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
489 DEBUG(0,("check_printq_info: invalid format %s\n",
490 id1
? id1
: "<NULL>" ));
493 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
494 DEBUG(0,("check_printq_info: invalid subformat %s\n",
495 id2
? id2
: "<NULL>" ));
502 #define RAP_JOB_STATUS_QUEUED 0
503 #define RAP_JOB_STATUS_PAUSED 1
504 #define RAP_JOB_STATUS_SPOOLING 2
505 #define RAP_JOB_STATUS_PRINTING 3
506 #define RAP_JOB_STATUS_PRINTED 4
508 #define RAP_QUEUE_STATUS_PAUSED 1
509 #define RAP_QUEUE_STATUS_ERROR 2
511 /* turn a print job status into a on the wire status
513 static int printj_spoolss_status(int v
)
515 if (v
== JOB_STATUS_QUEUED
)
516 return RAP_JOB_STATUS_QUEUED
;
517 if (v
& JOB_STATUS_PAUSED
)
518 return RAP_JOB_STATUS_PAUSED
;
519 if (v
& JOB_STATUS_SPOOLING
)
520 return RAP_JOB_STATUS_SPOOLING
;
521 if (v
& JOB_STATUS_PRINTING
)
522 return RAP_JOB_STATUS_PRINTING
;
526 /* turn a print queue status into a on the wire status
528 static int printq_spoolss_status(int v
)
530 if (v
== PRINTER_STATUS_OK
)
532 if (v
& PRINTER_STATUS_PAUSED
)
533 return RAP_QUEUE_STATUS_PAUSED
;
534 return RAP_QUEUE_STATUS_ERROR
;
537 static void fill_spoolss_printjob_info(int uLevel
,
538 struct pack_desc
*desc
,
539 struct spoolss_JobInfo2
*info2
,
542 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
544 /* the client expects localtime */
545 t
-= get_time_zone(t
);
547 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
549 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
550 PACKS(desc
,"B",""); /* pad */
551 PACKS(desc
,"B16",""); /* szNotifyName */
552 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
553 PACKS(desc
,"z",""); /* pszParms */
554 PACKI(desc
,"W",n
+1); /* uPosition */
555 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
556 PACKS(desc
,"z",""); /* pszStatus */
557 PACKI(desc
,"D", t
); /* ulSubmitted */
558 PACKI(desc
,"D", info2
->size
); /* ulSize */
559 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
561 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
562 PACKI(desc
,"W", info2
->priority
); /* uPriority */
563 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
564 PACKI(desc
,"W",n
+1); /* uPosition */
565 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
566 PACKI(desc
,"D",t
); /* ulSubmitted */
567 PACKI(desc
,"D", info2
->size
); /* ulSize */
568 PACKS(desc
,"z","Samba"); /* pszComment */
569 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
571 PACKS(desc
,"z",""); /* pszNotifyName */
572 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
573 PACKS(desc
,"z",""); /* pszParms */
574 PACKS(desc
,"z",""); /* pszStatus */
575 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
576 PACKS(desc
,"z","lpd"); /* pszQProcName */
577 PACKS(desc
,"z",""); /* pszQProcParms */
578 PACKS(desc
,"z","NULL"); /* pszDriverName */
579 PackDriverData(desc
); /* pDriverData */
580 PACKS(desc
,"z",""); /* pszPrinterName */
581 } else if (uLevel
== 4) { /* OS2 */
582 PACKS(desc
,"z",""); /* pszSpoolFileName */
583 PACKS(desc
,"z",""); /* pszPortName */
584 PACKS(desc
,"z",""); /* pszStatus */
585 PACKI(desc
,"D",0); /* ulPagesSpooled */
586 PACKI(desc
,"D",0); /* ulPagesSent */
587 PACKI(desc
,"D",0); /* ulPagesPrinted */
588 PACKI(desc
,"D",0); /* ulTimePrinted */
589 PACKI(desc
,"D",0); /* ulExtendJobStatus */
590 PACKI(desc
,"D",0); /* ulStartPage */
591 PACKI(desc
,"D",0); /* ulEndPage */
596 /********************************************************************
597 Respond to the DosPrintQInfo command with a level of 52
598 This is used to get printer driver information for Win9x clients
599 ********************************************************************/
600 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
601 struct pack_desc
* desc
, int count
,
602 const char *printer_name
)
606 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
607 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
608 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
610 PACKI(desc
, "W", 0x0400); /* don't know */
611 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
612 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
613 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
614 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
616 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
617 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
618 PACKS(desc
,"z", location
); /* share to retrieve files */
620 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
621 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
622 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
624 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
625 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
626 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
627 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
628 DEBUG(3,("Driver Location: %s:\n",location
));
629 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
630 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
631 PACKI(desc
,"N",count
); /* number of files to copy */
633 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
635 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
636 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
637 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
642 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
645 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
647 desc
->errcode
=NERR_Success
;
651 static const char *strip_unc(const char *unc
)
659 if ((p
= strrchr(unc
, '\\')) != NULL
) {
666 static void fill_printq_info(int uLevel
,
667 struct pack_desc
* desc
,
669 union spoolss_JobInfo
*job_info
,
670 struct spoolss_DriverInfo3
*driver_info
,
671 struct spoolss_PrinterInfo2
*printer_info
)
677 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
682 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
685 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
689 if (uLevel
== 1 || uLevel
== 2) {
690 PACKS(desc
,"B",""); /* alignment */
691 PACKI(desc
,"W",5); /* priority */
692 PACKI(desc
,"W",0); /* start time */
693 PACKI(desc
,"W",0); /* until time */
694 PACKS(desc
,"z",""); /* pSepFile */
695 PACKS(desc
,"z","lpd"); /* pPrProc */
696 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
697 PACKS(desc
,"z",""); /* pParms */
698 if (printer_info
->printername
== NULL
) {
699 PACKS(desc
,"z","UNKNOWN PRINTER");
700 PACKI(desc
,"W",LPSTAT_ERROR
);
702 PACKS(desc
,"z", printer_info
->comment
);
703 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
705 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
708 if (uLevel
== 3 || uLevel
== 4) {
709 PACKI(desc
,"W",5); /* uPriority */
710 PACKI(desc
,"W",0); /* uStarttime */
711 PACKI(desc
,"W",0); /* uUntiltime */
712 PACKI(desc
,"W",5); /* pad1 */
713 PACKS(desc
,"z",""); /* pszSepFile */
714 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
715 PACKS(desc
,"z",NULL
); /* pszParms */
716 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
717 /* "don't ask" that it's done this way to fix corrupted
718 Win9X/ME printer comments. */
719 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
720 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
721 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
722 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
723 PackDriverData(desc
); /* pDriverData */
726 if (uLevel
== 2 || uLevel
== 4) {
728 for (i
= 0; i
< count
; i
++) {
729 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
734 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
737 /* This function returns the number of files for a given driver */
738 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
742 /* count the number of files */
743 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
749 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
750 char *param
, int tpscnt
,
751 char *data
, int tdscnt
,
752 int mdrcnt
,int mprcnt
,
753 char **rdata
,char **rparam
,
754 int *rdata_len
,int *rparam_len
)
756 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
757 char *str2
= skip_string(param
,tpscnt
,str1
);
758 char *p
= skip_string(param
,tpscnt
,str2
);
763 struct pack_desc desc
;
766 WERROR werr
= WERR_OK
;
767 TALLOC_CTX
*mem_ctx
= talloc_tos();
769 struct rpc_pipe_client
*cli
= NULL
;
770 struct policy_handle handle
;
771 struct spoolss_DevmodeContainer devmode_ctr
;
772 union spoolss_DriverInfo driver_info
;
773 union spoolss_JobInfo
*job_info
;
774 union spoolss_PrinterInfo printer_info
;
776 if (!str1
|| !str2
|| !p
) {
779 memset((char *)&desc
,'\0',sizeof(desc
));
781 p
= skip_string(param
,tpscnt
,p
);
785 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
786 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
787 /* str3 may be null here and is checked in check_printq_info(). */
789 /* remove any trailing username */
790 if ((p
= strchr_m(QueueName
,'%')))
793 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
795 /* check it's a supported varient */
796 if (!prefix_ok(str1
,"zWrLh"))
798 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
800 * Patch from Scott Moomaw <scott@bridgewater.edu>
801 * to return the 'invalid info level' error if an
802 * unknown level was requested.
806 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
810 SSVALS(*rparam
,0,ERRunknownlevel
);
818 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
819 if (!NT_STATUS_IS_OK(status
)) {
820 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
822 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
826 ZERO_STRUCT(devmode_ctr
);
828 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
835 if (!NT_STATUS_IS_OK(status
)) {
836 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
839 if (!W_ERROR_IS_OK(werr
)) {
840 desc
.errcode
= W_ERROR_V(werr
);
844 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
849 if (!W_ERROR_IS_OK(werr
)) {
850 desc
.errcode
= W_ERROR_V(werr
);
855 uint32_t server_major_version
;
856 uint32_t server_minor_version
;
858 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
866 &server_major_version
,
867 &server_minor_version
);
868 if (!W_ERROR_IS_OK(werr
)) {
869 desc
.errcode
= W_ERROR_V(werr
);
873 count
= get_printerdrivernumber(&driver_info
.info3
);
874 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
877 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
885 if (!W_ERROR_IS_OK(werr
)) {
886 desc
.errcode
= W_ERROR_V(werr
);
894 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
899 desc
.buflen
= mdrcnt
;
902 * Don't return data but need to get correct length
903 * init_package will return wrong size if buflen=0
905 desc
.buflen
= getlen(desc
.format
);
906 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
909 if (init_package(&desc
,1,count
)) {
910 desc
.subcount
= count
;
911 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
914 *rdata_len
= desc
.usedlen
;
917 * We must set the return code to ERRbuftoosmall
918 * in order to support lanman style printing with Win NT/2k
921 if (!mdrcnt
&& lp_disable_spoolss())
922 desc
.errcode
= ERRbuftoosmall
;
925 if (cli
&& is_valid_policy_hnd(&handle
)) {
926 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
929 *rdata_len
= desc
.usedlen
;
931 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
936 SSVALS(*rparam
,0,desc
.errcode
);
938 SSVAL(*rparam
,4,desc
.neededlen
);
940 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
947 /****************************************************************************
948 View list of all print jobs on all queues.
949 ****************************************************************************/
951 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
952 char *param
, int tpscnt
,
953 char *data
, int tdscnt
,
954 int mdrcnt
, int mprcnt
,
955 char **rdata
, char** rparam
,
956 int *rdata_len
, int *rparam_len
)
958 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
959 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
960 char *p
= skip_string(param
,tpscnt
,output_format1
);
961 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
962 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
964 struct pack_desc desc
;
965 int *subcntarr
= NULL
;
966 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
968 WERROR werr
= WERR_OK
;
969 TALLOC_CTX
*mem_ctx
= talloc_tos();
971 struct rpc_pipe_client
*cli
= NULL
;
972 struct spoolss_DevmodeContainer devmode_ctr
;
973 uint32_t num_printers
;
974 union spoolss_PrinterInfo
*printer_info
;
975 union spoolss_DriverInfo
*driver_info
;
976 union spoolss_JobInfo
**job_info
;
978 if (!param_format
|| !output_format1
|| !p
) {
982 memset((char *)&desc
,'\0',sizeof(desc
));
984 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
986 if (!prefix_ok(param_format
,"WrLeh")) {
989 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
991 * Patch from Scott Moomaw <scott@bridgewater.edu>
992 * to return the 'invalid info level' error if an
993 * unknown level was requested.
997 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1001 SSVALS(*rparam
,0,ERRunknownlevel
);
1007 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
1008 if (!NT_STATUS_IS_OK(status
)) {
1009 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1010 nt_errstr(status
)));
1011 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1015 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1017 cli
->srv_name_slash
,
1022 if (!W_ERROR_IS_OK(werr
)) {
1023 desc
.errcode
= W_ERROR_V(werr
);
1027 queuecnt
= num_printers
;
1029 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1030 if (job_info
== NULL
) {
1034 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1035 if (driver_info
== NULL
) {
1039 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1040 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1045 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1051 desc
.buflen
= mdrcnt
;
1054 for (i
= 0; i
< num_printers
; i
++) {
1057 struct policy_handle handle
;
1058 const char *printername
;
1060 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1061 if (printername
== NULL
) {
1065 ZERO_STRUCT(handle
);
1066 ZERO_STRUCT(devmode_ctr
);
1068 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
1075 if (!NT_STATUS_IS_OK(status
)) {
1076 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1079 if (!W_ERROR_IS_OK(werr
)) {
1080 desc
.errcode
= W_ERROR_V(werr
);
1084 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1092 if (!W_ERROR_IS_OK(werr
)) {
1093 desc
.errcode
= W_ERROR_V(werr
);
1098 uint32_t server_major_version
;
1099 uint32_t server_minor_version
;
1101 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1109 &server_major_version
,
1110 &server_minor_version
);
1111 if (!W_ERROR_IS_OK(werr
)) {
1112 desc
.errcode
= W_ERROR_V(werr
);
1117 subcntarr
[i
] = num_jobs
;
1118 subcnt
+= subcntarr
[i
];
1120 if (cli
&& is_valid_policy_hnd(&handle
)) {
1121 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
1125 if (init_package(&desc
,queuecnt
,subcnt
)) {
1126 for (i
= 0; i
< num_printers
; i
++) {
1127 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1128 if (desc
.errcode
== NERR_Success
) {
1134 SAFE_FREE(subcntarr
);
1136 *rdata_len
= desc
.usedlen
;
1138 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1142 SSVALS(*rparam
,0,desc
.errcode
);
1144 SSVAL(*rparam
,4,succnt
);
1145 SSVAL(*rparam
,6,queuecnt
);
1151 SAFE_FREE(subcntarr
);
1156 /****************************************************************************
1157 Get info level for a server list query.
1158 ****************************************************************************/
1160 static bool check_server_info(int uLevel
, char* id
)
1164 if (strcmp(id
,"B16") != 0) {
1169 if (strcmp(id
,"B16BBDz") != 0) {
1179 struct srv_info_struct
{
1187 /*******************************************************************
1188 Get server info lists from the files saved by nmbd. Return the
1190 ******************************************************************/
1192 static int get_server_info(uint32 servertype
,
1193 struct srv_info_struct
**servers
,
1199 bool local_list_only
;
1202 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1204 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1208 /* request for everything is code for request all servers */
1209 if (servertype
== SV_TYPE_ALL
) {
1210 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1213 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1215 DEBUG(4,("Servertype search: %8x\n",servertype
));
1217 for (i
=0;lines
[i
];i
++) {
1219 struct srv_info_struct
*s
;
1220 const char *ptr
= lines
[i
];
1222 TALLOC_CTX
*frame
= NULL
;
1229 if (count
== alloced
) {
1231 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1233 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1237 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1239 s
= &(*servers
)[count
];
1241 frame
= talloc_stackframe();
1243 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1247 fstrcpy(s
->name
, p
);
1250 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1256 s
->comment
[0] = '\0';
1257 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1261 fstrcpy(s
->comment
, p
);
1262 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1264 s
->domain
[0] = '\0';
1265 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1266 /* this allows us to cope with an old nmbd */
1267 fstrcpy(s
->domain
,lp_workgroup());
1269 fstrcpy(s
->domain
, p
);
1273 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1274 DEBUG(4,("r:host file "));
1278 /* Filter the servers/domains we return based on what was asked for. */
1280 /* Check to see if we are being asked for a local list only. */
1281 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1282 DEBUG(4,("r: local list only"));
1286 /* doesn't match up: don't want it */
1287 if (!(servertype
& s
->type
)) {
1288 DEBUG(4,("r:serv type "));
1292 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1293 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1294 DEBUG(4,("s: dom mismatch "));
1298 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1302 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1303 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1306 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1307 s
->name
, s
->type
, s
->comment
, s
->domain
));
1308 s
->server_added
= True
;
1311 DEBUG(4,("%20s %8x %25s %15s\n",
1312 s
->name
, s
->type
, s
->comment
, s
->domain
));
1320 /*******************************************************************
1321 Fill in a server info structure.
1322 ******************************************************************/
1324 static int fill_srv_info(struct srv_info_struct
*service
,
1325 int uLevel
, char **buf
, int *buflen
,
1326 char **stringbuf
, int *stringspace
, char *baseaddr
)
1349 len
= strlen(service
->comment
)+1;
1353 *buflen
= struct_len
;
1355 return struct_len
+ len
;
1360 if (*buflen
< struct_len
) {
1367 p2
= p
+ struct_len
;
1368 l2
= *buflen
- struct_len
;
1376 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1380 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1381 SIVAL(p
,18,service
->type
);
1382 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1383 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1388 *buf
= p
+ struct_len
;
1389 *buflen
-= struct_len
;
1400 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1402 return StrCaseCmp(s1
->name
,s2
->name
);
1405 /****************************************************************************
1406 View list of servers available (or possibly domains). The info is
1407 extracted from lists saved by nmbd on the local host.
1408 ****************************************************************************/
1410 static bool api_RNetServerEnum2(connection_struct
*conn
, uint16 vuid
,
1411 char *param
, int tpscnt
,
1412 char *data
, int tdscnt
,
1413 int mdrcnt
, int mprcnt
, char **rdata
,
1414 char **rparam
, int *rdata_len
, int *rparam_len
)
1416 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1417 char *str2
= skip_string(param
,tpscnt
,str1
);
1418 char *p
= skip_string(param
,tpscnt
,str2
);
1419 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1420 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1421 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1423 int data_len
, fixed_len
, string_len
;
1424 int f_len
= 0, s_len
= 0;
1425 struct srv_info_struct
*servers
=NULL
;
1426 int counted
=0,total
=0;
1429 bool domain_request
;
1432 if (!str1
|| !str2
|| !p
) {
1436 /* If someone sets all the bits they don't really mean to set
1437 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1440 if (servertype
== SV_TYPE_ALL
) {
1441 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1444 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1445 any other bit (they may just set this bit on its own) they
1446 want all the locally seen servers. However this bit can be
1447 set on its own so set the requested servers to be
1448 ALL - DOMAIN_ENUM. */
1450 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1451 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1454 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1455 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1459 if (!prefix_ok(str1
,"WrLehD")) {
1462 if (!check_server_info(uLevel
,str2
)) {
1466 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1467 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1468 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1470 if (strcmp(str1
, "WrLehDz") == 0) {
1471 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1474 pull_ascii_fstring(domain
, p
);
1476 fstrcpy(domain
, lp_workgroup());
1479 DEBUG(4, ("domain [%s]\n", domain
));
1481 if (lp_browse_list()) {
1482 total
= get_server_info(servertype
,&servers
,domain
);
1485 data_len
= fixed_len
= string_len
= 0;
1488 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1491 char *lastname
=NULL
;
1493 for (i
=0;i
<total
;i
++) {
1494 struct srv_info_struct
*s
= &servers
[i
];
1496 if (lastname
&& strequal(lastname
,s
->name
)) {
1500 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1501 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1502 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1504 if (data_len
< buf_len
) {
1507 string_len
+= s_len
;
1514 *rdata_len
= fixed_len
+ string_len
;
1515 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1520 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1526 char *lastname
=NULL
;
1527 int count2
= counted
;
1529 for (i
= 0; i
< total
&& count2
;i
++) {
1530 struct srv_info_struct
*s
= &servers
[i
];
1532 if (lastname
&& strequal(lastname
,s
->name
)) {
1536 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1537 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1538 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1544 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1548 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1550 SSVAL(*rparam
,4,counted
);
1551 SSVAL(*rparam
,6,counted
+missed
);
1555 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1556 domain
,uLevel
,counted
,counted
+missed
));
1561 static int srv_name_match(const char *n1
, const char *n2
)
1564 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1566 * In Windows, FirstNameToReturn need not be an exact match:
1567 * the server will return a list of servers that exist on
1568 * the network greater than or equal to the FirstNameToReturn.
1570 int ret
= StrCaseCmp(n1
, n2
);
1579 static bool api_RNetServerEnum3(connection_struct
*conn
, uint16 vuid
,
1580 char *param
, int tpscnt
,
1581 char *data
, int tdscnt
,
1582 int mdrcnt
, int mprcnt
, char **rdata
,
1583 char **rparam
, int *rdata_len
, int *rparam_len
)
1585 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1586 char *str2
= skip_string(param
,tpscnt
,str1
);
1587 char *p
= skip_string(param
,tpscnt
,str2
);
1588 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1589 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1590 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1592 int data_len
, fixed_len
, string_len
;
1593 int f_len
= 0, s_len
= 0;
1594 struct srv_info_struct
*servers
=NULL
;
1595 int counted
=0,first
=0,total
=0;
1599 bool domain_request
;
1602 if (!str1
|| !str2
|| !p
) {
1606 /* If someone sets all the bits they don't really mean to set
1607 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1610 if (servertype
== SV_TYPE_ALL
) {
1611 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1614 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1615 any other bit (they may just set this bit on its own) they
1616 want all the locally seen servers. However this bit can be
1617 set on its own so set the requested servers to be
1618 ALL - DOMAIN_ENUM. */
1620 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1621 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1624 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1625 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1629 if (strcmp(str1
, "WrLehDzz") != 0) {
1632 if (!check_server_info(uLevel
,str2
)) {
1636 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1637 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1638 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1640 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1643 pull_ascii_fstring(domain
, p
);
1644 if (domain
[0] == '\0') {
1645 fstrcpy(domain
, lp_workgroup());
1647 p
= skip_string(param
,tpscnt
,p
);
1648 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1651 pull_ascii_fstring(first_name
, p
);
1653 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1654 domain
, first_name
));
1656 if (lp_browse_list()) {
1657 total
= get_server_info(servertype
,&servers
,domain
);
1660 data_len
= fixed_len
= string_len
= 0;
1663 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1665 if (first_name
[0] != '\0') {
1666 struct srv_info_struct
*first_server
= NULL
;
1668 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1669 srv_name_match
, first_server
);
1671 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1673 * The binary search may not find the exact match
1674 * so we need to search backward to find the first match
1676 * This implements the strange matching windows
1677 * implements. (see the comment in srv_name_match().
1681 ret
= StrCaseCmp(first_name
,
1682 servers
[first
-1].name
);
1689 /* we should return no entries */
1695 char *lastname
=NULL
;
1697 for (i
=first
;i
<total
;i
++) {
1698 struct srv_info_struct
*s
= &servers
[i
];
1700 if (lastname
&& strequal(lastname
,s
->name
)) {
1704 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1705 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1706 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1708 if (data_len
< buf_len
) {
1711 string_len
+= s_len
;
1718 *rdata_len
= fixed_len
+ string_len
;
1719 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1724 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1730 char *lastname
=NULL
;
1731 int count2
= counted
;
1733 for (i
= first
; i
< total
&& count2
;i
++) {
1734 struct srv_info_struct
*s
= &servers
[i
];
1736 if (lastname
&& strequal(lastname
,s
->name
)) {
1740 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1741 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1742 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1748 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1752 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1754 SSVAL(*rparam
,4,counted
);
1755 SSVAL(*rparam
,6,counted
+missed
);
1757 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1758 domain
,uLevel
,first
,first_name
,
1759 first
< total
? servers
[first
].name
: "",
1760 counted
,counted
+missed
));
1767 /****************************************************************************
1768 command 0x34 - suspected of being a "Lookup Names" stub api
1769 ****************************************************************************/
1771 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1772 char *param
, int tpscnt
,
1773 char *data
, int tdscnt
,
1774 int mdrcnt
, int mprcnt
, char **rdata
,
1775 char **rparam
, int *rdata_len
, int *rparam_len
)
1777 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1778 char *str2
= skip_string(param
,tpscnt
,str1
);
1779 char *p
= skip_string(param
,tpscnt
,str2
);
1780 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1781 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1785 if (!str1
|| !str2
|| !p
) {
1789 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1790 str1
, str2
, p
, uLevel
, buf_len
));
1792 if (!prefix_ok(str1
,"zWrLeh")) {
1799 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1804 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1806 SSVAL(*rparam
,4,counted
);
1807 SSVAL(*rparam
,6,counted
+missed
);
1812 /****************************************************************************
1813 get info about a share
1814 ****************************************************************************/
1816 static bool check_share_info(int uLevel
, char* id
)
1820 if (strcmp(id
,"B13") != 0) {
1825 /* Level-2 descriptor is allowed (and ignored) */
1826 if (strcmp(id
,"B13BWz") != 0 &&
1827 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1832 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1837 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1847 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1848 char** buf
, int* buflen
,
1849 char** stringbuf
, int* stringspace
, char* baseaddr
)
1878 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1881 len
+= strlen(lp_pathname(snum
)) + 1;
1884 *buflen
= struct_len
;
1889 return struct_len
+ len
;
1894 if ((*buflen
) < struct_len
) {
1902 p2
= p
+ struct_len
;
1903 l2
= (*buflen
) - struct_len
;
1910 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1916 type
= STYPE_DISKTREE
;
1917 if (lp_print_ok(snum
)) {
1918 type
= STYPE_PRINTQ
;
1920 if (strequal("IPC",lp_fstype(snum
))) {
1923 SSVAL(p
,14,type
); /* device type */
1924 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1925 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1929 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1930 SSVALS(p
,22,-1); /* max uses */
1931 SSVAL(p
,24,1); /* current uses */
1932 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1933 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1934 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1938 memset(p
+40,0,SHPWLEN
+2);
1949 (*buf
) = p
+ struct_len
;
1950 (*buflen
) -= struct_len
;
1952 (*stringspace
) = l2
;
1961 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1962 char *param
, int tpscnt
,
1963 char *data
, int tdscnt
,
1964 int mdrcnt
,int mprcnt
,
1965 char **rdata
,char **rparam
,
1966 int *rdata_len
,int *rparam_len
)
1968 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1969 char *str2
= skip_string(param
,tpscnt
,str1
);
1970 char *netname
= skip_string(param
,tpscnt
,str2
);
1971 char *p
= skip_string(param
,tpscnt
,netname
);
1972 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1975 if (!str1
|| !str2
|| !netname
|| !p
) {
1979 snum
= find_service(netname
);
1984 /* check it's a supported varient */
1985 if (!prefix_ok(str1
,"zWrLh")) {
1988 if (!check_share_info(uLevel
,str2
)) {
1992 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1997 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1998 if (*rdata_len
< 0) {
2003 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2007 SSVAL(*rparam
,0,NERR_Success
);
2008 SSVAL(*rparam
,2,0); /* converter word */
2009 SSVAL(*rparam
,4,*rdata_len
);
2014 /****************************************************************************
2015 View the list of available shares.
2017 This function is the server side of the NetShareEnum() RAP call.
2018 It fills the return buffer with share names and share comments.
2019 Note that the return buffer normally (in all known cases) allows only
2020 twelve byte strings for share names (plus one for a nul terminator).
2021 Share names longer than 12 bytes must be skipped.
2022 ****************************************************************************/
2024 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
2025 char *param
, int tpscnt
,
2026 char *data
, int tdscnt
,
2034 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2035 char *str2
= skip_string(param
,tpscnt
,str1
);
2036 char *p
= skip_string(param
,tpscnt
,str2
);
2037 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2038 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2041 int total
=0,counted
=0;
2042 bool missed
= False
;
2044 int data_len
, fixed_len
, string_len
;
2045 int f_len
= 0, s_len
= 0;
2047 if (!str1
|| !str2
|| !p
) {
2051 if (!prefix_ok(str1
,"WrLeh")) {
2054 if (!check_share_info(uLevel
,str2
)) {
2058 /* Ensure all the usershares are loaded. */
2060 load_registry_shares();
2061 count
= load_usershare_shares();
2064 data_len
= fixed_len
= string_len
= 0;
2065 for (i
=0;i
<count
;i
++) {
2066 fstring servicename_dos
;
2067 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2070 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2071 /* Maximum name length = 13. */
2072 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2074 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2075 if (data_len
< buf_len
) {
2078 string_len
+= s_len
;
2085 *rdata_len
= fixed_len
+ string_len
;
2086 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2091 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2096 for( i
= 0; i
< count
; i
++ ) {
2097 fstring servicename_dos
;
2098 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2102 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2103 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2104 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2111 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2115 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2117 SSVAL(*rparam
,4,counted
);
2118 SSVAL(*rparam
,6,total
);
2120 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2121 counted
,total
,uLevel
,
2122 buf_len
,*rdata_len
,mdrcnt
));
2127 /****************************************************************************
2129 ****************************************************************************/
2131 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
2132 char *param
, int tpscnt
,
2133 char *data
, int tdscnt
,
2134 int mdrcnt
,int mprcnt
,
2135 char **rdata
,char **rparam
,
2136 int *rdata_len
,int *rparam_len
)
2138 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2139 char *str2
= skip_string(param
,tpscnt
,str1
);
2140 char *p
= skip_string(param
,tpscnt
,str2
);
2141 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2144 char *pathname
= NULL
;
2145 unsigned int offset
;
2147 size_t converted_size
;
2149 WERROR werr
= WERR_OK
;
2150 TALLOC_CTX
*mem_ctx
= talloc_tos();
2152 struct rpc_pipe_client
*cli
= NULL
;
2153 union srvsvc_NetShareInfo info
;
2154 struct srvsvc_NetShareInfo2 info2
;
2156 if (!str1
|| !str2
|| !p
) {
2160 /* check it's a supported varient */
2161 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2164 if (!check_share_info(uLevel
,str2
)) {
2171 /* Do we have a string ? */
2172 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2175 pull_ascii_fstring(sharename
,data
);
2181 /* only support disk share adds */
2182 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2186 offset
= IVAL(data
, 16);
2187 if (offset
>= mdrcnt
) {
2188 res
= ERRinvalidparam
;
2192 /* Do we have a string ? */
2193 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2196 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2198 offset
= IVAL(data
, 26);
2200 if (offset
>= mdrcnt
) {
2201 res
= ERRinvalidparam
;
2205 /* Do we have a string ? */
2206 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2210 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2211 offset
? (data
+offset
) : "", &converted_size
))
2213 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2221 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2222 rpc_srvsvc_dispatch
, conn
->server_info
,
2224 if (!NT_STATUS_IS_OK(status
)) {
2225 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2226 nt_errstr(status
)));
2227 res
= W_ERROR_V(ntstatus_to_werror(status
));
2231 info2
.name
= sharename
;
2232 info2
.type
= STYPE_DISKTREE
;
2233 info2
.comment
= comment
;
2234 info2
.permissions
= 0;
2235 info2
.max_users
= 0;
2236 info2
.current_users
= 0;
2237 info2
.path
= pathname
;
2238 info2
.password
= NULL
;
2240 info
.info2
= &info2
;
2242 status
= rpccli_srvsvc_NetShareAdd(cli
, mem_ctx
,
2243 cli
->srv_name_slash
,
2248 if (!NT_STATUS_IS_OK(status
)) {
2249 res
= W_ERROR_V(ntstatus_to_werror(status
));
2252 if (!W_ERROR_IS_OK(werr
)) {
2253 res
= W_ERROR_V(werr
);
2258 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2262 SSVAL(*rparam
,0,NERR_Success
);
2263 SSVAL(*rparam
,2,0); /* converter word */
2264 SSVAL(*rparam
,4,*rdata_len
);
2272 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2277 SSVAL(*rparam
,0,res
);
2282 /****************************************************************************
2283 view list of groups available
2284 ****************************************************************************/
2286 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2287 char *param
, int tpscnt
,
2288 char *data
, int tdscnt
,
2289 int mdrcnt
,int mprcnt
,
2290 char **rdata
,char **rparam
,
2291 int *rdata_len
,int *rparam_len
)
2295 int resume_context
, cli_buf_size
;
2296 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2297 char *str2
= skip_string(param
,tpscnt
,str1
);
2298 char *p
= skip_string(param
,tpscnt
,str2
);
2300 uint32_t num_groups
;
2301 uint32_t resume_handle
;
2302 struct rpc_pipe_client
*samr_pipe
;
2303 struct policy_handle samr_handle
, domain_handle
;
2306 if (!str1
|| !str2
|| !p
) {
2310 if (strcmp(str1
,"WrLeh") != 0) {
2315 * W-> resume context (number of users to skip)
2316 * r -> return parameter pointer to receive buffer
2317 * L -> length of receive buffer
2318 * e -> return parameter number of entries
2319 * h -> return parameter total number of users
2322 if (strcmp("B21",str2
) != 0) {
2326 status
= rpc_pipe_open_internal(
2327 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2328 conn
->server_info
, &samr_pipe
);
2329 if (!NT_STATUS_IS_OK(status
)) {
2330 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2331 nt_errstr(status
)));
2335 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2336 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2337 if (!NT_STATUS_IS_OK(status
)) {
2338 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2339 nt_errstr(status
)));
2343 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2344 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2345 get_global_sam_sid(), &domain_handle
);
2346 if (!NT_STATUS_IS_OK(status
)) {
2347 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2348 nt_errstr(status
)));
2349 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2353 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2354 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2355 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2356 "%d\n", resume_context
, cli_buf_size
));
2358 *rdata_len
= cli_buf_size
;
2359 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2366 errflags
= NERR_Success
;
2371 struct samr_SamArray
*sam_entries
;
2372 uint32_t num_entries
;
2374 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2379 if (!NT_STATUS_IS_OK(status
)) {
2380 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2381 "%s\n", nt_errstr(status
)));
2385 if (num_entries
== 0) {
2386 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2387 "no entries -- done\n"));
2391 for(i
=0; i
<num_entries
; i
++) {
2394 name
= sam_entries
->entries
[i
].name
.string
;
2396 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2397 /* set overflow error */
2398 DEBUG(3,("overflow on entry %d group %s\n", i
,
2404 /* truncate the name at 21 chars. */
2406 strlcpy(p
, name
, 21);
2407 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2409 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2414 if (errflags
!= NERR_Success
) {
2418 TALLOC_FREE(sam_entries
);
2421 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2422 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2424 *rdata_len
= PTR_DIFF(p
,*rdata
);
2427 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2431 SSVAL(*rparam
, 0, errflags
);
2432 SSVAL(*rparam
, 2, 0); /* converter word */
2433 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2434 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2439 /*******************************************************************
2440 Get groups that a user is a member of.
2441 ******************************************************************/
2443 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2444 char *param
, int tpscnt
,
2445 char *data
, int tdscnt
,
2446 int mdrcnt
,int mprcnt
,
2447 char **rdata
,char **rparam
,
2448 int *rdata_len
,int *rparam_len
)
2450 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2451 char *str2
= skip_string(param
,tpscnt
,str1
);
2452 char *UserName
= skip_string(param
,tpscnt
,str2
);
2453 char *p
= skip_string(param
,tpscnt
,UserName
);
2454 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2455 const char *level_string
;
2461 struct rpc_pipe_client
*samr_pipe
;
2462 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2463 struct lsa_String name
;
2464 struct lsa_Strings names
;
2465 struct samr_Ids type
, rid
;
2466 struct samr_RidWithAttributeArray
*rids
;
2469 if (!str1
|| !str2
|| !UserName
|| !p
) {
2474 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2479 /* check it's a supported varient */
2481 if ( strcmp(str1
,"zWrLeh") != 0 )
2486 level_string
= "B21";
2492 if (strcmp(level_string
,str2
) != 0)
2495 *rdata_len
= mdrcnt
+ 1024;
2496 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2501 SSVAL(*rparam
,0,NERR_Success
);
2502 SSVAL(*rparam
,2,0); /* converter word */
2505 endp
= *rdata
+ *rdata_len
;
2507 status
= rpc_pipe_open_internal(
2508 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2509 conn
->server_info
, &samr_pipe
);
2510 if (!NT_STATUS_IS_OK(status
)) {
2511 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2512 nt_errstr(status
)));
2516 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2517 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2518 if (!NT_STATUS_IS_OK(status
)) {
2519 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2520 nt_errstr(status
)));
2524 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2525 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2526 get_global_sam_sid(), &domain_handle
);
2527 if (!NT_STATUS_IS_OK(status
)) {
2528 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2529 nt_errstr(status
)));
2533 name
.string
= UserName
;
2535 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2536 &domain_handle
, 1, &name
,
2538 if (!NT_STATUS_IS_OK(status
)) {
2539 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2540 nt_errstr(status
)));
2544 if (type
.ids
[0] != SID_NAME_USER
) {
2545 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2546 sid_type_lookup(type
.ids
[0])));
2550 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2552 SAMR_USER_ACCESS_GET_GROUPS
,
2553 rid
.ids
[0], &user_handle
);
2554 if (!NT_STATUS_IS_OK(status
)) {
2555 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2556 nt_errstr(status
)));
2560 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2561 &user_handle
, &rids
);
2562 if (!NT_STATUS_IS_OK(status
)) {
2563 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2564 nt_errstr(status
)));
2568 for (i
=0; i
<rids
->count
; i
++) {
2570 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2572 1, &rids
->rids
[i
].rid
,
2574 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2575 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2581 *rdata_len
= PTR_DIFF(p
,*rdata
);
2583 SSVAL(*rparam
,4,count
); /* is this right?? */
2584 SSVAL(*rparam
,6,count
); /* is this right?? */
2589 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2591 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2593 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2598 /*******************************************************************
2600 ******************************************************************/
2602 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2603 char *param
, int tpscnt
,
2604 char *data
, int tdscnt
,
2605 int mdrcnt
,int mprcnt
,
2606 char **rdata
,char **rparam
,
2607 int *rdata_len
,int *rparam_len
)
2612 int i
, resume_context
, cli_buf_size
;
2613 uint32_t resume_handle
;
2615 struct rpc_pipe_client
*samr_pipe
;
2616 struct policy_handle samr_handle
, domain_handle
;
2619 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2620 char *str2
= skip_string(param
,tpscnt
,str1
);
2621 char *p
= skip_string(param
,tpscnt
,str2
);
2624 if (!str1
|| !str2
|| !p
) {
2628 if (strcmp(str1
,"WrLeh") != 0)
2631 * W-> resume context (number of users to skip)
2632 * r -> return parameter pointer to receive buffer
2633 * L -> length of receive buffer
2634 * e -> return parameter number of entries
2635 * h -> return parameter total number of users
2638 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2639 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2640 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2641 resume_context
, cli_buf_size
));
2644 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2649 /* check it's a supported varient */
2650 if (strcmp("B21",str2
) != 0)
2653 *rdata_len
= cli_buf_size
;
2654 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2660 endp
= *rdata
+ *rdata_len
;
2662 status
= rpc_pipe_open_internal(
2663 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2664 conn
->server_info
, &samr_pipe
);
2665 if (!NT_STATUS_IS_OK(status
)) {
2666 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2667 nt_errstr(status
)));
2671 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2672 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2673 if (!NT_STATUS_IS_OK(status
)) {
2674 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2675 nt_errstr(status
)));
2679 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2680 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2681 get_global_sam_sid(), &domain_handle
);
2682 if (!NT_STATUS_IS_OK(status
)) {
2683 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2684 nt_errstr(status
)));
2685 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2689 errflags
=NERR_Success
;
2694 struct samr_SamArray
*sam_entries
;
2695 uint32_t num_entries
;
2697 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2703 if (!NT_STATUS_IS_OK(status
)) {
2704 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2705 "%s\n", nt_errstr(status
)));
2709 if (num_entries
== 0) {
2710 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2711 "no entries -- done\n"));
2715 for (i
=0; i
<num_entries
; i
++) {
2718 name
= sam_entries
->entries
[i
].name
.string
;
2720 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2721 &&(strlen(name
)<=21)) {
2722 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2723 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2724 "username %s\n",count_sent
,p
));
2728 /* set overflow error */
2729 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2730 "username %s\n",count_sent
,name
));
2736 if (errflags
!= NERR_Success
) {
2740 TALLOC_FREE(sam_entries
);
2743 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2744 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2746 *rdata_len
= PTR_DIFF(p
,*rdata
);
2748 SSVAL(*rparam
,0,errflags
);
2749 SSVAL(*rparam
,2,0); /* converter word */
2750 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2751 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2756 /****************************************************************************
2757 Get the time of day info.
2758 ****************************************************************************/
2760 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2761 char *param
, int tpscnt
,
2762 char *data
, int tdscnt
,
2763 int mdrcnt
,int mprcnt
,
2764 char **rdata
,char **rparam
,
2765 int *rdata_len
,int *rparam_len
)
2768 time_t unixdate
= time(NULL
);
2772 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2778 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2783 SSVAL(*rparam
,0,NERR_Success
);
2784 SSVAL(*rparam
,2,0); /* converter word */
2788 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2789 by NT in a "net time" operation,
2790 it seems to ignore the one below */
2792 /* the client expects to get localtime, not GMT, in this bit
2793 (I think, this needs testing) */
2794 t
= localtime(&unixdate
);
2799 SIVAL(p
,4,0); /* msecs ? */
2800 SCVAL(p
,8,t
->tm_hour
);
2801 SCVAL(p
,9,t
->tm_min
);
2802 SCVAL(p
,10,t
->tm_sec
);
2803 SCVAL(p
,11,0); /* hundredths of seconds */
2804 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2805 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2806 SCVAL(p
,16,t
->tm_mday
);
2807 SCVAL(p
,17,t
->tm_mon
+ 1);
2808 SSVAL(p
,18,1900+t
->tm_year
);
2809 SCVAL(p
,20,t
->tm_wday
);
2814 /****************************************************************************
2815 Set the user password.
2816 *****************************************************************************/
2818 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2819 char *param
, int tpscnt
,
2820 char *data
, int tdscnt
,
2821 int mdrcnt
,int mprcnt
,
2822 char **rdata
,char **rparam
,
2823 int *rdata_len
,int *rparam_len
)
2825 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2828 fstring pass1
,pass2
;
2830 /* Skip 2 strings. */
2831 p
= skip_string(param
,tpscnt
,np
);
2832 p
= skip_string(param
,tpscnt
,p
);
2838 /* Do we have a string ? */
2839 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2842 pull_ascii_fstring(user
,p
);
2844 p
= skip_string(param
,tpscnt
,p
);
2849 memset(pass1
,'\0',sizeof(pass1
));
2850 memset(pass2
,'\0',sizeof(pass2
));
2852 * We use 31 here not 32 as we're checking
2853 * the last byte we want to access is safe.
2855 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2859 memcpy(pass2
,p
+16,16);
2862 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2869 SSVAL(*rparam
,0,NERR_badpass
);
2870 SSVAL(*rparam
,2,0); /* converter word */
2872 DEBUG(3,("Set password for <%s>\n",user
));
2875 * Attempt to verify the old password against smbpasswd entries
2876 * Win98 clients send old and new password in plaintext for this call.
2880 struct auth_serversupplied_info
*server_info
= NULL
;
2881 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2883 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2886 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2887 SSVAL(*rparam
,0,NERR_Success
);
2891 TALLOC_FREE(server_info
);
2893 data_blob_clear_free(&password
);
2897 * If the plaintext change failed, attempt
2898 * the old encrypted method. NT will generate this
2899 * after trying the samr method. Note that this
2900 * method is done as a last resort as this
2901 * password change method loses the NT password hash
2902 * and cannot change the UNIX password as no plaintext
2906 if(SVAL(*rparam
,0) != NERR_Success
) {
2907 struct samu
*hnd
= NULL
;
2909 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2911 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2912 SSVAL(*rparam
,0,NERR_Success
);
2919 memset((char *)pass1
,'\0',sizeof(fstring
));
2920 memset((char *)pass2
,'\0',sizeof(fstring
));
2925 /****************************************************************************
2926 Set the user password (SamOEM version - gets plaintext).
2927 ****************************************************************************/
2929 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2930 char *param
, int tpscnt
,
2931 char *data
, int tdscnt
,
2932 int mdrcnt
,int mprcnt
,
2933 char **rdata
,char **rparam
,
2934 int *rdata_len
,int *rparam_len
)
2937 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2939 TALLOC_CTX
*mem_ctx
= talloc_tos();
2941 struct rpc_pipe_client
*cli
= NULL
;
2942 struct lsa_AsciiString server
, account
;
2943 struct samr_CryptPassword password
;
2944 struct samr_Password hash
;
2945 int errcode
= NERR_badpass
;
2949 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2959 SSVAL(*rparam
,0,NERR_badpass
);
2962 * Check the parameter definition is correct.
2965 /* Do we have a string ? */
2966 if (skip_string(param
,tpscnt
,p
) == 0) {
2969 if(!strequal(p
, "zsT")) {
2970 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2973 p
= skip_string(param
, tpscnt
, p
);
2978 /* Do we have a string ? */
2979 if (skip_string(param
,tpscnt
,p
) == 0) {
2982 if(!strequal(p
, "B516B16")) {
2983 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2986 p
= skip_string(param
,tpscnt
,p
);
2990 /* Do we have a string ? */
2991 if (skip_string(param
,tpscnt
,p
) == 0) {
2994 p
+= pull_ascii_fstring(user
,p
);
2996 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2998 if (tdscnt
!= 532) {
2999 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3003 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3004 if (bufsize
!= 532) {
3005 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3009 memcpy(password
.data
, data
, 516);
3010 memcpy(hash
.hash
, data
+516, 16);
3012 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3013 rpc_samr_dispatch
, conn
->server_info
,
3015 if (!NT_STATUS_IS_OK(status
)) {
3016 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3017 nt_errstr(status
)));
3018 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3022 init_lsa_AsciiString(&server
, global_myname());
3023 init_lsa_AsciiString(&account
, user
);
3025 status
= rpccli_samr_OemChangePasswordUser2(cli
, mem_ctx
,
3030 if (!NT_STATUS_IS_OK(status
)) {
3031 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3035 errcode
= NERR_Success
;
3037 SSVAL(*rparam
,0,errcode
);
3038 SSVAL(*rparam
,2,0); /* converter word */
3043 /****************************************************************************
3046 ****************************************************************************/
3048 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
3049 char *param
, int tpscnt
,
3050 char *data
, int tdscnt
,
3051 int mdrcnt
,int mprcnt
,
3052 char **rdata
,char **rparam
,
3053 int *rdata_len
,int *rparam_len
)
3055 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3056 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3057 char *str2
= skip_string(param
,tpscnt
,str1
);
3058 char *p
= skip_string(param
,tpscnt
,str2
);
3062 WERROR werr
= WERR_OK
;
3064 TALLOC_CTX
*mem_ctx
= talloc_tos();
3066 struct rpc_pipe_client
*cli
= NULL
;
3067 struct policy_handle handle
;
3068 struct spoolss_DevmodeContainer devmode_ctr
;
3069 enum spoolss_JobControl command
;
3071 if (!str1
|| !str2
|| !p
) {
3075 * We use 1 here not 2 as we're checking
3076 * the last byte we want to access is safe.
3078 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3081 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3084 /* check it's a supported varient */
3085 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3089 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3095 ZERO_STRUCT(handle
);
3097 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3098 if (!NT_STATUS_IS_OK(status
)) {
3099 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3100 nt_errstr(status
)));
3101 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3105 ZERO_STRUCT(devmode_ctr
);
3107 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3111 JOB_ACCESS_ADMINISTER
,
3114 if (!NT_STATUS_IS_OK(status
)) {
3115 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3118 if (!W_ERROR_IS_OK(werr
)) {
3119 errcode
= W_ERROR_V(werr
);
3123 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3124 * and NERR_DestNotFound if share did not exist */
3126 errcode
= NERR_Success
;
3129 case 81: /* delete */
3130 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3132 case 82: /* pause */
3133 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3135 case 83: /* resume */
3136 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3139 errcode
= NERR_notsupported
;
3143 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3146 NULL
, /* unique ptr ctr */
3149 if (!NT_STATUS_IS_OK(status
)) {
3150 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3153 if (!W_ERROR_IS_OK(werr
)) {
3154 errcode
= W_ERROR_V(werr
);
3159 if (cli
&& is_valid_policy_hnd(&handle
)) {
3160 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3163 SSVAL(*rparam
,0,errcode
);
3164 SSVAL(*rparam
,2,0); /* converter word */
3169 /****************************************************************************
3170 Purge a print queue - or pause or resume it.
3171 ****************************************************************************/
3173 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
3174 char *param
, int tpscnt
,
3175 char *data
, int tdscnt
,
3176 int mdrcnt
,int mprcnt
,
3177 char **rdata
,char **rparam
,
3178 int *rdata_len
,int *rparam_len
)
3180 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3181 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3182 char *str2
= skip_string(param
,tpscnt
,str1
);
3183 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3184 int errcode
= NERR_notsupported
;
3185 WERROR werr
= WERR_OK
;
3188 TALLOC_CTX
*mem_ctx
= talloc_tos();
3189 struct rpc_pipe_client
*cli
= NULL
;
3190 struct policy_handle handle
;
3191 struct spoolss_SetPrinterInfoCtr info_ctr
;
3192 struct spoolss_DevmodeContainer devmode_ctr
;
3193 struct sec_desc_buf secdesc_ctr
;
3194 enum spoolss_PrinterControl command
;
3196 if (!str1
|| !str2
|| !QueueName
) {
3200 /* check it's a supported varient */
3201 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3205 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3211 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3215 ZERO_STRUCT(handle
);
3217 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3218 if (!NT_STATUS_IS_OK(status
)) {
3219 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3220 nt_errstr(status
)));
3221 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3225 ZERO_STRUCT(devmode_ctr
);
3227 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3231 SEC_FLAG_MAXIMUM_ALLOWED
,
3234 if (!NT_STATUS_IS_OK(status
)) {
3235 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3238 if (!W_ERROR_IS_OK(werr
)) {
3239 errcode
= W_ERROR_V(werr
);
3244 case 74: /* Pause queue */
3245 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3247 case 75: /* Resume queue */
3248 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3250 case 103: /* Purge */
3251 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3254 werr
= WERR_NOT_SUPPORTED
;
3258 if (!W_ERROR_IS_OK(werr
)) {
3259 errcode
= W_ERROR_V(werr
);
3263 ZERO_STRUCT(info_ctr
);
3264 ZERO_STRUCT(secdesc_ctr
);
3266 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3273 if (!NT_STATUS_IS_OK(status
)) {
3274 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3277 if (!W_ERROR_IS_OK(werr
)) {
3278 errcode
= W_ERROR_V(werr
);
3282 errcode
= W_ERROR_V(werr
);
3286 if (cli
&& is_valid_policy_hnd(&handle
)) {
3287 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3290 SSVAL(*rparam
,0,errcode
);
3291 SSVAL(*rparam
,2,0); /* converter word */
3296 /****************************************************************************
3297 set the property of a print job (undocumented?)
3298 ? function = 0xb -> set name of print job
3299 ? function = 0x6 -> move print job up/down
3300 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3301 or <WWsTP> <WB21BB16B10zWWzDDz>
3302 ****************************************************************************/
3304 static int check_printjob_info(struct pack_desc
* desc
,
3305 int uLevel
, char* id
)
3307 desc
->subformat
= NULL
;
3309 case 0: desc
->format
= "W"; break;
3310 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3311 case 2: desc
->format
= "WWzWWDDzz"; break;
3312 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3313 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3315 DEBUG(0,("check_printjob_info: invalid level %d\n",
3319 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3320 DEBUG(0,("check_printjob_info: invalid format %s\n",
3321 id
? id
: "<NULL>" ));
3327 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
3328 char *param
, int tpscnt
,
3329 char *data
, int tdscnt
,
3330 int mdrcnt
,int mprcnt
,
3331 char **rdata
,char **rparam
,
3332 int *rdata_len
,int *rparam_len
)
3334 struct pack_desc desc
;
3335 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3336 char *str2
= skip_string(param
,tpscnt
,str1
);
3337 char *p
= skip_string(param
,tpscnt
,str2
);
3340 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3341 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3344 TALLOC_CTX
*mem_ctx
= talloc_tos();
3347 struct rpc_pipe_client
*cli
= NULL
;
3348 struct policy_handle handle
;
3349 struct spoolss_DevmodeContainer devmode_ctr
;
3350 struct spoolss_JobInfoContainer ctr
;
3351 union spoolss_JobInfo info
;
3352 struct spoolss_SetJobInfo1 info1
;
3354 if (!str1
|| !str2
|| !p
) {
3358 * We use 1 here not 2 as we're checking
3359 * the last byte we want to access is safe.
3361 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3364 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3367 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3374 /* check it's a supported varient */
3375 if ((strcmp(str1
,"WWsTP")) ||
3376 (!check_printjob_info(&desc
,uLevel
,str2
)))
3379 errcode
= NERR_notsupported
;
3383 /* change print job name, data gives the name */
3389 ZERO_STRUCT(handle
);
3391 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
3392 if (!NT_STATUS_IS_OK(status
)) {
3393 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3394 nt_errstr(status
)));
3395 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3399 ZERO_STRUCT(devmode_ctr
);
3401 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3408 if (!NT_STATUS_IS_OK(status
)) {
3409 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3412 if (!W_ERROR_IS_OK(werr
)) {
3413 errcode
= W_ERROR_V(werr
);
3417 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3423 if (!W_ERROR_IS_OK(werr
)) {
3424 errcode
= W_ERROR_V(werr
);
3430 info1
.job_id
= info
.info1
.job_id
;
3431 info1
.printer_name
= info
.info1
.printer_name
;
3432 info1
.user_name
= info
.info1
.user_name
;
3433 info1
.document_name
= data
;
3434 info1
.data_type
= info
.info1
.data_type
;
3435 info1
.text_status
= info
.info1
.text_status
;
3436 info1
.status
= info
.info1
.status
;
3437 info1
.priority
= info
.info1
.priority
;
3438 info1
.position
= info
.info1
.position
;
3439 info1
.total_pages
= info
.info1
.total_pages
;
3440 info1
.pages_printed
= info
.info1
.pages_printed
;
3441 info1
.submitted
= info
.info1
.submitted
;
3444 ctr
.info
.info1
= &info1
;
3446 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3452 if (!NT_STATUS_IS_OK(status
)) {
3453 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3456 if (!W_ERROR_IS_OK(werr
)) {
3457 errcode
= W_ERROR_V(werr
);
3461 errcode
= NERR_Success
;
3464 if (cli
&& is_valid_policy_hnd(&handle
)) {
3465 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3468 SSVALS(*rparam
,0,errcode
);
3469 SSVAL(*rparam
,2,0); /* converter word */
3475 /****************************************************************************
3476 Get info about the server.
3477 ****************************************************************************/
3479 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3480 char *param
, int tpscnt
,
3481 char *data
, int tdscnt
,
3482 int mdrcnt
,int mprcnt
,
3483 char **rdata
,char **rparam
,
3484 int *rdata_len
,int *rparam_len
)
3486 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3487 char *str2
= skip_string(param
,tpscnt
,str1
);
3488 char *p
= skip_string(param
,tpscnt
,str2
);
3489 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3495 TALLOC_CTX
*mem_ctx
= talloc_tos();
3496 struct rpc_pipe_client
*cli
= NULL
;
3497 union srvsvc_NetSrvInfo info
;
3500 if (!str1
|| !str2
|| !p
) {
3504 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3506 /* check it's a supported varient */
3507 if (!prefix_ok(str1
,"WrLh")) {
3513 if (strcmp(str2
,"B16") != 0) {
3519 if (strcmp(str2
,"B16BBDz") != 0) {
3525 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3531 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3537 if (strcmp(str2
,"DN") != 0) {
3543 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3552 *rdata_len
= mdrcnt
;
3553 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3559 p2
= p
+ struct_len
;
3561 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3562 rpc_srvsvc_dispatch
, conn
->server_info
,
3564 if (!NT_STATUS_IS_OK(status
)) {
3565 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3566 nt_errstr(status
)));
3567 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3571 status
= rpccli_srvsvc_NetSrvGetInfo(cli
, mem_ctx
,
3576 if (!NT_STATUS_IS_OK(status
)) {
3577 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3580 if (!W_ERROR_IS_OK(werr
)) {
3581 errcode
= W_ERROR_V(werr
);
3585 if (info
.info101
== NULL
) {
3586 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3591 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3592 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3596 SCVAL(p
,0,info
.info101
->version_major
);
3597 SCVAL(p
,1,info
.info101
->version_minor
);
3598 SIVAL(p
,2,info
.info101
->server_type
);
3600 if (mdrcnt
== struct_len
) {
3603 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3604 if (mdrcnt
- struct_len
<= 0) {
3608 info
.info101
->comment
,
3609 MIN(mdrcnt
- struct_len
,
3610 MAX_SERVER_STRING_LENGTH
),
3612 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3620 return False
; /* not yet implemented */
3623 errcode
= NERR_Success
;
3627 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3630 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3634 SSVAL(*rparam
,0,errcode
);
3635 SSVAL(*rparam
,2,0); /* converter word */
3636 SSVAL(*rparam
,4,*rdata_len
);
3641 /****************************************************************************
3642 Get info about the server.
3643 ****************************************************************************/
3645 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3646 char *param
, int tpscnt
,
3647 char *data
, int tdscnt
,
3648 int mdrcnt
,int mprcnt
,
3649 char **rdata
,char **rparam
,
3650 int *rdata_len
,int *rparam_len
)
3652 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3653 char *str2
= skip_string(param
,tpscnt
,str1
);
3654 char *p
= skip_string(param
,tpscnt
,str2
);
3657 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3659 if (!str1
|| !str2
|| !p
) {
3663 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3666 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3671 /* check it's a supported varient */
3672 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3676 *rdata_len
= mdrcnt
+ 1024;
3677 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3682 SSVAL(*rparam
,0,NERR_Success
);
3683 SSVAL(*rparam
,2,0); /* converter word */
3686 endp
= *rdata
+ *rdata_len
;
3688 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3693 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3694 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3696 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3702 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3703 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3704 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3710 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3711 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3713 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3719 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3720 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3723 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3724 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3725 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3731 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3732 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3733 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3739 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3741 SSVAL(*rparam
,4,*rdata_len
);
3746 /****************************************************************************
3747 get info about a user
3749 struct user_info_11 {
3750 char usri11_name[21]; 0-20
3752 char *usri11_comment; 22-25
3753 char *usri11_usr_comment; 26-29
3754 unsigned short usri11_priv; 30-31
3755 unsigned long usri11_auth_flags; 32-35
3756 long usri11_password_age; 36-39
3757 char *usri11_homedir; 40-43
3758 char *usri11_parms; 44-47
3759 long usri11_last_logon; 48-51
3760 long usri11_last_logoff; 52-55
3761 unsigned short usri11_bad_pw_count; 56-57
3762 unsigned short usri11_num_logons; 58-59
3763 char *usri11_logon_server; 60-63
3764 unsigned short usri11_country_code; 64-65
3765 char *usri11_workstations; 66-69
3766 unsigned long usri11_max_storage; 70-73
3767 unsigned short usri11_units_per_week; 74-75
3768 unsigned char *usri11_logon_hours; 76-79
3769 unsigned short usri11_code_page; 80-81
3774 usri11_name specifies the user name for which information is retrieved
3776 usri11_pad aligns the next data structure element to a word boundary
3778 usri11_comment is a null terminated ASCII comment
3780 usri11_user_comment is a null terminated ASCII comment about the user
3782 usri11_priv specifies the level of the privilege assigned to the user.
3783 The possible values are:
3785 Name Value Description
3786 USER_PRIV_GUEST 0 Guest privilege
3787 USER_PRIV_USER 1 User privilege
3788 USER_PRV_ADMIN 2 Administrator privilege
3790 usri11_auth_flags specifies the account operator privileges. The
3791 possible values are:
3793 Name Value Description
3794 AF_OP_PRINT 0 Print operator
3797 Leach, Naik [Page 28]
3801 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3804 AF_OP_COMM 1 Communications operator
3805 AF_OP_SERVER 2 Server operator
3806 AF_OP_ACCOUNTS 3 Accounts operator
3809 usri11_password_age specifies how many seconds have elapsed since the
3810 password was last changed.
3812 usri11_home_dir points to a null terminated ASCII string that contains
3813 the path name of the user's home directory.
3815 usri11_parms points to a null terminated ASCII string that is set
3816 aside for use by applications.
3818 usri11_last_logon specifies the time when the user last logged on.
3819 This value is stored as the number of seconds elapsed since
3820 00:00:00, January 1, 1970.
3822 usri11_last_logoff specifies the time when the user last logged off.
3823 This value is stored as the number of seconds elapsed since
3824 00:00:00, January 1, 1970. A value of 0 means the last logoff
3827 usri11_bad_pw_count specifies the number of incorrect passwords
3828 entered since the last successful logon.
3830 usri11_log1_num_logons specifies the number of times this user has
3831 logged on. A value of -1 means the number of logons is unknown.
3833 usri11_logon_server points to a null terminated ASCII string that
3834 contains the name of the server to which logon requests are sent.
3835 A null string indicates logon requests should be sent to the
3838 usri11_country_code specifies the country code for the user's language
3841 usri11_workstations points to a null terminated ASCII string that
3842 contains the names of workstations the user may log on from.
3843 There may be up to 8 workstations, with the names separated by
3844 commas. A null strings indicates there are no restrictions.
3846 usri11_max_storage specifies the maximum amount of disk space the user
3847 can occupy. A value of 0xffffffff indicates there are no
3850 usri11_units_per_week specifies the equal number of time units into
3851 which a week is divided. This value must be equal to 168.
3853 usri11_logon_hours points to a 21 byte (168 bits) string that
3854 specifies the time during which the user can log on. Each bit
3855 represents one unique hour in a week. The first bit (bit 0, word
3856 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3860 Leach, Naik [Page 29]
3864 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3867 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3868 are no restrictions.
3870 usri11_code_page specifies the code page for the user's language of
3873 All of the pointers in this data structure need to be treated
3874 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3875 to be ignored. The converter word returned in the parameters section
3876 needs to be subtracted from the lower 16 bits to calculate an offset
3877 into the return buffer where this ASCII string resides.
3879 There is no auxiliary data in the response.
3881 ****************************************************************************/
3883 #define usri11_name 0
3884 #define usri11_pad 21
3885 #define usri11_comment 22
3886 #define usri11_usr_comment 26
3887 #define usri11_full_name 30
3888 #define usri11_priv 34
3889 #define usri11_auth_flags 36
3890 #define usri11_password_age 40
3891 #define usri11_homedir 44
3892 #define usri11_parms 48
3893 #define usri11_last_logon 52
3894 #define usri11_last_logoff 56
3895 #define usri11_bad_pw_count 60
3896 #define usri11_num_logons 62
3897 #define usri11_logon_server 64
3898 #define usri11_country_code 68
3899 #define usri11_workstations 70
3900 #define usri11_max_storage 74
3901 #define usri11_units_per_week 78
3902 #define usri11_logon_hours 80
3903 #define usri11_code_page 84
3904 #define usri11_end 86
3906 #define USER_PRIV_GUEST 0
3907 #define USER_PRIV_USER 1
3908 #define USER_PRIV_ADMIN 2
3910 #define AF_OP_PRINT 0
3911 #define AF_OP_COMM 1
3912 #define AF_OP_SERVER 2
3913 #define AF_OP_ACCOUNTS 3
3916 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3917 char *param
, int tpscnt
,
3918 char *data
, int tdscnt
,
3919 int mdrcnt
,int mprcnt
,
3920 char **rdata
,char **rparam
,
3921 int *rdata_len
,int *rparam_len
)
3923 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3924 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3925 char *str2
= skip_string(param
,tpscnt
,str1
);
3926 char *UserName
= skip_string(param
,tpscnt
,str2
);
3927 char *p
= skip_string(param
,tpscnt
,UserName
);
3928 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3931 const char *level_string
;
3933 /* get NIS home of a previously validated user - simeon */
3934 /* With share level security vuid will always be zero.
3935 Don't depend on vuser being non-null !!. JRA */
3936 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3938 DEBUG(3,(" Username of UID %d is %s\n",
3939 (int)vuser
->server_info
->utok
.uid
,
3940 vuser
->server_info
->unix_name
));
3943 if (!str1
|| !str2
|| !UserName
|| !p
) {
3948 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3953 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3955 /* check it's a supported variant */
3956 if (strcmp(str1
,"zWrLh") != 0) {
3960 case 0: level_string
= "B21"; break;
3961 case 1: level_string
= "B21BB16DWzzWz"; break;
3962 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3963 case 10: level_string
= "B21Bzzz"; break;
3964 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3965 default: return False
;
3968 if (strcmp(level_string
,str2
) != 0) {
3972 *rdata_len
= mdrcnt
+ 1024;
3973 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3978 SSVAL(*rparam
,0,NERR_Success
);
3979 SSVAL(*rparam
,2,0); /* converter word */
3982 endp
= *rdata
+ *rdata_len
;
3983 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3989 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3992 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3997 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3998 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3999 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4004 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4005 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4006 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4011 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4012 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4013 strlcpy(p2
,((vuser
!= NULL
)
4014 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
4015 : UserName
),PTR_DIFF(endp
,p2
));
4016 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4023 const char *homedir
= "";
4024 if (vuser
!= NULL
) {
4025 homedir
= pdb_get_homedir(
4026 vuser
->server_info
->sam_account
);
4028 /* modelled after NTAS 3.51 reply */
4029 SSVAL(p
,usri11_priv
,
4030 (get_current_uid(conn
) == sec_initial_uid())?
4031 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4032 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4033 SIVALS(p
,usri11_password_age
,-1); /* password age */
4034 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4035 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4036 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4040 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4041 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4042 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4046 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4047 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4048 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4049 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4050 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4051 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4052 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4056 SSVAL(p
,usri11_country_code
,0); /* country code */
4058 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4059 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4060 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4065 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4066 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4067 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4069 /* a simple way to get logon hours at all times. */
4071 SCVAL(p2
,21,0); /* fix zero termination */
4072 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4077 SSVAL(p
,usri11_code_page
,0); /* code page */
4080 if (uLevel
== 1 || uLevel
== 2) {
4081 memset(p
+22,' ',16); /* password */
4082 SIVALS(p
,38,-1); /* password age */
4084 (get_current_uid(conn
) == sec_initial_uid())?
4085 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4086 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4087 strlcpy(p2
, vuser
? pdb_get_homedir(
4088 vuser
->server_info
->sam_account
) : "",
4090 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4094 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4096 SSVAL(p
,52,0); /* flags */
4097 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4098 strlcpy(p2
, vuser
? pdb_get_logon_script(
4099 vuser
->server_info
->sam_account
) : "",
4101 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4106 SIVAL(p
,60,0); /* auth_flags */
4107 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
4108 strlcpy(p2
,((vuser
!= NULL
)
4109 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
4110 : UserName
),PTR_DIFF(endp
,p2
));
4111 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4115 SIVAL(p
,68,0); /* urs_comment */
4116 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
4117 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4118 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4122 SIVAL(p
,76,0); /* workstations */
4123 SIVAL(p
,80,0); /* last_logon */
4124 SIVAL(p
,84,0); /* last_logoff */
4125 SIVALS(p
,88,-1); /* acct_expires */
4126 SIVALS(p
,92,-1); /* max_storage */
4127 SSVAL(p
,96,168); /* units_per_week */
4128 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4131 SSVALS(p
,102,-1); /* bad_pw_count */
4132 SSVALS(p
,104,-1); /* num_logons */
4133 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4135 TALLOC_CTX
*ctx
= talloc_tos();
4136 int space_rem
= *rdata_len
- (p2
- *rdata
);
4139 if (space_rem
<= 0) {
4142 tmp
= talloc_strdup(ctx
, "\\\\%L");
4146 tmp
= talloc_sub_basic(ctx
,
4159 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4163 SSVAL(p
,110,49); /* country_code */
4164 SSVAL(p
,112,860); /* code page */
4168 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4170 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4175 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
4176 char *param
, int tpscnt
,
4177 char *data
, int tdscnt
,
4178 int mdrcnt
,int mprcnt
,
4179 char **rdata
,char **rparam
,
4180 int *rdata_len
,int *rparam_len
)
4182 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4183 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4184 char *str2
= skip_string(param
,tpscnt
,str1
);
4185 char *p
= skip_string(param
,tpscnt
,str2
);
4187 struct pack_desc desc
;
4189 /* With share level security vuid will always be zero.
4190 Don't depend on vuser being non-null !!. JRA */
4191 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4193 if (!str1
|| !str2
|| !p
) {
4198 DEBUG(3,(" Username of UID %d is %s\n",
4199 (int)vuser
->server_info
->utok
.uid
,
4200 vuser
->server_info
->unix_name
));
4203 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4204 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4209 memset((char *)&desc
,'\0',sizeof(desc
));
4211 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4213 /* check it's a supported varient */
4214 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4217 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4221 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4228 desc
.buflen
= mdrcnt
;
4229 desc
.subformat
= NULL
;
4232 if (init_package(&desc
,1,0)) {
4233 PACKI(&desc
,"W",0); /* code */
4234 PACKS(&desc
,"B21",name
); /* eff. name */
4235 PACKS(&desc
,"B",""); /* pad */
4237 (get_current_uid(conn
) == sec_initial_uid())?
4238 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4239 PACKI(&desc
,"D",0); /* auth flags XXX */
4240 PACKI(&desc
,"W",0); /* num logons */
4241 PACKI(&desc
,"W",0); /* bad pw count */
4242 PACKI(&desc
,"D",0); /* last logon */
4243 PACKI(&desc
,"D",-1); /* last logoff */
4244 PACKI(&desc
,"D",-1); /* logoff time */
4245 PACKI(&desc
,"D",-1); /* kickoff time */
4246 PACKI(&desc
,"D",0); /* password age */
4247 PACKI(&desc
,"D",0); /* password can change */
4248 PACKI(&desc
,"D",-1); /* password must change */
4252 fstrcpy(mypath
,"\\\\");
4253 fstrcat(mypath
,get_local_machine_name());
4255 PACKS(&desc
,"z",mypath
); /* computer */
4258 PACKS(&desc
,"z",lp_workgroup());/* domain */
4259 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
4260 vuser
->server_info
->sam_account
) : ""); /* script path */
4261 PACKI(&desc
,"D",0x00000000); /* reserved */
4264 *rdata_len
= desc
.usedlen
;
4266 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4270 SSVALS(*rparam
,0,desc
.errcode
);
4272 SSVAL(*rparam
,4,desc
.neededlen
);
4274 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4279 /****************************************************************************
4280 api_WAccessGetUserPerms
4281 ****************************************************************************/
4283 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
4284 char *param
, int tpscnt
,
4285 char *data
, int tdscnt
,
4286 int mdrcnt
,int mprcnt
,
4287 char **rdata
,char **rparam
,
4288 int *rdata_len
,int *rparam_len
)
4290 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4291 char *str2
= skip_string(param
,tpscnt
,str1
);
4292 char *user
= skip_string(param
,tpscnt
,str2
);
4293 char *resource
= skip_string(param
,tpscnt
,user
);
4295 if (!str1
|| !str2
|| !user
|| !resource
) {
4299 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4302 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4304 /* check it's a supported varient */
4305 if (strcmp(str1
,"zzh") != 0) {
4308 if (strcmp(str2
,"") != 0) {
4313 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4317 SSVALS(*rparam
,0,0); /* errorcode */
4318 SSVAL(*rparam
,2,0); /* converter word */
4319 SSVAL(*rparam
,4,0x7f); /* permission flags */
4324 /****************************************************************************
4325 api_WPrintJobEnumerate
4326 ****************************************************************************/
4328 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
4329 char *param
, int tpscnt
,
4330 char *data
, int tdscnt
,
4331 int mdrcnt
,int mprcnt
,
4332 char **rdata
,char **rparam
,
4333 int *rdata_len
,int *rparam_len
)
4335 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4336 char *str2
= skip_string(param
,tpscnt
,str1
);
4337 char *p
= skip_string(param
,tpscnt
,str2
);
4341 struct pack_desc desc
;
4344 TALLOC_CTX
*mem_ctx
= talloc_tos();
4347 struct rpc_pipe_client
*cli
= NULL
;
4348 struct policy_handle handle
;
4349 struct spoolss_DevmodeContainer devmode_ctr
;
4350 union spoolss_JobInfo info
;
4352 if (!str1
|| !str2
|| !p
) {
4356 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4358 memset((char *)&desc
,'\0',sizeof(desc
));
4359 memset((char *)&status
,'\0',sizeof(status
));
4361 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4363 /* check it's a supported varient */
4364 if (strcmp(str1
,"WWrLh") != 0) {
4367 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4371 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4375 ZERO_STRUCT(handle
);
4377 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4378 if (!NT_STATUS_IS_OK(status
)) {
4379 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4380 nt_errstr(status
)));
4381 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4385 ZERO_STRUCT(devmode_ctr
);
4387 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4394 if (!NT_STATUS_IS_OK(status
)) {
4395 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4398 if (!W_ERROR_IS_OK(werr
)) {
4399 desc
.errcode
= W_ERROR_V(werr
);
4403 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4409 if (!W_ERROR_IS_OK(werr
)) {
4410 desc
.errcode
= W_ERROR_V(werr
);
4415 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4420 desc
.buflen
= mdrcnt
;
4423 * Don't return data but need to get correct length
4424 * init_package will return wrong size if buflen=0
4426 desc
.buflen
= getlen(desc
.format
);
4427 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4430 if (init_package(&desc
,1,0)) {
4431 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4432 *rdata_len
= desc
.usedlen
;
4434 desc
.errcode
= NERR_JobNotFound
;
4438 if (cli
&& is_valid_policy_hnd(&handle
)) {
4439 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4443 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4447 SSVALS(*rparam
,0,desc
.errcode
);
4449 SSVAL(*rparam
,4,desc
.neededlen
);
4453 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4458 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
4459 char *param
, int tpscnt
,
4460 char *data
, int tdscnt
,
4461 int mdrcnt
,int mprcnt
,
4462 char **rdata
,char **rparam
,
4463 int *rdata_len
,int *rparam_len
)
4465 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4466 char *str2
= skip_string(param
,tpscnt
,str1
);
4467 char *p
= skip_string(param
,tpscnt
,str2
);
4471 struct pack_desc desc
;
4473 TALLOC_CTX
*mem_ctx
= talloc_tos();
4476 struct rpc_pipe_client
*cli
= NULL
;
4477 struct policy_handle handle
;
4478 struct spoolss_DevmodeContainer devmode_ctr
;
4480 union spoolss_JobInfo
*info
;
4482 if (!str1
|| !str2
|| !p
) {
4486 memset((char *)&desc
,'\0',sizeof(desc
));
4488 p
= skip_string(param
,tpscnt
,p
);
4492 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4494 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4496 /* check it's a supported variant */
4497 if (strcmp(str1
,"zWrLeh") != 0) {
4502 return False
; /* defined only for uLevel 0,1,2 */
4505 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4509 ZERO_STRUCT(handle
);
4511 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4512 if (!NT_STATUS_IS_OK(status
)) {
4513 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4514 nt_errstr(status
)));
4515 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4519 ZERO_STRUCT(devmode_ctr
);
4521 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4525 SEC_FLAG_MAXIMUM_ALLOWED
,
4528 if (!NT_STATUS_IS_OK(status
)) {
4529 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4532 if (!W_ERROR_IS_OK(werr
)) {
4533 desc
.errcode
= W_ERROR_V(werr
);
4537 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4545 if (!W_ERROR_IS_OK(werr
)) {
4546 desc
.errcode
= W_ERROR_V(werr
);
4551 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4557 desc
.buflen
= mdrcnt
;
4559 if (init_package(&desc
,count
,0)) {
4561 for (i
= 0; i
< count
; i
++) {
4562 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4563 if (desc
.errcode
== NERR_Success
) {
4569 if (cli
&& is_valid_policy_hnd(&handle
)) {
4570 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4573 *rdata_len
= desc
.usedlen
;
4576 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4580 SSVALS(*rparam
,0,desc
.errcode
);
4582 SSVAL(*rparam
,4,succnt
);
4583 SSVAL(*rparam
,6,count
);
4585 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4590 static int check_printdest_info(struct pack_desc
* desc
,
4591 int uLevel
, char* id
)
4593 desc
->subformat
= NULL
;
4596 desc
->format
= "B9";
4599 desc
->format
= "B9B21WWzW";
4605 desc
->format
= "zzzWWzzzWW";
4608 DEBUG(0,("check_printdest_info: invalid level %d\n",
4612 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4613 DEBUG(0,("check_printdest_info: invalid string %s\n",
4614 id
? id
: "<NULL>" ));
4620 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4621 struct pack_desc
* desc
)
4625 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4626 buf
[sizeof(buf
)-1] = 0;
4630 PACKS(desc
,"B9",buf
); /* szName */
4632 PACKS(desc
,"B21",""); /* szUserName */
4633 PACKI(desc
,"W",0); /* uJobId */
4634 PACKI(desc
,"W",0); /* fsStatus */
4635 PACKS(desc
,"z",""); /* pszStatus */
4636 PACKI(desc
,"W",0); /* time */
4640 if (uLevel
== 2 || uLevel
== 3) {
4641 PACKS(desc
,"z",buf
); /* pszPrinterName */
4643 PACKS(desc
,"z",""); /* pszUserName */
4644 PACKS(desc
,"z",""); /* pszLogAddr */
4645 PACKI(desc
,"W",0); /* uJobId */
4646 PACKI(desc
,"W",0); /* fsStatus */
4647 PACKS(desc
,"z",""); /* pszStatus */
4648 PACKS(desc
,"z",""); /* pszComment */
4649 PACKS(desc
,"z","NULL"); /* pszDrivers */
4650 PACKI(desc
,"W",0); /* time */
4651 PACKI(desc
,"W",0); /* pad1 */
4656 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
4657 char *param
, int tpscnt
,
4658 char *data
, int tdscnt
,
4659 int mdrcnt
,int mprcnt
,
4660 char **rdata
,char **rparam
,
4661 int *rdata_len
,int *rparam_len
)
4663 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4664 char *str2
= skip_string(param
,tpscnt
,str1
);
4665 char *p
= skip_string(param
,tpscnt
,str2
);
4666 char* PrinterName
= p
;
4668 struct pack_desc desc
;
4671 TALLOC_CTX
*mem_ctx
= talloc_tos();
4674 struct rpc_pipe_client
*cli
= NULL
;
4675 struct policy_handle handle
;
4676 struct spoolss_DevmodeContainer devmode_ctr
;
4677 union spoolss_PrinterInfo info
;
4679 if (!str1
|| !str2
|| !p
) {
4683 memset((char *)&desc
,'\0',sizeof(desc
));
4685 p
= skip_string(param
,tpscnt
,p
);
4689 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4691 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4693 /* check it's a supported varient */
4694 if (strcmp(str1
,"zWrLh") != 0) {
4697 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4701 ZERO_STRUCT(handle
);
4703 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4704 if (!NT_STATUS_IS_OK(status
)) {
4705 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4706 nt_errstr(status
)));
4707 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4711 ZERO_STRUCT(devmode_ctr
);
4713 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4717 SEC_FLAG_MAXIMUM_ALLOWED
,
4720 if (!NT_STATUS_IS_OK(status
)) {
4722 desc
.errcode
= NERR_DestNotFound
;
4726 if (!W_ERROR_IS_OK(werr
)) {
4728 desc
.errcode
= NERR_DestNotFound
;
4733 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4738 if (!W_ERROR_IS_OK(werr
)) {
4740 desc
.errcode
= NERR_DestNotFound
;
4746 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4751 desc
.buflen
= mdrcnt
;
4754 * Don't return data but need to get correct length
4755 * init_package will return wrong size if buflen=0
4757 desc
.buflen
= getlen(desc
.format
);
4758 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4760 if (init_package(&desc
,1,0)) {
4761 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
4765 if (cli
&& is_valid_policy_hnd(&handle
)) {
4766 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4769 *rdata_len
= desc
.usedlen
;
4772 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4776 SSVALS(*rparam
,0,desc
.errcode
);
4778 SSVAL(*rparam
,4,desc
.neededlen
);
4780 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4786 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4787 char *param
, int tpscnt
,
4788 char *data
, int tdscnt
,
4789 int mdrcnt
,int mprcnt
,
4790 char **rdata
,char **rparam
,
4791 int *rdata_len
,int *rparam_len
)
4793 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4794 char *str2
= skip_string(param
,tpscnt
,str1
);
4795 char *p
= skip_string(param
,tpscnt
,str2
);
4799 struct pack_desc desc
;
4801 TALLOC_CTX
*mem_ctx
= talloc_tos();
4804 struct rpc_pipe_client
*cli
= NULL
;
4805 union spoolss_PrinterInfo
*info
;
4808 if (!str1
|| !str2
|| !p
) {
4812 memset((char *)&desc
,'\0',sizeof(desc
));
4814 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4816 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4818 /* check it's a supported varient */
4819 if (strcmp(str1
,"WrLeh") != 0) {
4822 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4828 status
= rpc_connect_spoolss_pipe(conn
, &cli
);
4829 if (!NT_STATUS_IS_OK(status
)) {
4830 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
4831 nt_errstr(status
)));
4832 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4836 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
4838 cli
->srv_name_slash
,
4843 if (!W_ERROR_IS_OK(werr
)) {
4844 desc
.errcode
= W_ERROR_V(werr
);
4846 desc
.errcode
= NERR_DestNotFound
;
4854 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4861 desc
.buflen
= mdrcnt
;
4862 if (init_package(&desc
,queuecnt
,0)) {
4865 for (i
= 0; i
< count
; i
++) {
4866 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
4868 if (desc
.errcode
== NERR_Success
) {
4874 *rdata_len
= desc
.usedlen
;
4877 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4881 SSVALS(*rparam
,0,desc
.errcode
);
4883 SSVAL(*rparam
,4,succnt
);
4884 SSVAL(*rparam
,6,queuecnt
);
4886 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4891 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4892 char *param
, int tpscnt
,
4893 char *data
, int tdscnt
,
4894 int mdrcnt
,int mprcnt
,
4895 char **rdata
,char **rparam
,
4896 int *rdata_len
,int *rparam_len
)
4898 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4899 char *str2
= skip_string(param
,tpscnt
,str1
);
4900 char *p
= skip_string(param
,tpscnt
,str2
);
4903 struct pack_desc desc
;
4905 if (!str1
|| !str2
|| !p
) {
4909 memset((char *)&desc
,'\0',sizeof(desc
));
4911 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4913 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4915 /* check it's a supported varient */
4916 if (strcmp(str1
,"WrLeh") != 0) {
4919 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4924 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4930 desc
.buflen
= mdrcnt
;
4931 if (init_package(&desc
,1,0)) {
4932 PACKS(&desc
,"B41","NULL");
4935 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4937 *rdata_len
= desc
.usedlen
;
4940 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4944 SSVALS(*rparam
,0,desc
.errcode
);
4946 SSVAL(*rparam
,4,succnt
);
4949 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4954 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4955 char *param
, int tpscnt
,
4956 char *data
, int tdscnt
,
4957 int mdrcnt
,int mprcnt
,
4958 char **rdata
,char **rparam
,
4959 int *rdata_len
,int *rparam_len
)
4961 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4962 char *str2
= skip_string(param
,tpscnt
,str1
);
4963 char *p
= skip_string(param
,tpscnt
,str2
);
4966 struct pack_desc desc
;
4968 if (!str1
|| !str2
|| !p
) {
4971 memset((char *)&desc
,'\0',sizeof(desc
));
4973 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4975 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4977 /* check it's a supported varient */
4978 if (strcmp(str1
,"WrLeh") != 0) {
4981 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4986 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4992 desc
.buflen
= mdrcnt
;
4994 if (init_package(&desc
,1,0)) {
4995 PACKS(&desc
,"B13","lpd");
4998 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5000 *rdata_len
= desc
.usedlen
;
5003 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5007 SSVALS(*rparam
,0,desc
.errcode
);
5009 SSVAL(*rparam
,4,succnt
);
5012 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5017 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
5018 char *param
, int tpscnt
,
5019 char *data
, int tdscnt
,
5020 int mdrcnt
,int mprcnt
,
5021 char **rdata
,char **rparam
,
5022 int *rdata_len
,int *rparam_len
)
5024 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5025 char *str2
= skip_string(param
,tpscnt
,str1
);
5026 char *p
= skip_string(param
,tpscnt
,str2
);
5029 struct pack_desc desc
;
5031 if (!str1
|| !str2
|| !p
) {
5035 memset((char *)&desc
,'\0',sizeof(desc
));
5037 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5039 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5041 /* check it's a supported varient */
5042 if (strcmp(str1
,"WrLeh") != 0) {
5045 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5050 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5055 memset((char *)&desc
,'\0',sizeof(desc
));
5057 desc
.buflen
= mdrcnt
;
5059 if (init_package(&desc
,1,0)) {
5060 PACKS(&desc
,"B13","lp0");
5063 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5065 *rdata_len
= desc
.usedlen
;
5068 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5072 SSVALS(*rparam
,0,desc
.errcode
);
5074 SSVAL(*rparam
,4,succnt
);
5077 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5082 /****************************************************************************
5084 ****************************************************************************/
5086 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
5087 char *param
, int tpscnt
,
5088 char *data
, int tdscnt
,
5089 int mdrcnt
,int mprcnt
,
5090 char **rdata
,char **rparam
,
5091 int *rdata_len
,int *rparam_len
)
5094 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5095 char *str2
= skip_string(param
,tpscnt
,str1
);
5096 char *p
= skip_string(param
,tpscnt
,str2
);
5098 struct pack_desc desc
;
5099 struct sessionid
*session_list
;
5100 int i
, num_sessions
;
5102 if (!str1
|| !str2
|| !p
) {
5106 memset((char *)&desc
,'\0',sizeof(desc
));
5108 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5110 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5111 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5112 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5114 /* check it's a supported varient */
5115 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5118 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5122 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5125 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5130 memset((char *)&desc
,'\0',sizeof(desc
));
5132 desc
.buflen
= mdrcnt
;
5134 if (!init_package(&desc
,num_sessions
,0)) {
5138 for(i
=0; i
<num_sessions
; i
++) {
5139 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5140 PACKS(&desc
, "z", session_list
[i
].username
);
5141 PACKI(&desc
, "W", 1); /* num conns */
5142 PACKI(&desc
, "W", 0); /* num opens */
5143 PACKI(&desc
, "W", 1); /* num users */
5144 PACKI(&desc
, "D", 0); /* session time */
5145 PACKI(&desc
, "D", 0); /* idle time */
5146 PACKI(&desc
, "D", 0); /* flags */
5147 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5150 *rdata_len
= desc
.usedlen
;
5153 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5157 SSVALS(*rparam
,0,desc
.errcode
);
5158 SSVAL(*rparam
,2,0); /* converter */
5159 SSVAL(*rparam
,4,num_sessions
); /* count */
5161 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5167 /****************************************************************************
5168 The buffer was too small.
5169 ****************************************************************************/
5171 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5172 int mdrcnt
, int mprcnt
,
5173 char **rdata
, char **rparam
,
5174 int *rdata_len
, int *rparam_len
)
5176 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5177 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5184 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5186 DEBUG(3,("Supplied buffer too small in API command\n"));
5191 /****************************************************************************
5192 The request is not supported.
5193 ****************************************************************************/
5195 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
5196 char *param
, int tpscnt
,
5197 char *data
, int tdscnt
,
5198 int mdrcnt
, int mprcnt
,
5199 char **rdata
, char **rparam
,
5200 int *rdata_len
, int *rparam_len
)
5203 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5210 SSVAL(*rparam
,0,NERR_notsupported
);
5211 SSVAL(*rparam
,2,0); /* converter word */
5213 DEBUG(3,("Unsupported API command\n"));
5218 static const struct {
5221 bool (*fn
)(connection_struct
*, uint16
,
5224 int,int,char **,char **,int *,int *);
5225 bool auth_user
; /* Deny anonymous access? */
5226 } api_commands
[] = {
5227 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5228 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5229 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5230 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5231 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5232 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5233 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5234 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5235 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5236 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5237 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5238 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5239 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5240 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5241 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5242 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5243 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5244 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5245 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5246 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5247 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5248 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5249 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5250 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5251 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5252 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5253 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5254 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5255 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5256 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5257 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5258 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5259 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5260 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5261 {NULL
, -1, api_Unsupported
}
5262 /* The following RAP calls are not implemented by Samba:
5264 RAP_WFileEnum2 - anon not OK
5269 /****************************************************************************
5270 Handle remote api calls.
5271 ****************************************************************************/
5273 void api_reply(connection_struct
*conn
, uint16 vuid
,
5274 struct smb_request
*req
,
5275 char *data
, char *params
,
5276 int tdscnt
, int tpscnt
,
5277 int mdrcnt
, int mprcnt
)
5279 struct smbd_server_connection
*sconn
= smbd_server_conn
;
5282 char *rparam
= NULL
;
5283 const char *name1
= NULL
;
5284 const char *name2
= NULL
;
5291 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5292 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5297 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5300 api_command
= SVAL(params
,0);
5301 /* Is there a string at position params+2 ? */
5302 if (skip_string(params
,tpscnt
,params
+2)) {
5307 name2
= skip_string(params
,tpscnt
,params
+2);
5312 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5316 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5318 for (i
=0;api_commands
[i
].name
;i
++) {
5319 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5320 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5325 /* Check whether this api call can be done anonymously */
5327 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5328 user_struct
*user
= get_valid_user_struct(sconn
, vuid
);
5330 if (!user
|| user
->server_info
->guest
) {
5331 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5336 rdata
= (char *)SMB_MALLOC(1024);
5338 memset(rdata
,'\0',1024);
5341 rparam
= (char *)SMB_MALLOC(1024);
5343 memset(rparam
,'\0',1024);
5346 if(!rdata
|| !rparam
) {
5347 DEBUG(0,("api_reply: malloc fail !\n"));
5350 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5354 reply
= api_commands
[i
].fn(conn
,
5356 params
,tpscnt
, /* params + length */
5357 data
,tdscnt
, /* data + length */
5359 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5362 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5363 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
5364 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5367 /* if we get False back then it's actually unsupported */
5369 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
5370 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5373 /* If api_Unsupported returns false we can't return anything. */
5375 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5376 rdata
, rdata_len
, False
);