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/smbd.h"
30 #include "smbd/globals.h"
31 #include "rpc_client/rpc_client.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
34 #include "rpc_client/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
37 #include "../librpc/gen_ndr/rap.h"
38 #include "../lib/util/binsearch.h"
39 #include "../libcli/auth/libcli_auth.h"
40 #include "rpc_client/init_lsa.h"
41 #include "../libcli/security/security.h"
43 #include "passdb/machine_sid.h"
45 #include "rpc_server/rpc_ncacn_np.h"
52 #define NERR_Success 0
53 #define NERR_badpass 86
54 #define NERR_notsupported 50
56 #define NERR_BASE (2100)
57 #define NERR_BufTooSmall (NERR_BASE+23)
58 #define NERR_JobNotFound (NERR_BASE+51)
59 #define NERR_DestNotFound (NERR_BASE+52)
61 #define ACCESS_READ 0x01
62 #define ACCESS_WRITE 0x02
63 #define ACCESS_CREATE 0x04
65 #define SHPWLEN 8 /* share password length */
67 /* Limit size of ipc replies */
69 static char *smb_realloc_limit(void *ptr
, size_t size
)
73 size
= MAX((size
),4*1024);
74 val
= (char *)SMB_REALLOC(ptr
,size
);
76 memset(val
,'\0',size
);
81 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
82 connection_struct
*conn
, uint64_t vuid
,
83 char *param
, int tpscnt
,
84 char *data
, int tdscnt
,
85 int mdrcnt
, int mprcnt
,
86 char **rdata
, char **rparam
,
87 int *rdata_len
, int *rparam_len
);
89 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
90 connection_struct
*conn
, uint64_t vuid
, char *param
, char *data
,
91 int mdrcnt
, int mprcnt
,
92 char **rdata
, char **rparam
,
93 int *rdata_len
, int *rparam_len
);
96 static int CopyExpanded(connection_struct
*conn
,
97 int snum
, char **dst
, char *src
, int *p_space_remaining
)
99 TALLOC_CTX
*ctx
= talloc_tos();
100 const struct loadparm_substitution
*lp_sub
=
101 loadparm_s3_global_substitution();
105 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
106 *p_space_remaining
<= 0) {
110 buf
= talloc_strdup(ctx
, src
);
112 *p_space_remaining
= 0;
115 buf
= talloc_string_sub(ctx
, buf
,"%S", lp_servicename(ctx
, lp_sub
, snum
));
117 *p_space_remaining
= 0;
120 buf
= talloc_sub_full(ctx
,
121 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
122 conn
->session_info
->unix_info
->unix_name
,
124 conn
->session_info
->unix_token
->gid
,
125 conn
->session_info
->unix_info
->sanitized_username
,
126 conn
->session_info
->info
->domain_name
,
129 *p_space_remaining
= 0;
132 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
137 (*p_space_remaining
) -= l
;
141 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
144 if (!src
|| !dst
|| !n
|| !(*dst
)) {
147 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
156 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
158 TALLOC_CTX
*ctx
= talloc_tos();
159 const struct loadparm_substitution
*lp_sub
=
160 loadparm_s3_global_substitution();
165 buf
= talloc_strdup(ctx
,s
);
169 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(ctx
, lp_sub
, snum
));
173 buf
= talloc_sub_full(ctx
,
174 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
175 conn
->session_info
->unix_info
->unix_name
,
177 conn
->session_info
->unix_token
->gid
,
178 conn
->session_info
->unix_info
->sanitized_username
,
179 conn
->session_info
->info
->domain_name
,
184 return strlen(buf
) + 1;
187 /*******************************************************************
188 Check a API string for validity when we only need to check the prefix.
189 ******************************************************************/
191 static bool prefix_ok(const char *str
, const char *prefix
)
193 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
197 const char *format
; /* formatstring for structure */
198 const char *subformat
; /* subformat for structure */
199 char *base
; /* baseaddress of buffer */
200 int buflen
; /* remaining size for fixed part; on init: length of base */
201 int subcount
; /* count of substructures */
202 char *structbuf
; /* pointer into buffer for remaining fixed part */
203 int stringlen
; /* remaining size for variable part */
204 char *stringbuf
; /* pointer into buffer for remaining variable part */
205 int neededlen
; /* total needed size */
206 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
207 const char *curpos
; /* current position; pointer into format or subformat */
211 static int get_counter(const char **p
)
217 if (!isdigit((int)**p
)) {
223 n
= 10 * n
+ (i
- '0');
231 static int getlen(const char *p
)
240 case 'W': /* word (2 byte) */
243 case 'K': /* status word? (2 byte) */
246 case 'N': /* count of substructures (word) at end */
249 case 'D': /* double word (4 byte) */
250 case 'z': /* offset to zero terminated string (4 byte) */
251 case 'l': /* offset to user data (4 byte) */
254 case 'b': /* offset to data (with counter) (4 byte) */
258 case 'B': /* byte (with optional counter) */
259 n
+= get_counter(&p
);
266 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
271 if (!p
->format
|| !p
->base
) {
275 i
= count
* getlen(p
->format
);
277 i
+= subcount
* getlen(p
->subformat
);
279 p
->structbuf
= p
->base
;
283 p
->curpos
= p
->format
;
289 * This is the old error code we used. Aparently
290 * WinNT/2k systems return ERRbuftoosmall (2123) and
291 * OS/2 needs this. I'm leaving this here so we can revert
294 p
->errcode
= ERRmoredata
;
296 p
->errcode
= ERRbuftoosmall
;
299 p
->errcode
= NERR_Success
;
303 p
->stringbuf
= p
->base
+ i
;
305 return (p
->errcode
== NERR_Success
);
308 static int package(struct pack_desc
*p
, ...)
311 int needed
=0, stringneeded
;
312 const char *str
=NULL
;
313 int is_string
=0, stringused
;
320 p
->curpos
= p
->format
;
322 p
->curpos
= p
->subformat
;
327 str
= va_arg(args
,char*);
328 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
337 switch( *p
->curpos
++ ) {
338 case 'W': /* word (2 byte) */
340 temp
= va_arg(args
,int);
341 if (p
->buflen
>= needed
) {
342 SSVAL(p
->structbuf
,0,temp
);
345 case 'K': /* status word? (2 byte) */
347 temp
= va_arg(args
,int);
348 if (p
->buflen
>= needed
) {
349 SSVAL(p
->structbuf
,0,temp
);
352 case 'N': /* count of substructures (word) at end */
354 p
->subcount
= va_arg(args
,int);
355 if (p
->buflen
>= needed
) {
356 SSVAL(p
->structbuf
,0,p
->subcount
);
359 case 'D': /* double word (4 byte) */
361 temp
= va_arg(args
,int);
362 if (p
->buflen
>= needed
) {
363 SIVAL(p
->structbuf
,0,temp
);
366 case 'B': /* byte (with optional counter) */
367 needed
= get_counter(&p
->curpos
);
369 char *s
= va_arg(args
,char*);
370 if (p
->buflen
>= needed
) {
371 strlcpy(p
->structbuf
,s
?s
:"",needed
);
375 case 'z': /* offset to zero terminated string (4 byte) */
376 str
= va_arg(args
,char*);
377 stringneeded
= (str
? strlen(str
)+1 : 0);
380 case 'l': /* offset to user data (4 byte) */
381 str
= va_arg(args
,char*);
382 stringneeded
= va_arg(args
,int);
385 case 'b': /* offset to data (with counter) (4 byte) */
386 str
= va_arg(args
,char*);
387 stringneeded
= get_counter(&p
->curpos
);
393 if (stringneeded
>= 0) {
395 if (p
->buflen
>= needed
) {
396 stringused
= stringneeded
;
397 if (stringused
> p
->stringlen
) {
398 stringused
= (is_string
? p
->stringlen
: 0);
399 if (p
->errcode
== NERR_Success
) {
400 p
->errcode
= ERRmoredata
;
404 SIVAL(p
->structbuf
,0,0);
406 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
407 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
409 p
->stringbuf
[stringused
-1] = '\0';
411 p
->stringbuf
+= stringused
;
412 p
->stringlen
-= stringused
;
413 p
->usedlen
+= stringused
;
416 p
->neededlen
+= stringneeded
;
419 p
->neededlen
+= needed
;
420 if (p
->buflen
>= needed
) {
421 p
->structbuf
+= needed
;
423 p
->usedlen
+= needed
;
425 if (p
->errcode
== NERR_Success
) {
426 p
->errcode
= ERRmoredata
;
433 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
434 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
436 #define PACK(desc,t,v) package(desc,v)
437 #define PACKl(desc,t,v,l) package(desc,v,l)
440 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
445 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
450 /****************************************************************************
452 ****************************************************************************/
454 static void PackDriverData(struct pack_desc
* desc
)
456 char drivdata
[4+4+32];
457 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
458 SIVAL(drivdata
,4,1000); /* lVersion */
459 memset(drivdata
+8,0,32); /* szDeviceName */
460 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
461 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
464 static int check_printq_info(struct pack_desc
* desc
,
465 unsigned int uLevel
, char *id1
, char *id2
)
467 desc
->subformat
= NULL
;
470 desc
->format
= "B13";
473 desc
->format
= "B13BWWWzzzzzWW";
476 desc
->format
= "B13BWWWzzzzzWN";
477 desc
->subformat
= "WB21BB16B10zWWzDDz";
480 desc
->format
= "zWWWWzzzzWWzzl";
483 desc
->format
= "zWWWWzzzzWNzzl";
484 desc
->subformat
= "WWzWWDDzz";
493 desc
->format
= "WzzzzzzzzN";
494 desc
->subformat
= "z";
497 DEBUG(0,("check_printq_info: invalid level %d\n",
501 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
502 DEBUG(0,("check_printq_info: invalid format %s\n",
503 id1
? id1
: "<NULL>" ));
506 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
507 DEBUG(0,("check_printq_info: invalid subformat %s\n",
508 id2
? id2
: "<NULL>" ));
515 #define RAP_JOB_STATUS_QUEUED 0
516 #define RAP_JOB_STATUS_PAUSED 1
517 #define RAP_JOB_STATUS_SPOOLING 2
518 #define RAP_JOB_STATUS_PRINTING 3
519 #define RAP_JOB_STATUS_PRINTED 4
521 #define RAP_QUEUE_STATUS_PAUSED 1
522 #define RAP_QUEUE_STATUS_ERROR 2
524 /* turn a print job status into a on the wire status
526 static int printj_spoolss_status(int v
)
528 if (v
== JOB_STATUS_QUEUED
)
529 return RAP_JOB_STATUS_QUEUED
;
530 if (v
& JOB_STATUS_PAUSED
)
531 return RAP_JOB_STATUS_PAUSED
;
532 if (v
& JOB_STATUS_SPOOLING
)
533 return RAP_JOB_STATUS_SPOOLING
;
534 if (v
& JOB_STATUS_PRINTING
)
535 return RAP_JOB_STATUS_PRINTING
;
539 /* turn a print queue status into a on the wire status
541 static int printq_spoolss_status(int v
)
543 if (v
== PRINTER_STATUS_OK
)
545 if (v
& PRINTER_STATUS_PAUSED
)
546 return RAP_QUEUE_STATUS_PAUSED
;
547 return RAP_QUEUE_STATUS_ERROR
;
550 static void fill_spoolss_printjob_info(int uLevel
,
551 struct pack_desc
*desc
,
552 struct spoolss_JobInfo2
*info2
,
555 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
557 /* the client expects localtime */
558 t
-= get_time_zone(t
);
560 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
562 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
563 PACKS(desc
,"B",""); /* pad */
564 PACKS(desc
,"B16",""); /* szNotifyName */
565 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
566 PACKS(desc
,"z",""); /* pszParms */
567 PACKI(desc
,"W",n
+1); /* uPosition */
568 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
569 PACKS(desc
,"z",""); /* pszStatus */
570 PACKI(desc
,"D", t
); /* ulSubmitted */
571 PACKI(desc
,"D", info2
->size
); /* ulSize */
572 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
574 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
575 PACKI(desc
,"W", info2
->priority
); /* uPriority */
576 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
577 PACKI(desc
,"W",n
+1); /* uPosition */
578 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
579 PACKI(desc
,"D",t
); /* ulSubmitted */
580 PACKI(desc
,"D", info2
->size
); /* ulSize */
581 PACKS(desc
,"z","Samba"); /* pszComment */
582 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
584 PACKS(desc
,"z",""); /* pszNotifyName */
585 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
586 PACKS(desc
,"z",""); /* pszParms */
587 PACKS(desc
,"z",""); /* pszStatus */
588 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
589 PACKS(desc
,"z","lpd"); /* pszQProcName */
590 PACKS(desc
,"z",""); /* pszQProcParms */
591 PACKS(desc
,"z","NULL"); /* pszDriverName */
592 PackDriverData(desc
); /* pDriverData */
593 PACKS(desc
,"z",""); /* pszPrinterName */
594 } else if (uLevel
== 4) { /* OS2 */
595 PACKS(desc
,"z",""); /* pszSpoolFileName */
596 PACKS(desc
,"z",""); /* pszPortName */
597 PACKS(desc
,"z",""); /* pszStatus */
598 PACKI(desc
,"D",0); /* ulPagesSpooled */
599 PACKI(desc
,"D",0); /* ulPagesSent */
600 PACKI(desc
,"D",0); /* ulPagesPrinted */
601 PACKI(desc
,"D",0); /* ulTimePrinted */
602 PACKI(desc
,"D",0); /* ulExtendJobStatus */
603 PACKI(desc
,"D",0); /* ulStartPage */
604 PACKI(desc
,"D",0); /* ulEndPage */
609 /********************************************************************
610 Respond to the DosPrintQInfo command with a level of 52
611 This is used to get printer driver information for Win9x clients
612 ********************************************************************/
613 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
614 struct pack_desc
* desc
, int count
,
615 const char *printer_name
)
619 trim_string(discard_const_p(char, driver
->driver_path
), "\\print$\\WIN40\\0\\", 0);
620 trim_string(discard_const_p(char, driver
->data_file
), "\\print$\\WIN40\\0\\", 0);
621 trim_string(discard_const_p(char, driver
->help_file
), "\\print$\\WIN40\\0\\", 0);
623 PACKI(desc
, "W", 0x0400); /* don't know */
624 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
625 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
626 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
627 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
629 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
630 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
631 PACKS(desc
,"z", location
); /* share to retrieve files */
633 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
634 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
635 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
637 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
638 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
639 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
640 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
641 DEBUG(3,("Driver Location: %s:\n",location
));
642 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
643 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
644 PACKI(desc
,"N",count
); /* number of files to copy */
646 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
648 trim_string(discard_const_p(char, driver
->dependent_files
[i
]), "\\print$\\WIN40\\0\\", 0);
649 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
650 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
655 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
658 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
660 desc
->errcode
=NERR_Success
;
664 static const char *strip_unc(const char *unc
)
672 if ((p
= strrchr(unc
, '\\')) != NULL
) {
679 static void fill_printq_info(int uLevel
,
680 struct pack_desc
* desc
,
682 union spoolss_JobInfo
*job_info
,
683 struct spoolss_DriverInfo3
*driver_info
,
684 struct spoolss_PrinterInfo2
*printer_info
)
690 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
695 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
698 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
702 if (uLevel
== 1 || uLevel
== 2) {
703 PACKS(desc
,"B",""); /* alignment */
704 PACKI(desc
,"W",5); /* priority */
705 PACKI(desc
,"W",0); /* start time */
706 PACKI(desc
,"W",0); /* until time */
707 PACKS(desc
,"z",""); /* pSepFile */
708 PACKS(desc
,"z","lpd"); /* pPrProc */
709 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
710 PACKS(desc
,"z",""); /* pParms */
711 if (printer_info
->printername
== NULL
) {
712 PACKS(desc
,"z","UNKNOWN PRINTER");
713 PACKI(desc
,"W",LPSTAT_ERROR
);
715 PACKS(desc
,"z", printer_info
->comment
);
716 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
718 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
721 if (uLevel
== 3 || uLevel
== 4) {
722 PACKI(desc
,"W",5); /* uPriority */
723 PACKI(desc
,"W",0); /* uStarttime */
724 PACKI(desc
,"W",0); /* uUntiltime */
725 PACKI(desc
,"W",5); /* pad1 */
726 PACKS(desc
,"z",""); /* pszSepFile */
727 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
728 PACKS(desc
,"z",NULL
); /* pszParms */
729 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
730 /* "don't ask" that it's done this way to fix corrupted
731 Win9X/ME printer comments. */
732 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
733 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
734 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
735 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
736 PackDriverData(desc
); /* pDriverData */
739 if (uLevel
== 2 || uLevel
== 4) {
741 for (i
= 0; i
< count
; i
++) {
742 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
747 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
750 /* This function returns the number of files for a given driver */
751 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
755 /* count the number of files */
756 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
762 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
763 connection_struct
*conn
, uint64_t vuid
,
764 char *param
, int tpscnt
,
765 char *data
, int tdscnt
,
766 int mdrcnt
,int mprcnt
,
767 char **rdata
,char **rparam
,
768 int *rdata_len
,int *rparam_len
)
770 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
771 char *str2
= skip_string(param
,tpscnt
,str1
);
772 char *p
= skip_string(param
,tpscnt
,str2
);
777 struct pack_desc desc
;
780 WERROR werr
= WERR_OK
;
781 TALLOC_CTX
*mem_ctx
= talloc_tos();
783 struct rpc_pipe_client
*cli
= NULL
;
784 struct dcerpc_binding_handle
*b
= NULL
;
785 struct policy_handle handle
;
786 struct spoolss_DevmodeContainer devmode_ctr
;
787 union spoolss_DriverInfo driver_info
;
788 union spoolss_JobInfo
*job_info
= NULL
;
789 union spoolss_PrinterInfo printer_info
;
791 if (!str1
|| !str2
|| !p
) {
794 memset((char *)&desc
,'\0',sizeof(desc
));
796 p
= skip_string(param
,tpscnt
,p
);
800 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
801 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
802 /* str3 may be null here and is checked in check_printq_info(). */
804 /* remove any trailing username */
805 if ((p
= strchr_m(QueueName
,'%')))
808 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
810 /* check it's a supported varient */
811 if (!prefix_ok(str1
,"zWrLh"))
813 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
815 * Patch from Scott Moomaw <scott@bridgewater.edu>
816 * to return the 'invalid info level' error if an
817 * unknown level was requested.
821 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
825 SSVALS(*rparam
,0,ERRunknownlevel
);
833 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
834 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
838 status
= rpc_pipe_open_interface(mem_ctx
,
841 conn
->sconn
->remote_address
,
842 conn
->sconn
->local_address
,
843 conn
->sconn
->msg_ctx
,
845 if (!NT_STATUS_IS_OK(status
)) {
846 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
848 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
851 b
= cli
->binding_handle
;
853 ZERO_STRUCT(devmode_ctr
);
855 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
862 if (!NT_STATUS_IS_OK(status
)) {
863 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
866 if (!W_ERROR_IS_OK(werr
)) {
867 desc
.errcode
= W_ERROR_V(werr
);
871 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
876 if (!W_ERROR_IS_OK(werr
)) {
877 desc
.errcode
= W_ERROR_V(werr
);
882 uint32_t server_major_version
;
883 uint32_t server_minor_version
;
885 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
893 &server_major_version
,
894 &server_minor_version
);
895 if (!W_ERROR_IS_OK(werr
)) {
896 desc
.errcode
= W_ERROR_V(werr
);
900 count
= get_printerdrivernumber(&driver_info
.info3
);
901 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
904 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
912 if (!W_ERROR_IS_OK(werr
)) {
913 desc
.errcode
= W_ERROR_V(werr
);
921 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
926 desc
.buflen
= mdrcnt
;
929 * Don't return data but need to get correct length
930 * init_package will return wrong size if buflen=0
932 desc
.buflen
= getlen(desc
.format
);
933 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
936 if (init_package(&desc
,1,count
)) {
937 desc
.subcount
= count
;
938 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
941 *rdata_len
= desc
.usedlen
;
944 * We must set the return code to ERRbuftoosmall
945 * in order to support lanman style printing with Win NT/2k
948 if (!mdrcnt
&& lp_disable_spoolss())
949 desc
.errcode
= ERRbuftoosmall
;
952 if (b
&& is_valid_policy_hnd(&handle
)) {
953 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
956 *rdata_len
= desc
.usedlen
;
958 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
963 SSVALS(*rparam
,0,desc
.errcode
);
965 SSVAL(*rparam
,4,desc
.neededlen
);
967 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
974 /****************************************************************************
975 View list of all print jobs on all queues.
976 ****************************************************************************/
978 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
979 connection_struct
*conn
, uint64_t vuid
,
980 char *param
, int tpscnt
,
981 char *data
, int tdscnt
,
982 int mdrcnt
, int mprcnt
,
983 char **rdata
, char** rparam
,
984 int *rdata_len
, int *rparam_len
)
986 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
987 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
988 char *p
= skip_string(param
,tpscnt
,output_format1
);
989 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
990 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
992 struct pack_desc desc
;
993 int *subcntarr
= NULL
;
994 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
996 WERROR werr
= WERR_OK
;
997 TALLOC_CTX
*mem_ctx
= talloc_tos();
999 struct rpc_pipe_client
*cli
= NULL
;
1000 struct dcerpc_binding_handle
*b
= NULL
;
1001 struct spoolss_DevmodeContainer devmode_ctr
;
1002 uint32_t num_printers
;
1003 union spoolss_PrinterInfo
*printer_info
;
1004 union spoolss_DriverInfo
*driver_info
;
1005 union spoolss_JobInfo
**job_info
;
1007 if (!param_format
|| !output_format1
|| !p
) {
1011 memset((char *)&desc
,'\0',sizeof(desc
));
1013 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1015 if (!prefix_ok(param_format
,"WrLeh")) {
1018 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1020 * Patch from Scott Moomaw <scott@bridgewater.edu>
1021 * to return the 'invalid info level' error if an
1022 * unknown level was requested.
1026 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1030 SSVALS(*rparam
,0,ERRunknownlevel
);
1036 status
= rpc_pipe_open_interface(mem_ctx
,
1039 conn
->sconn
->remote_address
,
1040 conn
->sconn
->local_address
,
1041 conn
->sconn
->msg_ctx
,
1043 if (!NT_STATUS_IS_OK(status
)) {
1044 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1045 nt_errstr(status
)));
1046 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1049 b
= cli
->binding_handle
;
1051 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1053 cli
->srv_name_slash
,
1058 if (!W_ERROR_IS_OK(werr
)) {
1059 desc
.errcode
= W_ERROR_V(werr
);
1063 queuecnt
= num_printers
;
1065 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1066 if (job_info
== NULL
) {
1070 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1071 if (driver_info
== NULL
) {
1075 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1076 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1081 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1087 desc
.buflen
= mdrcnt
;
1090 for (i
= 0; i
< num_printers
; i
++) {
1093 struct policy_handle handle
;
1094 const char *printername
;
1096 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1097 if (printername
== NULL
) {
1101 ZERO_STRUCT(handle
);
1102 ZERO_STRUCT(devmode_ctr
);
1104 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
1111 if (!NT_STATUS_IS_OK(status
)) {
1112 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1115 if (!W_ERROR_IS_OK(werr
)) {
1116 desc
.errcode
= W_ERROR_V(werr
);
1120 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1128 if (!W_ERROR_IS_OK(werr
)) {
1129 desc
.errcode
= W_ERROR_V(werr
);
1134 uint32_t server_major_version
;
1135 uint32_t server_minor_version
;
1137 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1145 &server_major_version
,
1146 &server_minor_version
);
1147 if (!W_ERROR_IS_OK(werr
)) {
1148 desc
.errcode
= W_ERROR_V(werr
);
1153 subcntarr
[i
] = num_jobs
;
1154 subcnt
+= subcntarr
[i
];
1156 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1159 if (init_package(&desc
,queuecnt
,subcnt
)) {
1160 for (i
= 0; i
< num_printers
; i
++) {
1161 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1162 if (desc
.errcode
== NERR_Success
) {
1169 SAFE_FREE(subcntarr
);
1170 *rdata_len
= desc
.usedlen
;
1172 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1176 SSVALS(*rparam
,0,desc
.errcode
);
1178 SSVAL(*rparam
,4,succnt
);
1179 SSVAL(*rparam
,6,queuecnt
);
1185 SAFE_FREE(subcntarr
);
1190 /****************************************************************************
1191 Get info level for a server list query.
1192 ****************************************************************************/
1194 static bool check_session_info(int uLevel
, char* id
)
1198 if (strcmp(id
,"B16") != 0) {
1203 if (strcmp(id
,"B16BBDz") != 0) {
1213 struct srv_info_struct
{
1221 /*******************************************************************
1222 Get server info lists from the files saved by nmbd. Return the
1224 ******************************************************************/
1226 static int get_session_info(uint32_t servertype
,
1227 struct srv_info_struct
**servers
,
1233 bool local_list_only
;
1235 char *slist_cache_path
= cache_path(talloc_tos(), SERVER_LIST
);
1236 if (slist_cache_path
== NULL
) {
1240 lines
= file_lines_load(slist_cache_path
, NULL
, 0, NULL
);
1242 DEBUG(4, ("Can't open %s - %s\n",
1243 slist_cache_path
, strerror(errno
)));
1244 TALLOC_FREE(slist_cache_path
);
1247 TALLOC_FREE(slist_cache_path
);
1249 /* request for everything is code for request all servers */
1250 if (servertype
== SV_TYPE_ALL
) {
1251 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1254 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1256 DEBUG(4,("Servertype search: %8x\n",servertype
));
1258 for (i
=0;lines
[i
];i
++) {
1260 struct srv_info_struct
*s
;
1261 const char *ptr
= lines
[i
];
1263 TALLOC_CTX
*frame
= NULL
;
1270 if (count
== alloced
) {
1272 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1274 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1278 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1280 s
= &(*servers
)[count
];
1282 frame
= talloc_stackframe();
1284 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1288 fstrcpy(s
->name
, p
);
1291 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1297 s
->comment
[0] = '\0';
1298 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1302 fstrcpy(s
->comment
, p
);
1303 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1305 s
->domain
[0] = '\0';
1306 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1307 /* this allows us to cope with an old nmbd */
1308 fstrcpy(s
->domain
,lp_workgroup());
1310 fstrcpy(s
->domain
, p
);
1314 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1315 DEBUG(4,("r:host file "));
1319 /* Filter the servers/domains we return based on what was asked for. */
1321 /* Check to see if we are being asked for a local list only. */
1322 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1323 DEBUG(4,("r: local list only"));
1327 /* doesn't match up: don't want it */
1328 if (!(servertype
& s
->type
)) {
1329 DEBUG(4,("r:serv type "));
1333 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1334 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1335 DEBUG(4,("s: dom mismatch "));
1339 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1343 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1344 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1347 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1348 s
->name
, s
->type
, s
->comment
, s
->domain
));
1349 s
->server_added
= True
;
1352 DEBUG(4,("%20s %8x %25s %15s\n",
1353 s
->name
, s
->type
, s
->comment
, s
->domain
));
1361 /*******************************************************************
1362 Fill in a server info structure.
1363 ******************************************************************/
1365 static int fill_srv_info(struct srv_info_struct
*service
,
1366 int uLevel
, char **buf
, int *buflen
,
1367 char **stringbuf
, int *stringspace
, char *baseaddr
)
1390 len
= strlen(service
->comment
)+1;
1394 *buflen
= struct_len
;
1396 return struct_len
+ len
;
1401 if (*buflen
< struct_len
) {
1408 p2
= p
+ struct_len
;
1409 l2
= *buflen
- struct_len
;
1417 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1421 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1422 SIVAL(p
,18,service
->type
);
1423 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1424 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1429 *buf
= p
+ struct_len
;
1430 *buflen
-= struct_len
;
1441 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1443 return strcasecmp_m(s1
->name
,s2
->name
);
1446 /****************************************************************************
1447 View list of servers available (or possibly domains). The info is
1448 extracted from lists saved by nmbd on the local host.
1449 ****************************************************************************/
1451 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1452 connection_struct
*conn
, uint64_t vuid
,
1453 char *param
, int tpscnt
,
1454 char *data
, int tdscnt
,
1455 int mdrcnt
, int mprcnt
, char **rdata
,
1456 char **rparam
, int *rdata_len
, int *rparam_len
)
1458 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1459 char *str2
= skip_string(param
,tpscnt
,str1
);
1460 char *p
= skip_string(param
,tpscnt
,str2
);
1461 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1462 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1463 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1465 int data_len
, fixed_len
, string_len
;
1466 int f_len
= 0, s_len
= 0;
1467 struct srv_info_struct
*servers
=NULL
;
1468 int counted
=0,total
=0;
1471 bool domain_request
;
1474 if (!str1
|| !str2
|| !p
) {
1478 /* If someone sets all the bits they don't really mean to set
1479 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1482 if (servertype
== SV_TYPE_ALL
) {
1483 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1486 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1487 any other bit (they may just set this bit on its own) they
1488 want all the locally seen servers. However this bit can be
1489 set on its own so set the requested servers to be
1490 ALL - DOMAIN_ENUM. */
1492 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1493 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1496 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1497 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1501 if (!prefix_ok(str1
,"WrLehD")) {
1504 if (!check_session_info(uLevel
,str2
)) {
1508 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1509 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1510 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1512 if (strcmp(str1
, "WrLehDz") == 0) {
1513 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1516 pull_ascii_fstring(domain
, p
);
1518 fstrcpy(domain
, lp_workgroup());
1521 DEBUG(4, ("domain [%s]\n", domain
));
1523 if (lp_browse_list()) {
1524 total
= get_session_info(servertype
,&servers
,domain
);
1527 data_len
= fixed_len
= string_len
= 0;
1530 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1533 char *lastname
=NULL
;
1535 for (i
=0;i
<total
;i
++) {
1536 struct srv_info_struct
*s
= &servers
[i
];
1538 if (lastname
&& strequal(lastname
,s
->name
)) {
1542 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1543 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1544 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1546 if (data_len
< buf_len
) {
1549 string_len
+= s_len
;
1556 *rdata_len
= fixed_len
+ string_len
;
1557 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1562 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1568 char *lastname
=NULL
;
1569 int count2
= counted
;
1571 for (i
= 0; i
< total
&& count2
;i
++) {
1572 struct srv_info_struct
*s
= &servers
[i
];
1574 if (lastname
&& strequal(lastname
,s
->name
)) {
1578 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1579 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1580 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1586 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1590 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1592 SSVAL(*rparam
,4,counted
);
1593 SSVAL(*rparam
,6,counted
+missed
);
1597 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1598 domain
,uLevel
,counted
,counted
+missed
));
1603 static int srv_name_match(const char *n1
, const char *n2
)
1606 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1608 * In Windows, FirstNameToReturn need not be an exact match:
1609 * the server will return a list of servers that exist on
1610 * the network greater than or equal to the FirstNameToReturn.
1612 int ret
= strcasecmp_m(n1
, n2
);
1621 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1622 connection_struct
*conn
, uint64_t vuid
,
1623 char *param
, int tpscnt
,
1624 char *data
, int tdscnt
,
1625 int mdrcnt
, int mprcnt
, char **rdata
,
1626 char **rparam
, int *rdata_len
, int *rparam_len
)
1628 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1629 char *str2
= skip_string(param
,tpscnt
,str1
);
1630 char *p
= skip_string(param
,tpscnt
,str2
);
1631 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1632 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1633 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1635 int data_len
, fixed_len
, string_len
;
1636 int f_len
= 0, s_len
= 0;
1637 struct srv_info_struct
*servers
=NULL
;
1638 int counted
=0,first
=0,total
=0;
1642 bool domain_request
;
1645 if (!str1
|| !str2
|| !p
) {
1649 /* If someone sets all the bits they don't really mean to set
1650 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1653 if (servertype
== SV_TYPE_ALL
) {
1654 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1657 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1658 any other bit (they may just set this bit on its own) they
1659 want all the locally seen servers. However this bit can be
1660 set on its own so set the requested servers to be
1661 ALL - DOMAIN_ENUM. */
1663 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1664 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1667 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1668 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1672 if (strcmp(str1
, "WrLehDzz") != 0) {
1675 if (!check_session_info(uLevel
,str2
)) {
1679 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1680 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1681 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1683 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1686 pull_ascii_fstring(domain
, p
);
1687 if (domain
[0] == '\0') {
1688 fstrcpy(domain
, lp_workgroup());
1690 p
= skip_string(param
,tpscnt
,p
);
1691 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1694 pull_ascii_fstring(first_name
, p
);
1696 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1697 domain
, first_name
));
1699 if (lp_browse_list()) {
1700 total
= get_session_info(servertype
,&servers
,domain
);
1703 data_len
= fixed_len
= string_len
= 0;
1706 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1708 if (first_name
[0] != '\0') {
1709 struct srv_info_struct
*first_server
= NULL
;
1711 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1712 srv_name_match
, first_server
);
1714 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1716 * The binary search may not find the exact match
1717 * so we need to search backward to find the first match
1719 * This implements the strange matching windows
1720 * implements. (see the comment in srv_name_match().
1724 ret
= strcasecmp_m(first_name
,
1725 servers
[first
-1].name
);
1732 /* we should return no entries */
1738 char *lastname
=NULL
;
1740 for (i
=first
;i
<total
;i
++) {
1741 struct srv_info_struct
*s
= &servers
[i
];
1743 if (lastname
&& strequal(lastname
,s
->name
)) {
1747 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1748 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1749 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1751 if (data_len
< buf_len
) {
1754 string_len
+= s_len
;
1761 *rdata_len
= fixed_len
+ string_len
;
1762 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1767 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1773 char *lastname
=NULL
;
1774 int count2
= counted
;
1776 for (i
= first
; i
< total
&& count2
;i
++) {
1777 struct srv_info_struct
*s
= &servers
[i
];
1779 if (lastname
&& strequal(lastname
,s
->name
)) {
1783 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1784 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1785 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1791 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1795 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1797 SSVAL(*rparam
,4,counted
);
1798 SSVAL(*rparam
,6,counted
+missed
);
1800 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1801 domain
,uLevel
,first
,first_name
,
1802 first
< total
? servers
[first
].name
: "",
1803 counted
,counted
+missed
));
1810 /****************************************************************************
1811 command 0x34 - suspected of being a "Lookup Names" stub api
1812 ****************************************************************************/
1814 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1815 connection_struct
*conn
, uint64_t vuid
,
1816 char *param
, int tpscnt
,
1817 char *data
, int tdscnt
,
1818 int mdrcnt
, int mprcnt
, char **rdata
,
1819 char **rparam
, int *rdata_len
, int *rparam_len
)
1821 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1822 char *str2
= skip_string(param
,tpscnt
,str1
);
1823 char *p
= skip_string(param
,tpscnt
,str2
);
1824 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1825 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1829 if (!str1
|| !str2
|| !p
) {
1833 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1834 str1
, str2
, p
, uLevel
, buf_len
));
1836 if (!prefix_ok(str1
,"zWrLeh")) {
1843 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1848 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1850 SSVAL(*rparam
,4,counted
);
1851 SSVAL(*rparam
,6,counted
+missed
);
1856 /****************************************************************************
1857 get info about a share
1858 ****************************************************************************/
1860 static bool check_share_info(int uLevel
, char* id
)
1864 if (strcmp(id
,"B13") != 0) {
1869 /* Level-2 descriptor is allowed (and ignored) */
1870 if (strcmp(id
,"B13BWz") != 0 &&
1871 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1876 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1881 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1891 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1892 char** buf
, int* buflen
,
1893 char** stringbuf
, int* stringspace
, char* baseaddr
)
1895 const struct loadparm_substitution
*lp_sub
=
1896 loadparm_s3_global_substitution();
1924 len
+= StrlenExpanded(conn
,snum
,lp_comment(talloc_tos(), lp_sub
, snum
));
1927 len
+= strlen(lp_path(talloc_tos(), lp_sub
, snum
)) + 1;
1930 *buflen
= struct_len
;
1935 return struct_len
+ len
;
1940 if ((*buflen
) < struct_len
) {
1948 p2
= p
+ struct_len
;
1949 l2
= (*buflen
) - struct_len
;
1956 push_ascii(p
,lp_servicename(talloc_tos(), lp_sub
, snum
),13, STR_TERMINATE
);
1962 type
= STYPE_DISKTREE
;
1963 if (lp_printable(snum
)) {
1964 type
= STYPE_PRINTQ
;
1966 if (strequal("IPC",lp_fstype(snum
))) {
1969 SSVAL(p
,14,type
); /* device type */
1970 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1971 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(talloc_tos(), lp_sub
, snum
),&l2
);
1975 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1976 SSVALS(p
,22,-1); /* max uses */
1977 SSVAL(p
,24,1); /* current uses */
1978 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1979 len
+= CopyAndAdvance(&p2
,lp_path(talloc_tos(),lp_sub
, snum
),&l2
);
1980 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1984 memset(p
+40,0,SHPWLEN
+2);
1995 (*buf
) = p
+ struct_len
;
1996 (*buflen
) -= struct_len
;
1998 (*stringspace
) = l2
;
2007 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
2008 connection_struct
*conn
,uint64_t vuid
,
2009 char *param
, int tpscnt
,
2010 char *data
, int tdscnt
,
2011 int mdrcnt
,int mprcnt
,
2012 char **rdata
,char **rparam
,
2013 int *rdata_len
,int *rparam_len
)
2015 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2016 char *str2
= skip_string(param
,tpscnt
,str1
);
2017 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2018 char *netname
= NULL
;
2019 char *p
= skip_string(param
,tpscnt
,netname
);
2020 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2023 if (!str1
|| !str2
|| !netname_in
|| !p
) {
2027 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2028 if (snum
< 0 || !netname
) {
2032 /* check it's a supported varient */
2033 if (!prefix_ok(str1
,"zWrLh")) {
2036 if (!check_share_info(uLevel
,str2
)) {
2040 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2045 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2046 if (*rdata_len
< 0) {
2051 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2055 SSVAL(*rparam
,0,NERR_Success
);
2056 SSVAL(*rparam
,2,0); /* converter word */
2057 SSVAL(*rparam
,4,*rdata_len
);
2062 /****************************************************************************
2063 View the list of available shares.
2065 This function is the server side of the NetShareEnum() RAP call.
2066 It fills the return buffer with share names and share comments.
2067 Note that the return buffer normally (in all known cases) allows only
2068 twelve byte strings for share names (plus one for a nul terminator).
2069 Share names longer than 12 bytes must be skipped.
2070 ****************************************************************************/
2072 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2073 connection_struct
*conn
, uint64_t vuid
,
2074 char *param
, int tpscnt
,
2075 char *data
, int tdscnt
,
2083 const struct loadparm_substitution
*lp_sub
=
2084 loadparm_s3_global_substitution();
2085 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2086 char *str2
= skip_string(param
,tpscnt
,str1
);
2087 char *p
= skip_string(param
,tpscnt
,str2
);
2088 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2089 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2092 int total
=0,counted
=0;
2093 bool missed
= False
;
2095 int data_len
, fixed_len
, string_len
;
2096 int f_len
= 0, s_len
= 0;
2098 if (!str1
|| !str2
|| !p
) {
2102 if (!prefix_ok(str1
,"WrLeh")) {
2105 if (!check_share_info(uLevel
,str2
)) {
2109 /* Ensure all the usershares are loaded. */
2111 delete_and_reload_printers();
2112 load_registry_shares();
2113 count
= load_usershare_shares(NULL
, connections_snum_used
);
2116 data_len
= fixed_len
= string_len
= 0;
2117 for (i
=0;i
<count
;i
++) {
2118 fstring servicename_dos
;
2119 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2122 push_ascii_fstring(servicename_dos
, lp_servicename(talloc_tos(), lp_sub
, i
));
2123 /* Maximum name length = 13. */
2124 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2126 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2127 if (data_len
< buf_len
) {
2130 string_len
+= s_len
;
2137 *rdata_len
= fixed_len
+ string_len
;
2138 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2143 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2148 for( i
= 0; i
< count
; i
++ ) {
2149 fstring servicename_dos
;
2150 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2154 push_ascii_fstring(servicename_dos
,
2155 lp_servicename(talloc_tos(), lp_sub
, i
));
2156 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2157 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2164 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2168 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2170 SSVAL(*rparam
,4,counted
);
2171 SSVAL(*rparam
,6,total
);
2173 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2174 counted
,total
,uLevel
,
2175 buf_len
,*rdata_len
,mdrcnt
));
2180 /****************************************************************************
2182 ****************************************************************************/
2184 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2185 connection_struct
*conn
,uint64_t vuid
,
2186 char *param
, int tpscnt
,
2187 char *data
, int tdscnt
,
2188 int mdrcnt
,int mprcnt
,
2189 char **rdata
,char **rparam
,
2190 int *rdata_len
,int *rparam_len
)
2192 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2193 char *str2
= skip_string(param
,tpscnt
,str1
);
2194 char *p
= skip_string(param
,tpscnt
,str2
);
2195 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2198 char *pathname
= NULL
;
2199 unsigned int offset
;
2201 size_t converted_size
;
2203 WERROR werr
= WERR_OK
;
2204 TALLOC_CTX
*mem_ctx
= talloc_tos();
2206 struct rpc_pipe_client
*cli
= NULL
;
2207 union srvsvc_NetShareInfo info
;
2208 struct srvsvc_NetShareInfo2 info2
;
2209 struct dcerpc_binding_handle
*b
;
2211 if (!str1
|| !str2
|| !p
) {
2215 /* check it's a supported varient */
2216 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2219 if (!check_share_info(uLevel
,str2
)) {
2226 /* Do we have a string ? */
2227 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2230 pull_ascii_fstring(sharename
,data
);
2236 /* only support disk share adds */
2237 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2241 offset
= IVAL(data
, 16);
2242 if (offset
>= mdrcnt
) {
2243 res
= ERRinvalidparam
;
2247 /* Do we have a string ? */
2248 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2251 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2253 offset
= IVAL(data
, 26);
2255 if (offset
>= mdrcnt
) {
2256 res
= ERRinvalidparam
;
2260 /* Do we have a string ? */
2261 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2265 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2266 offset
? (data
+offset
) : "", &converted_size
))
2268 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2276 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
2278 conn
->sconn
->remote_address
,
2279 conn
->sconn
->local_address
,
2280 conn
->sconn
->msg_ctx
,
2282 if (!NT_STATUS_IS_OK(status
)) {
2283 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2284 nt_errstr(status
)));
2285 res
= W_ERROR_V(ntstatus_to_werror(status
));
2289 b
= cli
->binding_handle
;
2291 info2
.name
= sharename
;
2292 info2
.type
= STYPE_DISKTREE
;
2293 info2
.comment
= comment
;
2294 info2
.permissions
= 0;
2295 info2
.max_users
= 0;
2296 info2
.current_users
= 0;
2297 info2
.path
= pathname
;
2298 info2
.password
= NULL
;
2300 info
.info2
= &info2
;
2302 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2303 cli
->srv_name_slash
,
2308 if (!NT_STATUS_IS_OK(status
)) {
2309 res
= W_ERROR_V(ntstatus_to_werror(status
));
2312 if (!W_ERROR_IS_OK(werr
)) {
2313 res
= W_ERROR_V(werr
);
2318 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2322 SSVAL(*rparam
,0,NERR_Success
);
2323 SSVAL(*rparam
,2,0); /* converter word */
2324 SSVAL(*rparam
,4,*rdata_len
);
2332 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2337 SSVAL(*rparam
,0,res
);
2342 /****************************************************************************
2343 view list of groups available
2344 ****************************************************************************/
2346 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2347 connection_struct
*conn
,uint64_t vuid
,
2348 char *param
, int tpscnt
,
2349 char *data
, int tdscnt
,
2350 int mdrcnt
,int mprcnt
,
2351 char **rdata
,char **rparam
,
2352 int *rdata_len
,int *rparam_len
)
2356 int resume_context
, cli_buf_size
;
2357 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2358 char *str2
= skip_string(param
,tpscnt
,str1
);
2359 char *p
= skip_string(param
,tpscnt
,str2
);
2361 uint32_t num_groups
;
2362 uint32_t resume_handle
;
2363 struct rpc_pipe_client
*samr_pipe
= NULL
;
2364 struct policy_handle samr_handle
, domain_handle
;
2365 NTSTATUS status
, result
;
2366 struct dcerpc_binding_handle
*b
;
2368 if (!str1
|| !str2
|| !p
) {
2372 if (strcmp(str1
,"WrLeh") != 0) {
2377 * W-> resume context (number of users to skip)
2378 * r -> return parameter pointer to receive buffer
2379 * L -> length of receive buffer
2380 * e -> return parameter number of entries
2381 * h -> return parameter total number of users
2384 if (strcmp("B21",str2
) != 0) {
2388 status
= rpc_pipe_open_interface(
2389 talloc_tos(), &ndr_table_samr
,
2390 conn
->session_info
, conn
->sconn
->remote_address
,
2391 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2392 if (!NT_STATUS_IS_OK(status
)) {
2393 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2394 nt_errstr(status
)));
2398 b
= samr_pipe
->binding_handle
;
2400 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2401 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2403 if (!NT_STATUS_IS_OK(status
)) {
2404 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2405 nt_errstr(status
)));
2408 if (!NT_STATUS_IS_OK(result
)) {
2409 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2410 nt_errstr(result
)));
2414 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2415 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2416 get_global_sam_sid(), &domain_handle
,
2418 if (!NT_STATUS_IS_OK(status
)) {
2419 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2420 nt_errstr(status
)));
2421 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2424 if (!NT_STATUS_IS_OK(result
)) {
2425 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2426 nt_errstr(result
)));
2427 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2431 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2432 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2433 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2434 "%d\n", resume_context
, cli_buf_size
));
2436 *rdata_len
= cli_buf_size
;
2437 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2444 errflags
= NERR_Success
;
2449 struct samr_SamArray
*sam_entries
;
2450 uint32_t num_entries
;
2452 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2458 if (!NT_STATUS_IS_OK(status
)) {
2459 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2460 "%s\n", nt_errstr(status
)));
2463 if (!NT_STATUS_IS_OK(result
)) {
2465 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2466 "%s\n", nt_errstr(result
)));
2470 if (num_entries
== 0) {
2471 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2472 "no entries -- done\n"));
2476 for(i
=0; i
<num_entries
; i
++) {
2479 name
= sam_entries
->entries
[i
].name
.string
;
2481 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2482 /* set overflow error */
2483 DEBUG(3,("overflow on entry %d group %s\n", i
,
2489 /* truncate the name at 21 chars. */
2491 strlcpy(p
, name
, 21);
2492 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2494 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2499 if (errflags
!= NERR_Success
) {
2503 TALLOC_FREE(sam_entries
);
2506 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2507 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2509 *rdata_len
= PTR_DIFF(p
,*rdata
);
2512 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2516 SSVAL(*rparam
, 0, errflags
);
2517 SSVAL(*rparam
, 2, 0); /* converter word */
2518 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2519 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2524 /*******************************************************************
2525 Get groups that a user is a member of.
2526 ******************************************************************/
2528 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2529 connection_struct
*conn
,uint64_t vuid
,
2530 char *param
, int tpscnt
,
2531 char *data
, int tdscnt
,
2532 int mdrcnt
,int mprcnt
,
2533 char **rdata
,char **rparam
,
2534 int *rdata_len
,int *rparam_len
)
2536 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2537 char *str2
= skip_string(param
,tpscnt
,str1
);
2538 char *UserName
= skip_string(param
,tpscnt
,str2
);
2539 char *p
= skip_string(param
,tpscnt
,UserName
);
2540 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2541 const char *level_string
;
2547 struct rpc_pipe_client
*samr_pipe
= NULL
;
2548 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2549 struct lsa_String name
;
2550 struct lsa_Strings names
;
2551 struct samr_Ids type
, rid
;
2552 struct samr_RidWithAttributeArray
*rids
;
2553 NTSTATUS status
, result
;
2554 struct dcerpc_binding_handle
*b
;
2556 if (!str1
|| !str2
|| !UserName
|| !p
) {
2561 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2566 /* check it's a supported varient */
2568 if ( strcmp(str1
,"zWrLeh") != 0 )
2573 level_string
= "B21";
2579 if (strcmp(level_string
,str2
) != 0)
2582 *rdata_len
= mdrcnt
+ 1024;
2583 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2588 SSVAL(*rparam
,0,NERR_Success
);
2589 SSVAL(*rparam
,2,0); /* converter word */
2592 endp
= *rdata
+ *rdata_len
;
2594 status
= rpc_pipe_open_interface(
2595 talloc_tos(), &ndr_table_samr
,
2596 conn
->session_info
, conn
->sconn
->remote_address
,
2597 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2598 if (!NT_STATUS_IS_OK(status
)) {
2599 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2600 nt_errstr(status
)));
2604 b
= samr_pipe
->binding_handle
;
2606 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2607 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2609 if (!NT_STATUS_IS_OK(status
)) {
2610 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2611 nt_errstr(status
)));
2614 if (!NT_STATUS_IS_OK(result
)) {
2615 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2616 nt_errstr(result
)));
2620 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2621 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2622 get_global_sam_sid(), &domain_handle
,
2624 if (!NT_STATUS_IS_OK(status
)) {
2625 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2626 nt_errstr(status
)));
2629 if (!NT_STATUS_IS_OK(result
)) {
2630 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2631 nt_errstr(result
)));
2635 name
.string
= UserName
;
2637 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2638 &domain_handle
, 1, &name
,
2641 if (!NT_STATUS_IS_OK(status
)) {
2642 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2643 nt_errstr(status
)));
2646 if (!NT_STATUS_IS_OK(result
)) {
2647 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2648 nt_errstr(result
)));
2651 if (rid
.count
!= 1) {
2652 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2655 if (type
.count
!= 1) {
2656 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2660 if (type
.ids
[0] != SID_NAME_USER
) {
2661 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2662 sid_type_lookup(type
.ids
[0])));
2666 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2668 SAMR_USER_ACCESS_GET_GROUPS
,
2669 rid
.ids
[0], &user_handle
,
2671 if (!NT_STATUS_IS_OK(status
)) {
2672 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2673 nt_errstr(status
)));
2676 if (!NT_STATUS_IS_OK(result
)) {
2677 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2678 nt_errstr(result
)));
2682 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2683 &user_handle
, &rids
,
2685 if (!NT_STATUS_IS_OK(status
)) {
2686 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2687 nt_errstr(status
)));
2690 if (!NT_STATUS_IS_OK(result
)) {
2691 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2692 nt_errstr(result
)));
2696 for (i
=0; i
<rids
->count
; i
++) {
2698 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2700 1, &rids
->rids
[i
].rid
,
2703 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2704 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2710 *rdata_len
= PTR_DIFF(p
,*rdata
);
2712 SSVAL(*rparam
,4,count
); /* is this right?? */
2713 SSVAL(*rparam
,6,count
); /* is this right?? */
2718 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2720 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2722 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2727 /*******************************************************************
2729 ******************************************************************/
2731 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2732 connection_struct
*conn
, uint64_t vuid
,
2733 char *param
, int tpscnt
,
2734 char *data
, int tdscnt
,
2735 int mdrcnt
,int mprcnt
,
2736 char **rdata
,char **rparam
,
2737 int *rdata_len
,int *rparam_len
)
2742 int i
, resume_context
, cli_buf_size
;
2743 uint32_t resume_handle
;
2745 struct rpc_pipe_client
*samr_pipe
= NULL
;
2746 struct policy_handle samr_handle
, domain_handle
;
2747 NTSTATUS status
, result
;
2749 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2750 char *str2
= skip_string(param
,tpscnt
,str1
);
2751 char *p
= skip_string(param
,tpscnt
,str2
);
2754 struct dcerpc_binding_handle
*b
;
2756 if (!str1
|| !str2
|| !p
) {
2760 if (strcmp(str1
,"WrLeh") != 0)
2763 * W-> resume context (number of users to skip)
2764 * r -> return parameter pointer to receive buffer
2765 * L -> length of receive buffer
2766 * e -> return parameter number of entries
2767 * h -> return parameter total number of users
2770 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2771 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2772 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2773 resume_context
, cli_buf_size
));
2776 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2781 /* check it's a supported varient */
2782 if (strcmp("B21",str2
) != 0)
2785 *rdata_len
= cli_buf_size
;
2786 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2792 endp
= *rdata
+ *rdata_len
;
2794 status
= rpc_pipe_open_interface(
2795 talloc_tos(), &ndr_table_samr
,
2796 conn
->session_info
, conn
->sconn
->remote_address
,
2797 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2798 if (!NT_STATUS_IS_OK(status
)) {
2799 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2800 nt_errstr(status
)));
2804 b
= samr_pipe
->binding_handle
;
2806 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2807 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2809 if (!NT_STATUS_IS_OK(status
)) {
2810 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2811 nt_errstr(status
)));
2814 if (!NT_STATUS_IS_OK(result
)) {
2815 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2816 nt_errstr(result
)));
2820 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2821 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2822 get_global_sam_sid(), &domain_handle
,
2824 if (!NT_STATUS_IS_OK(status
)) {
2825 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2826 nt_errstr(status
)));
2827 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2830 if (!NT_STATUS_IS_OK(result
)) {
2831 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2832 nt_errstr(result
)));
2833 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2837 errflags
=NERR_Success
;
2842 struct samr_SamArray
*sam_entries
;
2843 uint32_t num_entries
;
2845 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2852 if (!NT_STATUS_IS_OK(status
)) {
2853 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2854 "%s\n", nt_errstr(status
)));
2857 if (!NT_STATUS_IS_OK(result
)) {
2858 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2859 "%s\n", nt_errstr(result
)));
2863 if (num_entries
== 0) {
2864 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2865 "no entries -- done\n"));
2869 for (i
=0; i
<num_entries
; i
++) {
2872 name
= sam_entries
->entries
[i
].name
.string
;
2874 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2875 &&(strlen(name
)<=21)) {
2876 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2877 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2878 "username %s\n",count_sent
,p
));
2882 /* set overflow error */
2883 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2884 "username %s\n",count_sent
,name
));
2890 if (errflags
!= NERR_Success
) {
2894 TALLOC_FREE(sam_entries
);
2897 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2898 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2900 *rdata_len
= PTR_DIFF(p
,*rdata
);
2902 SSVAL(*rparam
,0,errflags
);
2903 SSVAL(*rparam
,2,0); /* converter word */
2904 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2905 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2910 /****************************************************************************
2911 Get the time of day info.
2912 ****************************************************************************/
2914 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2915 connection_struct
*conn
,uint64_t vuid
,
2916 char *param
, int tpscnt
,
2917 char *data
, int tdscnt
,
2918 int mdrcnt
,int mprcnt
,
2919 char **rdata
,char **rparam
,
2920 int *rdata_len
,int *rparam_len
)
2923 time_t unixdate
= time(NULL
);
2927 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2933 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2938 SSVAL(*rparam
,0,NERR_Success
);
2939 SSVAL(*rparam
,2,0); /* converter word */
2943 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2944 by NT in a "net time" operation,
2945 it seems to ignore the one below */
2947 /* the client expects to get localtime, not GMT, in this bit
2948 (I think, this needs testing) */
2949 t
= localtime(&unixdate
);
2954 SIVAL(p
,4,0); /* msecs ? */
2955 SCVAL(p
,8,t
->tm_hour
);
2956 SCVAL(p
,9,t
->tm_min
);
2957 SCVAL(p
,10,t
->tm_sec
);
2958 SCVAL(p
,11,0); /* hundredths of seconds */
2959 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2960 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2961 SCVAL(p
,16,t
->tm_mday
);
2962 SCVAL(p
,17,t
->tm_mon
+ 1);
2963 SSVAL(p
,18,1900+t
->tm_year
);
2964 SCVAL(p
,20,t
->tm_wday
);
2969 /****************************************************************************
2970 Set the user password (SamOEM version - gets plaintext).
2971 ****************************************************************************/
2973 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
2974 connection_struct
*conn
,uint64_t vuid
,
2975 char *param
, int tpscnt
,
2976 char *data
, int tdscnt
,
2977 int mdrcnt
,int mprcnt
,
2978 char **rdata
,char **rparam
,
2979 int *rdata_len
,int *rparam_len
)
2982 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2984 TALLOC_CTX
*mem_ctx
= talloc_tos();
2985 NTSTATUS status
, result
;
2986 struct rpc_pipe_client
*cli
= NULL
;
2987 struct lsa_AsciiString server
, account
;
2988 struct samr_CryptPassword password
;
2989 struct samr_Password hash
;
2990 int errcode
= NERR_badpass
;
2992 struct dcerpc_binding_handle
*b
;
2995 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3005 SSVAL(*rparam
,0,NERR_badpass
);
3008 * Check the parameter definition is correct.
3011 /* Do we have a string ? */
3012 if (skip_string(param
,tpscnt
,p
) == 0) {
3015 if(!strequal(p
, "zsT")) {
3016 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3019 p
= skip_string(param
, tpscnt
, p
);
3024 /* Do we have a string ? */
3025 if (skip_string(param
,tpscnt
,p
) == 0) {
3028 if(!strequal(p
, "B516B16")) {
3029 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3032 p
= skip_string(param
,tpscnt
,p
);
3036 /* Do we have a string ? */
3037 if (skip_string(param
,tpscnt
,p
) == 0) {
3040 p
+= pull_ascii_fstring(user
,p
);
3042 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3044 if (tdscnt
!= 532) {
3045 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3049 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3050 if (bufsize
!= 532) {
3051 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3055 memcpy(password
.data
, data
, 516);
3056 memcpy(hash
.hash
, data
+516, 16);
3058 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
3060 conn
->sconn
->remote_address
,
3061 conn
->sconn
->local_address
,
3062 conn
->sconn
->msg_ctx
,
3064 if (!NT_STATUS_IS_OK(status
)) {
3065 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3066 nt_errstr(status
)));
3067 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3071 b
= cli
->binding_handle
;
3073 init_lsa_AsciiString(&server
, lp_netbios_name());
3074 init_lsa_AsciiString(&account
, user
);
3076 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3082 if (!NT_STATUS_IS_OK(status
)) {
3083 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3086 if (!NT_STATUS_IS_OK(result
)) {
3087 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3091 errcode
= NERR_Success
;
3093 SSVAL(*rparam
,0,errcode
);
3094 SSVAL(*rparam
,2,0); /* converter word */
3099 /****************************************************************************
3102 ****************************************************************************/
3104 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3105 connection_struct
*conn
,uint64_t vuid
,
3106 char *param
, int tpscnt
,
3107 char *data
, int tdscnt
,
3108 int mdrcnt
,int mprcnt
,
3109 char **rdata
,char **rparam
,
3110 int *rdata_len
,int *rparam_len
)
3112 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3113 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3114 char *str2
= skip_string(param
,tpscnt
,str1
);
3115 char *p
= skip_string(param
,tpscnt
,str2
);
3119 WERROR werr
= WERR_OK
;
3121 TALLOC_CTX
*mem_ctx
= talloc_tos();
3123 struct rpc_pipe_client
*cli
= NULL
;
3124 struct dcerpc_binding_handle
*b
= NULL
;
3125 struct policy_handle handle
;
3126 struct spoolss_DevmodeContainer devmode_ctr
;
3127 enum spoolss_JobControl command
;
3129 if (!str1
|| !str2
|| !p
) {
3133 * We use 1 here not 2 as we're checking
3134 * the last byte we want to access is safe.
3136 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3139 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3142 /* check it's a supported varient */
3143 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3147 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3153 ZERO_STRUCT(handle
);
3155 status
= rpc_pipe_open_interface(mem_ctx
,
3158 conn
->sconn
->remote_address
,
3159 conn
->sconn
->local_address
,
3160 conn
->sconn
->msg_ctx
,
3162 if (!NT_STATUS_IS_OK(status
)) {
3163 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3164 nt_errstr(status
)));
3165 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3168 b
= cli
->binding_handle
;
3170 ZERO_STRUCT(devmode_ctr
);
3172 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3176 JOB_ACCESS_ADMINISTER
,
3179 if (!NT_STATUS_IS_OK(status
)) {
3180 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3183 if (!W_ERROR_IS_OK(werr
)) {
3184 errcode
= W_ERROR_V(werr
);
3188 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3189 * and NERR_DestNotFound if share did not exist */
3191 errcode
= NERR_Success
;
3194 case 81: /* delete */
3195 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3197 case 82: /* pause */
3198 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3200 case 83: /* resume */
3201 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3204 errcode
= NERR_notsupported
;
3208 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3211 NULL
, /* unique ptr ctr */
3214 if (!NT_STATUS_IS_OK(status
)) {
3215 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3218 if (!W_ERROR_IS_OK(werr
)) {
3219 errcode
= W_ERROR_V(werr
);
3224 if (b
&& is_valid_policy_hnd(&handle
)) {
3225 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3228 SSVAL(*rparam
,0,errcode
);
3229 SSVAL(*rparam
,2,0); /* converter word */
3234 /****************************************************************************
3235 Purge a print queue - or pause or resume it.
3236 ****************************************************************************/
3238 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3239 connection_struct
*conn
,uint64_t vuid
,
3240 char *param
, int tpscnt
,
3241 char *data
, int tdscnt
,
3242 int mdrcnt
,int mprcnt
,
3243 char **rdata
,char **rparam
,
3244 int *rdata_len
,int *rparam_len
)
3246 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3247 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3248 char *str2
= skip_string(param
,tpscnt
,str1
);
3249 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3250 int errcode
= NERR_notsupported
;
3251 WERROR werr
= WERR_OK
;
3254 TALLOC_CTX
*mem_ctx
= talloc_tos();
3255 struct rpc_pipe_client
*cli
= NULL
;
3256 struct dcerpc_binding_handle
*b
= NULL
;
3257 struct policy_handle handle
;
3258 struct spoolss_SetPrinterInfoCtr info_ctr
;
3259 struct spoolss_DevmodeContainer devmode_ctr
;
3260 struct sec_desc_buf secdesc_ctr
;
3261 enum spoolss_PrinterControl command
;
3263 if (!str1
|| !str2
|| !QueueName
) {
3267 /* check it's a supported varient */
3268 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3272 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3278 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3282 ZERO_STRUCT(handle
);
3284 status
= rpc_pipe_open_interface(mem_ctx
,
3287 conn
->sconn
->remote_address
,
3288 conn
->sconn
->local_address
,
3289 conn
->sconn
->msg_ctx
,
3291 if (!NT_STATUS_IS_OK(status
)) {
3292 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3293 nt_errstr(status
)));
3294 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3297 b
= cli
->binding_handle
;
3299 ZERO_STRUCT(devmode_ctr
);
3301 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3305 PRINTER_ACCESS_ADMINISTER
,
3308 if (!NT_STATUS_IS_OK(status
)) {
3309 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3312 if (!W_ERROR_IS_OK(werr
)) {
3313 errcode
= W_ERROR_V(werr
);
3318 case 74: /* Pause queue */
3319 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3321 case 75: /* Resume queue */
3322 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3324 case 103: /* Purge */
3325 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3328 werr
= WERR_NOT_SUPPORTED
;
3332 if (!W_ERROR_IS_OK(werr
)) {
3333 errcode
= W_ERROR_V(werr
);
3337 ZERO_STRUCT(info_ctr
);
3338 ZERO_STRUCT(secdesc_ctr
);
3340 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3347 if (!NT_STATUS_IS_OK(status
)) {
3348 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3351 if (!W_ERROR_IS_OK(werr
)) {
3352 errcode
= W_ERROR_V(werr
);
3356 errcode
= W_ERROR_V(werr
);
3360 if (b
&& is_valid_policy_hnd(&handle
)) {
3361 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3364 SSVAL(*rparam
,0,errcode
);
3365 SSVAL(*rparam
,2,0); /* converter word */
3370 /****************************************************************************
3371 set the property of a print job (undocumented?)
3372 ? function = 0xb -> set name of print job
3373 ? function = 0x6 -> move print job up/down
3374 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3375 or <WWsTP> <WB21BB16B10zWWzDDz>
3376 ****************************************************************************/
3378 static int check_printjob_info(struct pack_desc
* desc
,
3379 int uLevel
, char* id
)
3381 desc
->subformat
= NULL
;
3383 case 0: desc
->format
= "W"; break;
3384 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3385 case 2: desc
->format
= "WWzWWDDzz"; break;
3386 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3387 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3389 DEBUG(0,("check_printjob_info: invalid level %d\n",
3393 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3394 DEBUG(0,("check_printjob_info: invalid format %s\n",
3395 id
? id
: "<NULL>" ));
3401 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3402 connection_struct
*conn
, uint64_t vuid
,
3403 char *param
, int tpscnt
,
3404 char *data
, int tdscnt
,
3405 int mdrcnt
,int mprcnt
,
3406 char **rdata
,char **rparam
,
3407 int *rdata_len
,int *rparam_len
)
3409 struct pack_desc desc
;
3410 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3411 char *str2
= skip_string(param
,tpscnt
,str1
);
3412 char *p
= skip_string(param
,tpscnt
,str2
);
3415 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3416 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3419 TALLOC_CTX
*mem_ctx
= talloc_tos();
3422 struct rpc_pipe_client
*cli
= NULL
;
3423 struct dcerpc_binding_handle
*b
= NULL
;
3424 struct policy_handle handle
;
3425 struct spoolss_DevmodeContainer devmode_ctr
;
3426 struct spoolss_JobInfoContainer ctr
;
3427 union spoolss_JobInfo info
;
3428 struct spoolss_SetJobInfo1 info1
;
3430 if (!str1
|| !str2
|| !p
) {
3434 * We use 1 here not 2 as we're checking
3435 * the last byte we want to access is safe.
3437 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3440 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3443 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3450 /* check it's a supported varient */
3451 if ((strcmp(str1
,"WWsTP")) ||
3452 (!check_printjob_info(&desc
,uLevel
,str2
)))
3455 errcode
= NERR_notsupported
;
3459 /* change print job name, data gives the name */
3465 ZERO_STRUCT(handle
);
3467 status
= rpc_pipe_open_interface(mem_ctx
,
3470 conn
->sconn
->remote_address
,
3471 conn
->sconn
->local_address
,
3472 conn
->sconn
->msg_ctx
,
3474 if (!NT_STATUS_IS_OK(status
)) {
3475 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3476 nt_errstr(status
)));
3477 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3480 b
= cli
->binding_handle
;
3482 ZERO_STRUCT(devmode_ctr
);
3484 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3491 if (!NT_STATUS_IS_OK(status
)) {
3492 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3495 if (!W_ERROR_IS_OK(werr
)) {
3496 errcode
= W_ERROR_V(werr
);
3500 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3506 if (!W_ERROR_IS_OK(werr
)) {
3507 errcode
= W_ERROR_V(werr
);
3513 info1
.job_id
= info
.info1
.job_id
;
3514 info1
.printer_name
= info
.info1
.printer_name
;
3515 info1
.user_name
= info
.info1
.user_name
;
3516 info1
.document_name
= data
;
3517 info1
.data_type
= info
.info1
.data_type
;
3518 info1
.text_status
= info
.info1
.text_status
;
3519 info1
.status
= info
.info1
.status
;
3520 info1
.priority
= info
.info1
.priority
;
3521 info1
.position
= info
.info1
.position
;
3522 info1
.total_pages
= info
.info1
.total_pages
;
3523 info1
.pages_printed
= info
.info1
.pages_printed
;
3524 info1
.submitted
= info
.info1
.submitted
;
3527 ctr
.info
.info1
= &info1
;
3529 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3535 if (!NT_STATUS_IS_OK(status
)) {
3536 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3539 if (!W_ERROR_IS_OK(werr
)) {
3540 errcode
= W_ERROR_V(werr
);
3544 errcode
= NERR_Success
;
3547 if (b
&& is_valid_policy_hnd(&handle
)) {
3548 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3551 SSVALS(*rparam
,0,errcode
);
3552 SSVAL(*rparam
,2,0); /* converter word */
3558 /****************************************************************************
3559 Get info about the server.
3560 ****************************************************************************/
3562 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3563 connection_struct
*conn
,uint64_t vuid
,
3564 char *param
, int tpscnt
,
3565 char *data
, int tdscnt
,
3566 int mdrcnt
,int mprcnt
,
3567 char **rdata
,char **rparam
,
3568 int *rdata_len
,int *rparam_len
)
3570 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3571 char *str2
= skip_string(param
,tpscnt
,str1
);
3572 char *p
= skip_string(param
,tpscnt
,str2
);
3573 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3579 TALLOC_CTX
*mem_ctx
= talloc_tos();
3580 struct rpc_pipe_client
*cli
= NULL
;
3581 union srvsvc_NetSrvInfo info
;
3583 struct dcerpc_binding_handle
*b
;
3585 if (!str1
|| !str2
|| !p
) {
3589 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3591 /* check it's a supported varient */
3592 if (!prefix_ok(str1
,"WrLh")) {
3598 if (strcmp(str2
,"B16") != 0) {
3604 if (strcmp(str2
,"B16BBDz") != 0) {
3610 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3616 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3622 if (strcmp(str2
,"DN") != 0) {
3628 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3637 *rdata_len
= mdrcnt
;
3638 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3644 p2
= p
+ struct_len
;
3646 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
3648 conn
->sconn
->remote_address
,
3649 conn
->sconn
->local_address
,
3650 conn
->sconn
->msg_ctx
,
3652 if (!NT_STATUS_IS_OK(status
)) {
3653 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3654 nt_errstr(status
)));
3655 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3659 b
= cli
->binding_handle
;
3661 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3666 if (!NT_STATUS_IS_OK(status
)) {
3667 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3670 if (!W_ERROR_IS_OK(werr
)) {
3671 errcode
= W_ERROR_V(werr
);
3675 if (info
.info101
== NULL
) {
3676 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3682 status
= srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3683 STR_ASCII
|STR_UPPER
|STR_TERMINATE
, &len
);
3684 if (!NT_STATUS_IS_OK(status
)) {
3685 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3691 SCVAL(p
,0,info
.info101
->version_major
);
3692 SCVAL(p
,1,info
.info101
->version_minor
);
3693 SIVAL(p
,2,info
.info101
->server_type
);
3695 if (mdrcnt
== struct_len
) {
3698 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3699 if (mdrcnt
- struct_len
<= 0) {
3703 info
.info101
->comment
,
3704 MIN(mdrcnt
- struct_len
,
3705 MAX_SERVER_STRING_LENGTH
),
3707 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3715 return False
; /* not yet implemented */
3718 errcode
= NERR_Success
;
3722 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3725 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3729 SSVAL(*rparam
,0,errcode
);
3730 SSVAL(*rparam
,2,0); /* converter word */
3731 SSVAL(*rparam
,4,*rdata_len
);
3736 /****************************************************************************
3737 Get info about the server.
3738 ****************************************************************************/
3740 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3741 connection_struct
*conn
,uint64_t vuid
,
3742 char *param
, int tpscnt
,
3743 char *data
, int tdscnt
,
3744 int mdrcnt
,int mprcnt
,
3745 char **rdata
,char **rparam
,
3746 int *rdata_len
,int *rparam_len
)
3748 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3749 char *str2
= skip_string(param
,tpscnt
,str1
);
3750 char *p
= skip_string(param
,tpscnt
,str2
);
3753 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3755 if (!str1
|| !str2
|| !p
) {
3759 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3762 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3767 /* check it's a supported varient */
3768 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3772 *rdata_len
= mdrcnt
+ 1024;
3773 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3778 SSVAL(*rparam
,0,NERR_Success
);
3779 SSVAL(*rparam
,2,0); /* converter word */
3782 endp
= *rdata
+ *rdata_len
;
3784 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3789 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3790 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3791 if (!strupper_m(p2
)) {
3794 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3800 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3801 strlcpy(p2
,conn
->session_info
->unix_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3802 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3808 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3809 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3810 if (!strupper_m(p2
)) {
3813 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3819 SCVAL(p
,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g 4 in 4.1 */
3820 SCVAL(p
,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g .1 in 4.1 */
3823 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3824 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3825 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3831 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3832 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3833 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3839 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3841 SSVAL(*rparam
,4,*rdata_len
);
3846 /****************************************************************************
3847 get info about a user
3849 struct user_info_11 {
3850 char usri11_name[21]; 0-20
3852 char *usri11_comment; 22-25
3853 char *usri11_usr_comment; 26-29
3854 unsigned short usri11_priv; 30-31
3855 unsigned long usri11_auth_flags; 32-35
3856 long usri11_password_age; 36-39
3857 char *usri11_homedir; 40-43
3858 char *usri11_parms; 44-47
3859 long usri11_last_logon; 48-51
3860 long usri11_last_logoff; 52-55
3861 unsigned short usri11_bad_pw_count; 56-57
3862 unsigned short usri11_num_logons; 58-59
3863 char *usri11_logon_server; 60-63
3864 unsigned short usri11_country_code; 64-65
3865 char *usri11_workstations; 66-69
3866 unsigned long usri11_max_storage; 70-73
3867 unsigned short usri11_units_per_week; 74-75
3868 unsigned char *usri11_logon_hours; 76-79
3869 unsigned short usri11_code_page; 80-81
3874 usri11_name specifies the user name for which information is retrieved
3876 usri11_pad aligns the next data structure element to a word boundary
3878 usri11_comment is a null terminated ASCII comment
3880 usri11_user_comment is a null terminated ASCII comment about the user
3882 usri11_priv specifies the level of the privilege assigned to the user.
3883 The possible values are:
3885 Name Value Description
3886 USER_PRIV_GUEST 0 Guest privilege
3887 USER_PRIV_USER 1 User privilege
3888 USER_PRV_ADMIN 2 Administrator privilege
3890 usri11_auth_flags specifies the account operator privileges. The
3891 possible values are:
3893 Name Value Description
3894 AF_OP_PRINT 0 Print operator
3897 Leach, Naik [Page 28]
3901 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3904 AF_OP_COMM 1 Communications operator
3905 AF_OP_SERVER 2 Server operator
3906 AF_OP_ACCOUNTS 3 Accounts operator
3909 usri11_password_age specifies how many seconds have elapsed since the
3910 password was last changed.
3912 usri11_home_dir points to a null terminated ASCII string that contains
3913 the path name of the user's home directory.
3915 usri11_parms points to a null terminated ASCII string that is set
3916 aside for use by applications.
3918 usri11_last_logon specifies the time when the user last logged on.
3919 This value is stored as the number of seconds elapsed since
3920 00:00:00, January 1, 1970.
3922 usri11_last_logoff specifies the time when the user last logged off.
3923 This value is stored as the number of seconds elapsed since
3924 00:00:00, January 1, 1970. A value of 0 means the last logoff
3927 usri11_bad_pw_count specifies the number of incorrect passwords
3928 entered since the last successful logon.
3930 usri11_log1_num_logons specifies the number of times this user has
3931 logged on. A value of -1 means the number of logons is unknown.
3933 usri11_logon_server points to a null terminated ASCII string that
3934 contains the name of the server to which logon requests are sent.
3935 A null string indicates logon requests should be sent to the
3938 usri11_country_code specifies the country code for the user's language
3941 usri11_workstations points to a null terminated ASCII string that
3942 contains the names of workstations the user may log on from.
3943 There may be up to 8 workstations, with the names separated by
3944 commas. A null strings indicates there are no restrictions.
3946 usri11_max_storage specifies the maximum amount of disk space the user
3947 can occupy. A value of 0xffffffff indicates there are no
3950 usri11_units_per_week specifies the equal number of time units into
3951 which a week is divided. This value must be equal to 168.
3953 usri11_logon_hours points to a 21 byte (168 bits) string that
3954 specifies the time during which the user can log on. Each bit
3955 represents one unique hour in a week. The first bit (bit 0, word
3956 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3960 Leach, Naik [Page 29]
3964 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3967 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3968 are no restrictions.
3970 usri11_code_page specifies the code page for the user's language of
3973 All of the pointers in this data structure need to be treated
3974 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3975 to be ignored. The converter word returned in the parameters section
3976 needs to be subtracted from the lower 16 bits to calculate an offset
3977 into the return buffer where this ASCII string resides.
3979 There is no auxiliary data in the response.
3981 ****************************************************************************/
3983 #define usri11_name 0
3984 #define usri11_pad 21
3985 #define usri11_comment 22
3986 #define usri11_usr_comment 26
3987 #define usri11_full_name 30
3988 #define usri11_priv 34
3989 #define usri11_auth_flags 36
3990 #define usri11_password_age 40
3991 #define usri11_homedir 44
3992 #define usri11_parms 48
3993 #define usri11_last_logon 52
3994 #define usri11_last_logoff 56
3995 #define usri11_bad_pw_count 60
3996 #define usri11_num_logons 62
3997 #define usri11_logon_server 64
3998 #define usri11_country_code 68
3999 #define usri11_workstations 70
4000 #define usri11_max_storage 74
4001 #define usri11_units_per_week 78
4002 #define usri11_logon_hours 80
4003 #define usri11_code_page 84
4004 #define usri11_end 86
4006 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4007 connection_struct
*conn
, uint64_t vuid
,
4008 char *param
, int tpscnt
,
4009 char *data
, int tdscnt
,
4010 int mdrcnt
,int mprcnt
,
4011 char **rdata
,char **rparam
,
4012 int *rdata_len
,int *rparam_len
)
4014 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4015 char *str2
= skip_string(param
,tpscnt
,str1
);
4016 char *UserName
= skip_string(param
,tpscnt
,str2
);
4017 char *p
= skip_string(param
,tpscnt
,UserName
);
4018 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4021 const char *level_string
;
4023 TALLOC_CTX
*mem_ctx
= talloc_tos();
4024 NTSTATUS status
, result
;
4025 struct rpc_pipe_client
*cli
= NULL
;
4026 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4027 struct lsa_String domain_name
;
4028 struct dom_sid2
*domain_sid
;
4029 struct lsa_String names
;
4030 struct samr_Ids rids
;
4031 struct samr_Ids types
;
4032 int errcode
= W_ERROR_V(WERR_NERR_USERNOTFOUND
);
4034 union samr_UserInfo
*info
;
4035 struct dcerpc_binding_handle
*b
= NULL
;
4037 if (!str1
|| !str2
|| !UserName
|| !p
) {
4042 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4047 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4049 /* check it's a supported variant */
4050 if (strcmp(str1
,"zWrLh") != 0) {
4054 case 0: level_string
= "B21"; break;
4055 case 1: level_string
= "B21BB16DWzzWz"; break;
4056 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4057 case 10: level_string
= "B21Bzzz"; break;
4058 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4059 default: return False
;
4062 if (strcmp(level_string
,str2
) != 0) {
4066 *rdata_len
= mdrcnt
+ 1024;
4067 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4073 endp
= *rdata
+ *rdata_len
;
4074 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4079 ZERO_STRUCT(connect_handle
);
4080 ZERO_STRUCT(domain_handle
);
4081 ZERO_STRUCT(user_handle
);
4083 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
4085 conn
->sconn
->remote_address
,
4086 conn
->sconn
->local_address
,
4087 conn
->sconn
->msg_ctx
,
4089 if (!NT_STATUS_IS_OK(status
)) {
4090 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4091 nt_errstr(status
)));
4092 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4096 b
= cli
->binding_handle
;
4098 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4100 SAMR_ACCESS_CONNECT_TO_SERVER
|
4101 SAMR_ACCESS_ENUM_DOMAINS
|
4102 SAMR_ACCESS_LOOKUP_DOMAIN
,
4105 if (!NT_STATUS_IS_OK(status
)) {
4106 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4109 if (!NT_STATUS_IS_OK(result
)) {
4110 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4114 init_lsa_String(&domain_name
, get_global_sam_name());
4116 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4121 if (!NT_STATUS_IS_OK(status
)) {
4122 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4125 if (!NT_STATUS_IS_OK(result
)) {
4126 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4130 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4132 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4136 if (!NT_STATUS_IS_OK(status
)) {
4137 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4140 if (!NT_STATUS_IS_OK(result
)) {
4141 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4145 init_lsa_String(&names
, UserName
);
4147 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4154 if (!NT_STATUS_IS_OK(status
)) {
4155 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4158 if (!NT_STATUS_IS_OK(result
)) {
4159 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4163 if (rids
.count
!= 1) {
4164 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4167 if (rids
.count
!= types
.count
) {
4168 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4171 if (types
.ids
[0] != SID_NAME_USER
) {
4172 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4178 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4180 SAMR_USER_ACCESS_GET_LOCALE
|
4181 SAMR_USER_ACCESS_GET_LOGONINFO
|
4182 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4183 SAMR_USER_ACCESS_GET_GROUPS
|
4184 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4185 SEC_STD_READ_CONTROL
,
4189 if (!NT_STATUS_IS_OK(status
)) {
4190 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4193 if (!NT_STATUS_IS_OK(result
)) {
4194 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4198 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4203 if (!NT_STATUS_IS_OK(status
)) {
4204 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4207 if (!NT_STATUS_IS_OK(result
)) {
4208 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4213 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4216 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4221 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4222 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4223 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4228 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4229 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4230 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4235 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4236 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4237 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4238 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4245 const char *homedir
= info
->info21
.home_directory
.string
;
4246 /* modelled after NTAS 3.51 reply */
4247 SSVAL(p
,usri11_priv
,
4248 (get_current_uid(conn
) == sec_initial_uid())?
4249 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4250 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4251 SIVALS(p
,usri11_password_age
,-1); /* password age */
4252 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4253 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4254 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4258 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4259 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4260 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4264 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4265 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4266 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4267 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4268 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4269 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4270 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4274 SSVAL(p
,usri11_country_code
,0); /* country code */
4276 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4277 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4278 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4283 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4284 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4285 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4287 /* a simple way to get logon hours at all times. */
4289 SCVAL(p2
,21,0); /* fix zero termination */
4290 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4295 SSVAL(p
,usri11_code_page
,0); /* code page */
4298 if (uLevel
== 1 || uLevel
== 2) {
4299 memset(p
+22,' ',16); /* password */
4300 SIVALS(p
,38,-1); /* password age */
4302 (get_current_uid(conn
) == sec_initial_uid())?
4303 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4304 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4305 strlcpy(p2
, info
->info21
.home_directory
.string
,
4307 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4311 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4313 SSVAL(p
,52,0); /* flags */
4314 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4315 strlcpy(p2
, info
->info21
.logon_script
.string
,
4317 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4322 SIVAL(p
,58,0); /* auth_flags */
4323 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4324 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4325 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4329 SIVAL(p
,66,0); /* urs_comment */
4330 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4331 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4332 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4336 SIVAL(p
,74,0); /* workstations */
4337 SIVAL(p
,78,0); /* last_logon */
4338 SIVAL(p
,82,0); /* last_logoff */
4339 SIVALS(p
,86,-1); /* acct_expires */
4340 SIVALS(p
,90,-1); /* max_storage */
4341 SSVAL(p
,94,168); /* units_per_week */
4342 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4345 SSVALS(p
,100,-1); /* bad_pw_count */
4346 SSVALS(p
,102,-1); /* num_logons */
4347 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4349 TALLOC_CTX
*ctx
= talloc_tos();
4350 int space_rem
= *rdata_len
- (p2
- *rdata
);
4353 if (space_rem
<= 0) {
4356 tmp
= talloc_strdup(ctx
, "\\\\%L");
4360 tmp
= talloc_sub_basic(ctx
,
4373 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4377 SSVAL(p
,108,49); /* country_code */
4378 SSVAL(p
,110,860); /* code page */
4382 errcode
= NERR_Success
;
4385 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4387 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4388 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4390 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4391 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4393 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4394 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4397 SSVAL(*rparam
,0,errcode
);
4398 SSVAL(*rparam
,2,0); /* converter word */
4399 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4404 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4405 connection_struct
*conn
,uint64_t vuid
,
4406 char *param
, int tpscnt
,
4407 char *data
, int tdscnt
,
4408 int mdrcnt
,int mprcnt
,
4409 char **rdata
,char **rparam
,
4410 int *rdata_len
,int *rparam_len
)
4412 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4413 char *str2
= skip_string(param
,tpscnt
,str1
);
4414 char *p
= skip_string(param
,tpscnt
,str2
);
4416 struct pack_desc desc
;
4418 struct auth_session_info
*si
= NULL
;
4421 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
4424 if (!NT_STATUS_IS_OK(status
)) {
4428 if (!str1
|| !str2
|| !p
) {
4432 DBG_INFO("Username of UID %ju is %s\n",
4433 (uintmax_t)si
->unix_token
->uid
,
4434 si
->unix_info
->unix_name
);
4436 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4437 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4442 memset((char *)&desc
,'\0',sizeof(desc
));
4444 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4446 /* check it's a supported varient */
4447 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4450 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4454 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4461 desc
.buflen
= mdrcnt
;
4462 desc
.subformat
= NULL
;
4465 if (init_package(&desc
,1,0)) {
4466 PACKI(&desc
,"W",0); /* code */
4467 PACKS(&desc
,"B21",name
); /* eff. name */
4468 PACKS(&desc
,"B",""); /* pad */
4470 (get_current_uid(conn
) == sec_initial_uid())?
4471 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4472 PACKI(&desc
,"D",0); /* auth flags XXX */
4473 PACKI(&desc
,"W",0); /* num logons */
4474 PACKI(&desc
,"W",0); /* bad pw count */
4475 PACKI(&desc
,"D",0); /* last logon */
4476 PACKI(&desc
,"D",-1); /* last logoff */
4477 PACKI(&desc
,"D",-1); /* logoff time */
4478 PACKI(&desc
,"D",-1); /* kickoff time */
4479 PACKI(&desc
,"D",0); /* password age */
4480 PACKI(&desc
,"D",0); /* password can change */
4481 PACKI(&desc
,"D",-1); /* password must change */
4485 fstrcpy(mypath
,"\\\\");
4486 fstrcat(mypath
,get_local_machine_name());
4487 if (!strupper_m(mypath
)) {
4490 PACKS(&desc
,"z",mypath
); /* computer */
4493 PACKS(&desc
,"z",lp_workgroup());/* domain */
4494 PACKS(&desc
,"z", si
->info
->logon_script
); /* script path */
4495 PACKI(&desc
,"D",0x00000000); /* reserved */
4498 *rdata_len
= desc
.usedlen
;
4500 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4504 SSVALS(*rparam
,0,desc
.errcode
);
4506 SSVAL(*rparam
,4,desc
.neededlen
);
4508 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4513 /****************************************************************************
4514 api_WAccessGetUserPerms
4515 ****************************************************************************/
4517 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4518 connection_struct
*conn
,uint64_t vuid
,
4519 char *param
, int tpscnt
,
4520 char *data
, int tdscnt
,
4521 int mdrcnt
,int mprcnt
,
4522 char **rdata
,char **rparam
,
4523 int *rdata_len
,int *rparam_len
)
4525 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4526 char *str2
= skip_string(param
,tpscnt
,str1
);
4527 char *user
= skip_string(param
,tpscnt
,str2
);
4528 char *resource
= skip_string(param
,tpscnt
,user
);
4530 if (!str1
|| !str2
|| !user
|| !resource
) {
4534 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4537 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4539 /* check it's a supported varient */
4540 if (strcmp(str1
,"zzh") != 0) {
4543 if (strcmp(str2
,"") != 0) {
4548 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4552 SSVALS(*rparam
,0,0); /* errorcode */
4553 SSVAL(*rparam
,2,0); /* converter word */
4554 SSVAL(*rparam
,4,0x7f); /* permission flags */
4559 /****************************************************************************
4560 api_WPrintJobEnumerate
4561 ****************************************************************************/
4563 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4564 connection_struct
*conn
, uint64_t vuid
,
4565 char *param
, int tpscnt
,
4566 char *data
, int tdscnt
,
4567 int mdrcnt
,int mprcnt
,
4568 char **rdata
,char **rparam
,
4569 int *rdata_len
,int *rparam_len
)
4571 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4572 char *str2
= skip_string(param
,tpscnt
,str1
);
4573 char *p
= skip_string(param
,tpscnt
,str2
);
4577 struct pack_desc desc
;
4580 TALLOC_CTX
*mem_ctx
= talloc_tos();
4583 struct rpc_pipe_client
*cli
= NULL
;
4584 struct dcerpc_binding_handle
*b
= NULL
;
4585 struct policy_handle handle
;
4586 struct spoolss_DevmodeContainer devmode_ctr
;
4587 union spoolss_JobInfo info
;
4589 if (!str1
|| !str2
|| !p
) {
4593 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4595 memset((char *)&desc
,'\0',sizeof(desc
));
4596 memset((char *)&status
,'\0',sizeof(status
));
4598 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4600 /* check it's a supported varient */
4601 if (strcmp(str1
,"WWrLh") != 0) {
4604 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4608 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4612 ZERO_STRUCT(handle
);
4614 status
= rpc_pipe_open_interface(mem_ctx
,
4617 conn
->sconn
->remote_address
,
4618 conn
->sconn
->local_address
,
4619 conn
->sconn
->msg_ctx
,
4621 if (!NT_STATUS_IS_OK(status
)) {
4622 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4623 nt_errstr(status
)));
4624 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4627 b
= cli
->binding_handle
;
4629 ZERO_STRUCT(devmode_ctr
);
4631 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4638 if (!NT_STATUS_IS_OK(status
)) {
4639 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4642 if (!W_ERROR_IS_OK(werr
)) {
4643 desc
.errcode
= W_ERROR_V(werr
);
4647 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4653 if (!W_ERROR_IS_OK(werr
)) {
4654 desc
.errcode
= W_ERROR_V(werr
);
4659 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4664 desc
.buflen
= mdrcnt
;
4667 * Don't return data but need to get correct length
4668 * init_package will return wrong size if buflen=0
4670 desc
.buflen
= getlen(desc
.format
);
4671 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4674 if (init_package(&desc
,1,0)) {
4675 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4676 *rdata_len
= desc
.usedlen
;
4678 desc
.errcode
= NERR_JobNotFound
;
4682 if (b
&& is_valid_policy_hnd(&handle
)) {
4683 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4687 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4691 SSVALS(*rparam
,0,desc
.errcode
);
4693 SSVAL(*rparam
,4,desc
.neededlen
);
4697 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4702 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4703 connection_struct
*conn
, uint64_t vuid
,
4704 char *param
, int tpscnt
,
4705 char *data
, int tdscnt
,
4706 int mdrcnt
,int mprcnt
,
4707 char **rdata
,char **rparam
,
4708 int *rdata_len
,int *rparam_len
)
4710 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4711 char *str2
= skip_string(param
,tpscnt
,str1
);
4712 char *p
= skip_string(param
,tpscnt
,str2
);
4716 struct pack_desc desc
;
4718 TALLOC_CTX
*mem_ctx
= talloc_tos();
4721 struct rpc_pipe_client
*cli
= NULL
;
4722 struct dcerpc_binding_handle
*b
= NULL
;
4723 struct policy_handle handle
;
4724 struct spoolss_DevmodeContainer devmode_ctr
;
4726 union spoolss_JobInfo
*info
;
4728 if (!str1
|| !str2
|| !p
) {
4732 memset((char *)&desc
,'\0',sizeof(desc
));
4734 p
= skip_string(param
,tpscnt
,p
);
4738 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4740 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4742 /* check it's a supported variant */
4743 if (strcmp(str1
,"zWrLeh") != 0) {
4748 return False
; /* defined only for uLevel 0,1,2 */
4751 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4755 ZERO_STRUCT(handle
);
4757 status
= rpc_pipe_open_interface(mem_ctx
,
4760 conn
->sconn
->remote_address
,
4761 conn
->sconn
->local_address
,
4762 conn
->sconn
->msg_ctx
,
4764 if (!NT_STATUS_IS_OK(status
)) {
4765 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4766 nt_errstr(status
)));
4767 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4770 b
= cli
->binding_handle
;
4772 ZERO_STRUCT(devmode_ctr
);
4774 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4781 if (!NT_STATUS_IS_OK(status
)) {
4782 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4785 if (!W_ERROR_IS_OK(werr
)) {
4786 desc
.errcode
= W_ERROR_V(werr
);
4790 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4798 if (!W_ERROR_IS_OK(werr
)) {
4799 desc
.errcode
= W_ERROR_V(werr
);
4804 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4810 desc
.buflen
= mdrcnt
;
4812 if (init_package(&desc
,count
,0)) {
4814 for (i
= 0; i
< count
; i
++) {
4815 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4816 if (desc
.errcode
== NERR_Success
) {
4822 if (b
&& is_valid_policy_hnd(&handle
)) {
4823 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4826 *rdata_len
= desc
.usedlen
;
4829 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4833 SSVALS(*rparam
,0,desc
.errcode
);
4835 SSVAL(*rparam
,4,succnt
);
4836 SSVAL(*rparam
,6,count
);
4838 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4843 static int check_printdest_info(struct pack_desc
* desc
,
4844 int uLevel
, char* id
)
4846 desc
->subformat
= NULL
;
4849 desc
->format
= "B9";
4852 desc
->format
= "B9B21WWzW";
4858 desc
->format
= "zzzWWzzzWW";
4861 DEBUG(0,("check_printdest_info: invalid level %d\n",
4865 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4866 DEBUG(0,("check_printdest_info: invalid string %s\n",
4867 id
? id
: "<NULL>" ));
4873 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4874 struct pack_desc
* desc
)
4878 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4879 buf
[sizeof(buf
)-1] = 0;
4880 (void)strupper_m(buf
);
4883 PACKS(desc
,"B9",buf
); /* szName */
4885 PACKS(desc
,"B21",""); /* szUserName */
4886 PACKI(desc
,"W",0); /* uJobId */
4887 PACKI(desc
,"W",0); /* fsStatus */
4888 PACKS(desc
,"z",""); /* pszStatus */
4889 PACKI(desc
,"W",0); /* time */
4893 if (uLevel
== 2 || uLevel
== 3) {
4894 PACKS(desc
,"z",buf
); /* pszPrinterName */
4896 PACKS(desc
,"z",""); /* pszUserName */
4897 PACKS(desc
,"z",""); /* pszLogAddr */
4898 PACKI(desc
,"W",0); /* uJobId */
4899 PACKI(desc
,"W",0); /* fsStatus */
4900 PACKS(desc
,"z",""); /* pszStatus */
4901 PACKS(desc
,"z",""); /* pszComment */
4902 PACKS(desc
,"z","NULL"); /* pszDrivers */
4903 PACKI(desc
,"W",0); /* time */
4904 PACKI(desc
,"W",0); /* pad1 */
4909 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4910 connection_struct
*conn
, uint64_t vuid
,
4911 char *param
, int tpscnt
,
4912 char *data
, int tdscnt
,
4913 int mdrcnt
,int mprcnt
,
4914 char **rdata
,char **rparam
,
4915 int *rdata_len
,int *rparam_len
)
4917 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4918 char *str2
= skip_string(param
,tpscnt
,str1
);
4919 char *p
= skip_string(param
,tpscnt
,str2
);
4920 char* PrinterName
= p
;
4922 struct pack_desc desc
;
4925 TALLOC_CTX
*mem_ctx
= talloc_tos();
4928 struct rpc_pipe_client
*cli
= NULL
;
4929 struct dcerpc_binding_handle
*b
= NULL
;
4930 struct policy_handle handle
;
4931 struct spoolss_DevmodeContainer devmode_ctr
;
4932 union spoolss_PrinterInfo info
;
4934 if (!str1
|| !str2
|| !p
) {
4938 memset((char *)&desc
,'\0',sizeof(desc
));
4940 p
= skip_string(param
,tpscnt
,p
);
4944 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4946 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4948 /* check it's a supported varient */
4949 if (strcmp(str1
,"zWrLh") != 0) {
4952 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4956 ZERO_STRUCT(handle
);
4958 status
= rpc_pipe_open_interface(mem_ctx
,
4961 conn
->sconn
->remote_address
,
4962 conn
->sconn
->local_address
,
4963 conn
->sconn
->msg_ctx
,
4965 if (!NT_STATUS_IS_OK(status
)) {
4966 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4967 nt_errstr(status
)));
4968 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4971 b
= cli
->binding_handle
;
4973 ZERO_STRUCT(devmode_ctr
);
4975 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4982 if (!NT_STATUS_IS_OK(status
)) {
4984 desc
.errcode
= NERR_DestNotFound
;
4988 if (!W_ERROR_IS_OK(werr
)) {
4990 desc
.errcode
= NERR_DestNotFound
;
4995 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5000 if (!W_ERROR_IS_OK(werr
)) {
5002 desc
.errcode
= NERR_DestNotFound
;
5008 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5013 desc
.buflen
= mdrcnt
;
5016 * Don't return data but need to get correct length
5017 * init_package will return wrong size if buflen=0
5019 desc
.buflen
= getlen(desc
.format
);
5020 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5022 if (init_package(&desc
,1,0)) {
5023 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5027 if (b
&& is_valid_policy_hnd(&handle
)) {
5028 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5031 *rdata_len
= desc
.usedlen
;
5034 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5038 SSVALS(*rparam
,0,desc
.errcode
);
5040 SSVAL(*rparam
,4,desc
.neededlen
);
5042 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5048 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5049 connection_struct
*conn
, uint64_t vuid
,
5050 char *param
, int tpscnt
,
5051 char *data
, int tdscnt
,
5052 int mdrcnt
,int mprcnt
,
5053 char **rdata
,char **rparam
,
5054 int *rdata_len
,int *rparam_len
)
5056 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5057 char *str2
= skip_string(param
,tpscnt
,str1
);
5058 char *p
= skip_string(param
,tpscnt
,str2
);
5062 struct pack_desc desc
;
5064 TALLOC_CTX
*mem_ctx
= talloc_tos();
5067 struct rpc_pipe_client
*cli
= NULL
;
5068 union spoolss_PrinterInfo
*info
;
5071 if (!str1
|| !str2
|| !p
) {
5075 memset((char *)&desc
,'\0',sizeof(desc
));
5077 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5079 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5081 /* check it's a supported varient */
5082 if (strcmp(str1
,"WrLeh") != 0) {
5085 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5091 status
= rpc_pipe_open_interface(mem_ctx
,
5094 conn
->sconn
->remote_address
,
5095 conn
->sconn
->local_address
,
5096 conn
->sconn
->msg_ctx
,
5098 if (!NT_STATUS_IS_OK(status
)) {
5099 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5100 nt_errstr(status
)));
5101 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5105 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5107 cli
->srv_name_slash
,
5112 if (!W_ERROR_IS_OK(werr
)) {
5113 desc
.errcode
= W_ERROR_V(werr
);
5115 desc
.errcode
= NERR_DestNotFound
;
5123 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5130 desc
.buflen
= mdrcnt
;
5131 if (init_package(&desc
,queuecnt
,0)) {
5134 for (i
= 0; i
< count
; i
++) {
5135 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5137 if (desc
.errcode
== NERR_Success
) {
5143 *rdata_len
= desc
.usedlen
;
5146 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5150 SSVALS(*rparam
,0,desc
.errcode
);
5152 SSVAL(*rparam
,4,succnt
);
5153 SSVAL(*rparam
,6,queuecnt
);
5155 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5160 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5161 connection_struct
*conn
, uint64_t vuid
,
5162 char *param
, int tpscnt
,
5163 char *data
, int tdscnt
,
5164 int mdrcnt
,int mprcnt
,
5165 char **rdata
,char **rparam
,
5166 int *rdata_len
,int *rparam_len
)
5168 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5169 char *str2
= skip_string(param
,tpscnt
,str1
);
5170 char *p
= skip_string(param
,tpscnt
,str2
);
5173 struct pack_desc desc
;
5175 if (!str1
|| !str2
|| !p
) {
5179 memset((char *)&desc
,'\0',sizeof(desc
));
5181 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5183 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5185 /* check it's a supported varient */
5186 if (strcmp(str1
,"WrLeh") != 0) {
5189 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5194 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5200 desc
.buflen
= mdrcnt
;
5201 if (init_package(&desc
,1,0)) {
5202 PACKS(&desc
,"B41","NULL");
5205 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5207 *rdata_len
= desc
.usedlen
;
5210 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5214 SSVALS(*rparam
,0,desc
.errcode
);
5216 SSVAL(*rparam
,4,succnt
);
5219 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5224 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5225 connection_struct
*conn
, uint64_t vuid
,
5226 char *param
, int tpscnt
,
5227 char *data
, int tdscnt
,
5228 int mdrcnt
,int mprcnt
,
5229 char **rdata
,char **rparam
,
5230 int *rdata_len
,int *rparam_len
)
5232 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5233 char *str2
= skip_string(param
,tpscnt
,str1
);
5234 char *p
= skip_string(param
,tpscnt
,str2
);
5237 struct pack_desc desc
;
5239 if (!str1
|| !str2
|| !p
) {
5242 memset((char *)&desc
,'\0',sizeof(desc
));
5244 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5246 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5248 /* check it's a supported varient */
5249 if (strcmp(str1
,"WrLeh") != 0) {
5252 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5257 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5263 desc
.buflen
= mdrcnt
;
5265 if (init_package(&desc
,1,0)) {
5266 PACKS(&desc
,"B13","lpd");
5269 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5271 *rdata_len
= desc
.usedlen
;
5274 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5278 SSVALS(*rparam
,0,desc
.errcode
);
5280 SSVAL(*rparam
,4,succnt
);
5283 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5288 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5289 connection_struct
*conn
, uint64_t vuid
,
5290 char *param
, int tpscnt
,
5291 char *data
, int tdscnt
,
5292 int mdrcnt
,int mprcnt
,
5293 char **rdata
,char **rparam
,
5294 int *rdata_len
,int *rparam_len
)
5296 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5297 char *str2
= skip_string(param
,tpscnt
,str1
);
5298 char *p
= skip_string(param
,tpscnt
,str2
);
5301 struct pack_desc desc
;
5303 if (!str1
|| !str2
|| !p
) {
5307 memset((char *)&desc
,'\0',sizeof(desc
));
5309 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5311 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5313 /* check it's a supported varient */
5314 if (strcmp(str1
,"WrLeh") != 0) {
5317 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5322 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5327 memset((char *)&desc
,'\0',sizeof(desc
));
5329 desc
.buflen
= mdrcnt
;
5331 if (init_package(&desc
,1,0)) {
5332 PACKS(&desc
,"B13","lp0");
5335 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5337 *rdata_len
= desc
.usedlen
;
5340 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5344 SSVALS(*rparam
,0,desc
.errcode
);
5346 SSVAL(*rparam
,4,succnt
);
5349 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5354 /****************************************************************************
5356 ****************************************************************************/
5358 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5359 connection_struct
*conn
, uint64_t vuid
,
5360 char *param
, int tpscnt
,
5361 char *data
, int tdscnt
,
5362 int mdrcnt
,int mprcnt
,
5363 char **rdata
,char **rparam
,
5364 int *rdata_len
,int *rparam_len
)
5367 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5368 char *str2
= skip_string(param
,tpscnt
,str1
);
5369 char *p
= skip_string(param
,tpscnt
,str2
);
5371 struct pack_desc desc
;
5374 TALLOC_CTX
*mem_ctx
= talloc_tos();
5377 struct rpc_pipe_client
*cli
= NULL
;
5378 struct dcerpc_binding_handle
*b
= NULL
;
5379 struct srvsvc_NetSessInfoCtr info_ctr
;
5380 uint32_t totalentries
, resume_handle
= 0;
5383 if (!str1
|| !str2
|| !p
) {
5389 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5391 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5392 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5393 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5395 /* check it's a supported varient */
5396 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5399 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5403 status
= rpc_pipe_open_interface(mem_ctx
,
5406 conn
->sconn
->remote_address
,
5407 conn
->sconn
->local_address
,
5408 conn
->sconn
->msg_ctx
,
5410 if (!NT_STATUS_IS_OK(status
)) {
5411 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5412 nt_errstr(status
)));
5413 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5416 b
= cli
->binding_handle
;
5419 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5420 if (info_ctr
.ctr
.ctr1
== NULL
) {
5421 desc
.errcode
= W_ERROR_V(WERR_NOT_ENOUGH_MEMORY
);
5425 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5426 cli
->srv_name_slash
,
5430 (uint32_t)-1, /* max_buffer */
5434 if (!NT_STATUS_IS_OK(status
)) {
5435 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5436 nt_errstr(status
)));
5437 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5441 if (!W_ERROR_IS_OK(werr
)) {
5442 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5444 desc
.errcode
= W_ERROR_V(werr
);
5448 count
= info_ctr
.ctr
.ctr1
->count
;
5452 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5459 desc
.buflen
= mdrcnt
;
5461 if (!init_package(&desc
, count
,0)) {
5465 for(i
=0; i
< count
; i
++) {
5466 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5467 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5468 PACKI(&desc
, "W", 1); /* num conns */
5469 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5470 PACKI(&desc
, "W", 1); /* num users */
5471 PACKI(&desc
, "D", 0); /* session time */
5472 PACKI(&desc
, "D", 0); /* idle time */
5473 PACKI(&desc
, "D", 0); /* flags */
5474 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5477 *rdata_len
= desc
.usedlen
;
5480 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5484 SSVALS(*rparam
,0,desc
.errcode
);
5485 SSVAL(*rparam
,2,0); /* converter */
5486 SSVAL(*rparam
,4, count
); /* count */
5488 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5494 /****************************************************************************
5495 The buffer was too small.
5496 ****************************************************************************/
5498 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5499 connection_struct
*conn
,uint64_t vuid
, char *param
, char *data
,
5500 int mdrcnt
, int mprcnt
,
5501 char **rdata
, char **rparam
,
5502 int *rdata_len
, int *rparam_len
)
5504 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5505 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5512 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5514 DEBUG(3,("Supplied buffer too small in API command\n"));
5519 /****************************************************************************
5520 The request is not supported.
5521 ****************************************************************************/
5523 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5524 connection_struct
*conn
, uint64_t vuid
,
5525 char *param
, int tpscnt
,
5526 char *data
, int tdscnt
,
5527 int mdrcnt
, int mprcnt
,
5528 char **rdata
, char **rparam
,
5529 int *rdata_len
, int *rparam_len
)
5532 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5539 SSVAL(*rparam
,0,NERR_notsupported
);
5540 SSVAL(*rparam
,2,0); /* converter word */
5542 DEBUG(3,("Unsupported API command\n"));
5547 static const struct {
5550 bool (*fn
)(struct smbd_server_connection
*sconn
,
5551 connection_struct
*, uint64_t,
5554 int,int,char **,char **,int *,int *);
5555 bool auth_user
; /* Deny anonymous access? */
5556 } api_commands
[] = {
5558 .name
= "RNetShareEnum",
5559 .id
= RAP_WshareEnum
,
5560 .fn
= api_RNetShareEnum
,
5564 .name
= "RNetShareGetInfo",
5565 .id
= RAP_WshareGetInfo
,
5566 .fn
= api_RNetShareGetInfo
5569 .name
= "RNetShareAdd",
5570 .id
= RAP_WshareAdd
,
5571 .fn
= api_RNetShareAdd
5574 .name
= "RNetSessionEnum",
5575 .id
= RAP_WsessionEnum
,
5576 .fn
= api_RNetSessionEnum
,
5580 .name
= "RNetServerGetInfo",
5581 .id
= RAP_WserverGetInfo
,
5582 .fn
= api_RNetServerGetInfo
5585 .name
= "RNetGroupEnum",
5586 .id
= RAP_WGroupEnum
,
5587 .fn
= api_RNetGroupEnum
, True
5590 .name
= "RNetGroupGetUsers",
5591 .id
= RAP_WGroupGetUsers
,
5592 .fn
= api_RNetGroupGetUsers
,
5595 .name
= "RNetUserEnum",
5596 .id
= RAP_WUserEnum
,
5597 .fn
= api_RNetUserEnum
,
5601 .name
= "RNetUserGetInfo",
5602 .id
= RAP_WUserGetInfo
,
5603 .fn
= api_RNetUserGetInfo
5606 .name
= "NetUserGetGroups",
5607 .id
= RAP_WUserGetGroups
,
5608 .fn
= api_NetUserGetGroups
5611 .name
= "NetWkstaGetInfo",
5612 .id
= RAP_WWkstaGetInfo
,
5613 .fn
= api_NetWkstaGetInfo
5616 .name
= "DosPrintQEnum",
5617 .id
= RAP_WPrintQEnum
,
5618 .fn
= api_DosPrintQEnum
,
5622 .name
= "DosPrintQGetInfo",
5623 .id
= RAP_WPrintQGetInfo
,
5624 .fn
= api_DosPrintQGetInfo
5627 .name
= "WPrintQueuePause",
5628 .id
= RAP_WPrintQPause
,
5629 .fn
= api_WPrintQueueCtrl
5632 .name
= "WPrintQueueResume",
5633 .id
= RAP_WPrintQContinue
,
5634 .fn
= api_WPrintQueueCtrl
5637 .name
= "WPrintJobEnumerate",
5638 .id
= RAP_WPrintJobEnum
,
5639 .fn
= api_WPrintJobEnumerate
5642 .name
= "WPrintJobGetInfo",
5643 .id
= RAP_WPrintJobGetInfo
,
5644 .fn
= api_WPrintJobGetInfo
5647 .name
= "RDosPrintJobDel",
5648 .id
= RAP_WPrintJobDel
,
5649 .fn
= api_RDosPrintJobDel
5652 .name
= "RDosPrintJobPause",
5653 .id
= RAP_WPrintJobPause
,
5654 .fn
= api_RDosPrintJobDel
5657 .name
= "RDosPrintJobResume",
5658 .id
= RAP_WPrintJobContinue
,
5659 .fn
= api_RDosPrintJobDel
5662 .name
= "WPrintDestEnum",
5663 .id
= RAP_WPrintDestEnum
,
5664 .fn
= api_WPrintDestEnum
5667 .name
= "WPrintDestGetInfo",
5668 .id
= RAP_WPrintDestGetInfo
,
5669 .fn
= api_WPrintDestGetInfo
5672 .name
= "NetRemoteTOD",
5673 .id
= RAP_NetRemoteTOD
,
5674 .fn
= api_NetRemoteTOD
5677 .name
= "WPrintQueuePurge",
5678 .id
= RAP_WPrintQPurge
,
5679 .fn
= api_WPrintQueueCtrl
5682 .name
= "NetServerEnum2",
5683 .id
= RAP_NetServerEnum2
,
5684 .fn
= api_RNetServerEnum2
5687 .name
= "NetServerEnum3",
5688 .id
= RAP_NetServerEnum3
,
5689 .fn
= api_RNetServerEnum3
5692 .name
= "WAccessGetUserPerms",
5693 .id
= RAP_WAccessGetUserPerms
,
5694 .fn
= api_WAccessGetUserPerms
5697 .name
= "WWkstaUserLogon",
5698 .id
= RAP_WWkstaUserLogon
,
5699 .fn
= api_WWkstaUserLogon
5702 .name
= "PrintJobInfo",
5703 .id
= RAP_WPrintJobSetInfo
,
5704 .fn
= api_PrintJobInfo
5707 .name
= "WPrintDriverEnum",
5708 .id
= RAP_WPrintDriverEnum
,
5709 .fn
= api_WPrintDriverEnum
5712 .name
= "WPrintQProcEnum",
5713 .id
= RAP_WPrintQProcessorEnum
,
5714 .fn
= api_WPrintQProcEnum
5717 .name
= "WPrintPortEnum",
5718 .id
= RAP_WPrintPortEnum
,
5719 .fn
= api_WPrintPortEnum
5722 .name
= "SamOEMChangePassword",
5723 .id
= RAP_SamOEMChgPasswordUser2_P
,
5724 .fn
= api_SamOEMChangePassword
5729 .fn
= api_Unsupported
}
5731 * The following RAP calls are not implemented by Samba:
5732 * RAP_WFileEnum2 - anon not OK
5737 /****************************************************************************
5738 Handle remote api calls.
5739 ****************************************************************************/
5741 void api_reply(connection_struct
*conn
, uint64_t vuid
,
5742 struct smb_request
*req
,
5743 char *data
, char *params
,
5744 int tdscnt
, int tpscnt
,
5745 int mdrcnt
, int mprcnt
)
5749 char *rparam
= NULL
;
5750 const char *name1
= NULL
;
5751 const char *name2
= NULL
;
5758 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5759 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5764 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5767 api_command
= SVAL(params
,0);
5768 /* Is there a string at position params+2 ? */
5769 if (skip_string(params
,tpscnt
,params
+2)) {
5774 name2
= skip_string(params
,tpscnt
,params
+2);
5779 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5783 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5785 for (i
=0;api_commands
[i
].name
;i
++) {
5786 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5787 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5792 /* Check whether this api call can be done anonymously */
5794 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5795 struct auth_session_info
*si
= NULL
;
5798 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
5801 if (!NT_STATUS_IS_OK(status
)) {
5802 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5806 if (security_session_user_level(si
, NULL
) < SECURITY_USER
) {
5807 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5812 rdata
= (char *)SMB_MALLOC(1024);
5814 memset(rdata
,'\0',1024);
5817 rparam
= (char *)SMB_MALLOC(1024);
5819 memset(rparam
,'\0',1024);
5822 if(!rdata
|| !rparam
) {
5823 DEBUG(0,("api_reply: malloc fail !\n"));
5826 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5830 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5832 params
,tpscnt
, /* params + length */
5833 data
,tdscnt
, /* data + length */
5835 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5838 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5839 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5841 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5844 /* if we get False back then it's actually unsupported */
5846 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5848 tdscnt
,mdrcnt
,mprcnt
,
5849 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5852 /* If api_Unsupported returns false we can't return anything. */
5854 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5855 rdata
, rdata_len
, False
);