2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "../librpc/gen_ndr/cli_srvsvc.h"
35 #include "../librpc/gen_ndr/srv_samr.h"
36 #include "../librpc/gen_ndr/srv_srvsvc.h"
37 #include "../librpc/gen_ndr/rap.h"
38 #include "../lib/util/binsearch.h"
39 #include "../libcli/auth/libcli_auth.h"
40 #include "rpc_client/init_lsa.h"
47 #define NERR_Success 0
48 #define NERR_badpass 86
49 #define NERR_notsupported 50
51 #define NERR_BASE (2100)
52 #define NERR_BufTooSmall (NERR_BASE+23)
53 #define NERR_JobNotFound (NERR_BASE+51)
54 #define NERR_DestNotFound (NERR_BASE+52)
56 #define ACCESS_READ 0x01
57 #define ACCESS_WRITE 0x02
58 #define ACCESS_CREATE 0x04
60 #define SHPWLEN 8 /* share password length */
62 /* Limit size of ipc replies */
64 static char *smb_realloc_limit(void *ptr, size_t size)
68 size = MAX((size),4*1024);
69 val = (char *)SMB_REALLOC(ptr,size);
71 memset(val,'\0',size);
76 static bool api_Unsupported(struct smbd_server_connection *sconn,
77 connection_struct *conn, uint16 vuid,
78 char *param, int tpscnt,
79 char *data, int tdscnt,
80 int mdrcnt, int mprcnt,
81 char **rdata, char **rparam,
82 int *rdata_len, int *rparam_len);
84 static bool api_TooSmall(struct smbd_server_connection *sconn,
85 connection_struct *conn, uint16 vuid, char *param, char *data,
86 int mdrcnt, int mprcnt,
87 char **rdata, char **rparam,
88 int *rdata_len, int *rparam_len);
91 static int CopyExpanded(connection_struct *conn,
92 int snum, char **dst, char *src, int *p_space_remaining)
94 TALLOC_CTX *ctx = talloc_tos();
98 if (!src || !dst || !p_space_remaining || !(*dst) ||
99 *p_space_remaining <= 0) {
103 buf = talloc_strdup(ctx, src);
105 *p_space_remaining = 0;
108 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
110 *p_space_remaining = 0;
113 buf = talloc_sub_advanced(ctx,
114 lp_servicename(SNUM(conn)),
115 conn->server_info->unix_name,
117 conn->server_info->utok.gid,
118 conn->server_info->sanitized_username,
119 conn->server_info->info3->base.domain.string,
122 *p_space_remaining = 0;
125 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
130 (*p_space_remaining) -= l;
134 static int CopyAndAdvance(char **dst, char *src, int *n)
137 if (!src || !dst || !n || !(*dst)) {
140 l = push_ascii(*dst,src,*n, STR_TERMINATE);
149 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
151 TALLOC_CTX *ctx = talloc_tos();
156 buf = talloc_strdup(ctx,s);
160 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
164 buf = talloc_sub_advanced(ctx,
165 lp_servicename(SNUM(conn)),
166 conn->server_info->unix_name,
168 conn->server_info->utok.gid,
169 conn->server_info->sanitized_username,
170 conn->server_info->info3->base.domain.string,
175 return strlen(buf) + 1;
178 /*******************************************************************
179 Check a API string for validity when we only need to check the prefix.
180 ******************************************************************/
182 static bool prefix_ok(const char *str, const char *prefix)
184 return(strncmp(str,prefix,strlen(prefix)) == 0);
188 const char *format; /* formatstring for structure */
189 const char *subformat; /* subformat for structure */
190 char *base; /* baseaddress of buffer */
191 int buflen; /* remaining size for fixed part; on init: length of base */
192 int subcount; /* count of substructures */
193 char *structbuf; /* pointer into buffer for remaining fixed part */
194 int stringlen; /* remaining size for variable part */
195 char *stringbuf; /* pointer into buffer for remaining variable part */
196 int neededlen; /* total needed size */
197 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
198 const char *curpos; /* current position; pointer into format or subformat */
202 static int get_counter(const char **p)
208 if (!isdigit((int)**p)) {
214 n = 10 * n + (i - '0');
222 static int getlen(const char *p)
231 case 'W': /* word (2 byte) */
234 case 'K': /* status word? (2 byte) */
237 case 'N': /* count of substructures (word) at end */
240 case 'D': /* double word (4 byte) */
241 case 'z': /* offset to zero terminated string (4 byte) */
242 case 'l': /* offset to user data (4 byte) */
245 case 'b': /* offset to data (with counter) (4 byte) */
249 case 'B': /* byte (with optional counter) */
250 n += get_counter(&p);
257 static bool init_package(struct pack_desc *p, int count, int subcount)
262 if (!p->format || !p->base) {
266 i = count * getlen(p->format);
268 i += subcount * getlen(p->subformat);
270 p->structbuf = p->base;
274 p->curpos = p->format;
280 * This is the old error code we used. Aparently
281 * WinNT/2k systems return ERRbuftoosmall (2123) and
282 * OS/2 needs this. I'm leaving this here so we can revert
285 p->errcode = ERRmoredata;
287 p->errcode = ERRbuftoosmall;
290 p->errcode = NERR_Success;
294 p->stringbuf = p->base + i;
296 return (p->errcode == NERR_Success);
299 static int package(struct pack_desc *p, ...)
302 int needed=0, stringneeded;
303 const char *str=NULL;
304 int is_string=0, stringused;
311 p->curpos = p->format;
313 p->curpos = p->subformat;
318 str = va_arg(args,char*);
319 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
328 switch( *p->curpos++ ) {
329 case 'W': /* word (2 byte) */
331 temp = va_arg(args,int);
332 if (p->buflen >= needed) {
333 SSVAL(p->structbuf,0,temp);
336 case 'K': /* status word? (2 byte) */
338 temp = va_arg(args,int);
339 if (p->buflen >= needed) {
340 SSVAL(p->structbuf,0,temp);
343 case 'N': /* count of substructures (word) at end */
345 p->subcount = va_arg(args,int);
346 if (p->buflen >= needed) {
347 SSVAL(p->structbuf,0,p->subcount);
350 case 'D': /* double word (4 byte) */
352 temp = va_arg(args,int);
353 if (p->buflen >= needed) {
354 SIVAL(p->structbuf,0,temp);
357 case 'B': /* byte (with optional counter) */
358 needed = get_counter(&p->curpos);
360 char *s = va_arg(args,char*);
361 if (p->buflen >= needed) {
362 StrnCpy(p->structbuf,s?s:"",needed-1);
366 case 'z': /* offset to zero terminated string (4 byte) */
367 str = va_arg(args,char*);
368 stringneeded = (str ? strlen(str)+1 : 0);
371 case 'l': /* offset to user data (4 byte) */
372 str = va_arg(args,char*);
373 stringneeded = va_arg(args,int);
376 case 'b': /* offset to data (with counter) (4 byte) */
377 str = va_arg(args,char*);
378 stringneeded = get_counter(&p->curpos);
384 if (stringneeded >= 0) {
386 if (p->buflen >= needed) {
387 stringused = stringneeded;
388 if (stringused > p->stringlen) {
389 stringused = (is_string ? p->stringlen : 0);
390 if (p->errcode == NERR_Success) {
391 p->errcode = ERRmoredata;
395 SIVAL(p->structbuf,0,0);
397 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
398 memcpy(p->stringbuf,str?str:"",stringused);
400 p->stringbuf[stringused-1] = '\0';
402 p->stringbuf += stringused;
403 p->stringlen -= stringused;
404 p->usedlen += stringused;
407 p->neededlen += stringneeded;
410 p->neededlen += needed;
411 if (p->buflen >= needed) {
412 p->structbuf += needed;
414 p->usedlen += needed;
416 if (p->errcode == NERR_Success) {
417 p->errcode = ERRmoredata;
424 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
425 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
427 #define PACK(desc,t,v) package(desc,v)
428 #define PACKl(desc,t,v,l) package(desc,v,l)
431 static void PACKI(struct pack_desc* desc, const char *t,int v)
436 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
441 /****************************************************************************
443 ****************************************************************************/
445 static void PackDriverData(struct pack_desc* desc)
447 char drivdata[4+4+32];
448 SIVAL(drivdata,0,sizeof drivdata); /* cb */
449 SIVAL(drivdata,4,1000); /* lVersion */
450 memset(drivdata+8,0,32); /* szDeviceName */
451 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
452 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
455 static int check_printq_info(struct pack_desc* desc,
456 unsigned int uLevel, char *id1, char *id2)
458 desc->subformat = NULL;
461 desc->format = "B13";
464 desc->format = "B13BWWWzzzzzWW";
467 desc->format = "B13BWWWzzzzzWN";
468 desc->subformat = "WB21BB16B10zWWzDDz";
471 desc->format = "zWWWWzzzzWWzzl";
474 desc->format = "zWWWWzzzzWNzzl";
475 desc->subformat = "WWzWWDDzz";
484 desc->format = "WzzzzzzzzN";
485 desc->subformat = "z";
488 DEBUG(0,("check_printq_info: invalid level %d\n",
492 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
493 DEBUG(0,("check_printq_info: invalid format %s\n",
494 id1 ? id1 : "<NULL>" ));
497 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
498 DEBUG(0,("check_printq_info: invalid subformat %s\n",
499 id2 ? id2 : "<NULL>" ));
506 #define RAP_JOB_STATUS_QUEUED 0
507 #define RAP_JOB_STATUS_PAUSED 1
508 #define RAP_JOB_STATUS_SPOOLING 2
509 #define RAP_JOB_STATUS_PRINTING 3
510 #define RAP_JOB_STATUS_PRINTED 4
512 #define RAP_QUEUE_STATUS_PAUSED 1
513 #define RAP_QUEUE_STATUS_ERROR 2
515 /* turn a print job status into a on the wire status
517 static int printj_spoolss_status(int v)
519 if (v == JOB_STATUS_QUEUED)
520 return RAP_JOB_STATUS_QUEUED;
521 if (v & JOB_STATUS_PAUSED)
522 return RAP_JOB_STATUS_PAUSED;
523 if (v & JOB_STATUS_SPOOLING)
524 return RAP_JOB_STATUS_SPOOLING;
525 if (v & JOB_STATUS_PRINTING)
526 return RAP_JOB_STATUS_PRINTING;
530 /* turn a print queue status into a on the wire status
532 static int printq_spoolss_status(int v)
534 if (v == PRINTER_STATUS_OK)
536 if (v & PRINTER_STATUS_PAUSED)
537 return RAP_QUEUE_STATUS_PAUSED;
538 return RAP_QUEUE_STATUS_ERROR;
541 static void fill_spoolss_printjob_info(int uLevel,
542 struct pack_desc *desc,
543 struct spoolss_JobInfo2 *info2,
546 time_t t = spoolss_Time_to_time_t(&info2->submitted);
548 /* the client expects localtime */
549 t -= get_time_zone(t);
551 PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
553 PACKS(desc,"B21", info2->user_name); /* szUserName */
554 PACKS(desc,"B",""); /* pad */
555 PACKS(desc,"B16",""); /* szNotifyName */
556 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
557 PACKS(desc,"z",""); /* pszParms */
558 PACKI(desc,"W",n+1); /* uPosition */
559 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
560 PACKS(desc,"z",""); /* pszStatus */
561 PACKI(desc,"D", t); /* ulSubmitted */
562 PACKI(desc,"D", info2->size); /* ulSize */
563 PACKS(desc,"z", info2->document_name); /* pszComment */
565 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
566 PACKI(desc,"W", info2->priority); /* uPriority */
567 PACKS(desc,"z", info2->user_name); /* pszUserName */
568 PACKI(desc,"W",n+1); /* uPosition */
569 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
570 PACKI(desc,"D",t); /* ulSubmitted */
571 PACKI(desc,"D", info2->size); /* ulSize */
572 PACKS(desc,"z","Samba"); /* pszComment */
573 PACKS(desc,"z", info2->document_name); /* pszDocument */
575 PACKS(desc,"z",""); /* pszNotifyName */
576 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
577 PACKS(desc,"z",""); /* pszParms */
578 PACKS(desc,"z",""); /* pszStatus */
579 PACKS(desc,"z", info2->printer_name); /* pszQueue */
580 PACKS(desc,"z","lpd"); /* pszQProcName */
581 PACKS(desc,"z",""); /* pszQProcParms */
582 PACKS(desc,"z","NULL"); /* pszDriverName */
583 PackDriverData(desc); /* pDriverData */
584 PACKS(desc,"z",""); /* pszPrinterName */
585 } else if (uLevel == 4) { /* OS2 */
586 PACKS(desc,"z",""); /* pszSpoolFileName */
587 PACKS(desc,"z",""); /* pszPortName */
588 PACKS(desc,"z",""); /* pszStatus */
589 PACKI(desc,"D",0); /* ulPagesSpooled */
590 PACKI(desc,"D",0); /* ulPagesSent */
591 PACKI(desc,"D",0); /* ulPagesPrinted */
592 PACKI(desc,"D",0); /* ulTimePrinted */
593 PACKI(desc,"D",0); /* ulExtendJobStatus */
594 PACKI(desc,"D",0); /* ulStartPage */
595 PACKI(desc,"D",0); /* ulEndPage */
600 /********************************************************************
601 Respond to the DosPrintQInfo command with a level of 52
602 This is used to get printer driver information for Win9x clients
603 ********************************************************************/
604 static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver,
605 struct pack_desc* desc, int count,
606 const char *printer_name)
610 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
611 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
612 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
614 PACKI(desc, "W", 0x0400); /* don't know */
615 PACKS(desc, "z", driver->driver_name); /* long printer name */
616 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
617 PACKS(desc, "z", driver->data_file); /* Datafile name */
618 PACKS(desc, "z", driver->monitor_name); /* language monitor */
620 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
621 standard_sub_basic( "", "", location, sizeof(location)-1 );
622 PACKS(desc,"z", location); /* share to retrieve files */
624 PACKS(desc,"z", driver->default_datatype); /* default data type */
625 PACKS(desc,"z", driver->help_file); /* helpfile name */
626 PACKS(desc,"z", driver->driver_path); /* driver name */
628 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
629 DEBUG(3,("Driver: %s:\n",driver->driver_path));
630 DEBUG(3,("Data File: %s:\n",driver->data_file));
631 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
632 DEBUG(3,("Driver Location: %s:\n",location));
633 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
634 DEBUG(3,("Help File: %s:\n",driver->help_file));
635 PACKI(desc,"N",count); /* number of files to copy */
637 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
639 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
640 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
641 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
646 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
649 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name, i));
651 desc->errcode=NERR_Success;
655 static const char *strip_unc(const char *unc)
663 if ((p = strrchr(unc, '\\')) != NULL) {
670 static void fill_printq_info(int uLevel,
671 struct pack_desc* desc,
673 union spoolss_JobInfo *job_info,
674 struct spoolss_DriverInfo3 *driver_info,
675 struct spoolss_PrinterInfo2 *printer_info)
681 PACKS(desc,"B13", strip_unc(printer_info->printername));
686 PACKS(desc,"z", strip_unc(printer_info->printername));
689 PACKI(desc,"K", printq_spoolss_status(printer_info->status));
693 if (uLevel == 1 || uLevel == 2) {
694 PACKS(desc,"B",""); /* alignment */
695 PACKI(desc,"W",5); /* priority */
696 PACKI(desc,"W",0); /* start time */
697 PACKI(desc,"W",0); /* until time */
698 PACKS(desc,"z",""); /* pSepFile */
699 PACKS(desc,"z","lpd"); /* pPrProc */
700 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pDestinations */
701 PACKS(desc,"z",""); /* pParms */
702 if (printer_info->printername == NULL) {
703 PACKS(desc,"z","UNKNOWN PRINTER");
704 PACKI(desc,"W",LPSTAT_ERROR);
706 PACKS(desc,"z", printer_info->comment);
707 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* status */
709 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
712 if (uLevel == 3 || uLevel == 4) {
713 PACKI(desc,"W",5); /* uPriority */
714 PACKI(desc,"W",0); /* uStarttime */
715 PACKI(desc,"W",0); /* uUntiltime */
716 PACKI(desc,"W",5); /* pad1 */
717 PACKS(desc,"z",""); /* pszSepFile */
718 PACKS(desc,"z","WinPrint"); /* pszPrProc */
719 PACKS(desc,"z",NULL); /* pszParms */
720 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
721 /* "don't ask" that it's done this way to fix corrupted
722 Win9X/ME printer comments. */
723 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* fsStatus */
724 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
725 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pszPrinters */
726 PACKS(desc,"z", printer_info->drivername); /* pszDriverName */
727 PackDriverData(desc); /* pDriverData */
730 if (uLevel == 2 || uLevel == 4) {
732 for (i = 0; i < count; i++) {
733 fill_spoolss_printjob_info(uLevel == 2 ? 1 : 2, desc, &job_info[i].info2, i);
738 fill_printq_info_52(driver_info, desc, count, printer_info->printername);
741 /* This function returns the number of files for a given driver */
742 static int get_printerdrivernumber(const struct spoolss_DriverInfo3 *driver)
746 /* count the number of files */
747 while (driver->dependent_files && *driver->dependent_files[result])
753 static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn,
754 connection_struct *conn, uint16 vuid,
755 char *param, int tpscnt,
756 char *data, int tdscnt,
757 int mdrcnt,int mprcnt,
758 char **rdata,char **rparam,
759 int *rdata_len,int *rparam_len)
761 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
762 char *str2 = skip_string(param,tpscnt,str1);
763 char *p = skip_string(param,tpscnt,str2);
768 struct pack_desc desc;
771 WERROR werr = WERR_OK;
772 TALLOC_CTX *mem_ctx = talloc_tos();
774 struct rpc_pipe_client *cli = NULL;
775 struct policy_handle handle;
776 struct spoolss_DevmodeContainer devmode_ctr;
777 union spoolss_DriverInfo driver_info;
778 union spoolss_JobInfo *job_info = NULL;
779 union spoolss_PrinterInfo printer_info;
781 if (!str1 || !str2 || !p) {
784 memset((char *)&desc,'\0',sizeof(desc));
786 p = skip_string(param,tpscnt,p);
790 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
791 str3 = get_safe_str_ptr(param,tpscnt,p,4);
792 /* str3 may be null here and is checked in check_printq_info(). */
794 /* remove any trailing username */
795 if ((p = strchr_m(QueueName,'%')))
798 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
800 /* check it's a supported varient */
801 if (!prefix_ok(str1,"zWrLh"))
803 if (!check_printq_info(&desc,uLevel,str2,str3)) {
805 * Patch from Scott Moomaw <scott@bridgewater.edu>
806 * to return the 'invalid info level' error if an
807 * unknown level was requested.
811 *rparam = smb_realloc_limit(*rparam,*rparam_len);
815 SSVALS(*rparam,0,ERRunknownlevel);
823 if (QueueName == NULL || (strlen(QueueName) < 1)) {
824 desc.errcode = W_ERROR_V(WERR_INVALID_PARAM);
828 status = rpc_pipe_open_interface(conn,
829 &ndr_table_spoolss.syntax_id,
831 &conn->sconn->client_id,
832 conn->sconn->msg_ctx,
834 if (!NT_STATUS_IS_OK(status)) {
835 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
837 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
841 ZERO_STRUCT(devmode_ctr);
843 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
850 if (!NT_STATUS_IS_OK(status)) {
851 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
854 if (!W_ERROR_IS_OK(werr)) {
855 desc.errcode = W_ERROR_V(werr);
859 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
864 if (!W_ERROR_IS_OK(werr)) {
865 desc.errcode = W_ERROR_V(werr);
870 uint32_t server_major_version;
871 uint32_t server_minor_version;
873 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
881 &server_major_version,
882 &server_minor_version);
883 if (!W_ERROR_IS_OK(werr)) {
884 desc.errcode = W_ERROR_V(werr);
888 count = get_printerdrivernumber(&driver_info.info3);
889 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
892 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
900 if (!W_ERROR_IS_OK(werr)) {
901 desc.errcode = W_ERROR_V(werr);
909 *rdata = smb_realloc_limit(*rdata,mdrcnt);
914 desc.buflen = mdrcnt;
917 * Don't return data but need to get correct length
918 * init_package will return wrong size if buflen=0
920 desc.buflen = getlen(desc.format);
921 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
924 if (init_package(&desc,1,count)) {
925 desc.subcount = count;
926 fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
929 *rdata_len = desc.usedlen;
932 * We must set the return code to ERRbuftoosmall
933 * in order to support lanman style printing with Win NT/2k
936 if (!mdrcnt && lp_disable_spoolss())
937 desc.errcode = ERRbuftoosmall;
940 if (cli && is_valid_policy_hnd(&handle)) {
941 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
944 *rdata_len = desc.usedlen;
946 *rparam = smb_realloc_limit(*rparam,*rparam_len);
951 SSVALS(*rparam,0,desc.errcode);
953 SSVAL(*rparam,4,desc.neededlen);
955 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
962 /****************************************************************************
963 View list of all print jobs on all queues.
964 ****************************************************************************/
966 static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
967 connection_struct *conn, uint16 vuid,
968 char *param, int tpscnt,
969 char *data, int tdscnt,
970 int mdrcnt, int mprcnt,
971 char **rdata, char** rparam,
972 int *rdata_len, int *rparam_len)
974 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
975 char *output_format1 = skip_string(param,tpscnt,param_format);
976 char *p = skip_string(param,tpscnt,output_format1);
977 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
978 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
980 struct pack_desc desc;
981 int *subcntarr = NULL;
982 int queuecnt = 0, subcnt = 0, succnt = 0;
984 WERROR werr = WERR_OK;
985 TALLOC_CTX *mem_ctx = talloc_tos();
987 struct rpc_pipe_client *cli = NULL;
988 struct spoolss_DevmodeContainer devmode_ctr;
989 uint32_t num_printers;
990 union spoolss_PrinterInfo *printer_info;
991 union spoolss_DriverInfo *driver_info;
992 union spoolss_JobInfo **job_info;
994 if (!param_format || !output_format1 || !p) {
998 memset((char *)&desc,'\0',sizeof(desc));
1000 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
1002 if (!prefix_ok(param_format,"WrLeh")) {
1005 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1007 * Patch from Scott Moomaw <scott@bridgewater.edu>
1008 * to return the 'invalid info level' error if an
1009 * unknown level was requested.
1013 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1017 SSVALS(*rparam,0,ERRunknownlevel);
1023 status = rpc_pipe_open_interface(conn,
1024 &ndr_table_spoolss.syntax_id,
1026 &conn->sconn->client_id,
1027 conn->sconn->msg_ctx,
1029 if (!NT_STATUS_IS_OK(status)) {
1030 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1031 nt_errstr(status)));
1032 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1036 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
1038 cli->srv_name_slash,
1043 if (!W_ERROR_IS_OK(werr)) {
1044 desc.errcode = W_ERROR_V(werr);
1048 queuecnt = num_printers;
1050 job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
1051 if (job_info == NULL) {
1055 driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
1056 if (driver_info == NULL) {
1060 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1061 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1066 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1072 desc.buflen = mdrcnt;
1075 for (i = 0; i < num_printers; i++) {
1078 struct policy_handle handle;
1079 const char *printername;
1081 printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
1082 if (printername == NULL) {
1086 ZERO_STRUCT(handle);
1087 ZERO_STRUCT(devmode_ctr);
1089 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
1096 if (!NT_STATUS_IS_OK(status)) {
1097 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1100 if (!W_ERROR_IS_OK(werr)) {
1101 desc.errcode = W_ERROR_V(werr);
1105 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
1113 if (!W_ERROR_IS_OK(werr)) {
1114 desc.errcode = W_ERROR_V(werr);
1119 uint32_t server_major_version;
1120 uint32_t server_minor_version;
1122 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1130 &server_major_version,
1131 &server_minor_version);
1132 if (!W_ERROR_IS_OK(werr)) {
1133 desc.errcode = W_ERROR_V(werr);
1138 subcntarr[i] = num_jobs;
1139 subcnt += subcntarr[i];
1141 if (cli && is_valid_policy_hnd(&handle)) {
1142 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1146 if (init_package(&desc,queuecnt,subcnt)) {
1147 for (i = 0; i < num_printers; i++) {
1148 fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
1149 if (desc.errcode == NERR_Success) {
1155 SAFE_FREE(subcntarr);
1157 *rdata_len = desc.usedlen;
1159 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1163 SSVALS(*rparam,0,desc.errcode);
1165 SSVAL(*rparam,4,succnt);
1166 SSVAL(*rparam,6,queuecnt);
1172 SAFE_FREE(subcntarr);
1177 /****************************************************************************
1178 Get info level for a server list query.
1179 ****************************************************************************/
1181 static bool check_server_info(int uLevel, char* id)
1185 if (strcmp(id,"B16") != 0) {
1190 if (strcmp(id,"B16BBDz") != 0) {
1200 struct srv_info_struct {
1208 /*******************************************************************
1209 Get server info lists from the files saved by nmbd. Return the
1211 ******************************************************************/
1213 static int get_server_info(uint32 servertype,
1214 struct srv_info_struct **servers,
1220 bool local_list_only;
1223 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1225 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1229 /* request for everything is code for request all servers */
1230 if (servertype == SV_TYPE_ALL) {
1231 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1234 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1236 DEBUG(4,("Servertype search: %8x\n",servertype));
1238 for (i=0;lines[i];i++) {
1240 struct srv_info_struct *s;
1241 const char *ptr = lines[i];
1243 TALLOC_CTX *frame = NULL;
1250 if (count == alloced) {
1252 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1254 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1258 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1260 s = &(*servers)[count];
1262 frame = talloc_stackframe();
1264 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1268 fstrcpy(s->name, p);
1271 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1277 s->comment[0] = '\0';
1278 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1282 fstrcpy(s->comment, p);
1283 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1285 s->domain[0] = '\0';
1286 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1287 /* this allows us to cope with an old nmbd */
1288 fstrcpy(s->domain,lp_workgroup());
1290 fstrcpy(s->domain, p);
1294 if (sscanf(stype,"%X",&s->type) != 1) {
1295 DEBUG(4,("r:host file "));
1299 /* Filter the servers/domains we return based on what was asked for. */
1301 /* Check to see if we are being asked for a local list only. */
1302 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1303 DEBUG(4,("r: local list only"));
1307 /* doesn't match up: don't want it */
1308 if (!(servertype & s->type)) {
1309 DEBUG(4,("r:serv type "));
1313 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1314 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1315 DEBUG(4,("s: dom mismatch "));
1319 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1323 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1324 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1327 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1328 s->name, s->type, s->comment, s->domain));
1329 s->server_added = True;
1332 DEBUG(4,("%20s %8x %25s %15s\n",
1333 s->name, s->type, s->comment, s->domain));
1341 /*******************************************************************
1342 Fill in a server info structure.
1343 ******************************************************************/
1345 static int fill_srv_info(struct srv_info_struct *service,
1346 int uLevel, char **buf, int *buflen,
1347 char **stringbuf, int *stringspace, char *baseaddr)
1370 len = strlen(service->comment)+1;
1374 *buflen = struct_len;
1376 return struct_len + len;
1381 if (*buflen < struct_len) {
1388 p2 = p + struct_len;
1389 l2 = *buflen - struct_len;
1397 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1401 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1402 SIVAL(p,18,service->type);
1403 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1404 len += CopyAndAdvance(&p2,service->comment,&l2);
1409 *buf = p + struct_len;
1410 *buflen -= struct_len;
1421 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1423 return StrCaseCmp(s1->name,s2->name);
1426 /****************************************************************************
1427 View list of servers available (or possibly domains). The info is
1428 extracted from lists saved by nmbd on the local host.
1429 ****************************************************************************/
1431 static bool api_RNetServerEnum2(struct smbd_server_connection *sconn,
1432 connection_struct *conn, uint16 vuid,
1433 char *param, int tpscnt,
1434 char *data, int tdscnt,
1435 int mdrcnt, int mprcnt, char **rdata,
1436 char **rparam, int *rdata_len, int *rparam_len)
1438 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1439 char *str2 = skip_string(param,tpscnt,str1);
1440 char *p = skip_string(param,tpscnt,str2);
1441 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1442 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1443 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1445 int data_len, fixed_len, string_len;
1446 int f_len = 0, s_len = 0;
1447 struct srv_info_struct *servers=NULL;
1448 int counted=0,total=0;
1451 bool domain_request;
1454 if (!str1 || !str2 || !p) {
1458 /* If someone sets all the bits they don't really mean to set
1459 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1462 if (servertype == SV_TYPE_ALL) {
1463 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1466 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1467 any other bit (they may just set this bit on its own) they
1468 want all the locally seen servers. However this bit can be
1469 set on its own so set the requested servers to be
1470 ALL - DOMAIN_ENUM. */
1472 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1473 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1476 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1477 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1481 if (!prefix_ok(str1,"WrLehD")) {
1484 if (!check_server_info(uLevel,str2)) {
1488 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1489 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1490 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1492 if (strcmp(str1, "WrLehDz") == 0) {
1493 if (skip_string(param,tpscnt,p) == NULL) {
1496 pull_ascii_fstring(domain, p);
1498 fstrcpy(domain, lp_workgroup());
1501 DEBUG(4, ("domain [%s]\n", domain));
1503 if (lp_browse_list()) {
1504 total = get_server_info(servertype,&servers,domain);
1507 data_len = fixed_len = string_len = 0;
1510 TYPESAFE_QSORT(servers, total, srv_comp);
1513 char *lastname=NULL;
1515 for (i=0;i<total;i++) {
1516 struct srv_info_struct *s = &servers[i];
1518 if (lastname && strequal(lastname,s->name)) {
1522 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1523 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1524 i, s->name, s->type, s->comment, s->domain));
1526 if (data_len < buf_len) {
1529 string_len += s_len;
1536 *rdata_len = fixed_len + string_len;
1537 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1542 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1548 char *lastname=NULL;
1549 int count2 = counted;
1551 for (i = 0; i < total && count2;i++) {
1552 struct srv_info_struct *s = &servers[i];
1554 if (lastname && strequal(lastname,s->name)) {
1558 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1559 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1560 i, s->name, s->type, s->comment, s->domain));
1566 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1570 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1572 SSVAL(*rparam,4,counted);
1573 SSVAL(*rparam,6,counted+missed);
1577 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1578 domain,uLevel,counted,counted+missed));
1583 static int srv_name_match(const char *n1, const char *n2)
1586 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1588 * In Windows, FirstNameToReturn need not be an exact match:
1589 * the server will return a list of servers that exist on
1590 * the network greater than or equal to the FirstNameToReturn.
1592 int ret = StrCaseCmp(n1, n2);
1601 static bool api_RNetServerEnum3(struct smbd_server_connection *sconn,
1602 connection_struct *conn, uint16 vuid,
1603 char *param, int tpscnt,
1604 char *data, int tdscnt,
1605 int mdrcnt, int mprcnt, char **rdata,
1606 char **rparam, int *rdata_len, int *rparam_len)
1608 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1609 char *str2 = skip_string(param,tpscnt,str1);
1610 char *p = skip_string(param,tpscnt,str2);
1611 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1612 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1613 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1615 int data_len, fixed_len, string_len;
1616 int f_len = 0, s_len = 0;
1617 struct srv_info_struct *servers=NULL;
1618 int counted=0,first=0,total=0;
1622 bool domain_request;
1625 if (!str1 || !str2 || !p) {
1629 /* If someone sets all the bits they don't really mean to set
1630 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1633 if (servertype == SV_TYPE_ALL) {
1634 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1637 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1638 any other bit (they may just set this bit on its own) they
1639 want all the locally seen servers. However this bit can be
1640 set on its own so set the requested servers to be
1641 ALL - DOMAIN_ENUM. */
1643 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1644 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1647 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1648 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1652 if (strcmp(str1, "WrLehDzz") != 0) {
1655 if (!check_server_info(uLevel,str2)) {
1659 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1660 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1661 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1663 if (skip_string(param,tpscnt,p) == NULL) {
1666 pull_ascii_fstring(domain, p);
1667 if (domain[0] == '\0') {
1668 fstrcpy(domain, lp_workgroup());
1670 p = skip_string(param,tpscnt,p);
1671 if (skip_string(param,tpscnt,p) == NULL) {
1674 pull_ascii_fstring(first_name, p);
1676 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1677 domain, first_name));
1679 if (lp_browse_list()) {
1680 total = get_server_info(servertype,&servers,domain);
1683 data_len = fixed_len = string_len = 0;
1686 TYPESAFE_QSORT(servers, total, srv_comp);
1688 if (first_name[0] != '\0') {
1689 struct srv_info_struct *first_server = NULL;
1691 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1692 srv_name_match, first_server);
1694 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1696 * The binary search may not find the exact match
1697 * so we need to search backward to find the first match
1699 * This implements the strange matching windows
1700 * implements. (see the comment in srv_name_match().
1704 ret = StrCaseCmp(first_name,
1705 servers[first-1].name);
1712 /* we should return no entries */
1718 char *lastname=NULL;
1720 for (i=first;i<total;i++) {
1721 struct srv_info_struct *s = &servers[i];
1723 if (lastname && strequal(lastname,s->name)) {
1727 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1728 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1729 i, s->name, s->type, s->comment, s->domain));
1731 if (data_len < buf_len) {
1734 string_len += s_len;
1741 *rdata_len = fixed_len + string_len;
1742 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1747 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1753 char *lastname=NULL;
1754 int count2 = counted;
1756 for (i = first; i < total && count2;i++) {
1757 struct srv_info_struct *s = &servers[i];
1759 if (lastname && strequal(lastname,s->name)) {
1763 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1764 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1765 i, s->name, s->type, s->comment, s->domain));
1771 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1775 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1777 SSVAL(*rparam,4,counted);
1778 SSVAL(*rparam,6,counted+missed);
1780 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1781 domain,uLevel,first,first_name,
1782 first < total ? servers[first].name : "",
1783 counted,counted+missed));
1790 /****************************************************************************
1791 command 0x34 - suspected of being a "Lookup Names" stub api
1792 ****************************************************************************/
1794 static bool api_RNetGroupGetUsers(struct smbd_server_connection *sconn,
1795 connection_struct *conn, uint16 vuid,
1796 char *param, int tpscnt,
1797 char *data, int tdscnt,
1798 int mdrcnt, int mprcnt, char **rdata,
1799 char **rparam, int *rdata_len, int *rparam_len)
1801 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1802 char *str2 = skip_string(param,tpscnt,str1);
1803 char *p = skip_string(param,tpscnt,str2);
1804 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1805 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1809 if (!str1 || !str2 || !p) {
1813 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1814 str1, str2, p, uLevel, buf_len));
1816 if (!prefix_ok(str1,"zWrLeh")) {
1823 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1828 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1830 SSVAL(*rparam,4,counted);
1831 SSVAL(*rparam,6,counted+missed);
1836 /****************************************************************************
1837 get info about a share
1838 ****************************************************************************/
1840 static bool check_share_info(int uLevel, char* id)
1844 if (strcmp(id,"B13") != 0) {
1849 /* Level-2 descriptor is allowed (and ignored) */
1850 if (strcmp(id,"B13BWz") != 0 &&
1851 strcmp(id,"B13BWzWWWzB9B") != 0) {
1856 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1861 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1871 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1872 char** buf, int* buflen,
1873 char** stringbuf, int* stringspace, char* baseaddr)
1902 len += StrlenExpanded(conn,snum,lp_comment(snum));
1905 len += strlen(lp_pathname(snum)) + 1;
1908 *buflen = struct_len;
1913 return struct_len + len;
1918 if ((*buflen) < struct_len) {
1926 p2 = p + struct_len;
1927 l2 = (*buflen) - struct_len;
1934 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1940 type = STYPE_DISKTREE;
1941 if (lp_print_ok(snum)) {
1942 type = STYPE_PRINTQ;
1944 if (strequal("IPC",lp_fstype(snum))) {
1947 SSVAL(p,14,type); /* device type */
1948 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1949 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1953 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1954 SSVALS(p,22,-1); /* max uses */
1955 SSVAL(p,24,1); /* current uses */
1956 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1957 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1958 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1962 memset(p+40,0,SHPWLEN+2);
1973 (*buf) = p + struct_len;
1974 (*buflen) -= struct_len;
1976 (*stringspace) = l2;
1985 static bool api_RNetShareGetInfo(struct smbd_server_connection *sconn,
1986 connection_struct *conn,uint16 vuid,
1987 char *param, int tpscnt,
1988 char *data, int tdscnt,
1989 int mdrcnt,int mprcnt,
1990 char **rdata,char **rparam,
1991 int *rdata_len,int *rparam_len)
1993 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1994 char *str2 = skip_string(param,tpscnt,str1);
1995 char *netname = skip_string(param,tpscnt,str2);
1996 char *p = skip_string(param,tpscnt,netname);
1997 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2000 if (!str1 || !str2 || !netname || !p) {
2004 snum = find_service(netname);
2009 /* check it's a supported varient */
2010 if (!prefix_ok(str1,"zWrLh")) {
2013 if (!check_share_info(uLevel,str2)) {
2017 *rdata = smb_realloc_limit(*rdata,mdrcnt);
2022 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
2023 if (*rdata_len < 0) {
2028 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2032 SSVAL(*rparam,0,NERR_Success);
2033 SSVAL(*rparam,2,0); /* converter word */
2034 SSVAL(*rparam,4,*rdata_len);
2039 /****************************************************************************
2040 View the list of available shares.
2042 This function is the server side of the NetShareEnum() RAP call.
2043 It fills the return buffer with share names and share comments.
2044 Note that the return buffer normally (in all known cases) allows only
2045 twelve byte strings for share names (plus one for a nul terminator).
2046 Share names longer than 12 bytes must be skipped.
2047 ****************************************************************************/
2049 static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
2050 connection_struct *conn, uint16 vuid,
2051 char *param, int tpscnt,
2052 char *data, int tdscnt,
2060 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2061 char *str2 = skip_string(param,tpscnt,str1);
2062 char *p = skip_string(param,tpscnt,str2);
2063 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2064 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2067 int total=0,counted=0;
2068 bool missed = False;
2070 int data_len, fixed_len, string_len;
2071 int f_len = 0, s_len = 0;
2073 if (!str1 || !str2 || !p) {
2077 if (!prefix_ok(str1,"WrLeh")) {
2080 if (!check_share_info(uLevel,str2)) {
2084 /* Ensure all the usershares are loaded. */
2086 load_registry_shares();
2087 count = load_usershare_shares();
2090 data_len = fixed_len = string_len = 0;
2091 for (i=0;i<count;i++) {
2092 fstring servicename_dos;
2093 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2096 push_ascii_fstring(servicename_dos, lp_servicename(i));
2097 /* Maximum name length = 13. */
2098 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2100 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2101 if (data_len < buf_len) {
2104 string_len += s_len;
2111 *rdata_len = fixed_len + string_len;
2112 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2117 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2122 for( i = 0; i < count; i++ ) {
2123 fstring servicename_dos;
2124 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2128 push_ascii_fstring(servicename_dos, lp_servicename(i));
2129 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2130 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2137 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2141 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2143 SSVAL(*rparam,4,counted);
2144 SSVAL(*rparam,6,total);
2146 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2147 counted,total,uLevel,
2148 buf_len,*rdata_len,mdrcnt));
2153 /****************************************************************************
2155 ****************************************************************************/
2157 static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
2158 connection_struct *conn,uint16 vuid,
2159 char *param, int tpscnt,
2160 char *data, int tdscnt,
2161 int mdrcnt,int mprcnt,
2162 char **rdata,char **rparam,
2163 int *rdata_len,int *rparam_len)
2165 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2166 char *str2 = skip_string(param,tpscnt,str1);
2167 char *p = skip_string(param,tpscnt,str2);
2168 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2171 char *pathname = NULL;
2172 unsigned int offset;
2174 size_t converted_size;
2176 WERROR werr = WERR_OK;
2177 TALLOC_CTX *mem_ctx = talloc_tos();
2179 struct rpc_pipe_client *cli = NULL;
2180 union srvsvc_NetShareInfo info;
2181 struct srvsvc_NetShareInfo2 info2;
2183 if (!str1 || !str2 || !p) {
2187 /* check it's a supported varient */
2188 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2191 if (!check_share_info(uLevel,str2)) {
2198 /* Do we have a string ? */
2199 if (skip_string(data,mdrcnt,data) == NULL) {
2202 pull_ascii_fstring(sharename,data);
2208 /* only support disk share adds */
2209 if (SVAL(data,14)!=STYPE_DISKTREE) {
2213 offset = IVAL(data, 16);
2214 if (offset >= mdrcnt) {
2215 res = ERRinvalidparam;
2219 /* Do we have a string ? */
2220 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2223 pull_ascii_fstring(comment, offset? (data+offset) : "");
2225 offset = IVAL(data, 26);
2227 if (offset >= mdrcnt) {
2228 res = ERRinvalidparam;
2232 /* Do we have a string ? */
2233 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2237 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2238 offset ? (data+offset) : "", &converted_size))
2240 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2248 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
2250 &conn->sconn->client_id,
2251 conn->sconn->msg_ctx,
2253 if (!NT_STATUS_IS_OK(status)) {
2254 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2255 nt_errstr(status)));
2256 res = W_ERROR_V(ntstatus_to_werror(status));
2260 info2.name = sharename;
2261 info2.type = STYPE_DISKTREE;
2262 info2.comment = comment;
2263 info2.permissions = 0;
2264 info2.max_users = 0;
2265 info2.current_users = 0;
2266 info2.path = pathname;
2267 info2.password = NULL;
2269 info.info2 = &info2;
2271 status = rpccli_srvsvc_NetShareAdd(cli, mem_ctx,
2272 cli->srv_name_slash,
2277 if (!NT_STATUS_IS_OK(status)) {
2278 res = W_ERROR_V(ntstatus_to_werror(status));
2281 if (!W_ERROR_IS_OK(werr)) {
2282 res = W_ERROR_V(werr);
2287 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2291 SSVAL(*rparam,0,NERR_Success);
2292 SSVAL(*rparam,2,0); /* converter word */
2293 SSVAL(*rparam,4,*rdata_len);
2301 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2306 SSVAL(*rparam,0,res);
2311 /****************************************************************************
2312 view list of groups available
2313 ****************************************************************************/
2315 static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
2316 connection_struct *conn,uint16 vuid,
2317 char *param, int tpscnt,
2318 char *data, int tdscnt,
2319 int mdrcnt,int mprcnt,
2320 char **rdata,char **rparam,
2321 int *rdata_len,int *rparam_len)
2325 int resume_context, cli_buf_size;
2326 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2327 char *str2 = skip_string(param,tpscnt,str1);
2328 char *p = skip_string(param,tpscnt,str2);
2330 uint32_t num_groups;
2331 uint32_t resume_handle;
2332 struct rpc_pipe_client *samr_pipe;
2333 struct policy_handle samr_handle, domain_handle;
2336 if (!str1 || !str2 || !p) {
2340 if (strcmp(str1,"WrLeh") != 0) {
2345 * W-> resume context (number of users to skip)
2346 * r -> return parameter pointer to receive buffer
2347 * L -> length of receive buffer
2348 * e -> return parameter number of entries
2349 * h -> return parameter total number of users
2352 if (strcmp("B21",str2) != 0) {
2356 status = rpc_pipe_open_internal(
2357 talloc_tos(), &ndr_table_samr.syntax_id,
2358 conn->server_info, &conn->sconn->client_id,
2359 conn->sconn->msg_ctx, &samr_pipe);
2360 if (!NT_STATUS_IS_OK(status)) {
2361 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2362 nt_errstr(status)));
2366 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2367 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2368 if (!NT_STATUS_IS_OK(status)) {
2369 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2370 nt_errstr(status)));
2374 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2375 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2376 get_global_sam_sid(), &domain_handle);
2377 if (!NT_STATUS_IS_OK(status)) {
2378 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2379 nt_errstr(status)));
2380 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2384 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2385 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2386 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2387 "%d\n", resume_context, cli_buf_size));
2389 *rdata_len = cli_buf_size;
2390 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2397 errflags = NERR_Success;
2402 struct samr_SamArray *sam_entries;
2403 uint32_t num_entries;
2405 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2410 if (!NT_STATUS_IS_OK(status)) {
2411 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2412 "%s\n", nt_errstr(status)));
2416 if (num_entries == 0) {
2417 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2418 "no entries -- done\n"));
2422 for(i=0; i<num_entries; i++) {
2425 name = sam_entries->entries[i].name.string;
2427 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2428 /* set overflow error */
2429 DEBUG(3,("overflow on entry %d group %s\n", i,
2435 /* truncate the name at 21 chars. */
2437 strlcpy(p, name, 21);
2438 DEBUG(10,("adding entry %d group %s\n", i, p));
2440 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2445 if (errflags != NERR_Success) {
2449 TALLOC_FREE(sam_entries);
2452 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2453 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2455 *rdata_len = PTR_DIFF(p,*rdata);
2458 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2462 SSVAL(*rparam, 0, errflags);
2463 SSVAL(*rparam, 2, 0); /* converter word */
2464 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2465 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2470 /*******************************************************************
2471 Get groups that a user is a member of.
2472 ******************************************************************/
2474 static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
2475 connection_struct *conn,uint16 vuid,
2476 char *param, int tpscnt,
2477 char *data, int tdscnt,
2478 int mdrcnt,int mprcnt,
2479 char **rdata,char **rparam,
2480 int *rdata_len,int *rparam_len)
2482 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2483 char *str2 = skip_string(param,tpscnt,str1);
2484 char *UserName = skip_string(param,tpscnt,str2);
2485 char *p = skip_string(param,tpscnt,UserName);
2486 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2487 const char *level_string;
2493 struct rpc_pipe_client *samr_pipe;
2494 struct policy_handle samr_handle, domain_handle, user_handle;
2495 struct lsa_String name;
2496 struct lsa_Strings names;
2497 struct samr_Ids type, rid;
2498 struct samr_RidWithAttributeArray *rids;
2501 if (!str1 || !str2 || !UserName || !p) {
2506 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2511 /* check it's a supported varient */
2513 if ( strcmp(str1,"zWrLeh") != 0 )
2518 level_string = "B21";
2524 if (strcmp(level_string,str2) != 0)
2527 *rdata_len = mdrcnt + 1024;
2528 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2533 SSVAL(*rparam,0,NERR_Success);
2534 SSVAL(*rparam,2,0); /* converter word */
2537 endp = *rdata + *rdata_len;
2539 status = rpc_pipe_open_internal(
2540 talloc_tos(), &ndr_table_samr.syntax_id,
2541 conn->server_info, &conn->sconn->client_id,
2542 conn->sconn->msg_ctx, &samr_pipe);
2543 if (!NT_STATUS_IS_OK(status)) {
2544 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2545 nt_errstr(status)));
2549 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2550 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2553 nt_errstr(status)));
2557 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2558 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2559 get_global_sam_sid(), &domain_handle);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2562 nt_errstr(status)));
2566 name.string = UserName;
2568 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2569 &domain_handle, 1, &name,
2571 if (!NT_STATUS_IS_OK(status)) {
2572 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2573 nt_errstr(status)));
2577 if (type.ids[0] != SID_NAME_USER) {
2578 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2579 sid_type_lookup(type.ids[0])));
2583 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2585 SAMR_USER_ACCESS_GET_GROUPS,
2586 rid.ids[0], &user_handle);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2589 nt_errstr(status)));
2593 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2594 &user_handle, &rids);
2595 if (!NT_STATUS_IS_OK(status)) {
2596 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2597 nt_errstr(status)));
2601 for (i=0; i<rids->count; i++) {
2603 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2605 1, &rids->rids[i].rid,
2607 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2608 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2614 *rdata_len = PTR_DIFF(p,*rdata);
2616 SSVAL(*rparam,4,count); /* is this right?? */
2617 SSVAL(*rparam,6,count); /* is this right?? */
2622 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2624 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2626 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2631 /*******************************************************************
2633 ******************************************************************/
2635 static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
2636 connection_struct *conn, uint16 vuid,
2637 char *param, int tpscnt,
2638 char *data, int tdscnt,
2639 int mdrcnt,int mprcnt,
2640 char **rdata,char **rparam,
2641 int *rdata_len,int *rparam_len)
2646 int i, resume_context, cli_buf_size;
2647 uint32_t resume_handle;
2649 struct rpc_pipe_client *samr_pipe;
2650 struct policy_handle samr_handle, domain_handle;
2653 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2654 char *str2 = skip_string(param,tpscnt,str1);
2655 char *p = skip_string(param,tpscnt,str2);
2658 if (!str1 || !str2 || !p) {
2662 if (strcmp(str1,"WrLeh") != 0)
2665 * W-> resume context (number of users to skip)
2666 * r -> return parameter pointer to receive buffer
2667 * L -> length of receive buffer
2668 * e -> return parameter number of entries
2669 * h -> return parameter total number of users
2672 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2673 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2674 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2675 resume_context, cli_buf_size));
2678 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2683 /* check it's a supported varient */
2684 if (strcmp("B21",str2) != 0)
2687 *rdata_len = cli_buf_size;
2688 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2694 endp = *rdata + *rdata_len;
2696 status = rpc_pipe_open_internal(
2697 talloc_tos(), &ndr_table_samr.syntax_id,
2698 conn->server_info, &conn->sconn->client_id,
2699 conn->sconn->msg_ctx, &samr_pipe);
2700 if (!NT_STATUS_IS_OK(status)) {
2701 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2702 nt_errstr(status)));
2706 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2707 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2710 nt_errstr(status)));
2714 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2715 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2716 get_global_sam_sid(), &domain_handle);
2717 if (!NT_STATUS_IS_OK(status)) {
2718 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2719 nt_errstr(status)));
2720 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2724 errflags=NERR_Success;
2729 struct samr_SamArray *sam_entries;
2730 uint32_t num_entries;
2732 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2738 if (!NT_STATUS_IS_OK(status)) {
2739 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2740 "%s\n", nt_errstr(status)));
2744 if (num_entries == 0) {
2745 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2746 "no entries -- done\n"));
2750 for (i=0; i<num_entries; i++) {
2753 name = sam_entries->entries[i].name.string;
2755 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2756 &&(strlen(name)<=21)) {
2757 strlcpy(p,name,PTR_DIFF(endp,p));
2758 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2759 "username %s\n",count_sent,p));
2763 /* set overflow error */
2764 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2765 "username %s\n",count_sent,name));
2771 if (errflags != NERR_Success) {
2775 TALLOC_FREE(sam_entries);
2778 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2779 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2781 *rdata_len = PTR_DIFF(p,*rdata);
2783 SSVAL(*rparam,0,errflags);
2784 SSVAL(*rparam,2,0); /* converter word */
2785 SSVAL(*rparam,4,count_sent); /* is this right?? */
2786 SSVAL(*rparam,6,num_users); /* is this right?? */
2791 /****************************************************************************
2792 Get the time of day info.
2793 ****************************************************************************/
2795 static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
2796 connection_struct *conn,uint16 vuid,
2797 char *param, int tpscnt,
2798 char *data, int tdscnt,
2799 int mdrcnt,int mprcnt,
2800 char **rdata,char **rparam,
2801 int *rdata_len,int *rparam_len)
2804 time_t unixdate = time(NULL);
2808 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2814 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2819 SSVAL(*rparam,0,NERR_Success);
2820 SSVAL(*rparam,2,0); /* converter word */
2824 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2825 by NT in a "net time" operation,
2826 it seems to ignore the one below */
2828 /* the client expects to get localtime, not GMT, in this bit
2829 (I think, this needs testing) */
2830 t = localtime(&unixdate);
2835 SIVAL(p,4,0); /* msecs ? */
2836 SCVAL(p,8,t->tm_hour);
2837 SCVAL(p,9,t->tm_min);
2838 SCVAL(p,10,t->tm_sec);
2839 SCVAL(p,11,0); /* hundredths of seconds */
2840 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2841 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2842 SCVAL(p,16,t->tm_mday);
2843 SCVAL(p,17,t->tm_mon + 1);
2844 SSVAL(p,18,1900+t->tm_year);
2845 SCVAL(p,20,t->tm_wday);
2850 /****************************************************************************
2851 Set the user password.
2852 *****************************************************************************/
2854 static bool api_SetUserPassword(struct smbd_server_connection *sconn,
2855 connection_struct *conn,uint16 vuid,
2856 char *param, int tpscnt,
2857 char *data, int tdscnt,
2858 int mdrcnt,int mprcnt,
2859 char **rdata,char **rparam,
2860 int *rdata_len,int *rparam_len)
2862 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2865 fstring pass1,pass2;
2866 TALLOC_CTX *mem_ctx = talloc_tos();
2868 struct rpc_pipe_client *cli = NULL;
2869 struct policy_handle connect_handle, domain_handle, user_handle;
2870 struct lsa_String domain_name;
2871 struct dom_sid2 *domain_sid;
2872 struct lsa_String names;
2873 struct samr_Ids rids;
2874 struct samr_Ids types;
2875 struct samr_Password old_lm_hash;
2876 struct samr_Password new_lm_hash;
2877 int errcode = NERR_badpass;
2882 /* Skip 2 strings. */
2883 p = skip_string(param,tpscnt,np);
2884 p = skip_string(param,tpscnt,p);
2890 /* Do we have a string ? */
2891 if (skip_string(param,tpscnt,p) == NULL) {
2894 pull_ascii_fstring(user,p);
2896 p = skip_string(param,tpscnt,p);
2901 memset(pass1,'\0',sizeof(pass1));
2902 memset(pass2,'\0',sizeof(pass2));
2904 * We use 31 here not 32 as we're checking
2905 * the last byte we want to access is safe.
2907 if (!is_offset_safe(param,tpscnt,p,31)) {
2911 memcpy(pass2,p+16,16);
2913 encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
2914 if (encrypted == -1) {
2915 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2919 min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
2920 if (min_pwd_length == -1) {
2921 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2926 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2933 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2934 user, encrypted, min_pwd_length));
2936 ZERO_STRUCT(connect_handle);
2937 ZERO_STRUCT(domain_handle);
2938 ZERO_STRUCT(user_handle);
2940 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
2942 &conn->sconn->client_id,
2943 conn->sconn->msg_ctx,
2945 if (!NT_STATUS_IS_OK(status)) {
2946 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2947 nt_errstr(status)));
2948 errcode = W_ERROR_V(ntstatus_to_werror(status));
2952 status = rpccli_samr_Connect2(cli, mem_ctx,
2954 SAMR_ACCESS_CONNECT_TO_SERVER |
2955 SAMR_ACCESS_ENUM_DOMAINS |
2956 SAMR_ACCESS_LOOKUP_DOMAIN,
2958 if (!NT_STATUS_IS_OK(status)) {
2959 errcode = W_ERROR_V(ntstatus_to_werror(status));
2963 init_lsa_String(&domain_name, get_global_sam_name());
2965 status = rpccli_samr_LookupDomain(cli, mem_ctx,
2969 if (!NT_STATUS_IS_OK(status)) {
2970 errcode = W_ERROR_V(ntstatus_to_werror(status));
2974 status = rpccli_samr_OpenDomain(cli, mem_ctx,
2976 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2979 if (!NT_STATUS_IS_OK(status)) {
2980 errcode = W_ERROR_V(ntstatus_to_werror(status));
2984 init_lsa_String(&names, user);
2986 status = rpccli_samr_LookupNames(cli, mem_ctx,
2992 if (!NT_STATUS_IS_OK(status)) {
2993 errcode = W_ERROR_V(ntstatus_to_werror(status));
2997 if (rids.count != 1) {
2998 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
3001 if (rids.count != types.count) {
3002 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3005 if (types.ids[0] != SID_NAME_USER) {
3006 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3012 status = rpccli_samr_OpenUser(cli, mem_ctx,
3014 SAMR_USER_ACCESS_CHANGE_PASSWORD,
3017 if (!NT_STATUS_IS_OK(status)) {
3018 errcode = W_ERROR_V(ntstatus_to_werror(status));
3022 if (encrypted == 0) {
3023 E_deshash(pass1, old_lm_hash.hash);
3024 E_deshash(pass2, new_lm_hash.hash);
3026 ZERO_STRUCT(old_lm_hash);
3027 ZERO_STRUCT(new_lm_hash);
3028 memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
3029 memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16));
3032 status = rpccli_samr_ChangePasswordUser(cli, mem_ctx,
3034 true, /* lm_present */
3037 false, /* nt_present */
3038 NULL, /* old_nt_crypted */
3039 NULL, /* new_nt_crypted */
3040 false, /* cross1_present */
3041 NULL, /* nt_cross */
3042 false, /* cross2_present */
3043 NULL); /* lm_cross */
3044 if (!NT_STATUS_IS_OK(status)) {
3045 errcode = W_ERROR_V(ntstatus_to_werror(status));
3049 errcode = NERR_Success;
3052 if (cli && is_valid_policy_hnd(&user_handle)) {
3053 rpccli_samr_Close(cli, mem_ctx, &user_handle);
3055 if (cli && is_valid_policy_hnd(&domain_handle)) {
3056 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
3058 if (cli && is_valid_policy_hnd(&connect_handle)) {
3059 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
3062 memset((char *)pass1,'\0',sizeof(fstring));
3063 memset((char *)pass2,'\0',sizeof(fstring));
3065 SSVAL(*rparam,0,errcode);
3066 SSVAL(*rparam,2,0); /* converter word */
3070 /****************************************************************************
3071 Set the user password (SamOEM version - gets plaintext).
3072 ****************************************************************************/
3074 static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
3075 connection_struct *conn,uint16 vuid,
3076 char *param, int tpscnt,
3077 char *data, int tdscnt,
3078 int mdrcnt,int mprcnt,
3079 char **rdata,char **rparam,
3080 int *rdata_len,int *rparam_len)
3083 char *p = get_safe_str_ptr(param,tpscnt,param,2);
3085 TALLOC_CTX *mem_ctx = talloc_tos();
3087 struct rpc_pipe_client *cli = NULL;
3088 struct lsa_AsciiString server, account;
3089 struct samr_CryptPassword password;
3090 struct samr_Password hash;
3091 int errcode = NERR_badpass;
3095 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3105 SSVAL(*rparam,0,NERR_badpass);
3108 * Check the parameter definition is correct.
3111 /* Do we have a string ? */
3112 if (skip_string(param,tpscnt,p) == 0) {
3115 if(!strequal(p, "zsT")) {
3116 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3119 p = skip_string(param, tpscnt, p);
3124 /* Do we have a string ? */
3125 if (skip_string(param,tpscnt,p) == 0) {
3128 if(!strequal(p, "B516B16")) {
3129 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3132 p = skip_string(param,tpscnt,p);
3136 /* Do we have a string ? */
3137 if (skip_string(param,tpscnt,p) == 0) {
3140 p += pull_ascii_fstring(user,p);
3142 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3144 if (tdscnt != 532) {
3145 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3149 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3150 if (bufsize != 532) {
3151 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3155 memcpy(password.data, data, 516);
3156 memcpy(hash.hash, data+516, 16);
3158 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
3160 &conn->sconn->client_id,
3161 conn->sconn->msg_ctx,
3163 if (!NT_STATUS_IS_OK(status)) {
3164 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3165 nt_errstr(status)));
3166 errcode = W_ERROR_V(ntstatus_to_werror(status));
3170 init_lsa_AsciiString(&server, global_myname());
3171 init_lsa_AsciiString(&account, user);
3173 status = rpccli_samr_OemChangePasswordUser2(cli, mem_ctx,
3178 if (!NT_STATUS_IS_OK(status)) {
3179 errcode = W_ERROR_V(ntstatus_to_werror(status));
3183 errcode = NERR_Success;
3185 SSVAL(*rparam,0,errcode);
3186 SSVAL(*rparam,2,0); /* converter word */
3191 /****************************************************************************
3194 ****************************************************************************/
3196 static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
3197 connection_struct *conn,uint16 vuid,
3198 char *param, int tpscnt,
3199 char *data, int tdscnt,
3200 int mdrcnt,int mprcnt,
3201 char **rdata,char **rparam,
3202 int *rdata_len,int *rparam_len)
3204 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3205 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3206 char *str2 = skip_string(param,tpscnt,str1);
3207 char *p = skip_string(param,tpscnt,str2);
3211 WERROR werr = WERR_OK;
3213 TALLOC_CTX *mem_ctx = talloc_tos();
3215 struct rpc_pipe_client *cli = NULL;
3216 struct policy_handle handle;
3217 struct spoolss_DevmodeContainer devmode_ctr;
3218 enum spoolss_JobControl command;
3220 if (!str1 || !str2 || !p) {
3224 * We use 1 here not 2 as we're checking
3225 * the last byte we want to access is safe.
3227 if (!is_offset_safe(param,tpscnt,p,1)) {
3230 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3233 /* check it's a supported varient */
3234 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3238 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3244 ZERO_STRUCT(handle);
3246 status = rpc_pipe_open_interface(conn,
3247 &ndr_table_spoolss.syntax_id,
3249 &conn->sconn->client_id,
3250 conn->sconn->msg_ctx,
3252 if (!NT_STATUS_IS_OK(status)) {
3253 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3254 nt_errstr(status)));
3255 errcode = W_ERROR_V(ntstatus_to_werror(status));
3259 ZERO_STRUCT(devmode_ctr);
3261 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3265 JOB_ACCESS_ADMINISTER,
3268 if (!NT_STATUS_IS_OK(status)) {
3269 errcode = W_ERROR_V(ntstatus_to_werror(status));
3272 if (!W_ERROR_IS_OK(werr)) {
3273 errcode = W_ERROR_V(werr);
3277 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3278 * and NERR_DestNotFound if share did not exist */
3280 errcode = NERR_Success;
3283 case 81: /* delete */
3284 command = SPOOLSS_JOB_CONTROL_DELETE;
3286 case 82: /* pause */
3287 command = SPOOLSS_JOB_CONTROL_PAUSE;
3289 case 83: /* resume */
3290 command = SPOOLSS_JOB_CONTROL_RESUME;
3293 errcode = NERR_notsupported;
3297 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3300 NULL, /* unique ptr ctr */
3303 if (!NT_STATUS_IS_OK(status)) {
3304 errcode = W_ERROR_V(ntstatus_to_werror(status));
3307 if (!W_ERROR_IS_OK(werr)) {
3308 errcode = W_ERROR_V(werr);
3313 if (cli && is_valid_policy_hnd(&handle)) {
3314 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3317 SSVAL(*rparam,0,errcode);
3318 SSVAL(*rparam,2,0); /* converter word */
3323 /****************************************************************************
3324 Purge a print queue - or pause or resume it.
3325 ****************************************************************************/
3327 static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
3328 connection_struct *conn,uint16 vuid,
3329 char *param, int tpscnt,
3330 char *data, int tdscnt,
3331 int mdrcnt,int mprcnt,
3332 char **rdata,char **rparam,
3333 int *rdata_len,int *rparam_len)
3335 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3336 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3337 char *str2 = skip_string(param,tpscnt,str1);
3338 char *QueueName = skip_string(param,tpscnt,str2);
3339 int errcode = NERR_notsupported;
3340 WERROR werr = WERR_OK;
3343 TALLOC_CTX *mem_ctx = talloc_tos();
3344 struct rpc_pipe_client *cli = NULL;
3345 struct policy_handle handle;
3346 struct spoolss_SetPrinterInfoCtr info_ctr;
3347 struct spoolss_DevmodeContainer devmode_ctr;
3348 struct sec_desc_buf secdesc_ctr;
3349 enum spoolss_PrinterControl command;
3351 if (!str1 || !str2 || !QueueName) {
3355 /* check it's a supported varient */
3356 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3360 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3366 if (skip_string(param,tpscnt,QueueName) == NULL) {
3370 ZERO_STRUCT(handle);
3372 status = rpc_pipe_open_interface(conn,
3373 &ndr_table_spoolss.syntax_id,
3375 &conn->sconn->client_id,
3376 conn->sconn->msg_ctx,
3378 if (!NT_STATUS_IS_OK(status)) {
3379 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3380 nt_errstr(status)));
3381 errcode = W_ERROR_V(ntstatus_to_werror(status));
3385 ZERO_STRUCT(devmode_ctr);
3387 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3391 SEC_FLAG_MAXIMUM_ALLOWED,
3394 if (!NT_STATUS_IS_OK(status)) {
3395 errcode = W_ERROR_V(ntstatus_to_werror(status));
3398 if (!W_ERROR_IS_OK(werr)) {
3399 errcode = W_ERROR_V(werr);
3404 case 74: /* Pause queue */
3405 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3407 case 75: /* Resume queue */
3408 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3410 case 103: /* Purge */
3411 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3414 werr = WERR_NOT_SUPPORTED;
3418 if (!W_ERROR_IS_OK(werr)) {
3419 errcode = W_ERROR_V(werr);
3423 ZERO_STRUCT(info_ctr);
3424 ZERO_STRUCT(secdesc_ctr);
3426 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
3433 if (!NT_STATUS_IS_OK(status)) {
3434 errcode = W_ERROR_V(ntstatus_to_werror(status));
3437 if (!W_ERROR_IS_OK(werr)) {
3438 errcode = W_ERROR_V(werr);
3442 errcode = W_ERROR_V(werr);
3446 if (cli && is_valid_policy_hnd(&handle)) {
3447 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3450 SSVAL(*rparam,0,errcode);
3451 SSVAL(*rparam,2,0); /* converter word */
3456 /****************************************************************************
3457 set the property of a print job (undocumented?)
3458 ? function = 0xb -> set name of print job
3459 ? function = 0x6 -> move print job up/down
3460 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3461 or <WWsTP> <WB21BB16B10zWWzDDz>
3462 ****************************************************************************/
3464 static int check_printjob_info(struct pack_desc* desc,
3465 int uLevel, char* id)
3467 desc->subformat = NULL;
3469 case 0: desc->format = "W"; break;
3470 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3471 case 2: desc->format = "WWzWWDDzz"; break;
3472 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3473 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3475 DEBUG(0,("check_printjob_info: invalid level %d\n",
3479 if (id == NULL || strcmp(desc->format,id) != 0) {
3480 DEBUG(0,("check_printjob_info: invalid format %s\n",
3481 id ? id : "<NULL>" ));
3487 static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
3488 connection_struct *conn, uint16 vuid,
3489 char *param, int tpscnt,
3490 char *data, int tdscnt,
3491 int mdrcnt,int mprcnt,
3492 char **rdata,char **rparam,
3493 int *rdata_len,int *rparam_len)
3495 struct pack_desc desc;
3496 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3497 char *str2 = skip_string(param,tpscnt,str1);
3498 char *p = skip_string(param,tpscnt,str2);
3501 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3502 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3505 TALLOC_CTX *mem_ctx = talloc_tos();
3508 struct rpc_pipe_client *cli = NULL;
3509 struct policy_handle handle;
3510 struct spoolss_DevmodeContainer devmode_ctr;
3511 struct spoolss_JobInfoContainer ctr;
3512 union spoolss_JobInfo info;
3513 struct spoolss_SetJobInfo1 info1;
3515 if (!str1 || !str2 || !p) {
3519 * We use 1 here not 2 as we're checking
3520 * the last byte we want to access is safe.
3522 if (!is_offset_safe(param,tpscnt,p,1)) {
3525 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3528 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3535 /* check it's a supported varient */
3536 if ((strcmp(str1,"WWsTP")) ||
3537 (!check_printjob_info(&desc,uLevel,str2)))
3540 errcode = NERR_notsupported;
3544 /* change print job name, data gives the name */
3550 ZERO_STRUCT(handle);
3552 status = rpc_pipe_open_interface(conn,
3553 &ndr_table_spoolss.syntax_id,
3555 &conn->sconn->client_id,
3556 conn->sconn->msg_ctx,
3558 if (!NT_STATUS_IS_OK(status)) {
3559 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3560 nt_errstr(status)));
3561 errcode = W_ERROR_V(ntstatus_to_werror(status));
3565 ZERO_STRUCT(devmode_ctr);
3567 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3574 if (!NT_STATUS_IS_OK(status)) {
3575 errcode = W_ERROR_V(ntstatus_to_werror(status));
3578 if (!W_ERROR_IS_OK(werr)) {
3579 errcode = W_ERROR_V(werr);
3583 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3589 if (!W_ERROR_IS_OK(werr)) {
3590 errcode = W_ERROR_V(werr);
3596 info1.job_id = info.info1.job_id;
3597 info1.printer_name = info.info1.printer_name;
3598 info1.user_name = info.info1.user_name;
3599 info1.document_name = data;
3600 info1.data_type = info.info1.data_type;
3601 info1.text_status = info.info1.text_status;
3602 info1.status = info.info1.status;
3603 info1.priority = info.info1.priority;
3604 info1.position = info.info1.position;
3605 info1.total_pages = info.info1.total_pages;
3606 info1.pages_printed = info.info1.pages_printed;
3607 info1.submitted = info.info1.submitted;
3610 ctr.info.info1 = &info1;
3612 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3618 if (!NT_STATUS_IS_OK(status)) {
3619 errcode = W_ERROR_V(ntstatus_to_werror(status));
3622 if (!W_ERROR_IS_OK(werr)) {
3623 errcode = W_ERROR_V(werr);
3627 errcode = NERR_Success;
3630 if (cli && is_valid_policy_hnd(&handle)) {
3631 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3634 SSVALS(*rparam,0,errcode);
3635 SSVAL(*rparam,2,0); /* converter word */
3641 /****************************************************************************
3642 Get info about the server.
3643 ****************************************************************************/
3645 static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
3646 connection_struct *conn,uint16 vuid,
3647 char *param, int tpscnt,
3648 char *data, int tdscnt,
3649 int mdrcnt,int mprcnt,
3650 char **rdata,char **rparam,
3651 int *rdata_len,int *rparam_len)
3653 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3654 char *str2 = skip_string(param,tpscnt,str1);
3655 char *p = skip_string(param,tpscnt,str2);
3656 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3662 TALLOC_CTX *mem_ctx = talloc_tos();
3663 struct rpc_pipe_client *cli = NULL;
3664 union srvsvc_NetSrvInfo info;
3667 if (!str1 || !str2 || !p) {
3671 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3673 /* check it's a supported varient */
3674 if (!prefix_ok(str1,"WrLh")) {
3680 if (strcmp(str2,"B16") != 0) {
3686 if (strcmp(str2,"B16BBDz") != 0) {
3692 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3698 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3704 if (strcmp(str2,"DN") != 0) {
3710 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3719 *rdata_len = mdrcnt;
3720 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3726 p2 = p + struct_len;
3728 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
3730 &conn->sconn->client_id,
3731 conn->sconn->msg_ctx,
3733 if (!NT_STATUS_IS_OK(status)) {
3734 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3735 nt_errstr(status)));
3736 errcode = W_ERROR_V(ntstatus_to_werror(status));
3740 status = rpccli_srvsvc_NetSrvGetInfo(cli, mem_ctx,
3745 if (!NT_STATUS_IS_OK(status)) {
3746 errcode = W_ERROR_V(ntstatus_to_werror(status));
3749 if (!W_ERROR_IS_OK(werr)) {
3750 errcode = W_ERROR_V(werr);
3754 if (info.info101 == NULL) {
3755 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3760 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3761 STR_ASCII|STR_UPPER|STR_TERMINATE);
3765 SCVAL(p,0,info.info101->version_major);
3766 SCVAL(p,1,info.info101->version_minor);
3767 SIVAL(p,2,info.info101->server_type);
3769 if (mdrcnt == struct_len) {
3772 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3773 if (mdrcnt - struct_len <= 0) {
3777 info.info101->comment,
3778 MIN(mdrcnt - struct_len,
3779 MAX_SERVER_STRING_LENGTH),
3781 p2 = skip_string(*rdata,*rdata_len,p2);
3789 return False; /* not yet implemented */
3792 errcode = NERR_Success;
3796 *rdata_len = PTR_DIFF(p2,*rdata);
3799 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3803 SSVAL(*rparam,0,errcode);
3804 SSVAL(*rparam,2,0); /* converter word */
3805 SSVAL(*rparam,4,*rdata_len);
3810 /****************************************************************************
3811 Get info about the server.
3812 ****************************************************************************/
3814 static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
3815 connection_struct *conn,uint16 vuid,
3816 char *param, int tpscnt,
3817 char *data, int tdscnt,
3818 int mdrcnt,int mprcnt,
3819 char **rdata,char **rparam,
3820 int *rdata_len,int *rparam_len)
3822 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3823 char *str2 = skip_string(param,tpscnt,str1);
3824 char *p = skip_string(param,tpscnt,str2);
3827 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3829 if (!str1 || !str2 || !p) {
3833 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3836 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3841 /* check it's a supported varient */
3842 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3846 *rdata_len = mdrcnt + 1024;
3847 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3852 SSVAL(*rparam,0,NERR_Success);
3853 SSVAL(*rparam,2,0); /* converter word */
3856 endp = *rdata + *rdata_len;
3858 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3863 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3864 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3866 p2 = skip_string(*rdata,*rdata_len,p2);
3872 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3873 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3874 p2 = skip_string(*rdata,*rdata_len,p2);
3880 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3881 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3883 p2 = skip_string(*rdata,*rdata_len,p2);
3889 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3890 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3893 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3894 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3895 p2 = skip_string(*rdata,*rdata_len,p2);
3901 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3902 strlcpy(p2,"",PTR_DIFF(endp,p2));
3903 p2 = skip_string(*rdata,*rdata_len,p2);
3909 *rdata_len = PTR_DIFF(p2,*rdata);
3911 SSVAL(*rparam,4,*rdata_len);
3916 /****************************************************************************
3917 get info about a user
3919 struct user_info_11 {
3920 char usri11_name[21]; 0-20
3922 char *usri11_comment; 22-25
3923 char *usri11_usr_comment; 26-29
3924 unsigned short usri11_priv; 30-31
3925 unsigned long usri11_auth_flags; 32-35
3926 long usri11_password_age; 36-39
3927 char *usri11_homedir; 40-43
3928 char *usri11_parms; 44-47
3929 long usri11_last_logon; 48-51
3930 long usri11_last_logoff; 52-55
3931 unsigned short usri11_bad_pw_count; 56-57
3932 unsigned short usri11_num_logons; 58-59
3933 char *usri11_logon_server; 60-63
3934 unsigned short usri11_country_code; 64-65
3935 char *usri11_workstations; 66-69
3936 unsigned long usri11_max_storage; 70-73
3937 unsigned short usri11_units_per_week; 74-75
3938 unsigned char *usri11_logon_hours; 76-79
3939 unsigned short usri11_code_page; 80-81
3944 usri11_name specifies the user name for which information is retrieved
3946 usri11_pad aligns the next data structure element to a word boundary
3948 usri11_comment is a null terminated ASCII comment
3950 usri11_user_comment is a null terminated ASCII comment about the user
3952 usri11_priv specifies the level of the privilege assigned to the user.
3953 The possible values are:
3955 Name Value Description
3956 USER_PRIV_GUEST 0 Guest privilege
3957 USER_PRIV_USER 1 User privilege
3958 USER_PRV_ADMIN 2 Administrator privilege
3960 usri11_auth_flags specifies the account operator privileges. The
3961 possible values are:
3963 Name Value Description
3964 AF_OP_PRINT 0 Print operator
3967 Leach, Naik [Page 28]
3971 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3974 AF_OP_COMM 1 Communications operator
3975 AF_OP_SERVER 2 Server operator
3976 AF_OP_ACCOUNTS 3 Accounts operator
3979 usri11_password_age specifies how many seconds have elapsed since the
3980 password was last changed.
3982 usri11_home_dir points to a null terminated ASCII string that contains
3983 the path name of the user's home directory.
3985 usri11_parms points to a null terminated ASCII string that is set
3986 aside for use by applications.
3988 usri11_last_logon specifies the time when the user last logged on.
3989 This value is stored as the number of seconds elapsed since
3990 00:00:00, January 1, 1970.
3992 usri11_last_logoff specifies the time when the user last logged off.
3993 This value is stored as the number of seconds elapsed since
3994 00:00:00, January 1, 1970. A value of 0 means the last logoff
3997 usri11_bad_pw_count specifies the number of incorrect passwords
3998 entered since the last successful logon.
4000 usri11_log1_num_logons specifies the number of times this user has
4001 logged on. A value of -1 means the number of logons is unknown.
4003 usri11_logon_server points to a null terminated ASCII string that
4004 contains the name of the server to which logon requests are sent.
4005 A null string indicates logon requests should be sent to the
4008 usri11_country_code specifies the country code for the user's language
4011 usri11_workstations points to a null terminated ASCII string that
4012 contains the names of workstations the user may log on from.
4013 There may be up to 8 workstations, with the names separated by
4014 commas. A null strings indicates there are no restrictions.
4016 usri11_max_storage specifies the maximum amount of disk space the user
4017 can occupy. A value of 0xffffffff indicates there are no
4020 usri11_units_per_week specifies the equal number of time units into
4021 which a week is divided. This value must be equal to 168.
4023 usri11_logon_hours points to a 21 byte (168 bits) string that
4024 specifies the time during which the user can log on. Each bit
4025 represents one unique hour in a week. The first bit (bit 0, word
4026 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4030 Leach, Naik [Page 29]
4034 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4037 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4038 are no restrictions.
4040 usri11_code_page specifies the code page for the user's language of
4043 All of the pointers in this data structure need to be treated
4044 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4045 to be ignored. The converter word returned in the parameters section
4046 needs to be subtracted from the lower 16 bits to calculate an offset
4047 into the return buffer where this ASCII string resides.
4049 There is no auxiliary data in the response.
4051 ****************************************************************************/
4053 #define usri11_name 0
4054 #define usri11_pad 21
4055 #define usri11_comment 22
4056 #define usri11_usr_comment 26
4057 #define usri11_full_name 30
4058 #define usri11_priv 34
4059 #define usri11_auth_flags 36
4060 #define usri11_password_age 40
4061 #define usri11_homedir 44
4062 #define usri11_parms 48
4063 #define usri11_last_logon 52
4064 #define usri11_last_logoff 56
4065 #define usri11_bad_pw_count 60
4066 #define usri11_num_logons 62
4067 #define usri11_logon_server 64
4068 #define usri11_country_code 68
4069 #define usri11_workstations 70
4070 #define usri11_max_storage 74
4071 #define usri11_units_per_week 78
4072 #define usri11_logon_hours 80
4073 #define usri11_code_page 84
4074 #define usri11_end 86
4076 static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
4077 connection_struct *conn, uint16 vuid,
4078 char *param, int tpscnt,
4079 char *data, int tdscnt,
4080 int mdrcnt,int mprcnt,
4081 char **rdata,char **rparam,
4082 int *rdata_len,int *rparam_len)
4084 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4085 char *str2 = skip_string(param,tpscnt,str1);
4086 char *UserName = skip_string(param,tpscnt,str2);
4087 char *p = skip_string(param,tpscnt,UserName);
4088 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4091 const char *level_string;
4093 TALLOC_CTX *mem_ctx = talloc_tos();
4095 struct rpc_pipe_client *cli = NULL;
4096 struct policy_handle connect_handle, domain_handle, user_handle;
4097 struct lsa_String domain_name;
4098 struct dom_sid2 *domain_sid;
4099 struct lsa_String names;
4100 struct samr_Ids rids;
4101 struct samr_Ids types;
4102 int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
4104 union samr_UserInfo *info;
4106 if (!str1 || !str2 || !UserName || !p) {
4111 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4116 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4118 /* check it's a supported variant */
4119 if (strcmp(str1,"zWrLh") != 0) {
4123 case 0: level_string = "B21"; break;
4124 case 1: level_string = "B21BB16DWzzWz"; break;
4125 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4126 case 10: level_string = "B21Bzzz"; break;
4127 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4128 default: return False;
4131 if (strcmp(level_string,str2) != 0) {
4135 *rdata_len = mdrcnt + 1024;
4136 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4142 endp = *rdata + *rdata_len;
4143 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4148 ZERO_STRUCT(connect_handle);
4149 ZERO_STRUCT(domain_handle);
4150 ZERO_STRUCT(user_handle);
4152 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
4154 &conn->sconn->client_id,
4155 conn->sconn->msg_ctx,
4157 if (!NT_STATUS_IS_OK(status)) {
4158 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4159 nt_errstr(status)));
4160 errcode = W_ERROR_V(ntstatus_to_werror(status));
4164 status = rpccli_samr_Connect2(cli, mem_ctx,
4166 SAMR_ACCESS_CONNECT_TO_SERVER |
4167 SAMR_ACCESS_ENUM_DOMAINS |
4168 SAMR_ACCESS_LOOKUP_DOMAIN,
4170 if (!NT_STATUS_IS_OK(status)) {
4171 errcode = W_ERROR_V(ntstatus_to_werror(status));
4175 init_lsa_String(&domain_name, get_global_sam_name());
4177 status = rpccli_samr_LookupDomain(cli, mem_ctx,
4181 if (!NT_STATUS_IS_OK(status)) {
4182 errcode = W_ERROR_V(ntstatus_to_werror(status));
4186 status = rpccli_samr_OpenDomain(cli, mem_ctx,
4188 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
4191 if (!NT_STATUS_IS_OK(status)) {
4192 errcode = W_ERROR_V(ntstatus_to_werror(status));
4196 init_lsa_String(&names, UserName);
4198 status = rpccli_samr_LookupNames(cli, mem_ctx,
4204 if (!NT_STATUS_IS_OK(status)) {
4205 errcode = W_ERROR_V(ntstatus_to_werror(status));
4209 if (rids.count != 1) {
4210 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
4213 if (rids.count != types.count) {
4214 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4217 if (types.ids[0] != SID_NAME_USER) {
4218 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4224 status = rpccli_samr_OpenUser(cli, mem_ctx,
4226 SAMR_USER_ACCESS_GET_LOCALE |
4227 SAMR_USER_ACCESS_GET_LOGONINFO |
4228 SAMR_USER_ACCESS_GET_ATTRIBUTES |
4229 SAMR_USER_ACCESS_GET_GROUPS |
4230 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
4231 SEC_STD_READ_CONTROL,
4234 if (!NT_STATUS_IS_OK(status)) {
4235 errcode = W_ERROR_V(ntstatus_to_werror(status));
4239 status = rpccli_samr_QueryUserInfo2(cli, mem_ctx,
4243 if (!NT_STATUS_IS_OK(status)) {
4244 errcode = W_ERROR_V(ntstatus_to_werror(status));
4249 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4252 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4257 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4258 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4259 p2 = skip_string(*rdata,*rdata_len,p2);
4264 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4265 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4266 p2 = skip_string(*rdata,*rdata_len,p2);
4271 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4272 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4273 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4274 p2 = skip_string(*rdata,*rdata_len,p2);
4281 const char *homedir = info->info21.home_directory.string;
4282 /* modelled after NTAS 3.51 reply */
4283 SSVAL(p,usri11_priv,
4284 (get_current_uid(conn) == sec_initial_uid())?
4285 USER_PRIV_ADMIN:USER_PRIV_USER);
4286 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4287 SIVALS(p,usri11_password_age,-1); /* password age */
4288 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4289 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4290 p2 = skip_string(*rdata,*rdata_len,p2);
4294 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4295 strlcpy(p2,"",PTR_DIFF(endp,p2));
4296 p2 = skip_string(*rdata,*rdata_len,p2);
4300 SIVAL(p,usri11_last_logon,0); /* last logon */
4301 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4302 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4303 SSVALS(p,usri11_num_logons,-1); /* num logons */
4304 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4305 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4306 p2 = skip_string(*rdata,*rdata_len,p2);
4310 SSVAL(p,usri11_country_code,0); /* country code */
4312 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4313 strlcpy(p2,"",PTR_DIFF(endp,p2));
4314 p2 = skip_string(*rdata,*rdata_len,p2);
4319 SIVALS(p,usri11_max_storage,-1); /* max storage */
4320 SSVAL(p,usri11_units_per_week,168); /* units per week */
4321 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4323 /* a simple way to get logon hours at all times. */
4325 SCVAL(p2,21,0); /* fix zero termination */
4326 p2 = skip_string(*rdata,*rdata_len,p2);
4331 SSVAL(p,usri11_code_page,0); /* code page */
4334 if (uLevel == 1 || uLevel == 2) {
4335 memset(p+22,' ',16); /* password */
4336 SIVALS(p,38,-1); /* password age */
4338 (get_current_uid(conn) == sec_initial_uid())?
4339 USER_PRIV_ADMIN:USER_PRIV_USER);
4340 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4341 strlcpy(p2, info->info21.home_directory.string,
4343 p2 = skip_string(*rdata,*rdata_len,p2);
4347 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4349 SSVAL(p,52,0); /* flags */
4350 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4351 strlcpy(p2, info->info21.logon_script.string,
4353 p2 = skip_string(*rdata,*rdata_len,p2);
4358 SIVAL(p,58,0); /* auth_flags */
4359 SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
4360 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4361 p2 = skip_string(*rdata,*rdata_len,p2);
4365 SIVAL(p,66,0); /* urs_comment */
4366 SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
4367 strlcpy(p2,"",PTR_DIFF(endp,p2));
4368 p2 = skip_string(*rdata,*rdata_len,p2);
4372 SIVAL(p,74,0); /* workstations */
4373 SIVAL(p,78,0); /* last_logon */
4374 SIVAL(p,82,0); /* last_logoff */
4375 SIVALS(p,86,-1); /* acct_expires */
4376 SIVALS(p,90,-1); /* max_storage */
4377 SSVAL(p,94,168); /* units_per_week */
4378 SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
4381 SSVALS(p,100,-1); /* bad_pw_count */
4382 SSVALS(p,102,-1); /* num_logons */
4383 SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
4385 TALLOC_CTX *ctx = talloc_tos();
4386 int space_rem = *rdata_len - (p2 - *rdata);
4389 if (space_rem <= 0) {
4392 tmp = talloc_strdup(ctx, "\\\\%L");
4396 tmp = talloc_sub_basic(ctx,
4409 p2 = skip_string(*rdata,*rdata_len,p2);
4413 SSVAL(p,108,49); /* country_code */
4414 SSVAL(p,110,860); /* code page */
4418 errcode = NERR_Success;
4421 *rdata_len = PTR_DIFF(p2,*rdata);
4423 if (cli && is_valid_policy_hnd(&user_handle)) {
4424 rpccli_samr_Close(cli, mem_ctx, &user_handle);
4426 if (cli && is_valid_policy_hnd(&domain_handle)) {
4427 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
4429 if (cli && is_valid_policy_hnd(&connect_handle)) {
4430 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
4433 SSVAL(*rparam,0,errcode);
4434 SSVAL(*rparam,2,0); /* converter word */
4435 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4440 static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
4441 connection_struct *conn,uint16 vuid,
4442 char *param, int tpscnt,
4443 char *data, int tdscnt,
4444 int mdrcnt,int mprcnt,
4445 char **rdata,char **rparam,
4446 int *rdata_len,int *rparam_len)
4448 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4449 char *str2 = skip_string(param,tpscnt,str1);
4450 char *p = skip_string(param,tpscnt,str2);
4452 struct pack_desc desc;
4454 /* With share level security vuid will always be zero.
4455 Don't depend on vuser being non-null !!. JRA */
4456 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4458 if (!str1 || !str2 || !p) {
4463 DEBUG(3,(" Username of UID %d is %s\n",
4464 (int)vuser->server_info->utok.uid,
4465 vuser->server_info->unix_name));
4468 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4469 name = get_safe_str_ptr(param,tpscnt,p,2);
4474 memset((char *)&desc,'\0',sizeof(desc));
4476 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4478 /* check it's a supported varient */
4479 if (strcmp(str1,"OOWb54WrLh") != 0) {
4482 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4486 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4493 desc.buflen = mdrcnt;
4494 desc.subformat = NULL;
4497 if (init_package(&desc,1,0)) {
4498 PACKI(&desc,"W",0); /* code */
4499 PACKS(&desc,"B21",name); /* eff. name */
4500 PACKS(&desc,"B",""); /* pad */
4502 (get_current_uid(conn) == sec_initial_uid())?
4503 USER_PRIV_ADMIN:USER_PRIV_USER);
4504 PACKI(&desc,"D",0); /* auth flags XXX */
4505 PACKI(&desc,"W",0); /* num logons */
4506 PACKI(&desc,"W",0); /* bad pw count */
4507 PACKI(&desc,"D",0); /* last logon */
4508 PACKI(&desc,"D",-1); /* last logoff */
4509 PACKI(&desc,"D",-1); /* logoff time */
4510 PACKI(&desc,"D",-1); /* kickoff time */
4511 PACKI(&desc,"D",0); /* password age */
4512 PACKI(&desc,"D",0); /* password can change */
4513 PACKI(&desc,"D",-1); /* password must change */
4517 fstrcpy(mypath,"\\\\");
4518 fstrcat(mypath,get_local_machine_name());
4520 PACKS(&desc,"z",mypath); /* computer */
4523 PACKS(&desc,"z",lp_workgroup());/* domain */
4524 PACKS(&desc,"z", vuser ?
4525 vuser->server_info->info3->base.logon_script.string
4526 : ""); /* script path */
4527 PACKI(&desc,"D",0x00000000); /* reserved */
4530 *rdata_len = desc.usedlen;
4532 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4536 SSVALS(*rparam,0,desc.errcode);
4538 SSVAL(*rparam,4,desc.neededlen);
4540 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4545 /****************************************************************************
4546 api_WAccessGetUserPerms
4547 ****************************************************************************/
4549 static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
4550 connection_struct *conn,uint16 vuid,
4551 char *param, int tpscnt,
4552 char *data, int tdscnt,
4553 int mdrcnt,int mprcnt,
4554 char **rdata,char **rparam,
4555 int *rdata_len,int *rparam_len)
4557 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4558 char *str2 = skip_string(param,tpscnt,str1);
4559 char *user = skip_string(param,tpscnt,str2);
4560 char *resource = skip_string(param,tpscnt,user);
4562 if (!str1 || !str2 || !user || !resource) {
4566 if (skip_string(param,tpscnt,resource) == NULL) {
4569 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4571 /* check it's a supported varient */
4572 if (strcmp(str1,"zzh") != 0) {
4575 if (strcmp(str2,"") != 0) {
4580 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4584 SSVALS(*rparam,0,0); /* errorcode */
4585 SSVAL(*rparam,2,0); /* converter word */
4586 SSVAL(*rparam,4,0x7f); /* permission flags */
4591 /****************************************************************************
4592 api_WPrintJobEnumerate
4593 ****************************************************************************/
4595 static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
4596 connection_struct *conn, uint16 vuid,
4597 char *param, int tpscnt,
4598 char *data, int tdscnt,
4599 int mdrcnt,int mprcnt,
4600 char **rdata,char **rparam,
4601 int *rdata_len,int *rparam_len)
4603 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4604 char *str2 = skip_string(param,tpscnt,str1);
4605 char *p = skip_string(param,tpscnt,str2);
4609 struct pack_desc desc;
4612 TALLOC_CTX *mem_ctx = talloc_tos();
4615 struct rpc_pipe_client *cli = NULL;
4616 struct policy_handle handle;
4617 struct spoolss_DevmodeContainer devmode_ctr;
4618 union spoolss_JobInfo info;
4620 if (!str1 || !str2 || !p) {
4624 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4626 memset((char *)&desc,'\0',sizeof(desc));
4627 memset((char *)&status,'\0',sizeof(status));
4629 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4631 /* check it's a supported varient */
4632 if (strcmp(str1,"WWrLh") != 0) {
4635 if (!check_printjob_info(&desc,uLevel,str2)) {
4639 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4643 ZERO_STRUCT(handle);
4645 status = rpc_pipe_open_interface(conn,
4646 &ndr_table_spoolss.syntax_id,
4648 &conn->sconn->client_id,
4649 conn->sconn->msg_ctx,
4651 if (!NT_STATUS_IS_OK(status)) {
4652 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4653 nt_errstr(status)));
4654 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4658 ZERO_STRUCT(devmode_ctr);
4660 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4667 if (!NT_STATUS_IS_OK(status)) {
4668 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4671 if (!W_ERROR_IS_OK(werr)) {
4672 desc.errcode = W_ERROR_V(werr);
4676 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4682 if (!W_ERROR_IS_OK(werr)) {
4683 desc.errcode = W_ERROR_V(werr);
4688 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4693 desc.buflen = mdrcnt;
4696 * Don't return data but need to get correct length
4697 * init_package will return wrong size if buflen=0
4699 desc.buflen = getlen(desc.format);
4700 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4703 if (init_package(&desc,1,0)) {
4704 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4705 *rdata_len = desc.usedlen;
4707 desc.errcode = NERR_JobNotFound;
4711 if (cli && is_valid_policy_hnd(&handle)) {
4712 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4716 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4720 SSVALS(*rparam,0,desc.errcode);
4722 SSVAL(*rparam,4,desc.neededlen);
4726 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4731 static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
4732 connection_struct *conn, uint16 vuid,
4733 char *param, int tpscnt,
4734 char *data, int tdscnt,
4735 int mdrcnt,int mprcnt,
4736 char **rdata,char **rparam,
4737 int *rdata_len,int *rparam_len)
4739 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4740 char *str2 = skip_string(param,tpscnt,str1);
4741 char *p = skip_string(param,tpscnt,str2);
4745 struct pack_desc desc;
4747 TALLOC_CTX *mem_ctx = talloc_tos();
4750 struct rpc_pipe_client *cli = NULL;
4751 struct policy_handle handle;
4752 struct spoolss_DevmodeContainer devmode_ctr;
4754 union spoolss_JobInfo *info;
4756 if (!str1 || !str2 || !p) {
4760 memset((char *)&desc,'\0',sizeof(desc));
4762 p = skip_string(param,tpscnt,p);
4766 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4768 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4770 /* check it's a supported variant */
4771 if (strcmp(str1,"zWrLeh") != 0) {
4776 return False; /* defined only for uLevel 0,1,2 */
4779 if (!check_printjob_info(&desc,uLevel,str2)) {
4783 ZERO_STRUCT(handle);
4785 status = rpc_pipe_open_interface(conn,
4786 &ndr_table_spoolss.syntax_id,
4788 &conn->sconn->client_id,
4789 conn->sconn->msg_ctx,
4791 if (!NT_STATUS_IS_OK(status)) {
4792 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4793 nt_errstr(status)));
4794 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4798 ZERO_STRUCT(devmode_ctr);
4800 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4804 SEC_FLAG_MAXIMUM_ALLOWED,
4807 if (!NT_STATUS_IS_OK(status)) {
4808 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4811 if (!W_ERROR_IS_OK(werr)) {
4812 desc.errcode = W_ERROR_V(werr);
4816 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4824 if (!W_ERROR_IS_OK(werr)) {
4825 desc.errcode = W_ERROR_V(werr);
4830 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4836 desc.buflen = mdrcnt;
4838 if (init_package(&desc,count,0)) {
4840 for (i = 0; i < count; i++) {
4841 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4842 if (desc.errcode == NERR_Success) {
4848 if (cli && is_valid_policy_hnd(&handle)) {
4849 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4852 *rdata_len = desc.usedlen;
4855 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4859 SSVALS(*rparam,0,desc.errcode);
4861 SSVAL(*rparam,4,succnt);
4862 SSVAL(*rparam,6,count);
4864 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4869 static int check_printdest_info(struct pack_desc* desc,
4870 int uLevel, char* id)
4872 desc->subformat = NULL;
4875 desc->format = "B9";
4878 desc->format = "B9B21WWzW";
4884 desc->format = "zzzWWzzzWW";
4887 DEBUG(0,("check_printdest_info: invalid level %d\n",
4891 if (id == NULL || strcmp(desc->format,id) != 0) {
4892 DEBUG(0,("check_printdest_info: invalid string %s\n",
4893 id ? id : "<NULL>" ));
4899 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
4900 struct pack_desc* desc)
4904 strncpy(buf, info2->printername, sizeof(buf)-1);
4905 buf[sizeof(buf)-1] = 0;
4909 PACKS(desc,"B9",buf); /* szName */
4911 PACKS(desc,"B21",""); /* szUserName */
4912 PACKI(desc,"W",0); /* uJobId */
4913 PACKI(desc,"W",0); /* fsStatus */
4914 PACKS(desc,"z",""); /* pszStatus */
4915 PACKI(desc,"W",0); /* time */
4919 if (uLevel == 2 || uLevel == 3) {
4920 PACKS(desc,"z",buf); /* pszPrinterName */
4922 PACKS(desc,"z",""); /* pszUserName */
4923 PACKS(desc,"z",""); /* pszLogAddr */
4924 PACKI(desc,"W",0); /* uJobId */
4925 PACKI(desc,"W",0); /* fsStatus */
4926 PACKS(desc,"z",""); /* pszStatus */
4927 PACKS(desc,"z",""); /* pszComment */
4928 PACKS(desc,"z","NULL"); /* pszDrivers */
4929 PACKI(desc,"W",0); /* time */
4930 PACKI(desc,"W",0); /* pad1 */
4935 static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
4936 connection_struct *conn, uint16 vuid,
4937 char *param, int tpscnt,
4938 char *data, int tdscnt,
4939 int mdrcnt,int mprcnt,
4940 char **rdata,char **rparam,
4941 int *rdata_len,int *rparam_len)
4943 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4944 char *str2 = skip_string(param,tpscnt,str1);
4945 char *p = skip_string(param,tpscnt,str2);
4946 char* PrinterName = p;
4948 struct pack_desc desc;
4951 TALLOC_CTX *mem_ctx = talloc_tos();
4954 struct rpc_pipe_client *cli = NULL;
4955 struct policy_handle handle;
4956 struct spoolss_DevmodeContainer devmode_ctr;
4957 union spoolss_PrinterInfo info;
4959 if (!str1 || !str2 || !p) {
4963 memset((char *)&desc,'\0',sizeof(desc));
4965 p = skip_string(param,tpscnt,p);
4969 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4971 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4973 /* check it's a supported varient */
4974 if (strcmp(str1,"zWrLh") != 0) {
4977 if (!check_printdest_info(&desc,uLevel,str2)) {
4981 ZERO_STRUCT(handle);
4983 status = rpc_pipe_open_interface(conn,
4984 &ndr_table_spoolss.syntax_id,
4986 &conn->sconn->client_id,
4987 conn->sconn->msg_ctx,
4989 if (!NT_STATUS_IS_OK(status)) {
4990 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4991 nt_errstr(status)));
4992 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4996 ZERO_STRUCT(devmode_ctr);
4998 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5002 SEC_FLAG_MAXIMUM_ALLOWED,
5005 if (!NT_STATUS_IS_OK(status)) {
5007 desc.errcode = NERR_DestNotFound;
5011 if (!W_ERROR_IS_OK(werr)) {
5013 desc.errcode = NERR_DestNotFound;
5018 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
5023 if (!W_ERROR_IS_OK(werr)) {
5025 desc.errcode = NERR_DestNotFound;
5031 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5036 desc.buflen = mdrcnt;
5039 * Don't return data but need to get correct length
5040 * init_package will return wrong size if buflen=0
5042 desc.buflen = getlen(desc.format);
5043 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
5045 if (init_package(&desc,1,0)) {
5046 fill_printdest_info(&info.info2, uLevel,&desc);
5050 if (cli && is_valid_policy_hnd(&handle)) {
5051 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5054 *rdata_len = desc.usedlen;
5057 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5061 SSVALS(*rparam,0,desc.errcode);
5063 SSVAL(*rparam,4,desc.neededlen);
5065 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
5071 static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
5072 connection_struct *conn, uint16 vuid,
5073 char *param, int tpscnt,
5074 char *data, int tdscnt,
5075 int mdrcnt,int mprcnt,
5076 char **rdata,char **rparam,
5077 int *rdata_len,int *rparam_len)
5079 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5080 char *str2 = skip_string(param,tpscnt,str1);
5081 char *p = skip_string(param,tpscnt,str2);
5085 struct pack_desc desc;
5087 TALLOC_CTX *mem_ctx = talloc_tos();
5090 struct rpc_pipe_client *cli = NULL;
5091 union spoolss_PrinterInfo *info;
5094 if (!str1 || !str2 || !p) {
5098 memset((char *)&desc,'\0',sizeof(desc));
5100 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5102 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
5104 /* check it's a supported varient */
5105 if (strcmp(str1,"WrLeh") != 0) {
5108 if (!check_printdest_info(&desc,uLevel,str2)) {
5114 status = rpc_pipe_open_interface(conn,
5115 &ndr_table_spoolss.syntax_id,
5117 &conn->sconn->client_id,
5118 conn->sconn->msg_ctx,
5120 if (!NT_STATUS_IS_OK(status)) {
5121 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5122 nt_errstr(status)));
5123 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5127 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
5129 cli->srv_name_slash,
5134 if (!W_ERROR_IS_OK(werr)) {
5135 desc.errcode = W_ERROR_V(werr);
5137 desc.errcode = NERR_DestNotFound;
5145 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5152 desc.buflen = mdrcnt;
5153 if (init_package(&desc,queuecnt,0)) {
5156 for (i = 0; i < count; i++) {
5157 fill_printdest_info(&info[i].info2, uLevel,&desc);
5159 if (desc.errcode == NERR_Success) {
5165 *rdata_len = desc.usedlen;
5168 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5172 SSVALS(*rparam,0,desc.errcode);
5174 SSVAL(*rparam,4,succnt);
5175 SSVAL(*rparam,6,queuecnt);
5177 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
5182 static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
5183 connection_struct *conn, uint16 vuid,
5184 char *param, int tpscnt,
5185 char *data, int tdscnt,
5186 int mdrcnt,int mprcnt,
5187 char **rdata,char **rparam,
5188 int *rdata_len,int *rparam_len)
5190 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5191 char *str2 = skip_string(param,tpscnt,str1);
5192 char *p = skip_string(param,tpscnt,str2);
5195 struct pack_desc desc;
5197 if (!str1 || !str2 || !p) {
5201 memset((char *)&desc,'\0',sizeof(desc));
5203 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5205 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5207 /* check it's a supported varient */
5208 if (strcmp(str1,"WrLeh") != 0) {
5211 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5216 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5222 desc.buflen = mdrcnt;
5223 if (init_package(&desc,1,0)) {
5224 PACKS(&desc,"B41","NULL");
5227 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5229 *rdata_len = desc.usedlen;
5232 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5236 SSVALS(*rparam,0,desc.errcode);
5238 SSVAL(*rparam,4,succnt);
5241 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5246 static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
5247 connection_struct *conn, uint16 vuid,
5248 char *param, int tpscnt,
5249 char *data, int tdscnt,
5250 int mdrcnt,int mprcnt,
5251 char **rdata,char **rparam,
5252 int *rdata_len,int *rparam_len)
5254 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5255 char *str2 = skip_string(param,tpscnt,str1);
5256 char *p = skip_string(param,tpscnt,str2);
5259 struct pack_desc desc;
5261 if (!str1 || !str2 || !p) {
5264 memset((char *)&desc,'\0',sizeof(desc));
5266 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5268 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5270 /* check it's a supported varient */
5271 if (strcmp(str1,"WrLeh") != 0) {
5274 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5279 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5285 desc.buflen = mdrcnt;
5287 if (init_package(&desc,1,0)) {
5288 PACKS(&desc,"B13","lpd");
5291 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5293 *rdata_len = desc.usedlen;
5296 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5300 SSVALS(*rparam,0,desc.errcode);
5302 SSVAL(*rparam,4,succnt);
5305 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5310 static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
5311 connection_struct *conn, uint16 vuid,
5312 char *param, int tpscnt,
5313 char *data, int tdscnt,
5314 int mdrcnt,int mprcnt,
5315 char **rdata,char **rparam,
5316 int *rdata_len,int *rparam_len)
5318 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5319 char *str2 = skip_string(param,tpscnt,str1);
5320 char *p = skip_string(param,tpscnt,str2);
5323 struct pack_desc desc;
5325 if (!str1 || !str2 || !p) {
5329 memset((char *)&desc,'\0',sizeof(desc));
5331 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5333 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5335 /* check it's a supported varient */
5336 if (strcmp(str1,"WrLeh") != 0) {
5339 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5344 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5349 memset((char *)&desc,'\0',sizeof(desc));
5351 desc.buflen = mdrcnt;
5353 if (init_package(&desc,1,0)) {
5354 PACKS(&desc,"B13","lp0");
5357 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5359 *rdata_len = desc.usedlen;
5362 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5366 SSVALS(*rparam,0,desc.errcode);
5368 SSVAL(*rparam,4,succnt);
5371 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5376 /****************************************************************************
5378 ****************************************************************************/
5380 static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
5381 connection_struct *conn, uint16 vuid,
5382 char *param, int tpscnt,
5383 char *data, int tdscnt,
5384 int mdrcnt,int mprcnt,
5385 char **rdata,char **rparam,
5386 int *rdata_len,int *rparam_len)
5389 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5390 char *str2 = skip_string(param,tpscnt,str1);
5391 char *p = skip_string(param,tpscnt,str2);
5393 struct pack_desc desc;
5394 struct sessionid *session_list;
5395 int i, num_sessions;
5397 if (!str1 || !str2 || !p) {
5401 memset((char *)&desc,'\0',sizeof(desc));
5403 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5405 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5406 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5407 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5409 /* check it's a supported varient */
5410 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5413 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5417 num_sessions = list_sessions(talloc_tos(), &session_list);
5420 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5425 memset((char *)&desc,'\0',sizeof(desc));
5427 desc.buflen = mdrcnt;
5429 if (!init_package(&desc,num_sessions,0)) {
5433 for(i=0; i<num_sessions; i++) {
5434 PACKS(&desc, "z", session_list[i].remote_machine);
5435 PACKS(&desc, "z", session_list[i].username);
5436 PACKI(&desc, "W", 1); /* num conns */
5437 PACKI(&desc, "W", 0); /* num opens */
5438 PACKI(&desc, "W", 1); /* num users */
5439 PACKI(&desc, "D", 0); /* session time */
5440 PACKI(&desc, "D", 0); /* idle time */
5441 PACKI(&desc, "D", 0); /* flags */
5442 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5445 *rdata_len = desc.usedlen;
5448 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5452 SSVALS(*rparam,0,desc.errcode);
5453 SSVAL(*rparam,2,0); /* converter */
5454 SSVAL(*rparam,4,num_sessions); /* count */
5456 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5462 /****************************************************************************
5463 The buffer was too small.
5464 ****************************************************************************/
5466 static bool api_TooSmall(struct smbd_server_connection *sconn,
5467 connection_struct *conn,uint16 vuid, char *param, char *data,
5468 int mdrcnt, int mprcnt,
5469 char **rdata, char **rparam,
5470 int *rdata_len, int *rparam_len)
5472 *rparam_len = MIN(*rparam_len,mprcnt);
5473 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5480 SSVAL(*rparam,0,NERR_BufTooSmall);
5482 DEBUG(3,("Supplied buffer too small in API command\n"));
5487 /****************************************************************************
5488 The request is not supported.
5489 ****************************************************************************/
5491 static bool api_Unsupported(struct smbd_server_connection *sconn,
5492 connection_struct *conn, uint16 vuid,
5493 char *param, int tpscnt,
5494 char *data, int tdscnt,
5495 int mdrcnt, int mprcnt,
5496 char **rdata, char **rparam,
5497 int *rdata_len, int *rparam_len)
5500 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5507 SSVAL(*rparam,0,NERR_notsupported);
5508 SSVAL(*rparam,2,0); /* converter word */
5510 DEBUG(3,("Unsupported API command\n"));
5515 static const struct {
5518 bool (*fn)(struct smbd_server_connection *sconn,
5519 connection_struct *, uint16,
5522 int,int,char **,char **,int *,int *);
5523 bool auth_user; /* Deny anonymous access? */
5524 } api_commands[] = {
5525 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5526 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5527 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5528 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5529 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5530 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5531 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5532 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5533 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5534 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5535 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5536 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5537 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5538 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5539 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5540 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5541 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5542 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5543 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5544 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5545 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5546 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5547 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5548 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5549 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5550 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5551 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5552 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5553 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5554 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5555 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5556 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5557 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5558 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5559 {NULL, -1, api_Unsupported}
5560 /* The following RAP calls are not implemented by Samba:
5562 RAP_WFileEnum2 - anon not OK
5567 /****************************************************************************
5568 Handle remote api calls.
5569 ****************************************************************************/
5571 void api_reply(connection_struct *conn, uint16 vuid,
5572 struct smb_request *req,
5573 char *data, char *params,
5574 int tdscnt, int tpscnt,
5575 int mdrcnt, int mprcnt)
5579 char *rparam = NULL;
5580 const char *name1 = NULL;
5581 const char *name2 = NULL;
5588 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5597 api_command = SVAL(params,0);
5598 /* Is there a string at position params+2 ? */
5599 if (skip_string(params,tpscnt,params+2)) {
5604 name2 = skip_string(params,tpscnt,params+2);
5609 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5613 tdscnt,tpscnt,mdrcnt,mprcnt));
5615 for (i=0;api_commands[i].name;i++) {
5616 if (api_commands[i].id == api_command && api_commands[i].fn) {
5617 DEBUG(3,("Doing %s\n",api_commands[i].name));
5622 /* Check whether this api call can be done anonymously */
5624 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5625 user_struct *user = get_valid_user_struct(req->sconn, vuid);
5627 if (!user || user->server_info->guest) {
5628 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5633 rdata = (char *)SMB_MALLOC(1024);
5635 memset(rdata,'\0',1024);
5638 rparam = (char *)SMB_MALLOC(1024);
5640 memset(rparam,'\0',1024);
5643 if(!rdata || !rparam) {
5644 DEBUG(0,("api_reply: malloc fail !\n"));
5647 reply_nterror(req, NT_STATUS_NO_MEMORY);
5651 reply = api_commands[i].fn(req->sconn, conn,
5653 params,tpscnt, /* params + length */
5654 data,tdscnt, /* data + length */
5656 &rdata,&rparam,&rdata_len,&rparam_len);
5659 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5660 reply = api_TooSmall(req->sconn,conn,vuid,params,data,
5662 &rdata,&rparam,&rdata_len,&rparam_len);
5665 /* if we get False back then it's actually unsupported */
5667 reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
5669 tdscnt,mdrcnt,mprcnt,
5670 &rdata,&rparam,&rdata_len,&rparam_len);
5673 /* If api_Unsupported returns false we can't return anything. */
5675 send_trans_reply(conn, req, rparam, rparam_len,
5676 rdata, rdata_len, False);