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
)
2939 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2941 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2943 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2953 SSVAL(*rparam
,0,NERR_badpass
);
2956 * Check the parameter definition is correct.
2959 /* Do we have a string ? */
2960 if (skip_string(param
,tpscnt
,p
) == 0) {
2963 if(!strequal(p
, "zsT")) {
2964 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2967 p
= skip_string(param
, tpscnt
, p
);
2972 /* Do we have a string ? */
2973 if (skip_string(param
,tpscnt
,p
) == 0) {
2976 if(!strequal(p
, "B516B16")) {
2977 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2980 p
= skip_string(param
,tpscnt
,p
);
2984 /* Do we have a string ? */
2985 if (skip_string(param
,tpscnt
,p
) == 0) {
2988 p
+= pull_ascii_fstring(user
,p
);
2990 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2993 * Pass the user through the NT -> unix user mapping
2997 (void)map_username(sconn
, user
);
2999 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
3000 SSVAL(*rparam
,0,NERR_Success
);
3006 /****************************************************************************
3009 ****************************************************************************/
3011 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
3012 char *param
, int tpscnt
,
3013 char *data
, int tdscnt
,
3014 int mdrcnt
,int mprcnt
,
3015 char **rdata
,char **rparam
,
3016 int *rdata_len
,int *rparam_len
)
3018 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3019 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3020 char *str2
= skip_string(param
,tpscnt
,str1
);
3021 char *p
= skip_string(param
,tpscnt
,str2
);
3025 WERROR werr
= WERR_OK
;
3027 TALLOC_CTX
*mem_ctx
= talloc_tos();
3029 struct rpc_pipe_client
*cli
= NULL
;
3030 struct policy_handle handle
;
3031 struct spoolss_DevmodeContainer devmode_ctr
;
3032 enum spoolss_JobControl command
;
3034 if (!str1
|| !str2
|| !p
) {
3038 * We use 1 here not 2 as we're checking
3039 * the last byte we want to access is safe.
3041 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3044 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3047 /* check it's a supported varient */
3048 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3052 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3058 ZERO_STRUCT(handle
);
3060 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
3061 rpc_spoolss_dispatch
, conn
->server_info
,
3063 if (!NT_STATUS_IS_OK(status
)) {
3064 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3065 nt_errstr(status
)));
3066 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3070 ZERO_STRUCT(devmode_ctr
);
3072 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3076 SEC_FLAG_MAXIMUM_ALLOWED
,
3079 if (!NT_STATUS_IS_OK(status
)) {
3080 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3083 if (!W_ERROR_IS_OK(werr
)) {
3084 errcode
= W_ERROR_V(werr
);
3088 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3089 * and NERR_DestNotFound if share did not exist */
3091 errcode
= NERR_Success
;
3094 case 81: /* delete */
3095 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3097 case 82: /* pause */
3098 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3100 case 83: /* resume */
3101 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3104 errcode
= NERR_notsupported
;
3108 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3111 NULL
, /* unique ptr ctr */
3114 if (!NT_STATUS_IS_OK(status
)) {
3115 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3118 if (!W_ERROR_IS_OK(werr
)) {
3119 errcode
= W_ERROR_V(werr
);
3124 if (cli
&& is_valid_policy_hnd(&handle
)) {
3125 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3128 SSVAL(*rparam
,0,errcode
);
3129 SSVAL(*rparam
,2,0); /* converter word */
3134 /****************************************************************************
3135 Purge a print queue - or pause or resume it.
3136 ****************************************************************************/
3138 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
3139 char *param
, int tpscnt
,
3140 char *data
, int tdscnt
,
3141 int mdrcnt
,int mprcnt
,
3142 char **rdata
,char **rparam
,
3143 int *rdata_len
,int *rparam_len
)
3145 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3146 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3147 char *str2
= skip_string(param
,tpscnt
,str1
);
3148 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3149 int errcode
= NERR_notsupported
;
3150 WERROR werr
= WERR_OK
;
3153 TALLOC_CTX
*mem_ctx
= talloc_tos();
3154 struct rpc_pipe_client
*cli
= NULL
;
3155 struct policy_handle handle
;
3156 struct spoolss_SetPrinterInfoCtr info_ctr
;
3157 struct spoolss_DevmodeContainer devmode_ctr
;
3158 struct sec_desc_buf secdesc_ctr
;
3159 enum spoolss_PrinterControl command
;
3161 if (!str1
|| !str2
|| !QueueName
) {
3165 /* check it's a supported varient */
3166 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3170 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3176 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3180 ZERO_STRUCT(handle
);
3182 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
3183 rpc_spoolss_dispatch
, conn
->server_info
,
3185 if (!NT_STATUS_IS_OK(status
)) {
3186 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3187 nt_errstr(status
)));
3188 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3192 ZERO_STRUCT(devmode_ctr
);
3194 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3198 SEC_FLAG_MAXIMUM_ALLOWED
,
3201 if (!NT_STATUS_IS_OK(status
)) {
3202 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3205 if (!W_ERROR_IS_OK(werr
)) {
3206 errcode
= W_ERROR_V(werr
);
3211 case 74: /* Pause queue */
3212 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3214 case 75: /* Resume queue */
3215 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3217 case 103: /* Purge */
3218 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3221 werr
= WERR_NOT_SUPPORTED
;
3225 if (!W_ERROR_IS_OK(werr
)) {
3226 errcode
= W_ERROR_V(werr
);
3230 ZERO_STRUCT(info_ctr
);
3231 ZERO_STRUCT(secdesc_ctr
);
3233 status
= rpccli_spoolss_SetPrinter(cli
, mem_ctx
,
3240 if (!NT_STATUS_IS_OK(status
)) {
3241 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3244 if (!W_ERROR_IS_OK(werr
)) {
3245 errcode
= W_ERROR_V(werr
);
3249 errcode
= W_ERROR_V(werr
);
3253 if (cli
&& is_valid_policy_hnd(&handle
)) {
3254 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3257 SSVAL(*rparam
,0,errcode
);
3258 SSVAL(*rparam
,2,0); /* converter word */
3263 /****************************************************************************
3264 set the property of a print job (undocumented?)
3265 ? function = 0xb -> set name of print job
3266 ? function = 0x6 -> move print job up/down
3267 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3268 or <WWsTP> <WB21BB16B10zWWzDDz>
3269 ****************************************************************************/
3271 static int check_printjob_info(struct pack_desc
* desc
,
3272 int uLevel
, char* id
)
3274 desc
->subformat
= NULL
;
3276 case 0: desc
->format
= "W"; break;
3277 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3278 case 2: desc
->format
= "WWzWWDDzz"; break;
3279 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3280 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3282 DEBUG(0,("check_printjob_info: invalid level %d\n",
3286 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3287 DEBUG(0,("check_printjob_info: invalid format %s\n",
3288 id
? id
: "<NULL>" ));
3294 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
3295 char *param
, int tpscnt
,
3296 char *data
, int tdscnt
,
3297 int mdrcnt
,int mprcnt
,
3298 char **rdata
,char **rparam
,
3299 int *rdata_len
,int *rparam_len
)
3301 struct pack_desc desc
;
3302 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3303 char *str2
= skip_string(param
,tpscnt
,str1
);
3304 char *p
= skip_string(param
,tpscnt
,str2
);
3307 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3308 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3311 TALLOC_CTX
*mem_ctx
= talloc_tos();
3314 struct rpc_pipe_client
*cli
= NULL
;
3315 struct policy_handle handle
;
3316 struct spoolss_DevmodeContainer devmode_ctr
;
3317 struct spoolss_JobInfoContainer ctr
;
3318 union spoolss_JobInfo info
;
3319 struct spoolss_SetJobInfo1 info1
;
3321 if (!str1
|| !str2
|| !p
) {
3325 * We use 1 here not 2 as we're checking
3326 * the last byte we want to access is safe.
3328 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3331 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3334 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3341 /* check it's a supported varient */
3342 if ((strcmp(str1
,"WWsTP")) ||
3343 (!check_printjob_info(&desc
,uLevel
,str2
)))
3346 errcode
= NERR_notsupported
;
3350 /* change print job name, data gives the name */
3356 ZERO_STRUCT(handle
);
3358 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
3359 rpc_spoolss_dispatch
, conn
->server_info
,
3361 if (!NT_STATUS_IS_OK(status
)) {
3362 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3363 nt_errstr(status
)));
3364 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3368 ZERO_STRUCT(devmode_ctr
);
3370 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
3374 SEC_FLAG_MAXIMUM_ALLOWED
,
3377 if (!NT_STATUS_IS_OK(status
)) {
3378 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3381 if (!W_ERROR_IS_OK(werr
)) {
3382 errcode
= W_ERROR_V(werr
);
3386 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3392 if (!W_ERROR_IS_OK(werr
)) {
3393 errcode
= W_ERROR_V(werr
);
3399 info1
.job_id
= info
.info1
.job_id
;
3400 info1
.printer_name
= info
.info1
.printer_name
;
3401 info1
.user_name
= info
.info1
.user_name
;
3402 info1
.document_name
= data
;
3403 info1
.data_type
= info
.info1
.data_type
;
3404 info1
.text_status
= info
.info1
.text_status
;
3405 info1
.status
= info
.info1
.status
;
3406 info1
.priority
= info
.info1
.priority
;
3407 info1
.position
= info
.info1
.position
;
3408 info1
.total_pages
= info
.info1
.total_pages
;
3409 info1
.pages_printed
= info
.info1
.pages_printed
;
3410 info1
.submitted
= info
.info1
.submitted
;
3413 ctr
.info
.info1
= &info1
;
3415 status
= rpccli_spoolss_SetJob(cli
, mem_ctx
,
3421 if (!NT_STATUS_IS_OK(status
)) {
3422 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3425 if (!W_ERROR_IS_OK(werr
)) {
3426 errcode
= W_ERROR_V(werr
);
3430 errcode
= NERR_Success
;
3433 if (cli
&& is_valid_policy_hnd(&handle
)) {
3434 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
3437 SSVALS(*rparam
,0,errcode
);
3438 SSVAL(*rparam
,2,0); /* converter word */
3444 /****************************************************************************
3445 Get info about the server.
3446 ****************************************************************************/
3448 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3449 char *param
, int tpscnt
,
3450 char *data
, int tdscnt
,
3451 int mdrcnt
,int mprcnt
,
3452 char **rdata
,char **rparam
,
3453 int *rdata_len
,int *rparam_len
)
3455 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3456 char *str2
= skip_string(param
,tpscnt
,str1
);
3457 char *p
= skip_string(param
,tpscnt
,str2
);
3458 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3462 if (!str1
|| !str2
|| !p
) {
3466 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3468 /* check it's a supported varient */
3469 if (!prefix_ok(str1
,"WrLh")) {
3475 if (strcmp(str2
,"B16") != 0) {
3481 if (strcmp(str2
,"B16BBDz") != 0) {
3487 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3493 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3499 if (strcmp(str2
,"DN") != 0) {
3505 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3514 *rdata_len
= mdrcnt
;
3515 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3521 p2
= p
+ struct_len
;
3523 srvstr_push(NULL
, 0, p
,global_myname(),16,
3524 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3528 struct srv_info_struct
*servers
=NULL
;
3530 char *comment
= NULL
;
3531 TALLOC_CTX
*ctx
= talloc_tos();
3532 uint32 servertype
= lp_default_server_announce();
3534 comment
= talloc_strdup(ctx
,lp_serverstring());
3539 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
3540 for (i
=0;i
<count
;i
++) {
3541 if (strequal(servers
[i
].name
,global_myname())) {
3542 servertype
= servers
[i
].type
;
3543 TALLOC_FREE(comment
);
3544 comment
= talloc_strdup(ctx
,
3545 servers
[i
].comment
);
3555 SCVAL(p
,0,lp_major_announce_version());
3556 SCVAL(p
,1,lp_minor_announce_version());
3557 SIVAL(p
,2,servertype
);
3559 if (mdrcnt
== struct_len
) {
3562 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3563 comment
= talloc_sub_advanced(
3565 lp_servicename(SNUM(conn
)),
3566 conn
->server_info
->unix_name
,
3568 conn
->server_info
->utok
.gid
,
3569 conn
->server_info
->sanitized_username
,
3570 pdb_get_domain(conn
->server_info
->sam_account
),
3575 if (mdrcnt
- struct_len
<= 0) {
3580 MIN(mdrcnt
- struct_len
,
3581 MAX_SERVER_STRING_LENGTH
),
3583 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3591 return False
; /* not yet implemented */
3594 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3597 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3601 SSVAL(*rparam
,0,NERR_Success
);
3602 SSVAL(*rparam
,2,0); /* converter word */
3603 SSVAL(*rparam
,4,*rdata_len
);
3608 /****************************************************************************
3609 Get info about the server.
3610 ****************************************************************************/
3612 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3613 char *param
, int tpscnt
,
3614 char *data
, int tdscnt
,
3615 int mdrcnt
,int mprcnt
,
3616 char **rdata
,char **rparam
,
3617 int *rdata_len
,int *rparam_len
)
3619 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3620 char *str2
= skip_string(param
,tpscnt
,str1
);
3621 char *p
= skip_string(param
,tpscnt
,str2
);
3624 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3626 if (!str1
|| !str2
|| !p
) {
3630 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3633 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3638 /* check it's a supported varient */
3639 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3643 *rdata_len
= mdrcnt
+ 1024;
3644 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3649 SSVAL(*rparam
,0,NERR_Success
);
3650 SSVAL(*rparam
,2,0); /* converter word */
3653 endp
= *rdata
+ *rdata_len
;
3655 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3660 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3661 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3663 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3669 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3670 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3671 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3677 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3678 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3680 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3686 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3687 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3690 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3691 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3692 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3698 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3699 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3700 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3706 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3708 SSVAL(*rparam
,4,*rdata_len
);
3713 /****************************************************************************
3714 get info about a user
3716 struct user_info_11 {
3717 char usri11_name[21]; 0-20
3719 char *usri11_comment; 22-25
3720 char *usri11_usr_comment; 26-29
3721 unsigned short usri11_priv; 30-31
3722 unsigned long usri11_auth_flags; 32-35
3723 long usri11_password_age; 36-39
3724 char *usri11_homedir; 40-43
3725 char *usri11_parms; 44-47
3726 long usri11_last_logon; 48-51
3727 long usri11_last_logoff; 52-55
3728 unsigned short usri11_bad_pw_count; 56-57
3729 unsigned short usri11_num_logons; 58-59
3730 char *usri11_logon_server; 60-63
3731 unsigned short usri11_country_code; 64-65
3732 char *usri11_workstations; 66-69
3733 unsigned long usri11_max_storage; 70-73
3734 unsigned short usri11_units_per_week; 74-75
3735 unsigned char *usri11_logon_hours; 76-79
3736 unsigned short usri11_code_page; 80-81
3741 usri11_name specifies the user name for which information is retrieved
3743 usri11_pad aligns the next data structure element to a word boundary
3745 usri11_comment is a null terminated ASCII comment
3747 usri11_user_comment is a null terminated ASCII comment about the user
3749 usri11_priv specifies the level of the privilege assigned to the user.
3750 The possible values are:
3752 Name Value Description
3753 USER_PRIV_GUEST 0 Guest privilege
3754 USER_PRIV_USER 1 User privilege
3755 USER_PRV_ADMIN 2 Administrator privilege
3757 usri11_auth_flags specifies the account operator privileges. The
3758 possible values are:
3760 Name Value Description
3761 AF_OP_PRINT 0 Print operator
3764 Leach, Naik [Page 28]
3768 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3771 AF_OP_COMM 1 Communications operator
3772 AF_OP_SERVER 2 Server operator
3773 AF_OP_ACCOUNTS 3 Accounts operator
3776 usri11_password_age specifies how many seconds have elapsed since the
3777 password was last changed.
3779 usri11_home_dir points to a null terminated ASCII string that contains
3780 the path name of the user's home directory.
3782 usri11_parms points to a null terminated ASCII string that is set
3783 aside for use by applications.
3785 usri11_last_logon specifies the time when the user last logged on.
3786 This value is stored as the number of seconds elapsed since
3787 00:00:00, January 1, 1970.
3789 usri11_last_logoff specifies the time when the user last logged off.
3790 This value is stored as the number of seconds elapsed since
3791 00:00:00, January 1, 1970. A value of 0 means the last logoff
3794 usri11_bad_pw_count specifies the number of incorrect passwords
3795 entered since the last successful logon.
3797 usri11_log1_num_logons specifies the number of times this user has
3798 logged on. A value of -1 means the number of logons is unknown.
3800 usri11_logon_server points to a null terminated ASCII string that
3801 contains the name of the server to which logon requests are sent.
3802 A null string indicates logon requests should be sent to the
3805 usri11_country_code specifies the country code for the user's language
3808 usri11_workstations points to a null terminated ASCII string that
3809 contains the names of workstations the user may log on from.
3810 There may be up to 8 workstations, with the names separated by
3811 commas. A null strings indicates there are no restrictions.
3813 usri11_max_storage specifies the maximum amount of disk space the user
3814 can occupy. A value of 0xffffffff indicates there are no
3817 usri11_units_per_week specifies the equal number of time units into
3818 which a week is divided. This value must be equal to 168.
3820 usri11_logon_hours points to a 21 byte (168 bits) string that
3821 specifies the time during which the user can log on. Each bit
3822 represents one unique hour in a week. The first bit (bit 0, word
3823 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3827 Leach, Naik [Page 29]
3831 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3834 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3835 are no restrictions.
3837 usri11_code_page specifies the code page for the user's language of
3840 All of the pointers in this data structure need to be treated
3841 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3842 to be ignored. The converter word returned in the parameters section
3843 needs to be subtracted from the lower 16 bits to calculate an offset
3844 into the return buffer where this ASCII string resides.
3846 There is no auxiliary data in the response.
3848 ****************************************************************************/
3850 #define usri11_name 0
3851 #define usri11_pad 21
3852 #define usri11_comment 22
3853 #define usri11_usr_comment 26
3854 #define usri11_full_name 30
3855 #define usri11_priv 34
3856 #define usri11_auth_flags 36
3857 #define usri11_password_age 40
3858 #define usri11_homedir 44
3859 #define usri11_parms 48
3860 #define usri11_last_logon 52
3861 #define usri11_last_logoff 56
3862 #define usri11_bad_pw_count 60
3863 #define usri11_num_logons 62
3864 #define usri11_logon_server 64
3865 #define usri11_country_code 68
3866 #define usri11_workstations 70
3867 #define usri11_max_storage 74
3868 #define usri11_units_per_week 78
3869 #define usri11_logon_hours 80
3870 #define usri11_code_page 84
3871 #define usri11_end 86
3873 #define USER_PRIV_GUEST 0
3874 #define USER_PRIV_USER 1
3875 #define USER_PRIV_ADMIN 2
3877 #define AF_OP_PRINT 0
3878 #define AF_OP_COMM 1
3879 #define AF_OP_SERVER 2
3880 #define AF_OP_ACCOUNTS 3
3883 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3884 char *param
, int tpscnt
,
3885 char *data
, int tdscnt
,
3886 int mdrcnt
,int mprcnt
,
3887 char **rdata
,char **rparam
,
3888 int *rdata_len
,int *rparam_len
)
3890 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3891 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3892 char *str2
= skip_string(param
,tpscnt
,str1
);
3893 char *UserName
= skip_string(param
,tpscnt
,str2
);
3894 char *p
= skip_string(param
,tpscnt
,UserName
);
3895 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3898 const char *level_string
;
3900 /* get NIS home of a previously validated user - simeon */
3901 /* With share level security vuid will always be zero.
3902 Don't depend on vuser being non-null !!. JRA */
3903 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3905 DEBUG(3,(" Username of UID %d is %s\n",
3906 (int)vuser
->server_info
->utok
.uid
,
3907 vuser
->server_info
->unix_name
));
3910 if (!str1
|| !str2
|| !UserName
|| !p
) {
3915 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3920 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3922 /* check it's a supported variant */
3923 if (strcmp(str1
,"zWrLh") != 0) {
3927 case 0: level_string
= "B21"; break;
3928 case 1: level_string
= "B21BB16DWzzWz"; break;
3929 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3930 case 10: level_string
= "B21Bzzz"; break;
3931 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3932 default: return False
;
3935 if (strcmp(level_string
,str2
) != 0) {
3939 *rdata_len
= mdrcnt
+ 1024;
3940 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3945 SSVAL(*rparam
,0,NERR_Success
);
3946 SSVAL(*rparam
,2,0); /* converter word */
3949 endp
= *rdata
+ *rdata_len
;
3950 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3956 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3959 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3964 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3965 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3966 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3971 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3972 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3973 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3978 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3979 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3980 strlcpy(p2
,((vuser
!= NULL
)
3981 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3982 : UserName
),PTR_DIFF(endp
,p2
));
3983 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3990 const char *homedir
= "";
3991 if (vuser
!= NULL
) {
3992 homedir
= pdb_get_homedir(
3993 vuser
->server_info
->sam_account
);
3995 /* modelled after NTAS 3.51 reply */
3996 SSVAL(p
,usri11_priv
,
3997 (get_current_uid(conn
) == sec_initial_uid())?
3998 USER_PRIV_ADMIN
:USER_PRIV_USER
);
3999 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4000 SIVALS(p
,usri11_password_age
,-1); /* password age */
4001 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4002 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4003 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4007 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4008 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4009 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4013 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4014 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4015 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4016 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4017 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4018 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4019 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4023 SSVAL(p
,usri11_country_code
,0); /* country code */
4025 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4026 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4027 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4032 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4033 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4034 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4036 /* a simple way to get logon hours at all times. */
4038 SCVAL(p2
,21,0); /* fix zero termination */
4039 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4044 SSVAL(p
,usri11_code_page
,0); /* code page */
4047 if (uLevel
== 1 || uLevel
== 2) {
4048 memset(p
+22,' ',16); /* password */
4049 SIVALS(p
,38,-1); /* password age */
4051 (get_current_uid(conn
) == sec_initial_uid())?
4052 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4053 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4054 strlcpy(p2
, vuser
? pdb_get_homedir(
4055 vuser
->server_info
->sam_account
) : "",
4057 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4061 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4063 SSVAL(p
,52,0); /* flags */
4064 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4065 strlcpy(p2
, vuser
? pdb_get_logon_script(
4066 vuser
->server_info
->sam_account
) : "",
4068 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4073 SIVAL(p
,60,0); /* auth_flags */
4074 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
4075 strlcpy(p2
,((vuser
!= NULL
)
4076 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
4077 : UserName
),PTR_DIFF(endp
,p2
));
4078 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4082 SIVAL(p
,68,0); /* urs_comment */
4083 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
4084 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4085 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4089 SIVAL(p
,76,0); /* workstations */
4090 SIVAL(p
,80,0); /* last_logon */
4091 SIVAL(p
,84,0); /* last_logoff */
4092 SIVALS(p
,88,-1); /* acct_expires */
4093 SIVALS(p
,92,-1); /* max_storage */
4094 SSVAL(p
,96,168); /* units_per_week */
4095 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4098 SSVALS(p
,102,-1); /* bad_pw_count */
4099 SSVALS(p
,104,-1); /* num_logons */
4100 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4102 TALLOC_CTX
*ctx
= talloc_tos();
4103 int space_rem
= *rdata_len
- (p2
- *rdata
);
4106 if (space_rem
<= 0) {
4109 tmp
= talloc_strdup(ctx
, "\\\\%L");
4113 tmp
= talloc_sub_basic(ctx
,
4126 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4130 SSVAL(p
,110,49); /* country_code */
4131 SSVAL(p
,112,860); /* code page */
4135 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4137 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4142 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
4143 char *param
, int tpscnt
,
4144 char *data
, int tdscnt
,
4145 int mdrcnt
,int mprcnt
,
4146 char **rdata
,char **rparam
,
4147 int *rdata_len
,int *rparam_len
)
4149 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4150 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4151 char *str2
= skip_string(param
,tpscnt
,str1
);
4152 char *p
= skip_string(param
,tpscnt
,str2
);
4154 struct pack_desc desc
;
4156 /* With share level security vuid will always be zero.
4157 Don't depend on vuser being non-null !!. JRA */
4158 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
4160 if (!str1
|| !str2
|| !p
) {
4165 DEBUG(3,(" Username of UID %d is %s\n",
4166 (int)vuser
->server_info
->utok
.uid
,
4167 vuser
->server_info
->unix_name
));
4170 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4171 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4176 memset((char *)&desc
,'\0',sizeof(desc
));
4178 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4180 /* check it's a supported varient */
4181 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4184 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4188 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4195 desc
.buflen
= mdrcnt
;
4196 desc
.subformat
= NULL
;
4199 if (init_package(&desc
,1,0)) {
4200 PACKI(&desc
,"W",0); /* code */
4201 PACKS(&desc
,"B21",name
); /* eff. name */
4202 PACKS(&desc
,"B",""); /* pad */
4204 (get_current_uid(conn
) == sec_initial_uid())?
4205 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4206 PACKI(&desc
,"D",0); /* auth flags XXX */
4207 PACKI(&desc
,"W",0); /* num logons */
4208 PACKI(&desc
,"W",0); /* bad pw count */
4209 PACKI(&desc
,"D",0); /* last logon */
4210 PACKI(&desc
,"D",-1); /* last logoff */
4211 PACKI(&desc
,"D",-1); /* logoff time */
4212 PACKI(&desc
,"D",-1); /* kickoff time */
4213 PACKI(&desc
,"D",0); /* password age */
4214 PACKI(&desc
,"D",0); /* password can change */
4215 PACKI(&desc
,"D",-1); /* password must change */
4219 fstrcpy(mypath
,"\\\\");
4220 fstrcat(mypath
,get_local_machine_name());
4222 PACKS(&desc
,"z",mypath
); /* computer */
4225 PACKS(&desc
,"z",lp_workgroup());/* domain */
4226 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
4227 vuser
->server_info
->sam_account
) : ""); /* script path */
4228 PACKI(&desc
,"D",0x00000000); /* reserved */
4231 *rdata_len
= desc
.usedlen
;
4233 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4237 SSVALS(*rparam
,0,desc
.errcode
);
4239 SSVAL(*rparam
,4,desc
.neededlen
);
4241 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4246 /****************************************************************************
4247 api_WAccessGetUserPerms
4248 ****************************************************************************/
4250 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
4251 char *param
, int tpscnt
,
4252 char *data
, int tdscnt
,
4253 int mdrcnt
,int mprcnt
,
4254 char **rdata
,char **rparam
,
4255 int *rdata_len
,int *rparam_len
)
4257 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4258 char *str2
= skip_string(param
,tpscnt
,str1
);
4259 char *user
= skip_string(param
,tpscnt
,str2
);
4260 char *resource
= skip_string(param
,tpscnt
,user
);
4262 if (!str1
|| !str2
|| !user
|| !resource
) {
4266 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4269 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4271 /* check it's a supported varient */
4272 if (strcmp(str1
,"zzh") != 0) {
4275 if (strcmp(str2
,"") != 0) {
4280 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4284 SSVALS(*rparam
,0,0); /* errorcode */
4285 SSVAL(*rparam
,2,0); /* converter word */
4286 SSVAL(*rparam
,4,0x7f); /* permission flags */
4291 /****************************************************************************
4292 api_WPrintJobEnumerate
4293 ****************************************************************************/
4295 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
4296 char *param
, int tpscnt
,
4297 char *data
, int tdscnt
,
4298 int mdrcnt
,int mprcnt
,
4299 char **rdata
,char **rparam
,
4300 int *rdata_len
,int *rparam_len
)
4302 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4303 char *str2
= skip_string(param
,tpscnt
,str1
);
4304 char *p
= skip_string(param
,tpscnt
,str2
);
4308 struct pack_desc desc
;
4311 TALLOC_CTX
*mem_ctx
= talloc_tos();
4314 struct rpc_pipe_client
*cli
= NULL
;
4315 struct policy_handle handle
;
4316 struct spoolss_DevmodeContainer devmode_ctr
;
4317 union spoolss_JobInfo info
;
4319 if (!str1
|| !str2
|| !p
) {
4323 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4325 memset((char *)&desc
,'\0',sizeof(desc
));
4326 memset((char *)&status
,'\0',sizeof(status
));
4328 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4330 /* check it's a supported varient */
4331 if (strcmp(str1
,"WWrLh") != 0) {
4334 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4338 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4342 ZERO_STRUCT(handle
);
4344 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4345 rpc_spoolss_dispatch
, conn
->server_info
,
4347 if (!NT_STATUS_IS_OK(status
)) {
4348 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4349 nt_errstr(status
)));
4350 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4354 ZERO_STRUCT(devmode_ctr
);
4356 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4360 SEC_FLAG_MAXIMUM_ALLOWED
,
4363 if (!NT_STATUS_IS_OK(status
)) {
4364 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4367 if (!W_ERROR_IS_OK(werr
)) {
4368 desc
.errcode
= W_ERROR_V(werr
);
4372 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4378 if (!W_ERROR_IS_OK(werr
)) {
4379 desc
.errcode
= W_ERROR_V(werr
);
4384 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4389 desc
.buflen
= mdrcnt
;
4392 * Don't return data but need to get correct length
4393 * init_package will return wrong size if buflen=0
4395 desc
.buflen
= getlen(desc
.format
);
4396 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4399 if (init_package(&desc
,1,0)) {
4400 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4401 *rdata_len
= desc
.usedlen
;
4403 desc
.errcode
= NERR_JobNotFound
;
4407 if (cli
&& is_valid_policy_hnd(&handle
)) {
4408 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4412 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4416 SSVALS(*rparam
,0,desc
.errcode
);
4418 SSVAL(*rparam
,4,desc
.neededlen
);
4422 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4427 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
4428 char *param
, int tpscnt
,
4429 char *data
, int tdscnt
,
4430 int mdrcnt
,int mprcnt
,
4431 char **rdata
,char **rparam
,
4432 int *rdata_len
,int *rparam_len
)
4434 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4435 char *str2
= skip_string(param
,tpscnt
,str1
);
4436 char *p
= skip_string(param
,tpscnt
,str2
);
4440 struct pack_desc desc
;
4442 TALLOC_CTX
*mem_ctx
= talloc_tos();
4445 struct rpc_pipe_client
*cli
= NULL
;
4446 struct policy_handle handle
;
4447 struct spoolss_DevmodeContainer devmode_ctr
;
4449 union spoolss_JobInfo
*info
;
4451 if (!str1
|| !str2
|| !p
) {
4455 memset((char *)&desc
,'\0',sizeof(desc
));
4457 p
= skip_string(param
,tpscnt
,p
);
4461 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4463 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4465 /* check it's a supported variant */
4466 if (strcmp(str1
,"zWrLeh") != 0) {
4471 return False
; /* defined only for uLevel 0,1,2 */
4474 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4478 ZERO_STRUCT(handle
);
4480 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4481 rpc_spoolss_dispatch
, conn
->server_info
,
4483 if (!NT_STATUS_IS_OK(status
)) {
4484 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4485 nt_errstr(status
)));
4486 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4490 ZERO_STRUCT(devmode_ctr
);
4492 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4496 SEC_FLAG_MAXIMUM_ALLOWED
,
4499 if (!NT_STATUS_IS_OK(status
)) {
4500 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4503 if (!W_ERROR_IS_OK(werr
)) {
4504 desc
.errcode
= W_ERROR_V(werr
);
4508 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4516 if (!W_ERROR_IS_OK(werr
)) {
4517 desc
.errcode
= W_ERROR_V(werr
);
4522 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4528 desc
.buflen
= mdrcnt
;
4530 if (init_package(&desc
,count
,0)) {
4532 for (i
= 0; i
< count
; i
++) {
4533 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4534 if (desc
.errcode
== NERR_Success
) {
4540 if (cli
&& is_valid_policy_hnd(&handle
)) {
4541 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4544 *rdata_len
= desc
.usedlen
;
4547 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4551 SSVALS(*rparam
,0,desc
.errcode
);
4553 SSVAL(*rparam
,4,succnt
);
4554 SSVAL(*rparam
,6,count
);
4556 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4561 static int check_printdest_info(struct pack_desc
* desc
,
4562 int uLevel
, char* id
)
4564 desc
->subformat
= NULL
;
4567 desc
->format
= "B9";
4570 desc
->format
= "B9B21WWzW";
4576 desc
->format
= "zzzWWzzzWW";
4579 DEBUG(0,("check_printdest_info: invalid level %d\n",
4583 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4584 DEBUG(0,("check_printdest_info: invalid string %s\n",
4585 id
? id
: "<NULL>" ));
4591 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4592 struct pack_desc
* desc
)
4596 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4597 buf
[sizeof(buf
)-1] = 0;
4601 PACKS(desc
,"B9",buf
); /* szName */
4603 PACKS(desc
,"B21",""); /* szUserName */
4604 PACKI(desc
,"W",0); /* uJobId */
4605 PACKI(desc
,"W",0); /* fsStatus */
4606 PACKS(desc
,"z",""); /* pszStatus */
4607 PACKI(desc
,"W",0); /* time */
4611 if (uLevel
== 2 || uLevel
== 3) {
4612 PACKS(desc
,"z",buf
); /* pszPrinterName */
4614 PACKS(desc
,"z",""); /* pszUserName */
4615 PACKS(desc
,"z",""); /* pszLogAddr */
4616 PACKI(desc
,"W",0); /* uJobId */
4617 PACKI(desc
,"W",0); /* fsStatus */
4618 PACKS(desc
,"z",""); /* pszStatus */
4619 PACKS(desc
,"z",""); /* pszComment */
4620 PACKS(desc
,"z","NULL"); /* pszDrivers */
4621 PACKI(desc
,"W",0); /* time */
4622 PACKI(desc
,"W",0); /* pad1 */
4627 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
4628 char *param
, int tpscnt
,
4629 char *data
, int tdscnt
,
4630 int mdrcnt
,int mprcnt
,
4631 char **rdata
,char **rparam
,
4632 int *rdata_len
,int *rparam_len
)
4634 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4635 char *str2
= skip_string(param
,tpscnt
,str1
);
4636 char *p
= skip_string(param
,tpscnt
,str2
);
4637 char* PrinterName
= p
;
4639 struct pack_desc desc
;
4642 TALLOC_CTX
*mem_ctx
= talloc_tos();
4645 struct rpc_pipe_client
*cli
= NULL
;
4646 struct policy_handle handle
;
4647 struct spoolss_DevmodeContainer devmode_ctr
;
4648 union spoolss_PrinterInfo info
;
4650 if (!str1
|| !str2
|| !p
) {
4654 memset((char *)&desc
,'\0',sizeof(desc
));
4656 p
= skip_string(param
,tpscnt
,p
);
4660 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4662 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4664 /* check it's a supported varient */
4665 if (strcmp(str1
,"zWrLh") != 0) {
4668 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4672 ZERO_STRUCT(handle
);
4674 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4675 rpc_spoolss_dispatch
, conn
->server_info
,
4677 if (!NT_STATUS_IS_OK(status
)) {
4678 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4679 nt_errstr(status
)));
4680 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4684 ZERO_STRUCT(devmode_ctr
);
4686 status
= rpccli_spoolss_OpenPrinter(cli
, mem_ctx
,
4690 SEC_FLAG_MAXIMUM_ALLOWED
,
4693 if (!NT_STATUS_IS_OK(status
)) {
4695 desc
.errcode
= NERR_DestNotFound
;
4699 if (!W_ERROR_IS_OK(werr
)) {
4701 desc
.errcode
= NERR_DestNotFound
;
4706 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
4711 if (!W_ERROR_IS_OK(werr
)) {
4713 desc
.errcode
= NERR_DestNotFound
;
4719 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4724 desc
.buflen
= mdrcnt
;
4727 * Don't return data but need to get correct length
4728 * init_package will return wrong size if buflen=0
4730 desc
.buflen
= getlen(desc
.format
);
4731 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4733 if (init_package(&desc
,1,0)) {
4734 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
4738 if (cli
&& is_valid_policy_hnd(&handle
)) {
4739 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &handle
, NULL
);
4742 *rdata_len
= desc
.usedlen
;
4745 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4749 SSVALS(*rparam
,0,desc
.errcode
);
4751 SSVAL(*rparam
,4,desc
.neededlen
);
4753 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4759 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4760 char *param
, int tpscnt
,
4761 char *data
, int tdscnt
,
4762 int mdrcnt
,int mprcnt
,
4763 char **rdata
,char **rparam
,
4764 int *rdata_len
,int *rparam_len
)
4766 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4767 char *str2
= skip_string(param
,tpscnt
,str1
);
4768 char *p
= skip_string(param
,tpscnt
,str2
);
4772 struct pack_desc desc
;
4774 TALLOC_CTX
*mem_ctx
= talloc_tos();
4777 struct rpc_pipe_client
*cli
= NULL
;
4778 union spoolss_PrinterInfo
*info
;
4781 if (!str1
|| !str2
|| !p
) {
4785 memset((char *)&desc
,'\0',sizeof(desc
));
4787 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4789 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4791 /* check it's a supported varient */
4792 if (strcmp(str1
,"WrLeh") != 0) {
4795 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4801 status
= rpc_pipe_open_internal(mem_ctx
, &ndr_table_spoolss
.syntax_id
,
4802 rpc_spoolss_dispatch
, conn
->server_info
,
4804 if (!NT_STATUS_IS_OK(status
)) {
4805 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
4806 nt_errstr(status
)));
4807 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4811 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
4813 cli
->srv_name_slash
,
4818 if (!W_ERROR_IS_OK(werr
)) {
4819 desc
.errcode
= W_ERROR_V(werr
);
4821 desc
.errcode
= NERR_DestNotFound
;
4829 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4836 desc
.buflen
= mdrcnt
;
4837 if (init_package(&desc
,queuecnt
,0)) {
4840 for (i
= 0; i
< count
; i
++) {
4841 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
4843 if (desc
.errcode
== NERR_Success
) {
4849 *rdata_len
= desc
.usedlen
;
4852 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4856 SSVALS(*rparam
,0,desc
.errcode
);
4858 SSVAL(*rparam
,4,succnt
);
4859 SSVAL(*rparam
,6,queuecnt
);
4861 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4866 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4867 char *param
, int tpscnt
,
4868 char *data
, int tdscnt
,
4869 int mdrcnt
,int mprcnt
,
4870 char **rdata
,char **rparam
,
4871 int *rdata_len
,int *rparam_len
)
4873 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4874 char *str2
= skip_string(param
,tpscnt
,str1
);
4875 char *p
= skip_string(param
,tpscnt
,str2
);
4878 struct pack_desc desc
;
4880 if (!str1
|| !str2
|| !p
) {
4884 memset((char *)&desc
,'\0',sizeof(desc
));
4886 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4888 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4890 /* check it's a supported varient */
4891 if (strcmp(str1
,"WrLeh") != 0) {
4894 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4899 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4905 desc
.buflen
= mdrcnt
;
4906 if (init_package(&desc
,1,0)) {
4907 PACKS(&desc
,"B41","NULL");
4910 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4912 *rdata_len
= desc
.usedlen
;
4915 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4919 SSVALS(*rparam
,0,desc
.errcode
);
4921 SSVAL(*rparam
,4,succnt
);
4924 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4929 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4930 char *param
, int tpscnt
,
4931 char *data
, int tdscnt
,
4932 int mdrcnt
,int mprcnt
,
4933 char **rdata
,char **rparam
,
4934 int *rdata_len
,int *rparam_len
)
4936 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4937 char *str2
= skip_string(param
,tpscnt
,str1
);
4938 char *p
= skip_string(param
,tpscnt
,str2
);
4941 struct pack_desc desc
;
4943 if (!str1
|| !str2
|| !p
) {
4946 memset((char *)&desc
,'\0',sizeof(desc
));
4948 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4950 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4952 /* check it's a supported varient */
4953 if (strcmp(str1
,"WrLeh") != 0) {
4956 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4961 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4967 desc
.buflen
= mdrcnt
;
4969 if (init_package(&desc
,1,0)) {
4970 PACKS(&desc
,"B13","lpd");
4973 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4975 *rdata_len
= desc
.usedlen
;
4978 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4982 SSVALS(*rparam
,0,desc
.errcode
);
4984 SSVAL(*rparam
,4,succnt
);
4987 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4992 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4993 char *param
, int tpscnt
,
4994 char *data
, int tdscnt
,
4995 int mdrcnt
,int mprcnt
,
4996 char **rdata
,char **rparam
,
4997 int *rdata_len
,int *rparam_len
)
4999 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5000 char *str2
= skip_string(param
,tpscnt
,str1
);
5001 char *p
= skip_string(param
,tpscnt
,str2
);
5004 struct pack_desc desc
;
5006 if (!str1
|| !str2
|| !p
) {
5010 memset((char *)&desc
,'\0',sizeof(desc
));
5012 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5014 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5016 /* check it's a supported varient */
5017 if (strcmp(str1
,"WrLeh") != 0) {
5020 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5025 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5030 memset((char *)&desc
,'\0',sizeof(desc
));
5032 desc
.buflen
= mdrcnt
;
5034 if (init_package(&desc
,1,0)) {
5035 PACKS(&desc
,"B13","lp0");
5038 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5040 *rdata_len
= desc
.usedlen
;
5043 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5047 SSVALS(*rparam
,0,desc
.errcode
);
5049 SSVAL(*rparam
,4,succnt
);
5052 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5057 /****************************************************************************
5059 ****************************************************************************/
5061 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
5062 char *param
, int tpscnt
,
5063 char *data
, int tdscnt
,
5064 int mdrcnt
,int mprcnt
,
5065 char **rdata
,char **rparam
,
5066 int *rdata_len
,int *rparam_len
)
5069 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5070 char *str2
= skip_string(param
,tpscnt
,str1
);
5071 char *p
= skip_string(param
,tpscnt
,str2
);
5073 struct pack_desc desc
;
5074 struct sessionid
*session_list
;
5075 int i
, num_sessions
;
5077 if (!str1
|| !str2
|| !p
) {
5081 memset((char *)&desc
,'\0',sizeof(desc
));
5083 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5085 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5086 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5087 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5089 /* check it's a supported varient */
5090 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5093 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5097 num_sessions
= list_sessions(talloc_tos(), &session_list
);
5100 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5105 memset((char *)&desc
,'\0',sizeof(desc
));
5107 desc
.buflen
= mdrcnt
;
5109 if (!init_package(&desc
,num_sessions
,0)) {
5113 for(i
=0; i
<num_sessions
; i
++) {
5114 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
5115 PACKS(&desc
, "z", session_list
[i
].username
);
5116 PACKI(&desc
, "W", 1); /* num conns */
5117 PACKI(&desc
, "W", 0); /* num opens */
5118 PACKI(&desc
, "W", 1); /* num users */
5119 PACKI(&desc
, "D", 0); /* session time */
5120 PACKI(&desc
, "D", 0); /* idle time */
5121 PACKI(&desc
, "D", 0); /* flags */
5122 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5125 *rdata_len
= desc
.usedlen
;
5128 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5132 SSVALS(*rparam
,0,desc
.errcode
);
5133 SSVAL(*rparam
,2,0); /* converter */
5134 SSVAL(*rparam
,4,num_sessions
); /* count */
5136 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5142 /****************************************************************************
5143 The buffer was too small.
5144 ****************************************************************************/
5146 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
5147 int mdrcnt
, int mprcnt
,
5148 char **rdata
, char **rparam
,
5149 int *rdata_len
, int *rparam_len
)
5151 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5152 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5159 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5161 DEBUG(3,("Supplied buffer too small in API command\n"));
5166 /****************************************************************************
5167 The request is not supported.
5168 ****************************************************************************/
5170 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
5171 char *param
, int tpscnt
,
5172 char *data
, int tdscnt
,
5173 int mdrcnt
, int mprcnt
,
5174 char **rdata
, char **rparam
,
5175 int *rdata_len
, int *rparam_len
)
5178 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5185 SSVAL(*rparam
,0,NERR_notsupported
);
5186 SSVAL(*rparam
,2,0); /* converter word */
5188 DEBUG(3,("Unsupported API command\n"));
5193 static const struct {
5196 bool (*fn
)(connection_struct
*, uint16
,
5199 int,int,char **,char **,int *,int *);
5200 bool auth_user
; /* Deny anonymous access? */
5201 } api_commands
[] = {
5202 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
5203 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
5204 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
5205 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
5206 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
5207 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
5208 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
5209 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
5210 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
5211 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
5212 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
5213 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
5214 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
5215 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
5216 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
5217 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
5218 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
5219 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
5220 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
5221 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
5222 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
5223 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
5224 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
5225 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
5226 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
5227 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
5228 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
5229 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
5230 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
5231 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
5232 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
5233 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
5234 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
5235 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
5236 {NULL
, -1, api_Unsupported
}
5237 /* The following RAP calls are not implemented by Samba:
5239 RAP_WFileEnum2 - anon not OK
5244 /****************************************************************************
5245 Handle remote api calls.
5246 ****************************************************************************/
5248 void api_reply(connection_struct
*conn
, uint16 vuid
,
5249 struct smb_request
*req
,
5250 char *data
, char *params
,
5251 int tdscnt
, int tpscnt
,
5252 int mdrcnt
, int mprcnt
)
5254 struct smbd_server_connection
*sconn
= smbd_server_conn
;
5257 char *rparam
= NULL
;
5258 const char *name1
= NULL
;
5259 const char *name2
= NULL
;
5266 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5267 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5272 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5275 api_command
= SVAL(params
,0);
5276 /* Is there a string at position params+2 ? */
5277 if (skip_string(params
,tpscnt
,params
+2)) {
5282 name2
= skip_string(params
,tpscnt
,params
+2);
5287 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5291 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5293 for (i
=0;api_commands
[i
].name
;i
++) {
5294 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5295 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5300 /* Check whether this api call can be done anonymously */
5302 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5303 user_struct
*user
= get_valid_user_struct(sconn
, vuid
);
5305 if (!user
|| user
->server_info
->guest
) {
5306 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5311 rdata
= (char *)SMB_MALLOC(1024);
5313 memset(rdata
,'\0',1024);
5316 rparam
= (char *)SMB_MALLOC(1024);
5318 memset(rparam
,'\0',1024);
5321 if(!rdata
|| !rparam
) {
5322 DEBUG(0,("api_reply: malloc fail !\n"));
5325 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5329 reply
= api_commands
[i
].fn(conn
,
5331 params
,tpscnt
, /* params + length */
5332 data
,tdscnt
, /* data + length */
5334 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5337 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5338 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
5339 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5342 /* if we get False back then it's actually unsupported */
5344 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
5345 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5348 /* If api_Unsupported returns false we can't return anything. */
5350 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5351 rdata
, rdata_len
, False
);