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"
46 #define NERR_Success 0
47 #define NERR_badpass 86
48 #define NERR_notsupported 50
50 #define NERR_BASE (2100)
51 #define NERR_BufTooSmall (NERR_BASE+23)
52 #define NERR_JobNotFound (NERR_BASE+51)
53 #define NERR_DestNotFound (NERR_BASE+52)
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
61 /* Limit size of ipc replies */
63 static char *smb_realloc_limit(void *ptr, size_t size)
67 size = MAX((size),4*1024);
68 val = (char *)SMB_REALLOC(ptr,size);
70 memset(val,'\0',size);
75 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
76 char *param, int tpscnt,
77 char *data, int tdscnt,
78 int mdrcnt, int mprcnt,
79 char **rdata, char **rparam,
80 int *rdata_len, int *rparam_len);
82 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
83 int mdrcnt, int mprcnt,
84 char **rdata, char **rparam,
85 int *rdata_len, int *rparam_len);
88 static int CopyExpanded(connection_struct *conn,
89 int snum, char **dst, char *src, int *p_space_remaining)
91 TALLOC_CTX *ctx = talloc_tos();
95 if (!src || !dst || !p_space_remaining || !(*dst) ||
96 *p_space_remaining <= 0) {
100 buf = talloc_strdup(ctx, src);
102 *p_space_remaining = 0;
105 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
107 *p_space_remaining = 0;
110 buf = talloc_sub_advanced(ctx,
111 lp_servicename(SNUM(conn)),
112 conn->server_info->unix_name,
114 conn->server_info->utok.gid,
115 conn->server_info->sanitized_username,
116 pdb_get_domain(conn->server_info->sam_account),
119 *p_space_remaining = 0;
122 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
127 (*p_space_remaining) -= l;
131 static int CopyAndAdvance(char **dst, char *src, int *n)
134 if (!src || !dst || !n || !(*dst)) {
137 l = push_ascii(*dst,src,*n, STR_TERMINATE);
146 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
148 TALLOC_CTX *ctx = talloc_tos();
153 buf = talloc_strdup(ctx,s);
157 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
161 buf = talloc_sub_advanced(ctx,
162 lp_servicename(SNUM(conn)),
163 conn->server_info->unix_name,
165 conn->server_info->utok.gid,
166 conn->server_info->sanitized_username,
167 pdb_get_domain(conn->server_info->sam_account),
172 return strlen(buf) + 1;
175 /*******************************************************************
176 Check a API string for validity when we only need to check the prefix.
177 ******************************************************************/
179 static bool prefix_ok(const char *str, const char *prefix)
181 return(strncmp(str,prefix,strlen(prefix)) == 0);
185 const char *format; /* formatstring for structure */
186 const char *subformat; /* subformat for structure */
187 char *base; /* baseaddress of buffer */
188 int buflen; /* remaining size for fixed part; on init: length of base */
189 int subcount; /* count of substructures */
190 char *structbuf; /* pointer into buffer for remaining fixed part */
191 int stringlen; /* remaining size for variable part */
192 char *stringbuf; /* pointer into buffer for remaining variable part */
193 int neededlen; /* total needed size */
194 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
195 const char *curpos; /* current position; pointer into format or subformat */
199 static int get_counter(const char **p)
205 if (!isdigit((int)**p)) {
211 n = 10 * n + (i - '0');
219 static int getlen(const char *p)
228 case 'W': /* word (2 byte) */
231 case 'K': /* status word? (2 byte) */
234 case 'N': /* count of substructures (word) at end */
237 case 'D': /* double word (4 byte) */
238 case 'z': /* offset to zero terminated string (4 byte) */
239 case 'l': /* offset to user data (4 byte) */
242 case 'b': /* offset to data (with counter) (4 byte) */
246 case 'B': /* byte (with optional counter) */
247 n += get_counter(&p);
254 static bool init_package(struct pack_desc *p, int count, int subcount)
259 if (!p->format || !p->base) {
263 i = count * getlen(p->format);
265 i += subcount * getlen(p->subformat);
267 p->structbuf = p->base;
271 p->curpos = p->format;
277 * This is the old error code we used. Aparently
278 * WinNT/2k systems return ERRbuftoosmall (2123) and
279 * OS/2 needs this. I'm leaving this here so we can revert
282 p->errcode = ERRmoredata;
284 p->errcode = ERRbuftoosmall;
287 p->errcode = NERR_Success;
291 p->stringbuf = p->base + i;
293 return (p->errcode == NERR_Success);
296 static int package(struct pack_desc *p, ...)
299 int needed=0, stringneeded;
300 const char *str=NULL;
301 int is_string=0, stringused;
308 p->curpos = p->format;
310 p->curpos = p->subformat;
315 str = va_arg(args,char*);
316 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
325 switch( *p->curpos++ ) {
326 case 'W': /* word (2 byte) */
328 temp = va_arg(args,int);
329 if (p->buflen >= needed) {
330 SSVAL(p->structbuf,0,temp);
333 case 'K': /* status word? (2 byte) */
335 temp = va_arg(args,int);
336 if (p->buflen >= needed) {
337 SSVAL(p->structbuf,0,temp);
340 case 'N': /* count of substructures (word) at end */
342 p->subcount = va_arg(args,int);
343 if (p->buflen >= needed) {
344 SSVAL(p->structbuf,0,p->subcount);
347 case 'D': /* double word (4 byte) */
349 temp = va_arg(args,int);
350 if (p->buflen >= needed) {
351 SIVAL(p->structbuf,0,temp);
354 case 'B': /* byte (with optional counter) */
355 needed = get_counter(&p->curpos);
357 char *s = va_arg(args,char*);
358 if (p->buflen >= needed) {
359 StrnCpy(p->structbuf,s?s:"",needed-1);
363 case 'z': /* offset to zero terminated string (4 byte) */
364 str = va_arg(args,char*);
365 stringneeded = (str ? strlen(str)+1 : 0);
368 case 'l': /* offset to user data (4 byte) */
369 str = va_arg(args,char*);
370 stringneeded = va_arg(args,int);
373 case 'b': /* offset to data (with counter) (4 byte) */
374 str = va_arg(args,char*);
375 stringneeded = get_counter(&p->curpos);
381 if (stringneeded >= 0) {
383 if (p->buflen >= needed) {
384 stringused = stringneeded;
385 if (stringused > p->stringlen) {
386 stringused = (is_string ? p->stringlen : 0);
387 if (p->errcode == NERR_Success) {
388 p->errcode = ERRmoredata;
392 SIVAL(p->structbuf,0,0);
394 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
395 memcpy(p->stringbuf,str?str:"",stringused);
397 p->stringbuf[stringused-1] = '\0';
399 p->stringbuf += stringused;
400 p->stringlen -= stringused;
401 p->usedlen += stringused;
404 p->neededlen += stringneeded;
407 p->neededlen += needed;
408 if (p->buflen >= needed) {
409 p->structbuf += needed;
411 p->usedlen += needed;
413 if (p->errcode == NERR_Success) {
414 p->errcode = ERRmoredata;
421 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
422 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
424 #define PACK(desc,t,v) package(desc,v)
425 #define PACKl(desc,t,v,l) package(desc,v,l)
428 static void PACKI(struct pack_desc* desc, const char *t,int v)
433 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
438 /****************************************************************************
440 ****************************************************************************/
442 static void PackDriverData(struct pack_desc* desc)
444 char drivdata[4+4+32];
445 SIVAL(drivdata,0,sizeof drivdata); /* cb */
446 SIVAL(drivdata,4,1000); /* lVersion */
447 memset(drivdata+8,0,32); /* szDeviceName */
448 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
449 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
452 static int check_printq_info(struct pack_desc* desc,
453 unsigned int uLevel, char *id1, char *id2)
455 desc->subformat = NULL;
458 desc->format = "B13";
461 desc->format = "B13BWWWzzzzzWW";
464 desc->format = "B13BWWWzzzzzWN";
465 desc->subformat = "WB21BB16B10zWWzDDz";
468 desc->format = "zWWWWzzzzWWzzl";
471 desc->format = "zWWWWzzzzWNzzl";
472 desc->subformat = "WWzWWDDzz";
481 desc->format = "WzzzzzzzzN";
482 desc->subformat = "z";
485 DEBUG(0,("check_printq_info: invalid level %d\n",
489 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
490 DEBUG(0,("check_printq_info: invalid format %s\n",
491 id1 ? id1 : "<NULL>" ));
494 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
495 DEBUG(0,("check_printq_info: invalid subformat %s\n",
496 id2 ? id2 : "<NULL>" ));
503 #define RAP_JOB_STATUS_QUEUED 0
504 #define RAP_JOB_STATUS_PAUSED 1
505 #define RAP_JOB_STATUS_SPOOLING 2
506 #define RAP_JOB_STATUS_PRINTING 3
507 #define RAP_JOB_STATUS_PRINTED 4
509 #define RAP_QUEUE_STATUS_PAUSED 1
510 #define RAP_QUEUE_STATUS_ERROR 2
512 /* turn a print job status into a on the wire status
514 static int printj_spoolss_status(int v)
516 if (v == JOB_STATUS_QUEUED)
517 return RAP_JOB_STATUS_QUEUED;
518 if (v & JOB_STATUS_PAUSED)
519 return RAP_JOB_STATUS_PAUSED;
520 if (v & JOB_STATUS_SPOOLING)
521 return RAP_JOB_STATUS_SPOOLING;
522 if (v & JOB_STATUS_PRINTING)
523 return RAP_JOB_STATUS_PRINTING;
527 /* turn a print queue status into a on the wire status
529 static int printq_spoolss_status(int v)
531 if (v == PRINTER_STATUS_OK)
533 if (v & PRINTER_STATUS_PAUSED)
534 return RAP_QUEUE_STATUS_PAUSED;
535 return RAP_QUEUE_STATUS_ERROR;
538 static void fill_spoolss_printjob_info(int uLevel,
539 struct pack_desc *desc,
540 struct spoolss_JobInfo2 *info2,
543 time_t t = spoolss_Time_to_time_t(&info2->submitted);
545 /* the client expects localtime */
546 t -= get_time_zone(t);
548 PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
550 PACKS(desc,"B21", info2->user_name); /* szUserName */
551 PACKS(desc,"B",""); /* pad */
552 PACKS(desc,"B16",""); /* szNotifyName */
553 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
554 PACKS(desc,"z",""); /* pszParms */
555 PACKI(desc,"W",n+1); /* uPosition */
556 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
557 PACKS(desc,"z",""); /* pszStatus */
558 PACKI(desc,"D", t); /* ulSubmitted */
559 PACKI(desc,"D", info2->size); /* ulSize */
560 PACKS(desc,"z", info2->document_name); /* pszComment */
562 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
563 PACKI(desc,"W", info2->priority); /* uPriority */
564 PACKS(desc,"z", info2->user_name); /* pszUserName */
565 PACKI(desc,"W",n+1); /* uPosition */
566 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
567 PACKI(desc,"D",t); /* ulSubmitted */
568 PACKI(desc,"D", info2->size); /* ulSize */
569 PACKS(desc,"z","Samba"); /* pszComment */
570 PACKS(desc,"z", info2->document_name); /* pszDocument */
572 PACKS(desc,"z",""); /* pszNotifyName */
573 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
574 PACKS(desc,"z",""); /* pszParms */
575 PACKS(desc,"z",""); /* pszStatus */
576 PACKS(desc,"z", info2->printer_name); /* pszQueue */
577 PACKS(desc,"z","lpd"); /* pszQProcName */
578 PACKS(desc,"z",""); /* pszQProcParms */
579 PACKS(desc,"z","NULL"); /* pszDriverName */
580 PackDriverData(desc); /* pDriverData */
581 PACKS(desc,"z",""); /* pszPrinterName */
582 } else if (uLevel == 4) { /* OS2 */
583 PACKS(desc,"z",""); /* pszSpoolFileName */
584 PACKS(desc,"z",""); /* pszPortName */
585 PACKS(desc,"z",""); /* pszStatus */
586 PACKI(desc,"D",0); /* ulPagesSpooled */
587 PACKI(desc,"D",0); /* ulPagesSent */
588 PACKI(desc,"D",0); /* ulPagesPrinted */
589 PACKI(desc,"D",0); /* ulTimePrinted */
590 PACKI(desc,"D",0); /* ulExtendJobStatus */
591 PACKI(desc,"D",0); /* ulStartPage */
592 PACKI(desc,"D",0); /* ulEndPage */
597 /********************************************************************
598 Respond to the DosPrintQInfo command with a level of 52
599 This is used to get printer driver information for Win9x clients
600 ********************************************************************/
601 static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver,
602 struct pack_desc* desc, int count,
603 const char *printer_name)
607 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
608 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
609 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
611 PACKI(desc, "W", 0x0400); /* don't know */
612 PACKS(desc, "z", driver->driver_name); /* long printer name */
613 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
614 PACKS(desc, "z", driver->data_file); /* Datafile name */
615 PACKS(desc, "z", driver->monitor_name); /* language monitor */
617 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
618 standard_sub_basic( "", "", location, sizeof(location)-1 );
619 PACKS(desc,"z", location); /* share to retrieve files */
621 PACKS(desc,"z", driver->default_datatype); /* default data type */
622 PACKS(desc,"z", driver->help_file); /* helpfile name */
623 PACKS(desc,"z", driver->driver_path); /* driver name */
625 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
626 DEBUG(3,("Driver: %s:\n",driver->driver_path));
627 DEBUG(3,("Data File: %s:\n",driver->data_file));
628 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
629 DEBUG(3,("Driver Location: %s:\n",location));
630 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
631 DEBUG(3,("Help File: %s:\n",driver->help_file));
632 PACKI(desc,"N",count); /* number of files to copy */
634 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
636 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
637 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
638 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
643 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
646 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name, i));
648 desc->errcode=NERR_Success;
652 static const char *strip_unc(const char *unc)
660 if ((p = strrchr(unc, '\\')) != NULL) {
667 static void fill_printq_info(int uLevel,
668 struct pack_desc* desc,
670 union spoolss_JobInfo *job_info,
671 struct spoolss_DriverInfo3 *driver_info,
672 struct spoolss_PrinterInfo2 *printer_info)
678 PACKS(desc,"B13", strip_unc(printer_info->printername));
683 PACKS(desc,"z", strip_unc(printer_info->printername));
686 PACKI(desc,"K", printq_spoolss_status(printer_info->status));
690 if (uLevel == 1 || uLevel == 2) {
691 PACKS(desc,"B",""); /* alignment */
692 PACKI(desc,"W",5); /* priority */
693 PACKI(desc,"W",0); /* start time */
694 PACKI(desc,"W",0); /* until time */
695 PACKS(desc,"z",""); /* pSepFile */
696 PACKS(desc,"z","lpd"); /* pPrProc */
697 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pDestinations */
698 PACKS(desc,"z",""); /* pParms */
699 if (printer_info->printername == NULL) {
700 PACKS(desc,"z","UNKNOWN PRINTER");
701 PACKI(desc,"W",LPSTAT_ERROR);
703 PACKS(desc,"z", printer_info->comment);
704 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* status */
706 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
709 if (uLevel == 3 || uLevel == 4) {
710 PACKI(desc,"W",5); /* uPriority */
711 PACKI(desc,"W",0); /* uStarttime */
712 PACKI(desc,"W",0); /* uUntiltime */
713 PACKI(desc,"W",5); /* pad1 */
714 PACKS(desc,"z",""); /* pszSepFile */
715 PACKS(desc,"z","WinPrint"); /* pszPrProc */
716 PACKS(desc,"z",NULL); /* pszParms */
717 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
718 /* "don't ask" that it's done this way to fix corrupted
719 Win9X/ME printer comments. */
720 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* fsStatus */
721 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
722 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pszPrinters */
723 PACKS(desc,"z", printer_info->drivername); /* pszDriverName */
724 PackDriverData(desc); /* pDriverData */
727 if (uLevel == 2 || uLevel == 4) {
729 for (i = 0; i < count; i++) {
730 fill_spoolss_printjob_info(uLevel == 2 ? 1 : 2, desc, &job_info[i].info2, i);
735 fill_printq_info_52(driver_info, desc, count, printer_info->printername);
738 /* This function returns the number of files for a given driver */
739 static int get_printerdrivernumber(const struct spoolss_DriverInfo3 *driver)
743 /* count the number of files */
744 while (driver->dependent_files && *driver->dependent_files[result])
750 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
751 char *param, int tpscnt,
752 char *data, int tdscnt,
753 int mdrcnt,int mprcnt,
754 char **rdata,char **rparam,
755 int *rdata_len,int *rparam_len)
757 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
758 char *str2 = skip_string(param,tpscnt,str1);
759 char *p = skip_string(param,tpscnt,str2);
764 struct pack_desc desc;
767 WERROR werr = WERR_OK;
768 TALLOC_CTX *mem_ctx = talloc_tos();
770 struct rpc_pipe_client *cli = NULL;
771 struct policy_handle handle;
772 struct spoolss_DevmodeContainer devmode_ctr;
773 union spoolss_DriverInfo driver_info;
774 union spoolss_JobInfo *job_info;
775 union spoolss_PrinterInfo printer_info;
777 if (!str1 || !str2 || !p) {
780 memset((char *)&desc,'\0',sizeof(desc));
782 p = skip_string(param,tpscnt,p);
786 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
787 str3 = get_safe_str_ptr(param,tpscnt,p,4);
788 /* str3 may be null here and is checked in check_printq_info(). */
790 /* remove any trailing username */
791 if ((p = strchr_m(QueueName,'%')))
794 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
796 /* check it's a supported varient */
797 if (!prefix_ok(str1,"zWrLh"))
799 if (!check_printq_info(&desc,uLevel,str2,str3)) {
801 * Patch from Scott Moomaw <scott@bridgewater.edu>
802 * to return the 'invalid info level' error if an
803 * unknown level was requested.
807 *rparam = smb_realloc_limit(*rparam,*rparam_len);
811 SSVALS(*rparam,0,ERRunknownlevel);
819 status = rpc_connect_spoolss_pipe(conn, &cli);
820 if (!NT_STATUS_IS_OK(status)) {
821 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
823 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
827 ZERO_STRUCT(devmode_ctr);
829 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
836 if (!NT_STATUS_IS_OK(status)) {
837 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
840 if (!W_ERROR_IS_OK(werr)) {
841 desc.errcode = W_ERROR_V(werr);
845 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
850 if (!W_ERROR_IS_OK(werr)) {
851 desc.errcode = W_ERROR_V(werr);
856 uint32_t server_major_version;
857 uint32_t server_minor_version;
859 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
867 &server_major_version,
868 &server_minor_version);
869 if (!W_ERROR_IS_OK(werr)) {
870 desc.errcode = W_ERROR_V(werr);
874 count = get_printerdrivernumber(&driver_info.info3);
875 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
878 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
886 if (!W_ERROR_IS_OK(werr)) {
887 desc.errcode = W_ERROR_V(werr);
895 *rdata = smb_realloc_limit(*rdata,mdrcnt);
900 desc.buflen = mdrcnt;
903 * Don't return data but need to get correct length
904 * init_package will return wrong size if buflen=0
906 desc.buflen = getlen(desc.format);
907 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
910 if (init_package(&desc,1,count)) {
911 desc.subcount = count;
912 fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
915 *rdata_len = desc.usedlen;
918 * We must set the return code to ERRbuftoosmall
919 * in order to support lanman style printing with Win NT/2k
922 if (!mdrcnt && lp_disable_spoolss())
923 desc.errcode = ERRbuftoosmall;
926 if (cli && is_valid_policy_hnd(&handle)) {
927 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
930 *rdata_len = desc.usedlen;
932 *rparam = smb_realloc_limit(*rparam,*rparam_len);
937 SSVALS(*rparam,0,desc.errcode);
939 SSVAL(*rparam,4,desc.neededlen);
941 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
948 /****************************************************************************
949 View list of all print jobs on all queues.
950 ****************************************************************************/
952 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
953 char *param, int tpscnt,
954 char *data, int tdscnt,
955 int mdrcnt, int mprcnt,
956 char **rdata, char** rparam,
957 int *rdata_len, int *rparam_len)
959 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
960 char *output_format1 = skip_string(param,tpscnt,param_format);
961 char *p = skip_string(param,tpscnt,output_format1);
962 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
963 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
965 struct pack_desc desc;
966 int *subcntarr = NULL;
967 int queuecnt = 0, subcnt = 0, succnt = 0;
969 WERROR werr = WERR_OK;
970 TALLOC_CTX *mem_ctx = talloc_tos();
972 struct rpc_pipe_client *cli = NULL;
973 struct spoolss_DevmodeContainer devmode_ctr;
974 uint32_t num_printers;
975 union spoolss_PrinterInfo *printer_info;
976 union spoolss_DriverInfo *driver_info;
977 union spoolss_JobInfo **job_info;
979 if (!param_format || !output_format1 || !p) {
983 memset((char *)&desc,'\0',sizeof(desc));
985 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
987 if (!prefix_ok(param_format,"WrLeh")) {
990 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
992 * Patch from Scott Moomaw <scott@bridgewater.edu>
993 * to return the 'invalid info level' error if an
994 * unknown level was requested.
998 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1002 SSVALS(*rparam,0,ERRunknownlevel);
1008 status = rpc_connect_spoolss_pipe(conn, &cli);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1011 nt_errstr(status)));
1012 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1016 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
1018 cli->srv_name_slash,
1023 if (!W_ERROR_IS_OK(werr)) {
1024 desc.errcode = W_ERROR_V(werr);
1028 queuecnt = num_printers;
1030 job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
1031 if (job_info == NULL) {
1035 driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
1036 if (driver_info == NULL) {
1040 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1041 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1046 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1052 desc.buflen = mdrcnt;
1055 for (i = 0; i < num_printers; i++) {
1058 struct policy_handle handle;
1059 const char *printername;
1061 printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
1062 if (printername == NULL) {
1066 ZERO_STRUCT(handle);
1067 ZERO_STRUCT(devmode_ctr);
1069 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
1076 if (!NT_STATUS_IS_OK(status)) {
1077 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1080 if (!W_ERROR_IS_OK(werr)) {
1081 desc.errcode = W_ERROR_V(werr);
1085 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
1093 if (!W_ERROR_IS_OK(werr)) {
1094 desc.errcode = W_ERROR_V(werr);
1099 uint32_t server_major_version;
1100 uint32_t server_minor_version;
1102 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1110 &server_major_version,
1111 &server_minor_version);
1112 if (!W_ERROR_IS_OK(werr)) {
1113 desc.errcode = W_ERROR_V(werr);
1118 subcntarr[i] = num_jobs;
1119 subcnt += subcntarr[i];
1121 if (cli && is_valid_policy_hnd(&handle)) {
1122 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1126 if (init_package(&desc,queuecnt,subcnt)) {
1127 for (i = 0; i < num_printers; i++) {
1128 fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
1129 if (desc.errcode == NERR_Success) {
1135 SAFE_FREE(subcntarr);
1137 *rdata_len = desc.usedlen;
1139 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1143 SSVALS(*rparam,0,desc.errcode);
1145 SSVAL(*rparam,4,succnt);
1146 SSVAL(*rparam,6,queuecnt);
1152 SAFE_FREE(subcntarr);
1157 /****************************************************************************
1158 Get info level for a server list query.
1159 ****************************************************************************/
1161 static bool check_server_info(int uLevel, char* id)
1165 if (strcmp(id,"B16") != 0) {
1170 if (strcmp(id,"B16BBDz") != 0) {
1180 struct srv_info_struct {
1188 /*******************************************************************
1189 Get server info lists from the files saved by nmbd. Return the
1191 ******************************************************************/
1193 static int get_server_info(uint32 servertype,
1194 struct srv_info_struct **servers,
1200 bool local_list_only;
1203 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1205 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1209 /* request for everything is code for request all servers */
1210 if (servertype == SV_TYPE_ALL) {
1211 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1214 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1216 DEBUG(4,("Servertype search: %8x\n",servertype));
1218 for (i=0;lines[i];i++) {
1220 struct srv_info_struct *s;
1221 const char *ptr = lines[i];
1223 TALLOC_CTX *frame = NULL;
1230 if (count == alloced) {
1232 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1234 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1238 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1240 s = &(*servers)[count];
1242 frame = talloc_stackframe();
1244 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1248 fstrcpy(s->name, p);
1251 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1257 s->comment[0] = '\0';
1258 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1262 fstrcpy(s->comment, p);
1263 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1265 s->domain[0] = '\0';
1266 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1267 /* this allows us to cope with an old nmbd */
1268 fstrcpy(s->domain,lp_workgroup());
1270 fstrcpy(s->domain, p);
1274 if (sscanf(stype,"%X",&s->type) != 1) {
1275 DEBUG(4,("r:host file "));
1279 /* Filter the servers/domains we return based on what was asked for. */
1281 /* Check to see if we are being asked for a local list only. */
1282 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1283 DEBUG(4,("r: local list only"));
1287 /* doesn't match up: don't want it */
1288 if (!(servertype & s->type)) {
1289 DEBUG(4,("r:serv type "));
1293 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1294 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1295 DEBUG(4,("s: dom mismatch "));
1299 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1303 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1304 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1307 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1308 s->name, s->type, s->comment, s->domain));
1309 s->server_added = True;
1312 DEBUG(4,("%20s %8x %25s %15s\n",
1313 s->name, s->type, s->comment, s->domain));
1321 /*******************************************************************
1322 Fill in a server info structure.
1323 ******************************************************************/
1325 static int fill_srv_info(struct srv_info_struct *service,
1326 int uLevel, char **buf, int *buflen,
1327 char **stringbuf, int *stringspace, char *baseaddr)
1350 len = strlen(service->comment)+1;
1354 *buflen = struct_len;
1356 return struct_len + len;
1361 if (*buflen < struct_len) {
1368 p2 = p + struct_len;
1369 l2 = *buflen - struct_len;
1377 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1381 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1382 SIVAL(p,18,service->type);
1383 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1384 len += CopyAndAdvance(&p2,service->comment,&l2);
1389 *buf = p + struct_len;
1390 *buflen -= struct_len;
1401 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1403 return StrCaseCmp(s1->name,s2->name);
1406 /****************************************************************************
1407 View list of servers available (or possibly domains). The info is
1408 extracted from lists saved by nmbd on the local host.
1409 ****************************************************************************/
1411 static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
1412 char *param, int tpscnt,
1413 char *data, int tdscnt,
1414 int mdrcnt, int mprcnt, char **rdata,
1415 char **rparam, int *rdata_len, int *rparam_len)
1417 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1418 char *str2 = skip_string(param,tpscnt,str1);
1419 char *p = skip_string(param,tpscnt,str2);
1420 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1421 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1422 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1424 int data_len, fixed_len, string_len;
1425 int f_len = 0, s_len = 0;
1426 struct srv_info_struct *servers=NULL;
1427 int counted=0,total=0;
1430 bool domain_request;
1433 if (!str1 || !str2 || !p) {
1437 /* If someone sets all the bits they don't really mean to set
1438 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1441 if (servertype == SV_TYPE_ALL) {
1442 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1445 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1446 any other bit (they may just set this bit on its own) they
1447 want all the locally seen servers. However this bit can be
1448 set on its own so set the requested servers to be
1449 ALL - DOMAIN_ENUM. */
1451 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1452 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1455 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1456 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1460 if (!prefix_ok(str1,"WrLehD")) {
1463 if (!check_server_info(uLevel,str2)) {
1467 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1468 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1469 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1471 if (strcmp(str1, "WrLehDz") == 0) {
1472 if (skip_string(param,tpscnt,p) == NULL) {
1475 pull_ascii_fstring(domain, p);
1477 fstrcpy(domain, lp_workgroup());
1480 DEBUG(4, ("domain [%s]\n", domain));
1482 if (lp_browse_list()) {
1483 total = get_server_info(servertype,&servers,domain);
1486 data_len = fixed_len = string_len = 0;
1489 TYPESAFE_QSORT(servers, total, srv_comp);
1492 char *lastname=NULL;
1494 for (i=0;i<total;i++) {
1495 struct srv_info_struct *s = &servers[i];
1497 if (lastname && strequal(lastname,s->name)) {
1501 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1502 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1503 i, s->name, s->type, s->comment, s->domain));
1505 if (data_len < buf_len) {
1508 string_len += s_len;
1515 *rdata_len = fixed_len + string_len;
1516 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1521 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1527 char *lastname=NULL;
1528 int count2 = counted;
1530 for (i = 0; i < total && count2;i++) {
1531 struct srv_info_struct *s = &servers[i];
1533 if (lastname && strequal(lastname,s->name)) {
1537 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1538 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1539 i, s->name, s->type, s->comment, s->domain));
1545 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1549 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1551 SSVAL(*rparam,4,counted);
1552 SSVAL(*rparam,6,counted+missed);
1556 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1557 domain,uLevel,counted,counted+missed));
1562 static int srv_name_match(const char *n1, const char *n2)
1565 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1567 * In Windows, FirstNameToReturn need not be an exact match:
1568 * the server will return a list of servers that exist on
1569 * the network greater than or equal to the FirstNameToReturn.
1571 int ret = StrCaseCmp(n1, n2);
1580 static bool api_RNetServerEnum3(connection_struct *conn, uint16 vuid,
1581 char *param, int tpscnt,
1582 char *data, int tdscnt,
1583 int mdrcnt, int mprcnt, char **rdata,
1584 char **rparam, int *rdata_len, int *rparam_len)
1586 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1587 char *str2 = skip_string(param,tpscnt,str1);
1588 char *p = skip_string(param,tpscnt,str2);
1589 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1590 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1591 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1593 int data_len, fixed_len, string_len;
1594 int f_len = 0, s_len = 0;
1595 struct srv_info_struct *servers=NULL;
1596 int counted=0,first=0,total=0;
1600 bool domain_request;
1603 if (!str1 || !str2 || !p) {
1607 /* If someone sets all the bits they don't really mean to set
1608 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1611 if (servertype == SV_TYPE_ALL) {
1612 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1615 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1616 any other bit (they may just set this bit on its own) they
1617 want all the locally seen servers. However this bit can be
1618 set on its own so set the requested servers to be
1619 ALL - DOMAIN_ENUM. */
1621 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1622 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1625 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1626 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1630 if (strcmp(str1, "WrLehDzz") != 0) {
1633 if (!check_server_info(uLevel,str2)) {
1637 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1638 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1639 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1641 if (skip_string(param,tpscnt,p) == NULL) {
1644 pull_ascii_fstring(domain, p);
1645 if (domain[0] == '\0') {
1646 fstrcpy(domain, lp_workgroup());
1648 p = skip_string(param,tpscnt,p);
1649 if (skip_string(param,tpscnt,p) == NULL) {
1652 pull_ascii_fstring(first_name, p);
1654 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1655 domain, first_name));
1657 if (lp_browse_list()) {
1658 total = get_server_info(servertype,&servers,domain);
1661 data_len = fixed_len = string_len = 0;
1664 TYPESAFE_QSORT(servers, total, srv_comp);
1666 if (first_name[0] != '\0') {
1667 struct srv_info_struct *first_server = NULL;
1669 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1670 srv_name_match, first_server);
1672 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1674 * The binary search may not find the exact match
1675 * so we need to search backward to find the first match
1677 * This implements the strange matching windows
1678 * implements. (see the comment in srv_name_match().
1682 ret = StrCaseCmp(first_name,
1683 servers[first-1].name);
1690 /* we should return no entries */
1696 char *lastname=NULL;
1698 for (i=first;i<total;i++) {
1699 struct srv_info_struct *s = &servers[i];
1701 if (lastname && strequal(lastname,s->name)) {
1705 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1706 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1707 i, s->name, s->type, s->comment, s->domain));
1709 if (data_len < buf_len) {
1712 string_len += s_len;
1719 *rdata_len = fixed_len + string_len;
1720 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1725 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1731 char *lastname=NULL;
1732 int count2 = counted;
1734 for (i = first; i < total && count2;i++) {
1735 struct srv_info_struct *s = &servers[i];
1737 if (lastname && strequal(lastname,s->name)) {
1741 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1742 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1743 i, s->name, s->type, s->comment, s->domain));
1749 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1753 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1755 SSVAL(*rparam,4,counted);
1756 SSVAL(*rparam,6,counted+missed);
1758 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1759 domain,uLevel,first,first_name,
1760 first < total ? servers[first].name : "",
1761 counted,counted+missed));
1768 /****************************************************************************
1769 command 0x34 - suspected of being a "Lookup Names" stub api
1770 ****************************************************************************/
1772 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1773 char *param, int tpscnt,
1774 char *data, int tdscnt,
1775 int mdrcnt, int mprcnt, char **rdata,
1776 char **rparam, int *rdata_len, int *rparam_len)
1778 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1779 char *str2 = skip_string(param,tpscnt,str1);
1780 char *p = skip_string(param,tpscnt,str2);
1781 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1782 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1786 if (!str1 || !str2 || !p) {
1790 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1791 str1, str2, p, uLevel, buf_len));
1793 if (!prefix_ok(str1,"zWrLeh")) {
1800 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1805 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1807 SSVAL(*rparam,4,counted);
1808 SSVAL(*rparam,6,counted+missed);
1813 /****************************************************************************
1814 get info about a share
1815 ****************************************************************************/
1817 static bool check_share_info(int uLevel, char* id)
1821 if (strcmp(id,"B13") != 0) {
1826 /* Level-2 descriptor is allowed (and ignored) */
1827 if (strcmp(id,"B13BWz") != 0 &&
1828 strcmp(id,"B13BWzWWWzB9B") != 0) {
1833 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1838 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1848 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1849 char** buf, int* buflen,
1850 char** stringbuf, int* stringspace, char* baseaddr)
1879 len += StrlenExpanded(conn,snum,lp_comment(snum));
1882 len += strlen(lp_pathname(snum)) + 1;
1885 *buflen = struct_len;
1890 return struct_len + len;
1895 if ((*buflen) < struct_len) {
1903 p2 = p + struct_len;
1904 l2 = (*buflen) - struct_len;
1911 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1917 type = STYPE_DISKTREE;
1918 if (lp_print_ok(snum)) {
1919 type = STYPE_PRINTQ;
1921 if (strequal("IPC",lp_fstype(snum))) {
1924 SSVAL(p,14,type); /* device type */
1925 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1926 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1930 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1931 SSVALS(p,22,-1); /* max uses */
1932 SSVAL(p,24,1); /* current uses */
1933 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1934 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1935 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1939 memset(p+40,0,SHPWLEN+2);
1950 (*buf) = p + struct_len;
1951 (*buflen) -= struct_len;
1953 (*stringspace) = l2;
1962 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1963 char *param, int tpscnt,
1964 char *data, int tdscnt,
1965 int mdrcnt,int mprcnt,
1966 char **rdata,char **rparam,
1967 int *rdata_len,int *rparam_len)
1969 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1970 char *str2 = skip_string(param,tpscnt,str1);
1971 char *netname = skip_string(param,tpscnt,str2);
1972 char *p = skip_string(param,tpscnt,netname);
1973 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1976 if (!str1 || !str2 || !netname || !p) {
1980 snum = find_service(netname);
1985 /* check it's a supported varient */
1986 if (!prefix_ok(str1,"zWrLh")) {
1989 if (!check_share_info(uLevel,str2)) {
1993 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1998 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1999 if (*rdata_len < 0) {
2004 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2008 SSVAL(*rparam,0,NERR_Success);
2009 SSVAL(*rparam,2,0); /* converter word */
2010 SSVAL(*rparam,4,*rdata_len);
2015 /****************************************************************************
2016 View the list of available shares.
2018 This function is the server side of the NetShareEnum() RAP call.
2019 It fills the return buffer with share names and share comments.
2020 Note that the return buffer normally (in all known cases) allows only
2021 twelve byte strings for share names (plus one for a nul terminator).
2022 Share names longer than 12 bytes must be skipped.
2023 ****************************************************************************/
2025 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
2026 char *param, int tpscnt,
2027 char *data, int tdscnt,
2035 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2036 char *str2 = skip_string(param,tpscnt,str1);
2037 char *p = skip_string(param,tpscnt,str2);
2038 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2039 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2042 int total=0,counted=0;
2043 bool missed = False;
2045 int data_len, fixed_len, string_len;
2046 int f_len = 0, s_len = 0;
2048 if (!str1 || !str2 || !p) {
2052 if (!prefix_ok(str1,"WrLeh")) {
2055 if (!check_share_info(uLevel,str2)) {
2059 /* Ensure all the usershares are loaded. */
2061 load_registry_shares();
2062 count = load_usershare_shares();
2065 data_len = fixed_len = string_len = 0;
2066 for (i=0;i<count;i++) {
2067 fstring servicename_dos;
2068 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2071 push_ascii_fstring(servicename_dos, lp_servicename(i));
2072 /* Maximum name length = 13. */
2073 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2075 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2076 if (data_len < buf_len) {
2079 string_len += s_len;
2086 *rdata_len = fixed_len + string_len;
2087 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2092 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2097 for( i = 0; i < count; i++ ) {
2098 fstring servicename_dos;
2099 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2103 push_ascii_fstring(servicename_dos, lp_servicename(i));
2104 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2105 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2112 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2116 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2118 SSVAL(*rparam,4,counted);
2119 SSVAL(*rparam,6,total);
2121 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2122 counted,total,uLevel,
2123 buf_len,*rdata_len,mdrcnt));
2128 /****************************************************************************
2130 ****************************************************************************/
2132 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
2133 char *param, int tpscnt,
2134 char *data, int tdscnt,
2135 int mdrcnt,int mprcnt,
2136 char **rdata,char **rparam,
2137 int *rdata_len,int *rparam_len)
2139 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2140 char *str2 = skip_string(param,tpscnt,str1);
2141 char *p = skip_string(param,tpscnt,str2);
2142 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2145 char *pathname = NULL;
2146 unsigned int offset;
2148 size_t converted_size;
2150 WERROR werr = WERR_OK;
2151 TALLOC_CTX *mem_ctx = talloc_tos();
2153 struct rpc_pipe_client *cli = NULL;
2154 union srvsvc_NetShareInfo info;
2155 struct srvsvc_NetShareInfo2 info2;
2157 if (!str1 || !str2 || !p) {
2161 /* check it's a supported varient */
2162 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2165 if (!check_share_info(uLevel,str2)) {
2172 /* Do we have a string ? */
2173 if (skip_string(data,mdrcnt,data) == NULL) {
2176 pull_ascii_fstring(sharename,data);
2182 /* only support disk share adds */
2183 if (SVAL(data,14)!=STYPE_DISKTREE) {
2187 offset = IVAL(data, 16);
2188 if (offset >= mdrcnt) {
2189 res = ERRinvalidparam;
2193 /* Do we have a string ? */
2194 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2197 pull_ascii_fstring(comment, offset? (data+offset) : "");
2199 offset = IVAL(data, 26);
2201 if (offset >= mdrcnt) {
2202 res = ERRinvalidparam;
2206 /* Do we have a string ? */
2207 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2211 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2212 offset ? (data+offset) : "", &converted_size))
2214 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2222 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
2223 rpc_srvsvc_dispatch, conn->server_info,
2225 if (!NT_STATUS_IS_OK(status)) {
2226 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2227 nt_errstr(status)));
2228 res = W_ERROR_V(ntstatus_to_werror(status));
2232 info2.name = sharename;
2233 info2.type = STYPE_DISKTREE;
2234 info2.comment = comment;
2235 info2.permissions = 0;
2236 info2.max_users = 0;
2237 info2.current_users = 0;
2238 info2.path = pathname;
2239 info2.password = NULL;
2241 info.info2 = &info2;
2243 status = rpccli_srvsvc_NetShareAdd(cli, mem_ctx,
2244 cli->srv_name_slash,
2249 if (!NT_STATUS_IS_OK(status)) {
2250 res = W_ERROR_V(ntstatus_to_werror(status));
2253 if (!W_ERROR_IS_OK(werr)) {
2254 res = W_ERROR_V(werr);
2259 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2263 SSVAL(*rparam,0,NERR_Success);
2264 SSVAL(*rparam,2,0); /* converter word */
2265 SSVAL(*rparam,4,*rdata_len);
2273 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2278 SSVAL(*rparam,0,res);
2283 /****************************************************************************
2284 view list of groups available
2285 ****************************************************************************/
2287 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2288 char *param, int tpscnt,
2289 char *data, int tdscnt,
2290 int mdrcnt,int mprcnt,
2291 char **rdata,char **rparam,
2292 int *rdata_len,int *rparam_len)
2296 int resume_context, cli_buf_size;
2297 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2298 char *str2 = skip_string(param,tpscnt,str1);
2299 char *p = skip_string(param,tpscnt,str2);
2301 uint32_t num_groups;
2302 uint32_t resume_handle;
2303 struct rpc_pipe_client *samr_pipe;
2304 struct policy_handle samr_handle, domain_handle;
2307 if (!str1 || !str2 || !p) {
2311 if (strcmp(str1,"WrLeh") != 0) {
2316 * W-> resume context (number of users to skip)
2317 * r -> return parameter pointer to receive buffer
2318 * L -> length of receive buffer
2319 * e -> return parameter number of entries
2320 * h -> return parameter total number of users
2323 if (strcmp("B21",str2) != 0) {
2327 status = rpc_pipe_open_internal(
2328 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2329 conn->server_info, &samr_pipe);
2330 if (!NT_STATUS_IS_OK(status)) {
2331 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2332 nt_errstr(status)));
2336 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2337 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2340 nt_errstr(status)));
2344 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2345 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2346 get_global_sam_sid(), &domain_handle);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2349 nt_errstr(status)));
2350 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2354 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2355 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2356 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2357 "%d\n", resume_context, cli_buf_size));
2359 *rdata_len = cli_buf_size;
2360 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2367 errflags = NERR_Success;
2372 struct samr_SamArray *sam_entries;
2373 uint32_t num_entries;
2375 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2380 if (!NT_STATUS_IS_OK(status)) {
2381 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2382 "%s\n", nt_errstr(status)));
2386 if (num_entries == 0) {
2387 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2388 "no entries -- done\n"));
2392 for(i=0; i<num_entries; i++) {
2395 name = sam_entries->entries[i].name.string;
2397 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2398 /* set overflow error */
2399 DEBUG(3,("overflow on entry %d group %s\n", i,
2405 /* truncate the name at 21 chars. */
2407 strlcpy(p, name, 21);
2408 DEBUG(10,("adding entry %d group %s\n", i, p));
2410 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2415 if (errflags != NERR_Success) {
2419 TALLOC_FREE(sam_entries);
2422 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2423 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2425 *rdata_len = PTR_DIFF(p,*rdata);
2428 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2432 SSVAL(*rparam, 0, errflags);
2433 SSVAL(*rparam, 2, 0); /* converter word */
2434 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2435 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2440 /*******************************************************************
2441 Get groups that a user is a member of.
2442 ******************************************************************/
2444 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2445 char *param, int tpscnt,
2446 char *data, int tdscnt,
2447 int mdrcnt,int mprcnt,
2448 char **rdata,char **rparam,
2449 int *rdata_len,int *rparam_len)
2451 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2452 char *str2 = skip_string(param,tpscnt,str1);
2453 char *UserName = skip_string(param,tpscnt,str2);
2454 char *p = skip_string(param,tpscnt,UserName);
2455 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2456 const char *level_string;
2462 struct rpc_pipe_client *samr_pipe;
2463 struct policy_handle samr_handle, domain_handle, user_handle;
2464 struct lsa_String name;
2465 struct lsa_Strings names;
2466 struct samr_Ids type, rid;
2467 struct samr_RidWithAttributeArray *rids;
2470 if (!str1 || !str2 || !UserName || !p) {
2475 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2480 /* check it's a supported varient */
2482 if ( strcmp(str1,"zWrLeh") != 0 )
2487 level_string = "B21";
2493 if (strcmp(level_string,str2) != 0)
2496 *rdata_len = mdrcnt + 1024;
2497 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2502 SSVAL(*rparam,0,NERR_Success);
2503 SSVAL(*rparam,2,0); /* converter word */
2506 endp = *rdata + *rdata_len;
2508 status = rpc_pipe_open_internal(
2509 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2510 conn->server_info, &samr_pipe);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2513 nt_errstr(status)));
2517 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2518 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2521 nt_errstr(status)));
2525 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2526 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2527 get_global_sam_sid(), &domain_handle);
2528 if (!NT_STATUS_IS_OK(status)) {
2529 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2530 nt_errstr(status)));
2534 name.string = UserName;
2536 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2537 &domain_handle, 1, &name,
2539 if (!NT_STATUS_IS_OK(status)) {
2540 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2541 nt_errstr(status)));
2545 if (type.ids[0] != SID_NAME_USER) {
2546 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2547 sid_type_lookup(type.ids[0])));
2551 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2553 SAMR_USER_ACCESS_GET_GROUPS,
2554 rid.ids[0], &user_handle);
2555 if (!NT_STATUS_IS_OK(status)) {
2556 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2557 nt_errstr(status)));
2561 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2562 &user_handle, &rids);
2563 if (!NT_STATUS_IS_OK(status)) {
2564 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2565 nt_errstr(status)));
2569 for (i=0; i<rids->count; i++) {
2571 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2573 1, &rids->rids[i].rid,
2575 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2576 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2582 *rdata_len = PTR_DIFF(p,*rdata);
2584 SSVAL(*rparam,4,count); /* is this right?? */
2585 SSVAL(*rparam,6,count); /* is this right?? */
2590 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2592 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2594 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2599 /*******************************************************************
2601 ******************************************************************/
2603 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2604 char *param, int tpscnt,
2605 char *data, int tdscnt,
2606 int mdrcnt,int mprcnt,
2607 char **rdata,char **rparam,
2608 int *rdata_len,int *rparam_len)
2613 int i, resume_context, cli_buf_size;
2614 uint32_t resume_handle;
2616 struct rpc_pipe_client *samr_pipe;
2617 struct policy_handle samr_handle, domain_handle;
2620 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2621 char *str2 = skip_string(param,tpscnt,str1);
2622 char *p = skip_string(param,tpscnt,str2);
2625 if (!str1 || !str2 || !p) {
2629 if (strcmp(str1,"WrLeh") != 0)
2632 * W-> resume context (number of users to skip)
2633 * r -> return parameter pointer to receive buffer
2634 * L -> length of receive buffer
2635 * e -> return parameter number of entries
2636 * h -> return parameter total number of users
2639 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2640 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2641 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2642 resume_context, cli_buf_size));
2645 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2650 /* check it's a supported varient */
2651 if (strcmp("B21",str2) != 0)
2654 *rdata_len = cli_buf_size;
2655 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2661 endp = *rdata + *rdata_len;
2663 status = rpc_pipe_open_internal(
2664 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2665 conn->server_info, &samr_pipe);
2666 if (!NT_STATUS_IS_OK(status)) {
2667 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2668 nt_errstr(status)));
2672 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2673 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2676 nt_errstr(status)));
2680 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2681 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2682 get_global_sam_sid(), &domain_handle);
2683 if (!NT_STATUS_IS_OK(status)) {
2684 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2685 nt_errstr(status)));
2686 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2690 errflags=NERR_Success;
2695 struct samr_SamArray *sam_entries;
2696 uint32_t num_entries;
2698 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2704 if (!NT_STATUS_IS_OK(status)) {
2705 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2706 "%s\n", nt_errstr(status)));
2710 if (num_entries == 0) {
2711 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2712 "no entries -- done\n"));
2716 for (i=0; i<num_entries; i++) {
2719 name = sam_entries->entries[i].name.string;
2721 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2722 &&(strlen(name)<=21)) {
2723 strlcpy(p,name,PTR_DIFF(endp,p));
2724 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2725 "username %s\n",count_sent,p));
2729 /* set overflow error */
2730 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2731 "username %s\n",count_sent,name));
2737 if (errflags != NERR_Success) {
2741 TALLOC_FREE(sam_entries);
2744 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2745 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2747 *rdata_len = PTR_DIFF(p,*rdata);
2749 SSVAL(*rparam,0,errflags);
2750 SSVAL(*rparam,2,0); /* converter word */
2751 SSVAL(*rparam,4,count_sent); /* is this right?? */
2752 SSVAL(*rparam,6,num_users); /* is this right?? */
2757 /****************************************************************************
2758 Get the time of day info.
2759 ****************************************************************************/
2761 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2762 char *param, int tpscnt,
2763 char *data, int tdscnt,
2764 int mdrcnt,int mprcnt,
2765 char **rdata,char **rparam,
2766 int *rdata_len,int *rparam_len)
2769 time_t unixdate = time(NULL);
2773 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2779 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2784 SSVAL(*rparam,0,NERR_Success);
2785 SSVAL(*rparam,2,0); /* converter word */
2789 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2790 by NT in a "net time" operation,
2791 it seems to ignore the one below */
2793 /* the client expects to get localtime, not GMT, in this bit
2794 (I think, this needs testing) */
2795 t = localtime(&unixdate);
2800 SIVAL(p,4,0); /* msecs ? */
2801 SCVAL(p,8,t->tm_hour);
2802 SCVAL(p,9,t->tm_min);
2803 SCVAL(p,10,t->tm_sec);
2804 SCVAL(p,11,0); /* hundredths of seconds */
2805 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2806 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2807 SCVAL(p,16,t->tm_mday);
2808 SCVAL(p,17,t->tm_mon + 1);
2809 SSVAL(p,18,1900+t->tm_year);
2810 SCVAL(p,20,t->tm_wday);
2815 /****************************************************************************
2816 Set the user password.
2817 *****************************************************************************/
2819 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2820 char *param, int tpscnt,
2821 char *data, int tdscnt,
2822 int mdrcnt,int mprcnt,
2823 char **rdata,char **rparam,
2824 int *rdata_len,int *rparam_len)
2826 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2829 fstring pass1,pass2;
2830 TALLOC_CTX *mem_ctx = talloc_tos();
2832 struct rpc_pipe_client *cli = NULL;
2833 struct policy_handle connect_handle, domain_handle, user_handle;
2834 struct lsa_String domain_name;
2835 struct dom_sid2 *domain_sid;
2836 struct lsa_String names;
2837 struct samr_Ids rids;
2838 struct samr_Ids types;
2839 struct samr_Password old_lm_hash;
2840 struct samr_Password new_lm_hash;
2841 int errcode = NERR_badpass;
2844 /* Skip 2 strings. */
2845 p = skip_string(param,tpscnt,np);
2846 p = skip_string(param,tpscnt,p);
2852 /* Do we have a string ? */
2853 if (skip_string(param,tpscnt,p) == NULL) {
2856 pull_ascii_fstring(user,p);
2858 p = skip_string(param,tpscnt,p);
2863 memset(pass1,'\0',sizeof(pass1));
2864 memset(pass2,'\0',sizeof(pass2));
2866 * We use 31 here not 32 as we're checking
2867 * the last byte we want to access is safe.
2869 if (!is_offset_safe(param,tpscnt,p,31)) {
2873 memcpy(pass2,p+16,16);
2876 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2883 DEBUG(3,("Set password for <%s>\n",user));
2885 ZERO_STRUCT(connect_handle);
2886 ZERO_STRUCT(domain_handle);
2887 ZERO_STRUCT(user_handle);
2889 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
2890 rpc_samr_dispatch, conn->server_info,
2892 if (!NT_STATUS_IS_OK(status)) {
2893 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2894 nt_errstr(status)));
2895 errcode = W_ERROR_V(ntstatus_to_werror(status));
2899 status = rpccli_samr_Connect2(cli, mem_ctx,
2901 SAMR_ACCESS_CONNECT_TO_SERVER |
2902 SAMR_ACCESS_ENUM_DOMAINS |
2903 SAMR_ACCESS_LOOKUP_DOMAIN,
2905 if (!NT_STATUS_IS_OK(status)) {
2906 errcode = W_ERROR_V(ntstatus_to_werror(status));
2910 init_lsa_String(&domain_name, get_global_sam_name());
2912 status = rpccli_samr_LookupDomain(cli, mem_ctx,
2916 if (!NT_STATUS_IS_OK(status)) {
2917 errcode = W_ERROR_V(ntstatus_to_werror(status));
2921 status = rpccli_samr_OpenDomain(cli, mem_ctx,
2923 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2926 if (!NT_STATUS_IS_OK(status)) {
2927 errcode = W_ERROR_V(ntstatus_to_werror(status));
2931 init_lsa_String(&names, user);
2933 status = rpccli_samr_LookupNames(cli, mem_ctx,
2939 if (!NT_STATUS_IS_OK(status)) {
2940 errcode = W_ERROR_V(ntstatus_to_werror(status));
2944 if (rids.count != 1) {
2945 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
2948 if (rids.count != types.count) {
2949 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2952 if (types.ids[0] != SID_NAME_USER) {
2953 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2959 status = rpccli_samr_OpenUser(cli, mem_ctx,
2961 SAMR_USER_ACCESS_CHANGE_PASSWORD,
2964 if (!NT_STATUS_IS_OK(status)) {
2965 errcode = W_ERROR_V(ntstatus_to_werror(status));
2969 E_deshash(pass1, old_lm_hash.hash);
2970 E_deshash(pass2, new_lm_hash.hash);
2972 status = rpccli_samr_ChangePasswordUser(cli, mem_ctx,
2974 true, /* lm_present */
2977 false, /* nt_present */
2978 NULL, /* old_nt_crypted */
2979 NULL, /* new_nt_crypted */
2980 false, /* cross1_present */
2981 NULL, /* nt_cross */
2982 false, /* cross2_present */
2983 NULL); /* lm_cross */
2984 if (!NT_STATUS_IS_OK(status)) {
2985 errcode = W_ERROR_V(ntstatus_to_werror(status));
2989 errcode = NERR_Success;
2992 if (cli && is_valid_policy_hnd(&user_handle)) {
2993 rpccli_samr_Close(cli, mem_ctx, &user_handle);
2995 if (cli && is_valid_policy_hnd(&domain_handle)) {
2996 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
2998 if (cli && is_valid_policy_hnd(&connect_handle)) {
2999 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
3002 memset((char *)pass1,'\0',sizeof(fstring));
3003 memset((char *)pass2,'\0',sizeof(fstring));
3005 SSVAL(*rparam,0,errcode);
3006 SSVAL(*rparam,2,0); /* converter word */
3010 /****************************************************************************
3011 Set the user password (SamOEM version - gets plaintext).
3012 ****************************************************************************/
3014 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
3015 char *param, int tpscnt,
3016 char *data, int tdscnt,
3017 int mdrcnt,int mprcnt,
3018 char **rdata,char **rparam,
3019 int *rdata_len,int *rparam_len)
3022 char *p = get_safe_str_ptr(param,tpscnt,param,2);
3024 TALLOC_CTX *mem_ctx = talloc_tos();
3026 struct rpc_pipe_client *cli = NULL;
3027 struct lsa_AsciiString server, account;
3028 struct samr_CryptPassword password;
3029 struct samr_Password hash;
3030 int errcode = NERR_badpass;
3034 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3044 SSVAL(*rparam,0,NERR_badpass);
3047 * Check the parameter definition is correct.
3050 /* Do we have a string ? */
3051 if (skip_string(param,tpscnt,p) == 0) {
3054 if(!strequal(p, "zsT")) {
3055 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3058 p = skip_string(param, tpscnt, p);
3063 /* Do we have a string ? */
3064 if (skip_string(param,tpscnt,p) == 0) {
3067 if(!strequal(p, "B516B16")) {
3068 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3071 p = skip_string(param,tpscnt,p);
3075 /* Do we have a string ? */
3076 if (skip_string(param,tpscnt,p) == 0) {
3079 p += pull_ascii_fstring(user,p);
3081 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3083 if (tdscnt != 532) {
3084 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3088 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3089 if (bufsize != 532) {
3090 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3094 memcpy(password.data, data, 516);
3095 memcpy(hash.hash, data+516, 16);
3097 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
3098 rpc_samr_dispatch, conn->server_info,
3100 if (!NT_STATUS_IS_OK(status)) {
3101 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3102 nt_errstr(status)));
3103 errcode = W_ERROR_V(ntstatus_to_werror(status));
3107 init_lsa_AsciiString(&server, global_myname());
3108 init_lsa_AsciiString(&account, user);
3110 status = rpccli_samr_OemChangePasswordUser2(cli, mem_ctx,
3115 if (!NT_STATUS_IS_OK(status)) {
3116 errcode = W_ERROR_V(ntstatus_to_werror(status));
3120 errcode = NERR_Success;
3122 SSVAL(*rparam,0,errcode);
3123 SSVAL(*rparam,2,0); /* converter word */
3128 /****************************************************************************
3131 ****************************************************************************/
3133 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
3134 char *param, int tpscnt,
3135 char *data, int tdscnt,
3136 int mdrcnt,int mprcnt,
3137 char **rdata,char **rparam,
3138 int *rdata_len,int *rparam_len)
3140 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3141 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3142 char *str2 = skip_string(param,tpscnt,str1);
3143 char *p = skip_string(param,tpscnt,str2);
3147 WERROR werr = WERR_OK;
3149 TALLOC_CTX *mem_ctx = talloc_tos();
3151 struct rpc_pipe_client *cli = NULL;
3152 struct policy_handle handle;
3153 struct spoolss_DevmodeContainer devmode_ctr;
3154 enum spoolss_JobControl command;
3156 if (!str1 || !str2 || !p) {
3160 * We use 1 here not 2 as we're checking
3161 * the last byte we want to access is safe.
3163 if (!is_offset_safe(param,tpscnt,p,1)) {
3166 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3169 /* check it's a supported varient */
3170 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3174 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3180 ZERO_STRUCT(handle);
3182 status = rpc_connect_spoolss_pipe(conn, &cli);
3183 if (!NT_STATUS_IS_OK(status)) {
3184 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3185 nt_errstr(status)));
3186 errcode = W_ERROR_V(ntstatus_to_werror(status));
3190 ZERO_STRUCT(devmode_ctr);
3192 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3196 JOB_ACCESS_ADMINISTER,
3199 if (!NT_STATUS_IS_OK(status)) {
3200 errcode = W_ERROR_V(ntstatus_to_werror(status));
3203 if (!W_ERROR_IS_OK(werr)) {
3204 errcode = W_ERROR_V(werr);
3208 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3209 * and NERR_DestNotFound if share did not exist */
3211 errcode = NERR_Success;
3214 case 81: /* delete */
3215 command = SPOOLSS_JOB_CONTROL_DELETE;
3217 case 82: /* pause */
3218 command = SPOOLSS_JOB_CONTROL_PAUSE;
3220 case 83: /* resume */
3221 command = SPOOLSS_JOB_CONTROL_RESUME;
3224 errcode = NERR_notsupported;
3228 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3231 NULL, /* unique ptr ctr */
3234 if (!NT_STATUS_IS_OK(status)) {
3235 errcode = W_ERROR_V(ntstatus_to_werror(status));
3238 if (!W_ERROR_IS_OK(werr)) {
3239 errcode = W_ERROR_V(werr);
3244 if (cli && is_valid_policy_hnd(&handle)) {
3245 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3248 SSVAL(*rparam,0,errcode);
3249 SSVAL(*rparam,2,0); /* converter word */
3254 /****************************************************************************
3255 Purge a print queue - or pause or resume it.
3256 ****************************************************************************/
3258 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
3259 char *param, int tpscnt,
3260 char *data, int tdscnt,
3261 int mdrcnt,int mprcnt,
3262 char **rdata,char **rparam,
3263 int *rdata_len,int *rparam_len)
3265 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3266 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3267 char *str2 = skip_string(param,tpscnt,str1);
3268 char *QueueName = skip_string(param,tpscnt,str2);
3269 int errcode = NERR_notsupported;
3270 WERROR werr = WERR_OK;
3273 TALLOC_CTX *mem_ctx = talloc_tos();
3274 struct rpc_pipe_client *cli = NULL;
3275 struct policy_handle handle;
3276 struct spoolss_SetPrinterInfoCtr info_ctr;
3277 struct spoolss_DevmodeContainer devmode_ctr;
3278 struct sec_desc_buf secdesc_ctr;
3279 enum spoolss_PrinterControl command;
3281 if (!str1 || !str2 || !QueueName) {
3285 /* check it's a supported varient */
3286 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3290 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3296 if (skip_string(param,tpscnt,QueueName) == NULL) {
3300 ZERO_STRUCT(handle);
3302 status = rpc_connect_spoolss_pipe(conn, &cli);
3303 if (!NT_STATUS_IS_OK(status)) {
3304 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3305 nt_errstr(status)));
3306 errcode = W_ERROR_V(ntstatus_to_werror(status));
3310 ZERO_STRUCT(devmode_ctr);
3312 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3316 SEC_FLAG_MAXIMUM_ALLOWED,
3319 if (!NT_STATUS_IS_OK(status)) {
3320 errcode = W_ERROR_V(ntstatus_to_werror(status));
3323 if (!W_ERROR_IS_OK(werr)) {
3324 errcode = W_ERROR_V(werr);
3329 case 74: /* Pause queue */
3330 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3332 case 75: /* Resume queue */
3333 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3335 case 103: /* Purge */
3336 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3339 werr = WERR_NOT_SUPPORTED;
3343 if (!W_ERROR_IS_OK(werr)) {
3344 errcode = W_ERROR_V(werr);
3348 ZERO_STRUCT(info_ctr);
3349 ZERO_STRUCT(secdesc_ctr);
3351 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
3358 if (!NT_STATUS_IS_OK(status)) {
3359 errcode = W_ERROR_V(ntstatus_to_werror(status));
3362 if (!W_ERROR_IS_OK(werr)) {
3363 errcode = W_ERROR_V(werr);
3367 errcode = W_ERROR_V(werr);
3371 if (cli && is_valid_policy_hnd(&handle)) {
3372 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3375 SSVAL(*rparam,0,errcode);
3376 SSVAL(*rparam,2,0); /* converter word */
3381 /****************************************************************************
3382 set the property of a print job (undocumented?)
3383 ? function = 0xb -> set name of print job
3384 ? function = 0x6 -> move print job up/down
3385 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3386 or <WWsTP> <WB21BB16B10zWWzDDz>
3387 ****************************************************************************/
3389 static int check_printjob_info(struct pack_desc* desc,
3390 int uLevel, char* id)
3392 desc->subformat = NULL;
3394 case 0: desc->format = "W"; break;
3395 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3396 case 2: desc->format = "WWzWWDDzz"; break;
3397 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3398 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3400 DEBUG(0,("check_printjob_info: invalid level %d\n",
3404 if (id == NULL || strcmp(desc->format,id) != 0) {
3405 DEBUG(0,("check_printjob_info: invalid format %s\n",
3406 id ? id : "<NULL>" ));
3412 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
3413 char *param, int tpscnt,
3414 char *data, int tdscnt,
3415 int mdrcnt,int mprcnt,
3416 char **rdata,char **rparam,
3417 int *rdata_len,int *rparam_len)
3419 struct pack_desc desc;
3420 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3421 char *str2 = skip_string(param,tpscnt,str1);
3422 char *p = skip_string(param,tpscnt,str2);
3425 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3426 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3429 TALLOC_CTX *mem_ctx = talloc_tos();
3432 struct rpc_pipe_client *cli = NULL;
3433 struct policy_handle handle;
3434 struct spoolss_DevmodeContainer devmode_ctr;
3435 struct spoolss_JobInfoContainer ctr;
3436 union spoolss_JobInfo info;
3437 struct spoolss_SetJobInfo1 info1;
3439 if (!str1 || !str2 || !p) {
3443 * We use 1 here not 2 as we're checking
3444 * the last byte we want to access is safe.
3446 if (!is_offset_safe(param,tpscnt,p,1)) {
3449 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3452 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3459 /* check it's a supported varient */
3460 if ((strcmp(str1,"WWsTP")) ||
3461 (!check_printjob_info(&desc,uLevel,str2)))
3464 errcode = NERR_notsupported;
3468 /* change print job name, data gives the name */
3474 ZERO_STRUCT(handle);
3476 status = rpc_connect_spoolss_pipe(conn, &cli);
3477 if (!NT_STATUS_IS_OK(status)) {
3478 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3479 nt_errstr(status)));
3480 errcode = W_ERROR_V(ntstatus_to_werror(status));
3484 ZERO_STRUCT(devmode_ctr);
3486 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3493 if (!NT_STATUS_IS_OK(status)) {
3494 errcode = W_ERROR_V(ntstatus_to_werror(status));
3497 if (!W_ERROR_IS_OK(werr)) {
3498 errcode = W_ERROR_V(werr);
3502 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3508 if (!W_ERROR_IS_OK(werr)) {
3509 errcode = W_ERROR_V(werr);
3515 info1.job_id = info.info1.job_id;
3516 info1.printer_name = info.info1.printer_name;
3517 info1.user_name = info.info1.user_name;
3518 info1.document_name = data;
3519 info1.data_type = info.info1.data_type;
3520 info1.text_status = info.info1.text_status;
3521 info1.status = info.info1.status;
3522 info1.priority = info.info1.priority;
3523 info1.position = info.info1.position;
3524 info1.total_pages = info.info1.total_pages;
3525 info1.pages_printed = info.info1.pages_printed;
3526 info1.submitted = info.info1.submitted;
3529 ctr.info.info1 = &info1;
3531 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3537 if (!NT_STATUS_IS_OK(status)) {
3538 errcode = W_ERROR_V(ntstatus_to_werror(status));
3541 if (!W_ERROR_IS_OK(werr)) {
3542 errcode = W_ERROR_V(werr);
3546 errcode = NERR_Success;
3549 if (cli && is_valid_policy_hnd(&handle)) {
3550 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3553 SSVALS(*rparam,0,errcode);
3554 SSVAL(*rparam,2,0); /* converter word */
3560 /****************************************************************************
3561 Get info about the server.
3562 ****************************************************************************/
3564 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3565 char *param, int tpscnt,
3566 char *data, int tdscnt,
3567 int mdrcnt,int mprcnt,
3568 char **rdata,char **rparam,
3569 int *rdata_len,int *rparam_len)
3571 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3572 char *str2 = skip_string(param,tpscnt,str1);
3573 char *p = skip_string(param,tpscnt,str2);
3574 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3580 TALLOC_CTX *mem_ctx = talloc_tos();
3581 struct rpc_pipe_client *cli = NULL;
3582 union srvsvc_NetSrvInfo info;
3585 if (!str1 || !str2 || !p) {
3589 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3591 /* check it's a supported varient */
3592 if (!prefix_ok(str1,"WrLh")) {
3598 if (strcmp(str2,"B16") != 0) {
3604 if (strcmp(str2,"B16BBDz") != 0) {
3610 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3616 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3622 if (strcmp(str2,"DN") != 0) {
3628 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3637 *rdata_len = mdrcnt;
3638 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3644 p2 = p + struct_len;
3646 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
3647 rpc_srvsvc_dispatch, conn->server_info,
3649 if (!NT_STATUS_IS_OK(status)) {
3650 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3651 nt_errstr(status)));
3652 errcode = W_ERROR_V(ntstatus_to_werror(status));
3656 status = rpccli_srvsvc_NetSrvGetInfo(cli, mem_ctx,
3661 if (!NT_STATUS_IS_OK(status)) {
3662 errcode = W_ERROR_V(ntstatus_to_werror(status));
3665 if (!W_ERROR_IS_OK(werr)) {
3666 errcode = W_ERROR_V(werr);
3670 if (info.info101 == NULL) {
3671 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3676 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3677 STR_ASCII|STR_UPPER|STR_TERMINATE);
3681 SCVAL(p,0,info.info101->version_major);
3682 SCVAL(p,1,info.info101->version_minor);
3683 SIVAL(p,2,info.info101->server_type);
3685 if (mdrcnt == struct_len) {
3688 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3689 if (mdrcnt - struct_len <= 0) {
3693 info.info101->comment,
3694 MIN(mdrcnt - struct_len,
3695 MAX_SERVER_STRING_LENGTH),
3697 p2 = skip_string(*rdata,*rdata_len,p2);
3705 return False; /* not yet implemented */
3708 errcode = NERR_Success;
3712 *rdata_len = PTR_DIFF(p2,*rdata);
3715 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3719 SSVAL(*rparam,0,errcode);
3720 SSVAL(*rparam,2,0); /* converter word */
3721 SSVAL(*rparam,4,*rdata_len);
3726 /****************************************************************************
3727 Get info about the server.
3728 ****************************************************************************/
3730 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3731 char *param, int tpscnt,
3732 char *data, int tdscnt,
3733 int mdrcnt,int mprcnt,
3734 char **rdata,char **rparam,
3735 int *rdata_len,int *rparam_len)
3737 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3738 char *str2 = skip_string(param,tpscnt,str1);
3739 char *p = skip_string(param,tpscnt,str2);
3742 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3744 if (!str1 || !str2 || !p) {
3748 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3751 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3756 /* check it's a supported varient */
3757 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3761 *rdata_len = mdrcnt + 1024;
3762 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3767 SSVAL(*rparam,0,NERR_Success);
3768 SSVAL(*rparam,2,0); /* converter word */
3771 endp = *rdata + *rdata_len;
3773 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3778 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3779 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3781 p2 = skip_string(*rdata,*rdata_len,p2);
3787 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3788 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3789 p2 = skip_string(*rdata,*rdata_len,p2);
3795 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3796 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3798 p2 = skip_string(*rdata,*rdata_len,p2);
3804 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3805 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3808 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3809 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3810 p2 = skip_string(*rdata,*rdata_len,p2);
3816 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3817 strlcpy(p2,"",PTR_DIFF(endp,p2));
3818 p2 = skip_string(*rdata,*rdata_len,p2);
3824 *rdata_len = PTR_DIFF(p2,*rdata);
3826 SSVAL(*rparam,4,*rdata_len);
3831 /****************************************************************************
3832 get info about a user
3834 struct user_info_11 {
3835 char usri11_name[21]; 0-20
3837 char *usri11_comment; 22-25
3838 char *usri11_usr_comment; 26-29
3839 unsigned short usri11_priv; 30-31
3840 unsigned long usri11_auth_flags; 32-35
3841 long usri11_password_age; 36-39
3842 char *usri11_homedir; 40-43
3843 char *usri11_parms; 44-47
3844 long usri11_last_logon; 48-51
3845 long usri11_last_logoff; 52-55
3846 unsigned short usri11_bad_pw_count; 56-57
3847 unsigned short usri11_num_logons; 58-59
3848 char *usri11_logon_server; 60-63
3849 unsigned short usri11_country_code; 64-65
3850 char *usri11_workstations; 66-69
3851 unsigned long usri11_max_storage; 70-73
3852 unsigned short usri11_units_per_week; 74-75
3853 unsigned char *usri11_logon_hours; 76-79
3854 unsigned short usri11_code_page; 80-81
3859 usri11_name specifies the user name for which information is retrieved
3861 usri11_pad aligns the next data structure element to a word boundary
3863 usri11_comment is a null terminated ASCII comment
3865 usri11_user_comment is a null terminated ASCII comment about the user
3867 usri11_priv specifies the level of the privilege assigned to the user.
3868 The possible values are:
3870 Name Value Description
3871 USER_PRIV_GUEST 0 Guest privilege
3872 USER_PRIV_USER 1 User privilege
3873 USER_PRV_ADMIN 2 Administrator privilege
3875 usri11_auth_flags specifies the account operator privileges. The
3876 possible values are:
3878 Name Value Description
3879 AF_OP_PRINT 0 Print operator
3882 Leach, Naik [Page 28]
3886 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3889 AF_OP_COMM 1 Communications operator
3890 AF_OP_SERVER 2 Server operator
3891 AF_OP_ACCOUNTS 3 Accounts operator
3894 usri11_password_age specifies how many seconds have elapsed since the
3895 password was last changed.
3897 usri11_home_dir points to a null terminated ASCII string that contains
3898 the path name of the user's home directory.
3900 usri11_parms points to a null terminated ASCII string that is set
3901 aside for use by applications.
3903 usri11_last_logon specifies the time when the user last logged on.
3904 This value is stored as the number of seconds elapsed since
3905 00:00:00, January 1, 1970.
3907 usri11_last_logoff specifies the time when the user last logged off.
3908 This value is stored as the number of seconds elapsed since
3909 00:00:00, January 1, 1970. A value of 0 means the last logoff
3912 usri11_bad_pw_count specifies the number of incorrect passwords
3913 entered since the last successful logon.
3915 usri11_log1_num_logons specifies the number of times this user has
3916 logged on. A value of -1 means the number of logons is unknown.
3918 usri11_logon_server points to a null terminated ASCII string that
3919 contains the name of the server to which logon requests are sent.
3920 A null string indicates logon requests should be sent to the
3923 usri11_country_code specifies the country code for the user's language
3926 usri11_workstations points to a null terminated ASCII string that
3927 contains the names of workstations the user may log on from.
3928 There may be up to 8 workstations, with the names separated by
3929 commas. A null strings indicates there are no restrictions.
3931 usri11_max_storage specifies the maximum amount of disk space the user
3932 can occupy. A value of 0xffffffff indicates there are no
3935 usri11_units_per_week specifies the equal number of time units into
3936 which a week is divided. This value must be equal to 168.
3938 usri11_logon_hours points to a 21 byte (168 bits) string that
3939 specifies the time during which the user can log on. Each bit
3940 represents one unique hour in a week. The first bit (bit 0, word
3941 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3945 Leach, Naik [Page 29]
3949 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3952 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3953 are no restrictions.
3955 usri11_code_page specifies the code page for the user's language of
3958 All of the pointers in this data structure need to be treated
3959 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3960 to be ignored. The converter word returned in the parameters section
3961 needs to be subtracted from the lower 16 bits to calculate an offset
3962 into the return buffer where this ASCII string resides.
3964 There is no auxiliary data in the response.
3966 ****************************************************************************/
3968 #define usri11_name 0
3969 #define usri11_pad 21
3970 #define usri11_comment 22
3971 #define usri11_usr_comment 26
3972 #define usri11_full_name 30
3973 #define usri11_priv 34
3974 #define usri11_auth_flags 36
3975 #define usri11_password_age 40
3976 #define usri11_homedir 44
3977 #define usri11_parms 48
3978 #define usri11_last_logon 52
3979 #define usri11_last_logoff 56
3980 #define usri11_bad_pw_count 60
3981 #define usri11_num_logons 62
3982 #define usri11_logon_server 64
3983 #define usri11_country_code 68
3984 #define usri11_workstations 70
3985 #define usri11_max_storage 74
3986 #define usri11_units_per_week 78
3987 #define usri11_logon_hours 80
3988 #define usri11_code_page 84
3989 #define usri11_end 86
3991 #define USER_PRIV_GUEST 0
3992 #define USER_PRIV_USER 1
3993 #define USER_PRIV_ADMIN 2
3995 #define AF_OP_PRINT 0
3996 #define AF_OP_COMM 1
3997 #define AF_OP_SERVER 2
3998 #define AF_OP_ACCOUNTS 3
4001 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
4002 char *param, int tpscnt,
4003 char *data, int tdscnt,
4004 int mdrcnt,int mprcnt,
4005 char **rdata,char **rparam,
4006 int *rdata_len,int *rparam_len)
4008 struct smbd_server_connection *sconn = smbd_server_conn;
4009 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4010 char *str2 = skip_string(param,tpscnt,str1);
4011 char *UserName = skip_string(param,tpscnt,str2);
4012 char *p = skip_string(param,tpscnt,UserName);
4013 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4016 const char *level_string;
4018 /* get NIS home of a previously validated user - simeon */
4019 /* With share level security vuid will always be zero.
4020 Don't depend on vuser being non-null !!. JRA */
4021 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4023 DEBUG(3,(" Username of UID %d is %s\n",
4024 (int)vuser->server_info->utok.uid,
4025 vuser->server_info->unix_name));
4028 if (!str1 || !str2 || !UserName || !p) {
4033 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4038 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4040 /* check it's a supported variant */
4041 if (strcmp(str1,"zWrLh") != 0) {
4045 case 0: level_string = "B21"; break;
4046 case 1: level_string = "B21BB16DWzzWz"; break;
4047 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4048 case 10: level_string = "B21Bzzz"; break;
4049 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4050 default: return False;
4053 if (strcmp(level_string,str2) != 0) {
4057 *rdata_len = mdrcnt + 1024;
4058 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4063 SSVAL(*rparam,0,NERR_Success);
4064 SSVAL(*rparam,2,0); /* converter word */
4067 endp = *rdata + *rdata_len;
4068 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4074 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4077 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4082 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4083 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4084 p2 = skip_string(*rdata,*rdata_len,p2);
4089 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4090 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4091 p2 = skip_string(*rdata,*rdata_len,p2);
4096 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4097 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4098 strlcpy(p2,((vuser != NULL)
4099 ? pdb_get_fullname(vuser->server_info->sam_account)
4100 : UserName),PTR_DIFF(endp,p2));
4101 p2 = skip_string(*rdata,*rdata_len,p2);
4108 const char *homedir = "";
4109 if (vuser != NULL) {
4110 homedir = pdb_get_homedir(
4111 vuser->server_info->sam_account);
4113 /* modelled after NTAS 3.51 reply */
4114 SSVAL(p,usri11_priv,
4115 (get_current_uid(conn) == sec_initial_uid())?
4116 USER_PRIV_ADMIN:USER_PRIV_USER);
4117 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4118 SIVALS(p,usri11_password_age,-1); /* password age */
4119 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4120 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4121 p2 = skip_string(*rdata,*rdata_len,p2);
4125 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4126 strlcpy(p2,"",PTR_DIFF(endp,p2));
4127 p2 = skip_string(*rdata,*rdata_len,p2);
4131 SIVAL(p,usri11_last_logon,0); /* last logon */
4132 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4133 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4134 SSVALS(p,usri11_num_logons,-1); /* num logons */
4135 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4136 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4137 p2 = skip_string(*rdata,*rdata_len,p2);
4141 SSVAL(p,usri11_country_code,0); /* country code */
4143 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4144 strlcpy(p2,"",PTR_DIFF(endp,p2));
4145 p2 = skip_string(*rdata,*rdata_len,p2);
4150 SIVALS(p,usri11_max_storage,-1); /* max storage */
4151 SSVAL(p,usri11_units_per_week,168); /* units per week */
4152 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4154 /* a simple way to get logon hours at all times. */
4156 SCVAL(p2,21,0); /* fix zero termination */
4157 p2 = skip_string(*rdata,*rdata_len,p2);
4162 SSVAL(p,usri11_code_page,0); /* code page */
4165 if (uLevel == 1 || uLevel == 2) {
4166 memset(p+22,' ',16); /* password */
4167 SIVALS(p,38,-1); /* password age */
4169 (get_current_uid(conn) == sec_initial_uid())?
4170 USER_PRIV_ADMIN:USER_PRIV_USER);
4171 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4172 strlcpy(p2, vuser ? pdb_get_homedir(
4173 vuser->server_info->sam_account) : "",
4175 p2 = skip_string(*rdata,*rdata_len,p2);
4179 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4181 SSVAL(p,52,0); /* flags */
4182 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4183 strlcpy(p2, vuser ? pdb_get_logon_script(
4184 vuser->server_info->sam_account) : "",
4186 p2 = skip_string(*rdata,*rdata_len,p2);
4191 SIVAL(p,60,0); /* auth_flags */
4192 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
4193 strlcpy(p2,((vuser != NULL)
4194 ? pdb_get_fullname(vuser->server_info->sam_account)
4195 : UserName),PTR_DIFF(endp,p2));
4196 p2 = skip_string(*rdata,*rdata_len,p2);
4200 SIVAL(p,68,0); /* urs_comment */
4201 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
4202 strlcpy(p2,"",PTR_DIFF(endp,p2));
4203 p2 = skip_string(*rdata,*rdata_len,p2);
4207 SIVAL(p,76,0); /* workstations */
4208 SIVAL(p,80,0); /* last_logon */
4209 SIVAL(p,84,0); /* last_logoff */
4210 SIVALS(p,88,-1); /* acct_expires */
4211 SIVALS(p,92,-1); /* max_storage */
4212 SSVAL(p,96,168); /* units_per_week */
4213 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
4216 SSVALS(p,102,-1); /* bad_pw_count */
4217 SSVALS(p,104,-1); /* num_logons */
4218 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
4220 TALLOC_CTX *ctx = talloc_tos();
4221 int space_rem = *rdata_len - (p2 - *rdata);
4224 if (space_rem <= 0) {
4227 tmp = talloc_strdup(ctx, "\\\\%L");
4231 tmp = talloc_sub_basic(ctx,
4244 p2 = skip_string(*rdata,*rdata_len,p2);
4248 SSVAL(p,110,49); /* country_code */
4249 SSVAL(p,112,860); /* code page */
4253 *rdata_len = PTR_DIFF(p2,*rdata);
4255 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4260 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
4261 char *param, int tpscnt,
4262 char *data, int tdscnt,
4263 int mdrcnt,int mprcnt,
4264 char **rdata,char **rparam,
4265 int *rdata_len,int *rparam_len)
4267 struct smbd_server_connection *sconn = smbd_server_conn;
4268 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4269 char *str2 = skip_string(param,tpscnt,str1);
4270 char *p = skip_string(param,tpscnt,str2);
4272 struct pack_desc desc;
4274 /* With share level security vuid will always be zero.
4275 Don't depend on vuser being non-null !!. JRA */
4276 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4278 if (!str1 || !str2 || !p) {
4283 DEBUG(3,(" Username of UID %d is %s\n",
4284 (int)vuser->server_info->utok.uid,
4285 vuser->server_info->unix_name));
4288 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4289 name = get_safe_str_ptr(param,tpscnt,p,2);
4294 memset((char *)&desc,'\0',sizeof(desc));
4296 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4298 /* check it's a supported varient */
4299 if (strcmp(str1,"OOWb54WrLh") != 0) {
4302 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4306 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4313 desc.buflen = mdrcnt;
4314 desc.subformat = NULL;
4317 if (init_package(&desc,1,0)) {
4318 PACKI(&desc,"W",0); /* code */
4319 PACKS(&desc,"B21",name); /* eff. name */
4320 PACKS(&desc,"B",""); /* pad */
4322 (get_current_uid(conn) == sec_initial_uid())?
4323 USER_PRIV_ADMIN:USER_PRIV_USER);
4324 PACKI(&desc,"D",0); /* auth flags XXX */
4325 PACKI(&desc,"W",0); /* num logons */
4326 PACKI(&desc,"W",0); /* bad pw count */
4327 PACKI(&desc,"D",0); /* last logon */
4328 PACKI(&desc,"D",-1); /* last logoff */
4329 PACKI(&desc,"D",-1); /* logoff time */
4330 PACKI(&desc,"D",-1); /* kickoff time */
4331 PACKI(&desc,"D",0); /* password age */
4332 PACKI(&desc,"D",0); /* password can change */
4333 PACKI(&desc,"D",-1); /* password must change */
4337 fstrcpy(mypath,"\\\\");
4338 fstrcat(mypath,get_local_machine_name());
4340 PACKS(&desc,"z",mypath); /* computer */
4343 PACKS(&desc,"z",lp_workgroup());/* domain */
4344 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
4345 vuser->server_info->sam_account) : ""); /* script path */
4346 PACKI(&desc,"D",0x00000000); /* reserved */
4349 *rdata_len = desc.usedlen;
4351 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4355 SSVALS(*rparam,0,desc.errcode);
4357 SSVAL(*rparam,4,desc.neededlen);
4359 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4364 /****************************************************************************
4365 api_WAccessGetUserPerms
4366 ****************************************************************************/
4368 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
4369 char *param, int tpscnt,
4370 char *data, int tdscnt,
4371 int mdrcnt,int mprcnt,
4372 char **rdata,char **rparam,
4373 int *rdata_len,int *rparam_len)
4375 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4376 char *str2 = skip_string(param,tpscnt,str1);
4377 char *user = skip_string(param,tpscnt,str2);
4378 char *resource = skip_string(param,tpscnt,user);
4380 if (!str1 || !str2 || !user || !resource) {
4384 if (skip_string(param,tpscnt,resource) == NULL) {
4387 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4389 /* check it's a supported varient */
4390 if (strcmp(str1,"zzh") != 0) {
4393 if (strcmp(str2,"") != 0) {
4398 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4402 SSVALS(*rparam,0,0); /* errorcode */
4403 SSVAL(*rparam,2,0); /* converter word */
4404 SSVAL(*rparam,4,0x7f); /* permission flags */
4409 /****************************************************************************
4410 api_WPrintJobEnumerate
4411 ****************************************************************************/
4413 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
4414 char *param, int tpscnt,
4415 char *data, int tdscnt,
4416 int mdrcnt,int mprcnt,
4417 char **rdata,char **rparam,
4418 int *rdata_len,int *rparam_len)
4420 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4421 char *str2 = skip_string(param,tpscnt,str1);
4422 char *p = skip_string(param,tpscnt,str2);
4426 struct pack_desc desc;
4429 TALLOC_CTX *mem_ctx = talloc_tos();
4432 struct rpc_pipe_client *cli = NULL;
4433 struct policy_handle handle;
4434 struct spoolss_DevmodeContainer devmode_ctr;
4435 union spoolss_JobInfo info;
4437 if (!str1 || !str2 || !p) {
4441 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4443 memset((char *)&desc,'\0',sizeof(desc));
4444 memset((char *)&status,'\0',sizeof(status));
4446 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4448 /* check it's a supported varient */
4449 if (strcmp(str1,"WWrLh") != 0) {
4452 if (!check_printjob_info(&desc,uLevel,str2)) {
4456 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4460 ZERO_STRUCT(handle);
4462 status = rpc_connect_spoolss_pipe(conn, &cli);
4463 if (!NT_STATUS_IS_OK(status)) {
4464 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4465 nt_errstr(status)));
4466 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4470 ZERO_STRUCT(devmode_ctr);
4472 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4479 if (!NT_STATUS_IS_OK(status)) {
4480 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4483 if (!W_ERROR_IS_OK(werr)) {
4484 desc.errcode = W_ERROR_V(werr);
4488 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4494 if (!W_ERROR_IS_OK(werr)) {
4495 desc.errcode = W_ERROR_V(werr);
4500 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4505 desc.buflen = mdrcnt;
4508 * Don't return data but need to get correct length
4509 * init_package will return wrong size if buflen=0
4511 desc.buflen = getlen(desc.format);
4512 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4515 if (init_package(&desc,1,0)) {
4516 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4517 *rdata_len = desc.usedlen;
4519 desc.errcode = NERR_JobNotFound;
4523 if (cli && is_valid_policy_hnd(&handle)) {
4524 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4528 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4532 SSVALS(*rparam,0,desc.errcode);
4534 SSVAL(*rparam,4,desc.neededlen);
4538 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4543 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
4544 char *param, int tpscnt,
4545 char *data, int tdscnt,
4546 int mdrcnt,int mprcnt,
4547 char **rdata,char **rparam,
4548 int *rdata_len,int *rparam_len)
4550 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4551 char *str2 = skip_string(param,tpscnt,str1);
4552 char *p = skip_string(param,tpscnt,str2);
4556 struct pack_desc desc;
4558 TALLOC_CTX *mem_ctx = talloc_tos();
4561 struct rpc_pipe_client *cli = NULL;
4562 struct policy_handle handle;
4563 struct spoolss_DevmodeContainer devmode_ctr;
4565 union spoolss_JobInfo *info;
4567 if (!str1 || !str2 || !p) {
4571 memset((char *)&desc,'\0',sizeof(desc));
4573 p = skip_string(param,tpscnt,p);
4577 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4579 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4581 /* check it's a supported variant */
4582 if (strcmp(str1,"zWrLeh") != 0) {
4587 return False; /* defined only for uLevel 0,1,2 */
4590 if (!check_printjob_info(&desc,uLevel,str2)) {
4594 ZERO_STRUCT(handle);
4596 status = rpc_connect_spoolss_pipe(conn, &cli);
4597 if (!NT_STATUS_IS_OK(status)) {
4598 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4599 nt_errstr(status)));
4600 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4604 ZERO_STRUCT(devmode_ctr);
4606 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4610 SEC_FLAG_MAXIMUM_ALLOWED,
4613 if (!NT_STATUS_IS_OK(status)) {
4614 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4617 if (!W_ERROR_IS_OK(werr)) {
4618 desc.errcode = W_ERROR_V(werr);
4622 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4630 if (!W_ERROR_IS_OK(werr)) {
4631 desc.errcode = W_ERROR_V(werr);
4636 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4642 desc.buflen = mdrcnt;
4644 if (init_package(&desc,count,0)) {
4646 for (i = 0; i < count; i++) {
4647 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4648 if (desc.errcode == NERR_Success) {
4654 if (cli && is_valid_policy_hnd(&handle)) {
4655 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4658 *rdata_len = desc.usedlen;
4661 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4665 SSVALS(*rparam,0,desc.errcode);
4667 SSVAL(*rparam,4,succnt);
4668 SSVAL(*rparam,6,count);
4670 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4675 static int check_printdest_info(struct pack_desc* desc,
4676 int uLevel, char* id)
4678 desc->subformat = NULL;
4681 desc->format = "B9";
4684 desc->format = "B9B21WWzW";
4690 desc->format = "zzzWWzzzWW";
4693 DEBUG(0,("check_printdest_info: invalid level %d\n",
4697 if (id == NULL || strcmp(desc->format,id) != 0) {
4698 DEBUG(0,("check_printdest_info: invalid string %s\n",
4699 id ? id : "<NULL>" ));
4705 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
4706 struct pack_desc* desc)
4710 strncpy(buf, info2->printername, sizeof(buf)-1);
4711 buf[sizeof(buf)-1] = 0;
4715 PACKS(desc,"B9",buf); /* szName */
4717 PACKS(desc,"B21",""); /* szUserName */
4718 PACKI(desc,"W",0); /* uJobId */
4719 PACKI(desc,"W",0); /* fsStatus */
4720 PACKS(desc,"z",""); /* pszStatus */
4721 PACKI(desc,"W",0); /* time */
4725 if (uLevel == 2 || uLevel == 3) {
4726 PACKS(desc,"z",buf); /* pszPrinterName */
4728 PACKS(desc,"z",""); /* pszUserName */
4729 PACKS(desc,"z",""); /* pszLogAddr */
4730 PACKI(desc,"W",0); /* uJobId */
4731 PACKI(desc,"W",0); /* fsStatus */
4732 PACKS(desc,"z",""); /* pszStatus */
4733 PACKS(desc,"z",""); /* pszComment */
4734 PACKS(desc,"z","NULL"); /* pszDrivers */
4735 PACKI(desc,"W",0); /* time */
4736 PACKI(desc,"W",0); /* pad1 */
4741 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4742 char *param, int tpscnt,
4743 char *data, int tdscnt,
4744 int mdrcnt,int mprcnt,
4745 char **rdata,char **rparam,
4746 int *rdata_len,int *rparam_len)
4748 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4749 char *str2 = skip_string(param,tpscnt,str1);
4750 char *p = skip_string(param,tpscnt,str2);
4751 char* PrinterName = p;
4753 struct pack_desc desc;
4756 TALLOC_CTX *mem_ctx = talloc_tos();
4759 struct rpc_pipe_client *cli = NULL;
4760 struct policy_handle handle;
4761 struct spoolss_DevmodeContainer devmode_ctr;
4762 union spoolss_PrinterInfo info;
4764 if (!str1 || !str2 || !p) {
4768 memset((char *)&desc,'\0',sizeof(desc));
4770 p = skip_string(param,tpscnt,p);
4774 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4776 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4778 /* check it's a supported varient */
4779 if (strcmp(str1,"zWrLh") != 0) {
4782 if (!check_printdest_info(&desc,uLevel,str2)) {
4786 ZERO_STRUCT(handle);
4788 status = rpc_connect_spoolss_pipe(conn, &cli);
4789 if (!NT_STATUS_IS_OK(status)) {
4790 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4791 nt_errstr(status)));
4792 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4796 ZERO_STRUCT(devmode_ctr);
4798 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4802 SEC_FLAG_MAXIMUM_ALLOWED,
4805 if (!NT_STATUS_IS_OK(status)) {
4807 desc.errcode = NERR_DestNotFound;
4811 if (!W_ERROR_IS_OK(werr)) {
4813 desc.errcode = NERR_DestNotFound;
4818 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
4823 if (!W_ERROR_IS_OK(werr)) {
4825 desc.errcode = NERR_DestNotFound;
4831 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4836 desc.buflen = mdrcnt;
4839 * Don't return data but need to get correct length
4840 * init_package will return wrong size if buflen=0
4842 desc.buflen = getlen(desc.format);
4843 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4845 if (init_package(&desc,1,0)) {
4846 fill_printdest_info(&info.info2, uLevel,&desc);
4850 if (cli && is_valid_policy_hnd(&handle)) {
4851 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4854 *rdata_len = desc.usedlen;
4857 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4861 SSVALS(*rparam,0,desc.errcode);
4863 SSVAL(*rparam,4,desc.neededlen);
4865 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4871 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4872 char *param, int tpscnt,
4873 char *data, int tdscnt,
4874 int mdrcnt,int mprcnt,
4875 char **rdata,char **rparam,
4876 int *rdata_len,int *rparam_len)
4878 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4879 char *str2 = skip_string(param,tpscnt,str1);
4880 char *p = skip_string(param,tpscnt,str2);
4884 struct pack_desc desc;
4886 TALLOC_CTX *mem_ctx = talloc_tos();
4889 struct rpc_pipe_client *cli = NULL;
4890 union spoolss_PrinterInfo *info;
4893 if (!str1 || !str2 || !p) {
4897 memset((char *)&desc,'\0',sizeof(desc));
4899 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4901 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4903 /* check it's a supported varient */
4904 if (strcmp(str1,"WrLeh") != 0) {
4907 if (!check_printdest_info(&desc,uLevel,str2)) {
4913 status = rpc_connect_spoolss_pipe(conn, &cli);
4914 if (!NT_STATUS_IS_OK(status)) {
4915 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
4916 nt_errstr(status)));
4917 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4921 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
4923 cli->srv_name_slash,
4928 if (!W_ERROR_IS_OK(werr)) {
4929 desc.errcode = W_ERROR_V(werr);
4931 desc.errcode = NERR_DestNotFound;
4939 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4946 desc.buflen = mdrcnt;
4947 if (init_package(&desc,queuecnt,0)) {
4950 for (i = 0; i < count; i++) {
4951 fill_printdest_info(&info[i].info2, uLevel,&desc);
4953 if (desc.errcode == NERR_Success) {
4959 *rdata_len = desc.usedlen;
4962 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4966 SSVALS(*rparam,0,desc.errcode);
4968 SSVAL(*rparam,4,succnt);
4969 SSVAL(*rparam,6,queuecnt);
4971 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4976 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4977 char *param, int tpscnt,
4978 char *data, int tdscnt,
4979 int mdrcnt,int mprcnt,
4980 char **rdata,char **rparam,
4981 int *rdata_len,int *rparam_len)
4983 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4984 char *str2 = skip_string(param,tpscnt,str1);
4985 char *p = skip_string(param,tpscnt,str2);
4988 struct pack_desc desc;
4990 if (!str1 || !str2 || !p) {
4994 memset((char *)&desc,'\0',sizeof(desc));
4996 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4998 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5000 /* check it's a supported varient */
5001 if (strcmp(str1,"WrLeh") != 0) {
5004 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5009 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5015 desc.buflen = mdrcnt;
5016 if (init_package(&desc,1,0)) {
5017 PACKS(&desc,"B41","NULL");
5020 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5022 *rdata_len = desc.usedlen;
5025 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5029 SSVALS(*rparam,0,desc.errcode);
5031 SSVAL(*rparam,4,succnt);
5034 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5039 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
5040 char *param, int tpscnt,
5041 char *data, int tdscnt,
5042 int mdrcnt,int mprcnt,
5043 char **rdata,char **rparam,
5044 int *rdata_len,int *rparam_len)
5046 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5047 char *str2 = skip_string(param,tpscnt,str1);
5048 char *p = skip_string(param,tpscnt,str2);
5051 struct pack_desc desc;
5053 if (!str1 || !str2 || !p) {
5056 memset((char *)&desc,'\0',sizeof(desc));
5058 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5060 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5062 /* check it's a supported varient */
5063 if (strcmp(str1,"WrLeh") != 0) {
5066 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5071 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5077 desc.buflen = mdrcnt;
5079 if (init_package(&desc,1,0)) {
5080 PACKS(&desc,"B13","lpd");
5083 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5085 *rdata_len = desc.usedlen;
5088 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5092 SSVALS(*rparam,0,desc.errcode);
5094 SSVAL(*rparam,4,succnt);
5097 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5102 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
5103 char *param, int tpscnt,
5104 char *data, int tdscnt,
5105 int mdrcnt,int mprcnt,
5106 char **rdata,char **rparam,
5107 int *rdata_len,int *rparam_len)
5109 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5110 char *str2 = skip_string(param,tpscnt,str1);
5111 char *p = skip_string(param,tpscnt,str2);
5114 struct pack_desc desc;
5116 if (!str1 || !str2 || !p) {
5120 memset((char *)&desc,'\0',sizeof(desc));
5122 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5124 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5126 /* check it's a supported varient */
5127 if (strcmp(str1,"WrLeh") != 0) {
5130 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5135 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5140 memset((char *)&desc,'\0',sizeof(desc));
5142 desc.buflen = mdrcnt;
5144 if (init_package(&desc,1,0)) {
5145 PACKS(&desc,"B13","lp0");
5148 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5150 *rdata_len = desc.usedlen;
5153 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5157 SSVALS(*rparam,0,desc.errcode);
5159 SSVAL(*rparam,4,succnt);
5162 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5167 /****************************************************************************
5169 ****************************************************************************/
5171 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
5172 char *param, int tpscnt,
5173 char *data, int tdscnt,
5174 int mdrcnt,int mprcnt,
5175 char **rdata,char **rparam,
5176 int *rdata_len,int *rparam_len)
5179 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5180 char *str2 = skip_string(param,tpscnt,str1);
5181 char *p = skip_string(param,tpscnt,str2);
5183 struct pack_desc desc;
5184 struct sessionid *session_list;
5185 int i, num_sessions;
5187 if (!str1 || !str2 || !p) {
5191 memset((char *)&desc,'\0',sizeof(desc));
5193 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5195 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5196 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5197 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5199 /* check it's a supported varient */
5200 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5203 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5207 num_sessions = list_sessions(talloc_tos(), &session_list);
5210 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5215 memset((char *)&desc,'\0',sizeof(desc));
5217 desc.buflen = mdrcnt;
5219 if (!init_package(&desc,num_sessions,0)) {
5223 for(i=0; i<num_sessions; i++) {
5224 PACKS(&desc, "z", session_list[i].remote_machine);
5225 PACKS(&desc, "z", session_list[i].username);
5226 PACKI(&desc, "W", 1); /* num conns */
5227 PACKI(&desc, "W", 0); /* num opens */
5228 PACKI(&desc, "W", 1); /* num users */
5229 PACKI(&desc, "D", 0); /* session time */
5230 PACKI(&desc, "D", 0); /* idle time */
5231 PACKI(&desc, "D", 0); /* flags */
5232 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5235 *rdata_len = desc.usedlen;
5238 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5242 SSVALS(*rparam,0,desc.errcode);
5243 SSVAL(*rparam,2,0); /* converter */
5244 SSVAL(*rparam,4,num_sessions); /* count */
5246 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5252 /****************************************************************************
5253 The buffer was too small.
5254 ****************************************************************************/
5256 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
5257 int mdrcnt, int mprcnt,
5258 char **rdata, char **rparam,
5259 int *rdata_len, int *rparam_len)
5261 *rparam_len = MIN(*rparam_len,mprcnt);
5262 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5269 SSVAL(*rparam,0,NERR_BufTooSmall);
5271 DEBUG(3,("Supplied buffer too small in API command\n"));
5276 /****************************************************************************
5277 The request is not supported.
5278 ****************************************************************************/
5280 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
5281 char *param, int tpscnt,
5282 char *data, int tdscnt,
5283 int mdrcnt, int mprcnt,
5284 char **rdata, char **rparam,
5285 int *rdata_len, int *rparam_len)
5288 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5295 SSVAL(*rparam,0,NERR_notsupported);
5296 SSVAL(*rparam,2,0); /* converter word */
5298 DEBUG(3,("Unsupported API command\n"));
5303 static const struct {
5306 bool (*fn)(connection_struct *, uint16,
5309 int,int,char **,char **,int *,int *);
5310 bool auth_user; /* Deny anonymous access? */
5311 } api_commands[] = {
5312 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5313 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5314 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5315 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5316 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5317 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5318 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5319 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5320 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5321 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5322 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5323 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5324 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5325 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5326 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5327 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5328 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5329 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5330 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5331 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5332 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5333 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5334 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5335 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5336 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5337 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5338 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5339 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5340 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5341 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5342 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5343 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5344 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5345 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5346 {NULL, -1, api_Unsupported}
5347 /* The following RAP calls are not implemented by Samba:
5349 RAP_WFileEnum2 - anon not OK
5354 /****************************************************************************
5355 Handle remote api calls.
5356 ****************************************************************************/
5358 void api_reply(connection_struct *conn, uint16 vuid,
5359 struct smb_request *req,
5360 char *data, char *params,
5361 int tdscnt, int tpscnt,
5362 int mdrcnt, int mprcnt)
5364 struct smbd_server_connection *sconn = smbd_server_conn;
5367 char *rparam = NULL;
5368 const char *name1 = NULL;
5369 const char *name2 = NULL;
5376 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5385 api_command = SVAL(params,0);
5386 /* Is there a string at position params+2 ? */
5387 if (skip_string(params,tpscnt,params+2)) {
5392 name2 = skip_string(params,tpscnt,params+2);
5397 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5401 tdscnt,tpscnt,mdrcnt,mprcnt));
5403 for (i=0;api_commands[i].name;i++) {
5404 if (api_commands[i].id == api_command && api_commands[i].fn) {
5405 DEBUG(3,("Doing %s\n",api_commands[i].name));
5410 /* Check whether this api call can be done anonymously */
5412 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5413 user_struct *user = get_valid_user_struct(sconn, vuid);
5415 if (!user || user->server_info->guest) {
5416 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5421 rdata = (char *)SMB_MALLOC(1024);
5423 memset(rdata,'\0',1024);
5426 rparam = (char *)SMB_MALLOC(1024);
5428 memset(rparam,'\0',1024);
5431 if(!rdata || !rparam) {
5432 DEBUG(0,("api_reply: malloc fail !\n"));
5435 reply_nterror(req, NT_STATUS_NO_MEMORY);
5439 reply = api_commands[i].fn(conn,
5441 params,tpscnt, /* params + length */
5442 data,tdscnt, /* data + length */
5444 &rdata,&rparam,&rdata_len,&rparam_len);
5447 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5448 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
5449 &rdata,&rparam,&rdata_len,&rparam_len);
5452 /* if we get False back then it's actually unsupported */
5454 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
5455 &rdata,&rparam,&rdata_len,&rparam_len);
5458 /* If api_Unsupported returns false we can't return anything. */
5460 send_trans_reply(conn, req, rparam, rparam_len,
5461 rdata, rdata_len, False);