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 "../librpc/gen_ndr/cli_srvsvc.h"
33 #include "../librpc/gen_ndr/srv_samr.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/srv_srvsvc.h"
36 #include "../librpc/gen_ndr/rap.h"
37 #include "../lib/util/binsearch.h"
44 #define NERR_Success 0
45 #define NERR_badpass 86
46 #define NERR_notsupported 50
48 #define NERR_BASE (2100)
49 #define NERR_BufTooSmall (NERR_BASE+23)
50 #define NERR_JobNotFound (NERR_BASE+51)
51 #define NERR_DestNotFound (NERR_BASE+52)
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
59 /* Limit size of ipc replies */
61 static char *smb_realloc_limit(void *ptr
, size_t size
)
65 size
= MAX((size
),4*1024);
66 val
= (char *)SMB_REALLOC(ptr
,size
);
68 memset(val
,'\0',size
);
73 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
74 char *param
, int tpscnt
,
75 char *data
, int tdscnt
,
76 int mdrcnt
, int mprcnt
,
77 char **rdata
, char **rparam
,
78 int *rdata_len
, int *rparam_len
);
80 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
81 int mdrcnt
, int mprcnt
,
82 char **rdata
, char **rparam
,
83 int *rdata_len
, int *rparam_len
);
86 static int CopyExpanded(connection_struct
*conn
,
87 int snum
, char **dst
, char *src
, int *p_space_remaining
)
89 TALLOC_CTX
*ctx
= talloc_tos();
93 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
94 *p_space_remaining
<= 0) {
98 buf
= talloc_strdup(ctx
, src
);
100 *p_space_remaining
= 0;
103 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
105 *p_space_remaining
= 0;
108 buf
= talloc_sub_advanced(ctx
,
109 lp_servicename(SNUM(conn
)),
110 conn
->server_info
->unix_name
,
112 conn
->server_info
->utok
.gid
,
113 conn
->server_info
->sanitized_username
,
114 pdb_get_domain(conn
->server_info
->sam_account
),
117 *p_space_remaining
= 0;
120 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
125 (*p_space_remaining
) -= l
;
129 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
132 if (!src
|| !dst
|| !n
|| !(*dst
)) {
135 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
144 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
146 TALLOC_CTX
*ctx
= talloc_tos();
151 buf
= talloc_strdup(ctx
,s
);
155 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
159 buf
= talloc_sub_advanced(ctx
,
160 lp_servicename(SNUM(conn
)),
161 conn
->server_info
->unix_name
,
163 conn
->server_info
->utok
.gid
,
164 conn
->server_info
->sanitized_username
,
165 pdb_get_domain(conn
->server_info
->sam_account
),
170 return strlen(buf
) + 1;
173 /*******************************************************************
174 Check a API string for validity when we only need to check the prefix.
175 ******************************************************************/
177 static bool prefix_ok(const char *str
, const char *prefix
)
179 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
183 const char *format
; /* formatstring for structure */
184 const char *subformat
; /* subformat for structure */
185 char *base
; /* baseaddress of buffer */
186 int buflen
; /* remaining size for fixed part; on init: length of base */
187 int subcount
; /* count of substructures */
188 char *structbuf
; /* pointer into buffer for remaining fixed part */
189 int stringlen
; /* remaining size for variable part */
190 char *stringbuf
; /* pointer into buffer for remaining variable part */
191 int neededlen
; /* total needed size */
192 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
193 const char *curpos
; /* current position; pointer into format or subformat */
197 static int get_counter(const char **p
)
203 if (!isdigit((int)**p
)) {
209 n
= 10 * n
+ (i
- '0');
217 static int getlen(const char *p
)
226 case 'W': /* word (2 byte) */
229 case 'K': /* status word? (2 byte) */
232 case 'N': /* count of substructures (word) at end */
235 case 'D': /* double word (4 byte) */
236 case 'z': /* offset to zero terminated string (4 byte) */
237 case 'l': /* offset to user data (4 byte) */
240 case 'b': /* offset to data (with counter) (4 byte) */
244 case 'B': /* byte (with optional counter) */
245 n
+= get_counter(&p
);
252 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
257 if (!p
->format
|| !p
->base
) {
261 i
= count
* getlen(p
->format
);
263 i
+= subcount
* getlen(p
->subformat
);
265 p
->structbuf
= p
->base
;
269 p
->curpos
= p
->format
;
275 * This is the old error code we used. Aparently
276 * WinNT/2k systems return ERRbuftoosmall (2123) and
277 * OS/2 needs this. I'm leaving this here so we can revert
280 p
->errcode
= ERRmoredata
;
282 p
->errcode
= ERRbuftoosmall
;
285 p
->errcode
= NERR_Success
;
289 p
->stringbuf
= p
->base
+ i
;
291 return (p
->errcode
== NERR_Success
);
294 static int package(struct pack_desc
*p
, ...)
297 int needed
=0, stringneeded
;
298 const char *str
=NULL
;
299 int is_string
=0, stringused
;
306 p
->curpos
= p
->format
;
308 p
->curpos
= p
->subformat
;
313 str
= va_arg(args
,char*);
314 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
323 switch( *p
->curpos
++ ) {
324 case 'W': /* word (2 byte) */
326 temp
= va_arg(args
,int);
327 if (p
->buflen
>= needed
) {
328 SSVAL(p
->structbuf
,0,temp
);
331 case 'K': /* status word? (2 byte) */
333 temp
= va_arg(args
,int);
334 if (p
->buflen
>= needed
) {
335 SSVAL(p
->structbuf
,0,temp
);
338 case 'N': /* count of substructures (word) at end */
340 p
->subcount
= va_arg(args
,int);
341 if (p
->buflen
>= needed
) {
342 SSVAL(p
->structbuf
,0,p
->subcount
);
345 case 'D': /* double word (4 byte) */
347 temp
= va_arg(args
,int);
348 if (p
->buflen
>= needed
) {
349 SIVAL(p
->structbuf
,0,temp
);
352 case 'B': /* byte (with optional counter) */
353 needed
= get_counter(&p
->curpos
);
355 char *s
= va_arg(args
,char*);
356 if (p
->buflen
>= needed
) {
357 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
361 case 'z': /* offset to zero terminated string (4 byte) */
362 str
= va_arg(args
,char*);
363 stringneeded
= (str
? strlen(str
)+1 : 0);
366 case 'l': /* offset to user data (4 byte) */
367 str
= va_arg(args
,char*);
368 stringneeded
= va_arg(args
,int);
371 case 'b': /* offset to data (with counter) (4 byte) */
372 str
= va_arg(args
,char*);
373 stringneeded
= get_counter(&p
->curpos
);
379 if (stringneeded
>= 0) {
381 if (p
->buflen
>= needed
) {
382 stringused
= stringneeded
;
383 if (stringused
> p
->stringlen
) {
384 stringused
= (is_string
? p
->stringlen
: 0);
385 if (p
->errcode
== NERR_Success
) {
386 p
->errcode
= ERRmoredata
;
390 SIVAL(p
->structbuf
,0,0);
392 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
393 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
395 p
->stringbuf
[stringused
-1] = '\0';
397 p
->stringbuf
+= stringused
;
398 p
->stringlen
-= stringused
;
399 p
->usedlen
+= stringused
;
402 p
->neededlen
+= stringneeded
;
405 p
->neededlen
+= needed
;
406 if (p
->buflen
>= needed
) {
407 p
->structbuf
+= needed
;
409 p
->usedlen
+= needed
;
411 if (p
->errcode
== NERR_Success
) {
412 p
->errcode
= ERRmoredata
;
419 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
420 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
422 #define PACK(desc,t,v) package(desc,v)
423 #define PACKl(desc,t,v,l) package(desc,v,l)
426 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
431 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
436 /****************************************************************************
438 ****************************************************************************/
440 static void PackDriverData(struct pack_desc
* desc
)
442 char drivdata
[4+4+32];
443 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
444 SIVAL(drivdata
,4,1000); /* lVersion */
445 memset(drivdata
+8,0,32); /* szDeviceName */
446 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
447 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
450 static int check_printq_info(struct pack_desc
* desc
,
451 unsigned int uLevel
, char *id1
, char *id2
)
453 desc
->subformat
= NULL
;
456 desc
->format
= "B13";
459 desc
->format
= "B13BWWWzzzzzWW";
462 desc
->format
= "B13BWWWzzzzzWN";
463 desc
->subformat
= "WB21BB16B10zWWzDDz";
466 desc
->format
= "zWWWWzzzzWWzzl";
469 desc
->format
= "zWWWWzzzzWNzzl";
470 desc
->subformat
= "WWzWWDDzz";
479 desc
->format
= "WzzzzzzzzN";
480 desc
->subformat
= "z";
483 DEBUG(0,("check_printq_info: invalid level %d\n",
487 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
488 DEBUG(0,("check_printq_info: invalid format %s\n",
489 id1
? id1
: "<NULL>" ));
492 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
493 DEBUG(0,("check_printq_info: invalid subformat %s\n",
494 id2
? id2
: "<NULL>" ));
501 #define RAP_JOB_STATUS_QUEUED 0
502 #define RAP_JOB_STATUS_PAUSED 1
503 #define RAP_JOB_STATUS_SPOOLING 2
504 #define RAP_JOB_STATUS_PRINTING 3
505 #define RAP_JOB_STATUS_PRINTED 4
507 #define RAP_QUEUE_STATUS_PAUSED 1
508 #define RAP_QUEUE_STATUS_ERROR 2
510 /* turn a print job status into a on the wire status
512 static int printj_spoolss_status(int v
)
514 if (v
== JOB_STATUS_QUEUED
)
515 return RAP_JOB_STATUS_QUEUED
;
516 if (v
& JOB_STATUS_PAUSED
)
517 return RAP_JOB_STATUS_PAUSED
;
518 if (v
& JOB_STATUS_SPOOLING
)
519 return RAP_JOB_STATUS_SPOOLING
;
520 if (v
& JOB_STATUS_PRINTING
)
521 return RAP_JOB_STATUS_PRINTING
;
525 /* turn a print queue status into a on the wire status
527 static int printq_spoolss_status(int v
)
529 if (v
== PRINTER_STATUS_OK
)
531 if (v
& PRINTER_STATUS_PAUSED
)
532 return RAP_QUEUE_STATUS_PAUSED
;
533 return RAP_QUEUE_STATUS_ERROR
;
536 static void fill_spoolss_printjob_info(int uLevel
,
537 struct pack_desc
*desc
,
538 struct spoolss_JobInfo2
*info2
,
541 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
543 /* the client expects localtime */
544 t
-= get_time_zone(t
);
546 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
548 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
549 PACKS(desc
,"B",""); /* pad */
550 PACKS(desc
,"B16",""); /* szNotifyName */
551 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
552 PACKS(desc
,"z",""); /* pszParms */
553 PACKI(desc
,"W",n
+1); /* uPosition */
554 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
555 PACKS(desc
,"z",""); /* pszStatus */
556 PACKI(desc
,"D", t
); /* ulSubmitted */
557 PACKI(desc
,"D", info2
->size
); /* ulSize */
558 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
560 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
561 PACKI(desc
,"W", info2
->priority
); /* uPriority */
562 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
563 PACKI(desc
,"W",n
+1); /* uPosition */
564 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
565 PACKI(desc
,"D",t
); /* ulSubmitted */
566 PACKI(desc
,"D", info2
->size
); /* ulSize */
567 PACKS(desc
,"z","Samba"); /* pszComment */
568 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
570 PACKS(desc
,"z",""); /* pszNotifyName */
571 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
572 PACKS(desc
,"z",""); /* pszParms */
573 PACKS(desc
,"z",""); /* pszStatus */
574 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
575 PACKS(desc
,"z","lpd"); /* pszQProcName */
576 PACKS(desc
,"z",""); /* pszQProcParms */
577 PACKS(desc
,"z","NULL"); /* pszDriverName */
578 PackDriverData(desc
); /* pDriverData */
579 PACKS(desc
,"z",""); /* pszPrinterName */
580 } else if (uLevel
== 4) { /* OS2 */
581 PACKS(desc
,"z",""); /* pszSpoolFileName */
582 PACKS(desc
,"z",""); /* pszPortName */
583 PACKS(desc
,"z",""); /* pszStatus */
584 PACKI(desc
,"D",0); /* ulPagesSpooled */
585 PACKI(desc
,"D",0); /* ulPagesSent */
586 PACKI(desc
,"D",0); /* ulPagesPrinted */
587 PACKI(desc
,"D",0); /* ulTimePrinted */
588 PACKI(desc
,"D",0); /* ulExtendJobStatus */
589 PACKI(desc
,"D",0); /* ulStartPage */
590 PACKI(desc
,"D",0); /* ulEndPage */
595 /********************************************************************
596 Respond to the DosPrintQInfo command with a level of 52
597 This is used to get printer driver information for Win9x clients
598 ********************************************************************/
599 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
600 struct pack_desc
* desc
, int count
,
601 const char *printer_name
)
605 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
606 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
607 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
609 PACKI(desc
, "W", 0x0400); /* don't know */
610 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
611 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
612 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
613 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
615 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
616 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
617 PACKS(desc
,"z", location
); /* share to retrieve files */
619 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
620 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
621 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
623 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
624 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
625 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
626 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
627 DEBUG(3,("Driver Location: %s:\n",location
));
628 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
629 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
630 PACKI(desc
,"N",count
); /* number of files to copy */
632 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
634 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
635 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
636 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
641 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
644 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
646 desc
->errcode
=NERR_Success
;
650 static const char *strip_unc(const char *unc
)
658 if ((p
= strrchr(unc
, '\\')) != NULL
) {
665 static void fill_printq_info(int uLevel
,
666 struct pack_desc
* desc
,
668 union spoolss_JobInfo
*job_info
,
669 struct spoolss_DriverInfo3
*driver_info
,
670 struct spoolss_PrinterInfo2
*printer_info
)
676 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
681 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
684 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
688 if (uLevel
== 1 || uLevel
== 2) {
689 PACKS(desc
,"B",""); /* alignment */
690 PACKI(desc
,"W",5); /* priority */
691 PACKI(desc
,"W",0); /* start time */
692 PACKI(desc
,"W",0); /* until time */
693 PACKS(desc
,"z",""); /* pSepFile */
694 PACKS(desc
,"z","lpd"); /* pPrProc */
695 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
696 PACKS(desc
,"z",""); /* pParms */
697 if (printer_info
->printername
== NULL
) {
698 PACKS(desc
,"z","UNKNOWN PRINTER");
699 PACKI(desc
,"W",LPSTAT_ERROR
);
701 PACKS(desc
,"z", printer_info
->comment
);
702 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
704 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
707 if (uLevel
== 3 || uLevel
== 4) {
708 PACKI(desc
,"W",5); /* uPriority */
709 PACKI(desc
,"W",0); /* uStarttime */
710 PACKI(desc
,"W",0); /* uUntiltime */
711 PACKI(desc
,"W",5); /* pad1 */
712 PACKS(desc
,"z",""); /* pszSepFile */
713 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
714 PACKS(desc
,"z",NULL
); /* pszParms */
715 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
716 /* "don't ask" that it's done this way to fix corrupted
717 Win9X/ME printer comments. */
718 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
719 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
720 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
721 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
722 PackDriverData(desc
); /* pDriverData */
725 if (uLevel
== 2 || uLevel
== 4) {
727 for (i
= 0; i
< count
; i
++) {
728 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
733 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
736 /* This function returns the number of files for a given driver */
737 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
741 /* count the number of files */
742 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
748 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
749 char *param
, int tpscnt
,
750 char *data
, int tdscnt
,
751 int mdrcnt
,int mprcnt
,
752 char **rdata
,char **rparam
,
753 int *rdata_len
,int *rparam_len
)
755 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
756 char *str2
= skip_string(param
,tpscnt
,str1
);
757 char *p
= skip_string(param
,tpscnt
,str2
);
762 struct pack_desc desc
;
765 WERROR werr
= WERR_OK
;
766 TALLOC_CTX
*mem_ctx
= talloc_tos();
768 struct rpc_pipe_client
*cli
= NULL
;
769 struct policy_handle handle
;
770 struct spoolss_DevmodeContainer devmode_ctr
;
771 union spoolss_DriverInfo driver_info
;
772 union spoolss_JobInfo
*job_info
;
773 union spoolss_PrinterInfo printer_info
;
775 if (!str1
|| !str2
|| !p
) {
778 memset((char *)&desc
,'\0',sizeof(desc
));
780 p
= skip_string(param
,tpscnt
,p
);
784 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
785 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
786 /* str3 may be null here and is checked in check_printq_info(). */
788 /* remove any trailing username */
789 if ((p
= strchr_m(QueueName
,'%')))
792 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
794 /* check it's a supported varient */
795 if (!prefix_ok(str1
,"zWrLh"))
797 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
799 * Patch from Scott Moomaw <scott@bridgewater.edu>
800 * to return the 'invalid info level' error if an
801 * unknown level was requested.
805 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
809 SSVALS(*rparam
,0,ERRunknownlevel
);
817 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
818 rpc_spoolss_dispatch
, conn
->server_info
,
820 if (!NT_STATUS_IS_OK(status
)) {
821 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
823 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
827 ZERO_STRUCT(devmode_ctr
);
829 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
833 SEC_FLAG_MAXIMUM_ALLOWED
,
836 if (!NT_STATUS_IS_OK(status
)) {
837 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
840 if (!W_ERROR_IS_OK(werr
)) {
841 desc
.errcode
= W_ERROR_V(werr
);
845 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
850 if (!W_ERROR_IS_OK(werr
)) {
851 desc
.errcode
= W_ERROR_V(werr
);
856 uint32_t server_major_version
;
857 uint32_t server_minor_version
;
859 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
867 &server_major_version
,
868 &server_minor_version
);
869 if (!W_ERROR_IS_OK(werr
)) {
870 desc
.errcode
= W_ERROR_V(werr
);
874 count
= get_printerdrivernumber(&driver_info
.info3
);
875 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
878 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
886 if (!W_ERROR_IS_OK(werr
)) {
887 desc
.errcode
= W_ERROR_V(werr
);
895 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
900 desc
.buflen
= mdrcnt
;
903 * Don't return data but need to get correct length
904 * init_package will return wrong size if buflen=0
906 desc
.buflen
= getlen(desc
.format
);
907 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
910 if (init_package(&desc
,1,count
)) {
911 desc
.subcount
= count
;
912 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
915 *rdata_len
= desc
.usedlen
;
918 * We must set the return code to ERRbuftoosmall
919 * in order to support lanman style printing with Win NT/2k
922 if (!mdrcnt
&& lp_disable_spoolss())
923 desc
.errcode
= ERRbuftoosmall
;
926 if (cli
&& is_valid_policy_hnd(&handle
)) {
927 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
930 *rdata_len
= desc
.usedlen
;
932 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
937 SSVALS(*rparam
,0,desc
.errcode
);
939 SSVAL(*rparam
,4,desc
.neededlen
);
941 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
948 /****************************************************************************
949 View list of all print jobs on all queues.
950 ****************************************************************************/
952 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
953 char *param
, int tpscnt
,
954 char *data
, int tdscnt
,
955 int mdrcnt
, int mprcnt
,
956 char **rdata
, char** rparam
,
957 int *rdata_len
, int *rparam_len
)
959 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
960 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
961 char *p
= skip_string(param
,tpscnt
,output_format1
);
962 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
963 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
965 struct pack_desc desc
;
966 int *subcntarr
= NULL
;
967 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
969 WERROR werr
= WERR_OK
;
970 TALLOC_CTX
*mem_ctx
= talloc_tos();
972 struct rpc_pipe_client
*cli
= NULL
;
973 struct spoolss_DevmodeContainer devmode_ctr
;
974 uint32_t num_printers
;
975 union spoolss_PrinterInfo
*printer_info
;
976 union spoolss_DriverInfo
*driver_info
;
977 union spoolss_JobInfo
**job_info
;
979 if (!param_format
|| !output_format1
|| !p
) {
983 memset((char *)&desc
,'\0',sizeof(desc
));
985 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
987 if (!prefix_ok(param_format
,"WrLeh")) {
990 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
992 * Patch from Scott Moomaw <scott@bridgewater.edu>
993 * to return the 'invalid info level' error if an
994 * unknown level was requested.
998 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1002 SSVALS(*rparam
,0,ERRunknownlevel
);
1008 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
1009 rpc_spoolss_dispatch
, conn
->server_info
,
1011 if (!NT_STATUS_IS_OK(status
)) {
1012 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1013 nt_errstr(status
)));
1014 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1018 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1020 cli
->srv_name_slash
,
1025 if (!W_ERROR_IS_OK(werr
)) {
1026 desc
.errcode
= W_ERROR_V(werr
);
1030 queuecnt
= num_printers
;
1032 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1033 if (job_info
== NULL
) {
1037 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1038 if (driver_info
== NULL
) {
1042 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1043 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1048 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1054 desc
.buflen
= mdrcnt
;
1057 for (i
= 0; i
< num_printers
; i
++) {
1060 struct policy_handle handle
;
1061 const char *printername
;
1063 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1064 if (printername
== NULL
) {
1068 ZERO_STRUCT(handle
);
1069 ZERO_STRUCT(devmode_ctr
);
1071 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
1075 SEC_FLAG_MAXIMUM_ALLOWED
,
1078 if (!NT_STATUS_IS_OK(status
)) {
1079 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1082 if (!W_ERROR_IS_OK(werr
)) {
1083 desc
.errcode
= W_ERROR_V(werr
);
1087 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1095 if (!W_ERROR_IS_OK(werr
)) {
1096 desc
.errcode
= W_ERROR_V(werr
);
1101 uint32_t server_major_version
;
1102 uint32_t server_minor_version
;
1104 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1112 &server_major_version
,
1113 &server_minor_version
);
1114 if (!W_ERROR_IS_OK(werr
)) {
1115 desc
.errcode
= W_ERROR_V(werr
);
1120 subcntarr
[i
] = num_jobs
;
1121 subcnt
+= subcntarr
[i
];
1123 if (cli
&& is_valid_policy_hnd(&handle
)) {
1124 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
1128 if (init_package(&desc
,queuecnt
,subcnt
)) {
1129 for (i
= 0; i
< num_printers
; i
++) {
1130 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1131 if (desc
.errcode
== NERR_Success
) {
1137 SAFE_FREE(subcntarr
);
1139 *rdata_len
= desc
.usedlen
;
1141 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1145 SSVALS(*rparam
,0,desc
.errcode
);
1147 SSVAL(*rparam
,4,succnt
);
1148 SSVAL(*rparam
,6,queuecnt
);
1154 SAFE_FREE(subcntarr
);
1159 /****************************************************************************
1160 Get info level for a server list query.
1161 ****************************************************************************/
1163 static bool check_server_info(int uLevel
, char* id
)
1167 if (strcmp(id
,"B16") != 0) {
1172 if (strcmp(id
,"B16BBDz") != 0) {
1182 struct srv_info_struct
{
1190 /*******************************************************************
1191 Get server info lists from the files saved by nmbd. Return the
1193 ******************************************************************/
1195 static int get_server_info(uint32 servertype
,
1196 struct srv_info_struct
**servers
,
1202 bool local_list_only
;
1205 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1207 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1211 /* request for everything is code for request all servers */
1212 if (servertype
== SV_TYPE_ALL
) {
1213 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1216 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1218 DEBUG(4,("Servertype search: %8x\n",servertype
));
1220 for (i
=0;lines
[i
];i
++) {
1222 struct srv_info_struct
*s
;
1223 const char *ptr
= lines
[i
];
1225 TALLOC_CTX
*frame
= NULL
;
1232 if (count
== alloced
) {
1234 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1236 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1240 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1242 s
= &(*servers
)[count
];
1244 frame
= talloc_stackframe();
1246 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1250 fstrcpy(s
->name
, p
);
1253 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1259 s
->comment
[0] = '\0';
1260 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1264 fstrcpy(s
->comment
, p
);
1265 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1267 s
->domain
[0] = '\0';
1268 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1269 /* this allows us to cope with an old nmbd */
1270 fstrcpy(s
->domain
,lp_workgroup());
1272 fstrcpy(s
->domain
, p
);
1276 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1277 DEBUG(4,("r:host file "));
1281 /* Filter the servers/domains we return based on what was asked for. */
1283 /* Check to see if we are being asked for a local list only. */
1284 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1285 DEBUG(4,("r: local list only"));
1289 /* doesn't match up: don't want it */
1290 if (!(servertype
& s
->type
)) {
1291 DEBUG(4,("r:serv type "));
1295 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1296 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1297 DEBUG(4,("s: dom mismatch "));
1301 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1305 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1306 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1309 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1310 s
->name
, s
->type
, s
->comment
, s
->domain
));
1311 s
->server_added
= True
;
1314 DEBUG(4,("%20s %8x %25s %15s\n",
1315 s
->name
, s
->type
, s
->comment
, s
->domain
));
1323 /*******************************************************************
1324 Fill in a server info structure.
1325 ******************************************************************/
1327 static int fill_srv_info(struct srv_info_struct
*service
,
1328 int uLevel
, char **buf
, int *buflen
,
1329 char **stringbuf
, int *stringspace
, char *baseaddr
)
1352 len
= strlen(service
->comment
)+1;
1356 *buflen
= struct_len
;
1358 return struct_len
+ len
;
1363 if (*buflen
< struct_len
) {
1370 p2
= p
+ struct_len
;
1371 l2
= *buflen
- struct_len
;
1379 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1383 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1384 SIVAL(p
,18,service
->type
);
1385 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1386 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1391 *buf
= p
+ struct_len
;
1392 *buflen
-= struct_len
;
1403 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1405 return StrCaseCmp(s1
->name
,s2
->name
);
1408 /****************************************************************************
1409 View list of servers available (or possibly domains). The info is
1410 extracted from lists saved by nmbd on the local host.
1411 ****************************************************************************/
1413 static bool api_RNetServerEnum2(connection_struct
*conn
, uint16 vuid
,
1414 char *param
, int tpscnt
,
1415 char *data
, int tdscnt
,
1416 int mdrcnt
, int mprcnt
, char **rdata
,
1417 char **rparam
, int *rdata_len
, int *rparam_len
)
1419 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1420 char *str2
= skip_string(param
,tpscnt
,str1
);
1421 char *p
= skip_string(param
,tpscnt
,str2
);
1422 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1423 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1424 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1426 int data_len
, fixed_len
, string_len
;
1427 int f_len
= 0, s_len
= 0;
1428 struct srv_info_struct
*servers
=NULL
;
1429 int counted
=0,total
=0;
1432 bool domain_request
;
1435 if (!str1
|| !str2
|| !p
) {
1439 /* If someone sets all the bits they don't really mean to set
1440 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1443 if (servertype
== SV_TYPE_ALL
) {
1444 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1447 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1448 any other bit (they may just set this bit on its own) they
1449 want all the locally seen servers. However this bit can be
1450 set on its own so set the requested servers to be
1451 ALL - DOMAIN_ENUM. */
1453 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1454 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1457 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1458 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1462 if (!prefix_ok(str1
,"WrLehD")) {
1465 if (!check_server_info(uLevel
,str2
)) {
1469 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1470 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1471 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1473 if (strcmp(str1
, "WrLehDz") == 0) {
1474 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1477 pull_ascii_fstring(domain
, p
);
1479 fstrcpy(domain
, lp_workgroup());
1482 DEBUG(4, ("domain [%s]\n", domain
));
1484 if (lp_browse_list()) {
1485 total
= get_server_info(servertype
,&servers
,domain
);
1488 data_len
= fixed_len
= string_len
= 0;
1491 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1494 char *lastname
=NULL
;
1496 for (i
=0;i
<total
;i
++) {
1497 struct srv_info_struct
*s
= &servers
[i
];
1499 if (lastname
&& strequal(lastname
,s
->name
)) {
1503 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1504 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1505 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1507 if (data_len
< buf_len
) {
1510 string_len
+= s_len
;
1517 *rdata_len
= fixed_len
+ string_len
;
1518 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1523 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1529 char *lastname
=NULL
;
1530 int count2
= counted
;
1532 for (i
= 0; i
< total
&& count2
;i
++) {
1533 struct srv_info_struct
*s
= &servers
[i
];
1535 if (lastname
&& strequal(lastname
,s
->name
)) {
1539 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1540 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1541 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1547 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1551 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1553 SSVAL(*rparam
,4,counted
);
1554 SSVAL(*rparam
,6,counted
+missed
);
1558 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1559 domain
,uLevel
,counted
,counted
+missed
));
1564 static int srv_name_match(const char *n1
, const char *n2
)
1567 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1569 * In Windows, FirstNameToReturn need not be an exact match:
1570 * the server will return a list of servers that exist on
1571 * the network greater than or equal to the FirstNameToReturn.
1573 int ret
= StrCaseCmp(n1
, n2
);
1582 static bool api_RNetServerEnum3(connection_struct
*conn
, uint16 vuid
,
1583 char *param
, int tpscnt
,
1584 char *data
, int tdscnt
,
1585 int mdrcnt
, int mprcnt
, char **rdata
,
1586 char **rparam
, int *rdata_len
, int *rparam_len
)
1588 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1589 char *str2
= skip_string(param
,tpscnt
,str1
);
1590 char *p
= skip_string(param
,tpscnt
,str2
);
1591 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1592 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1593 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1595 int data_len
, fixed_len
, string_len
;
1596 int f_len
= 0, s_len
= 0;
1597 struct srv_info_struct
*servers
=NULL
;
1598 int counted
=0,first
=0,total
=0;
1602 bool domain_request
;
1605 if (!str1
|| !str2
|| !p
) {
1609 /* If someone sets all the bits they don't really mean to set
1610 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1613 if (servertype
== SV_TYPE_ALL
) {
1614 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1617 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1618 any other bit (they may just set this bit on its own) they
1619 want all the locally seen servers. However this bit can be
1620 set on its own so set the requested servers to be
1621 ALL - DOMAIN_ENUM. */
1623 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1624 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1627 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1628 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1632 if (strcmp(str1
, "WrLehDzz") != 0) {
1635 if (!check_server_info(uLevel
,str2
)) {
1639 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1640 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1641 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1643 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1646 pull_ascii_fstring(domain
, p
);
1647 if (domain
[0] == '\0') {
1648 fstrcpy(domain
, lp_workgroup());
1650 p
= skip_string(param
,tpscnt
,p
);
1651 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1654 pull_ascii_fstring(first_name
, p
);
1656 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1657 domain
, first_name
));
1659 if (lp_browse_list()) {
1660 total
= get_server_info(servertype
,&servers
,domain
);
1663 data_len
= fixed_len
= string_len
= 0;
1666 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1668 if (first_name
[0] != '\0') {
1669 struct srv_info_struct
*first_server
= NULL
;
1671 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1672 srv_name_match
, first_server
);
1674 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1676 * The binary search may not find the exact match
1677 * so we need to search backward to find the first match
1679 * This implements the strange matching windows
1680 * implements. (see the comment in srv_name_match().
1684 ret
= StrCaseCmp(first_name
,
1685 servers
[first
-1].name
);
1692 /* we should return no entries */
1698 char *lastname
=NULL
;
1700 for (i
=first
;i
<total
;i
++) {
1701 struct srv_info_struct
*s
= &servers
[i
];
1703 if (lastname
&& strequal(lastname
,s
->name
)) {
1707 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1708 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1709 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1711 if (data_len
< buf_len
) {
1714 string_len
+= s_len
;
1721 *rdata_len
= fixed_len
+ string_len
;
1722 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1727 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1733 char *lastname
=NULL
;
1734 int count2
= counted
;
1736 for (i
= first
; i
< total
&& count2
;i
++) {
1737 struct srv_info_struct
*s
= &servers
[i
];
1739 if (lastname
&& strequal(lastname
,s
->name
)) {
1743 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1744 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1745 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1751 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1755 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1757 SSVAL(*rparam
,4,counted
);
1758 SSVAL(*rparam
,6,counted
+missed
);
1760 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1761 domain
,uLevel
,first
,first_name
,
1762 first
< total
? servers
[first
].name
: "",
1763 counted
,counted
+missed
));
1770 /****************************************************************************
1771 command 0x34 - suspected of being a "Lookup Names" stub api
1772 ****************************************************************************/
1774 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1775 char *param
, int tpscnt
,
1776 char *data
, int tdscnt
,
1777 int mdrcnt
, int mprcnt
, char **rdata
,
1778 char **rparam
, int *rdata_len
, int *rparam_len
)
1780 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1781 char *str2
= skip_string(param
,tpscnt
,str1
);
1782 char *p
= skip_string(param
,tpscnt
,str2
);
1783 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1784 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1788 if (!str1
|| !str2
|| !p
) {
1792 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1793 str1
, str2
, p
, uLevel
, buf_len
));
1795 if (!prefix_ok(str1
,"zWrLeh")) {
1802 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1807 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1809 SSVAL(*rparam
,4,counted
);
1810 SSVAL(*rparam
,6,counted
+missed
);
1815 /****************************************************************************
1816 get info about a share
1817 ****************************************************************************/
1819 static bool check_share_info(int uLevel
, char* id
)
1823 if (strcmp(id
,"B13") != 0) {
1828 /* Level-2 descriptor is allowed (and ignored) */
1829 if (strcmp(id
,"B13BWz") != 0 &&
1830 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1835 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1840 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1850 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1851 char** buf
, int* buflen
,
1852 char** stringbuf
, int* stringspace
, char* baseaddr
)
1881 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1884 len
+= strlen(lp_pathname(snum
)) + 1;
1887 *buflen
= struct_len
;
1892 return struct_len
+ len
;
1897 if ((*buflen
) < struct_len
) {
1905 p2
= p
+ struct_len
;
1906 l2
= (*buflen
) - struct_len
;
1913 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1919 type
= STYPE_DISKTREE
;
1920 if (lp_print_ok(snum
)) {
1921 type
= STYPE_PRINTQ
;
1923 if (strequal("IPC",lp_fstype(snum
))) {
1926 SSVAL(p
,14,type
); /* device type */
1927 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1928 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1932 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1933 SSVALS(p
,22,-1); /* max uses */
1934 SSVAL(p
,24,1); /* current uses */
1935 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1936 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1937 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1941 memset(p
+40,0,SHPWLEN
+2);
1952 (*buf
) = p
+ struct_len
;
1953 (*buflen
) -= struct_len
;
1955 (*stringspace
) = l2
;
1964 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1965 char *param
, int tpscnt
,
1966 char *data
, int tdscnt
,
1967 int mdrcnt
,int mprcnt
,
1968 char **rdata
,char **rparam
,
1969 int *rdata_len
,int *rparam_len
)
1971 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1972 char *str2
= skip_string(param
,tpscnt
,str1
);
1973 char *netname
= skip_string(param
,tpscnt
,str2
);
1974 char *p
= skip_string(param
,tpscnt
,netname
);
1975 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1978 if (!str1
|| !str2
|| !netname
|| !p
) {
1982 snum
= find_service(netname
);
1987 /* check it's a supported varient */
1988 if (!prefix_ok(str1
,"zWrLh")) {
1991 if (!check_share_info(uLevel
,str2
)) {
1995 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2000 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2001 if (*rdata_len
< 0) {
2006 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2010 SSVAL(*rparam
,0,NERR_Success
);
2011 SSVAL(*rparam
,2,0); /* converter word */
2012 SSVAL(*rparam
,4,*rdata_len
);
2017 /****************************************************************************
2018 View the list of available shares.
2020 This function is the server side of the NetShareEnum() RAP call.
2021 It fills the return buffer with share names and share comments.
2022 Note that the return buffer normally (in all known cases) allows only
2023 twelve byte strings for share names (plus one for a nul terminator).
2024 Share names longer than 12 bytes must be skipped.
2025 ****************************************************************************/
2027 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
2028 char *param
, int tpscnt
,
2029 char *data
, int tdscnt
,
2037 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2038 char *str2
= skip_string(param
,tpscnt
,str1
);
2039 char *p
= skip_string(param
,tpscnt
,str2
);
2040 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2041 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2044 int total
=0,counted
=0;
2045 bool missed
= False
;
2047 int data_len
, fixed_len
, string_len
;
2048 int f_len
= 0, s_len
= 0;
2050 if (!str1
|| !str2
|| !p
) {
2054 if (!prefix_ok(str1
,"WrLeh")) {
2057 if (!check_share_info(uLevel
,str2
)) {
2061 /* Ensure all the usershares are loaded. */
2063 load_registry_shares();
2064 count
= load_usershare_shares();
2067 data_len
= fixed_len
= string_len
= 0;
2068 for (i
=0;i
<count
;i
++) {
2069 fstring servicename_dos
;
2070 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2073 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2074 /* Maximum name length = 13. */
2075 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2077 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2078 if (data_len
< buf_len
) {
2081 string_len
+= s_len
;
2088 *rdata_len
= fixed_len
+ string_len
;
2089 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2094 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2099 for( i
= 0; i
< count
; i
++ ) {
2100 fstring servicename_dos
;
2101 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2105 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2106 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2107 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2114 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2118 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2120 SSVAL(*rparam
,4,counted
);
2121 SSVAL(*rparam
,6,total
);
2123 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2124 counted
,total
,uLevel
,
2125 buf_len
,*rdata_len
,mdrcnt
));
2130 /****************************************************************************
2132 ****************************************************************************/
2134 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
2135 char *param
, int tpscnt
,
2136 char *data
, int tdscnt
,
2137 int mdrcnt
,int mprcnt
,
2138 char **rdata
,char **rparam
,
2139 int *rdata_len
,int *rparam_len
)
2141 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2142 char *str2
= skip_string(param
,tpscnt
,str1
);
2143 char *p
= skip_string(param
,tpscnt
,str2
);
2144 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2147 char *pathname
= NULL
;
2148 unsigned int offset
;
2150 size_t converted_size
;
2152 WERROR werr
= WERR_OK
;
2153 TALLOC_CTX
*mem_ctx
= talloc_tos();
2155 struct rpc_pipe_client
*cli
= NULL
;
2156 union srvsvc_NetShareInfo info
;
2157 struct srvsvc_NetShareInfo2 info2
;
2159 if (!str1
|| !str2
|| !p
) {
2163 /* check it's a supported varient */
2164 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2167 if (!check_share_info(uLevel
,str2
)) {
2174 /* Do we have a string ? */
2175 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2178 pull_ascii_fstring(sharename
,data
);
2184 /* only support disk share adds */
2185 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2189 offset
= IVAL(data
, 16);
2190 if (offset
>= mdrcnt
) {
2191 res
= ERRinvalidparam
;
2195 /* Do we have a string ? */
2196 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2199 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2201 offset
= IVAL(data
, 26);
2203 if (offset
>= mdrcnt
) {
2204 res
= ERRinvalidparam
;
2208 /* Do we have a string ? */
2209 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2213 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2214 offset
? (data
+offset
) : "", &converted_size
))
2216 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2224 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
2225 rpc_srvsvc_dispatch
, conn
->server_info
,
2227 if (!NT_STATUS_IS_OK(status
)) {
2228 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2229 nt_errstr(status
)));
2230 res
= W_ERROR_V(ntstatus_to_werror(status
));
2234 info2
.name
= sharename
;
2235 info2
.type
= STYPE_DISKTREE
;
2236 info2
.comment
= comment
;
2237 info2
.permissions
= 0;
2238 info2
.max_users
= 0;
2239 info2
.current_users
= 0;
2240 info2
.path
= pathname
;
2241 info2
.password
= NULL
;
2243 info
.info2
= &info2
;
2245 status
= rpccli_srvsvc_NetShareAdd(cli
, mem_ctx
,
2246 cli
->srv_name_slash
,
2251 if (!NT_STATUS_IS_OK(status
)) {
2252 res
= W_ERROR_V(ntstatus_to_werror(status
));
2255 if (!W_ERROR_IS_OK(werr
)) {
2256 res
= W_ERROR_V(werr
);
2261 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2265 SSVAL(*rparam
,0,NERR_Success
);
2266 SSVAL(*rparam
,2,0); /* converter word */
2267 SSVAL(*rparam
,4,*rdata_len
);
2275 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2280 SSVAL(*rparam
,0,res
);
2285 /****************************************************************************
2286 view list of groups available
2287 ****************************************************************************/
2289 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2290 char *param
, int tpscnt
,
2291 char *data
, int tdscnt
,
2292 int mdrcnt
,int mprcnt
,
2293 char **rdata
,char **rparam
,
2294 int *rdata_len
,int *rparam_len
)
2298 int resume_context
, cli_buf_size
;
2299 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2300 char *str2
= skip_string(param
,tpscnt
,str1
);
2301 char *p
= skip_string(param
,tpscnt
,str2
);
2303 uint32_t num_groups
;
2304 uint32_t resume_handle
;
2305 struct rpc_pipe_client
*samr_pipe
;
2306 struct policy_handle samr_handle
, domain_handle
;
2309 if (!str1
|| !str2
|| !p
) {
2313 if (strcmp(str1
,"WrLeh") != 0) {
2318 * W-> resume context (number of users to skip)
2319 * r -> return parameter pointer to receive buffer
2320 * L -> length of receive buffer
2321 * e -> return parameter number of entries
2322 * h -> return parameter total number of users
2325 if (strcmp("B21",str2
) != 0) {
2329 status
= rpc_pipe_open_internal(
2330 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2331 conn
->server_info
, &samr_pipe
);
2332 if (!NT_STATUS_IS_OK(status
)) {
2333 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2334 nt_errstr(status
)));
2338 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2339 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2340 if (!NT_STATUS_IS_OK(status
)) {
2341 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2342 nt_errstr(status
)));
2346 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2347 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2348 get_global_sam_sid(), &domain_handle
);
2349 if (!NT_STATUS_IS_OK(status
)) {
2350 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2351 nt_errstr(status
)));
2352 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2356 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2357 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2358 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2359 "%d\n", resume_context
, cli_buf_size
));
2361 *rdata_len
= cli_buf_size
;
2362 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2369 errflags
= NERR_Success
;
2374 struct samr_SamArray
*sam_entries
;
2375 uint32_t num_entries
;
2377 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2382 if (!NT_STATUS_IS_OK(status
)) {
2383 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2384 "%s\n", nt_errstr(status
)));
2388 if (num_entries
== 0) {
2389 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2390 "no entries -- done\n"));
2394 for(i
=0; i
<num_entries
; i
++) {
2397 name
= sam_entries
->entries
[i
].name
.string
;
2399 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2400 /* set overflow error */
2401 DEBUG(3,("overflow on entry %d group %s\n", i
,
2407 /* truncate the name at 21 chars. */
2409 strlcpy(p
, name
, 21);
2410 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2412 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2417 if (errflags
!= NERR_Success
) {
2421 TALLOC_FREE(sam_entries
);
2424 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2425 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2427 *rdata_len
= PTR_DIFF(p
,*rdata
);
2430 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2434 SSVAL(*rparam
, 0, errflags
);
2435 SSVAL(*rparam
, 2, 0); /* converter word */
2436 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2437 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2442 /*******************************************************************
2443 Get groups that a user is a member of.
2444 ******************************************************************/
2446 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2447 char *param
, int tpscnt
,
2448 char *data
, int tdscnt
,
2449 int mdrcnt
,int mprcnt
,
2450 char **rdata
,char **rparam
,
2451 int *rdata_len
,int *rparam_len
)
2453 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2454 char *str2
= skip_string(param
,tpscnt
,str1
);
2455 char *UserName
= skip_string(param
,tpscnt
,str2
);
2456 char *p
= skip_string(param
,tpscnt
,UserName
);
2457 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2458 const char *level_string
;
2464 struct rpc_pipe_client
*samr_pipe
;
2465 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2466 struct lsa_String name
;
2467 struct lsa_Strings names
;
2468 struct samr_Ids type
, rid
;
2469 struct samr_RidWithAttributeArray
*rids
;
2472 if (!str1
|| !str2
|| !UserName
|| !p
) {
2477 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2482 /* check it's a supported varient */
2484 if ( strcmp(str1
,"zWrLeh") != 0 )
2489 level_string
= "B21";
2495 if (strcmp(level_string
,str2
) != 0)
2498 *rdata_len
= mdrcnt
+ 1024;
2499 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2504 SSVAL(*rparam
,0,NERR_Success
);
2505 SSVAL(*rparam
,2,0); /* converter word */
2508 endp
= *rdata
+ *rdata_len
;
2510 status
= rpc_pipe_open_internal(
2511 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2512 conn
->server_info
, &samr_pipe
);
2513 if (!NT_STATUS_IS_OK(status
)) {
2514 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2515 nt_errstr(status
)));
2519 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2520 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2521 if (!NT_STATUS_IS_OK(status
)) {
2522 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2523 nt_errstr(status
)));
2527 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2528 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2529 get_global_sam_sid(), &domain_handle
);
2530 if (!NT_STATUS_IS_OK(status
)) {
2531 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2532 nt_errstr(status
)));
2536 name
.string
= UserName
;
2538 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2539 &domain_handle
, 1, &name
,
2541 if (!NT_STATUS_IS_OK(status
)) {
2542 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2543 nt_errstr(status
)));
2547 if (type
.ids
[0] != SID_NAME_USER
) {
2548 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2549 sid_type_lookup(type
.ids
[0])));
2553 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2555 SAMR_USER_ACCESS_GET_GROUPS
,
2556 rid
.ids
[0], &user_handle
);
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2559 nt_errstr(status
)));
2563 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2564 &user_handle
, &rids
);
2565 if (!NT_STATUS_IS_OK(status
)) {
2566 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2567 nt_errstr(status
)));
2571 for (i
=0; i
<rids
->count
; i
++) {
2573 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2575 1, &rids
->rids
[i
].rid
,
2577 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2578 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2584 *rdata_len
= PTR_DIFF(p
,*rdata
);
2586 SSVAL(*rparam
,4,count
); /* is this right?? */
2587 SSVAL(*rparam
,6,count
); /* is this right?? */
2592 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2594 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2596 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2601 /*******************************************************************
2603 ******************************************************************/
2605 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2606 char *param
, int tpscnt
,
2607 char *data
, int tdscnt
,
2608 int mdrcnt
,int mprcnt
,
2609 char **rdata
,char **rparam
,
2610 int *rdata_len
,int *rparam_len
)
2615 int i
, resume_context
, cli_buf_size
;
2616 uint32_t resume_handle
;
2618 struct rpc_pipe_client
*samr_pipe
;
2619 struct policy_handle samr_handle
, domain_handle
;
2622 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2623 char *str2
= skip_string(param
,tpscnt
,str1
);
2624 char *p
= skip_string(param
,tpscnt
,str2
);
2627 if (!str1
|| !str2
|| !p
) {
2631 if (strcmp(str1
,"WrLeh") != 0)
2634 * W-> resume context (number of users to skip)
2635 * r -> return parameter pointer to receive buffer
2636 * L -> length of receive buffer
2637 * e -> return parameter number of entries
2638 * h -> return parameter total number of users
2641 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2642 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2643 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2644 resume_context
, cli_buf_size
));
2647 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2652 /* check it's a supported varient */
2653 if (strcmp("B21",str2
) != 0)
2656 *rdata_len
= cli_buf_size
;
2657 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2663 endp
= *rdata
+ *rdata_len
;
2665 status
= rpc_pipe_open_internal(
2666 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2667 conn
->server_info
, &samr_pipe
);
2668 if (!NT_STATUS_IS_OK(status
)) {
2669 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2670 nt_errstr(status
)));
2674 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2675 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2676 if (!NT_STATUS_IS_OK(status
)) {
2677 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2678 nt_errstr(status
)));
2682 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2683 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2684 get_global_sam_sid(), &domain_handle
);
2685 if (!NT_STATUS_IS_OK(status
)) {
2686 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2687 nt_errstr(status
)));
2688 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2692 errflags
=NERR_Success
;
2697 struct samr_SamArray
*sam_entries
;
2698 uint32_t num_entries
;
2700 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2706 if (!NT_STATUS_IS_OK(status
)) {
2707 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2708 "%s\n", nt_errstr(status
)));
2712 if (num_entries
== 0) {
2713 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2714 "no entries -- done\n"));
2718 for (i
=0; i
<num_entries
; i
++) {
2721 name
= sam_entries
->entries
[i
].name
.string
;
2723 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2724 &&(strlen(name
)<=21)) {
2725 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2726 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2727 "username %s\n",count_sent
,p
));
2731 /* set overflow error */
2732 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2733 "username %s\n",count_sent
,name
));
2739 if (errflags
!= NERR_Success
) {
2743 TALLOC_FREE(sam_entries
);
2746 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2747 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2749 *rdata_len
= PTR_DIFF(p
,*rdata
);
2751 SSVAL(*rparam
,0,errflags
);
2752 SSVAL(*rparam
,2,0); /* converter word */
2753 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2754 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2759 /****************************************************************************
2760 Get the time of day info.
2761 ****************************************************************************/
2763 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2764 char *param
, int tpscnt
,
2765 char *data
, int tdscnt
,
2766 int mdrcnt
,int mprcnt
,
2767 char **rdata
,char **rparam
,
2768 int *rdata_len
,int *rparam_len
)
2771 time_t unixdate
= time(NULL
);
2775 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2781 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2786 SSVAL(*rparam
,0,NERR_Success
);
2787 SSVAL(*rparam
,2,0); /* converter word */
2791 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2792 by NT in a "net time" operation,
2793 it seems to ignore the one below */
2795 /* the client expects to get localtime, not GMT, in this bit
2796 (I think, this needs testing) */
2797 t
= localtime(&unixdate
);
2802 SIVAL(p
,4,0); /* msecs ? */
2803 SCVAL(p
,8,t
->tm_hour
);
2804 SCVAL(p
,9,t
->tm_min
);
2805 SCVAL(p
,10,t
->tm_sec
);
2806 SCVAL(p
,11,0); /* hundredths of seconds */
2807 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2808 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2809 SCVAL(p
,16,t
->tm_mday
);
2810 SCVAL(p
,17,t
->tm_mon
+ 1);
2811 SSVAL(p
,18,1900+t
->tm_year
);
2812 SCVAL(p
,20,t
->tm_wday
);
2817 /****************************************************************************
2818 Set the user password.
2819 *****************************************************************************/
2821 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2822 char *param
, int tpscnt
,
2823 char *data
, int tdscnt
,
2824 int mdrcnt
,int mprcnt
,
2825 char **rdata
,char **rparam
,
2826 int *rdata_len
,int *rparam_len
)
2828 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2831 fstring pass1
,pass2
;
2833 /* Skip 2 strings. */
2834 p
= skip_string(param
,tpscnt
,np
);
2835 p
= skip_string(param
,tpscnt
,p
);
2841 /* Do we have a string ? */
2842 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2845 pull_ascii_fstring(user
,p
);
2847 p
= skip_string(param
,tpscnt
,p
);
2852 memset(pass1
,'\0',sizeof(pass1
));
2853 memset(pass2
,'\0',sizeof(pass2
));
2855 * We use 31 here not 32 as we're checking
2856 * the last byte we want to access is safe.
2858 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2862 memcpy(pass2
,p
+16,16);
2865 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2872 SSVAL(*rparam
,0,NERR_badpass
);
2873 SSVAL(*rparam
,2,0); /* converter word */
2875 DEBUG(3,("Set password for <%s>\n",user
));
2878 * Attempt to verify the old password against smbpasswd entries
2879 * Win98 clients send old and new password in plaintext for this call.
2883 struct auth_serversupplied_info
*server_info
= NULL
;
2884 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2886 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2889 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2890 SSVAL(*rparam
,0,NERR_Success
);
2894 TALLOC_FREE(server_info
);
2896 data_blob_clear_free(&password
);
2900 * If the plaintext change failed, attempt
2901 * the old encrypted method. NT will generate this
2902 * after trying the samr method. Note that this
2903 * method is done as a last resort as this
2904 * password change method loses the NT password hash
2905 * and cannot change the UNIX password as no plaintext
2909 if(SVAL(*rparam
,0) != NERR_Success
) {
2910 struct samu
*hnd
= NULL
;
2912 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2914 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2915 SSVAL(*rparam
,0,NERR_Success
);
2922 memset((char *)pass1
,'\0',sizeof(fstring
));
2923 memset((char *)pass2
,'\0',sizeof(fstring
));
2928 /****************************************************************************
2929 Set the user password (SamOEM version - gets plaintext).
2930 ****************************************************************************/
2932 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2933 char *param
, int tpscnt
,
2934 char *data
, int tdscnt
,
2935 int mdrcnt
,int mprcnt
,
2936 char **rdata
,char **rparam
,
2937 int *rdata_len
,int *rparam_len
)
2940 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2942 TALLOC_CTX
*mem_ctx
= talloc_tos();
2944 struct rpc_pipe_client
*cli
= NULL
;
2945 struct lsa_AsciiString server
, account
;
2946 struct samr_CryptPassword password
;
2947 struct samr_Password hash
;
2948 int errcode
= NERR_badpass
;
2952 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2962 SSVAL(*rparam
,0,NERR_badpass
);
2965 * Check the parameter definition is correct.
2968 /* Do we have a string ? */
2969 if (skip_string(param
,tpscnt
,p
) == 0) {
2972 if(!strequal(p
, "zsT")) {
2973 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2976 p
= skip_string(param
, tpscnt
, p
);
2981 /* Do we have a string ? */
2982 if (skip_string(param
,tpscnt
,p
) == 0) {
2985 if(!strequal(p
, "B516B16")) {
2986 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2989 p
= skip_string(param
,tpscnt
,p
);
2993 /* Do we have a string ? */
2994 if (skip_string(param
,tpscnt
,p
) == 0) {
2997 p
+= pull_ascii_fstring(user
,p
);
2999 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3001 if (tdscnt
!= 532) {
3002 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3006 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3007 if (bufsize
!= 532) {
3008 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3012 memcpy(password
.data
, data
, 516);
3013 memcpy(hash
.hash
, data
+516, 16);
3015 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_samr
.syntax_id
,
3016 rpc_samr_dispatch
, conn
->server_info
,
3018 if (!NT_STATUS_IS_OK(status
)) {
3019 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3020 nt_errstr(status
)));
3021 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3025 init_lsa_AsciiString(&server
, global_myname());
3026 init_lsa_AsciiString(&account
, user
);
3028 status
= rpccli_samr_OemChangePasswordUser2(cli
, mem_ctx
,
3033 if (!NT_STATUS_IS_OK(status
)) {
3034 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3038 errcode
= NERR_Success
;
3040 SSVAL(*rparam
,0,errcode
);
3041 SSVAL(*rparam
,2,0); /* converter word */
3046 /****************************************************************************
3049 ****************************************************************************/
3051 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
3052 char *param
, int tpscnt
,
3053 char *data
, int tdscnt
,
3054 int mdrcnt
,int mprcnt
,
3055 char **rdata
,char **rparam
,
3056 int *rdata_len
,int *rparam_len
)
3058 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3059 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3060 char *str2
= skip_string(param
,tpscnt
,str1
);
3061 char *p
= skip_string(param
,tpscnt
,str2
);
3065 WERROR werr
= WERR_OK
;
3067 TALLOC_CTX
*mem_ctx
= talloc_tos();
3069 struct rpc_pipe_client
*cli
= NULL
;
3070 struct policy_handle handle
;
3071 struct spoolss_DevmodeContainer devmode_ctr
;
3072 enum spoolss_JobControl command
;
3074 if (!str1
|| !str2
|| !p
) {
3078 * We use 1 here not 2 as we're checking
3079 * the last byte we want to access is safe.
3081 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3084 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3087 /* check it's a supported varient */
3088 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3092 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3098 ZERO_STRUCT(handle
);
3100 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
3101 rpc_spoolss_dispatch
, conn
->server_info
,
3103 if (!NT_STATUS_IS_OK(status
)) {
3104 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3105 nt_errstr(status
)));
3106 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3110 ZERO_STRUCT(devmode_ctr
);
3112 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3116 SEC_FLAG_MAXIMUM_ALLOWED
,
3119 if (!NT_STATUS_IS_OK(status
)) {
3120 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3123 if (!W_ERROR_IS_OK(werr
)) {
3124 errcode
= W_ERROR_V(werr
);
3128 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3129 * and NERR_DestNotFound if share did not exist */
3131 errcode
= NERR_Success
;
3134 case 81: /* delete */
3135 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3137 case 82: /* pause */
3138 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3140 case 83: /* resume */
3141 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3144 errcode
= NERR_notsupported
;
3148 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3151 NULL
, /* unique ptr ctr */
3154 if (!NT_STATUS_IS_OK(status
)) {
3155 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3158 if (!W_ERROR_IS_OK(werr
)) {
3159 errcode
= W_ERROR_V(werr
);
3164 if (cli
&& is_valid_policy_hnd(&handle
)) {
3165 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3168 SSVAL(*rparam
,0,errcode
);
3169 SSVAL(*rparam
,2,0); /* converter word */
3174 /****************************************************************************
3175 Purge a print queue - or pause or resume it.
3176 ****************************************************************************/
3178 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
3179 char *param
, int tpscnt
,
3180 char *data
, int tdscnt
,
3181 int mdrcnt
,int mprcnt
,
3182 char **rdata
,char **rparam
,
3183 int *rdata_len
,int *rparam_len
)
3185 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3186 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3187 char *str2
= skip_string(param
,tpscnt
,str1
);
3188 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3189 int errcode
= NERR_notsupported
;
3190 WERROR werr
= WERR_OK
;
3193 TALLOC_CTX
*mem_ctx
= talloc_tos();
3194 struct rpc_pipe_client
*cli
= NULL
;
3195 struct policy_handle handle
;
3196 struct spoolss_SetPrinterInfoCtr info_ctr
;
3197 struct spoolss_DevmodeContainer devmode_ctr
;
3198 struct sec_desc_buf secdesc_ctr
;
3199 enum spoolss_PrinterControl command
;
3201 if (!str1
|| !str2
|| !QueueName
) {
3205 /* check it's a supported varient */
3206 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3210 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3216 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3220 ZERO_STRUCT(handle
);
3222 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
3223 rpc_spoolss_dispatch
, conn
->server_info
,
3225 if (!NT_STATUS_IS_OK(status
)) {
3226 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3227 nt_errstr(status
)));
3228 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3232 ZERO_STRUCT(devmode_ctr
);
3234 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3238 SEC_FLAG_MAXIMUM_ALLOWED
,
3241 if (!NT_STATUS_IS_OK(status
)) {
3242 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3245 if (!W_ERROR_IS_OK(werr
)) {
3246 errcode
= W_ERROR_V(werr
);
3251 case 74: /* Pause queue */
3252 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3254 case 75: /* Resume queue */
3255 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3257 case 103: /* Purge */
3258 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3261 werr
= WERR_NOT_SUPPORTED
;
3265 if (!W_ERROR_IS_OK(werr
)) {
3266 errcode
= W_ERROR_V(werr
);
3270 ZERO_STRUCT(info_ctr
);
3271 ZERO_STRUCT(secdesc_ctr
);
3273 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3280 if (!NT_STATUS_IS_OK(status
)) {
3281 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3284 if (!W_ERROR_IS_OK(werr
)) {
3285 errcode
= W_ERROR_V(werr
);
3289 errcode
= W_ERROR_V(werr
);
3293 if (cli
&& is_valid_policy_hnd(&handle
)) {
3294 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3297 SSVAL(*rparam
,0,errcode
);
3298 SSVAL(*rparam
,2,0); /* converter word */
3303 /****************************************************************************
3304 set the property of a print job (undocumented?)
3305 ? function = 0xb -> set name of print job
3306 ? function = 0x6 -> move print job up/down
3307 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3308 or <WWsTP> <WB21BB16B10zWWzDDz>
3309 ****************************************************************************/
3311 static int check_printjob_info(struct pack_desc
* desc
,
3312 int uLevel
, char* id
)
3314 desc
->subformat
= NULL
;
3316 case 0: desc
->format
= "W"; break;
3317 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3318 case 2: desc
->format
= "WWzWWDDzz"; break;
3319 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3320 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3322 DEBUG(0,("check_printjob_info: invalid level %d\n",
3326 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3327 DEBUG(0,("check_printjob_info: invalid format %s\n",
3328 id
? id
: "<NULL>" ));
3334 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
3335 char *param
, int tpscnt
,
3336 char *data
, int tdscnt
,
3337 int mdrcnt
,int mprcnt
,
3338 char **rdata
,char **rparam
,
3339 int *rdata_len
,int *rparam_len
)
3341 struct pack_desc desc
;
3342 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3343 char *str2
= skip_string(param
,tpscnt
,str1
);
3344 char *p
= skip_string(param
,tpscnt
,str2
);
3347 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3348 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3351 TALLOC_CTX
*mem_ctx
= talloc_tos();
3354 struct rpc_pipe_client
*cli
= NULL
;
3355 struct policy_handle handle
;
3356 struct spoolss_DevmodeContainer devmode_ctr
;
3357 struct spoolss_JobInfoContainer ctr
;
3358 union spoolss_JobInfo info
;
3359 struct spoolss_SetJobInfo1 info1
;
3361 if (!str1
|| !str2
|| !p
) {
3365 * We use 1 here not 2 as we're checking
3366 * the last byte we want to access is safe.
3368 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3371 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3374 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3381 /* check it's a supported varient */
3382 if ((strcmp(str1
,"WWsTP")) ||
3383 (!check_printjob_info(&desc
,uLevel
,str2
)))
3386 errcode
= NERR_notsupported
;
3390 /* change print job name, data gives the name */
3396 ZERO_STRUCT(handle
);
3398 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
3399 rpc_spoolss_dispatch
, conn
->server_info
,
3401 if (!NT_STATUS_IS_OK(status
)) {
3402 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3403 nt_errstr(status
)));
3404 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3408 ZERO_STRUCT(devmode_ctr
);
3410 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3414 SEC_FLAG_MAXIMUM_ALLOWED
,
3417 if (!NT_STATUS_IS_OK(status
)) {
3418 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3421 if (!W_ERROR_IS_OK(werr
)) {
3422 errcode
= W_ERROR_V(werr
);
3426 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3432 if (!W_ERROR_IS_OK(werr
)) {
3433 errcode
= W_ERROR_V(werr
);
3439 info1
.job_id
= info
.info1
.job_id
;
3440 info1
.printer_name
= info
.info1
.printer_name
;
3441 info1
.user_name
= info
.info1
.user_name
;
3442 info1
.document_name
= data
;
3443 info1
.data_type
= info
.info1
.data_type
;
3444 info1
.text_status
= info
.info1
.text_status
;
3445 info1
.status
= info
.info1
.status
;
3446 info1
.priority
= info
.info1
.priority
;
3447 info1
.position
= info
.info1
.position
;
3448 info1
.total_pages
= info
.info1
.total_pages
;
3449 info1
.pages_printed
= info
.info1
.pages_printed
;
3450 info1
.submitted
= info
.info1
.submitted
;
3453 ctr
.info
.info1
= &info1
;
3455 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3461 if (!NT_STATUS_IS_OK(status
)) {
3462 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3465 if (!W_ERROR_IS_OK(werr
)) {
3466 errcode
= W_ERROR_V(werr
);
3470 errcode
= NERR_Success
;
3473 if (cli
&& is_valid_policy_hnd(&handle
)) {
3474 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3477 SSVALS(*rparam
,0,errcode
);
3478 SSVAL(*rparam
,2,0); /* converter word */
3484 /****************************************************************************
3485 Get info about the server.
3486 ****************************************************************************/
3488 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3489 char *param
, int tpscnt
,
3490 char *data
, int tdscnt
,
3491 int mdrcnt
,int mprcnt
,
3492 char **rdata
,char **rparam
,
3493 int *rdata_len
,int *rparam_len
)
3495 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3496 char *str2
= skip_string(param
,tpscnt
,str1
);
3497 char *p
= skip_string(param
,tpscnt
,str2
);
3498 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3504 TALLOC_CTX
*mem_ctx
= talloc_tos();
3505 struct rpc_pipe_client
*cli
= NULL
;
3506 union srvsvc_NetSrvInfo info
;
3509 if (!str1
|| !str2
|| !p
) {
3513 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3515 /* check it's a supported varient */
3516 if (!prefix_ok(str1
,"WrLh")) {
3522 if (strcmp(str2
,"B16") != 0) {
3528 if (strcmp(str2
,"B16BBDz") != 0) {
3534 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3540 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3546 if (strcmp(str2
,"DN") != 0) {
3552 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3561 *rdata_len
= mdrcnt
;
3562 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3568 p2
= p
+ struct_len
;
3570 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_srvsvc
.syntax_id
,
3571 rpc_srvsvc_dispatch
, conn
->server_info
,
3573 if (!NT_STATUS_IS_OK(status
)) {
3574 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3575 nt_errstr(status
)));
3576 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3580 status
= rpccli_srvsvc_NetSrvGetInfo(cli
, mem_ctx
,
3585 if (!NT_STATUS_IS_OK(status
)) {
3586 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3589 if (!W_ERROR_IS_OK(werr
)) {
3590 errcode
= W_ERROR_V(werr
);
3594 if (info
.info101
== NULL
) {
3595 errcode
= W_ERROR_V(WERR_INVALID_PARAM
);
3600 srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3601 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3605 SCVAL(p
,0,info
.info101
->version_major
);
3606 SCVAL(p
,1,info
.info101
->version_minor
);
3607 SIVAL(p
,2,info
.info101
->server_type
);
3609 if (mdrcnt
== struct_len
) {
3612 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3613 if (mdrcnt
- struct_len
<= 0) {
3617 info
.info101
->comment
,
3618 MIN(mdrcnt
- struct_len
,
3619 MAX_SERVER_STRING_LENGTH
),
3621 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3629 return False
; /* not yet implemented */
3632 errcode
= NERR_Success
;
3636 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3639 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3643 SSVAL(*rparam
,0,errcode
);
3644 SSVAL(*rparam
,2,0); /* converter word */
3645 SSVAL(*rparam
,4,*rdata_len
);
3650 /****************************************************************************
3651 Get info about the server.
3652 ****************************************************************************/
3654 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3655 char *param
, int tpscnt
,
3656 char *data
, int tdscnt
,
3657 int mdrcnt
,int mprcnt
,
3658 char **rdata
,char **rparam
,
3659 int *rdata_len
,int *rparam_len
)
3661 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3662 char *str2
= skip_string(param
,tpscnt
,str1
);
3663 char *p
= skip_string(param
,tpscnt
,str2
);
3666 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3668 if (!str1
|| !str2
|| !p
) {
3672 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3675 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3680 /* check it's a supported varient */
3681 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3685 *rdata_len
= mdrcnt
+ 1024;
3686 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3691 SSVAL(*rparam
,0,NERR_Success
);
3692 SSVAL(*rparam
,2,0); /* converter word */
3695 endp
= *rdata
+ *rdata_len
;
3697 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3702 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3703 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3705 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3711 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3712 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3713 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3719 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3720 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3722 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3728 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3729 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3732 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3733 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3734 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3740 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3741 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3742 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3748 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3750 SSVAL(*rparam
,4,*rdata_len
);
3755 /****************************************************************************
3756 get info about a user
3758 struct user_info_11 {
3759 char usri11_name[21]; 0-20
3761 char *usri11_comment; 22-25
3762 char *usri11_usr_comment; 26-29
3763 unsigned short usri11_priv; 30-31
3764 unsigned long usri11_auth_flags; 32-35
3765 long usri11_password_age; 36-39
3766 char *usri11_homedir; 40-43
3767 char *usri11_parms; 44-47
3768 long usri11_last_logon; 48-51
3769 long usri11_last_logoff; 52-55
3770 unsigned short usri11_bad_pw_count; 56-57
3771 unsigned short usri11_num_logons; 58-59
3772 char *usri11_logon_server; 60-63
3773 unsigned short usri11_country_code; 64-65
3774 char *usri11_workstations; 66-69
3775 unsigned long usri11_max_storage; 70-73
3776 unsigned short usri11_units_per_week; 74-75
3777 unsigned char *usri11_logon_hours; 76-79
3778 unsigned short usri11_code_page; 80-81
3783 usri11_name specifies the user name for which information is retrieved
3785 usri11_pad aligns the next data structure element to a word boundary
3787 usri11_comment is a null terminated ASCII comment
3789 usri11_user_comment is a null terminated ASCII comment about the user
3791 usri11_priv specifies the level of the privilege assigned to the user.
3792 The possible values are:
3794 Name Value Description
3795 USER_PRIV_GUEST 0 Guest privilege
3796 USER_PRIV_USER 1 User privilege
3797 USER_PRV_ADMIN 2 Administrator privilege
3799 usri11_auth_flags specifies the account operator privileges. The
3800 possible values are:
3802 Name Value Description
3803 AF_OP_PRINT 0 Print operator
3806 Leach, Naik [Page 28]
3810 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3813 AF_OP_COMM 1 Communications operator
3814 AF_OP_SERVER 2 Server operator
3815 AF_OP_ACCOUNTS 3 Accounts operator
3818 usri11_password_age specifies how many seconds have elapsed since the
3819 password was last changed.
3821 usri11_home_dir points to a null terminated ASCII string that contains
3822 the path name of the user's home directory.
3824 usri11_parms points to a null terminated ASCII string that is set
3825 aside for use by applications.
3827 usri11_last_logon specifies the time when the user last logged on.
3828 This value is stored as the number of seconds elapsed since
3829 00:00:00, January 1, 1970.
3831 usri11_last_logoff specifies the time when the user last logged off.
3832 This value is stored as the number of seconds elapsed since
3833 00:00:00, January 1, 1970. A value of 0 means the last logoff
3836 usri11_bad_pw_count specifies the number of incorrect passwords
3837 entered since the last successful logon.
3839 usri11_log1_num_logons specifies the number of times this user has
3840 logged on. A value of -1 means the number of logons is unknown.
3842 usri11_logon_server points to a null terminated ASCII string that
3843 contains the name of the server to which logon requests are sent.
3844 A null string indicates logon requests should be sent to the
3847 usri11_country_code specifies the country code for the user's language
3850 usri11_workstations points to a null terminated ASCII string that
3851 contains the names of workstations the user may log on from.
3852 There may be up to 8 workstations, with the names separated by
3853 commas. A null strings indicates there are no restrictions.
3855 usri11_max_storage specifies the maximum amount of disk space the user
3856 can occupy. A value of 0xffffffff indicates there are no
3859 usri11_units_per_week specifies the equal number of time units into
3860 which a week is divided. This value must be equal to 168.
3862 usri11_logon_hours points to a 21 byte (168 bits) string that
3863 specifies the time during which the user can log on. Each bit
3864 represents one unique hour in a week. The first bit (bit 0, word
3865 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3869 Leach, Naik [Page 29]
3873 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3876 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3877 are no restrictions.
3879 usri11_code_page specifies the code page for the user's language of
3882 All of the pointers in this data structure need to be treated
3883 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3884 to be ignored. The converter word returned in the parameters section
3885 needs to be subtracted from the lower 16 bits to calculate an offset
3886 into the return buffer where this ASCII string resides.
3888 There is no auxiliary data in the response.
3890 ****************************************************************************/
3892 #define usri11_name 0
3893 #define usri11_pad 21
3894 #define usri11_comment 22
3895 #define usri11_usr_comment 26
3896 #define usri11_full_name 30
3897 #define usri11_priv 34
3898 #define usri11_auth_flags 36
3899 #define usri11_password_age 40
3900 #define usri11_homedir 44
3901 #define usri11_parms 48
3902 #define usri11_last_logon 52
3903 #define usri11_last_logoff 56
3904 #define usri11_bad_pw_count 60
3905 #define usri11_num_logons 62
3906 #define usri11_logon_server 64
3907 #define usri11_country_code 68
3908 #define usri11_workstations 70
3909 #define usri11_max_storage 74
3910 #define usri11_units_per_week 78
3911 #define usri11_logon_hours 80
3912 #define usri11_code_page 84
3913 #define usri11_end 86
3915 #define USER_PRIV_GUEST 0
3916 #define USER_PRIV_USER 1
3917 #define USER_PRIV_ADMIN 2
3919 #define AF_OP_PRINT 0
3920 #define AF_OP_COMM 1
3921 #define AF_OP_SERVER 2
3922 #define AF_OP_ACCOUNTS 3
3925 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3926 char *param
, int tpscnt
,
3927 char *data
, int tdscnt
,
3928 int mdrcnt
,int mprcnt
,
3929 char **rdata
,char **rparam
,
3930 int *rdata_len
,int *rparam_len
)
3932 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3933 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3934 char *str2
= skip_string(param
,tpscnt
,str1
);
3935 char *UserName
= skip_string(param
,tpscnt
,str2
);
3936 char *p
= skip_string(param
,tpscnt
,UserName
);
3937 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3940 const char *level_string
;
3942 /* get NIS home of a previously validated user - simeon */
3943 /* With share level security vuid will always be zero.
3944 Don't depend on vuser being non-null !!. JRA */
3945 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3947 DEBUG(3,(" Username of UID %d is %s\n",
3948 (int)vuser
->server_info
->utok
.uid
,
3949 vuser
->server_info
->unix_name
));
3952 if (!str1
|| !str2
|| !UserName
|| !p
) {
3957 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3962 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3964 /* check it's a supported variant */
3965 if (strcmp(str1
,"zWrLh") != 0) {
3969 case 0: level_string
= "B21"; break;
3970 case 1: level_string
= "B21BB16DWzzWz"; break;
3971 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3972 case 10: level_string
= "B21Bzzz"; break;
3973 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3974 default: return False
;
3977 if (strcmp(level_string
,str2
) != 0) {
3981 *rdata_len
= mdrcnt
+ 1024;
3982 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3987 SSVAL(*rparam
,0,NERR_Success
);
3988 SSVAL(*rparam
,2,0); /* converter word */
3991 endp
= *rdata
+ *rdata_len
;
3992 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3998 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4001 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4006 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4007 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4008 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4013 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4014 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4015 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4020 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4021 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4022 strlcpy(p2
,((vuser
!= NULL
)
4023 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
4024 : UserName
),PTR_DIFF(endp
,p2
));
4025 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4032 const char *homedir
= "";
4033 if (vuser
!= NULL
) {
4034 homedir
= pdb_get_homedir(
4035 vuser
->server_info
->sam_account
);
4037 /* modelled after NTAS 3.51 reply */
4038 SSVAL(p
,usri11_priv
,
4039 (get_current_uid(conn
) == sec_initial_uid())?
4040 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4041 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4042 SIVALS(p
,usri11_password_age
,-1); /* password age */
4043 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4044 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4045 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4049 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4050 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4051 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4055 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4056 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4057 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4058 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4059 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4060 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4061 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4065 SSVAL(p
,usri11_country_code
,0); /* country code */
4067 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4068 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4069 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4074 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4075 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4076 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4078 /* a simple way to get logon hours at all times. */
4080 SCVAL(p2
,21,0); /* fix zero termination */
4081 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4086 SSVAL(p
,usri11_code_page
,0); /* code page */
4089 if (uLevel
== 1 || uLevel
== 2) {
4090 memset(p
+22,' ',16); /* password */
4091 SIVALS(p
,38,-1); /* password age */
4093 (get_current_uid(conn
) == sec_initial_uid())?
4094 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4095 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4096 strlcpy(p2
, vuser
? pdb_get_homedir(
4097 vuser
->server_info
->sam_account
) : "",
4099 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4103 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4105 SSVAL(p
,52,0); /* flags */
4106 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4107 strlcpy(p2
, vuser
? pdb_get_logon_script(
4108 vuser
->server_info
->sam_account
) : "",
4110 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4115 SIVAL(p
,60,0); /* auth_flags */
4116 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
4117 strlcpy(p2
,((vuser
!= NULL
)
4118 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
4119 : UserName
),PTR_DIFF(endp
,p2
));
4120 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4124 SIVAL(p
,68,0); /* urs_comment */
4125 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
4126 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4127 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4131 SIVAL(p
,76,0); /* workstations */
4132 SIVAL(p
,80,0); /* last_logon */
4133 SIVAL(p
,84,0); /* last_logoff */
4134 SIVALS(p
,88,-1); /* acct_expires */
4135 SIVALS(p
,92,-1); /* max_storage */
4136 SSVAL(p
,96,168); /* units_per_week */
4137 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4140 SSVALS(p
,102,-1); /* bad_pw_count */
4141 SSVALS(p
,104,-1); /* num_logons */
4142 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4144 TALLOC_CTX
*ctx
= talloc_tos();
4145 int space_rem
= *rdata_len
- (p2
- *rdata
);
4148 if (space_rem
<= 0) {
4151 tmp
= talloc_strdup(ctx
, "\\\\%L");
4155 tmp
= talloc_sub_basic(ctx
,
4168 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4172 SSVAL(p
,110,49); /* country_code */
4173 SSVAL(p
,112,860); /* code page */
4177 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4179 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4184 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
4185 char *param
, int tpscnt
,
4186 char *data
, int tdscnt
,
4187 int mdrcnt
,int mprcnt
,
4188 char **rdata
,char **rparam
,
4189 int *rdata_len
,int *rparam_len
)
4191 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4192 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4193 char *str2
= skip_string(param
,tpscnt
,str1
);
4194 char *p
= skip_string(param
,tpscnt
,str2
);
4196 struct pack_desc desc
;
4198 /* With share level security vuid will always be zero.
4199 Don't depend on vuser being non-null !!. JRA */
4200 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4202 if (!str1
|| !str2
|| !p
) {
4207 DEBUG(3,(" Username of UID %d is %s\n",
4208 (int)vuser
->server_info
->utok
.uid
,
4209 vuser
->server_info
->unix_name
));
4212 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4213 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4218 memset((char *)&desc
,'\0',sizeof(desc
));
4220 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4222 /* check it's a supported varient */
4223 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4226 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4230 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4237 desc
.buflen
= mdrcnt
;
4238 desc
.subformat
= NULL
;
4241 if (init_package(&desc
,1,0)) {
4242 PACKI(&desc
,"W",0); /* code */
4243 PACKS(&desc
,"B21",name
); /* eff. name */
4244 PACKS(&desc
,"B",""); /* pad */
4246 (get_current_uid(conn
) == sec_initial_uid())?
4247 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4248 PACKI(&desc
,"D",0); /* auth flags XXX */
4249 PACKI(&desc
,"W",0); /* num logons */
4250 PACKI(&desc
,"W",0); /* bad pw count */
4251 PACKI(&desc
,"D",0); /* last logon */
4252 PACKI(&desc
,"D",-1); /* last logoff */
4253 PACKI(&desc
,"D",-1); /* logoff time */
4254 PACKI(&desc
,"D",-1); /* kickoff time */
4255 PACKI(&desc
,"D",0); /* password age */
4256 PACKI(&desc
,"D",0); /* password can change */
4257 PACKI(&desc
,"D",-1); /* password must change */
4261 fstrcpy(mypath
,"\\\\");
4262 fstrcat(mypath
,get_local_machine_name());
4264 PACKS(&desc
,"z",mypath
); /* computer */
4267 PACKS(&desc
,"z",lp_workgroup());/* domain */
4268 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
4269 vuser
->server_info
->sam_account
) : ""); /* script path */
4270 PACKI(&desc
,"D",0x00000000); /* reserved */
4273 *rdata_len
= desc
.usedlen
;
4275 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4279 SSVALS(*rparam
,0,desc
.errcode
);
4281 SSVAL(*rparam
,4,desc
.neededlen
);
4283 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4288 /****************************************************************************
4289 api_WAccessGetUserPerms
4290 ****************************************************************************/
4292 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
4293 char *param
, int tpscnt
,
4294 char *data
, int tdscnt
,
4295 int mdrcnt
,int mprcnt
,
4296 char **rdata
,char **rparam
,
4297 int *rdata_len
,int *rparam_len
)
4299 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4300 char *str2
= skip_string(param
,tpscnt
,str1
);
4301 char *user
= skip_string(param
,tpscnt
,str2
);
4302 char *resource
= skip_string(param
,tpscnt
,user
);
4304 if (!str1
|| !str2
|| !user
|| !resource
) {
4308 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4311 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4313 /* check it's a supported varient */
4314 if (strcmp(str1
,"zzh") != 0) {
4317 if (strcmp(str2
,"") != 0) {
4322 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4326 SSVALS(*rparam
,0,0); /* errorcode */
4327 SSVAL(*rparam
,2,0); /* converter word */
4328 SSVAL(*rparam
,4,0x7f); /* permission flags */
4333 /****************************************************************************
4334 api_WPrintJobEnumerate
4335 ****************************************************************************/
4337 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
4338 char *param
, int tpscnt
,
4339 char *data
, int tdscnt
,
4340 int mdrcnt
,int mprcnt
,
4341 char **rdata
,char **rparam
,
4342 int *rdata_len
,int *rparam_len
)
4344 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4345 char *str2
= skip_string(param
,tpscnt
,str1
);
4346 char *p
= skip_string(param
,tpscnt
,str2
);
4350 struct pack_desc desc
;
4353 TALLOC_CTX
*mem_ctx
= talloc_tos();
4356 struct rpc_pipe_client
*cli
= NULL
;
4357 struct policy_handle handle
;
4358 struct spoolss_DevmodeContainer devmode_ctr
;
4359 union spoolss_JobInfo info
;
4361 if (!str1
|| !str2
|| !p
) {
4365 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4367 memset((char *)&desc
,'\0',sizeof(desc
));
4368 memset((char *)&status
,'\0',sizeof(status
));
4370 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4372 /* check it's a supported varient */
4373 if (strcmp(str1
,"WWrLh") != 0) {
4376 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4380 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4384 ZERO_STRUCT(handle
);
4386 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4387 rpc_spoolss_dispatch
, conn
->server_info
,
4389 if (!NT_STATUS_IS_OK(status
)) {
4390 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4391 nt_errstr(status
)));
4392 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4396 ZERO_STRUCT(devmode_ctr
);
4398 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4402 SEC_FLAG_MAXIMUM_ALLOWED
,
4405 if (!NT_STATUS_IS_OK(status
)) {
4406 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4409 if (!W_ERROR_IS_OK(werr
)) {
4410 desc
.errcode
= W_ERROR_V(werr
);
4414 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4420 if (!W_ERROR_IS_OK(werr
)) {
4421 desc
.errcode
= W_ERROR_V(werr
);
4426 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4431 desc
.buflen
= mdrcnt
;
4434 * Don't return data but need to get correct length
4435 * init_package will return wrong size if buflen=0
4437 desc
.buflen
= getlen(desc
.format
);
4438 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4441 if (init_package(&desc
,1,0)) {
4442 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4443 *rdata_len
= desc
.usedlen
;
4445 desc
.errcode
= NERR_JobNotFound
;
4449 if (cli
&& is_valid_policy_hnd(&handle
)) {
4450 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4454 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4458 SSVALS(*rparam
,0,desc
.errcode
);
4460 SSVAL(*rparam
,4,desc
.neededlen
);
4464 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4469 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
4470 char *param
, int tpscnt
,
4471 char *data
, int tdscnt
,
4472 int mdrcnt
,int mprcnt
,
4473 char **rdata
,char **rparam
,
4474 int *rdata_len
,int *rparam_len
)
4476 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4477 char *str2
= skip_string(param
,tpscnt
,str1
);
4478 char *p
= skip_string(param
,tpscnt
,str2
);
4482 struct pack_desc desc
;
4484 TALLOC_CTX
*mem_ctx
= talloc_tos();
4487 struct rpc_pipe_client
*cli
= NULL
;
4488 struct policy_handle handle
;
4489 struct spoolss_DevmodeContainer devmode_ctr
;
4491 union spoolss_JobInfo
*info
;
4493 if (!str1
|| !str2
|| !p
) {
4497 memset((char *)&desc
,'\0',sizeof(desc
));
4499 p
= skip_string(param
,tpscnt
,p
);
4503 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4505 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4507 /* check it's a supported variant */
4508 if (strcmp(str1
,"zWrLeh") != 0) {
4513 return False
; /* defined only for uLevel 0,1,2 */
4516 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4520 ZERO_STRUCT(handle
);
4522 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4523 rpc_spoolss_dispatch
, conn
->server_info
,
4525 if (!NT_STATUS_IS_OK(status
)) {
4526 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4527 nt_errstr(status
)));
4528 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4532 ZERO_STRUCT(devmode_ctr
);
4534 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4538 SEC_FLAG_MAXIMUM_ALLOWED
,
4541 if (!NT_STATUS_IS_OK(status
)) {
4542 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4545 if (!W_ERROR_IS_OK(werr
)) {
4546 desc
.errcode
= W_ERROR_V(werr
);
4550 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4558 if (!W_ERROR_IS_OK(werr
)) {
4559 desc
.errcode
= W_ERROR_V(werr
);
4564 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4570 desc
.buflen
= mdrcnt
;
4572 if (init_package(&desc
,count
,0)) {
4574 for (i
= 0; i
< count
; i
++) {
4575 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4576 if (desc
.errcode
== NERR_Success
) {
4582 if (cli
&& is_valid_policy_hnd(&handle
)) {
4583 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4586 *rdata_len
= desc
.usedlen
;
4589 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4593 SSVALS(*rparam
,0,desc
.errcode
);
4595 SSVAL(*rparam
,4,succnt
);
4596 SSVAL(*rparam
,6,count
);
4598 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4603 static int check_printdest_info(struct pack_desc
* desc
,
4604 int uLevel
, char* id
)
4606 desc
->subformat
= NULL
;
4609 desc
->format
= "B9";
4612 desc
->format
= "B9B21WWzW";
4618 desc
->format
= "zzzWWzzzWW";
4621 DEBUG(0,("check_printdest_info: invalid level %d\n",
4625 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4626 DEBUG(0,("check_printdest_info: invalid string %s\n",
4627 id
? id
: "<NULL>" ));
4633 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4634 struct pack_desc
* desc
)
4638 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4639 buf
[sizeof(buf
)-1] = 0;
4643 PACKS(desc
,"B9",buf
); /* szName */
4645 PACKS(desc
,"B21",""); /* szUserName */
4646 PACKI(desc
,"W",0); /* uJobId */
4647 PACKI(desc
,"W",0); /* fsStatus */
4648 PACKS(desc
,"z",""); /* pszStatus */
4649 PACKI(desc
,"W",0); /* time */
4653 if (uLevel
== 2 || uLevel
== 3) {
4654 PACKS(desc
,"z",buf
); /* pszPrinterName */
4656 PACKS(desc
,"z",""); /* pszUserName */
4657 PACKS(desc
,"z",""); /* pszLogAddr */
4658 PACKI(desc
,"W",0); /* uJobId */
4659 PACKI(desc
,"W",0); /* fsStatus */
4660 PACKS(desc
,"z",""); /* pszStatus */
4661 PACKS(desc
,"z",""); /* pszComment */
4662 PACKS(desc
,"z","NULL"); /* pszDrivers */
4663 PACKI(desc
,"W",0); /* time */
4664 PACKI(desc
,"W",0); /* pad1 */
4669 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
4670 char *param
, int tpscnt
,
4671 char *data
, int tdscnt
,
4672 int mdrcnt
,int mprcnt
,
4673 char **rdata
,char **rparam
,
4674 int *rdata_len
,int *rparam_len
)
4676 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4677 char *str2
= skip_string(param
,tpscnt
,str1
);
4678 char *p
= skip_string(param
,tpscnt
,str2
);
4679 char* PrinterName
= p
;
4681 struct pack_desc desc
;
4684 TALLOC_CTX
*mem_ctx
= talloc_tos();
4687 struct rpc_pipe_client
*cli
= NULL
;
4688 struct policy_handle handle
;
4689 struct spoolss_DevmodeContainer devmode_ctr
;
4690 union spoolss_PrinterInfo info
;
4692 if (!str1
|| !str2
|| !p
) {
4696 memset((char *)&desc
,'\0',sizeof(desc
));
4698 p
= skip_string(param
,tpscnt
,p
);
4702 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4704 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4706 /* check it's a supported varient */
4707 if (strcmp(str1
,"zWrLh") != 0) {
4710 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4714 ZERO_STRUCT(handle
);
4716 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4717 rpc_spoolss_dispatch
, conn
->server_info
,
4719 if (!NT_STATUS_IS_OK(status
)) {
4720 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4721 nt_errstr(status
)));
4722 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4726 ZERO_STRUCT(devmode_ctr
);
4728 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4732 SEC_FLAG_MAXIMUM_ALLOWED
,
4735 if (!NT_STATUS_IS_OK(status
)) {
4737 desc
.errcode
= NERR_DestNotFound
;
4741 if (!W_ERROR_IS_OK(werr
)) {
4743 desc
.errcode
= NERR_DestNotFound
;
4748 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4753 if (!W_ERROR_IS_OK(werr
)) {
4755 desc
.errcode
= NERR_DestNotFound
;
4761 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4766 desc
.buflen
= mdrcnt
;
4769 * Don't return data but need to get correct length
4770 * init_package will return wrong size if buflen=0
4772 desc
.buflen
= getlen(desc
.format
);
4773 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4775 if (init_package(&desc
,1,0)) {
4776 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
4780 if (cli
&& is_valid_policy_hnd(&handle
)) {
4781 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4784 *rdata_len
= desc
.usedlen
;
4787 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4791 SSVALS(*rparam
,0,desc
.errcode
);
4793 SSVAL(*rparam
,4,desc
.neededlen
);
4795 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4801 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4802 char *param
, int tpscnt
,
4803 char *data
, int tdscnt
,
4804 int mdrcnt
,int mprcnt
,
4805 char **rdata
,char **rparam
,
4806 int *rdata_len
,int *rparam_len
)
4808 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4809 char *str2
= skip_string(param
,tpscnt
,str1
);
4810 char *p
= skip_string(param
,tpscnt
,str2
);
4814 struct pack_desc desc
;
4816 TALLOC_CTX
*mem_ctx
= talloc_tos();
4819 struct rpc_pipe_client
*cli
= NULL
;
4820 union spoolss_PrinterInfo
*info
;
4823 if (!str1
|| !str2
|| !p
) {
4827 memset((char *)&desc
,'\0',sizeof(desc
));
4829 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4831 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4833 /* check it's a supported varient */
4834 if (strcmp(str1
,"WrLeh") != 0) {
4837 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4843 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4844 rpc_spoolss_dispatch
, conn
->server_info
,
4846 if (!NT_STATUS_IS_OK(status
)) {
4847 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
4848 nt_errstr(status
)));
4849 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4853 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
4855 cli
->srv_name_slash
,
4860 if (!W_ERROR_IS_OK(werr
)) {
4861 desc
.errcode
= W_ERROR_V(werr
);
4863 desc
.errcode
= NERR_DestNotFound
;
4871 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4878 desc
.buflen
= mdrcnt
;
4879 if (init_package(&desc
,queuecnt
,0)) {
4882 for (i
= 0; i
< count
; i
++) {
4883 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
4885 if (desc
.errcode
== NERR_Success
) {
4891 *rdata_len
= desc
.usedlen
;
4894 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4898 SSVALS(*rparam
,0,desc
.errcode
);
4900 SSVAL(*rparam
,4,succnt
);
4901 SSVAL(*rparam
,6,queuecnt
);
4903 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4908 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4909 char *param
, int tpscnt
,
4910 char *data
, int tdscnt
,
4911 int mdrcnt
,int mprcnt
,
4912 char **rdata
,char **rparam
,
4913 int *rdata_len
,int *rparam_len
)
4915 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4916 char *str2
= skip_string(param
,tpscnt
,str1
);
4917 char *p
= skip_string(param
,tpscnt
,str2
);
4920 struct pack_desc desc
;
4922 if (!str1
|| !str2
|| !p
) {
4926 memset((char *)&desc
,'\0',sizeof(desc
));
4928 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4930 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4932 /* check it's a supported varient */
4933 if (strcmp(str1
,"WrLeh") != 0) {
4936 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4941 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4947 desc
.buflen
= mdrcnt
;
4948 if (init_package(&desc
,1,0)) {
4949 PACKS(&desc
,"B41","NULL");
4952 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4954 *rdata_len
= desc
.usedlen
;
4957 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4961 SSVALS(*rparam
,0,desc
.errcode
);
4963 SSVAL(*rparam
,4,succnt
);
4966 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4971 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4972 char *param
, int tpscnt
,
4973 char *data
, int tdscnt
,
4974 int mdrcnt
,int mprcnt
,
4975 char **rdata
,char **rparam
,
4976 int *rdata_len
,int *rparam_len
)
4978 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4979 char *str2
= skip_string(param
,tpscnt
,str1
);
4980 char *p
= skip_string(param
,tpscnt
,str2
);
4983 struct pack_desc desc
;
4985 if (!str1
|| !str2
|| !p
) {
4988 memset((char *)&desc
,'\0',sizeof(desc
));
4990 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4992 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4994 /* check it's a supported varient */
4995 if (strcmp(str1
,"WrLeh") != 0) {
4998 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5003 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5009 desc
.buflen
= mdrcnt
;
5011 if (init_package(&desc
,1,0)) {
5012 PACKS(&desc
,"B13","lpd");
5015 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5017 *rdata_len
= desc
.usedlen
;
5020 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5024 SSVALS(*rparam
,0,desc
.errcode
);
5026 SSVAL(*rparam
,4,succnt
);
5029 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5034 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
5035 char *param
, int tpscnt
,
5036 char *data
, int tdscnt
,
5037 int mdrcnt
,int mprcnt
,
5038 char **rdata
,char **rparam
,
5039 int *rdata_len
,int *rparam_len
)
5041 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5042 char *str2
= skip_string(param
,tpscnt
,str1
);
5043 char *p
= skip_string(param
,tpscnt
,str2
);
5046 struct pack_desc desc
;
5048 if (!str1
|| !str2
|| !p
) {
5052 memset((char *)&desc
,'\0',sizeof(desc
));
5054 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5056 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5058 /* check it's a supported varient */
5059 if (strcmp(str1
,"WrLeh") != 0) {
5062 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5067 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5072 memset((char *)&desc
,'\0',sizeof(desc
));
5074 desc
.buflen
= mdrcnt
;
5076 if (init_package(&desc
,1,0)) {
5077 PACKS(&desc
,"B13","lp0");
5080 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5082 *rdata_len
= desc
.usedlen
;
5085 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5089 SSVALS(*rparam
,0,desc
.errcode
);
5091 SSVAL(*rparam
,4,succnt
);
5094 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5099 /****************************************************************************
5101 ****************************************************************************/
5103 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
5104 char *param
, int tpscnt
,
5105 char *data
, int tdscnt
,
5106 int mdrcnt
,int mprcnt
,
5107 char **rdata
,char **rparam
,
5108 int *rdata_len
,int *rparam_len
)
5111 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5112 char *str2
= skip_string(param
,tpscnt
,str1
);
5113 char *p
= skip_string(param
,tpscnt
,str2
);
5115 struct pack_desc desc
;
5116 struct sessionid
*session_list
;
5117 int i
, num_sessions
;
5119 if (!str1
|| !str2
|| !p
) {
5123 memset((char *)&desc
,'\0',sizeof(desc
));
5125 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5127 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5128 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5129 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5131 /* check it's a supported varient */
5132 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5135 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5139 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5142 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5147 memset((char *)&desc
,'\0',sizeof(desc
));
5149 desc
.buflen
= mdrcnt
;
5151 if (!init_package(&desc
,num_sessions
,0)) {
5155 for(i
=0; i
<num_sessions
; i
++) {
5156 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5157 PACKS(&desc
, "z", session_list
[i
].username
);
5158 PACKI(&desc
, "W", 1); /* num conns */
5159 PACKI(&desc
, "W", 0); /* num opens */
5160 PACKI(&desc
, "W", 1); /* num users */
5161 PACKI(&desc
, "D", 0); /* session time */
5162 PACKI(&desc
, "D", 0); /* idle time */
5163 PACKI(&desc
, "D", 0); /* flags */
5164 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5167 *rdata_len
= desc
.usedlen
;
5170 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5174 SSVALS(*rparam
,0,desc
.errcode
);
5175 SSVAL(*rparam
,2,0); /* converter */
5176 SSVAL(*rparam
,4,num_sessions
); /* count */
5178 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5184 /****************************************************************************
5185 The buffer was too small.
5186 ****************************************************************************/
5188 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5189 int mdrcnt
, int mprcnt
,
5190 char **rdata
, char **rparam
,
5191 int *rdata_len
, int *rparam_len
)
5193 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5194 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5201 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5203 DEBUG(3,("Supplied buffer too small in API command\n"));
5208 /****************************************************************************
5209 The request is not supported.
5210 ****************************************************************************/
5212 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
5213 char *param
, int tpscnt
,
5214 char *data
, int tdscnt
,
5215 int mdrcnt
, int mprcnt
,
5216 char **rdata
, char **rparam
,
5217 int *rdata_len
, int *rparam_len
)
5220 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5227 SSVAL(*rparam
,0,NERR_notsupported
);
5228 SSVAL(*rparam
,2,0); /* converter word */
5230 DEBUG(3,("Unsupported API command\n"));
5235 static const struct {
5238 bool (*fn
)(connection_struct
*, uint16
,
5241 int,int,char **,char **,int *,int *);
5242 bool auth_user
; /* Deny anonymous access? */
5243 } api_commands
[] = {
5244 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5245 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5246 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5247 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5248 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5249 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5250 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5251 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5252 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5253 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5254 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5255 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5256 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5257 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5258 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5259 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5260 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5261 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5262 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5263 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5264 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5265 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5266 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5267 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5268 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5269 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5270 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5271 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5272 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5273 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5274 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5275 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5276 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5277 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5278 {NULL
, -1, api_Unsupported
}
5279 /* The following RAP calls are not implemented by Samba:
5281 RAP_WFileEnum2 - anon not OK
5286 /****************************************************************************
5287 Handle remote api calls.
5288 ****************************************************************************/
5290 void api_reply(connection_struct
*conn
, uint16 vuid
,
5291 struct smb_request
*req
,
5292 char *data
, char *params
,
5293 int tdscnt
, int tpscnt
,
5294 int mdrcnt
, int mprcnt
)
5296 struct smbd_server_connection
*sconn
= smbd_server_conn
;
5299 char *rparam
= NULL
;
5300 const char *name1
= NULL
;
5301 const char *name2
= NULL
;
5308 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5309 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5314 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5317 api_command
= SVAL(params
,0);
5318 /* Is there a string at position params+2 ? */
5319 if (skip_string(params
,tpscnt
,params
+2)) {
5324 name2
= skip_string(params
,tpscnt
,params
+2);
5329 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5333 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5335 for (i
=0;api_commands
[i
].name
;i
++) {
5336 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5337 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5342 /* Check whether this api call can be done anonymously */
5344 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5345 user_struct
*user
= get_valid_user_struct(sconn
, vuid
);
5347 if (!user
|| user
->server_info
->guest
) {
5348 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5353 rdata
= (char *)SMB_MALLOC(1024);
5355 memset(rdata
,'\0',1024);
5358 rparam
= (char *)SMB_MALLOC(1024);
5360 memset(rparam
,'\0',1024);
5363 if(!rdata
|| !rparam
) {
5364 DEBUG(0,("api_reply: malloc fail !\n"));
5367 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5371 reply
= api_commands
[i
].fn(conn
,
5373 params
,tpscnt
, /* params + length */
5374 data
,tdscnt
, /* data + length */
5376 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5379 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5380 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
5381 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5384 /* if we get False back then it's actually unsupported */
5386 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
5387 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5390 /* If api_Unsupported returns false we can't return anything. */
5392 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5393 rdata
, rdata_len
, False
);