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"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/printing/rap_jobid.h"
48 #include "source3/lib/substitute.h"
55 #define NERR_Success 0
56 #define NERR_badpass 86
57 #define NERR_notsupported 50
59 #define NERR_BASE (2100)
60 #define NERR_BufTooSmall (NERR_BASE+23)
61 #define NERR_JobNotFound (NERR_BASE+51)
62 #define NERR_DestNotFound (NERR_BASE+52)
64 #define ACCESS_READ 0x01
65 #define ACCESS_WRITE 0x02
66 #define ACCESS_CREATE 0x04
68 #define SHPWLEN 8 /* share password length */
70 /* Limit size of ipc replies */
72 static char *smb_realloc_limit(void *ptr
, size_t size
)
76 size
= MAX((size
),4*1024);
77 val
= (char *)SMB_REALLOC(ptr
,size
);
79 memset(val
,'\0',size
);
84 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
85 connection_struct
*conn
, uint64_t vuid
,
86 char *param
, int tpscnt
,
87 char *data
, int tdscnt
,
88 int mdrcnt
, int mprcnt
,
89 char **rdata
, char **rparam
,
90 int *rdata_len
, int *rparam_len
);
92 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
93 connection_struct
*conn
, uint64_t vuid
, char *param
, char *data
,
94 int mdrcnt
, int mprcnt
,
95 char **rdata
, char **rparam
,
96 int *rdata_len
, int *rparam_len
);
99 static int CopyExpanded(connection_struct
*conn
,
100 int snum
, char **dst
, char *src
, int *p_space_remaining
)
102 TALLOC_CTX
*ctx
= talloc_tos();
103 const struct loadparm_substitution
*lp_sub
=
104 loadparm_s3_global_substitution();
108 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
109 *p_space_remaining
<= 0) {
113 buf
= talloc_strdup(ctx
, src
);
115 *p_space_remaining
= 0;
118 buf
= talloc_string_sub(ctx
, buf
,"%S", lp_servicename(ctx
, lp_sub
, snum
));
120 *p_space_remaining
= 0;
123 buf
= talloc_sub_full(ctx
,
124 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
125 conn
->session_info
->unix_info
->unix_name
,
127 conn
->session_info
->unix_token
->gid
,
128 conn
->session_info
->unix_info
->sanitized_username
,
129 conn
->session_info
->info
->domain_name
,
132 *p_space_remaining
= 0;
135 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
140 (*p_space_remaining
) -= l
;
144 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
147 if (!src
|| !dst
|| !n
|| !(*dst
)) {
150 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
159 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
161 TALLOC_CTX
*ctx
= talloc_tos();
162 const struct loadparm_substitution
*lp_sub
=
163 loadparm_s3_global_substitution();
168 buf
= talloc_strdup(ctx
,s
);
172 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(ctx
, lp_sub
, snum
));
176 buf
= talloc_sub_full(ctx
,
177 lp_servicename(ctx
, lp_sub
, SNUM(conn
)),
178 conn
->session_info
->unix_info
->unix_name
,
180 conn
->session_info
->unix_token
->gid
,
181 conn
->session_info
->unix_info
->sanitized_username
,
182 conn
->session_info
->info
->domain_name
,
187 return strlen(buf
) + 1;
190 /*******************************************************************
191 Check a API string for validity when we only need to check the prefix.
192 ******************************************************************/
194 static bool prefix_ok(const char *str
, const char *prefix
)
196 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
200 const char *format
; /* formatstring for structure */
201 const char *subformat
; /* subformat for structure */
202 char *base
; /* baseaddress of buffer */
203 int buflen
; /* remaining size for fixed part; on init: length of base */
204 int subcount
; /* count of substructures */
205 char *structbuf
; /* pointer into buffer for remaining fixed part */
206 int stringlen
; /* remaining size for variable part */
207 char *stringbuf
; /* pointer into buffer for remaining variable part */
208 int neededlen
; /* total needed size */
209 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
210 const char *curpos
; /* current position; pointer into format or subformat */
214 static int get_counter(const char **p
)
220 if (!isdigit((int)**p
)) {
226 n
= 10 * n
+ (i
- '0');
234 static int getlen(const char *p
)
243 case 'W': /* word (2 byte) */
246 case 'K': /* status word? (2 byte) */
249 case 'N': /* count of substructures (word) at end */
252 case 'D': /* double word (4 byte) */
253 case 'z': /* offset to zero terminated string (4 byte) */
254 case 'l': /* offset to user data (4 byte) */
257 case 'b': /* offset to data (with counter) (4 byte) */
261 case 'B': /* byte (with optional counter) */
262 n
+= get_counter(&p
);
269 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
274 if (!p
->format
|| !p
->base
) {
278 i
= count
* getlen(p
->format
);
280 i
+= subcount
* getlen(p
->subformat
);
282 p
->structbuf
= p
->base
;
286 p
->curpos
= p
->format
;
292 * This is the old error code we used. Aparently
293 * WinNT/2k systems return ERRbuftoosmall (2123) and
294 * OS/2 needs this. I'm leaving this here so we can revert
297 p
->errcode
= ERRmoredata
;
299 p
->errcode
= ERRbuftoosmall
;
302 p
->errcode
= NERR_Success
;
306 p
->stringbuf
= p
->base
+ i
;
308 return (p
->errcode
== NERR_Success
);
311 static int package(struct pack_desc
*p
, ...)
314 int needed
=0, stringneeded
;
315 const char *str
=NULL
;
316 int is_string
=0, stringused
;
323 p
->curpos
= p
->format
;
325 p
->curpos
= p
->subformat
;
330 str
= va_arg(args
,char*);
331 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
340 switch( *p
->curpos
++ ) {
341 case 'W': /* word (2 byte) */
343 temp
= va_arg(args
,int);
344 if (p
->buflen
>= needed
) {
345 SSVAL(p
->structbuf
,0,temp
);
348 case 'K': /* status word? (2 byte) */
350 temp
= va_arg(args
,int);
351 if (p
->buflen
>= needed
) {
352 SSVAL(p
->structbuf
,0,temp
);
355 case 'N': /* count of substructures (word) at end */
357 p
->subcount
= va_arg(args
,int);
358 if (p
->buflen
>= needed
) {
359 SSVAL(p
->structbuf
,0,p
->subcount
);
362 case 'D': /* double word (4 byte) */
364 temp
= va_arg(args
,int);
365 if (p
->buflen
>= needed
) {
366 SIVAL(p
->structbuf
,0,temp
);
369 case 'B': /* byte (with optional counter) */
370 needed
= get_counter(&p
->curpos
);
372 char *s
= va_arg(args
,char*);
373 if (p
->buflen
>= needed
) {
374 strlcpy(p
->structbuf
,s
?s
:"",needed
);
378 case 'z': /* offset to zero terminated string (4 byte) */
379 str
= va_arg(args
,char*);
380 stringneeded
= (str
? strlen(str
)+1 : 0);
383 case 'l': /* offset to user data (4 byte) */
384 str
= va_arg(args
,char*);
385 stringneeded
= va_arg(args
,int);
388 case 'b': /* offset to data (with counter) (4 byte) */
389 str
= va_arg(args
,char*);
390 stringneeded
= get_counter(&p
->curpos
);
396 if (stringneeded
>= 0) {
398 if (p
->buflen
>= needed
) {
399 stringused
= stringneeded
;
400 if (stringused
> p
->stringlen
) {
401 stringused
= (is_string
? p
->stringlen
: 0);
402 if (p
->errcode
== NERR_Success
) {
403 p
->errcode
= ERRmoredata
;
407 SIVAL(p
->structbuf
,0,0);
409 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
410 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
412 p
->stringbuf
[stringused
-1] = '\0';
414 p
->stringbuf
+= stringused
;
415 p
->stringlen
-= stringused
;
416 p
->usedlen
+= stringused
;
419 p
->neededlen
+= stringneeded
;
422 p
->neededlen
+= needed
;
423 if (p
->buflen
>= needed
) {
424 p
->structbuf
+= needed
;
426 p
->usedlen
+= needed
;
428 if (p
->errcode
== NERR_Success
) {
429 p
->errcode
= ERRmoredata
;
436 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
437 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
439 #define PACK(desc,t,v) package(desc,v)
440 #define PACKl(desc,t,v,l) package(desc,v,l)
443 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
448 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
453 /****************************************************************************
455 ****************************************************************************/
457 static void PackDriverData(struct pack_desc
* desc
)
459 char drivdata
[4+4+32];
460 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
461 SIVAL(drivdata
,4,1000); /* lVersion */
462 memset(drivdata
+8,0,32); /* szDeviceName */
463 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
464 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
467 static int check_printq_info(struct pack_desc
* desc
,
468 unsigned int uLevel
, char *id1
, char *id2
)
470 desc
->subformat
= NULL
;
473 desc
->format
= "B13";
476 desc
->format
= "B13BWWWzzzzzWW";
479 desc
->format
= "B13BWWWzzzzzWN";
480 desc
->subformat
= "WB21BB16B10zWWzDDz";
483 desc
->format
= "zWWWWzzzzWWzzl";
486 desc
->format
= "zWWWWzzzzWNzzl";
487 desc
->subformat
= "WWzWWDDzz";
496 desc
->format
= "WzzzzzzzzN";
497 desc
->subformat
= "z";
500 DEBUG(0,("check_printq_info: invalid level %d\n",
504 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
505 DEBUG(0,("check_printq_info: invalid format %s\n",
506 id1
? id1
: "<NULL>" ));
509 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
510 DEBUG(0,("check_printq_info: invalid subformat %s\n",
511 id2
? id2
: "<NULL>" ));
518 #define RAP_JOB_STATUS_QUEUED 0
519 #define RAP_JOB_STATUS_PAUSED 1
520 #define RAP_JOB_STATUS_SPOOLING 2
521 #define RAP_JOB_STATUS_PRINTING 3
522 #define RAP_JOB_STATUS_PRINTED 4
524 #define RAP_QUEUE_STATUS_PAUSED 1
525 #define RAP_QUEUE_STATUS_ERROR 2
527 /* turn a print job status into a on the wire status
529 static int printj_spoolss_status(int v
)
531 if (v
== JOB_STATUS_QUEUED
)
532 return RAP_JOB_STATUS_QUEUED
;
533 if (v
& JOB_STATUS_PAUSED
)
534 return RAP_JOB_STATUS_PAUSED
;
535 if (v
& JOB_STATUS_SPOOLING
)
536 return RAP_JOB_STATUS_SPOOLING
;
537 if (v
& JOB_STATUS_PRINTING
)
538 return RAP_JOB_STATUS_PRINTING
;
542 /* turn a print queue status into a on the wire status
544 static int printq_spoolss_status(int v
)
546 if (v
== PRINTER_STATUS_OK
)
548 if (v
& PRINTER_STATUS_PAUSED
)
549 return RAP_QUEUE_STATUS_PAUSED
;
550 return RAP_QUEUE_STATUS_ERROR
;
553 static void fill_spoolss_printjob_info(int uLevel
,
554 struct pack_desc
*desc
,
555 struct spoolss_JobInfo2
*info2
,
558 time_t t
= spoolss_Time_to_time_t(&info2
->submitted
);
560 /* the client expects localtime */
561 t
-= get_time_zone(t
);
563 PACKI(desc
,"W",pjobid_to_rap(info2
->printer_name
, info2
->job_id
)); /* uJobId */
565 PACKS(desc
,"B21", info2
->user_name
); /* szUserName */
566 PACKS(desc
,"B",""); /* pad */
567 PACKS(desc
,"B16",""); /* szNotifyName */
568 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
569 PACKS(desc
,"z",""); /* pszParms */
570 PACKI(desc
,"W",n
+1); /* uPosition */
571 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
572 PACKS(desc
,"z",""); /* pszStatus */
573 PACKI(desc
,"D", t
); /* ulSubmitted */
574 PACKI(desc
,"D", info2
->size
); /* ulSize */
575 PACKS(desc
,"z", info2
->document_name
); /* pszComment */
577 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
578 PACKI(desc
,"W", info2
->priority
); /* uPriority */
579 PACKS(desc
,"z", info2
->user_name
); /* pszUserName */
580 PACKI(desc
,"W",n
+1); /* uPosition */
581 PACKI(desc
,"W", printj_spoolss_status(info2
->status
)); /* fsStatus */
582 PACKI(desc
,"D",t
); /* ulSubmitted */
583 PACKI(desc
,"D", info2
->size
); /* ulSize */
584 PACKS(desc
,"z","Samba"); /* pszComment */
585 PACKS(desc
,"z", info2
->document_name
); /* pszDocument */
587 PACKS(desc
,"z",""); /* pszNotifyName */
588 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
589 PACKS(desc
,"z",""); /* pszParms */
590 PACKS(desc
,"z",""); /* pszStatus */
591 PACKS(desc
,"z", info2
->printer_name
); /* pszQueue */
592 PACKS(desc
,"z","lpd"); /* pszQProcName */
593 PACKS(desc
,"z",""); /* pszQProcParms */
594 PACKS(desc
,"z","NULL"); /* pszDriverName */
595 PackDriverData(desc
); /* pDriverData */
596 PACKS(desc
,"z",""); /* pszPrinterName */
597 } else if (uLevel
== 4) { /* OS2 */
598 PACKS(desc
,"z",""); /* pszSpoolFileName */
599 PACKS(desc
,"z",""); /* pszPortName */
600 PACKS(desc
,"z",""); /* pszStatus */
601 PACKI(desc
,"D",0); /* ulPagesSpooled */
602 PACKI(desc
,"D",0); /* ulPagesSent */
603 PACKI(desc
,"D",0); /* ulPagesPrinted */
604 PACKI(desc
,"D",0); /* ulTimePrinted */
605 PACKI(desc
,"D",0); /* ulExtendJobStatus */
606 PACKI(desc
,"D",0); /* ulStartPage */
607 PACKI(desc
,"D",0); /* ulEndPage */
612 /********************************************************************
613 Respond to the DosPrintQInfo command with a level of 52
614 This is used to get printer driver information for Win9x clients
615 ********************************************************************/
616 static void fill_printq_info_52(struct spoolss_DriverInfo3
*driver
,
617 struct pack_desc
* desc
, int count
,
618 const char *printer_name
)
622 trim_string(discard_const_p(char, driver
->driver_path
), "\\print$\\WIN40\\0\\", 0);
623 trim_string(discard_const_p(char, driver
->data_file
), "\\print$\\WIN40\\0\\", 0);
624 trim_string(discard_const_p(char, driver
->help_file
), "\\print$\\WIN40\\0\\", 0);
626 PACKI(desc
, "W", 0x0400); /* don't know */
627 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
628 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
629 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
630 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
632 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
633 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
634 PACKS(desc
,"z", location
); /* share to retrieve files */
636 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
637 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
638 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
640 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
641 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
642 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
643 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
644 DEBUG(3,("Driver Location: %s:\n",location
));
645 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
646 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
647 PACKI(desc
,"N",count
); /* number of files to copy */
649 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
651 trim_string(discard_const_p(char, driver
->dependent_files
[i
]), "\\print$\\WIN40\\0\\", 0);
652 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
653 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
658 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
661 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name
, i
));
663 desc
->errcode
=NERR_Success
;
667 static const char *strip_unc(const char *unc
)
675 if ((p
= strrchr(unc
, '\\')) != NULL
) {
682 static void fill_printq_info(int uLevel
,
683 struct pack_desc
* desc
,
685 union spoolss_JobInfo
*job_info
,
686 struct spoolss_DriverInfo3
*driver_info
,
687 struct spoolss_PrinterInfo2
*printer_info
)
693 PACKS(desc
,"B13", strip_unc(printer_info
->printername
));
698 PACKS(desc
,"z", strip_unc(printer_info
->printername
));
701 PACKI(desc
,"K", printq_spoolss_status(printer_info
->status
));
705 if (uLevel
== 1 || uLevel
== 2) {
706 PACKS(desc
,"B",""); /* alignment */
707 PACKI(desc
,"W",5); /* priority */
708 PACKI(desc
,"W",0); /* start time */
709 PACKI(desc
,"W",0); /* until time */
710 PACKS(desc
,"z",""); /* pSepFile */
711 PACKS(desc
,"z","lpd"); /* pPrProc */
712 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pDestinations */
713 PACKS(desc
,"z",""); /* pParms */
714 if (printer_info
->printername
== NULL
) {
715 PACKS(desc
,"z","UNKNOWN PRINTER");
716 PACKI(desc
,"W",LPSTAT_ERROR
);
718 PACKS(desc
,"z", printer_info
->comment
);
719 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* status */
721 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
724 if (uLevel
== 3 || uLevel
== 4) {
725 PACKI(desc
,"W",5); /* uPriority */
726 PACKI(desc
,"W",0); /* uStarttime */
727 PACKI(desc
,"W",0); /* uUntiltime */
728 PACKI(desc
,"W",5); /* pad1 */
729 PACKS(desc
,"z",""); /* pszSepFile */
730 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
731 PACKS(desc
,"z",NULL
); /* pszParms */
732 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
733 /* "don't ask" that it's done this way to fix corrupted
734 Win9X/ME printer comments. */
735 PACKI(desc
,"W", printq_spoolss_status(printer_info
->status
)); /* fsStatus */
736 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
737 PACKS(desc
,"z", strip_unc(printer_info
->printername
)); /* pszPrinters */
738 PACKS(desc
,"z", printer_info
->drivername
); /* pszDriverName */
739 PackDriverData(desc
); /* pDriverData */
742 if (uLevel
== 2 || uLevel
== 4) {
744 for (i
= 0; i
< count
; i
++) {
745 fill_spoolss_printjob_info(uLevel
== 2 ? 1 : 2, desc
, &job_info
[i
].info2
, i
);
750 fill_printq_info_52(driver_info
, desc
, count
, printer_info
->printername
);
753 /* This function returns the number of files for a given driver */
754 static int get_printerdrivernumber(const struct spoolss_DriverInfo3
*driver
)
758 /* count the number of files */
759 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
765 static bool api_DosPrintQGetInfo(struct smbd_server_connection
*sconn
,
766 connection_struct
*conn
, uint64_t vuid
,
767 char *param
, int tpscnt
,
768 char *data
, int tdscnt
,
769 int mdrcnt
,int mprcnt
,
770 char **rdata
,char **rparam
,
771 int *rdata_len
,int *rparam_len
)
773 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
774 char *str2
= skip_string(param
,tpscnt
,str1
);
775 char *p
= skip_string(param
,tpscnt
,str2
);
780 struct pack_desc desc
;
783 WERROR werr
= WERR_OK
;
784 TALLOC_CTX
*mem_ctx
= talloc_tos();
786 struct rpc_pipe_client
*cli
= NULL
;
787 struct dcerpc_binding_handle
*b
= NULL
;
788 struct policy_handle handle
;
789 struct spoolss_DevmodeContainer devmode_ctr
;
790 union spoolss_DriverInfo driver_info
;
791 union spoolss_JobInfo
*job_info
= NULL
;
792 union spoolss_PrinterInfo printer_info
;
794 if (!str1
|| !str2
|| !p
) {
797 memset((char *)&desc
,'\0',sizeof(desc
));
799 p
= skip_string(param
,tpscnt
,p
);
803 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
804 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
805 /* str3 may be null here and is checked in check_printq_info(). */
807 /* remove any trailing username */
808 if ((p
= strchr_m(QueueName
,'%')))
811 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
813 /* check it's a supported varient */
814 if (!prefix_ok(str1
,"zWrLh"))
816 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
818 * Patch from Scott Moomaw <scott@bridgewater.edu>
819 * to return the 'invalid info level' error if an
820 * unknown level was requested.
824 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
828 SSVALS(*rparam
,0,ERRunknownlevel
);
836 if (QueueName
== NULL
|| (strlen(QueueName
) < 1)) {
837 desc
.errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
841 status
= rpc_pipe_open_interface(mem_ctx
,
844 conn
->sconn
->remote_address
,
845 conn
->sconn
->local_address
,
846 conn
->sconn
->msg_ctx
,
848 if (!NT_STATUS_IS_OK(status
)) {
849 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
851 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
854 b
= cli
->binding_handle
;
856 ZERO_STRUCT(devmode_ctr
);
858 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
865 if (!NT_STATUS_IS_OK(status
)) {
866 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
869 if (!W_ERROR_IS_OK(werr
)) {
870 desc
.errcode
= W_ERROR_V(werr
);
874 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
879 if (!W_ERROR_IS_OK(werr
)) {
880 desc
.errcode
= W_ERROR_V(werr
);
885 uint32_t server_major_version
;
886 uint32_t server_minor_version
;
888 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
896 &server_major_version
,
897 &server_minor_version
);
898 if (!W_ERROR_IS_OK(werr
)) {
899 desc
.errcode
= W_ERROR_V(werr
);
903 count
= get_printerdrivernumber(&driver_info
.info3
);
904 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
907 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
915 if (!W_ERROR_IS_OK(werr
)) {
916 desc
.errcode
= W_ERROR_V(werr
);
924 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
929 desc
.buflen
= mdrcnt
;
932 * Don't return data but need to get correct length
933 * init_package will return wrong size if buflen=0
935 desc
.buflen
= getlen(desc
.format
);
936 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
939 if (init_package(&desc
,1,count
)) {
940 desc
.subcount
= count
;
941 fill_printq_info(uLevel
,&desc
,count
, job_info
, &driver_info
.info3
, &printer_info
.info2
);
944 *rdata_len
= desc
.usedlen
;
947 * We must set the return code to ERRbuftoosmall
948 * in order to support lanman style printing with Win NT/2k
951 if (!mdrcnt
&& lp_disable_spoolss())
952 desc
.errcode
= ERRbuftoosmall
;
955 if (b
&& is_valid_policy_hnd(&handle
)) {
956 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
959 *rdata_len
= desc
.usedlen
;
961 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
966 SSVALS(*rparam
,0,desc
.errcode
);
968 SSVAL(*rparam
,4,desc
.neededlen
);
970 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
977 /****************************************************************************
978 View list of all print jobs on all queues.
979 ****************************************************************************/
981 static bool api_DosPrintQEnum(struct smbd_server_connection
*sconn
,
982 connection_struct
*conn
, uint64_t vuid
,
983 char *param
, int tpscnt
,
984 char *data
, int tdscnt
,
985 int mdrcnt
, int mprcnt
,
986 char **rdata
, char** rparam
,
987 int *rdata_len
, int *rparam_len
)
989 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
990 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
991 char *p
= skip_string(param
,tpscnt
,output_format1
);
992 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
993 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
995 struct pack_desc desc
;
996 int *subcntarr
= NULL
;
997 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
999 WERROR werr
= WERR_OK
;
1000 TALLOC_CTX
*mem_ctx
= talloc_tos();
1002 struct rpc_pipe_client
*cli
= NULL
;
1003 struct dcerpc_binding_handle
*b
= NULL
;
1004 struct spoolss_DevmodeContainer devmode_ctr
;
1005 uint32_t num_printers
;
1006 union spoolss_PrinterInfo
*printer_info
;
1007 union spoolss_DriverInfo
*driver_info
;
1008 union spoolss_JobInfo
**job_info
;
1010 if (!param_format
|| !output_format1
|| !p
) {
1014 memset((char *)&desc
,'\0',sizeof(desc
));
1016 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1018 if (!prefix_ok(param_format
,"WrLeh")) {
1021 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1023 * Patch from Scott Moomaw <scott@bridgewater.edu>
1024 * to return the 'invalid info level' error if an
1025 * unknown level was requested.
1029 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1033 SSVALS(*rparam
,0,ERRunknownlevel
);
1039 status
= rpc_pipe_open_interface(mem_ctx
,
1042 conn
->sconn
->remote_address
,
1043 conn
->sconn
->local_address
,
1044 conn
->sconn
->msg_ctx
,
1046 if (!NT_STATUS_IS_OK(status
)) {
1047 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1048 nt_errstr(status
)));
1049 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1052 b
= cli
->binding_handle
;
1054 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
1056 cli
->srv_name_slash
,
1061 if (!W_ERROR_IS_OK(werr
)) {
1062 desc
.errcode
= W_ERROR_V(werr
);
1066 queuecnt
= num_printers
;
1068 job_info
= talloc_array(mem_ctx
, union spoolss_JobInfo
*, num_printers
);
1069 if (job_info
== NULL
) {
1073 driver_info
= talloc_array(mem_ctx
, union spoolss_DriverInfo
, num_printers
);
1074 if (driver_info
== NULL
) {
1078 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1079 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1084 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1090 desc
.buflen
= mdrcnt
;
1093 for (i
= 0; i
< num_printers
; i
++) {
1096 struct policy_handle handle
;
1097 const char *printername
;
1099 printername
= talloc_strdup(mem_ctx
, printer_info
[i
].info2
.printername
);
1100 if (printername
== NULL
) {
1104 ZERO_STRUCT(handle
);
1105 ZERO_STRUCT(devmode_ctr
);
1107 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
1114 if (!NT_STATUS_IS_OK(status
)) {
1115 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
1118 if (!W_ERROR_IS_OK(werr
)) {
1119 desc
.errcode
= W_ERROR_V(werr
);
1123 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
1131 if (!W_ERROR_IS_OK(werr
)) {
1132 desc
.errcode
= W_ERROR_V(werr
);
1137 uint32_t server_major_version
;
1138 uint32_t server_minor_version
;
1140 werr
= rpccli_spoolss_getprinterdriver2(cli
, mem_ctx
,
1148 &server_major_version
,
1149 &server_minor_version
);
1150 if (!W_ERROR_IS_OK(werr
)) {
1151 desc
.errcode
= W_ERROR_V(werr
);
1156 subcntarr
[i
] = num_jobs
;
1157 subcnt
+= subcntarr
[i
];
1159 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
1162 if (init_package(&desc
,queuecnt
,subcnt
)) {
1163 for (i
= 0; i
< num_printers
; i
++) {
1164 fill_printq_info(uLevel
,&desc
,subcntarr
[i
], job_info
[i
], &driver_info
[i
].info3
, &printer_info
[i
].info2
);
1165 if (desc
.errcode
== NERR_Success
) {
1172 SAFE_FREE(subcntarr
);
1173 *rdata_len
= desc
.usedlen
;
1175 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1179 SSVALS(*rparam
,0,desc
.errcode
);
1181 SSVAL(*rparam
,4,succnt
);
1182 SSVAL(*rparam
,6,queuecnt
);
1188 SAFE_FREE(subcntarr
);
1193 /****************************************************************************
1194 Get info level for a server list query.
1195 ****************************************************************************/
1197 static bool check_session_info(int uLevel
, char* id
)
1201 if (strcmp(id
,"B16") != 0) {
1206 if (strcmp(id
,"B16BBDz") != 0) {
1216 struct srv_info_struct
{
1224 /*******************************************************************
1225 Get server info lists from the files saved by nmbd. Return the
1227 ******************************************************************/
1229 static int get_session_info(uint32_t servertype
,
1230 struct srv_info_struct
**servers
,
1236 bool local_list_only
;
1238 char *slist_cache_path
= cache_path(talloc_tos(), SERVER_LIST
);
1239 if (slist_cache_path
== NULL
) {
1243 lines
= file_lines_load(slist_cache_path
, NULL
, 0, NULL
);
1245 DEBUG(4, ("Can't open %s - %s\n",
1246 slist_cache_path
, strerror(errno
)));
1247 TALLOC_FREE(slist_cache_path
);
1250 TALLOC_FREE(slist_cache_path
);
1252 /* request for everything is code for request all servers */
1253 if (servertype
== SV_TYPE_ALL
) {
1254 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1257 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1259 DEBUG(4,("Servertype search: %8x\n",servertype
));
1261 for (i
=0;lines
[i
];i
++) {
1263 struct srv_info_struct
*s
;
1264 const char *ptr
= lines
[i
];
1266 TALLOC_CTX
*frame
= NULL
;
1273 if (count
== alloced
) {
1275 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1277 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1281 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1283 s
= &(*servers
)[count
];
1285 frame
= talloc_stackframe();
1287 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1291 fstrcpy(s
->name
, p
);
1294 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1300 s
->comment
[0] = '\0';
1301 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1305 fstrcpy(s
->comment
, p
);
1306 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1308 s
->domain
[0] = '\0';
1309 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1310 /* this allows us to cope with an old nmbd */
1311 fstrcpy(s
->domain
,lp_workgroup());
1313 fstrcpy(s
->domain
, p
);
1317 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1318 DEBUG(4,("r:host file "));
1322 /* Filter the servers/domains we return based on what was asked for. */
1324 /* Check to see if we are being asked for a local list only. */
1325 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1326 DEBUG(4,("r: local list only"));
1330 /* doesn't match up: don't want it */
1331 if (!(servertype
& s
->type
)) {
1332 DEBUG(4,("r:serv type "));
1336 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1337 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1338 DEBUG(4,("s: dom mismatch "));
1342 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1346 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1347 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1350 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1351 s
->name
, s
->type
, s
->comment
, s
->domain
));
1352 s
->server_added
= True
;
1355 DEBUG(4,("%20s %8x %25s %15s\n",
1356 s
->name
, s
->type
, s
->comment
, s
->domain
));
1364 /*******************************************************************
1365 Fill in a server info structure.
1366 ******************************************************************/
1368 static int fill_srv_info(struct srv_info_struct
*service
,
1369 int uLevel
, char **buf
, int *buflen
,
1370 char **stringbuf
, int *stringspace
, char *baseaddr
)
1393 len
= strlen(service
->comment
)+1;
1397 *buflen
= struct_len
;
1399 return struct_len
+ len
;
1404 if (*buflen
< struct_len
) {
1411 p2
= p
+ struct_len
;
1412 l2
= *buflen
- struct_len
;
1420 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1424 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1425 SIVAL(p
,18,service
->type
);
1426 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1427 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1432 *buf
= p
+ struct_len
;
1433 *buflen
-= struct_len
;
1444 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1446 return strcasecmp_m(s1
->name
,s2
->name
);
1449 /****************************************************************************
1450 View list of servers available (or possibly domains). The info is
1451 extracted from lists saved by nmbd on the local host.
1452 ****************************************************************************/
1454 static bool api_RNetServerEnum2(struct smbd_server_connection
*sconn
,
1455 connection_struct
*conn
, uint64_t vuid
,
1456 char *param
, int tpscnt
,
1457 char *data
, int tdscnt
,
1458 int mdrcnt
, int mprcnt
, char **rdata
,
1459 char **rparam
, int *rdata_len
, int *rparam_len
)
1461 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1462 char *str2
= skip_string(param
,tpscnt
,str1
);
1463 char *p
= skip_string(param
,tpscnt
,str2
);
1464 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1465 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1466 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1468 int data_len
, fixed_len
, string_len
;
1469 int f_len
= 0, s_len
= 0;
1470 struct srv_info_struct
*servers
=NULL
;
1471 int counted
=0,total
=0;
1474 bool domain_request
;
1477 if (!str1
|| !str2
|| !p
) {
1481 /* If someone sets all the bits they don't really mean to set
1482 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1485 if (servertype
== SV_TYPE_ALL
) {
1486 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1489 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1490 any other bit (they may just set this bit on its own) they
1491 want all the locally seen servers. However this bit can be
1492 set on its own so set the requested servers to be
1493 ALL - DOMAIN_ENUM. */
1495 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1496 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1499 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1500 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1504 if (!prefix_ok(str1
,"WrLehD")) {
1507 if (!check_session_info(uLevel
,str2
)) {
1511 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1512 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1513 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1515 if (strcmp(str1
, "WrLehDz") == 0) {
1516 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1519 pull_ascii_fstring(domain
, p
);
1521 fstrcpy(domain
, lp_workgroup());
1524 DEBUG(4, ("domain [%s]\n", domain
));
1526 if (lp_browse_list()) {
1527 total
= get_session_info(servertype
,&servers
,domain
);
1530 data_len
= fixed_len
= string_len
= 0;
1533 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1536 char *lastname
=NULL
;
1538 for (i
=0;i
<total
;i
++) {
1539 struct srv_info_struct
*s
= &servers
[i
];
1541 if (lastname
&& strequal(lastname
,s
->name
)) {
1545 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1546 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1547 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1549 if (data_len
< buf_len
) {
1552 string_len
+= s_len
;
1559 *rdata_len
= fixed_len
+ string_len
;
1560 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1565 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1571 char *lastname
=NULL
;
1572 int count2
= counted
;
1574 for (i
= 0; i
< total
&& count2
;i
++) {
1575 struct srv_info_struct
*s
= &servers
[i
];
1577 if (lastname
&& strequal(lastname
,s
->name
)) {
1581 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1582 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1583 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1589 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1593 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1595 SSVAL(*rparam
,4,counted
);
1596 SSVAL(*rparam
,6,counted
+missed
);
1600 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1601 domain
,uLevel
,counted
,counted
+missed
));
1606 static int srv_name_match(const char *n1
, const char *n2
)
1609 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1611 * In Windows, FirstNameToReturn need not be an exact match:
1612 * the server will return a list of servers that exist on
1613 * the network greater than or equal to the FirstNameToReturn.
1615 int ret
= strcasecmp_m(n1
, n2
);
1624 static bool api_RNetServerEnum3(struct smbd_server_connection
*sconn
,
1625 connection_struct
*conn
, uint64_t vuid
,
1626 char *param
, int tpscnt
,
1627 char *data
, int tdscnt
,
1628 int mdrcnt
, int mprcnt
, char **rdata
,
1629 char **rparam
, int *rdata_len
, int *rparam_len
)
1631 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1632 char *str2
= skip_string(param
,tpscnt
,str1
);
1633 char *p
= skip_string(param
,tpscnt
,str2
);
1634 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1635 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1636 uint32_t servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1638 int data_len
, fixed_len
, string_len
;
1639 int f_len
= 0, s_len
= 0;
1640 struct srv_info_struct
*servers
=NULL
;
1641 int counted
=0,first
=0,total
=0;
1645 bool domain_request
;
1648 if (!str1
|| !str2
|| !p
) {
1652 /* If someone sets all the bits they don't really mean to set
1653 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1656 if (servertype
== SV_TYPE_ALL
) {
1657 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1660 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1661 any other bit (they may just set this bit on its own) they
1662 want all the locally seen servers. However this bit can be
1663 set on its own so set the requested servers to be
1664 ALL - DOMAIN_ENUM. */
1666 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1667 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1670 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1671 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1675 if (strcmp(str1
, "WrLehDzz") != 0) {
1678 if (!check_session_info(uLevel
,str2
)) {
1682 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1683 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1684 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1686 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1689 pull_ascii_fstring(domain
, p
);
1690 if (domain
[0] == '\0') {
1691 fstrcpy(domain
, lp_workgroup());
1693 p
= skip_string(param
,tpscnt
,p
);
1694 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1697 pull_ascii_fstring(first_name
, p
);
1699 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1700 domain
, first_name
));
1702 if (lp_browse_list()) {
1703 total
= get_session_info(servertype
,&servers
,domain
);
1706 data_len
= fixed_len
= string_len
= 0;
1709 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1711 if (first_name
[0] != '\0') {
1712 struct srv_info_struct
*first_server
= NULL
;
1714 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1715 srv_name_match
, first_server
);
1717 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1719 * The binary search may not find the exact match
1720 * so we need to search backward to find the first match
1722 * This implements the strange matching windows
1723 * implements. (see the comment in srv_name_match().
1727 ret
= strcasecmp_m(first_name
,
1728 servers
[first
-1].name
);
1735 /* we should return no entries */
1741 char *lastname
=NULL
;
1743 for (i
=first
;i
<total
;i
++) {
1744 struct srv_info_struct
*s
= &servers
[i
];
1746 if (lastname
&& strequal(lastname
,s
->name
)) {
1750 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1751 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1752 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1754 if (data_len
< buf_len
) {
1757 string_len
+= s_len
;
1764 *rdata_len
= fixed_len
+ string_len
;
1765 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1770 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1776 char *lastname
=NULL
;
1777 int count2
= counted
;
1779 for (i
= first
; i
< total
&& count2
;i
++) {
1780 struct srv_info_struct
*s
= &servers
[i
];
1782 if (lastname
&& strequal(lastname
,s
->name
)) {
1786 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1787 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1788 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1794 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1798 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1800 SSVAL(*rparam
,4,counted
);
1801 SSVAL(*rparam
,6,counted
+missed
);
1803 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1804 domain
,uLevel
,first
,first_name
,
1805 first
< total
? servers
[first
].name
: "",
1806 counted
,counted
+missed
));
1813 /****************************************************************************
1814 command 0x34 - suspected of being a "Lookup Names" stub api
1815 ****************************************************************************/
1817 static bool api_RNetGroupGetUsers(struct smbd_server_connection
*sconn
,
1818 connection_struct
*conn
, uint64_t vuid
,
1819 char *param
, int tpscnt
,
1820 char *data
, int tdscnt
,
1821 int mdrcnt
, int mprcnt
, char **rdata
,
1822 char **rparam
, int *rdata_len
, int *rparam_len
)
1824 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1825 char *str2
= skip_string(param
,tpscnt
,str1
);
1826 char *p
= skip_string(param
,tpscnt
,str2
);
1827 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1828 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1832 if (!str1
|| !str2
|| !p
) {
1836 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1837 str1
, str2
, p
, uLevel
, buf_len
));
1839 if (!prefix_ok(str1
,"zWrLeh")) {
1846 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1851 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1853 SSVAL(*rparam
,4,counted
);
1854 SSVAL(*rparam
,6,counted
+missed
);
1859 /****************************************************************************
1860 get info about a share
1861 ****************************************************************************/
1863 static bool check_share_info(int uLevel
, char* id
)
1867 if (strcmp(id
,"B13") != 0) {
1872 /* Level-2 descriptor is allowed (and ignored) */
1873 if (strcmp(id
,"B13BWz") != 0 &&
1874 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1879 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1884 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1894 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1895 char** buf
, int* buflen
,
1896 char** stringbuf
, int* stringspace
, char* baseaddr
)
1898 const struct loadparm_substitution
*lp_sub
=
1899 loadparm_s3_global_substitution();
1927 len
+= StrlenExpanded(conn
,snum
,lp_comment(talloc_tos(), lp_sub
, snum
));
1930 len
+= strlen(lp_path(talloc_tos(), lp_sub
, snum
)) + 1;
1933 *buflen
= struct_len
;
1938 return struct_len
+ len
;
1943 if ((*buflen
) < struct_len
) {
1951 p2
= p
+ struct_len
;
1952 l2
= (*buflen
) - struct_len
;
1959 push_ascii(p
,lp_servicename(talloc_tos(), lp_sub
, snum
),13, STR_TERMINATE
);
1965 type
= STYPE_DISKTREE
;
1966 if (lp_printable(snum
)) {
1967 type
= STYPE_PRINTQ
;
1969 if (strequal("IPC",lp_fstype(snum
))) {
1972 SSVAL(p
,14,type
); /* device type */
1973 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1974 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(talloc_tos(), lp_sub
, snum
),&l2
);
1978 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1979 SSVALS(p
,22,-1); /* max uses */
1980 SSVAL(p
,24,1); /* current uses */
1981 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1982 len
+= CopyAndAdvance(&p2
,lp_path(talloc_tos(),lp_sub
, snum
),&l2
);
1983 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1987 memset(p
+40,0,SHPWLEN
+2);
1998 (*buf
) = p
+ struct_len
;
1999 (*buflen
) -= struct_len
;
2001 (*stringspace
) = l2
;
2010 static bool api_RNetShareGetInfo(struct smbd_server_connection
*sconn
,
2011 connection_struct
*conn
,uint64_t vuid
,
2012 char *param
, int tpscnt
,
2013 char *data
, int tdscnt
,
2014 int mdrcnt
,int mprcnt
,
2015 char **rdata
,char **rparam
,
2016 int *rdata_len
,int *rparam_len
)
2018 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2019 char *str2
= skip_string(param
,tpscnt
,str1
);
2020 char *netname_in
= skip_string(param
,tpscnt
,str2
);
2021 char *netname
= NULL
;
2022 char *p
= skip_string(param
,tpscnt
,netname
);
2023 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2026 if (!str1
|| !str2
|| !netname_in
|| !p
) {
2030 snum
= find_service(talloc_tos(), netname_in
, &netname
);
2031 if (snum
< 0 || !netname
) {
2035 /* check it's a supported varient */
2036 if (!prefix_ok(str1
,"zWrLh")) {
2039 if (!check_share_info(uLevel
,str2
)) {
2043 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
2048 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
2049 if (*rdata_len
< 0) {
2054 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2058 SSVAL(*rparam
,0,NERR_Success
);
2059 SSVAL(*rparam
,2,0); /* converter word */
2060 SSVAL(*rparam
,4,*rdata_len
);
2065 /****************************************************************************
2066 View the list of available shares.
2068 This function is the server side of the NetShareEnum() RAP call.
2069 It fills the return buffer with share names and share comments.
2070 Note that the return buffer normally (in all known cases) allows only
2071 twelve byte strings for share names (plus one for a nul terminator).
2072 Share names longer than 12 bytes must be skipped.
2073 ****************************************************************************/
2075 static bool api_RNetShareEnum(struct smbd_server_connection
*sconn
,
2076 connection_struct
*conn
, uint64_t vuid
,
2077 char *param
, int tpscnt
,
2078 char *data
, int tdscnt
,
2086 const struct loadparm_substitution
*lp_sub
=
2087 loadparm_s3_global_substitution();
2088 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2089 char *str2
= skip_string(param
,tpscnt
,str1
);
2090 char *p
= skip_string(param
,tpscnt
,str2
);
2091 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2092 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2095 int total
=0,counted
=0;
2096 bool missed
= False
;
2098 int data_len
, fixed_len
, string_len
;
2099 int f_len
= 0, s_len
= 0;
2101 if (!str1
|| !str2
|| !p
) {
2105 if (!prefix_ok(str1
,"WrLeh")) {
2108 if (!check_share_info(uLevel
,str2
)) {
2112 /* Ensure all the usershares are loaded. */
2114 delete_and_reload_printers();
2115 load_registry_shares();
2116 count
= load_usershare_shares(NULL
, connections_snum_used
);
2119 data_len
= fixed_len
= string_len
= 0;
2120 for (i
=0;i
<count
;i
++) {
2121 fstring servicename_dos
;
2122 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2125 push_ascii_fstring(servicename_dos
, lp_servicename(talloc_tos(), lp_sub
, i
));
2126 /* Maximum name length = 13. */
2127 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2129 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2130 if (data_len
< buf_len
) {
2133 string_len
+= s_len
;
2140 *rdata_len
= fixed_len
+ string_len
;
2141 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2146 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2151 for( i
= 0; i
< count
; i
++ ) {
2152 fstring servicename_dos
;
2153 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2157 push_ascii_fstring(servicename_dos
,
2158 lp_servicename(talloc_tos(), lp_sub
, i
));
2159 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2160 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2167 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2171 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2173 SSVAL(*rparam
,4,counted
);
2174 SSVAL(*rparam
,6,total
);
2176 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2177 counted
,total
,uLevel
,
2178 buf_len
,*rdata_len
,mdrcnt
));
2183 /****************************************************************************
2185 ****************************************************************************/
2187 static bool api_RNetShareAdd(struct smbd_server_connection
*sconn
,
2188 connection_struct
*conn
,uint64_t vuid
,
2189 char *param
, int tpscnt
,
2190 char *data
, int tdscnt
,
2191 int mdrcnt
,int mprcnt
,
2192 char **rdata
,char **rparam
,
2193 int *rdata_len
,int *rparam_len
)
2195 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2196 char *str2
= skip_string(param
,tpscnt
,str1
);
2197 char *p
= skip_string(param
,tpscnt
,str2
);
2198 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2201 char *pathname
= NULL
;
2202 unsigned int offset
;
2204 size_t converted_size
;
2206 WERROR werr
= WERR_OK
;
2207 TALLOC_CTX
*mem_ctx
= talloc_tos();
2209 struct rpc_pipe_client
*cli
= NULL
;
2210 union srvsvc_NetShareInfo info
;
2211 struct srvsvc_NetShareInfo2 info2
;
2212 struct dcerpc_binding_handle
*b
;
2214 if (!str1
|| !str2
|| !p
) {
2218 /* check it's a supported varient */
2219 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2222 if (!check_share_info(uLevel
,str2
)) {
2229 /* Do we have a string ? */
2230 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2233 pull_ascii_fstring(sharename
,data
);
2239 /* only support disk share adds */
2240 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2244 offset
= IVAL(data
, 16);
2245 if (offset
>= mdrcnt
) {
2246 res
= ERRinvalidparam
;
2250 /* Do we have a string ? */
2251 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2254 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2256 offset
= IVAL(data
, 26);
2258 if (offset
>= mdrcnt
) {
2259 res
= ERRinvalidparam
;
2263 /* Do we have a string ? */
2264 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2268 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2269 offset
? (data
+offset
) : "", &converted_size
))
2271 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2279 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
2281 conn
->sconn
->remote_address
,
2282 conn
->sconn
->local_address
,
2283 conn
->sconn
->msg_ctx
,
2285 if (!NT_STATUS_IS_OK(status
)) {
2286 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2287 nt_errstr(status
)));
2288 res
= W_ERROR_V(ntstatus_to_werror(status
));
2292 b
= cli
->binding_handle
;
2294 info2
.name
= sharename
;
2295 info2
.type
= STYPE_DISKTREE
;
2296 info2
.comment
= comment
;
2297 info2
.permissions
= 0;
2298 info2
.max_users
= 0;
2299 info2
.current_users
= 0;
2300 info2
.path
= pathname
;
2301 info2
.password
= NULL
;
2303 info
.info2
= &info2
;
2305 status
= dcerpc_srvsvc_NetShareAdd(b
, mem_ctx
,
2306 cli
->srv_name_slash
,
2311 if (!NT_STATUS_IS_OK(status
)) {
2312 res
= W_ERROR_V(ntstatus_to_werror(status
));
2315 if (!W_ERROR_IS_OK(werr
)) {
2316 res
= W_ERROR_V(werr
);
2321 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2325 SSVAL(*rparam
,0,NERR_Success
);
2326 SSVAL(*rparam
,2,0); /* converter word */
2327 SSVAL(*rparam
,4,*rdata_len
);
2335 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2340 SSVAL(*rparam
,0,res
);
2345 /****************************************************************************
2346 view list of groups available
2347 ****************************************************************************/
2349 static bool api_RNetGroupEnum(struct smbd_server_connection
*sconn
,
2350 connection_struct
*conn
,uint64_t vuid
,
2351 char *param
, int tpscnt
,
2352 char *data
, int tdscnt
,
2353 int mdrcnt
,int mprcnt
,
2354 char **rdata
,char **rparam
,
2355 int *rdata_len
,int *rparam_len
)
2359 int resume_context
, cli_buf_size
;
2360 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2361 char *str2
= skip_string(param
,tpscnt
,str1
);
2362 char *p
= skip_string(param
,tpscnt
,str2
);
2364 uint32_t num_groups
;
2365 uint32_t resume_handle
;
2366 struct rpc_pipe_client
*samr_pipe
= NULL
;
2367 struct policy_handle samr_handle
, domain_handle
;
2368 NTSTATUS status
, result
;
2369 struct dcerpc_binding_handle
*b
;
2371 if (!str1
|| !str2
|| !p
) {
2375 if (strcmp(str1
,"WrLeh") != 0) {
2380 * W-> resume context (number of users to skip)
2381 * r -> return parameter pointer to receive buffer
2382 * L -> length of receive buffer
2383 * e -> return parameter number of entries
2384 * h -> return parameter total number of users
2387 if (strcmp("B21",str2
) != 0) {
2391 status
= rpc_pipe_open_interface(
2392 talloc_tos(), &ndr_table_samr
,
2393 conn
->session_info
, conn
->sconn
->remote_address
,
2394 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2395 if (!NT_STATUS_IS_OK(status
)) {
2396 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2397 nt_errstr(status
)));
2401 b
= samr_pipe
->binding_handle
;
2403 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2404 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2406 if (!NT_STATUS_IS_OK(status
)) {
2407 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2408 nt_errstr(status
)));
2411 if (!NT_STATUS_IS_OK(result
)) {
2412 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2413 nt_errstr(result
)));
2417 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2418 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2419 get_global_sam_sid(), &domain_handle
,
2421 if (!NT_STATUS_IS_OK(status
)) {
2422 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2423 nt_errstr(status
)));
2424 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2427 if (!NT_STATUS_IS_OK(result
)) {
2428 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2429 nt_errstr(result
)));
2430 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2434 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2435 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2436 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2437 "%d\n", resume_context
, cli_buf_size
));
2439 *rdata_len
= cli_buf_size
;
2440 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2447 errflags
= NERR_Success
;
2452 struct samr_SamArray
*sam_entries
;
2453 uint32_t num_entries
;
2455 status
= dcerpc_samr_EnumDomainGroups(b
, talloc_tos(),
2461 if (!NT_STATUS_IS_OK(status
)) {
2462 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2463 "%s\n", nt_errstr(status
)));
2466 if (!NT_STATUS_IS_OK(result
)) {
2468 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2469 "%s\n", nt_errstr(result
)));
2473 if (num_entries
== 0) {
2474 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2475 "no entries -- done\n"));
2479 for(i
=0; i
<num_entries
; i
++) {
2482 name
= sam_entries
->entries
[i
].name
.string
;
2484 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2485 /* set overflow error */
2486 DEBUG(3,("overflow on entry %d group %s\n", i
,
2492 /* truncate the name at 21 chars. */
2494 strlcpy(p
, name
, 21);
2495 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2497 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2502 if (errflags
!= NERR_Success
) {
2506 TALLOC_FREE(sam_entries
);
2509 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2510 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2512 *rdata_len
= PTR_DIFF(p
,*rdata
);
2515 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2519 SSVAL(*rparam
, 0, errflags
);
2520 SSVAL(*rparam
, 2, 0); /* converter word */
2521 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2522 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2527 /*******************************************************************
2528 Get groups that a user is a member of.
2529 ******************************************************************/
2531 static bool api_NetUserGetGroups(struct smbd_server_connection
*sconn
,
2532 connection_struct
*conn
,uint64_t vuid
,
2533 char *param
, int tpscnt
,
2534 char *data
, int tdscnt
,
2535 int mdrcnt
,int mprcnt
,
2536 char **rdata
,char **rparam
,
2537 int *rdata_len
,int *rparam_len
)
2539 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2540 char *str2
= skip_string(param
,tpscnt
,str1
);
2541 char *UserName
= skip_string(param
,tpscnt
,str2
);
2542 char *p
= skip_string(param
,tpscnt
,UserName
);
2543 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2544 const char *level_string
;
2550 struct rpc_pipe_client
*samr_pipe
= NULL
;
2551 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2552 struct lsa_String name
;
2553 struct lsa_Strings names
;
2554 struct samr_Ids type
, rid
;
2555 struct samr_RidWithAttributeArray
*rids
;
2556 NTSTATUS status
, result
;
2557 struct dcerpc_binding_handle
*b
;
2559 if (!str1
|| !str2
|| !UserName
|| !p
) {
2564 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2569 /* check it's a supported varient */
2571 if ( strcmp(str1
,"zWrLeh") != 0 )
2576 level_string
= "B21";
2582 if (strcmp(level_string
,str2
) != 0)
2585 *rdata_len
= mdrcnt
+ 1024;
2586 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2591 SSVAL(*rparam
,0,NERR_Success
);
2592 SSVAL(*rparam
,2,0); /* converter word */
2595 endp
= *rdata
+ *rdata_len
;
2597 status
= rpc_pipe_open_interface(
2598 talloc_tos(), &ndr_table_samr
,
2599 conn
->session_info
, conn
->sconn
->remote_address
,
2600 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2601 if (!NT_STATUS_IS_OK(status
)) {
2602 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2603 nt_errstr(status
)));
2607 b
= samr_pipe
->binding_handle
;
2609 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2610 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2612 if (!NT_STATUS_IS_OK(status
)) {
2613 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2614 nt_errstr(status
)));
2617 if (!NT_STATUS_IS_OK(result
)) {
2618 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2619 nt_errstr(result
)));
2623 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2624 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2625 get_global_sam_sid(), &domain_handle
,
2627 if (!NT_STATUS_IS_OK(status
)) {
2628 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2629 nt_errstr(status
)));
2632 if (!NT_STATUS_IS_OK(result
)) {
2633 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2634 nt_errstr(result
)));
2638 name
.string
= UserName
;
2640 status
= dcerpc_samr_LookupNames(b
, talloc_tos(),
2641 &domain_handle
, 1, &name
,
2644 if (!NT_STATUS_IS_OK(status
)) {
2645 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2646 nt_errstr(status
)));
2649 if (!NT_STATUS_IS_OK(result
)) {
2650 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2651 nt_errstr(result
)));
2654 if (rid
.count
!= 1) {
2655 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2658 if (type
.count
!= 1) {
2659 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
2663 if (type
.ids
[0] != SID_NAME_USER
) {
2664 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2665 sid_type_lookup(type
.ids
[0])));
2669 status
= dcerpc_samr_OpenUser(b
, talloc_tos(),
2671 SAMR_USER_ACCESS_GET_GROUPS
,
2672 rid
.ids
[0], &user_handle
,
2674 if (!NT_STATUS_IS_OK(status
)) {
2675 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2676 nt_errstr(status
)));
2679 if (!NT_STATUS_IS_OK(result
)) {
2680 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2681 nt_errstr(result
)));
2685 status
= dcerpc_samr_GetGroupsForUser(b
, talloc_tos(),
2686 &user_handle
, &rids
,
2688 if (!NT_STATUS_IS_OK(status
)) {
2689 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2690 nt_errstr(status
)));
2693 if (!NT_STATUS_IS_OK(result
)) {
2694 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2695 nt_errstr(result
)));
2699 for (i
=0; i
<rids
->count
; i
++) {
2701 status
= dcerpc_samr_LookupRids(b
, talloc_tos(),
2703 1, &rids
->rids
[i
].rid
,
2706 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
) && (names
.count
== 1)) {
2707 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2713 *rdata_len
= PTR_DIFF(p
,*rdata
);
2715 SSVAL(*rparam
,4,count
); /* is this right?? */
2716 SSVAL(*rparam
,6,count
); /* is this right?? */
2721 dcerpc_samr_Close(b
, talloc_tos(), &user_handle
, &result
);
2723 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2725 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2730 /*******************************************************************
2732 ******************************************************************/
2734 static bool api_RNetUserEnum(struct smbd_server_connection
*sconn
,
2735 connection_struct
*conn
, uint64_t vuid
,
2736 char *param
, int tpscnt
,
2737 char *data
, int tdscnt
,
2738 int mdrcnt
,int mprcnt
,
2739 char **rdata
,char **rparam
,
2740 int *rdata_len
,int *rparam_len
)
2745 int i
, resume_context
, cli_buf_size
;
2746 uint32_t resume_handle
;
2748 struct rpc_pipe_client
*samr_pipe
= NULL
;
2749 struct policy_handle samr_handle
, domain_handle
;
2750 NTSTATUS status
, result
;
2752 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2753 char *str2
= skip_string(param
,tpscnt
,str1
);
2754 char *p
= skip_string(param
,tpscnt
,str2
);
2757 struct dcerpc_binding_handle
*b
;
2759 if (!str1
|| !str2
|| !p
) {
2763 if (strcmp(str1
,"WrLeh") != 0)
2766 * W-> resume context (number of users to skip)
2767 * r -> return parameter pointer to receive buffer
2768 * L -> length of receive buffer
2769 * e -> return parameter number of entries
2770 * h -> return parameter total number of users
2773 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2774 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2775 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2776 resume_context
, cli_buf_size
));
2779 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2784 /* check it's a supported varient */
2785 if (strcmp("B21",str2
) != 0)
2788 *rdata_len
= cli_buf_size
;
2789 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2795 endp
= *rdata
+ *rdata_len
;
2797 status
= rpc_pipe_open_interface(
2798 talloc_tos(), &ndr_table_samr
,
2799 conn
->session_info
, conn
->sconn
->remote_address
,
2800 conn
->sconn
->local_address
, conn
->sconn
->msg_ctx
, &samr_pipe
);
2801 if (!NT_STATUS_IS_OK(status
)) {
2802 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2803 nt_errstr(status
)));
2807 b
= samr_pipe
->binding_handle
;
2809 status
= dcerpc_samr_Connect2(b
, talloc_tos(), lp_netbios_name(),
2810 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
,
2812 if (!NT_STATUS_IS_OK(status
)) {
2813 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2814 nt_errstr(status
)));
2817 if (!NT_STATUS_IS_OK(result
)) {
2818 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2819 nt_errstr(result
)));
2823 status
= dcerpc_samr_OpenDomain(b
, talloc_tos(), &samr_handle
,
2824 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2825 get_global_sam_sid(), &domain_handle
,
2827 if (!NT_STATUS_IS_OK(status
)) {
2828 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2829 nt_errstr(status
)));
2830 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2833 if (!NT_STATUS_IS_OK(result
)) {
2834 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2835 nt_errstr(result
)));
2836 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2840 errflags
=NERR_Success
;
2845 struct samr_SamArray
*sam_entries
;
2846 uint32_t num_entries
;
2848 status
= dcerpc_samr_EnumDomainUsers(b
, talloc_tos(),
2855 if (!NT_STATUS_IS_OK(status
)) {
2856 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2857 "%s\n", nt_errstr(status
)));
2860 if (!NT_STATUS_IS_OK(result
)) {
2861 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2862 "%s\n", nt_errstr(result
)));
2866 if (num_entries
== 0) {
2867 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2868 "no entries -- done\n"));
2872 for (i
=0; i
<num_entries
; i
++) {
2875 name
= sam_entries
->entries
[i
].name
.string
;
2877 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2878 &&(strlen(name
)<=21)) {
2879 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2880 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2881 "username %s\n",count_sent
,p
));
2885 /* set overflow error */
2886 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2887 "username %s\n",count_sent
,name
));
2893 if (errflags
!= NERR_Success
) {
2897 TALLOC_FREE(sam_entries
);
2900 dcerpc_samr_Close(b
, talloc_tos(), &domain_handle
, &result
);
2901 dcerpc_samr_Close(b
, talloc_tos(), &samr_handle
, &result
);
2903 *rdata_len
= PTR_DIFF(p
,*rdata
);
2905 SSVAL(*rparam
,0,errflags
);
2906 SSVAL(*rparam
,2,0); /* converter word */
2907 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2908 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2913 /****************************************************************************
2914 Get the time of day info.
2915 ****************************************************************************/
2917 static bool api_NetRemoteTOD(struct smbd_server_connection
*sconn
,
2918 connection_struct
*conn
,uint64_t vuid
,
2919 char *param
, int tpscnt
,
2920 char *data
, int tdscnt
,
2921 int mdrcnt
,int mprcnt
,
2922 char **rdata
,char **rparam
,
2923 int *rdata_len
,int *rparam_len
)
2926 time_t unixdate
= time(NULL
);
2930 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2936 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2941 SSVAL(*rparam
,0,NERR_Success
);
2942 SSVAL(*rparam
,2,0); /* converter word */
2946 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2947 by NT in a "net time" operation,
2948 it seems to ignore the one below */
2950 /* the client expects to get localtime, not GMT, in this bit
2951 (I think, this needs testing) */
2952 t
= localtime(&unixdate
);
2957 SIVAL(p
,4,0); /* msecs ? */
2958 SCVAL(p
,8,t
->tm_hour
);
2959 SCVAL(p
,9,t
->tm_min
);
2960 SCVAL(p
,10,t
->tm_sec
);
2961 SCVAL(p
,11,0); /* hundredths of seconds */
2962 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2963 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2964 SCVAL(p
,16,t
->tm_mday
);
2965 SCVAL(p
,17,t
->tm_mon
+ 1);
2966 SSVAL(p
,18,1900+t
->tm_year
);
2967 SCVAL(p
,20,t
->tm_wday
);
2972 /****************************************************************************
2973 Set the user password (SamOEM version - gets plaintext).
2974 ****************************************************************************/
2976 static bool api_SamOEMChangePassword(struct smbd_server_connection
*sconn
,
2977 connection_struct
*conn
,uint64_t vuid
,
2978 char *param
, int tpscnt
,
2979 char *data
, int tdscnt
,
2980 int mdrcnt
,int mprcnt
,
2981 char **rdata
,char **rparam
,
2982 int *rdata_len
,int *rparam_len
)
2985 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2987 TALLOC_CTX
*mem_ctx
= talloc_tos();
2988 NTSTATUS status
, result
;
2989 struct rpc_pipe_client
*cli
= NULL
;
2990 struct lsa_AsciiString server
, account
;
2991 struct samr_CryptPassword password
;
2992 struct samr_Password hash
;
2993 int errcode
= NERR_badpass
;
2995 struct dcerpc_binding_handle
*b
;
2998 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3008 SSVAL(*rparam
,0,NERR_badpass
);
3011 * Check the parameter definition is correct.
3014 /* Do we have a string ? */
3015 if (skip_string(param
,tpscnt
,p
) == 0) {
3018 if(!strequal(p
, "zsT")) {
3019 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
3022 p
= skip_string(param
, tpscnt
, p
);
3027 /* Do we have a string ? */
3028 if (skip_string(param
,tpscnt
,p
) == 0) {
3031 if(!strequal(p
, "B516B16")) {
3032 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
3035 p
= skip_string(param
,tpscnt
,p
);
3039 /* Do we have a string ? */
3040 if (skip_string(param
,tpscnt
,p
) == 0) {
3043 p
+= pull_ascii_fstring(user
,p
);
3045 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
3047 if (tdscnt
!= 532) {
3048 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3052 bufsize
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3053 if (bufsize
!= 532) {
3054 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3058 memcpy(password
.data
, data
, 516);
3059 memcpy(hash
.hash
, data
+516, 16);
3061 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
3063 conn
->sconn
->remote_address
,
3064 conn
->sconn
->local_address
,
3065 conn
->sconn
->msg_ctx
,
3067 if (!NT_STATUS_IS_OK(status
)) {
3068 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3069 nt_errstr(status
)));
3070 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3074 b
= cli
->binding_handle
;
3076 init_lsa_AsciiString(&server
, lp_netbios_name());
3077 init_lsa_AsciiString(&account
, user
);
3079 status
= dcerpc_samr_OemChangePasswordUser2(b
, mem_ctx
,
3085 if (!NT_STATUS_IS_OK(status
)) {
3086 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3089 if (!NT_STATUS_IS_OK(result
)) {
3090 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
3094 errcode
= NERR_Success
;
3096 SSVAL(*rparam
,0,errcode
);
3097 SSVAL(*rparam
,2,0); /* converter word */
3102 /****************************************************************************
3105 ****************************************************************************/
3107 static bool api_RDosPrintJobDel(struct smbd_server_connection
*sconn
,
3108 connection_struct
*conn
,uint64_t vuid
,
3109 char *param
, int tpscnt
,
3110 char *data
, int tdscnt
,
3111 int mdrcnt
,int mprcnt
,
3112 char **rdata
,char **rparam
,
3113 int *rdata_len
,int *rparam_len
)
3115 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3116 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3117 char *str2
= skip_string(param
,tpscnt
,str1
);
3118 char *p
= skip_string(param
,tpscnt
,str2
);
3122 WERROR werr
= WERR_OK
;
3124 TALLOC_CTX
*mem_ctx
= talloc_tos();
3126 struct rpc_pipe_client
*cli
= NULL
;
3127 struct dcerpc_binding_handle
*b
= NULL
;
3128 struct policy_handle handle
;
3129 struct spoolss_DevmodeContainer devmode_ctr
;
3130 enum spoolss_JobControl command
;
3132 if (!str1
|| !str2
|| !p
) {
3136 * We use 1 here not 2 as we're checking
3137 * the last byte we want to access is safe.
3139 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3142 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3145 /* check it's a supported varient */
3146 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
3150 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3156 ZERO_STRUCT(handle
);
3158 status
= rpc_pipe_open_interface(mem_ctx
,
3161 conn
->sconn
->remote_address
,
3162 conn
->sconn
->local_address
,
3163 conn
->sconn
->msg_ctx
,
3165 if (!NT_STATUS_IS_OK(status
)) {
3166 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3167 nt_errstr(status
)));
3168 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3171 b
= cli
->binding_handle
;
3173 ZERO_STRUCT(devmode_ctr
);
3175 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3179 JOB_ACCESS_ADMINISTER
,
3182 if (!NT_STATUS_IS_OK(status
)) {
3183 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3186 if (!W_ERROR_IS_OK(werr
)) {
3187 errcode
= W_ERROR_V(werr
);
3191 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3192 * and NERR_DestNotFound if share did not exist */
3194 errcode
= NERR_Success
;
3197 case 81: /* delete */
3198 command
= SPOOLSS_JOB_CONTROL_DELETE
;
3200 case 82: /* pause */
3201 command
= SPOOLSS_JOB_CONTROL_PAUSE
;
3203 case 83: /* resume */
3204 command
= SPOOLSS_JOB_CONTROL_RESUME
;
3207 errcode
= NERR_notsupported
;
3211 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3214 NULL
, /* unique ptr ctr */
3217 if (!NT_STATUS_IS_OK(status
)) {
3218 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3221 if (!W_ERROR_IS_OK(werr
)) {
3222 errcode
= W_ERROR_V(werr
);
3227 if (b
&& is_valid_policy_hnd(&handle
)) {
3228 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3231 SSVAL(*rparam
,0,errcode
);
3232 SSVAL(*rparam
,2,0); /* converter word */
3237 /****************************************************************************
3238 Purge a print queue - or pause or resume it.
3239 ****************************************************************************/
3241 static bool api_WPrintQueueCtrl(struct smbd_server_connection
*sconn
,
3242 connection_struct
*conn
,uint64_t vuid
,
3243 char *param
, int tpscnt
,
3244 char *data
, int tdscnt
,
3245 int mdrcnt
,int mprcnt
,
3246 char **rdata
,char **rparam
,
3247 int *rdata_len
,int *rparam_len
)
3249 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3250 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3251 char *str2
= skip_string(param
,tpscnt
,str1
);
3252 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3253 int errcode
= NERR_notsupported
;
3254 WERROR werr
= WERR_OK
;
3257 TALLOC_CTX
*mem_ctx
= talloc_tos();
3258 struct rpc_pipe_client
*cli
= NULL
;
3259 struct dcerpc_binding_handle
*b
= NULL
;
3260 struct policy_handle handle
;
3261 struct spoolss_SetPrinterInfoCtr info_ctr
;
3262 struct spoolss_DevmodeContainer devmode_ctr
;
3263 struct sec_desc_buf secdesc_ctr
;
3264 enum spoolss_PrinterControl command
= SPOOLSS_PRINTER_CONTROL_UNPAUSE
;
3266 if (!str1
|| !str2
|| !QueueName
) {
3270 /* check it's a supported varient */
3271 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3275 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3281 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3285 ZERO_STRUCT(handle
);
3287 status
= rpc_pipe_open_interface(mem_ctx
,
3290 conn
->sconn
->remote_address
,
3291 conn
->sconn
->local_address
,
3292 conn
->sconn
->msg_ctx
,
3294 if (!NT_STATUS_IS_OK(status
)) {
3295 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3296 nt_errstr(status
)));
3297 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3300 b
= cli
->binding_handle
;
3302 ZERO_STRUCT(devmode_ctr
);
3304 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3308 PRINTER_ACCESS_ADMINISTER
,
3311 if (!NT_STATUS_IS_OK(status
)) {
3312 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3315 if (!W_ERROR_IS_OK(werr
)) {
3316 errcode
= W_ERROR_V(werr
);
3321 case 74: /* Pause queue */
3322 command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3324 case 75: /* Resume queue */
3325 command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3327 case 103: /* Purge */
3328 command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3331 werr
= WERR_NOT_SUPPORTED
;
3335 if (!W_ERROR_IS_OK(werr
)) {
3336 errcode
= W_ERROR_V(werr
);
3340 ZERO_STRUCT(info_ctr
);
3341 ZERO_STRUCT(secdesc_ctr
);
3343 status
= dcerpc_spoolss_SetPrinter(b
, mem_ctx
,
3350 if (!NT_STATUS_IS_OK(status
)) {
3351 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3354 if (!W_ERROR_IS_OK(werr
)) {
3355 errcode
= W_ERROR_V(werr
);
3359 errcode
= W_ERROR_V(werr
);
3363 if (b
&& is_valid_policy_hnd(&handle
)) {
3364 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3367 SSVAL(*rparam
,0,errcode
);
3368 SSVAL(*rparam
,2,0); /* converter word */
3373 /****************************************************************************
3374 set the property of a print job (undocumented?)
3375 ? function = 0xb -> set name of print job
3376 ? function = 0x6 -> move print job up/down
3377 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3378 or <WWsTP> <WB21BB16B10zWWzDDz>
3379 ****************************************************************************/
3381 static int check_printjob_info(struct pack_desc
* desc
,
3382 int uLevel
, char* id
)
3384 desc
->subformat
= NULL
;
3386 case 0: desc
->format
= "W"; break;
3387 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3388 case 2: desc
->format
= "WWzWWDDzz"; break;
3389 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3390 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3392 DEBUG(0,("check_printjob_info: invalid level %d\n",
3396 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3397 DEBUG(0,("check_printjob_info: invalid format %s\n",
3398 id
? id
: "<NULL>" ));
3404 static bool api_PrintJobInfo(struct smbd_server_connection
*sconn
,
3405 connection_struct
*conn
, uint64_t vuid
,
3406 char *param
, int tpscnt
,
3407 char *data
, int tdscnt
,
3408 int mdrcnt
,int mprcnt
,
3409 char **rdata
,char **rparam
,
3410 int *rdata_len
,int *rparam_len
)
3412 struct pack_desc desc
;
3413 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3414 char *str2
= skip_string(param
,tpscnt
,str1
);
3415 char *p
= skip_string(param
,tpscnt
,str2
);
3418 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3419 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3422 TALLOC_CTX
*mem_ctx
= talloc_tos();
3425 struct rpc_pipe_client
*cli
= NULL
;
3426 struct dcerpc_binding_handle
*b
= NULL
;
3427 struct policy_handle handle
;
3428 struct spoolss_DevmodeContainer devmode_ctr
;
3429 struct spoolss_JobInfoContainer ctr
;
3430 union spoolss_JobInfo info
;
3431 struct spoolss_SetJobInfo1 info1
;
3433 if (!str1
|| !str2
|| !p
) {
3437 * We use 1 here not 2 as we're checking
3438 * the last byte we want to access is safe.
3440 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3443 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3446 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3453 /* check it's a supported varient */
3454 if ((strcmp(str1
,"WWsTP")) ||
3455 (!check_printjob_info(&desc
,uLevel
,str2
)))
3458 errcode
= NERR_notsupported
;
3462 /* change print job name, data gives the name */
3468 ZERO_STRUCT(handle
);
3470 status
= rpc_pipe_open_interface(mem_ctx
,
3473 conn
->sconn
->remote_address
,
3474 conn
->sconn
->local_address
,
3475 conn
->sconn
->msg_ctx
,
3477 if (!NT_STATUS_IS_OK(status
)) {
3478 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3479 nt_errstr(status
)));
3480 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3483 b
= cli
->binding_handle
;
3485 ZERO_STRUCT(devmode_ctr
);
3487 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
3494 if (!NT_STATUS_IS_OK(status
)) {
3495 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3498 if (!W_ERROR_IS_OK(werr
)) {
3499 errcode
= W_ERROR_V(werr
);
3503 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
3509 if (!W_ERROR_IS_OK(werr
)) {
3510 errcode
= W_ERROR_V(werr
);
3516 info1
.job_id
= info
.info1
.job_id
;
3517 info1
.printer_name
= info
.info1
.printer_name
;
3518 info1
.user_name
= info
.info1
.user_name
;
3519 info1
.document_name
= data
;
3520 info1
.data_type
= info
.info1
.data_type
;
3521 info1
.text_status
= info
.info1
.text_status
;
3522 info1
.status
= info
.info1
.status
;
3523 info1
.priority
= info
.info1
.priority
;
3524 info1
.position
= info
.info1
.position
;
3525 info1
.total_pages
= info
.info1
.total_pages
;
3526 info1
.pages_printed
= info
.info1
.pages_printed
;
3527 info1
.submitted
= info
.info1
.submitted
;
3530 ctr
.info
.info1
= &info1
;
3532 status
= dcerpc_spoolss_SetJob(b
, mem_ctx
,
3538 if (!NT_STATUS_IS_OK(status
)) {
3539 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3542 if (!W_ERROR_IS_OK(werr
)) {
3543 errcode
= W_ERROR_V(werr
);
3547 errcode
= NERR_Success
;
3550 if (b
&& is_valid_policy_hnd(&handle
)) {
3551 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
3554 SSVALS(*rparam
,0,errcode
);
3555 SSVAL(*rparam
,2,0); /* converter word */
3561 /****************************************************************************
3562 Get info about the server.
3563 ****************************************************************************/
3565 static bool api_RNetServerGetInfo(struct smbd_server_connection
*sconn
,
3566 connection_struct
*conn
,uint64_t vuid
,
3567 char *param
, int tpscnt
,
3568 char *data
, int tdscnt
,
3569 int mdrcnt
,int mprcnt
,
3570 char **rdata
,char **rparam
,
3571 int *rdata_len
,int *rparam_len
)
3573 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3574 char *str2
= skip_string(param
,tpscnt
,str1
);
3575 char *p
= skip_string(param
,tpscnt
,str2
);
3576 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3582 TALLOC_CTX
*mem_ctx
= talloc_tos();
3583 struct rpc_pipe_client
*cli
= NULL
;
3584 union srvsvc_NetSrvInfo info
;
3586 struct dcerpc_binding_handle
*b
;
3588 if (!str1
|| !str2
|| !p
) {
3592 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3594 /* check it's a supported varient */
3595 if (!prefix_ok(str1
,"WrLh")) {
3601 if (strcmp(str2
,"B16") != 0) {
3607 if (strcmp(str2
,"B16BBDz") != 0) {
3613 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3619 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3625 if (strcmp(str2
,"DN") != 0) {
3631 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3640 *rdata_len
= mdrcnt
;
3641 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3647 p2
= p
+ struct_len
;
3649 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_srvsvc
,
3651 conn
->sconn
->remote_address
,
3652 conn
->sconn
->local_address
,
3653 conn
->sconn
->msg_ctx
,
3655 if (!NT_STATUS_IS_OK(status
)) {
3656 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3657 nt_errstr(status
)));
3658 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3662 b
= cli
->binding_handle
;
3664 status
= dcerpc_srvsvc_NetSrvGetInfo(b
, mem_ctx
,
3669 if (!NT_STATUS_IS_OK(status
)) {
3670 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3673 if (!W_ERROR_IS_OK(werr
)) {
3674 errcode
= W_ERROR_V(werr
);
3678 if (info
.info101
== NULL
) {
3679 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
3685 status
= srvstr_push(NULL
, 0, p
, info
.info101
->server_name
, 16,
3686 STR_ASCII
|STR_UPPER
|STR_TERMINATE
, &len
);
3687 if (!NT_STATUS_IS_OK(status
)) {
3688 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
3694 SCVAL(p
,0,info
.info101
->version_major
);
3695 SCVAL(p
,1,info
.info101
->version_minor
);
3696 SIVAL(p
,2,info
.info101
->server_type
);
3698 if (mdrcnt
== struct_len
) {
3701 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3702 if (mdrcnt
- struct_len
<= 0) {
3706 info
.info101
->comment
,
3707 MIN(mdrcnt
- struct_len
,
3708 MAX_SERVER_STRING_LENGTH
),
3710 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3718 return False
; /* not yet implemented */
3721 errcode
= NERR_Success
;
3725 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3728 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3732 SSVAL(*rparam
,0,errcode
);
3733 SSVAL(*rparam
,2,0); /* converter word */
3734 SSVAL(*rparam
,4,*rdata_len
);
3739 /****************************************************************************
3740 Get info about the server.
3741 ****************************************************************************/
3743 static bool api_NetWkstaGetInfo(struct smbd_server_connection
*sconn
,
3744 connection_struct
*conn
,uint64_t vuid
,
3745 char *param
, int tpscnt
,
3746 char *data
, int tdscnt
,
3747 int mdrcnt
,int mprcnt
,
3748 char **rdata
,char **rparam
,
3749 int *rdata_len
,int *rparam_len
)
3751 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3752 char *str2
= skip_string(param
,tpscnt
,str1
);
3753 char *p
= skip_string(param
,tpscnt
,str2
);
3756 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3758 if (!str1
|| !str2
|| !p
) {
3762 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3765 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3770 /* check it's a supported varient */
3771 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3775 *rdata_len
= mdrcnt
+ 1024;
3776 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3781 SSVAL(*rparam
,0,NERR_Success
);
3782 SSVAL(*rparam
,2,0); /* converter word */
3785 endp
= *rdata
+ *rdata_len
;
3787 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3792 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3793 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3794 if (!strupper_m(p2
)) {
3797 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3803 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3804 strlcpy(p2
,conn
->session_info
->unix_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3805 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3811 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3812 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3813 if (!strupper_m(p2
)) {
3816 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3822 SCVAL(p
,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g 4 in 4.1 */
3823 SCVAL(p
,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION
); /* system version - e.g .1 in 4.1 */
3826 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3827 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3828 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3834 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3835 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3836 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3842 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3844 SSVAL(*rparam
,4,*rdata_len
);
3849 /****************************************************************************
3850 get info about a user
3852 struct user_info_11 {
3853 char usri11_name[21]; 0-20
3855 char *usri11_comment; 22-25
3856 char *usri11_usr_comment; 26-29
3857 unsigned short usri11_priv; 30-31
3858 unsigned long usri11_auth_flags; 32-35
3859 long usri11_password_age; 36-39
3860 char *usri11_homedir; 40-43
3861 char *usri11_parms; 44-47
3862 long usri11_last_logon; 48-51
3863 long usri11_last_logoff; 52-55
3864 unsigned short usri11_bad_pw_count; 56-57
3865 unsigned short usri11_num_logons; 58-59
3866 char *usri11_logon_server; 60-63
3867 unsigned short usri11_country_code; 64-65
3868 char *usri11_workstations; 66-69
3869 unsigned long usri11_max_storage; 70-73
3870 unsigned short usri11_units_per_week; 74-75
3871 unsigned char *usri11_logon_hours; 76-79
3872 unsigned short usri11_code_page; 80-81
3877 usri11_name specifies the user name for which information is retrieved
3879 usri11_pad aligns the next data structure element to a word boundary
3881 usri11_comment is a null terminated ASCII comment
3883 usri11_user_comment is a null terminated ASCII comment about the user
3885 usri11_priv specifies the level of the privilege assigned to the user.
3886 The possible values are:
3888 Name Value Description
3889 USER_PRIV_GUEST 0 Guest privilege
3890 USER_PRIV_USER 1 User privilege
3891 USER_PRV_ADMIN 2 Administrator privilege
3893 usri11_auth_flags specifies the account operator privileges. The
3894 possible values are:
3896 Name Value Description
3897 AF_OP_PRINT 0 Print operator
3900 Leach, Naik [Page 28]
3904 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3907 AF_OP_COMM 1 Communications operator
3908 AF_OP_SERVER 2 Server operator
3909 AF_OP_ACCOUNTS 3 Accounts operator
3912 usri11_password_age specifies how many seconds have elapsed since the
3913 password was last changed.
3915 usri11_home_dir points to a null terminated ASCII string that contains
3916 the path name of the user's home directory.
3918 usri11_parms points to a null terminated ASCII string that is set
3919 aside for use by applications.
3921 usri11_last_logon specifies the time when the user last logged on.
3922 This value is stored as the number of seconds elapsed since
3923 00:00:00, January 1, 1970.
3925 usri11_last_logoff specifies the time when the user last logged off.
3926 This value is stored as the number of seconds elapsed since
3927 00:00:00, January 1, 1970. A value of 0 means the last logoff
3930 usri11_bad_pw_count specifies the number of incorrect passwords
3931 entered since the last successful logon.
3933 usri11_log1_num_logons specifies the number of times this user has
3934 logged on. A value of -1 means the number of logons is unknown.
3936 usri11_logon_server points to a null terminated ASCII string that
3937 contains the name of the server to which logon requests are sent.
3938 A null string indicates logon requests should be sent to the
3941 usri11_country_code specifies the country code for the user's language
3944 usri11_workstations points to a null terminated ASCII string that
3945 contains the names of workstations the user may log on from.
3946 There may be up to 8 workstations, with the names separated by
3947 commas. A null strings indicates there are no restrictions.
3949 usri11_max_storage specifies the maximum amount of disk space the user
3950 can occupy. A value of 0xffffffff indicates there are no
3953 usri11_units_per_week specifies the equal number of time units into
3954 which a week is divided. This value must be equal to 168.
3956 usri11_logon_hours points to a 21 byte (168 bits) string that
3957 specifies the time during which the user can log on. Each bit
3958 represents one unique hour in a week. The first bit (bit 0, word
3959 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3963 Leach, Naik [Page 29]
3967 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3970 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3971 are no restrictions.
3973 usri11_code_page specifies the code page for the user's language of
3976 All of the pointers in this data structure need to be treated
3977 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3978 to be ignored. The converter word returned in the parameters section
3979 needs to be subtracted from the lower 16 bits to calculate an offset
3980 into the return buffer where this ASCII string resides.
3982 There is no auxiliary data in the response.
3984 ****************************************************************************/
3986 #define usri11_name 0
3987 #define usri11_pad 21
3988 #define usri11_comment 22
3989 #define usri11_usr_comment 26
3990 #define usri11_full_name 30
3991 #define usri11_priv 34
3992 #define usri11_auth_flags 36
3993 #define usri11_password_age 40
3994 #define usri11_homedir 44
3995 #define usri11_parms 48
3996 #define usri11_last_logon 52
3997 #define usri11_last_logoff 56
3998 #define usri11_bad_pw_count 60
3999 #define usri11_num_logons 62
4000 #define usri11_logon_server 64
4001 #define usri11_country_code 68
4002 #define usri11_workstations 70
4003 #define usri11_max_storage 74
4004 #define usri11_units_per_week 78
4005 #define usri11_logon_hours 80
4006 #define usri11_code_page 84
4007 #define usri11_end 86
4009 static bool api_RNetUserGetInfo(struct smbd_server_connection
*sconn
,
4010 connection_struct
*conn
, uint64_t vuid
,
4011 char *param
, int tpscnt
,
4012 char *data
, int tdscnt
,
4013 int mdrcnt
,int mprcnt
,
4014 char **rdata
,char **rparam
,
4015 int *rdata_len
,int *rparam_len
)
4017 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4018 char *str2
= skip_string(param
,tpscnt
,str1
);
4019 char *UserName
= skip_string(param
,tpscnt
,str2
);
4020 char *p
= skip_string(param
,tpscnt
,UserName
);
4021 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4024 const char *level_string
;
4026 TALLOC_CTX
*mem_ctx
= talloc_tos();
4027 NTSTATUS status
, result
;
4028 struct rpc_pipe_client
*cli
= NULL
;
4029 struct policy_handle connect_handle
, domain_handle
, user_handle
;
4030 struct lsa_String domain_name
;
4031 struct dom_sid2
*domain_sid
;
4032 struct lsa_String names
;
4033 struct samr_Ids rids
;
4034 struct samr_Ids types
;
4035 int errcode
= W_ERROR_V(WERR_NERR_USERNOTFOUND
);
4037 union samr_UserInfo
*info
;
4038 struct dcerpc_binding_handle
*b
= NULL
;
4040 if (!str1
|| !str2
|| !UserName
|| !p
) {
4045 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4050 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
4052 /* check it's a supported variant */
4053 if (strcmp(str1
,"zWrLh") != 0) {
4057 case 0: level_string
= "B21"; break;
4058 case 1: level_string
= "B21BB16DWzzWz"; break;
4059 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4060 case 10: level_string
= "B21Bzzz"; break;
4061 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4062 default: return False
;
4065 if (strcmp(level_string
,str2
) != 0) {
4069 *rdata_len
= mdrcnt
+ 1024;
4070 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
4076 endp
= *rdata
+ *rdata_len
;
4077 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
4082 ZERO_STRUCT(connect_handle
);
4083 ZERO_STRUCT(domain_handle
);
4084 ZERO_STRUCT(user_handle
);
4086 status
= rpc_pipe_open_interface(mem_ctx
, &ndr_table_samr
,
4088 conn
->sconn
->remote_address
,
4089 conn
->sconn
->local_address
,
4090 conn
->sconn
->msg_ctx
,
4092 if (!NT_STATUS_IS_OK(status
)) {
4093 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4094 nt_errstr(status
)));
4095 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4099 b
= cli
->binding_handle
;
4101 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
4103 SAMR_ACCESS_CONNECT_TO_SERVER
|
4104 SAMR_ACCESS_ENUM_DOMAINS
|
4105 SAMR_ACCESS_LOOKUP_DOMAIN
,
4108 if (!NT_STATUS_IS_OK(status
)) {
4109 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4112 if (!NT_STATUS_IS_OK(result
)) {
4113 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4117 init_lsa_String(&domain_name
, get_global_sam_name());
4119 status
= dcerpc_samr_LookupDomain(b
, mem_ctx
,
4124 if (!NT_STATUS_IS_OK(status
)) {
4125 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4128 if (!NT_STATUS_IS_OK(result
)) {
4129 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4133 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
4135 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
4139 if (!NT_STATUS_IS_OK(status
)) {
4140 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4143 if (!NT_STATUS_IS_OK(result
)) {
4144 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4148 init_lsa_String(&names
, UserName
);
4150 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
4157 if (!NT_STATUS_IS_OK(status
)) {
4158 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4161 if (!NT_STATUS_IS_OK(result
)) {
4162 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4166 if (rids
.count
!= 1) {
4167 errcode
= W_ERROR_V(WERR_NO_SUCH_USER
);
4170 if (rids
.count
!= types
.count
) {
4171 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4174 if (types
.ids
[0] != SID_NAME_USER
) {
4175 errcode
= W_ERROR_V(WERR_INVALID_PARAMETER
);
4181 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
4183 SAMR_USER_ACCESS_GET_LOCALE
|
4184 SAMR_USER_ACCESS_GET_LOGONINFO
|
4185 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
4186 SAMR_USER_ACCESS_GET_GROUPS
|
4187 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP
|
4188 SEC_STD_READ_CONTROL
,
4192 if (!NT_STATUS_IS_OK(status
)) {
4193 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4196 if (!NT_STATUS_IS_OK(result
)) {
4197 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4201 status
= dcerpc_samr_QueryUserInfo2(b
, mem_ctx
,
4206 if (!NT_STATUS_IS_OK(status
)) {
4207 errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4210 if (!NT_STATUS_IS_OK(result
)) {
4211 errcode
= W_ERROR_V(ntstatus_to_werror(result
));
4216 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
4219 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
4224 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
4225 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
4226 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4231 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
4232 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
4233 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4238 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4239 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
4240 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4241 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4248 const char *homedir
= info
->info21
.home_directory
.string
;
4249 /* modelled after NTAS 3.51 reply */
4250 SSVAL(p
,usri11_priv
,
4251 (get_current_uid(conn
) == sec_initial_uid())?
4252 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4253 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
4254 SIVALS(p
,usri11_password_age
,-1); /* password age */
4255 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
4256 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
4257 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4261 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
4262 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4263 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4267 SIVAL(p
,usri11_last_logon
,0); /* last logon */
4268 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
4269 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
4270 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
4271 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
4272 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
4273 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4277 SSVAL(p
,usri11_country_code
,0); /* country code */
4279 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
4280 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4281 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4286 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
4287 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
4288 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
4290 /* a simple way to get logon hours at all times. */
4292 SCVAL(p2
,21,0); /* fix zero termination */
4293 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4298 SSVAL(p
,usri11_code_page
,0); /* code page */
4301 if (uLevel
== 1 || uLevel
== 2) {
4302 memset(p
+22,' ',16); /* password */
4303 SIVALS(p
,38,-1); /* password age */
4305 (get_current_uid(conn
) == sec_initial_uid())?
4306 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4307 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
4308 strlcpy(p2
, info
->info21
.home_directory
.string
,
4310 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4314 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
4316 SSVAL(p
,52,0); /* flags */
4317 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
4318 strlcpy(p2
, info
->info21
.logon_script
.string
,
4320 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4325 SIVAL(p
,58,0); /* auth_flags */
4326 SIVAL(p
,62,PTR_DIFF(p2
,*rdata
)); /* full_name */
4327 strlcpy(p2
,info
->info21
.full_name
.string
,PTR_DIFF(endp
,p2
));
4328 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4332 SIVAL(p
,66,0); /* urs_comment */
4333 SIVAL(p
,70,PTR_DIFF(p2
,*rdata
)); /* parms */
4334 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
4335 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4339 SIVAL(p
,74,0); /* workstations */
4340 SIVAL(p
,78,0); /* last_logon */
4341 SIVAL(p
,82,0); /* last_logoff */
4342 SIVALS(p
,86,-1); /* acct_expires */
4343 SIVALS(p
,90,-1); /* max_storage */
4344 SSVAL(p
,94,168); /* units_per_week */
4345 SIVAL(p
,96,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
4348 SSVALS(p
,100,-1); /* bad_pw_count */
4349 SSVALS(p
,102,-1); /* num_logons */
4350 SIVAL(p
,104,PTR_DIFF(p2
,*rdata
)); /* logon_server */
4352 TALLOC_CTX
*ctx
= talloc_tos();
4353 int space_rem
= *rdata_len
- (p2
- *rdata
);
4356 if (space_rem
<= 0) {
4359 tmp
= talloc_strdup(ctx
, "\\\\%L");
4363 tmp
= talloc_sub_basic(ctx
,
4376 p2
= skip_string(*rdata
,*rdata_len
,p2
);
4380 SSVAL(p
,108,49); /* country_code */
4381 SSVAL(p
,110,860); /* code page */
4385 errcode
= NERR_Success
;
4388 *rdata_len
= PTR_DIFF(p2
,*rdata
);
4390 if (b
&& is_valid_policy_hnd(&user_handle
)) {
4391 dcerpc_samr_Close(b
, mem_ctx
, &user_handle
, &result
);
4393 if (b
&& is_valid_policy_hnd(&domain_handle
)) {
4394 dcerpc_samr_Close(b
, mem_ctx
, &domain_handle
, &result
);
4396 if (b
&& is_valid_policy_hnd(&connect_handle
)) {
4397 dcerpc_samr_Close(b
, mem_ctx
, &connect_handle
, &result
);
4400 SSVAL(*rparam
,0,errcode
);
4401 SSVAL(*rparam
,2,0); /* converter word */
4402 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
4407 static bool api_WWkstaUserLogon(struct smbd_server_connection
*sconn
,
4408 connection_struct
*conn
,uint64_t vuid
,
4409 char *param
, int tpscnt
,
4410 char *data
, int tdscnt
,
4411 int mdrcnt
,int mprcnt
,
4412 char **rdata
,char **rparam
,
4413 int *rdata_len
,int *rparam_len
)
4415 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4416 char *str2
= skip_string(param
,tpscnt
,str1
);
4417 char *p
= skip_string(param
,tpscnt
,str2
);
4419 struct pack_desc desc
;
4421 struct auth_session_info
*si
= NULL
;
4424 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
4427 if (!NT_STATUS_IS_OK(status
)) {
4431 if (!str1
|| !str2
|| !p
) {
4435 DBG_INFO("Username of UID %ju is %s\n",
4436 (uintmax_t)si
->unix_token
->uid
,
4437 si
->unix_info
->unix_name
);
4439 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4440 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
4445 memset((char *)&desc
,'\0',sizeof(desc
));
4447 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
4449 /* check it's a supported varient */
4450 if (strcmp(str1
,"OOWb54WrLh") != 0) {
4453 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
4457 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4464 desc
.buflen
= mdrcnt
;
4465 desc
.subformat
= NULL
;
4468 if (init_package(&desc
,1,0)) {
4469 PACKI(&desc
,"W",0); /* code */
4470 PACKS(&desc
,"B21",name
); /* eff. name */
4471 PACKS(&desc
,"B",""); /* pad */
4473 (get_current_uid(conn
) == sec_initial_uid())?
4474 USER_PRIV_ADMIN
:USER_PRIV_USER
);
4475 PACKI(&desc
,"D",0); /* auth flags XXX */
4476 PACKI(&desc
,"W",0); /* num logons */
4477 PACKI(&desc
,"W",0); /* bad pw count */
4478 PACKI(&desc
,"D",0); /* last logon */
4479 PACKI(&desc
,"D",-1); /* last logoff */
4480 PACKI(&desc
,"D",-1); /* logoff time */
4481 PACKI(&desc
,"D",-1); /* kickoff time */
4482 PACKI(&desc
,"D",0); /* password age */
4483 PACKI(&desc
,"D",0); /* password can change */
4484 PACKI(&desc
,"D",-1); /* password must change */
4488 fstrcpy(mypath
,"\\\\");
4489 fstrcat(mypath
,get_local_machine_name());
4490 if (!strupper_m(mypath
)) {
4493 PACKS(&desc
,"z",mypath
); /* computer */
4496 PACKS(&desc
,"z",lp_workgroup());/* domain */
4497 PACKS(&desc
,"z", si
->info
->logon_script
); /* script path */
4498 PACKI(&desc
,"D",0x00000000); /* reserved */
4501 *rdata_len
= desc
.usedlen
;
4503 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4507 SSVALS(*rparam
,0,desc
.errcode
);
4509 SSVAL(*rparam
,4,desc
.neededlen
);
4511 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4516 /****************************************************************************
4517 api_WAccessGetUserPerms
4518 ****************************************************************************/
4520 static bool api_WAccessGetUserPerms(struct smbd_server_connection
*sconn
,
4521 connection_struct
*conn
,uint64_t vuid
,
4522 char *param
, int tpscnt
,
4523 char *data
, int tdscnt
,
4524 int mdrcnt
,int mprcnt
,
4525 char **rdata
,char **rparam
,
4526 int *rdata_len
,int *rparam_len
)
4528 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4529 char *str2
= skip_string(param
,tpscnt
,str1
);
4530 char *user
= skip_string(param
,tpscnt
,str2
);
4531 char *resource
= skip_string(param
,tpscnt
,user
);
4533 if (!str1
|| !str2
|| !user
|| !resource
) {
4537 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4540 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4542 /* check it's a supported varient */
4543 if (strcmp(str1
,"zzh") != 0) {
4546 if (strcmp(str2
,"") != 0) {
4551 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4555 SSVALS(*rparam
,0,0); /* errorcode */
4556 SSVAL(*rparam
,2,0); /* converter word */
4557 SSVAL(*rparam
,4,0x7f); /* permission flags */
4562 /****************************************************************************
4563 api_WPrintJobEnumerate
4564 ****************************************************************************/
4566 static bool api_WPrintJobGetInfo(struct smbd_server_connection
*sconn
,
4567 connection_struct
*conn
, uint64_t vuid
,
4568 char *param
, int tpscnt
,
4569 char *data
, int tdscnt
,
4570 int mdrcnt
,int mprcnt
,
4571 char **rdata
,char **rparam
,
4572 int *rdata_len
,int *rparam_len
)
4574 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4575 char *str2
= skip_string(param
,tpscnt
,str1
);
4576 char *p
= skip_string(param
,tpscnt
,str2
);
4580 struct pack_desc desc
;
4583 TALLOC_CTX
*mem_ctx
= talloc_tos();
4586 struct rpc_pipe_client
*cli
= NULL
;
4587 struct dcerpc_binding_handle
*b
= NULL
;
4588 struct policy_handle handle
;
4589 struct spoolss_DevmodeContainer devmode_ctr
;
4590 union spoolss_JobInfo info
;
4592 if (!str1
|| !str2
|| !p
) {
4596 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4598 memset((char *)&desc
,'\0',sizeof(desc
));
4599 memset((char *)&status
,'\0',sizeof(status
));
4601 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4603 /* check it's a supported varient */
4604 if (strcmp(str1
,"WWrLh") != 0) {
4607 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4611 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4615 ZERO_STRUCT(handle
);
4617 status
= rpc_pipe_open_interface(mem_ctx
,
4620 conn
->sconn
->remote_address
,
4621 conn
->sconn
->local_address
,
4622 conn
->sconn
->msg_ctx
,
4624 if (!NT_STATUS_IS_OK(status
)) {
4625 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4626 nt_errstr(status
)));
4627 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4630 b
= cli
->binding_handle
;
4632 ZERO_STRUCT(devmode_ctr
);
4634 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4641 if (!NT_STATUS_IS_OK(status
)) {
4642 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4645 if (!W_ERROR_IS_OK(werr
)) {
4646 desc
.errcode
= W_ERROR_V(werr
);
4650 werr
= rpccli_spoolss_getjob(cli
, mem_ctx
,
4656 if (!W_ERROR_IS_OK(werr
)) {
4657 desc
.errcode
= W_ERROR_V(werr
);
4662 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4667 desc
.buflen
= mdrcnt
;
4670 * Don't return data but need to get correct length
4671 * init_package will return wrong size if buflen=0
4673 desc
.buflen
= getlen(desc
.format
);
4674 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4677 if (init_package(&desc
,1,0)) {
4678 fill_spoolss_printjob_info(uLevel
, &desc
, &info
.info2
, info
.info2
.position
);
4679 *rdata_len
= desc
.usedlen
;
4681 desc
.errcode
= NERR_JobNotFound
;
4685 if (b
&& is_valid_policy_hnd(&handle
)) {
4686 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4690 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4694 SSVALS(*rparam
,0,desc
.errcode
);
4696 SSVAL(*rparam
,4,desc
.neededlen
);
4700 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4705 static bool api_WPrintJobEnumerate(struct smbd_server_connection
*sconn
,
4706 connection_struct
*conn
, uint64_t vuid
,
4707 char *param
, int tpscnt
,
4708 char *data
, int tdscnt
,
4709 int mdrcnt
,int mprcnt
,
4710 char **rdata
,char **rparam
,
4711 int *rdata_len
,int *rparam_len
)
4713 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4714 char *str2
= skip_string(param
,tpscnt
,str1
);
4715 char *p
= skip_string(param
,tpscnt
,str2
);
4719 struct pack_desc desc
;
4721 TALLOC_CTX
*mem_ctx
= talloc_tos();
4724 struct rpc_pipe_client
*cli
= NULL
;
4725 struct dcerpc_binding_handle
*b
= NULL
;
4726 struct policy_handle handle
;
4727 struct spoolss_DevmodeContainer devmode_ctr
;
4729 union spoolss_JobInfo
*info
;
4731 if (!str1
|| !str2
|| !p
) {
4735 memset((char *)&desc
,'\0',sizeof(desc
));
4737 p
= skip_string(param
,tpscnt
,p
);
4741 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4743 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4745 /* check it's a supported variant */
4746 if (strcmp(str1
,"zWrLeh") != 0) {
4751 return False
; /* defined only for uLevel 0,1,2 */
4754 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4758 ZERO_STRUCT(handle
);
4760 status
= rpc_pipe_open_interface(mem_ctx
,
4763 conn
->sconn
->remote_address
,
4764 conn
->sconn
->local_address
,
4765 conn
->sconn
->msg_ctx
,
4767 if (!NT_STATUS_IS_OK(status
)) {
4768 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4769 nt_errstr(status
)));
4770 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4773 b
= cli
->binding_handle
;
4775 ZERO_STRUCT(devmode_ctr
);
4777 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4784 if (!NT_STATUS_IS_OK(status
)) {
4785 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4788 if (!W_ERROR_IS_OK(werr
)) {
4789 desc
.errcode
= W_ERROR_V(werr
);
4793 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
4801 if (!W_ERROR_IS_OK(werr
)) {
4802 desc
.errcode
= W_ERROR_V(werr
);
4807 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4813 desc
.buflen
= mdrcnt
;
4815 if (init_package(&desc
,count
,0)) {
4817 for (i
= 0; i
< count
; i
++) {
4818 fill_spoolss_printjob_info(uLevel
, &desc
, &info
[i
].info2
, i
);
4819 if (desc
.errcode
== NERR_Success
) {
4825 if (b
&& is_valid_policy_hnd(&handle
)) {
4826 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
4829 *rdata_len
= desc
.usedlen
;
4832 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4836 SSVALS(*rparam
,0,desc
.errcode
);
4838 SSVAL(*rparam
,4,succnt
);
4839 SSVAL(*rparam
,6,count
);
4841 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4846 static int check_printdest_info(struct pack_desc
* desc
,
4847 int uLevel
, char* id
)
4849 desc
->subformat
= NULL
;
4852 desc
->format
= "B9";
4855 desc
->format
= "B9B21WWzW";
4861 desc
->format
= "zzzWWzzzWW";
4864 DEBUG(0,("check_printdest_info: invalid level %d\n",
4868 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4869 DEBUG(0,("check_printdest_info: invalid string %s\n",
4870 id
? id
: "<NULL>" ));
4876 static void fill_printdest_info(struct spoolss_PrinterInfo2
*info2
, int uLevel
,
4877 struct pack_desc
* desc
)
4881 strncpy(buf
, info2
->printername
, sizeof(buf
)-1);
4882 buf
[sizeof(buf
)-1] = 0;
4883 (void)strupper_m(buf
);
4886 PACKS(desc
,"B9",buf
); /* szName */
4888 PACKS(desc
,"B21",""); /* szUserName */
4889 PACKI(desc
,"W",0); /* uJobId */
4890 PACKI(desc
,"W",0); /* fsStatus */
4891 PACKS(desc
,"z",""); /* pszStatus */
4892 PACKI(desc
,"W",0); /* time */
4896 if (uLevel
== 2 || uLevel
== 3) {
4897 PACKS(desc
,"z",buf
); /* pszPrinterName */
4899 PACKS(desc
,"z",""); /* pszUserName */
4900 PACKS(desc
,"z",""); /* pszLogAddr */
4901 PACKI(desc
,"W",0); /* uJobId */
4902 PACKI(desc
,"W",0); /* fsStatus */
4903 PACKS(desc
,"z",""); /* pszStatus */
4904 PACKS(desc
,"z",""); /* pszComment */
4905 PACKS(desc
,"z","NULL"); /* pszDrivers */
4906 PACKI(desc
,"W",0); /* time */
4907 PACKI(desc
,"W",0); /* pad1 */
4912 static bool api_WPrintDestGetInfo(struct smbd_server_connection
*sconn
,
4913 connection_struct
*conn
, uint64_t vuid
,
4914 char *param
, int tpscnt
,
4915 char *data
, int tdscnt
,
4916 int mdrcnt
,int mprcnt
,
4917 char **rdata
,char **rparam
,
4918 int *rdata_len
,int *rparam_len
)
4920 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4921 char *str2
= skip_string(param
,tpscnt
,str1
);
4922 char *p
= skip_string(param
,tpscnt
,str2
);
4923 char* PrinterName
= p
;
4925 struct pack_desc desc
;
4928 TALLOC_CTX
*mem_ctx
= talloc_tos();
4931 struct rpc_pipe_client
*cli
= NULL
;
4932 struct dcerpc_binding_handle
*b
= NULL
;
4933 struct policy_handle handle
;
4934 struct spoolss_DevmodeContainer devmode_ctr
;
4935 union spoolss_PrinterInfo info
;
4937 if (!str1
|| !str2
|| !p
) {
4941 memset((char *)&desc
,'\0',sizeof(desc
));
4943 p
= skip_string(param
,tpscnt
,p
);
4947 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4949 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4951 /* check it's a supported varient */
4952 if (strcmp(str1
,"zWrLh") != 0) {
4955 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4959 ZERO_STRUCT(handle
);
4961 status
= rpc_pipe_open_interface(mem_ctx
,
4964 conn
->sconn
->remote_address
,
4965 conn
->sconn
->local_address
,
4966 conn
->sconn
->msg_ctx
,
4968 if (!NT_STATUS_IS_OK(status
)) {
4969 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4970 nt_errstr(status
)));
4971 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
4974 b
= cli
->binding_handle
;
4976 ZERO_STRUCT(devmode_ctr
);
4978 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
4985 if (!NT_STATUS_IS_OK(status
)) {
4987 desc
.errcode
= NERR_DestNotFound
;
4991 if (!W_ERROR_IS_OK(werr
)) {
4993 desc
.errcode
= NERR_DestNotFound
;
4998 werr
= rpccli_spoolss_getprinter(cli
, mem_ctx
,
5003 if (!W_ERROR_IS_OK(werr
)) {
5005 desc
.errcode
= NERR_DestNotFound
;
5011 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5016 desc
.buflen
= mdrcnt
;
5019 * Don't return data but need to get correct length
5020 * init_package will return wrong size if buflen=0
5022 desc
.buflen
= getlen(desc
.format
);
5023 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
5025 if (init_package(&desc
,1,0)) {
5026 fill_printdest_info(&info
.info2
, uLevel
,&desc
);
5030 if (b
&& is_valid_policy_hnd(&handle
)) {
5031 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5034 *rdata_len
= desc
.usedlen
;
5037 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5041 SSVALS(*rparam
,0,desc
.errcode
);
5043 SSVAL(*rparam
,4,desc
.neededlen
);
5045 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
5051 static bool api_WPrintDestEnum(struct smbd_server_connection
*sconn
,
5052 connection_struct
*conn
, uint64_t vuid
,
5053 char *param
, int tpscnt
,
5054 char *data
, int tdscnt
,
5055 int mdrcnt
,int mprcnt
,
5056 char **rdata
,char **rparam
,
5057 int *rdata_len
,int *rparam_len
)
5059 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5060 char *str2
= skip_string(param
,tpscnt
,str1
);
5061 char *p
= skip_string(param
,tpscnt
,str2
);
5065 struct pack_desc desc
;
5067 TALLOC_CTX
*mem_ctx
= talloc_tos();
5070 struct rpc_pipe_client
*cli
= NULL
;
5071 union spoolss_PrinterInfo
*info
;
5074 if (!str1
|| !str2
|| !p
) {
5078 memset((char *)&desc
,'\0',sizeof(desc
));
5080 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5082 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
5084 /* check it's a supported varient */
5085 if (strcmp(str1
,"WrLeh") != 0) {
5088 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
5094 status
= rpc_pipe_open_interface(mem_ctx
,
5097 conn
->sconn
->remote_address
,
5098 conn
->sconn
->local_address
,
5099 conn
->sconn
->msg_ctx
,
5101 if (!NT_STATUS_IS_OK(status
)) {
5102 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5103 nt_errstr(status
)));
5104 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5108 werr
= rpccli_spoolss_enumprinters(cli
, mem_ctx
,
5110 cli
->srv_name_slash
,
5115 if (!W_ERROR_IS_OK(werr
)) {
5116 desc
.errcode
= W_ERROR_V(werr
);
5118 desc
.errcode
= NERR_DestNotFound
;
5126 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5133 desc
.buflen
= mdrcnt
;
5134 if (init_package(&desc
,queuecnt
,0)) {
5137 for (i
= 0; i
< count
; i
++) {
5138 fill_printdest_info(&info
[i
].info2
, uLevel
,&desc
);
5140 if (desc
.errcode
== NERR_Success
) {
5146 *rdata_len
= desc
.usedlen
;
5149 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5153 SSVALS(*rparam
,0,desc
.errcode
);
5155 SSVAL(*rparam
,4,succnt
);
5156 SSVAL(*rparam
,6,queuecnt
);
5158 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
5163 static bool api_WPrintDriverEnum(struct smbd_server_connection
*sconn
,
5164 connection_struct
*conn
, uint64_t vuid
,
5165 char *param
, int tpscnt
,
5166 char *data
, int tdscnt
,
5167 int mdrcnt
,int mprcnt
,
5168 char **rdata
,char **rparam
,
5169 int *rdata_len
,int *rparam_len
)
5171 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5172 char *str2
= skip_string(param
,tpscnt
,str1
);
5173 char *p
= skip_string(param
,tpscnt
,str2
);
5176 struct pack_desc desc
;
5178 if (!str1
|| !str2
|| !p
) {
5182 memset((char *)&desc
,'\0',sizeof(desc
));
5184 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5186 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
5188 /* check it's a supported varient */
5189 if (strcmp(str1
,"WrLeh") != 0) {
5192 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
5197 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5203 desc
.buflen
= mdrcnt
;
5204 if (init_package(&desc
,1,0)) {
5205 PACKS(&desc
,"B41","NULL");
5208 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5210 *rdata_len
= desc
.usedlen
;
5213 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5217 SSVALS(*rparam
,0,desc
.errcode
);
5219 SSVAL(*rparam
,4,succnt
);
5222 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
5227 static bool api_WPrintQProcEnum(struct smbd_server_connection
*sconn
,
5228 connection_struct
*conn
, uint64_t vuid
,
5229 char *param
, int tpscnt
,
5230 char *data
, int tdscnt
,
5231 int mdrcnt
,int mprcnt
,
5232 char **rdata
,char **rparam
,
5233 int *rdata_len
,int *rparam_len
)
5235 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5236 char *str2
= skip_string(param
,tpscnt
,str1
);
5237 char *p
= skip_string(param
,tpscnt
,str2
);
5240 struct pack_desc desc
;
5242 if (!str1
|| !str2
|| !p
) {
5245 memset((char *)&desc
,'\0',sizeof(desc
));
5247 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5249 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
5251 /* check it's a supported varient */
5252 if (strcmp(str1
,"WrLeh") != 0) {
5255 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
5260 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5266 desc
.buflen
= mdrcnt
;
5268 if (init_package(&desc
,1,0)) {
5269 PACKS(&desc
,"B13","lpd");
5272 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5274 *rdata_len
= desc
.usedlen
;
5277 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5281 SSVALS(*rparam
,0,desc
.errcode
);
5283 SSVAL(*rparam
,4,succnt
);
5286 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
5291 static bool api_WPrintPortEnum(struct smbd_server_connection
*sconn
,
5292 connection_struct
*conn
, uint64_t vuid
,
5293 char *param
, int tpscnt
,
5294 char *data
, int tdscnt
,
5295 int mdrcnt
,int mprcnt
,
5296 char **rdata
,char **rparam
,
5297 int *rdata_len
,int *rparam_len
)
5299 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5300 char *str2
= skip_string(param
,tpscnt
,str1
);
5301 char *p
= skip_string(param
,tpscnt
,str2
);
5304 struct pack_desc desc
;
5306 if (!str1
|| !str2
|| !p
) {
5310 memset((char *)&desc
,'\0',sizeof(desc
));
5312 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5314 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
5316 /* check it's a supported varient */
5317 if (strcmp(str1
,"WrLeh") != 0) {
5320 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
5325 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5330 memset((char *)&desc
,'\0',sizeof(desc
));
5332 desc
.buflen
= mdrcnt
;
5334 if (init_package(&desc
,1,0)) {
5335 PACKS(&desc
,"B13","lp0");
5338 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
5340 *rdata_len
= desc
.usedlen
;
5343 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5347 SSVALS(*rparam
,0,desc
.errcode
);
5349 SSVAL(*rparam
,4,succnt
);
5352 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
5357 /****************************************************************************
5359 ****************************************************************************/
5361 static bool api_RNetSessionEnum(struct smbd_server_connection
*sconn
,
5362 connection_struct
*conn
, uint64_t vuid
,
5363 char *param
, int tpscnt
,
5364 char *data
, int tdscnt
,
5365 int mdrcnt
,int mprcnt
,
5366 char **rdata
,char **rparam
,
5367 int *rdata_len
,int *rparam_len
)
5370 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
5371 char *str2
= skip_string(param
,tpscnt
,str1
);
5372 char *p
= skip_string(param
,tpscnt
,str2
);
5374 struct pack_desc desc
;
5377 TALLOC_CTX
*mem_ctx
= talloc_tos();
5380 struct rpc_pipe_client
*cli
= NULL
;
5381 struct dcerpc_binding_handle
*b
= NULL
;
5382 struct srvsvc_NetSessInfoCtr info_ctr
;
5383 uint32_t totalentries
, resume_handle
= 0;
5386 if (!str1
|| !str2
|| !p
) {
5392 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
5394 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
5395 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
5396 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
5398 /* check it's a supported varient */
5399 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
5402 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
5406 status
= rpc_pipe_open_interface(mem_ctx
,
5409 conn
->sconn
->remote_address
,
5410 conn
->sconn
->local_address
,
5411 conn
->sconn
->msg_ctx
,
5413 if (!NT_STATUS_IS_OK(status
)) {
5414 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5415 nt_errstr(status
)));
5416 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5419 b
= cli
->binding_handle
;
5422 info_ctr
.ctr
.ctr1
= talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1
);
5423 if (info_ctr
.ctr
.ctr1
== NULL
) {
5424 desc
.errcode
= W_ERROR_V(WERR_NOT_ENOUGH_MEMORY
);
5428 status
= dcerpc_srvsvc_NetSessEnum(b
, mem_ctx
,
5429 cli
->srv_name_slash
,
5433 (uint32_t)-1, /* max_buffer */
5437 if (!NT_STATUS_IS_OK(status
)) {
5438 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5439 nt_errstr(status
)));
5440 desc
.errcode
= W_ERROR_V(ntstatus_to_werror(status
));
5444 if (!W_ERROR_IS_OK(werr
)) {
5445 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5447 desc
.errcode
= W_ERROR_V(werr
);
5451 count
= info_ctr
.ctr
.ctr1
->count
;
5455 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
5462 desc
.buflen
= mdrcnt
;
5464 if (!init_package(&desc
, count
,0)) {
5468 for(i
=0; i
< count
; i
++) {
5469 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].client
);
5470 PACKS(&desc
, "z", info_ctr
.ctr
.ctr1
->array
[i
].user
);
5471 PACKI(&desc
, "W", 1); /* num conns */
5472 PACKI(&desc
, "W", info_ctr
.ctr
.ctr1
->array
[i
].num_open
);
5473 PACKI(&desc
, "W", 1); /* num users */
5474 PACKI(&desc
, "D", 0); /* session time */
5475 PACKI(&desc
, "D", 0); /* idle time */
5476 PACKI(&desc
, "D", 0); /* flags */
5477 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
5480 *rdata_len
= desc
.usedlen
;
5483 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5487 SSVALS(*rparam
,0,desc
.errcode
);
5488 SSVAL(*rparam
,2,0); /* converter */
5489 SSVAL(*rparam
,4, count
); /* count */
5491 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
5497 /****************************************************************************
5498 The buffer was too small.
5499 ****************************************************************************/
5501 static bool api_TooSmall(struct smbd_server_connection
*sconn
,
5502 connection_struct
*conn
,uint64_t vuid
, char *param
, char *data
,
5503 int mdrcnt
, int mprcnt
,
5504 char **rdata
, char **rparam
,
5505 int *rdata_len
, int *rparam_len
)
5507 *rparam_len
= MIN(*rparam_len
,mprcnt
);
5508 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5515 SSVAL(*rparam
,0,NERR_BufTooSmall
);
5517 DEBUG(3,("Supplied buffer too small in API command\n"));
5522 /****************************************************************************
5523 The request is not supported.
5524 ****************************************************************************/
5526 static bool api_Unsupported(struct smbd_server_connection
*sconn
,
5527 connection_struct
*conn
, uint64_t vuid
,
5528 char *param
, int tpscnt
,
5529 char *data
, int tdscnt
,
5530 int mdrcnt
, int mprcnt
,
5531 char **rdata
, char **rparam
,
5532 int *rdata_len
, int *rparam_len
)
5535 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
5542 SSVAL(*rparam
,0,NERR_notsupported
);
5543 SSVAL(*rparam
,2,0); /* converter word */
5545 DEBUG(3,("Unsupported API command\n"));
5550 static const struct {
5553 bool (*fn
)(struct smbd_server_connection
*sconn
,
5554 connection_struct
*, uint64_t,
5557 int,int,char **,char **,int *,int *);
5558 bool auth_user
; /* Deny anonymous access? */
5559 } api_commands
[] = {
5561 .name
= "RNetShareEnum",
5562 .id
= RAP_WshareEnum
,
5563 .fn
= api_RNetShareEnum
,
5567 .name
= "RNetShareGetInfo",
5568 .id
= RAP_WshareGetInfo
,
5569 .fn
= api_RNetShareGetInfo
5572 .name
= "RNetShareAdd",
5573 .id
= RAP_WshareAdd
,
5574 .fn
= api_RNetShareAdd
5577 .name
= "RNetSessionEnum",
5578 .id
= RAP_WsessionEnum
,
5579 .fn
= api_RNetSessionEnum
,
5583 .name
= "RNetServerGetInfo",
5584 .id
= RAP_WserverGetInfo
,
5585 .fn
= api_RNetServerGetInfo
5588 .name
= "RNetGroupEnum",
5589 .id
= RAP_WGroupEnum
,
5590 .fn
= api_RNetGroupEnum
, True
5593 .name
= "RNetGroupGetUsers",
5594 .id
= RAP_WGroupGetUsers
,
5595 .fn
= api_RNetGroupGetUsers
,
5598 .name
= "RNetUserEnum",
5599 .id
= RAP_WUserEnum
,
5600 .fn
= api_RNetUserEnum
,
5604 .name
= "RNetUserGetInfo",
5605 .id
= RAP_WUserGetInfo
,
5606 .fn
= api_RNetUserGetInfo
5609 .name
= "NetUserGetGroups",
5610 .id
= RAP_WUserGetGroups
,
5611 .fn
= api_NetUserGetGroups
5614 .name
= "NetWkstaGetInfo",
5615 .id
= RAP_WWkstaGetInfo
,
5616 .fn
= api_NetWkstaGetInfo
5619 .name
= "DosPrintQEnum",
5620 .id
= RAP_WPrintQEnum
,
5621 .fn
= api_DosPrintQEnum
,
5625 .name
= "DosPrintQGetInfo",
5626 .id
= RAP_WPrintQGetInfo
,
5627 .fn
= api_DosPrintQGetInfo
5630 .name
= "WPrintQueuePause",
5631 .id
= RAP_WPrintQPause
,
5632 .fn
= api_WPrintQueueCtrl
5635 .name
= "WPrintQueueResume",
5636 .id
= RAP_WPrintQContinue
,
5637 .fn
= api_WPrintQueueCtrl
5640 .name
= "WPrintJobEnumerate",
5641 .id
= RAP_WPrintJobEnum
,
5642 .fn
= api_WPrintJobEnumerate
5645 .name
= "WPrintJobGetInfo",
5646 .id
= RAP_WPrintJobGetInfo
,
5647 .fn
= api_WPrintJobGetInfo
5650 .name
= "RDosPrintJobDel",
5651 .id
= RAP_WPrintJobDel
,
5652 .fn
= api_RDosPrintJobDel
5655 .name
= "RDosPrintJobPause",
5656 .id
= RAP_WPrintJobPause
,
5657 .fn
= api_RDosPrintJobDel
5660 .name
= "RDosPrintJobResume",
5661 .id
= RAP_WPrintJobContinue
,
5662 .fn
= api_RDosPrintJobDel
5665 .name
= "WPrintDestEnum",
5666 .id
= RAP_WPrintDestEnum
,
5667 .fn
= api_WPrintDestEnum
5670 .name
= "WPrintDestGetInfo",
5671 .id
= RAP_WPrintDestGetInfo
,
5672 .fn
= api_WPrintDestGetInfo
5675 .name
= "NetRemoteTOD",
5676 .id
= RAP_NetRemoteTOD
,
5677 .fn
= api_NetRemoteTOD
5680 .name
= "WPrintQueuePurge",
5681 .id
= RAP_WPrintQPurge
,
5682 .fn
= api_WPrintQueueCtrl
5685 .name
= "NetServerEnum2",
5686 .id
= RAP_NetServerEnum2
,
5687 .fn
= api_RNetServerEnum2
5690 .name
= "NetServerEnum3",
5691 .id
= RAP_NetServerEnum3
,
5692 .fn
= api_RNetServerEnum3
5695 .name
= "WAccessGetUserPerms",
5696 .id
= RAP_WAccessGetUserPerms
,
5697 .fn
= api_WAccessGetUserPerms
5700 .name
= "WWkstaUserLogon",
5701 .id
= RAP_WWkstaUserLogon
,
5702 .fn
= api_WWkstaUserLogon
5705 .name
= "PrintJobInfo",
5706 .id
= RAP_WPrintJobSetInfo
,
5707 .fn
= api_PrintJobInfo
5710 .name
= "WPrintDriverEnum",
5711 .id
= RAP_WPrintDriverEnum
,
5712 .fn
= api_WPrintDriverEnum
5715 .name
= "WPrintQProcEnum",
5716 .id
= RAP_WPrintQProcessorEnum
,
5717 .fn
= api_WPrintQProcEnum
5720 .name
= "WPrintPortEnum",
5721 .id
= RAP_WPrintPortEnum
,
5722 .fn
= api_WPrintPortEnum
5725 .name
= "SamOEMChangePassword",
5726 .id
= RAP_SamOEMChgPasswordUser2_P
,
5727 .fn
= api_SamOEMChangePassword
5732 .fn
= api_Unsupported
}
5734 * The following RAP calls are not implemented by Samba:
5735 * RAP_WFileEnum2 - anon not OK
5740 /****************************************************************************
5741 Handle remote api calls.
5742 ****************************************************************************/
5744 void api_reply(connection_struct
*conn
, uint64_t vuid
,
5745 struct smb_request
*req
,
5746 char *data
, char *params
,
5747 int tdscnt
, int tpscnt
,
5748 int mdrcnt
, int mprcnt
)
5752 char *rparam
= NULL
;
5753 const char *name1
= NULL
;
5754 const char *name2
= NULL
;
5761 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5762 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5770 api_command
= SVAL(params
,0);
5771 /* Is there a string at position params+2 ? */
5772 if (skip_string(params
,tpscnt
,params
+2)) {
5777 name2
= skip_string(params
,tpscnt
,params
+2);
5782 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5786 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
5788 for (i
=0;api_commands
[i
].name
;i
++) {
5789 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
5790 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
5795 /* Check whether this api call can be done anonymously */
5797 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
5798 struct auth_session_info
*si
= NULL
;
5801 status
= smbXsrv_session_info_lookup(conn
->sconn
->client
,
5804 if (!NT_STATUS_IS_OK(status
)) {
5805 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5809 if (security_session_user_level(si
, NULL
) < SECURITY_USER
) {
5810 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5815 rdata
= (char *)SMB_MALLOC(1024);
5817 memset(rdata
,'\0',1024);
5820 rparam
= (char *)SMB_MALLOC(1024);
5822 memset(rparam
,'\0',1024);
5825 if(!rdata
|| !rparam
) {
5826 DEBUG(0,("api_reply: malloc fail !\n"));
5829 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5833 reply
= api_commands
[i
].fn(req
->sconn
, conn
,
5835 params
,tpscnt
, /* params + length */
5836 data
,tdscnt
, /* data + length */
5838 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5841 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
5842 reply
= api_TooSmall(req
->sconn
,conn
,vuid
,params
,data
,
5844 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5847 /* if we get False back then it's actually unsupported */
5849 reply
= api_Unsupported(req
->sconn
,conn
,vuid
,params
,tpscnt
,
5851 tdscnt
,mdrcnt
,mprcnt
,
5852 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
5855 /* If api_Unsupported returns false we can't return anything. */
5857 send_trans_reply(conn
, req
, rparam
, rparam_len
,
5858 rdata
, rdata_len
, False
);