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 "../librpc/gen_ndr/ndr_samr_c.h"
32 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
33 #include "rpc_client/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
36 #include "../librpc/gen_ndr/srv_samr.h"
37 #include "../librpc/gen_ndr/srv_srvsvc.h"
38 #include "../librpc/gen_ndr/rap.h"
39 #include "../lib/util/binsearch.h"
40 #include "../libcli/auth/libcli_auth.h"
41 #include "rpc_client/init_lsa.h"
42 #include "rpc_server/rpc_ncacn_np.h"
43 #include "../libcli/security/security.h"
45 #include "passdb/machine_sid.h"
53 #define NERR_Success 0
54 #define NERR_badpass 86
55 #define NERR_notsupported 50
57 #define NERR_BASE (2100)
58 #define NERR_BufTooSmall (NERR_BASE+23)
59 #define NERR_JobNotFound (NERR_BASE+51)
60 #define NERR_DestNotFound (NERR_BASE+52)
62 #define ACCESS_READ 0x01
63 #define ACCESS_WRITE 0x02
64 #define ACCESS_CREATE 0x04
66 #define SHPWLEN 8 /* share password length */
68 /* Limit size of ipc replies */
70 static char *smb_realloc_limit(void *ptr, size_t size)
74 size = MAX((size),4*1024);
75 val = (char *)SMB_REALLOC(ptr,size);
77 memset(val,'\0',size);
82 static bool api_Unsupported(struct smbd_server_connection *sconn,
83 connection_struct *conn, uint16 vuid,
84 char *param, int tpscnt,
85 char *data, int tdscnt,
86 int mdrcnt, int mprcnt,
87 char **rdata, char **rparam,
88 int *rdata_len, int *rparam_len);
90 static bool api_TooSmall(struct smbd_server_connection *sconn,
91 connection_struct *conn, uint16 vuid, char *param, char *data,
92 int mdrcnt, int mprcnt,
93 char **rdata, char **rparam,
94 int *rdata_len, int *rparam_len);
97 static int CopyExpanded(connection_struct *conn,
98 int snum, char **dst, char *src, int *p_space_remaining)
100 TALLOC_CTX *ctx = talloc_tos();
104 if (!src || !dst || !p_space_remaining || !(*dst) ||
105 *p_space_remaining <= 0) {
109 buf = talloc_strdup(ctx, src);
111 *p_space_remaining = 0;
114 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
116 *p_space_remaining = 0;
119 buf = talloc_sub_advanced(ctx,
120 lp_servicename(SNUM(conn)),
121 conn->session_info->unix_name,
123 conn->session_info->utok.gid,
124 conn->session_info->sanitized_username,
125 conn->session_info->info3->base.domain.string,
128 *p_space_remaining = 0;
131 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
136 (*p_space_remaining) -= l;
140 static int CopyAndAdvance(char **dst, char *src, int *n)
143 if (!src || !dst || !n || !(*dst)) {
146 l = push_ascii(*dst,src,*n, STR_TERMINATE);
155 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
157 TALLOC_CTX *ctx = talloc_tos();
162 buf = talloc_strdup(ctx,s);
166 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
170 buf = talloc_sub_advanced(ctx,
171 lp_servicename(SNUM(conn)),
172 conn->session_info->unix_name,
174 conn->session_info->utok.gid,
175 conn->session_info->sanitized_username,
176 conn->session_info->info3->base.domain.string,
181 return strlen(buf) + 1;
184 /*******************************************************************
185 Check a API string for validity when we only need to check the prefix.
186 ******************************************************************/
188 static bool prefix_ok(const char *str, const char *prefix)
190 return(strncmp(str,prefix,strlen(prefix)) == 0);
194 const char *format; /* formatstring for structure */
195 const char *subformat; /* subformat for structure */
196 char *base; /* baseaddress of buffer */
197 int buflen; /* remaining size for fixed part; on init: length of base */
198 int subcount; /* count of substructures */
199 char *structbuf; /* pointer into buffer for remaining fixed part */
200 int stringlen; /* remaining size for variable part */
201 char *stringbuf; /* pointer into buffer for remaining variable part */
202 int neededlen; /* total needed size */
203 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
204 const char *curpos; /* current position; pointer into format or subformat */
208 static int get_counter(const char **p)
214 if (!isdigit((int)**p)) {
220 n = 10 * n + (i - '0');
228 static int getlen(const char *p)
237 case 'W': /* word (2 byte) */
240 case 'K': /* status word? (2 byte) */
243 case 'N': /* count of substructures (word) at end */
246 case 'D': /* double word (4 byte) */
247 case 'z': /* offset to zero terminated string (4 byte) */
248 case 'l': /* offset to user data (4 byte) */
251 case 'b': /* offset to data (with counter) (4 byte) */
255 case 'B': /* byte (with optional counter) */
256 n += get_counter(&p);
263 static bool init_package(struct pack_desc *p, int count, int subcount)
268 if (!p->format || !p->base) {
272 i = count * getlen(p->format);
274 i += subcount * getlen(p->subformat);
276 p->structbuf = p->base;
280 p->curpos = p->format;
286 * This is the old error code we used. Aparently
287 * WinNT/2k systems return ERRbuftoosmall (2123) and
288 * OS/2 needs this. I'm leaving this here so we can revert
291 p->errcode = ERRmoredata;
293 p->errcode = ERRbuftoosmall;
296 p->errcode = NERR_Success;
300 p->stringbuf = p->base + i;
302 return (p->errcode == NERR_Success);
305 static int package(struct pack_desc *p, ...)
308 int needed=0, stringneeded;
309 const char *str=NULL;
310 int is_string=0, stringused;
317 p->curpos = p->format;
319 p->curpos = p->subformat;
324 str = va_arg(args,char*);
325 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
334 switch( *p->curpos++ ) {
335 case 'W': /* word (2 byte) */
337 temp = va_arg(args,int);
338 if (p->buflen >= needed) {
339 SSVAL(p->structbuf,0,temp);
342 case 'K': /* status word? (2 byte) */
344 temp = va_arg(args,int);
345 if (p->buflen >= needed) {
346 SSVAL(p->structbuf,0,temp);
349 case 'N': /* count of substructures (word) at end */
351 p->subcount = va_arg(args,int);
352 if (p->buflen >= needed) {
353 SSVAL(p->structbuf,0,p->subcount);
356 case 'D': /* double word (4 byte) */
358 temp = va_arg(args,int);
359 if (p->buflen >= needed) {
360 SIVAL(p->structbuf,0,temp);
363 case 'B': /* byte (with optional counter) */
364 needed = get_counter(&p->curpos);
366 char *s = va_arg(args,char*);
367 if (p->buflen >= needed) {
368 StrnCpy(p->structbuf,s?s:"",needed-1);
372 case 'z': /* offset to zero terminated string (4 byte) */
373 str = va_arg(args,char*);
374 stringneeded = (str ? strlen(str)+1 : 0);
377 case 'l': /* offset to user data (4 byte) */
378 str = va_arg(args,char*);
379 stringneeded = va_arg(args,int);
382 case 'b': /* offset to data (with counter) (4 byte) */
383 str = va_arg(args,char*);
384 stringneeded = get_counter(&p->curpos);
390 if (stringneeded >= 0) {
392 if (p->buflen >= needed) {
393 stringused = stringneeded;
394 if (stringused > p->stringlen) {
395 stringused = (is_string ? p->stringlen : 0);
396 if (p->errcode == NERR_Success) {
397 p->errcode = ERRmoredata;
401 SIVAL(p->structbuf,0,0);
403 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
404 memcpy(p->stringbuf,str?str:"",stringused);
406 p->stringbuf[stringused-1] = '\0';
408 p->stringbuf += stringused;
409 p->stringlen -= stringused;
410 p->usedlen += stringused;
413 p->neededlen += stringneeded;
416 p->neededlen += needed;
417 if (p->buflen >= needed) {
418 p->structbuf += needed;
420 p->usedlen += needed;
422 if (p->errcode == NERR_Success) {
423 p->errcode = ERRmoredata;
430 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
431 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
433 #define PACK(desc,t,v) package(desc,v)
434 #define PACKl(desc,t,v,l) package(desc,v,l)
437 static void PACKI(struct pack_desc* desc, const char *t,int v)
442 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
447 /****************************************************************************
449 ****************************************************************************/
451 static void PackDriverData(struct pack_desc* desc)
453 char drivdata[4+4+32];
454 SIVAL(drivdata,0,sizeof drivdata); /* cb */
455 SIVAL(drivdata,4,1000); /* lVersion */
456 memset(drivdata+8,0,32); /* szDeviceName */
457 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
458 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
461 static int check_printq_info(struct pack_desc* desc,
462 unsigned int uLevel, char *id1, char *id2)
464 desc->subformat = NULL;
467 desc->format = "B13";
470 desc->format = "B13BWWWzzzzzWW";
473 desc->format = "B13BWWWzzzzzWN";
474 desc->subformat = "WB21BB16B10zWWzDDz";
477 desc->format = "zWWWWzzzzWWzzl";
480 desc->format = "zWWWWzzzzWNzzl";
481 desc->subformat = "WWzWWDDzz";
490 desc->format = "WzzzzzzzzN";
491 desc->subformat = "z";
494 DEBUG(0,("check_printq_info: invalid level %d\n",
498 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
499 DEBUG(0,("check_printq_info: invalid format %s\n",
500 id1 ? id1 : "<NULL>" ));
503 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
504 DEBUG(0,("check_printq_info: invalid subformat %s\n",
505 id2 ? id2 : "<NULL>" ));
512 #define RAP_JOB_STATUS_QUEUED 0
513 #define RAP_JOB_STATUS_PAUSED 1
514 #define RAP_JOB_STATUS_SPOOLING 2
515 #define RAP_JOB_STATUS_PRINTING 3
516 #define RAP_JOB_STATUS_PRINTED 4
518 #define RAP_QUEUE_STATUS_PAUSED 1
519 #define RAP_QUEUE_STATUS_ERROR 2
521 /* turn a print job status into a on the wire status
523 static int printj_spoolss_status(int v)
525 if (v == JOB_STATUS_QUEUED)
526 return RAP_JOB_STATUS_QUEUED;
527 if (v & JOB_STATUS_PAUSED)
528 return RAP_JOB_STATUS_PAUSED;
529 if (v & JOB_STATUS_SPOOLING)
530 return RAP_JOB_STATUS_SPOOLING;
531 if (v & JOB_STATUS_PRINTING)
532 return RAP_JOB_STATUS_PRINTING;
536 /* turn a print queue status into a on the wire status
538 static int printq_spoolss_status(int v)
540 if (v == PRINTER_STATUS_OK)
542 if (v & PRINTER_STATUS_PAUSED)
543 return RAP_QUEUE_STATUS_PAUSED;
544 return RAP_QUEUE_STATUS_ERROR;
547 static void fill_spoolss_printjob_info(int uLevel,
548 struct pack_desc *desc,
549 struct spoolss_JobInfo2 *info2,
552 time_t t = spoolss_Time_to_time_t(&info2->submitted);
554 /* the client expects localtime */
555 t -= get_time_zone(t);
557 PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
559 PACKS(desc,"B21", info2->user_name); /* szUserName */
560 PACKS(desc,"B",""); /* pad */
561 PACKS(desc,"B16",""); /* szNotifyName */
562 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
563 PACKS(desc,"z",""); /* pszParms */
564 PACKI(desc,"W",n+1); /* uPosition */
565 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
566 PACKS(desc,"z",""); /* pszStatus */
567 PACKI(desc,"D", t); /* ulSubmitted */
568 PACKI(desc,"D", info2->size); /* ulSize */
569 PACKS(desc,"z", info2->document_name); /* pszComment */
571 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
572 PACKI(desc,"W", info2->priority); /* uPriority */
573 PACKS(desc,"z", info2->user_name); /* pszUserName */
574 PACKI(desc,"W",n+1); /* uPosition */
575 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
576 PACKI(desc,"D",t); /* ulSubmitted */
577 PACKI(desc,"D", info2->size); /* ulSize */
578 PACKS(desc,"z","Samba"); /* pszComment */
579 PACKS(desc,"z", info2->document_name); /* pszDocument */
581 PACKS(desc,"z",""); /* pszNotifyName */
582 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
583 PACKS(desc,"z",""); /* pszParms */
584 PACKS(desc,"z",""); /* pszStatus */
585 PACKS(desc,"z", info2->printer_name); /* pszQueue */
586 PACKS(desc,"z","lpd"); /* pszQProcName */
587 PACKS(desc,"z",""); /* pszQProcParms */
588 PACKS(desc,"z","NULL"); /* pszDriverName */
589 PackDriverData(desc); /* pDriverData */
590 PACKS(desc,"z",""); /* pszPrinterName */
591 } else if (uLevel == 4) { /* OS2 */
592 PACKS(desc,"z",""); /* pszSpoolFileName */
593 PACKS(desc,"z",""); /* pszPortName */
594 PACKS(desc,"z",""); /* pszStatus */
595 PACKI(desc,"D",0); /* ulPagesSpooled */
596 PACKI(desc,"D",0); /* ulPagesSent */
597 PACKI(desc,"D",0); /* ulPagesPrinted */
598 PACKI(desc,"D",0); /* ulTimePrinted */
599 PACKI(desc,"D",0); /* ulExtendJobStatus */
600 PACKI(desc,"D",0); /* ulStartPage */
601 PACKI(desc,"D",0); /* ulEndPage */
606 /********************************************************************
607 Respond to the DosPrintQInfo command with a level of 52
608 This is used to get printer driver information for Win9x clients
609 ********************************************************************/
610 static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver,
611 struct pack_desc* desc, int count,
612 const char *printer_name)
616 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
617 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
618 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
620 PACKI(desc, "W", 0x0400); /* don't know */
621 PACKS(desc, "z", driver->driver_name); /* long printer name */
622 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
623 PACKS(desc, "z", driver->data_file); /* Datafile name */
624 PACKS(desc, "z", driver->monitor_name); /* language monitor */
626 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
627 standard_sub_basic( "", "", location, sizeof(location)-1 );
628 PACKS(desc,"z", location); /* share to retrieve files */
630 PACKS(desc,"z", driver->default_datatype); /* default data type */
631 PACKS(desc,"z", driver->help_file); /* helpfile name */
632 PACKS(desc,"z", driver->driver_path); /* driver name */
634 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
635 DEBUG(3,("Driver: %s:\n",driver->driver_path));
636 DEBUG(3,("Data File: %s:\n",driver->data_file));
637 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
638 DEBUG(3,("Driver Location: %s:\n",location));
639 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
640 DEBUG(3,("Help File: %s:\n",driver->help_file));
641 PACKI(desc,"N",count); /* number of files to copy */
643 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
645 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
646 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
647 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
652 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
655 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name, i));
657 desc->errcode=NERR_Success;
661 static const char *strip_unc(const char *unc)
669 if ((p = strrchr(unc, '\\')) != NULL) {
676 static void fill_printq_info(int uLevel,
677 struct pack_desc* desc,
679 union spoolss_JobInfo *job_info,
680 struct spoolss_DriverInfo3 *driver_info,
681 struct spoolss_PrinterInfo2 *printer_info)
687 PACKS(desc,"B13", strip_unc(printer_info->printername));
692 PACKS(desc,"z", strip_unc(printer_info->printername));
695 PACKI(desc,"K", printq_spoolss_status(printer_info->status));
699 if (uLevel == 1 || uLevel == 2) {
700 PACKS(desc,"B",""); /* alignment */
701 PACKI(desc,"W",5); /* priority */
702 PACKI(desc,"W",0); /* start time */
703 PACKI(desc,"W",0); /* until time */
704 PACKS(desc,"z",""); /* pSepFile */
705 PACKS(desc,"z","lpd"); /* pPrProc */
706 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pDestinations */
707 PACKS(desc,"z",""); /* pParms */
708 if (printer_info->printername == NULL) {
709 PACKS(desc,"z","UNKNOWN PRINTER");
710 PACKI(desc,"W",LPSTAT_ERROR);
712 PACKS(desc,"z", printer_info->comment);
713 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* status */
715 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
718 if (uLevel == 3 || uLevel == 4) {
719 PACKI(desc,"W",5); /* uPriority */
720 PACKI(desc,"W",0); /* uStarttime */
721 PACKI(desc,"W",0); /* uUntiltime */
722 PACKI(desc,"W",5); /* pad1 */
723 PACKS(desc,"z",""); /* pszSepFile */
724 PACKS(desc,"z","WinPrint"); /* pszPrProc */
725 PACKS(desc,"z",NULL); /* pszParms */
726 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
727 /* "don't ask" that it's done this way to fix corrupted
728 Win9X/ME printer comments. */
729 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* fsStatus */
730 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
731 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pszPrinters */
732 PACKS(desc,"z", printer_info->drivername); /* pszDriverName */
733 PackDriverData(desc); /* pDriverData */
736 if (uLevel == 2 || uLevel == 4) {
738 for (i = 0; i < count; i++) {
739 fill_spoolss_printjob_info(uLevel == 2 ? 1 : 2, desc, &job_info[i].info2, i);
744 fill_printq_info_52(driver_info, desc, count, printer_info->printername);
747 /* This function returns the number of files for a given driver */
748 static int get_printerdrivernumber(const struct spoolss_DriverInfo3 *driver)
752 /* count the number of files */
753 while (driver->dependent_files && *driver->dependent_files[result])
759 static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn,
760 connection_struct *conn, uint16 vuid,
761 char *param, int tpscnt,
762 char *data, int tdscnt,
763 int mdrcnt,int mprcnt,
764 char **rdata,char **rparam,
765 int *rdata_len,int *rparam_len)
767 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
768 char *str2 = skip_string(param,tpscnt,str1);
769 char *p = skip_string(param,tpscnt,str2);
774 struct pack_desc desc;
777 WERROR werr = WERR_OK;
778 TALLOC_CTX *mem_ctx = talloc_tos();
780 struct rpc_pipe_client *cli = NULL;
781 struct dcerpc_binding_handle *b = NULL;
782 struct policy_handle handle;
783 struct spoolss_DevmodeContainer devmode_ctr;
784 union spoolss_DriverInfo driver_info;
785 union spoolss_JobInfo *job_info = NULL;
786 union spoolss_PrinterInfo printer_info;
788 if (!str1 || !str2 || !p) {
791 memset((char *)&desc,'\0',sizeof(desc));
793 p = skip_string(param,tpscnt,p);
797 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
798 str3 = get_safe_str_ptr(param,tpscnt,p,4);
799 /* str3 may be null here and is checked in check_printq_info(). */
801 /* remove any trailing username */
802 if ((p = strchr_m(QueueName,'%')))
805 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
807 /* check it's a supported varient */
808 if (!prefix_ok(str1,"zWrLh"))
810 if (!check_printq_info(&desc,uLevel,str2,str3)) {
812 * Patch from Scott Moomaw <scott@bridgewater.edu>
813 * to return the 'invalid info level' error if an
814 * unknown level was requested.
818 *rparam = smb_realloc_limit(*rparam,*rparam_len);
822 SSVALS(*rparam,0,ERRunknownlevel);
830 if (QueueName == NULL || (strlen(QueueName) < 1)) {
831 desc.errcode = W_ERROR_V(WERR_INVALID_PARAM);
835 status = rpc_pipe_open_interface(conn,
836 &ndr_table_spoolss.syntax_id,
838 &conn->sconn->client_id,
839 conn->sconn->msg_ctx,
841 if (!NT_STATUS_IS_OK(status)) {
842 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
844 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
847 b = cli->binding_handle;
849 ZERO_STRUCT(devmode_ctr);
851 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
858 if (!NT_STATUS_IS_OK(status)) {
859 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
862 if (!W_ERROR_IS_OK(werr)) {
863 desc.errcode = W_ERROR_V(werr);
867 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
872 if (!W_ERROR_IS_OK(werr)) {
873 desc.errcode = W_ERROR_V(werr);
878 uint32_t server_major_version;
879 uint32_t server_minor_version;
881 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
889 &server_major_version,
890 &server_minor_version);
891 if (!W_ERROR_IS_OK(werr)) {
892 desc.errcode = W_ERROR_V(werr);
896 count = get_printerdrivernumber(&driver_info.info3);
897 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
900 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
908 if (!W_ERROR_IS_OK(werr)) {
909 desc.errcode = W_ERROR_V(werr);
917 *rdata = smb_realloc_limit(*rdata,mdrcnt);
922 desc.buflen = mdrcnt;
925 * Don't return data but need to get correct length
926 * init_package will return wrong size if buflen=0
928 desc.buflen = getlen(desc.format);
929 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
932 if (init_package(&desc,1,count)) {
933 desc.subcount = count;
934 fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
937 *rdata_len = desc.usedlen;
940 * We must set the return code to ERRbuftoosmall
941 * in order to support lanman style printing with Win NT/2k
944 if (!mdrcnt && lp_disable_spoolss())
945 desc.errcode = ERRbuftoosmall;
948 if (b && is_valid_policy_hnd(&handle)) {
949 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
952 *rdata_len = desc.usedlen;
954 *rparam = smb_realloc_limit(*rparam,*rparam_len);
959 SSVALS(*rparam,0,desc.errcode);
961 SSVAL(*rparam,4,desc.neededlen);
963 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
970 /****************************************************************************
971 View list of all print jobs on all queues.
972 ****************************************************************************/
974 static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
975 connection_struct *conn, uint16 vuid,
976 char *param, int tpscnt,
977 char *data, int tdscnt,
978 int mdrcnt, int mprcnt,
979 char **rdata, char** rparam,
980 int *rdata_len, int *rparam_len)
982 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
983 char *output_format1 = skip_string(param,tpscnt,param_format);
984 char *p = skip_string(param,tpscnt,output_format1);
985 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
986 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
988 struct pack_desc desc;
989 int *subcntarr = NULL;
990 int queuecnt = 0, subcnt = 0, succnt = 0;
992 WERROR werr = WERR_OK;
993 TALLOC_CTX *mem_ctx = talloc_tos();
995 struct rpc_pipe_client *cli = NULL;
996 struct dcerpc_binding_handle *b = NULL;
997 struct spoolss_DevmodeContainer devmode_ctr;
998 uint32_t num_printers;
999 union spoolss_PrinterInfo *printer_info;
1000 union spoolss_DriverInfo *driver_info;
1001 union spoolss_JobInfo **job_info;
1003 if (!param_format || !output_format1 || !p) {
1007 memset((char *)&desc,'\0',sizeof(desc));
1009 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
1011 if (!prefix_ok(param_format,"WrLeh")) {
1014 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1016 * Patch from Scott Moomaw <scott@bridgewater.edu>
1017 * to return the 'invalid info level' error if an
1018 * unknown level was requested.
1022 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1026 SSVALS(*rparam,0,ERRunknownlevel);
1032 status = rpc_pipe_open_interface(conn,
1033 &ndr_table_spoolss.syntax_id,
1035 &conn->sconn->client_id,
1036 conn->sconn->msg_ctx,
1038 if (!NT_STATUS_IS_OK(status)) {
1039 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1040 nt_errstr(status)));
1041 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1044 b = cli->binding_handle;
1046 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
1048 cli->srv_name_slash,
1053 if (!W_ERROR_IS_OK(werr)) {
1054 desc.errcode = W_ERROR_V(werr);
1058 queuecnt = num_printers;
1060 job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
1061 if (job_info == NULL) {
1065 driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
1066 if (driver_info == NULL) {
1070 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1071 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1076 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1082 desc.buflen = mdrcnt;
1085 for (i = 0; i < num_printers; i++) {
1088 struct policy_handle handle;
1089 const char *printername;
1091 printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
1092 if (printername == NULL) {
1096 ZERO_STRUCT(handle);
1097 ZERO_STRUCT(devmode_ctr);
1099 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
1106 if (!NT_STATUS_IS_OK(status)) {
1107 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1110 if (!W_ERROR_IS_OK(werr)) {
1111 desc.errcode = W_ERROR_V(werr);
1115 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
1123 if (!W_ERROR_IS_OK(werr)) {
1124 desc.errcode = W_ERROR_V(werr);
1129 uint32_t server_major_version;
1130 uint32_t server_minor_version;
1132 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1140 &server_major_version,
1141 &server_minor_version);
1142 if (!W_ERROR_IS_OK(werr)) {
1143 desc.errcode = W_ERROR_V(werr);
1148 subcntarr[i] = num_jobs;
1149 subcnt += subcntarr[i];
1151 if (b && is_valid_policy_hnd(&handle)) {
1152 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
1156 if (init_package(&desc,queuecnt,subcnt)) {
1157 for (i = 0; i < num_printers; i++) {
1158 fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
1159 if (desc.errcode == NERR_Success) {
1165 SAFE_FREE(subcntarr);
1167 *rdata_len = desc.usedlen;
1169 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1173 SSVALS(*rparam,0,desc.errcode);
1175 SSVAL(*rparam,4,succnt);
1176 SSVAL(*rparam,6,queuecnt);
1182 SAFE_FREE(subcntarr);
1187 /****************************************************************************
1188 Get info level for a server list query.
1189 ****************************************************************************/
1191 static bool check_session_info(int uLevel, char* id)
1195 if (strcmp(id,"B16") != 0) {
1200 if (strcmp(id,"B16BBDz") != 0) {
1210 struct srv_info_struct {
1218 /*******************************************************************
1219 Get server info lists from the files saved by nmbd. Return the
1221 ******************************************************************/
1223 static int get_session_info(uint32 servertype,
1224 struct srv_info_struct **servers,
1230 bool local_list_only;
1233 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1235 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1239 /* request for everything is code for request all servers */
1240 if (servertype == SV_TYPE_ALL) {
1241 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1244 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1246 DEBUG(4,("Servertype search: %8x\n",servertype));
1248 for (i=0;lines[i];i++) {
1250 struct srv_info_struct *s;
1251 const char *ptr = lines[i];
1253 TALLOC_CTX *frame = NULL;
1260 if (count == alloced) {
1262 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1264 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1268 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1270 s = &(*servers)[count];
1272 frame = talloc_stackframe();
1274 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1278 fstrcpy(s->name, p);
1281 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1287 s->comment[0] = '\0';
1288 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1292 fstrcpy(s->comment, p);
1293 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1295 s->domain[0] = '\0';
1296 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1297 /* this allows us to cope with an old nmbd */
1298 fstrcpy(s->domain,lp_workgroup());
1300 fstrcpy(s->domain, p);
1304 if (sscanf(stype,"%X",&s->type) != 1) {
1305 DEBUG(4,("r:host file "));
1309 /* Filter the servers/domains we return based on what was asked for. */
1311 /* Check to see if we are being asked for a local list only. */
1312 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1313 DEBUG(4,("r: local list only"));
1317 /* doesn't match up: don't want it */
1318 if (!(servertype & s->type)) {
1319 DEBUG(4,("r:serv type "));
1323 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1324 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1325 DEBUG(4,("s: dom mismatch "));
1329 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1333 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1334 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1337 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1338 s->name, s->type, s->comment, s->domain));
1339 s->server_added = True;
1342 DEBUG(4,("%20s %8x %25s %15s\n",
1343 s->name, s->type, s->comment, s->domain));
1351 /*******************************************************************
1352 Fill in a server info structure.
1353 ******************************************************************/
1355 static int fill_srv_info(struct srv_info_struct *service,
1356 int uLevel, char **buf, int *buflen,
1357 char **stringbuf, int *stringspace, char *baseaddr)
1380 len = strlen(service->comment)+1;
1384 *buflen = struct_len;
1386 return struct_len + len;
1391 if (*buflen < struct_len) {
1398 p2 = p + struct_len;
1399 l2 = *buflen - struct_len;
1407 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1411 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1412 SIVAL(p,18,service->type);
1413 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1414 len += CopyAndAdvance(&p2,service->comment,&l2);
1419 *buf = p + struct_len;
1420 *buflen -= struct_len;
1431 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1433 return StrCaseCmp(s1->name,s2->name);
1436 /****************************************************************************
1437 View list of servers available (or possibly domains). The info is
1438 extracted from lists saved by nmbd on the local host.
1439 ****************************************************************************/
1441 static bool api_RNetServerEnum2(struct smbd_server_connection *sconn,
1442 connection_struct *conn, uint16 vuid,
1443 char *param, int tpscnt,
1444 char *data, int tdscnt,
1445 int mdrcnt, int mprcnt, char **rdata,
1446 char **rparam, int *rdata_len, int *rparam_len)
1448 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1449 char *str2 = skip_string(param,tpscnt,str1);
1450 char *p = skip_string(param,tpscnt,str2);
1451 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1452 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1453 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1455 int data_len, fixed_len, string_len;
1456 int f_len = 0, s_len = 0;
1457 struct srv_info_struct *servers=NULL;
1458 int counted=0,total=0;
1461 bool domain_request;
1464 if (!str1 || !str2 || !p) {
1468 /* If someone sets all the bits they don't really mean to set
1469 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1472 if (servertype == SV_TYPE_ALL) {
1473 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1476 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1477 any other bit (they may just set this bit on its own) they
1478 want all the locally seen servers. However this bit can be
1479 set on its own so set the requested servers to be
1480 ALL - DOMAIN_ENUM. */
1482 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1483 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1486 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1487 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1491 if (!prefix_ok(str1,"WrLehD")) {
1494 if (!check_session_info(uLevel,str2)) {
1498 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1499 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1500 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1502 if (strcmp(str1, "WrLehDz") == 0) {
1503 if (skip_string(param,tpscnt,p) == NULL) {
1506 pull_ascii_fstring(domain, p);
1508 fstrcpy(domain, lp_workgroup());
1511 DEBUG(4, ("domain [%s]\n", domain));
1513 if (lp_browse_list()) {
1514 total = get_session_info(servertype,&servers,domain);
1517 data_len = fixed_len = string_len = 0;
1520 TYPESAFE_QSORT(servers, total, srv_comp);
1523 char *lastname=NULL;
1525 for (i=0;i<total;i++) {
1526 struct srv_info_struct *s = &servers[i];
1528 if (lastname && strequal(lastname,s->name)) {
1532 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1533 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1534 i, s->name, s->type, s->comment, s->domain));
1536 if (data_len < buf_len) {
1539 string_len += s_len;
1546 *rdata_len = fixed_len + string_len;
1547 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1552 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1558 char *lastname=NULL;
1559 int count2 = counted;
1561 for (i = 0; i < total && count2;i++) {
1562 struct srv_info_struct *s = &servers[i];
1564 if (lastname && strequal(lastname,s->name)) {
1568 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1569 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1570 i, s->name, s->type, s->comment, s->domain));
1576 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1580 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1582 SSVAL(*rparam,4,counted);
1583 SSVAL(*rparam,6,counted+missed);
1587 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1588 domain,uLevel,counted,counted+missed));
1593 static int srv_name_match(const char *n1, const char *n2)
1596 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1598 * In Windows, FirstNameToReturn need not be an exact match:
1599 * the server will return a list of servers that exist on
1600 * the network greater than or equal to the FirstNameToReturn.
1602 int ret = StrCaseCmp(n1, n2);
1611 static bool api_RNetServerEnum3(struct smbd_server_connection *sconn,
1612 connection_struct *conn, uint16 vuid,
1613 char *param, int tpscnt,
1614 char *data, int tdscnt,
1615 int mdrcnt, int mprcnt, char **rdata,
1616 char **rparam, int *rdata_len, int *rparam_len)
1618 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1619 char *str2 = skip_string(param,tpscnt,str1);
1620 char *p = skip_string(param,tpscnt,str2);
1621 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1622 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1623 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1625 int data_len, fixed_len, string_len;
1626 int f_len = 0, s_len = 0;
1627 struct srv_info_struct *servers=NULL;
1628 int counted=0,first=0,total=0;
1632 bool domain_request;
1635 if (!str1 || !str2 || !p) {
1639 /* If someone sets all the bits they don't really mean to set
1640 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1643 if (servertype == SV_TYPE_ALL) {
1644 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1647 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1648 any other bit (they may just set this bit on its own) they
1649 want all the locally seen servers. However this bit can be
1650 set on its own so set the requested servers to be
1651 ALL - DOMAIN_ENUM. */
1653 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1654 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1657 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1658 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1662 if (strcmp(str1, "WrLehDzz") != 0) {
1665 if (!check_session_info(uLevel,str2)) {
1669 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1670 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1671 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1673 if (skip_string(param,tpscnt,p) == NULL) {
1676 pull_ascii_fstring(domain, p);
1677 if (domain[0] == '\0') {
1678 fstrcpy(domain, lp_workgroup());
1680 p = skip_string(param,tpscnt,p);
1681 if (skip_string(param,tpscnt,p) == NULL) {
1684 pull_ascii_fstring(first_name, p);
1686 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1687 domain, first_name));
1689 if (lp_browse_list()) {
1690 total = get_session_info(servertype,&servers,domain);
1693 data_len = fixed_len = string_len = 0;
1696 TYPESAFE_QSORT(servers, total, srv_comp);
1698 if (first_name[0] != '\0') {
1699 struct srv_info_struct *first_server = NULL;
1701 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1702 srv_name_match, first_server);
1704 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1706 * The binary search may not find the exact match
1707 * so we need to search backward to find the first match
1709 * This implements the strange matching windows
1710 * implements. (see the comment in srv_name_match().
1714 ret = StrCaseCmp(first_name,
1715 servers[first-1].name);
1722 /* we should return no entries */
1728 char *lastname=NULL;
1730 for (i=first;i<total;i++) {
1731 struct srv_info_struct *s = &servers[i];
1733 if (lastname && strequal(lastname,s->name)) {
1737 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1738 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1739 i, s->name, s->type, s->comment, s->domain));
1741 if (data_len < buf_len) {
1744 string_len += s_len;
1751 *rdata_len = fixed_len + string_len;
1752 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1757 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1763 char *lastname=NULL;
1764 int count2 = counted;
1766 for (i = first; i < total && count2;i++) {
1767 struct srv_info_struct *s = &servers[i];
1769 if (lastname && strequal(lastname,s->name)) {
1773 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1774 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1775 i, s->name, s->type, s->comment, s->domain));
1781 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1785 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1787 SSVAL(*rparam,4,counted);
1788 SSVAL(*rparam,6,counted+missed);
1790 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1791 domain,uLevel,first,first_name,
1792 first < total ? servers[first].name : "",
1793 counted,counted+missed));
1800 /****************************************************************************
1801 command 0x34 - suspected of being a "Lookup Names" stub api
1802 ****************************************************************************/
1804 static bool api_RNetGroupGetUsers(struct smbd_server_connection *sconn,
1805 connection_struct *conn, uint16 vuid,
1806 char *param, int tpscnt,
1807 char *data, int tdscnt,
1808 int mdrcnt, int mprcnt, char **rdata,
1809 char **rparam, int *rdata_len, int *rparam_len)
1811 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1812 char *str2 = skip_string(param,tpscnt,str1);
1813 char *p = skip_string(param,tpscnt,str2);
1814 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1815 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1819 if (!str1 || !str2 || !p) {
1823 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1824 str1, str2, p, uLevel, buf_len));
1826 if (!prefix_ok(str1,"zWrLeh")) {
1833 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1838 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1840 SSVAL(*rparam,4,counted);
1841 SSVAL(*rparam,6,counted+missed);
1846 /****************************************************************************
1847 get info about a share
1848 ****************************************************************************/
1850 static bool check_share_info(int uLevel, char* id)
1854 if (strcmp(id,"B13") != 0) {
1859 /* Level-2 descriptor is allowed (and ignored) */
1860 if (strcmp(id,"B13BWz") != 0 &&
1861 strcmp(id,"B13BWzWWWzB9B") != 0) {
1866 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1871 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1881 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1882 char** buf, int* buflen,
1883 char** stringbuf, int* stringspace, char* baseaddr)
1912 len += StrlenExpanded(conn,snum,lp_comment(snum));
1915 len += strlen(lp_pathname(snum)) + 1;
1918 *buflen = struct_len;
1923 return struct_len + len;
1928 if ((*buflen) < struct_len) {
1936 p2 = p + struct_len;
1937 l2 = (*buflen) - struct_len;
1944 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1950 type = STYPE_DISKTREE;
1951 if (lp_print_ok(snum)) {
1952 type = STYPE_PRINTQ;
1954 if (strequal("IPC",lp_fstype(snum))) {
1957 SSVAL(p,14,type); /* device type */
1958 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1959 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1963 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1964 SSVALS(p,22,-1); /* max uses */
1965 SSVAL(p,24,1); /* current uses */
1966 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1967 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1968 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1972 memset(p+40,0,SHPWLEN+2);
1983 (*buf) = p + struct_len;
1984 (*buflen) -= struct_len;
1986 (*stringspace) = l2;
1995 static bool api_RNetShareGetInfo(struct smbd_server_connection *sconn,
1996 connection_struct *conn,uint16 vuid,
1997 char *param, int tpscnt,
1998 char *data, int tdscnt,
1999 int mdrcnt,int mprcnt,
2000 char **rdata,char **rparam,
2001 int *rdata_len,int *rparam_len)
2003 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2004 char *str2 = skip_string(param,tpscnt,str1);
2005 char *netname_in = skip_string(param,tpscnt,str2);
2006 char *netname = NULL;
2007 char *p = skip_string(param,tpscnt,netname);
2008 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2011 if (!str1 || !str2 || !netname_in || !p) {
2015 snum = find_service(talloc_tos(), netname_in, &netname);
2016 if (snum < 0 || !netname) {
2020 /* check it's a supported varient */
2021 if (!prefix_ok(str1,"zWrLh")) {
2024 if (!check_share_info(uLevel,str2)) {
2028 *rdata = smb_realloc_limit(*rdata,mdrcnt);
2033 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
2034 if (*rdata_len < 0) {
2039 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2043 SSVAL(*rparam,0,NERR_Success);
2044 SSVAL(*rparam,2,0); /* converter word */
2045 SSVAL(*rparam,4,*rdata_len);
2050 /****************************************************************************
2051 View the list of available shares.
2053 This function is the server side of the NetShareEnum() RAP call.
2054 It fills the return buffer with share names and share comments.
2055 Note that the return buffer normally (in all known cases) allows only
2056 twelve byte strings for share names (plus one for a nul terminator).
2057 Share names longer than 12 bytes must be skipped.
2058 ****************************************************************************/
2060 static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
2061 connection_struct *conn, uint16 vuid,
2062 char *param, int tpscnt,
2063 char *data, int tdscnt,
2071 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2072 char *str2 = skip_string(param,tpscnt,str1);
2073 char *p = skip_string(param,tpscnt,str2);
2074 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2075 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2078 int total=0,counted=0;
2079 bool missed = False;
2081 int data_len, fixed_len, string_len;
2082 int f_len = 0, s_len = 0;
2084 if (!str1 || !str2 || !p) {
2088 if (!prefix_ok(str1,"WrLeh")) {
2091 if (!check_share_info(uLevel,str2)) {
2095 /* Ensure all the usershares are loaded. */
2097 load_registry_shares();
2098 count = load_usershare_shares();
2101 data_len = fixed_len = string_len = 0;
2102 for (i=0;i<count;i++) {
2103 fstring servicename_dos;
2104 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2107 push_ascii_fstring(servicename_dos, lp_servicename(i));
2108 /* Maximum name length = 13. */
2109 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2111 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2112 if (data_len < buf_len) {
2115 string_len += s_len;
2122 *rdata_len = fixed_len + string_len;
2123 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2128 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2133 for( i = 0; i < count; i++ ) {
2134 fstring servicename_dos;
2135 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2139 push_ascii_fstring(servicename_dos, lp_servicename(i));
2140 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2141 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2148 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2152 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2154 SSVAL(*rparam,4,counted);
2155 SSVAL(*rparam,6,total);
2157 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2158 counted,total,uLevel,
2159 buf_len,*rdata_len,mdrcnt));
2164 /****************************************************************************
2166 ****************************************************************************/
2168 static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
2169 connection_struct *conn,uint16 vuid,
2170 char *param, int tpscnt,
2171 char *data, int tdscnt,
2172 int mdrcnt,int mprcnt,
2173 char **rdata,char **rparam,
2174 int *rdata_len,int *rparam_len)
2176 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2177 char *str2 = skip_string(param,tpscnt,str1);
2178 char *p = skip_string(param,tpscnt,str2);
2179 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2182 char *pathname = NULL;
2183 unsigned int offset;
2185 size_t converted_size;
2187 WERROR werr = WERR_OK;
2188 TALLOC_CTX *mem_ctx = talloc_tos();
2190 struct rpc_pipe_client *cli = NULL;
2191 union srvsvc_NetShareInfo info;
2192 struct srvsvc_NetShareInfo2 info2;
2193 struct dcerpc_binding_handle *b;
2195 if (!str1 || !str2 || !p) {
2199 /* check it's a supported varient */
2200 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2203 if (!check_share_info(uLevel,str2)) {
2210 /* Do we have a string ? */
2211 if (skip_string(data,mdrcnt,data) == NULL) {
2214 pull_ascii_fstring(sharename,data);
2220 /* only support disk share adds */
2221 if (SVAL(data,14)!=STYPE_DISKTREE) {
2225 offset = IVAL(data, 16);
2226 if (offset >= mdrcnt) {
2227 res = ERRinvalidparam;
2231 /* Do we have a string ? */
2232 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2235 pull_ascii_fstring(comment, offset? (data+offset) : "");
2237 offset = IVAL(data, 26);
2239 if (offset >= mdrcnt) {
2240 res = ERRinvalidparam;
2244 /* Do we have a string ? */
2245 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2249 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2250 offset ? (data+offset) : "", &converted_size))
2252 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2260 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
2262 &conn->sconn->client_id,
2263 conn->sconn->msg_ctx,
2265 if (!NT_STATUS_IS_OK(status)) {
2266 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2267 nt_errstr(status)));
2268 res = W_ERROR_V(ntstatus_to_werror(status));
2272 b = cli->binding_handle;
2274 info2.name = sharename;
2275 info2.type = STYPE_DISKTREE;
2276 info2.comment = comment;
2277 info2.permissions = 0;
2278 info2.max_users = 0;
2279 info2.current_users = 0;
2280 info2.path = pathname;
2281 info2.password = NULL;
2283 info.info2 = &info2;
2285 status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
2286 cli->srv_name_slash,
2291 if (!NT_STATUS_IS_OK(status)) {
2292 res = W_ERROR_V(ntstatus_to_werror(status));
2295 if (!W_ERROR_IS_OK(werr)) {
2296 res = W_ERROR_V(werr);
2301 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2305 SSVAL(*rparam,0,NERR_Success);
2306 SSVAL(*rparam,2,0); /* converter word */
2307 SSVAL(*rparam,4,*rdata_len);
2315 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2320 SSVAL(*rparam,0,res);
2325 /****************************************************************************
2326 view list of groups available
2327 ****************************************************************************/
2329 static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
2330 connection_struct *conn,uint16 vuid,
2331 char *param, int tpscnt,
2332 char *data, int tdscnt,
2333 int mdrcnt,int mprcnt,
2334 char **rdata,char **rparam,
2335 int *rdata_len,int *rparam_len)
2339 int resume_context, cli_buf_size;
2340 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2341 char *str2 = skip_string(param,tpscnt,str1);
2342 char *p = skip_string(param,tpscnt,str2);
2344 uint32_t num_groups;
2345 uint32_t resume_handle;
2346 struct rpc_pipe_client *samr_pipe;
2347 struct policy_handle samr_handle, domain_handle;
2348 NTSTATUS status, result;
2349 struct dcerpc_binding_handle *b;
2351 if (!str1 || !str2 || !p) {
2355 if (strcmp(str1,"WrLeh") != 0) {
2360 * W-> resume context (number of users to skip)
2361 * r -> return parameter pointer to receive buffer
2362 * L -> length of receive buffer
2363 * e -> return parameter number of entries
2364 * h -> return parameter total number of users
2367 if (strcmp("B21",str2) != 0) {
2371 status = rpc_pipe_open_internal(
2372 talloc_tos(), &ndr_table_samr.syntax_id,
2373 conn->session_info, &conn->sconn->client_id,
2374 conn->sconn->msg_ctx, &samr_pipe);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2377 nt_errstr(status)));
2381 b = samr_pipe->binding_handle;
2383 status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(),
2384 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
2386 if (!NT_STATUS_IS_OK(status)) {
2387 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2388 nt_errstr(status)));
2391 if (!NT_STATUS_IS_OK(result)) {
2392 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2393 nt_errstr(result)));
2397 status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
2398 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2399 get_global_sam_sid(), &domain_handle,
2401 if (!NT_STATUS_IS_OK(status)) {
2402 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2403 nt_errstr(status)));
2404 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2407 if (!NT_STATUS_IS_OK(result)) {
2408 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2409 nt_errstr(result)));
2410 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2414 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2415 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2416 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2417 "%d\n", resume_context, cli_buf_size));
2419 *rdata_len = cli_buf_size;
2420 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2427 errflags = NERR_Success;
2432 struct samr_SamArray *sam_entries;
2433 uint32_t num_entries;
2435 status = dcerpc_samr_EnumDomainGroups(b, talloc_tos(),
2441 if (!NT_STATUS_IS_OK(status)) {
2442 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2443 "%s\n", nt_errstr(status)));
2446 if (!NT_STATUS_IS_OK(result)) {
2448 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2449 "%s\n", nt_errstr(result)));
2453 if (num_entries == 0) {
2454 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2455 "no entries -- done\n"));
2459 for(i=0; i<num_entries; i++) {
2462 name = sam_entries->entries[i].name.string;
2464 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2465 /* set overflow error */
2466 DEBUG(3,("overflow on entry %d group %s\n", i,
2472 /* truncate the name at 21 chars. */
2474 strlcpy(p, name, 21);
2475 DEBUG(10,("adding entry %d group %s\n", i, p));
2477 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2482 if (errflags != NERR_Success) {
2486 TALLOC_FREE(sam_entries);
2489 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2490 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2492 *rdata_len = PTR_DIFF(p,*rdata);
2495 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2499 SSVAL(*rparam, 0, errflags);
2500 SSVAL(*rparam, 2, 0); /* converter word */
2501 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2502 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2507 /*******************************************************************
2508 Get groups that a user is a member of.
2509 ******************************************************************/
2511 static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
2512 connection_struct *conn,uint16 vuid,
2513 char *param, int tpscnt,
2514 char *data, int tdscnt,
2515 int mdrcnt,int mprcnt,
2516 char **rdata,char **rparam,
2517 int *rdata_len,int *rparam_len)
2519 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2520 char *str2 = skip_string(param,tpscnt,str1);
2521 char *UserName = skip_string(param,tpscnt,str2);
2522 char *p = skip_string(param,tpscnt,UserName);
2523 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2524 const char *level_string;
2530 struct rpc_pipe_client *samr_pipe;
2531 struct policy_handle samr_handle, domain_handle, user_handle;
2532 struct lsa_String name;
2533 struct lsa_Strings names;
2534 struct samr_Ids type, rid;
2535 struct samr_RidWithAttributeArray *rids;
2536 NTSTATUS status, result;
2537 struct dcerpc_binding_handle *b;
2539 if (!str1 || !str2 || !UserName || !p) {
2544 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2549 /* check it's a supported varient */
2551 if ( strcmp(str1,"zWrLeh") != 0 )
2556 level_string = "B21";
2562 if (strcmp(level_string,str2) != 0)
2565 *rdata_len = mdrcnt + 1024;
2566 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2571 SSVAL(*rparam,0,NERR_Success);
2572 SSVAL(*rparam,2,0); /* converter word */
2575 endp = *rdata + *rdata_len;
2577 status = rpc_pipe_open_internal(
2578 talloc_tos(), &ndr_table_samr.syntax_id,
2579 conn->session_info, &conn->sconn->client_id,
2580 conn->sconn->msg_ctx, &samr_pipe);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2583 nt_errstr(status)));
2587 b = samr_pipe->binding_handle;
2589 status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(),
2590 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
2592 if (!NT_STATUS_IS_OK(status)) {
2593 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2594 nt_errstr(status)));
2597 if (!NT_STATUS_IS_OK(result)) {
2598 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2599 nt_errstr(result)));
2603 status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
2604 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2605 get_global_sam_sid(), &domain_handle,
2607 if (!NT_STATUS_IS_OK(status)) {
2608 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2609 nt_errstr(status)));
2612 if (!NT_STATUS_IS_OK(result)) {
2613 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2614 nt_errstr(result)));
2618 name.string = UserName;
2620 status = dcerpc_samr_LookupNames(b, talloc_tos(),
2621 &domain_handle, 1, &name,
2624 if (!NT_STATUS_IS_OK(status)) {
2625 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2626 nt_errstr(status)));
2629 if (!NT_STATUS_IS_OK(result)) {
2630 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2631 nt_errstr(result)));
2635 if (type.ids[0] != SID_NAME_USER) {
2636 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2637 sid_type_lookup(type.ids[0])));
2641 status = dcerpc_samr_OpenUser(b, talloc_tos(),
2643 SAMR_USER_ACCESS_GET_GROUPS,
2644 rid.ids[0], &user_handle,
2646 if (!NT_STATUS_IS_OK(status)) {
2647 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2648 nt_errstr(status)));
2651 if (!NT_STATUS_IS_OK(result)) {
2652 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2653 nt_errstr(result)));
2657 status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
2658 &user_handle, &rids,
2660 if (!NT_STATUS_IS_OK(status)) {
2661 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2662 nt_errstr(status)));
2665 if (!NT_STATUS_IS_OK(result)) {
2666 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2667 nt_errstr(result)));
2671 for (i=0; i<rids->count; i++) {
2673 status = dcerpc_samr_LookupRids(b, talloc_tos(),
2675 1, &rids->rids[i].rid,
2678 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result) && (names.count == 1)) {
2679 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2685 *rdata_len = PTR_DIFF(p,*rdata);
2687 SSVAL(*rparam,4,count); /* is this right?? */
2688 SSVAL(*rparam,6,count); /* is this right?? */
2693 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
2695 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2697 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2702 /*******************************************************************
2704 ******************************************************************/
2706 static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
2707 connection_struct *conn, uint16 vuid,
2708 char *param, int tpscnt,
2709 char *data, int tdscnt,
2710 int mdrcnt,int mprcnt,
2711 char **rdata,char **rparam,
2712 int *rdata_len,int *rparam_len)
2717 int i, resume_context, cli_buf_size;
2718 uint32_t resume_handle;
2720 struct rpc_pipe_client *samr_pipe;
2721 struct policy_handle samr_handle, domain_handle;
2722 NTSTATUS status, result;
2724 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2725 char *str2 = skip_string(param,tpscnt,str1);
2726 char *p = skip_string(param,tpscnt,str2);
2729 struct dcerpc_binding_handle *b;
2731 if (!str1 || !str2 || !p) {
2735 if (strcmp(str1,"WrLeh") != 0)
2738 * W-> resume context (number of users to skip)
2739 * r -> return parameter pointer to receive buffer
2740 * L -> length of receive buffer
2741 * e -> return parameter number of entries
2742 * h -> return parameter total number of users
2745 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2746 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2747 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2748 resume_context, cli_buf_size));
2751 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2756 /* check it's a supported varient */
2757 if (strcmp("B21",str2) != 0)
2760 *rdata_len = cli_buf_size;
2761 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2767 endp = *rdata + *rdata_len;
2769 status = rpc_pipe_open_internal(
2770 talloc_tos(), &ndr_table_samr.syntax_id,
2771 conn->session_info, &conn->sconn->client_id,
2772 conn->sconn->msg_ctx, &samr_pipe);
2773 if (!NT_STATUS_IS_OK(status)) {
2774 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2775 nt_errstr(status)));
2779 b = samr_pipe->binding_handle;
2781 status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(),
2782 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
2784 if (!NT_STATUS_IS_OK(status)) {
2785 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2786 nt_errstr(status)));
2789 if (!NT_STATUS_IS_OK(result)) {
2790 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2791 nt_errstr(result)));
2795 status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
2796 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2797 get_global_sam_sid(), &domain_handle,
2799 if (!NT_STATUS_IS_OK(status)) {
2800 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2801 nt_errstr(status)));
2802 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2805 if (!NT_STATUS_IS_OK(result)) {
2806 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2807 nt_errstr(result)));
2808 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2812 errflags=NERR_Success;
2817 struct samr_SamArray *sam_entries;
2818 uint32_t num_entries;
2820 status = dcerpc_samr_EnumDomainUsers(b, talloc_tos(),
2827 if (!NT_STATUS_IS_OK(status)) {
2828 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2829 "%s\n", nt_errstr(status)));
2832 if (!NT_STATUS_IS_OK(result)) {
2833 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2834 "%s\n", nt_errstr(result)));
2838 if (num_entries == 0) {
2839 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2840 "no entries -- done\n"));
2844 for (i=0; i<num_entries; i++) {
2847 name = sam_entries->entries[i].name.string;
2849 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2850 &&(strlen(name)<=21)) {
2851 strlcpy(p,name,PTR_DIFF(endp,p));
2852 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2853 "username %s\n",count_sent,p));
2857 /* set overflow error */
2858 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2859 "username %s\n",count_sent,name));
2865 if (errflags != NERR_Success) {
2869 TALLOC_FREE(sam_entries);
2872 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2873 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2875 *rdata_len = PTR_DIFF(p,*rdata);
2877 SSVAL(*rparam,0,errflags);
2878 SSVAL(*rparam,2,0); /* converter word */
2879 SSVAL(*rparam,4,count_sent); /* is this right?? */
2880 SSVAL(*rparam,6,num_users); /* is this right?? */
2885 /****************************************************************************
2886 Get the time of day info.
2887 ****************************************************************************/
2889 static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
2890 connection_struct *conn,uint16 vuid,
2891 char *param, int tpscnt,
2892 char *data, int tdscnt,
2893 int mdrcnt,int mprcnt,
2894 char **rdata,char **rparam,
2895 int *rdata_len,int *rparam_len)
2898 time_t unixdate = time(NULL);
2902 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2908 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2913 SSVAL(*rparam,0,NERR_Success);
2914 SSVAL(*rparam,2,0); /* converter word */
2918 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2919 by NT in a "net time" operation,
2920 it seems to ignore the one below */
2922 /* the client expects to get localtime, not GMT, in this bit
2923 (I think, this needs testing) */
2924 t = localtime(&unixdate);
2929 SIVAL(p,4,0); /* msecs ? */
2930 SCVAL(p,8,t->tm_hour);
2931 SCVAL(p,9,t->tm_min);
2932 SCVAL(p,10,t->tm_sec);
2933 SCVAL(p,11,0); /* hundredths of seconds */
2934 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2935 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2936 SCVAL(p,16,t->tm_mday);
2937 SCVAL(p,17,t->tm_mon + 1);
2938 SSVAL(p,18,1900+t->tm_year);
2939 SCVAL(p,20,t->tm_wday);
2944 /****************************************************************************
2945 Set the user password.
2946 *****************************************************************************/
2948 static bool api_SetUserPassword(struct smbd_server_connection *sconn,
2949 connection_struct *conn,uint16 vuid,
2950 char *param, int tpscnt,
2951 char *data, int tdscnt,
2952 int mdrcnt,int mprcnt,
2953 char **rdata,char **rparam,
2954 int *rdata_len,int *rparam_len)
2956 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2959 fstring pass1,pass2;
2960 TALLOC_CTX *mem_ctx = talloc_tos();
2961 NTSTATUS status, result;
2962 struct rpc_pipe_client *cli = NULL;
2963 struct policy_handle connect_handle, domain_handle, user_handle;
2964 struct lsa_String domain_name;
2965 struct dom_sid2 *domain_sid;
2966 struct lsa_String names;
2967 struct samr_Ids rids;
2968 struct samr_Ids types;
2969 struct samr_Password old_lm_hash;
2970 struct samr_Password new_lm_hash;
2971 int errcode = NERR_badpass;
2975 struct dcerpc_binding_handle *b = NULL;
2977 /* Skip 2 strings. */
2978 p = skip_string(param,tpscnt,np);
2979 p = skip_string(param,tpscnt,p);
2985 /* Do we have a string ? */
2986 if (skip_string(param,tpscnt,p) == NULL) {
2989 pull_ascii_fstring(user,p);
2991 p = skip_string(param,tpscnt,p);
2996 memset(pass1,'\0',sizeof(pass1));
2997 memset(pass2,'\0',sizeof(pass2));
2999 * We use 31 here not 32 as we're checking
3000 * the last byte we want to access is safe.
3002 if (!is_offset_safe(param,tpscnt,p,31)) {
3006 memcpy(pass2,p+16,16);
3008 encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
3009 if (encrypted == -1) {
3010 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3014 min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
3015 if (min_pwd_length == -1) {
3016 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3021 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3028 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
3029 user, encrypted, min_pwd_length));
3031 ZERO_STRUCT(connect_handle);
3032 ZERO_STRUCT(domain_handle);
3033 ZERO_STRUCT(user_handle);
3035 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
3037 &conn->sconn->client_id,
3038 conn->sconn->msg_ctx,
3040 if (!NT_STATUS_IS_OK(status)) {
3041 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
3042 nt_errstr(status)));
3043 errcode = W_ERROR_V(ntstatus_to_werror(status));
3047 b = cli->binding_handle;
3049 status = dcerpc_samr_Connect2(b, mem_ctx,
3051 SAMR_ACCESS_CONNECT_TO_SERVER |
3052 SAMR_ACCESS_ENUM_DOMAINS |
3053 SAMR_ACCESS_LOOKUP_DOMAIN,
3056 if (!NT_STATUS_IS_OK(status)) {
3057 errcode = W_ERROR_V(ntstatus_to_werror(status));
3060 if (!NT_STATUS_IS_OK(result)) {
3061 errcode = W_ERROR_V(ntstatus_to_werror(result));
3065 init_lsa_String(&domain_name, get_global_sam_name());
3067 status = dcerpc_samr_LookupDomain(b, mem_ctx,
3072 if (!NT_STATUS_IS_OK(status)) {
3073 errcode = W_ERROR_V(ntstatus_to_werror(status));
3076 if (!NT_STATUS_IS_OK(result)) {
3077 errcode = W_ERROR_V(ntstatus_to_werror(result));
3081 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3083 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
3087 if (!NT_STATUS_IS_OK(status)) {
3088 errcode = W_ERROR_V(ntstatus_to_werror(status));
3091 if (!NT_STATUS_IS_OK(result)) {
3092 errcode = W_ERROR_V(ntstatus_to_werror(result));
3096 init_lsa_String(&names, user);
3098 status = dcerpc_samr_LookupNames(b, mem_ctx,
3105 if (!NT_STATUS_IS_OK(status)) {
3106 errcode = W_ERROR_V(ntstatus_to_werror(status));
3109 if (!NT_STATUS_IS_OK(result)) {
3110 errcode = W_ERROR_V(ntstatus_to_werror(result));
3114 if (rids.count != 1) {
3115 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
3118 if (rids.count != types.count) {
3119 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3122 if (types.ids[0] != SID_NAME_USER) {
3123 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3129 status = dcerpc_samr_OpenUser(b, mem_ctx,
3131 SAMR_USER_ACCESS_CHANGE_PASSWORD,
3135 if (!NT_STATUS_IS_OK(status)) {
3136 errcode = W_ERROR_V(ntstatus_to_werror(status));
3139 if (!NT_STATUS_IS_OK(result)) {
3140 errcode = W_ERROR_V(ntstatus_to_werror(result));
3144 if (encrypted == 0) {
3145 E_deshash(pass1, old_lm_hash.hash);
3146 E_deshash(pass2, new_lm_hash.hash);
3148 ZERO_STRUCT(old_lm_hash);
3149 ZERO_STRUCT(new_lm_hash);
3150 memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
3151 memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16));
3154 status = dcerpc_samr_ChangePasswordUser(b, mem_ctx,
3156 true, /* lm_present */
3159 false, /* nt_present */
3160 NULL, /* old_nt_crypted */
3161 NULL, /* new_nt_crypted */
3162 false, /* cross1_present */
3163 NULL, /* nt_cross */
3164 false, /* cross2_present */
3165 NULL, /* lm_cross */
3167 if (!NT_STATUS_IS_OK(status)) {
3168 errcode = W_ERROR_V(ntstatus_to_werror(status));
3171 if (!NT_STATUS_IS_OK(result)) {
3172 errcode = W_ERROR_V(ntstatus_to_werror(result));
3176 errcode = NERR_Success;
3179 if (b && is_valid_policy_hnd(&user_handle)) {
3180 dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
3182 if (b && is_valid_policy_hnd(&domain_handle)) {
3183 dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
3185 if (b && is_valid_policy_hnd(&connect_handle)) {
3186 dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
3189 memset((char *)pass1,'\0',sizeof(fstring));
3190 memset((char *)pass2,'\0',sizeof(fstring));
3192 SSVAL(*rparam,0,errcode);
3193 SSVAL(*rparam,2,0); /* converter word */
3197 /****************************************************************************
3198 Set the user password (SamOEM version - gets plaintext).
3199 ****************************************************************************/
3201 static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
3202 connection_struct *conn,uint16 vuid,
3203 char *param, int tpscnt,
3204 char *data, int tdscnt,
3205 int mdrcnt,int mprcnt,
3206 char **rdata,char **rparam,
3207 int *rdata_len,int *rparam_len)
3210 char *p = get_safe_str_ptr(param,tpscnt,param,2);
3212 TALLOC_CTX *mem_ctx = talloc_tos();
3213 NTSTATUS status, result;
3214 struct rpc_pipe_client *cli = NULL;
3215 struct lsa_AsciiString server, account;
3216 struct samr_CryptPassword password;
3217 struct samr_Password hash;
3218 int errcode = NERR_badpass;
3220 struct dcerpc_binding_handle *b;
3223 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3233 SSVAL(*rparam,0,NERR_badpass);
3236 * Check the parameter definition is correct.
3239 /* Do we have a string ? */
3240 if (skip_string(param,tpscnt,p) == 0) {
3243 if(!strequal(p, "zsT")) {
3244 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3247 p = skip_string(param, tpscnt, p);
3252 /* Do we have a string ? */
3253 if (skip_string(param,tpscnt,p) == 0) {
3256 if(!strequal(p, "B516B16")) {
3257 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3260 p = skip_string(param,tpscnt,p);
3264 /* Do we have a string ? */
3265 if (skip_string(param,tpscnt,p) == 0) {
3268 p += pull_ascii_fstring(user,p);
3270 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3272 if (tdscnt != 532) {
3273 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3277 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3278 if (bufsize != 532) {
3279 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3283 memcpy(password.data, data, 516);
3284 memcpy(hash.hash, data+516, 16);
3286 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
3288 &conn->sconn->client_id,
3289 conn->sconn->msg_ctx,
3291 if (!NT_STATUS_IS_OK(status)) {
3292 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3293 nt_errstr(status)));
3294 errcode = W_ERROR_V(ntstatus_to_werror(status));
3298 b = cli->binding_handle;
3300 init_lsa_AsciiString(&server, global_myname());
3301 init_lsa_AsciiString(&account, user);
3303 status = dcerpc_samr_OemChangePasswordUser2(b, mem_ctx,
3309 if (!NT_STATUS_IS_OK(status)) {
3310 errcode = W_ERROR_V(ntstatus_to_werror(status));
3313 if (!NT_STATUS_IS_OK(result)) {
3314 errcode = W_ERROR_V(ntstatus_to_werror(result));
3318 errcode = NERR_Success;
3320 SSVAL(*rparam,0,errcode);
3321 SSVAL(*rparam,2,0); /* converter word */
3326 /****************************************************************************
3329 ****************************************************************************/
3331 static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
3332 connection_struct *conn,uint16 vuid,
3333 char *param, int tpscnt,
3334 char *data, int tdscnt,
3335 int mdrcnt,int mprcnt,
3336 char **rdata,char **rparam,
3337 int *rdata_len,int *rparam_len)
3339 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3340 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3341 char *str2 = skip_string(param,tpscnt,str1);
3342 char *p = skip_string(param,tpscnt,str2);
3346 WERROR werr = WERR_OK;
3348 TALLOC_CTX *mem_ctx = talloc_tos();
3350 struct rpc_pipe_client *cli = NULL;
3351 struct dcerpc_binding_handle *b = NULL;
3352 struct policy_handle handle;
3353 struct spoolss_DevmodeContainer devmode_ctr;
3354 enum spoolss_JobControl command;
3356 if (!str1 || !str2 || !p) {
3360 * We use 1 here not 2 as we're checking
3361 * the last byte we want to access is safe.
3363 if (!is_offset_safe(param,tpscnt,p,1)) {
3366 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3369 /* check it's a supported varient */
3370 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3374 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3380 ZERO_STRUCT(handle);
3382 status = rpc_pipe_open_interface(conn,
3383 &ndr_table_spoolss.syntax_id,
3385 &conn->sconn->client_id,
3386 conn->sconn->msg_ctx,
3388 if (!NT_STATUS_IS_OK(status)) {
3389 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3390 nt_errstr(status)));
3391 errcode = W_ERROR_V(ntstatus_to_werror(status));
3394 b = cli->binding_handle;
3396 ZERO_STRUCT(devmode_ctr);
3398 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3402 JOB_ACCESS_ADMINISTER,
3405 if (!NT_STATUS_IS_OK(status)) {
3406 errcode = W_ERROR_V(ntstatus_to_werror(status));
3409 if (!W_ERROR_IS_OK(werr)) {
3410 errcode = W_ERROR_V(werr);
3414 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3415 * and NERR_DestNotFound if share did not exist */
3417 errcode = NERR_Success;
3420 case 81: /* delete */
3421 command = SPOOLSS_JOB_CONTROL_DELETE;
3423 case 82: /* pause */
3424 command = SPOOLSS_JOB_CONTROL_PAUSE;
3426 case 83: /* resume */
3427 command = SPOOLSS_JOB_CONTROL_RESUME;
3430 errcode = NERR_notsupported;
3434 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3437 NULL, /* unique ptr ctr */
3440 if (!NT_STATUS_IS_OK(status)) {
3441 errcode = W_ERROR_V(ntstatus_to_werror(status));
3444 if (!W_ERROR_IS_OK(werr)) {
3445 errcode = W_ERROR_V(werr);
3450 if (b && is_valid_policy_hnd(&handle)) {
3451 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3454 SSVAL(*rparam,0,errcode);
3455 SSVAL(*rparam,2,0); /* converter word */
3460 /****************************************************************************
3461 Purge a print queue - or pause or resume it.
3462 ****************************************************************************/
3464 static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
3465 connection_struct *conn,uint16 vuid,
3466 char *param, int tpscnt,
3467 char *data, int tdscnt,
3468 int mdrcnt,int mprcnt,
3469 char **rdata,char **rparam,
3470 int *rdata_len,int *rparam_len)
3472 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3473 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3474 char *str2 = skip_string(param,tpscnt,str1);
3475 char *QueueName = skip_string(param,tpscnt,str2);
3476 int errcode = NERR_notsupported;
3477 WERROR werr = WERR_OK;
3480 TALLOC_CTX *mem_ctx = talloc_tos();
3481 struct rpc_pipe_client *cli = NULL;
3482 struct dcerpc_binding_handle *b = NULL;
3483 struct policy_handle handle;
3484 struct spoolss_SetPrinterInfoCtr info_ctr;
3485 struct spoolss_DevmodeContainer devmode_ctr;
3486 struct sec_desc_buf secdesc_ctr;
3487 enum spoolss_PrinterControl command;
3489 if (!str1 || !str2 || !QueueName) {
3493 /* check it's a supported varient */
3494 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3498 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3504 if (skip_string(param,tpscnt,QueueName) == NULL) {
3508 ZERO_STRUCT(handle);
3510 status = rpc_pipe_open_interface(conn,
3511 &ndr_table_spoolss.syntax_id,
3513 &conn->sconn->client_id,
3514 conn->sconn->msg_ctx,
3516 if (!NT_STATUS_IS_OK(status)) {
3517 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3518 nt_errstr(status)));
3519 errcode = W_ERROR_V(ntstatus_to_werror(status));
3522 b = cli->binding_handle;
3524 ZERO_STRUCT(devmode_ctr);
3526 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3530 SEC_FLAG_MAXIMUM_ALLOWED,
3533 if (!NT_STATUS_IS_OK(status)) {
3534 errcode = W_ERROR_V(ntstatus_to_werror(status));
3537 if (!W_ERROR_IS_OK(werr)) {
3538 errcode = W_ERROR_V(werr);
3543 case 74: /* Pause queue */
3544 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3546 case 75: /* Resume queue */
3547 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3549 case 103: /* Purge */
3550 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3553 werr = WERR_NOT_SUPPORTED;
3557 if (!W_ERROR_IS_OK(werr)) {
3558 errcode = W_ERROR_V(werr);
3562 ZERO_STRUCT(info_ctr);
3563 ZERO_STRUCT(secdesc_ctr);
3565 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
3572 if (!NT_STATUS_IS_OK(status)) {
3573 errcode = W_ERROR_V(ntstatus_to_werror(status));
3576 if (!W_ERROR_IS_OK(werr)) {
3577 errcode = W_ERROR_V(werr);
3581 errcode = W_ERROR_V(werr);
3585 if (b && is_valid_policy_hnd(&handle)) {
3586 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3589 SSVAL(*rparam,0,errcode);
3590 SSVAL(*rparam,2,0); /* converter word */
3595 /****************************************************************************
3596 set the property of a print job (undocumented?)
3597 ? function = 0xb -> set name of print job
3598 ? function = 0x6 -> move print job up/down
3599 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3600 or <WWsTP> <WB21BB16B10zWWzDDz>
3601 ****************************************************************************/
3603 static int check_printjob_info(struct pack_desc* desc,
3604 int uLevel, char* id)
3606 desc->subformat = NULL;
3608 case 0: desc->format = "W"; break;
3609 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3610 case 2: desc->format = "WWzWWDDzz"; break;
3611 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3612 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3614 DEBUG(0,("check_printjob_info: invalid level %d\n",
3618 if (id == NULL || strcmp(desc->format,id) != 0) {
3619 DEBUG(0,("check_printjob_info: invalid format %s\n",
3620 id ? id : "<NULL>" ));
3626 static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
3627 connection_struct *conn, uint16 vuid,
3628 char *param, int tpscnt,
3629 char *data, int tdscnt,
3630 int mdrcnt,int mprcnt,
3631 char **rdata,char **rparam,
3632 int *rdata_len,int *rparam_len)
3634 struct pack_desc desc;
3635 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3636 char *str2 = skip_string(param,tpscnt,str1);
3637 char *p = skip_string(param,tpscnt,str2);
3640 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3641 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3644 TALLOC_CTX *mem_ctx = talloc_tos();
3647 struct rpc_pipe_client *cli = NULL;
3648 struct dcerpc_binding_handle *b = NULL;
3649 struct policy_handle handle;
3650 struct spoolss_DevmodeContainer devmode_ctr;
3651 struct spoolss_JobInfoContainer ctr;
3652 union spoolss_JobInfo info;
3653 struct spoolss_SetJobInfo1 info1;
3655 if (!str1 || !str2 || !p) {
3659 * We use 1 here not 2 as we're checking
3660 * the last byte we want to access is safe.
3662 if (!is_offset_safe(param,tpscnt,p,1)) {
3665 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3668 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3675 /* check it's a supported varient */
3676 if ((strcmp(str1,"WWsTP")) ||
3677 (!check_printjob_info(&desc,uLevel,str2)))
3680 errcode = NERR_notsupported;
3684 /* change print job name, data gives the name */
3690 ZERO_STRUCT(handle);
3692 status = rpc_pipe_open_interface(conn,
3693 &ndr_table_spoolss.syntax_id,
3695 &conn->sconn->client_id,
3696 conn->sconn->msg_ctx,
3698 if (!NT_STATUS_IS_OK(status)) {
3699 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3700 nt_errstr(status)));
3701 errcode = W_ERROR_V(ntstatus_to_werror(status));
3704 b = cli->binding_handle;
3706 ZERO_STRUCT(devmode_ctr);
3708 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3715 if (!NT_STATUS_IS_OK(status)) {
3716 errcode = W_ERROR_V(ntstatus_to_werror(status));
3719 if (!W_ERROR_IS_OK(werr)) {
3720 errcode = W_ERROR_V(werr);
3724 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3730 if (!W_ERROR_IS_OK(werr)) {
3731 errcode = W_ERROR_V(werr);
3737 info1.job_id = info.info1.job_id;
3738 info1.printer_name = info.info1.printer_name;
3739 info1.user_name = info.info1.user_name;
3740 info1.document_name = data;
3741 info1.data_type = info.info1.data_type;
3742 info1.text_status = info.info1.text_status;
3743 info1.status = info.info1.status;
3744 info1.priority = info.info1.priority;
3745 info1.position = info.info1.position;
3746 info1.total_pages = info.info1.total_pages;
3747 info1.pages_printed = info.info1.pages_printed;
3748 info1.submitted = info.info1.submitted;
3751 ctr.info.info1 = &info1;
3753 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3759 if (!NT_STATUS_IS_OK(status)) {
3760 errcode = W_ERROR_V(ntstatus_to_werror(status));
3763 if (!W_ERROR_IS_OK(werr)) {
3764 errcode = W_ERROR_V(werr);
3768 errcode = NERR_Success;
3771 if (b && is_valid_policy_hnd(&handle)) {
3772 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3775 SSVALS(*rparam,0,errcode);
3776 SSVAL(*rparam,2,0); /* converter word */
3782 /****************************************************************************
3783 Get info about the server.
3784 ****************************************************************************/
3786 static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
3787 connection_struct *conn,uint16 vuid,
3788 char *param, int tpscnt,
3789 char *data, int tdscnt,
3790 int mdrcnt,int mprcnt,
3791 char **rdata,char **rparam,
3792 int *rdata_len,int *rparam_len)
3794 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3795 char *str2 = skip_string(param,tpscnt,str1);
3796 char *p = skip_string(param,tpscnt,str2);
3797 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3803 TALLOC_CTX *mem_ctx = talloc_tos();
3804 struct rpc_pipe_client *cli = NULL;
3805 union srvsvc_NetSrvInfo info;
3807 struct dcerpc_binding_handle *b;
3809 if (!str1 || !str2 || !p) {
3813 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3815 /* check it's a supported varient */
3816 if (!prefix_ok(str1,"WrLh")) {
3822 if (strcmp(str2,"B16") != 0) {
3828 if (strcmp(str2,"B16BBDz") != 0) {
3834 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3840 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3846 if (strcmp(str2,"DN") != 0) {
3852 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3861 *rdata_len = mdrcnt;
3862 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3868 p2 = p + struct_len;
3870 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
3872 &conn->sconn->client_id,
3873 conn->sconn->msg_ctx,
3875 if (!NT_STATUS_IS_OK(status)) {
3876 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3877 nt_errstr(status)));
3878 errcode = W_ERROR_V(ntstatus_to_werror(status));
3882 b = cli->binding_handle;
3884 status = dcerpc_srvsvc_NetSrvGetInfo(b, mem_ctx,
3889 if (!NT_STATUS_IS_OK(status)) {
3890 errcode = W_ERROR_V(ntstatus_to_werror(status));
3893 if (!W_ERROR_IS_OK(werr)) {
3894 errcode = W_ERROR_V(werr);
3898 if (info.info101 == NULL) {
3899 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3904 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3905 STR_ASCII|STR_UPPER|STR_TERMINATE);
3909 SCVAL(p,0,info.info101->version_major);
3910 SCVAL(p,1,info.info101->version_minor);
3911 SIVAL(p,2,info.info101->server_type);
3913 if (mdrcnt == struct_len) {
3916 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3917 if (mdrcnt - struct_len <= 0) {
3921 info.info101->comment,
3922 MIN(mdrcnt - struct_len,
3923 MAX_SERVER_STRING_LENGTH),
3925 p2 = skip_string(*rdata,*rdata_len,p2);
3933 return False; /* not yet implemented */
3936 errcode = NERR_Success;
3940 *rdata_len = PTR_DIFF(p2,*rdata);
3943 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3947 SSVAL(*rparam,0,errcode);
3948 SSVAL(*rparam,2,0); /* converter word */
3949 SSVAL(*rparam,4,*rdata_len);
3954 /****************************************************************************
3955 Get info about the server.
3956 ****************************************************************************/
3958 static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
3959 connection_struct *conn,uint16 vuid,
3960 char *param, int tpscnt,
3961 char *data, int tdscnt,
3962 int mdrcnt,int mprcnt,
3963 char **rdata,char **rparam,
3964 int *rdata_len,int *rparam_len)
3966 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3967 char *str2 = skip_string(param,tpscnt,str1);
3968 char *p = skip_string(param,tpscnt,str2);
3971 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3973 if (!str1 || !str2 || !p) {
3977 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3980 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3985 /* check it's a supported varient */
3986 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3990 *rdata_len = mdrcnt + 1024;
3991 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3996 SSVAL(*rparam,0,NERR_Success);
3997 SSVAL(*rparam,2,0); /* converter word */
4000 endp = *rdata + *rdata_len;
4002 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
4007 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
4008 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
4010 p2 = skip_string(*rdata,*rdata_len,p2);
4016 SIVAL(p,0,PTR_DIFF(p2,*rdata));
4017 strlcpy(p2,conn->session_info->sanitized_username,PTR_DIFF(endp,p2));
4018 p2 = skip_string(*rdata,*rdata_len,p2);
4024 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
4025 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
4027 p2 = skip_string(*rdata,*rdata_len,p2);
4033 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
4034 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
4037 SIVAL(p,0,PTR_DIFF(p2,*rdata));
4038 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
4039 p2 = skip_string(*rdata,*rdata_len,p2);
4045 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
4046 strlcpy(p2,"",PTR_DIFF(endp,p2));
4047 p2 = skip_string(*rdata,*rdata_len,p2);
4053 *rdata_len = PTR_DIFF(p2,*rdata);
4055 SSVAL(*rparam,4,*rdata_len);
4060 /****************************************************************************
4061 get info about a user
4063 struct user_info_11 {
4064 char usri11_name[21]; 0-20
4066 char *usri11_comment; 22-25
4067 char *usri11_usr_comment; 26-29
4068 unsigned short usri11_priv; 30-31
4069 unsigned long usri11_auth_flags; 32-35
4070 long usri11_password_age; 36-39
4071 char *usri11_homedir; 40-43
4072 char *usri11_parms; 44-47
4073 long usri11_last_logon; 48-51
4074 long usri11_last_logoff; 52-55
4075 unsigned short usri11_bad_pw_count; 56-57
4076 unsigned short usri11_num_logons; 58-59
4077 char *usri11_logon_server; 60-63
4078 unsigned short usri11_country_code; 64-65
4079 char *usri11_workstations; 66-69
4080 unsigned long usri11_max_storage; 70-73
4081 unsigned short usri11_units_per_week; 74-75
4082 unsigned char *usri11_logon_hours; 76-79
4083 unsigned short usri11_code_page; 80-81
4088 usri11_name specifies the user name for which information is retrieved
4090 usri11_pad aligns the next data structure element to a word boundary
4092 usri11_comment is a null terminated ASCII comment
4094 usri11_user_comment is a null terminated ASCII comment about the user
4096 usri11_priv specifies the level of the privilege assigned to the user.
4097 The possible values are:
4099 Name Value Description
4100 USER_PRIV_GUEST 0 Guest privilege
4101 USER_PRIV_USER 1 User privilege
4102 USER_PRV_ADMIN 2 Administrator privilege
4104 usri11_auth_flags specifies the account operator privileges. The
4105 possible values are:
4107 Name Value Description
4108 AF_OP_PRINT 0 Print operator
4111 Leach, Naik [Page 28]
4115 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4118 AF_OP_COMM 1 Communications operator
4119 AF_OP_SERVER 2 Server operator
4120 AF_OP_ACCOUNTS 3 Accounts operator
4123 usri11_password_age specifies how many seconds have elapsed since the
4124 password was last changed.
4126 usri11_home_dir points to a null terminated ASCII string that contains
4127 the path name of the user's home directory.
4129 usri11_parms points to a null terminated ASCII string that is set
4130 aside for use by applications.
4132 usri11_last_logon specifies the time when the user last logged on.
4133 This value is stored as the number of seconds elapsed since
4134 00:00:00, January 1, 1970.
4136 usri11_last_logoff specifies the time when the user last logged off.
4137 This value is stored as the number of seconds elapsed since
4138 00:00:00, January 1, 1970. A value of 0 means the last logoff
4141 usri11_bad_pw_count specifies the number of incorrect passwords
4142 entered since the last successful logon.
4144 usri11_log1_num_logons specifies the number of times this user has
4145 logged on. A value of -1 means the number of logons is unknown.
4147 usri11_logon_server points to a null terminated ASCII string that
4148 contains the name of the server to which logon requests are sent.
4149 A null string indicates logon requests should be sent to the
4152 usri11_country_code specifies the country code for the user's language
4155 usri11_workstations points to a null terminated ASCII string that
4156 contains the names of workstations the user may log on from.
4157 There may be up to 8 workstations, with the names separated by
4158 commas. A null strings indicates there are no restrictions.
4160 usri11_max_storage specifies the maximum amount of disk space the user
4161 can occupy. A value of 0xffffffff indicates there are no
4164 usri11_units_per_week specifies the equal number of time units into
4165 which a week is divided. This value must be equal to 168.
4167 usri11_logon_hours points to a 21 byte (168 bits) string that
4168 specifies the time during which the user can log on. Each bit
4169 represents one unique hour in a week. The first bit (bit 0, word
4170 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4174 Leach, Naik [Page 29]
4178 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4181 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4182 are no restrictions.
4184 usri11_code_page specifies the code page for the user's language of
4187 All of the pointers in this data structure need to be treated
4188 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4189 to be ignored. The converter word returned in the parameters section
4190 needs to be subtracted from the lower 16 bits to calculate an offset
4191 into the return buffer where this ASCII string resides.
4193 There is no auxiliary data in the response.
4195 ****************************************************************************/
4197 #define usri11_name 0
4198 #define usri11_pad 21
4199 #define usri11_comment 22
4200 #define usri11_usr_comment 26
4201 #define usri11_full_name 30
4202 #define usri11_priv 34
4203 #define usri11_auth_flags 36
4204 #define usri11_password_age 40
4205 #define usri11_homedir 44
4206 #define usri11_parms 48
4207 #define usri11_last_logon 52
4208 #define usri11_last_logoff 56
4209 #define usri11_bad_pw_count 60
4210 #define usri11_num_logons 62
4211 #define usri11_logon_server 64
4212 #define usri11_country_code 68
4213 #define usri11_workstations 70
4214 #define usri11_max_storage 74
4215 #define usri11_units_per_week 78
4216 #define usri11_logon_hours 80
4217 #define usri11_code_page 84
4218 #define usri11_end 86
4220 static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
4221 connection_struct *conn, uint16 vuid,
4222 char *param, int tpscnt,
4223 char *data, int tdscnt,
4224 int mdrcnt,int mprcnt,
4225 char **rdata,char **rparam,
4226 int *rdata_len,int *rparam_len)
4228 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4229 char *str2 = skip_string(param,tpscnt,str1);
4230 char *UserName = skip_string(param,tpscnt,str2);
4231 char *p = skip_string(param,tpscnt,UserName);
4232 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4235 const char *level_string;
4237 TALLOC_CTX *mem_ctx = talloc_tos();
4238 NTSTATUS status, result;
4239 struct rpc_pipe_client *cli = NULL;
4240 struct policy_handle connect_handle, domain_handle, user_handle;
4241 struct lsa_String domain_name;
4242 struct dom_sid2 *domain_sid;
4243 struct lsa_String names;
4244 struct samr_Ids rids;
4245 struct samr_Ids types;
4246 int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
4248 union samr_UserInfo *info;
4249 struct dcerpc_binding_handle *b = NULL;
4251 if (!str1 || !str2 || !UserName || !p) {
4256 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4261 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4263 /* check it's a supported variant */
4264 if (strcmp(str1,"zWrLh") != 0) {
4268 case 0: level_string = "B21"; break;
4269 case 1: level_string = "B21BB16DWzzWz"; break;
4270 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4271 case 10: level_string = "B21Bzzz"; break;
4272 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4273 default: return False;
4276 if (strcmp(level_string,str2) != 0) {
4280 *rdata_len = mdrcnt + 1024;
4281 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4287 endp = *rdata + *rdata_len;
4288 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4293 ZERO_STRUCT(connect_handle);
4294 ZERO_STRUCT(domain_handle);
4295 ZERO_STRUCT(user_handle);
4297 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
4299 &conn->sconn->client_id,
4300 conn->sconn->msg_ctx,
4302 if (!NT_STATUS_IS_OK(status)) {
4303 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4304 nt_errstr(status)));
4305 errcode = W_ERROR_V(ntstatus_to_werror(status));
4309 b = cli->binding_handle;
4311 status = dcerpc_samr_Connect2(b, mem_ctx,
4313 SAMR_ACCESS_CONNECT_TO_SERVER |
4314 SAMR_ACCESS_ENUM_DOMAINS |
4315 SAMR_ACCESS_LOOKUP_DOMAIN,
4318 if (!NT_STATUS_IS_OK(status)) {
4319 errcode = W_ERROR_V(ntstatus_to_werror(status));
4322 if (!NT_STATUS_IS_OK(result)) {
4323 errcode = W_ERROR_V(ntstatus_to_werror(result));
4327 init_lsa_String(&domain_name, get_global_sam_name());
4329 status = dcerpc_samr_LookupDomain(b, mem_ctx,
4334 if (!NT_STATUS_IS_OK(status)) {
4335 errcode = W_ERROR_V(ntstatus_to_werror(status));
4338 if (!NT_STATUS_IS_OK(result)) {
4339 errcode = W_ERROR_V(ntstatus_to_werror(result));
4343 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4345 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
4349 if (!NT_STATUS_IS_OK(status)) {
4350 errcode = W_ERROR_V(ntstatus_to_werror(status));
4353 if (!NT_STATUS_IS_OK(result)) {
4354 errcode = W_ERROR_V(ntstatus_to_werror(result));
4358 init_lsa_String(&names, UserName);
4360 status = dcerpc_samr_LookupNames(b, mem_ctx,
4367 if (!NT_STATUS_IS_OK(status)) {
4368 errcode = W_ERROR_V(ntstatus_to_werror(status));
4371 if (!NT_STATUS_IS_OK(result)) {
4372 errcode = W_ERROR_V(ntstatus_to_werror(result));
4376 if (rids.count != 1) {
4377 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
4380 if (rids.count != types.count) {
4381 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4384 if (types.ids[0] != SID_NAME_USER) {
4385 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4391 status = dcerpc_samr_OpenUser(b, mem_ctx,
4393 SAMR_USER_ACCESS_GET_LOCALE |
4394 SAMR_USER_ACCESS_GET_LOGONINFO |
4395 SAMR_USER_ACCESS_GET_ATTRIBUTES |
4396 SAMR_USER_ACCESS_GET_GROUPS |
4397 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
4398 SEC_STD_READ_CONTROL,
4402 if (!NT_STATUS_IS_OK(status)) {
4403 errcode = W_ERROR_V(ntstatus_to_werror(status));
4406 if (!NT_STATUS_IS_OK(result)) {
4407 errcode = W_ERROR_V(ntstatus_to_werror(result));
4411 status = dcerpc_samr_QueryUserInfo2(b, mem_ctx,
4416 if (!NT_STATUS_IS_OK(status)) {
4417 errcode = W_ERROR_V(ntstatus_to_werror(status));
4420 if (!NT_STATUS_IS_OK(result)) {
4421 errcode = W_ERROR_V(ntstatus_to_werror(result));
4426 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4429 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4434 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4435 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4436 p2 = skip_string(*rdata,*rdata_len,p2);
4441 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4442 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4443 p2 = skip_string(*rdata,*rdata_len,p2);
4448 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4449 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4450 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4451 p2 = skip_string(*rdata,*rdata_len,p2);
4458 const char *homedir = info->info21.home_directory.string;
4459 /* modelled after NTAS 3.51 reply */
4460 SSVAL(p,usri11_priv,
4461 (get_current_uid(conn) == sec_initial_uid())?
4462 USER_PRIV_ADMIN:USER_PRIV_USER);
4463 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4464 SIVALS(p,usri11_password_age,-1); /* password age */
4465 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4466 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4467 p2 = skip_string(*rdata,*rdata_len,p2);
4471 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4472 strlcpy(p2,"",PTR_DIFF(endp,p2));
4473 p2 = skip_string(*rdata,*rdata_len,p2);
4477 SIVAL(p,usri11_last_logon,0); /* last logon */
4478 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4479 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4480 SSVALS(p,usri11_num_logons,-1); /* num logons */
4481 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4482 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4483 p2 = skip_string(*rdata,*rdata_len,p2);
4487 SSVAL(p,usri11_country_code,0); /* country code */
4489 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4490 strlcpy(p2,"",PTR_DIFF(endp,p2));
4491 p2 = skip_string(*rdata,*rdata_len,p2);
4496 SIVALS(p,usri11_max_storage,-1); /* max storage */
4497 SSVAL(p,usri11_units_per_week,168); /* units per week */
4498 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4500 /* a simple way to get logon hours at all times. */
4502 SCVAL(p2,21,0); /* fix zero termination */
4503 p2 = skip_string(*rdata,*rdata_len,p2);
4508 SSVAL(p,usri11_code_page,0); /* code page */
4511 if (uLevel == 1 || uLevel == 2) {
4512 memset(p+22,' ',16); /* password */
4513 SIVALS(p,38,-1); /* password age */
4515 (get_current_uid(conn) == sec_initial_uid())?
4516 USER_PRIV_ADMIN:USER_PRIV_USER);
4517 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4518 strlcpy(p2, info->info21.home_directory.string,
4520 p2 = skip_string(*rdata,*rdata_len,p2);
4524 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4526 SSVAL(p,52,0); /* flags */
4527 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4528 strlcpy(p2, info->info21.logon_script.string,
4530 p2 = skip_string(*rdata,*rdata_len,p2);
4535 SIVAL(p,58,0); /* auth_flags */
4536 SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
4537 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4538 p2 = skip_string(*rdata,*rdata_len,p2);
4542 SIVAL(p,66,0); /* urs_comment */
4543 SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
4544 strlcpy(p2,"",PTR_DIFF(endp,p2));
4545 p2 = skip_string(*rdata,*rdata_len,p2);
4549 SIVAL(p,74,0); /* workstations */
4550 SIVAL(p,78,0); /* last_logon */
4551 SIVAL(p,82,0); /* last_logoff */
4552 SIVALS(p,86,-1); /* acct_expires */
4553 SIVALS(p,90,-1); /* max_storage */
4554 SSVAL(p,94,168); /* units_per_week */
4555 SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
4558 SSVALS(p,100,-1); /* bad_pw_count */
4559 SSVALS(p,102,-1); /* num_logons */
4560 SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
4562 TALLOC_CTX *ctx = talloc_tos();
4563 int space_rem = *rdata_len - (p2 - *rdata);
4566 if (space_rem <= 0) {
4569 tmp = talloc_strdup(ctx, "\\\\%L");
4573 tmp = talloc_sub_basic(ctx,
4586 p2 = skip_string(*rdata,*rdata_len,p2);
4590 SSVAL(p,108,49); /* country_code */
4591 SSVAL(p,110,860); /* code page */
4595 errcode = NERR_Success;
4598 *rdata_len = PTR_DIFF(p2,*rdata);
4600 if (b && is_valid_policy_hnd(&user_handle)) {
4601 dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
4603 if (b && is_valid_policy_hnd(&domain_handle)) {
4604 dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
4606 if (b && is_valid_policy_hnd(&connect_handle)) {
4607 dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
4610 SSVAL(*rparam,0,errcode);
4611 SSVAL(*rparam,2,0); /* converter word */
4612 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4617 static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
4618 connection_struct *conn,uint16 vuid,
4619 char *param, int tpscnt,
4620 char *data, int tdscnt,
4621 int mdrcnt,int mprcnt,
4622 char **rdata,char **rparam,
4623 int *rdata_len,int *rparam_len)
4625 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4626 char *str2 = skip_string(param,tpscnt,str1);
4627 char *p = skip_string(param,tpscnt,str2);
4629 struct pack_desc desc;
4631 /* With share level security vuid will always be zero.
4632 Don't depend on vuser being non-null !!. JRA */
4633 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4635 if (!str1 || !str2 || !p) {
4640 DEBUG(3,(" Username of UID %d is %s\n",
4641 (int)vuser->session_info->utok.uid,
4642 vuser->session_info->unix_name));
4645 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4646 name = get_safe_str_ptr(param,tpscnt,p,2);
4651 memset((char *)&desc,'\0',sizeof(desc));
4653 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4655 /* check it's a supported varient */
4656 if (strcmp(str1,"OOWb54WrLh") != 0) {
4659 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4663 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4670 desc.buflen = mdrcnt;
4671 desc.subformat = NULL;
4674 if (init_package(&desc,1,0)) {
4675 PACKI(&desc,"W",0); /* code */
4676 PACKS(&desc,"B21",name); /* eff. name */
4677 PACKS(&desc,"B",""); /* pad */
4679 (get_current_uid(conn) == sec_initial_uid())?
4680 USER_PRIV_ADMIN:USER_PRIV_USER);
4681 PACKI(&desc,"D",0); /* auth flags XXX */
4682 PACKI(&desc,"W",0); /* num logons */
4683 PACKI(&desc,"W",0); /* bad pw count */
4684 PACKI(&desc,"D",0); /* last logon */
4685 PACKI(&desc,"D",-1); /* last logoff */
4686 PACKI(&desc,"D",-1); /* logoff time */
4687 PACKI(&desc,"D",-1); /* kickoff time */
4688 PACKI(&desc,"D",0); /* password age */
4689 PACKI(&desc,"D",0); /* password can change */
4690 PACKI(&desc,"D",-1); /* password must change */
4694 fstrcpy(mypath,"\\\\");
4695 fstrcat(mypath,get_local_machine_name());
4697 PACKS(&desc,"z",mypath); /* computer */
4700 PACKS(&desc,"z",lp_workgroup());/* domain */
4701 PACKS(&desc,"z", vuser ?
4702 vuser->session_info->info3->base.logon_script.string
4703 : ""); /* script path */
4704 PACKI(&desc,"D",0x00000000); /* reserved */
4707 *rdata_len = desc.usedlen;
4709 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4713 SSVALS(*rparam,0,desc.errcode);
4715 SSVAL(*rparam,4,desc.neededlen);
4717 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4722 /****************************************************************************
4723 api_WAccessGetUserPerms
4724 ****************************************************************************/
4726 static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
4727 connection_struct *conn,uint16 vuid,
4728 char *param, int tpscnt,
4729 char *data, int tdscnt,
4730 int mdrcnt,int mprcnt,
4731 char **rdata,char **rparam,
4732 int *rdata_len,int *rparam_len)
4734 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4735 char *str2 = skip_string(param,tpscnt,str1);
4736 char *user = skip_string(param,tpscnt,str2);
4737 char *resource = skip_string(param,tpscnt,user);
4739 if (!str1 || !str2 || !user || !resource) {
4743 if (skip_string(param,tpscnt,resource) == NULL) {
4746 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4748 /* check it's a supported varient */
4749 if (strcmp(str1,"zzh") != 0) {
4752 if (strcmp(str2,"") != 0) {
4757 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4761 SSVALS(*rparam,0,0); /* errorcode */
4762 SSVAL(*rparam,2,0); /* converter word */
4763 SSVAL(*rparam,4,0x7f); /* permission flags */
4768 /****************************************************************************
4769 api_WPrintJobEnumerate
4770 ****************************************************************************/
4772 static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
4773 connection_struct *conn, uint16 vuid,
4774 char *param, int tpscnt,
4775 char *data, int tdscnt,
4776 int mdrcnt,int mprcnt,
4777 char **rdata,char **rparam,
4778 int *rdata_len,int *rparam_len)
4780 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4781 char *str2 = skip_string(param,tpscnt,str1);
4782 char *p = skip_string(param,tpscnt,str2);
4786 struct pack_desc desc;
4789 TALLOC_CTX *mem_ctx = talloc_tos();
4792 struct rpc_pipe_client *cli = NULL;
4793 struct dcerpc_binding_handle *b = NULL;
4794 struct policy_handle handle;
4795 struct spoolss_DevmodeContainer devmode_ctr;
4796 union spoolss_JobInfo info;
4798 if (!str1 || !str2 || !p) {
4802 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4804 memset((char *)&desc,'\0',sizeof(desc));
4805 memset((char *)&status,'\0',sizeof(status));
4807 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4809 /* check it's a supported varient */
4810 if (strcmp(str1,"WWrLh") != 0) {
4813 if (!check_printjob_info(&desc,uLevel,str2)) {
4817 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4821 ZERO_STRUCT(handle);
4823 status = rpc_pipe_open_interface(conn,
4824 &ndr_table_spoolss.syntax_id,
4826 &conn->sconn->client_id,
4827 conn->sconn->msg_ctx,
4829 if (!NT_STATUS_IS_OK(status)) {
4830 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4831 nt_errstr(status)));
4832 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4835 b = cli->binding_handle;
4837 ZERO_STRUCT(devmode_ctr);
4839 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4846 if (!NT_STATUS_IS_OK(status)) {
4847 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4850 if (!W_ERROR_IS_OK(werr)) {
4851 desc.errcode = W_ERROR_V(werr);
4855 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4861 if (!W_ERROR_IS_OK(werr)) {
4862 desc.errcode = W_ERROR_V(werr);
4867 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4872 desc.buflen = mdrcnt;
4875 * Don't return data but need to get correct length
4876 * init_package will return wrong size if buflen=0
4878 desc.buflen = getlen(desc.format);
4879 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4882 if (init_package(&desc,1,0)) {
4883 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4884 *rdata_len = desc.usedlen;
4886 desc.errcode = NERR_JobNotFound;
4890 if (b && is_valid_policy_hnd(&handle)) {
4891 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
4895 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4899 SSVALS(*rparam,0,desc.errcode);
4901 SSVAL(*rparam,4,desc.neededlen);
4905 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4910 static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
4911 connection_struct *conn, uint16 vuid,
4912 char *param, int tpscnt,
4913 char *data, int tdscnt,
4914 int mdrcnt,int mprcnt,
4915 char **rdata,char **rparam,
4916 int *rdata_len,int *rparam_len)
4918 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4919 char *str2 = skip_string(param,tpscnt,str1);
4920 char *p = skip_string(param,tpscnt,str2);
4924 struct pack_desc desc;
4926 TALLOC_CTX *mem_ctx = talloc_tos();
4929 struct rpc_pipe_client *cli = NULL;
4930 struct dcerpc_binding_handle *b = NULL;
4931 struct policy_handle handle;
4932 struct spoolss_DevmodeContainer devmode_ctr;
4934 union spoolss_JobInfo *info;
4936 if (!str1 || !str2 || !p) {
4940 memset((char *)&desc,'\0',sizeof(desc));
4942 p = skip_string(param,tpscnt,p);
4946 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4948 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4950 /* check it's a supported variant */
4951 if (strcmp(str1,"zWrLeh") != 0) {
4956 return False; /* defined only for uLevel 0,1,2 */
4959 if (!check_printjob_info(&desc,uLevel,str2)) {
4963 ZERO_STRUCT(handle);
4965 status = rpc_pipe_open_interface(conn,
4966 &ndr_table_spoolss.syntax_id,
4968 &conn->sconn->client_id,
4969 conn->sconn->msg_ctx,
4971 if (!NT_STATUS_IS_OK(status)) {
4972 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4973 nt_errstr(status)));
4974 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4977 b = cli->binding_handle;
4979 ZERO_STRUCT(devmode_ctr);
4981 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4985 SEC_FLAG_MAXIMUM_ALLOWED,
4988 if (!NT_STATUS_IS_OK(status)) {
4989 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4992 if (!W_ERROR_IS_OK(werr)) {
4993 desc.errcode = W_ERROR_V(werr);
4997 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5005 if (!W_ERROR_IS_OK(werr)) {
5006 desc.errcode = W_ERROR_V(werr);
5011 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5017 desc.buflen = mdrcnt;
5019 if (init_package(&desc,count,0)) {
5021 for (i = 0; i < count; i++) {
5022 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
5023 if (desc.errcode == NERR_Success) {
5029 if (b && is_valid_policy_hnd(&handle)) {
5030 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5033 *rdata_len = desc.usedlen;
5036 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5040 SSVALS(*rparam,0,desc.errcode);
5042 SSVAL(*rparam,4,succnt);
5043 SSVAL(*rparam,6,count);
5045 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
5050 static int check_printdest_info(struct pack_desc* desc,
5051 int uLevel, char* id)
5053 desc->subformat = NULL;
5056 desc->format = "B9";
5059 desc->format = "B9B21WWzW";
5065 desc->format = "zzzWWzzzWW";
5068 DEBUG(0,("check_printdest_info: invalid level %d\n",
5072 if (id == NULL || strcmp(desc->format,id) != 0) {
5073 DEBUG(0,("check_printdest_info: invalid string %s\n",
5074 id ? id : "<NULL>" ));
5080 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
5081 struct pack_desc* desc)
5085 strncpy(buf, info2->printername, sizeof(buf)-1);
5086 buf[sizeof(buf)-1] = 0;
5090 PACKS(desc,"B9",buf); /* szName */
5092 PACKS(desc,"B21",""); /* szUserName */
5093 PACKI(desc,"W",0); /* uJobId */
5094 PACKI(desc,"W",0); /* fsStatus */
5095 PACKS(desc,"z",""); /* pszStatus */
5096 PACKI(desc,"W",0); /* time */
5100 if (uLevel == 2 || uLevel == 3) {
5101 PACKS(desc,"z",buf); /* pszPrinterName */
5103 PACKS(desc,"z",""); /* pszUserName */
5104 PACKS(desc,"z",""); /* pszLogAddr */
5105 PACKI(desc,"W",0); /* uJobId */
5106 PACKI(desc,"W",0); /* fsStatus */
5107 PACKS(desc,"z",""); /* pszStatus */
5108 PACKS(desc,"z",""); /* pszComment */
5109 PACKS(desc,"z","NULL"); /* pszDrivers */
5110 PACKI(desc,"W",0); /* time */
5111 PACKI(desc,"W",0); /* pad1 */
5116 static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
5117 connection_struct *conn, uint16 vuid,
5118 char *param, int tpscnt,
5119 char *data, int tdscnt,
5120 int mdrcnt,int mprcnt,
5121 char **rdata,char **rparam,
5122 int *rdata_len,int *rparam_len)
5124 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5125 char *str2 = skip_string(param,tpscnt,str1);
5126 char *p = skip_string(param,tpscnt,str2);
5127 char* PrinterName = p;
5129 struct pack_desc desc;
5132 TALLOC_CTX *mem_ctx = talloc_tos();
5135 struct rpc_pipe_client *cli = NULL;
5136 struct dcerpc_binding_handle *b = NULL;
5137 struct policy_handle handle;
5138 struct spoolss_DevmodeContainer devmode_ctr;
5139 union spoolss_PrinterInfo info;
5141 if (!str1 || !str2 || !p) {
5145 memset((char *)&desc,'\0',sizeof(desc));
5147 p = skip_string(param,tpscnt,p);
5151 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5153 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
5155 /* check it's a supported varient */
5156 if (strcmp(str1,"zWrLh") != 0) {
5159 if (!check_printdest_info(&desc,uLevel,str2)) {
5163 ZERO_STRUCT(handle);
5165 status = rpc_pipe_open_interface(conn,
5166 &ndr_table_spoolss.syntax_id,
5168 &conn->sconn->client_id,
5169 conn->sconn->msg_ctx,
5171 if (!NT_STATUS_IS_OK(status)) {
5172 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5173 nt_errstr(status)));
5174 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5177 b = cli->binding_handle;
5179 ZERO_STRUCT(devmode_ctr);
5181 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5185 SEC_FLAG_MAXIMUM_ALLOWED,
5188 if (!NT_STATUS_IS_OK(status)) {
5190 desc.errcode = NERR_DestNotFound;
5194 if (!W_ERROR_IS_OK(werr)) {
5196 desc.errcode = NERR_DestNotFound;
5201 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
5206 if (!W_ERROR_IS_OK(werr)) {
5208 desc.errcode = NERR_DestNotFound;
5214 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5219 desc.buflen = mdrcnt;
5222 * Don't return data but need to get correct length
5223 * init_package will return wrong size if buflen=0
5225 desc.buflen = getlen(desc.format);
5226 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
5228 if (init_package(&desc,1,0)) {
5229 fill_printdest_info(&info.info2, uLevel,&desc);
5233 if (b && is_valid_policy_hnd(&handle)) {
5234 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5237 *rdata_len = desc.usedlen;
5240 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5244 SSVALS(*rparam,0,desc.errcode);
5246 SSVAL(*rparam,4,desc.neededlen);
5248 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
5254 static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
5255 connection_struct *conn, uint16 vuid,
5256 char *param, int tpscnt,
5257 char *data, int tdscnt,
5258 int mdrcnt,int mprcnt,
5259 char **rdata,char **rparam,
5260 int *rdata_len,int *rparam_len)
5262 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5263 char *str2 = skip_string(param,tpscnt,str1);
5264 char *p = skip_string(param,tpscnt,str2);
5268 struct pack_desc desc;
5270 TALLOC_CTX *mem_ctx = talloc_tos();
5273 struct rpc_pipe_client *cli = NULL;
5274 union spoolss_PrinterInfo *info;
5277 if (!str1 || !str2 || !p) {
5281 memset((char *)&desc,'\0',sizeof(desc));
5283 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5285 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
5287 /* check it's a supported varient */
5288 if (strcmp(str1,"WrLeh") != 0) {
5291 if (!check_printdest_info(&desc,uLevel,str2)) {
5297 status = rpc_pipe_open_interface(conn,
5298 &ndr_table_spoolss.syntax_id,
5300 &conn->sconn->client_id,
5301 conn->sconn->msg_ctx,
5303 if (!NT_STATUS_IS_OK(status)) {
5304 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5305 nt_errstr(status)));
5306 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5310 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
5312 cli->srv_name_slash,
5317 if (!W_ERROR_IS_OK(werr)) {
5318 desc.errcode = W_ERROR_V(werr);
5320 desc.errcode = NERR_DestNotFound;
5328 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5335 desc.buflen = mdrcnt;
5336 if (init_package(&desc,queuecnt,0)) {
5339 for (i = 0; i < count; i++) {
5340 fill_printdest_info(&info[i].info2, uLevel,&desc);
5342 if (desc.errcode == NERR_Success) {
5348 *rdata_len = desc.usedlen;
5351 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5355 SSVALS(*rparam,0,desc.errcode);
5357 SSVAL(*rparam,4,succnt);
5358 SSVAL(*rparam,6,queuecnt);
5360 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
5365 static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
5366 connection_struct *conn, uint16 vuid,
5367 char *param, int tpscnt,
5368 char *data, int tdscnt,
5369 int mdrcnt,int mprcnt,
5370 char **rdata,char **rparam,
5371 int *rdata_len,int *rparam_len)
5373 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5374 char *str2 = skip_string(param,tpscnt,str1);
5375 char *p = skip_string(param,tpscnt,str2);
5378 struct pack_desc desc;
5380 if (!str1 || !str2 || !p) {
5384 memset((char *)&desc,'\0',sizeof(desc));
5386 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5388 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5390 /* check it's a supported varient */
5391 if (strcmp(str1,"WrLeh") != 0) {
5394 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5399 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5405 desc.buflen = mdrcnt;
5406 if (init_package(&desc,1,0)) {
5407 PACKS(&desc,"B41","NULL");
5410 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5412 *rdata_len = desc.usedlen;
5415 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5419 SSVALS(*rparam,0,desc.errcode);
5421 SSVAL(*rparam,4,succnt);
5424 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5429 static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
5430 connection_struct *conn, uint16 vuid,
5431 char *param, int tpscnt,
5432 char *data, int tdscnt,
5433 int mdrcnt,int mprcnt,
5434 char **rdata,char **rparam,
5435 int *rdata_len,int *rparam_len)
5437 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5438 char *str2 = skip_string(param,tpscnt,str1);
5439 char *p = skip_string(param,tpscnt,str2);
5442 struct pack_desc desc;
5444 if (!str1 || !str2 || !p) {
5447 memset((char *)&desc,'\0',sizeof(desc));
5449 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5451 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5453 /* check it's a supported varient */
5454 if (strcmp(str1,"WrLeh") != 0) {
5457 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5462 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5468 desc.buflen = mdrcnt;
5470 if (init_package(&desc,1,0)) {
5471 PACKS(&desc,"B13","lpd");
5474 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5476 *rdata_len = desc.usedlen;
5479 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5483 SSVALS(*rparam,0,desc.errcode);
5485 SSVAL(*rparam,4,succnt);
5488 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5493 static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
5494 connection_struct *conn, uint16 vuid,
5495 char *param, int tpscnt,
5496 char *data, int tdscnt,
5497 int mdrcnt,int mprcnt,
5498 char **rdata,char **rparam,
5499 int *rdata_len,int *rparam_len)
5501 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5502 char *str2 = skip_string(param,tpscnt,str1);
5503 char *p = skip_string(param,tpscnt,str2);
5506 struct pack_desc desc;
5508 if (!str1 || !str2 || !p) {
5512 memset((char *)&desc,'\0',sizeof(desc));
5514 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5516 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5518 /* check it's a supported varient */
5519 if (strcmp(str1,"WrLeh") != 0) {
5522 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5527 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5532 memset((char *)&desc,'\0',sizeof(desc));
5534 desc.buflen = mdrcnt;
5536 if (init_package(&desc,1,0)) {
5537 PACKS(&desc,"B13","lp0");
5540 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5542 *rdata_len = desc.usedlen;
5545 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5549 SSVALS(*rparam,0,desc.errcode);
5551 SSVAL(*rparam,4,succnt);
5554 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5559 /****************************************************************************
5561 ****************************************************************************/
5563 static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
5564 connection_struct *conn, uint16 vuid,
5565 char *param, int tpscnt,
5566 char *data, int tdscnt,
5567 int mdrcnt,int mprcnt,
5568 char **rdata,char **rparam,
5569 int *rdata_len,int *rparam_len)
5572 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5573 char *str2 = skip_string(param,tpscnt,str1);
5574 char *p = skip_string(param,tpscnt,str2);
5576 struct pack_desc desc;
5579 TALLOC_CTX *mem_ctx = talloc_tos();
5582 struct rpc_pipe_client *cli = NULL;
5583 struct dcerpc_binding_handle *b = NULL;
5584 struct srvsvc_NetSessInfoCtr info_ctr;
5585 uint32_t totalentries, resume_handle = 0;
5588 if (!str1 || !str2 || !p) {
5594 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5596 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5597 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5598 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5600 /* check it's a supported varient */
5601 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5604 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5608 status = rpc_pipe_open_interface(conn,
5609 &ndr_table_srvsvc.syntax_id,
5611 &conn->sconn->client_id,
5612 conn->sconn->msg_ctx,
5614 if (!NT_STATUS_IS_OK(status)) {
5615 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5616 nt_errstr(status)));
5617 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5620 b = cli->binding_handle;
5623 info_ctr.ctr.ctr1 = talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1);
5624 if (info_ctr.ctr.ctr1 == NULL) {
5625 desc.errcode = W_ERROR_V(WERR_NOMEM);
5629 status = dcerpc_srvsvc_NetSessEnum(b, mem_ctx,
5630 cli->srv_name_slash,
5634 (uint32_t)-1, /* max_buffer */
5638 if (!NT_STATUS_IS_OK(status)) {
5639 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5640 nt_errstr(status)));
5641 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5645 if (!W_ERROR_IS_OK(werr)) {
5646 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5648 desc.errcode = W_ERROR_V(werr);
5652 count = info_ctr.ctr.ctr1->count;
5656 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5663 desc.buflen = mdrcnt;
5665 if (!init_package(&desc, count,0)) {
5669 for(i=0; i < count; i++) {
5670 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].client);
5671 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].user);
5672 PACKI(&desc, "W", 1); /* num conns */
5673 PACKI(&desc, "W", info_ctr.ctr.ctr1->array[i].num_open);
5674 PACKI(&desc, "W", 1); /* num users */
5675 PACKI(&desc, "D", 0); /* session time */
5676 PACKI(&desc, "D", 0); /* idle time */
5677 PACKI(&desc, "D", 0); /* flags */
5678 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5681 *rdata_len = desc.usedlen;
5684 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5688 SSVALS(*rparam,0,desc.errcode);
5689 SSVAL(*rparam,2,0); /* converter */
5690 SSVAL(*rparam,4, count); /* count */
5692 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5698 /****************************************************************************
5699 The buffer was too small.
5700 ****************************************************************************/
5702 static bool api_TooSmall(struct smbd_server_connection *sconn,
5703 connection_struct *conn,uint16 vuid, char *param, char *data,
5704 int mdrcnt, int mprcnt,
5705 char **rdata, char **rparam,
5706 int *rdata_len, int *rparam_len)
5708 *rparam_len = MIN(*rparam_len,mprcnt);
5709 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5716 SSVAL(*rparam,0,NERR_BufTooSmall);
5718 DEBUG(3,("Supplied buffer too small in API command\n"));
5723 /****************************************************************************
5724 The request is not supported.
5725 ****************************************************************************/
5727 static bool api_Unsupported(struct smbd_server_connection *sconn,
5728 connection_struct *conn, uint16 vuid,
5729 char *param, int tpscnt,
5730 char *data, int tdscnt,
5731 int mdrcnt, int mprcnt,
5732 char **rdata, char **rparam,
5733 int *rdata_len, int *rparam_len)
5736 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5743 SSVAL(*rparam,0,NERR_notsupported);
5744 SSVAL(*rparam,2,0); /* converter word */
5746 DEBUG(3,("Unsupported API command\n"));
5751 static const struct {
5754 bool (*fn)(struct smbd_server_connection *sconn,
5755 connection_struct *, uint16,
5758 int,int,char **,char **,int *,int *);
5759 bool auth_user; /* Deny anonymous access? */
5760 } api_commands[] = {
5761 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5762 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5763 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5764 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5765 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5766 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5767 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5768 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5769 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5770 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5771 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5772 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5773 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5774 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5775 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5776 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5777 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5778 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5779 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5780 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5781 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5782 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5783 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5784 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5785 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5786 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5787 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5788 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5789 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5790 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5791 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5792 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5793 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5794 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5795 {NULL, -1, api_Unsupported}
5796 /* The following RAP calls are not implemented by Samba:
5798 RAP_WFileEnum2 - anon not OK
5803 /****************************************************************************
5804 Handle remote api calls.
5805 ****************************************************************************/
5807 void api_reply(connection_struct *conn, uint16 vuid,
5808 struct smb_request *req,
5809 char *data, char *params,
5810 int tdscnt, int tpscnt,
5811 int mdrcnt, int mprcnt)
5815 char *rparam = NULL;
5816 const char *name1 = NULL;
5817 const char *name2 = NULL;
5824 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5833 api_command = SVAL(params,0);
5834 /* Is there a string at position params+2 ? */
5835 if (skip_string(params,tpscnt,params+2)) {
5840 name2 = skip_string(params,tpscnt,params+2);
5845 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5849 tdscnt,tpscnt,mdrcnt,mprcnt));
5851 for (i=0;api_commands[i].name;i++) {
5852 if (api_commands[i].id == api_command && api_commands[i].fn) {
5853 DEBUG(3,("Doing %s\n",api_commands[i].name));
5858 /* Check whether this api call can be done anonymously */
5860 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5861 user_struct *user = get_valid_user_struct(req->sconn, vuid);
5863 if (!user || user->session_info->guest) {
5864 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5869 rdata = (char *)SMB_MALLOC(1024);
5871 memset(rdata,'\0',1024);
5874 rparam = (char *)SMB_MALLOC(1024);
5876 memset(rparam,'\0',1024);
5879 if(!rdata || !rparam) {
5880 DEBUG(0,("api_reply: malloc fail !\n"));
5883 reply_nterror(req, NT_STATUS_NO_MEMORY);
5887 reply = api_commands[i].fn(req->sconn, conn,
5889 params,tpscnt, /* params + length */
5890 data,tdscnt, /* data + length */
5892 &rdata,&rparam,&rdata_len,&rparam_len);
5895 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5896 reply = api_TooSmall(req->sconn,conn,vuid,params,data,
5898 &rdata,&rparam,&rdata_len,&rparam_len);
5901 /* if we get False back then it's actually unsupported */
5903 reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
5905 tdscnt,mdrcnt,mprcnt,
5906 &rdata,&rparam,&rdata_len,&rparam_len);
5909 /* If api_Unsupported returns false we can't return anything. */
5911 send_trans_reply(conn, req, rparam, rparam_len,
5912 rdata, rdata_len, False);