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;
2846 /* Skip 2 strings. */
2847 p = skip_string(param,tpscnt,np);
2848 p = skip_string(param,tpscnt,p);
2854 /* Do we have a string ? */
2855 if (skip_string(param,tpscnt,p) == NULL) {
2858 pull_ascii_fstring(user,p);
2860 p = skip_string(param,tpscnt,p);
2865 memset(pass1,'\0',sizeof(pass1));
2866 memset(pass2,'\0',sizeof(pass2));
2868 * We use 31 here not 32 as we're checking
2869 * the last byte we want to access is safe.
2871 if (!is_offset_safe(param,tpscnt,p,31)) {
2875 memcpy(pass2,p+16,16);
2877 encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
2878 if (encrypted == -1) {
2879 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2883 min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
2884 if (min_pwd_length == -1) {
2885 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2890 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2897 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2898 user, encrypted, min_pwd_length));
2900 ZERO_STRUCT(connect_handle);
2901 ZERO_STRUCT(domain_handle);
2902 ZERO_STRUCT(user_handle);
2904 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
2905 rpc_samr_dispatch, conn->server_info,
2907 if (!NT_STATUS_IS_OK(status)) {
2908 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2909 nt_errstr(status)));
2910 errcode = W_ERROR_V(ntstatus_to_werror(status));
2914 status = rpccli_samr_Connect2(cli, mem_ctx,
2916 SAMR_ACCESS_CONNECT_TO_SERVER |
2917 SAMR_ACCESS_ENUM_DOMAINS |
2918 SAMR_ACCESS_LOOKUP_DOMAIN,
2920 if (!NT_STATUS_IS_OK(status)) {
2921 errcode = W_ERROR_V(ntstatus_to_werror(status));
2925 init_lsa_String(&domain_name, get_global_sam_name());
2927 status = rpccli_samr_LookupDomain(cli, mem_ctx,
2931 if (!NT_STATUS_IS_OK(status)) {
2932 errcode = W_ERROR_V(ntstatus_to_werror(status));
2936 status = rpccli_samr_OpenDomain(cli, mem_ctx,
2938 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2941 if (!NT_STATUS_IS_OK(status)) {
2942 errcode = W_ERROR_V(ntstatus_to_werror(status));
2946 init_lsa_String(&names, user);
2948 status = rpccli_samr_LookupNames(cli, mem_ctx,
2954 if (!NT_STATUS_IS_OK(status)) {
2955 errcode = W_ERROR_V(ntstatus_to_werror(status));
2959 if (rids.count != 1) {
2960 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
2963 if (rids.count != types.count) {
2964 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2967 if (types.ids[0] != SID_NAME_USER) {
2968 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2974 status = rpccli_samr_OpenUser(cli, mem_ctx,
2976 SAMR_USER_ACCESS_CHANGE_PASSWORD,
2979 if (!NT_STATUS_IS_OK(status)) {
2980 errcode = W_ERROR_V(ntstatus_to_werror(status));
2984 if (encrypted == 0) {
2985 E_deshash(pass1, old_lm_hash.hash);
2986 E_deshash(pass2, new_lm_hash.hash);
2988 ZERO_STRUCT(old_lm_hash);
2989 ZERO_STRUCT(new_lm_hash);
2990 memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
2991 memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16));
2994 status = rpccli_samr_ChangePasswordUser(cli, mem_ctx,
2996 true, /* lm_present */
2999 false, /* nt_present */
3000 NULL, /* old_nt_crypted */
3001 NULL, /* new_nt_crypted */
3002 false, /* cross1_present */
3003 NULL, /* nt_cross */
3004 false, /* cross2_present */
3005 NULL); /* lm_cross */
3006 if (!NT_STATUS_IS_OK(status)) {
3007 errcode = W_ERROR_V(ntstatus_to_werror(status));
3011 errcode = NERR_Success;
3014 if (cli && is_valid_policy_hnd(&user_handle)) {
3015 rpccli_samr_Close(cli, mem_ctx, &user_handle);
3017 if (cli && is_valid_policy_hnd(&domain_handle)) {
3018 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
3020 if (cli && is_valid_policy_hnd(&connect_handle)) {
3021 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
3024 memset((char *)pass1,'\0',sizeof(fstring));
3025 memset((char *)pass2,'\0',sizeof(fstring));
3027 SSVAL(*rparam,0,errcode);
3028 SSVAL(*rparam,2,0); /* converter word */
3032 /****************************************************************************
3033 Set the user password (SamOEM version - gets plaintext).
3034 ****************************************************************************/
3036 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
3037 char *param, int tpscnt,
3038 char *data, int tdscnt,
3039 int mdrcnt,int mprcnt,
3040 char **rdata,char **rparam,
3041 int *rdata_len,int *rparam_len)
3044 char *p = get_safe_str_ptr(param,tpscnt,param,2);
3046 TALLOC_CTX *mem_ctx = talloc_tos();
3048 struct rpc_pipe_client *cli = NULL;
3049 struct lsa_AsciiString server, account;
3050 struct samr_CryptPassword password;
3051 struct samr_Password hash;
3052 int errcode = NERR_badpass;
3056 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3066 SSVAL(*rparam,0,NERR_badpass);
3069 * Check the parameter definition is correct.
3072 /* Do we have a string ? */
3073 if (skip_string(param,tpscnt,p) == 0) {
3076 if(!strequal(p, "zsT")) {
3077 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3080 p = skip_string(param, tpscnt, p);
3085 /* Do we have a string ? */
3086 if (skip_string(param,tpscnt,p) == 0) {
3089 if(!strequal(p, "B516B16")) {
3090 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3093 p = skip_string(param,tpscnt,p);
3097 /* Do we have a string ? */
3098 if (skip_string(param,tpscnt,p) == 0) {
3101 p += pull_ascii_fstring(user,p);
3103 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3105 if (tdscnt != 532) {
3106 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3110 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3111 if (bufsize != 532) {
3112 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3116 memcpy(password.data, data, 516);
3117 memcpy(hash.hash, data+516, 16);
3119 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
3120 rpc_samr_dispatch, conn->server_info,
3122 if (!NT_STATUS_IS_OK(status)) {
3123 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3124 nt_errstr(status)));
3125 errcode = W_ERROR_V(ntstatus_to_werror(status));
3129 init_lsa_AsciiString(&server, global_myname());
3130 init_lsa_AsciiString(&account, user);
3132 status = rpccli_samr_OemChangePasswordUser2(cli, mem_ctx,
3137 if (!NT_STATUS_IS_OK(status)) {
3138 errcode = W_ERROR_V(ntstatus_to_werror(status));
3142 errcode = NERR_Success;
3144 SSVAL(*rparam,0,errcode);
3145 SSVAL(*rparam,2,0); /* converter word */
3150 /****************************************************************************
3153 ****************************************************************************/
3155 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
3156 char *param, int tpscnt,
3157 char *data, int tdscnt,
3158 int mdrcnt,int mprcnt,
3159 char **rdata,char **rparam,
3160 int *rdata_len,int *rparam_len)
3162 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3163 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3164 char *str2 = skip_string(param,tpscnt,str1);
3165 char *p = skip_string(param,tpscnt,str2);
3169 WERROR werr = WERR_OK;
3171 TALLOC_CTX *mem_ctx = talloc_tos();
3173 struct rpc_pipe_client *cli = NULL;
3174 struct policy_handle handle;
3175 struct spoolss_DevmodeContainer devmode_ctr;
3176 enum spoolss_JobControl command;
3178 if (!str1 || !str2 || !p) {
3182 * We use 1 here not 2 as we're checking
3183 * the last byte we want to access is safe.
3185 if (!is_offset_safe(param,tpscnt,p,1)) {
3188 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3191 /* check it's a supported varient */
3192 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3196 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3202 ZERO_STRUCT(handle);
3204 status = rpc_connect_spoolss_pipe(conn, &cli);
3205 if (!NT_STATUS_IS_OK(status)) {
3206 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3207 nt_errstr(status)));
3208 errcode = W_ERROR_V(ntstatus_to_werror(status));
3212 ZERO_STRUCT(devmode_ctr);
3214 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3218 JOB_ACCESS_ADMINISTER,
3221 if (!NT_STATUS_IS_OK(status)) {
3222 errcode = W_ERROR_V(ntstatus_to_werror(status));
3225 if (!W_ERROR_IS_OK(werr)) {
3226 errcode = W_ERROR_V(werr);
3230 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3231 * and NERR_DestNotFound if share did not exist */
3233 errcode = NERR_Success;
3236 case 81: /* delete */
3237 command = SPOOLSS_JOB_CONTROL_DELETE;
3239 case 82: /* pause */
3240 command = SPOOLSS_JOB_CONTROL_PAUSE;
3242 case 83: /* resume */
3243 command = SPOOLSS_JOB_CONTROL_RESUME;
3246 errcode = NERR_notsupported;
3250 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3253 NULL, /* unique ptr ctr */
3256 if (!NT_STATUS_IS_OK(status)) {
3257 errcode = W_ERROR_V(ntstatus_to_werror(status));
3260 if (!W_ERROR_IS_OK(werr)) {
3261 errcode = W_ERROR_V(werr);
3266 if (cli && is_valid_policy_hnd(&handle)) {
3267 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3270 SSVAL(*rparam,0,errcode);
3271 SSVAL(*rparam,2,0); /* converter word */
3276 /****************************************************************************
3277 Purge a print queue - or pause or resume it.
3278 ****************************************************************************/
3280 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
3281 char *param, int tpscnt,
3282 char *data, int tdscnt,
3283 int mdrcnt,int mprcnt,
3284 char **rdata,char **rparam,
3285 int *rdata_len,int *rparam_len)
3287 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3288 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3289 char *str2 = skip_string(param,tpscnt,str1);
3290 char *QueueName = skip_string(param,tpscnt,str2);
3291 int errcode = NERR_notsupported;
3292 WERROR werr = WERR_OK;
3295 TALLOC_CTX *mem_ctx = talloc_tos();
3296 struct rpc_pipe_client *cli = NULL;
3297 struct policy_handle handle;
3298 struct spoolss_SetPrinterInfoCtr info_ctr;
3299 struct spoolss_DevmodeContainer devmode_ctr;
3300 struct sec_desc_buf secdesc_ctr;
3301 enum spoolss_PrinterControl command;
3303 if (!str1 || !str2 || !QueueName) {
3307 /* check it's a supported varient */
3308 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3312 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3318 if (skip_string(param,tpscnt,QueueName) == NULL) {
3322 ZERO_STRUCT(handle);
3324 status = rpc_connect_spoolss_pipe(conn, &cli);
3325 if (!NT_STATUS_IS_OK(status)) {
3326 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3327 nt_errstr(status)));
3328 errcode = W_ERROR_V(ntstatus_to_werror(status));
3332 ZERO_STRUCT(devmode_ctr);
3334 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3338 SEC_FLAG_MAXIMUM_ALLOWED,
3341 if (!NT_STATUS_IS_OK(status)) {
3342 errcode = W_ERROR_V(ntstatus_to_werror(status));
3345 if (!W_ERROR_IS_OK(werr)) {
3346 errcode = W_ERROR_V(werr);
3351 case 74: /* Pause queue */
3352 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3354 case 75: /* Resume queue */
3355 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3357 case 103: /* Purge */
3358 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3361 werr = WERR_NOT_SUPPORTED;
3365 if (!W_ERROR_IS_OK(werr)) {
3366 errcode = W_ERROR_V(werr);
3370 ZERO_STRUCT(info_ctr);
3371 ZERO_STRUCT(secdesc_ctr);
3373 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
3380 if (!NT_STATUS_IS_OK(status)) {
3381 errcode = W_ERROR_V(ntstatus_to_werror(status));
3384 if (!W_ERROR_IS_OK(werr)) {
3385 errcode = W_ERROR_V(werr);
3389 errcode = W_ERROR_V(werr);
3393 if (cli && is_valid_policy_hnd(&handle)) {
3394 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3397 SSVAL(*rparam,0,errcode);
3398 SSVAL(*rparam,2,0); /* converter word */
3403 /****************************************************************************
3404 set the property of a print job (undocumented?)
3405 ? function = 0xb -> set name of print job
3406 ? function = 0x6 -> move print job up/down
3407 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3408 or <WWsTP> <WB21BB16B10zWWzDDz>
3409 ****************************************************************************/
3411 static int check_printjob_info(struct pack_desc* desc,
3412 int uLevel, char* id)
3414 desc->subformat = NULL;
3416 case 0: desc->format = "W"; break;
3417 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3418 case 2: desc->format = "WWzWWDDzz"; break;
3419 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3420 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3422 DEBUG(0,("check_printjob_info: invalid level %d\n",
3426 if (id == NULL || strcmp(desc->format,id) != 0) {
3427 DEBUG(0,("check_printjob_info: invalid format %s\n",
3428 id ? id : "<NULL>" ));
3434 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
3435 char *param, int tpscnt,
3436 char *data, int tdscnt,
3437 int mdrcnt,int mprcnt,
3438 char **rdata,char **rparam,
3439 int *rdata_len,int *rparam_len)
3441 struct pack_desc desc;
3442 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3443 char *str2 = skip_string(param,tpscnt,str1);
3444 char *p = skip_string(param,tpscnt,str2);
3447 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3448 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3451 TALLOC_CTX *mem_ctx = talloc_tos();
3454 struct rpc_pipe_client *cli = NULL;
3455 struct policy_handle handle;
3456 struct spoolss_DevmodeContainer devmode_ctr;
3457 struct spoolss_JobInfoContainer ctr;
3458 union spoolss_JobInfo info;
3459 struct spoolss_SetJobInfo1 info1;
3461 if (!str1 || !str2 || !p) {
3465 * We use 1 here not 2 as we're checking
3466 * the last byte we want to access is safe.
3468 if (!is_offset_safe(param,tpscnt,p,1)) {
3471 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3474 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3481 /* check it's a supported varient */
3482 if ((strcmp(str1,"WWsTP")) ||
3483 (!check_printjob_info(&desc,uLevel,str2)))
3486 errcode = NERR_notsupported;
3490 /* change print job name, data gives the name */
3496 ZERO_STRUCT(handle);
3498 status = rpc_connect_spoolss_pipe(conn, &cli);
3499 if (!NT_STATUS_IS_OK(status)) {
3500 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3501 nt_errstr(status)));
3502 errcode = W_ERROR_V(ntstatus_to_werror(status));
3506 ZERO_STRUCT(devmode_ctr);
3508 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3515 if (!NT_STATUS_IS_OK(status)) {
3516 errcode = W_ERROR_V(ntstatus_to_werror(status));
3519 if (!W_ERROR_IS_OK(werr)) {
3520 errcode = W_ERROR_V(werr);
3524 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3530 if (!W_ERROR_IS_OK(werr)) {
3531 errcode = W_ERROR_V(werr);
3537 info1.job_id = info.info1.job_id;
3538 info1.printer_name = info.info1.printer_name;
3539 info1.user_name = info.info1.user_name;
3540 info1.document_name = data;
3541 info1.data_type = info.info1.data_type;
3542 info1.text_status = info.info1.text_status;
3543 info1.status = info.info1.status;
3544 info1.priority = info.info1.priority;
3545 info1.position = info.info1.position;
3546 info1.total_pages = info.info1.total_pages;
3547 info1.pages_printed = info.info1.pages_printed;
3548 info1.submitted = info.info1.submitted;
3551 ctr.info.info1 = &info1;
3553 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3559 if (!NT_STATUS_IS_OK(status)) {
3560 errcode = W_ERROR_V(ntstatus_to_werror(status));
3563 if (!W_ERROR_IS_OK(werr)) {
3564 errcode = W_ERROR_V(werr);
3568 errcode = NERR_Success;
3571 if (cli && is_valid_policy_hnd(&handle)) {
3572 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3575 SSVALS(*rparam,0,errcode);
3576 SSVAL(*rparam,2,0); /* converter word */
3582 /****************************************************************************
3583 Get info about the server.
3584 ****************************************************************************/
3586 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3587 char *param, int tpscnt,
3588 char *data, int tdscnt,
3589 int mdrcnt,int mprcnt,
3590 char **rdata,char **rparam,
3591 int *rdata_len,int *rparam_len)
3593 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3594 char *str2 = skip_string(param,tpscnt,str1);
3595 char *p = skip_string(param,tpscnt,str2);
3596 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3602 TALLOC_CTX *mem_ctx = talloc_tos();
3603 struct rpc_pipe_client *cli = NULL;
3604 union srvsvc_NetSrvInfo info;
3607 if (!str1 || !str2 || !p) {
3611 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3613 /* check it's a supported varient */
3614 if (!prefix_ok(str1,"WrLh")) {
3620 if (strcmp(str2,"B16") != 0) {
3626 if (strcmp(str2,"B16BBDz") != 0) {
3632 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3638 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3644 if (strcmp(str2,"DN") != 0) {
3650 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3659 *rdata_len = mdrcnt;
3660 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3666 p2 = p + struct_len;
3668 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
3669 rpc_srvsvc_dispatch, conn->server_info,
3671 if (!NT_STATUS_IS_OK(status)) {
3672 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3673 nt_errstr(status)));
3674 errcode = W_ERROR_V(ntstatus_to_werror(status));
3678 status = rpccli_srvsvc_NetSrvGetInfo(cli, mem_ctx,
3683 if (!NT_STATUS_IS_OK(status)) {
3684 errcode = W_ERROR_V(ntstatus_to_werror(status));
3687 if (!W_ERROR_IS_OK(werr)) {
3688 errcode = W_ERROR_V(werr);
3692 if (info.info101 == NULL) {
3693 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3698 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3699 STR_ASCII|STR_UPPER|STR_TERMINATE);
3703 SCVAL(p,0,info.info101->version_major);
3704 SCVAL(p,1,info.info101->version_minor);
3705 SIVAL(p,2,info.info101->server_type);
3707 if (mdrcnt == struct_len) {
3710 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3711 if (mdrcnt - struct_len <= 0) {
3715 info.info101->comment,
3716 MIN(mdrcnt - struct_len,
3717 MAX_SERVER_STRING_LENGTH),
3719 p2 = skip_string(*rdata,*rdata_len,p2);
3727 return False; /* not yet implemented */
3730 errcode = NERR_Success;
3734 *rdata_len = PTR_DIFF(p2,*rdata);
3737 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3741 SSVAL(*rparam,0,errcode);
3742 SSVAL(*rparam,2,0); /* converter word */
3743 SSVAL(*rparam,4,*rdata_len);
3748 /****************************************************************************
3749 Get info about the server.
3750 ****************************************************************************/
3752 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3753 char *param, int tpscnt,
3754 char *data, int tdscnt,
3755 int mdrcnt,int mprcnt,
3756 char **rdata,char **rparam,
3757 int *rdata_len,int *rparam_len)
3759 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3760 char *str2 = skip_string(param,tpscnt,str1);
3761 char *p = skip_string(param,tpscnt,str2);
3764 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3766 if (!str1 || !str2 || !p) {
3770 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3773 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3778 /* check it's a supported varient */
3779 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3783 *rdata_len = mdrcnt + 1024;
3784 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3789 SSVAL(*rparam,0,NERR_Success);
3790 SSVAL(*rparam,2,0); /* converter word */
3793 endp = *rdata + *rdata_len;
3795 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3800 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3801 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3803 p2 = skip_string(*rdata,*rdata_len,p2);
3809 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3810 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3811 p2 = skip_string(*rdata,*rdata_len,p2);
3817 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3818 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3820 p2 = skip_string(*rdata,*rdata_len,p2);
3826 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3827 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3830 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3831 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3832 p2 = skip_string(*rdata,*rdata_len,p2);
3838 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3839 strlcpy(p2,"",PTR_DIFF(endp,p2));
3840 p2 = skip_string(*rdata,*rdata_len,p2);
3846 *rdata_len = PTR_DIFF(p2,*rdata);
3848 SSVAL(*rparam,4,*rdata_len);
3853 /****************************************************************************
3854 get info about a user
3856 struct user_info_11 {
3857 char usri11_name[21]; 0-20
3859 char *usri11_comment; 22-25
3860 char *usri11_usr_comment; 26-29
3861 unsigned short usri11_priv; 30-31
3862 unsigned long usri11_auth_flags; 32-35
3863 long usri11_password_age; 36-39
3864 char *usri11_homedir; 40-43
3865 char *usri11_parms; 44-47
3866 long usri11_last_logon; 48-51
3867 long usri11_last_logoff; 52-55
3868 unsigned short usri11_bad_pw_count; 56-57
3869 unsigned short usri11_num_logons; 58-59
3870 char *usri11_logon_server; 60-63
3871 unsigned short usri11_country_code; 64-65
3872 char *usri11_workstations; 66-69
3873 unsigned long usri11_max_storage; 70-73
3874 unsigned short usri11_units_per_week; 74-75
3875 unsigned char *usri11_logon_hours; 76-79
3876 unsigned short usri11_code_page; 80-81
3881 usri11_name specifies the user name for which information is retrieved
3883 usri11_pad aligns the next data structure element to a word boundary
3885 usri11_comment is a null terminated ASCII comment
3887 usri11_user_comment is a null terminated ASCII comment about the user
3889 usri11_priv specifies the level of the privilege assigned to the user.
3890 The possible values are:
3892 Name Value Description
3893 USER_PRIV_GUEST 0 Guest privilege
3894 USER_PRIV_USER 1 User privilege
3895 USER_PRV_ADMIN 2 Administrator privilege
3897 usri11_auth_flags specifies the account operator privileges. The
3898 possible values are:
3900 Name Value Description
3901 AF_OP_PRINT 0 Print operator
3904 Leach, Naik [Page 28]
3908 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3911 AF_OP_COMM 1 Communications operator
3912 AF_OP_SERVER 2 Server operator
3913 AF_OP_ACCOUNTS 3 Accounts operator
3916 usri11_password_age specifies how many seconds have elapsed since the
3917 password was last changed.
3919 usri11_home_dir points to a null terminated ASCII string that contains
3920 the path name of the user's home directory.
3922 usri11_parms points to a null terminated ASCII string that is set
3923 aside for use by applications.
3925 usri11_last_logon specifies the time when the user last logged on.
3926 This value is stored as the number of seconds elapsed since
3927 00:00:00, January 1, 1970.
3929 usri11_last_logoff specifies the time when the user last logged off.
3930 This value is stored as the number of seconds elapsed since
3931 00:00:00, January 1, 1970. A value of 0 means the last logoff
3934 usri11_bad_pw_count specifies the number of incorrect passwords
3935 entered since the last successful logon.
3937 usri11_log1_num_logons specifies the number of times this user has
3938 logged on. A value of -1 means the number of logons is unknown.
3940 usri11_logon_server points to a null terminated ASCII string that
3941 contains the name of the server to which logon requests are sent.
3942 A null string indicates logon requests should be sent to the
3945 usri11_country_code specifies the country code for the user's language
3948 usri11_workstations points to a null terminated ASCII string that
3949 contains the names of workstations the user may log on from.
3950 There may be up to 8 workstations, with the names separated by
3951 commas. A null strings indicates there are no restrictions.
3953 usri11_max_storage specifies the maximum amount of disk space the user
3954 can occupy. A value of 0xffffffff indicates there are no
3957 usri11_units_per_week specifies the equal number of time units into
3958 which a week is divided. This value must be equal to 168.
3960 usri11_logon_hours points to a 21 byte (168 bits) string that
3961 specifies the time during which the user can log on. Each bit
3962 represents one unique hour in a week. The first bit (bit 0, word
3963 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3967 Leach, Naik [Page 29]
3971 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3974 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3975 are no restrictions.
3977 usri11_code_page specifies the code page for the user's language of
3980 All of the pointers in this data structure need to be treated
3981 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3982 to be ignored. The converter word returned in the parameters section
3983 needs to be subtracted from the lower 16 bits to calculate an offset
3984 into the return buffer where this ASCII string resides.
3986 There is no auxiliary data in the response.
3988 ****************************************************************************/
3990 #define usri11_name 0
3991 #define usri11_pad 21
3992 #define usri11_comment 22
3993 #define usri11_usr_comment 26
3994 #define usri11_full_name 30
3995 #define usri11_priv 34
3996 #define usri11_auth_flags 36
3997 #define usri11_password_age 40
3998 #define usri11_homedir 44
3999 #define usri11_parms 48
4000 #define usri11_last_logon 52
4001 #define usri11_last_logoff 56
4002 #define usri11_bad_pw_count 60
4003 #define usri11_num_logons 62
4004 #define usri11_logon_server 64
4005 #define usri11_country_code 68
4006 #define usri11_workstations 70
4007 #define usri11_max_storage 74
4008 #define usri11_units_per_week 78
4009 #define usri11_logon_hours 80
4010 #define usri11_code_page 84
4011 #define usri11_end 86
4013 #define USER_PRIV_GUEST 0
4014 #define USER_PRIV_USER 1
4015 #define USER_PRIV_ADMIN 2
4017 #define AF_OP_PRINT 0
4018 #define AF_OP_COMM 1
4019 #define AF_OP_SERVER 2
4020 #define AF_OP_ACCOUNTS 3
4023 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
4024 char *param, int tpscnt,
4025 char *data, int tdscnt,
4026 int mdrcnt,int mprcnt,
4027 char **rdata,char **rparam,
4028 int *rdata_len,int *rparam_len)
4030 struct smbd_server_connection *sconn = smbd_server_conn;
4031 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4032 char *str2 = skip_string(param,tpscnt,str1);
4033 char *UserName = skip_string(param,tpscnt,str2);
4034 char *p = skip_string(param,tpscnt,UserName);
4035 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4038 const char *level_string;
4040 /* get NIS home of a previously validated user - simeon */
4041 /* With share level security vuid will always be zero.
4042 Don't depend on vuser being non-null !!. JRA */
4043 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4045 DEBUG(3,(" Username of UID %d is %s\n",
4046 (int)vuser->server_info->utok.uid,
4047 vuser->server_info->unix_name));
4050 if (!str1 || !str2 || !UserName || !p) {
4055 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4060 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4062 /* check it's a supported variant */
4063 if (strcmp(str1,"zWrLh") != 0) {
4067 case 0: level_string = "B21"; break;
4068 case 1: level_string = "B21BB16DWzzWz"; break;
4069 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4070 case 10: level_string = "B21Bzzz"; break;
4071 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4072 default: return False;
4075 if (strcmp(level_string,str2) != 0) {
4079 *rdata_len = mdrcnt + 1024;
4080 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4085 SSVAL(*rparam,0,NERR_Success);
4086 SSVAL(*rparam,2,0); /* converter word */
4089 endp = *rdata + *rdata_len;
4090 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4096 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4099 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4104 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4105 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4106 p2 = skip_string(*rdata,*rdata_len,p2);
4111 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4112 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4113 p2 = skip_string(*rdata,*rdata_len,p2);
4118 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4119 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4120 strlcpy(p2,((vuser != NULL)
4121 ? pdb_get_fullname(vuser->server_info->sam_account)
4122 : UserName),PTR_DIFF(endp,p2));
4123 p2 = skip_string(*rdata,*rdata_len,p2);
4130 const char *homedir = "";
4131 if (vuser != NULL) {
4132 homedir = pdb_get_homedir(
4133 vuser->server_info->sam_account);
4135 /* modelled after NTAS 3.51 reply */
4136 SSVAL(p,usri11_priv,
4137 (get_current_uid(conn) == sec_initial_uid())?
4138 USER_PRIV_ADMIN:USER_PRIV_USER);
4139 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4140 SIVALS(p,usri11_password_age,-1); /* password age */
4141 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4142 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4143 p2 = skip_string(*rdata,*rdata_len,p2);
4147 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4148 strlcpy(p2,"",PTR_DIFF(endp,p2));
4149 p2 = skip_string(*rdata,*rdata_len,p2);
4153 SIVAL(p,usri11_last_logon,0); /* last logon */
4154 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4155 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4156 SSVALS(p,usri11_num_logons,-1); /* num logons */
4157 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4158 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4159 p2 = skip_string(*rdata,*rdata_len,p2);
4163 SSVAL(p,usri11_country_code,0); /* country code */
4165 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4166 strlcpy(p2,"",PTR_DIFF(endp,p2));
4167 p2 = skip_string(*rdata,*rdata_len,p2);
4172 SIVALS(p,usri11_max_storage,-1); /* max storage */
4173 SSVAL(p,usri11_units_per_week,168); /* units per week */
4174 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4176 /* a simple way to get logon hours at all times. */
4178 SCVAL(p2,21,0); /* fix zero termination */
4179 p2 = skip_string(*rdata,*rdata_len,p2);
4184 SSVAL(p,usri11_code_page,0); /* code page */
4187 if (uLevel == 1 || uLevel == 2) {
4188 memset(p+22,' ',16); /* password */
4189 SIVALS(p,38,-1); /* password age */
4191 (get_current_uid(conn) == sec_initial_uid())?
4192 USER_PRIV_ADMIN:USER_PRIV_USER);
4193 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4194 strlcpy(p2, vuser ? pdb_get_homedir(
4195 vuser->server_info->sam_account) : "",
4197 p2 = skip_string(*rdata,*rdata_len,p2);
4201 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4203 SSVAL(p,52,0); /* flags */
4204 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4205 strlcpy(p2, vuser ? pdb_get_logon_script(
4206 vuser->server_info->sam_account) : "",
4208 p2 = skip_string(*rdata,*rdata_len,p2);
4213 SIVAL(p,60,0); /* auth_flags */
4214 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
4215 strlcpy(p2,((vuser != NULL)
4216 ? pdb_get_fullname(vuser->server_info->sam_account)
4217 : UserName),PTR_DIFF(endp,p2));
4218 p2 = skip_string(*rdata,*rdata_len,p2);
4222 SIVAL(p,68,0); /* urs_comment */
4223 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
4224 strlcpy(p2,"",PTR_DIFF(endp,p2));
4225 p2 = skip_string(*rdata,*rdata_len,p2);
4229 SIVAL(p,76,0); /* workstations */
4230 SIVAL(p,80,0); /* last_logon */
4231 SIVAL(p,84,0); /* last_logoff */
4232 SIVALS(p,88,-1); /* acct_expires */
4233 SIVALS(p,92,-1); /* max_storage */
4234 SSVAL(p,96,168); /* units_per_week */
4235 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
4238 SSVALS(p,102,-1); /* bad_pw_count */
4239 SSVALS(p,104,-1); /* num_logons */
4240 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
4242 TALLOC_CTX *ctx = talloc_tos();
4243 int space_rem = *rdata_len - (p2 - *rdata);
4246 if (space_rem <= 0) {
4249 tmp = talloc_strdup(ctx, "\\\\%L");
4253 tmp = talloc_sub_basic(ctx,
4266 p2 = skip_string(*rdata,*rdata_len,p2);
4270 SSVAL(p,110,49); /* country_code */
4271 SSVAL(p,112,860); /* code page */
4275 *rdata_len = PTR_DIFF(p2,*rdata);
4277 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4282 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
4283 char *param, int tpscnt,
4284 char *data, int tdscnt,
4285 int mdrcnt,int mprcnt,
4286 char **rdata,char **rparam,
4287 int *rdata_len,int *rparam_len)
4289 struct smbd_server_connection *sconn = smbd_server_conn;
4290 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4291 char *str2 = skip_string(param,tpscnt,str1);
4292 char *p = skip_string(param,tpscnt,str2);
4294 struct pack_desc desc;
4296 /* With share level security vuid will always be zero.
4297 Don't depend on vuser being non-null !!. JRA */
4298 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4300 if (!str1 || !str2 || !p) {
4305 DEBUG(3,(" Username of UID %d is %s\n",
4306 (int)vuser->server_info->utok.uid,
4307 vuser->server_info->unix_name));
4310 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4311 name = get_safe_str_ptr(param,tpscnt,p,2);
4316 memset((char *)&desc,'\0',sizeof(desc));
4318 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4320 /* check it's a supported varient */
4321 if (strcmp(str1,"OOWb54WrLh") != 0) {
4324 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4328 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4335 desc.buflen = mdrcnt;
4336 desc.subformat = NULL;
4339 if (init_package(&desc,1,0)) {
4340 PACKI(&desc,"W",0); /* code */
4341 PACKS(&desc,"B21",name); /* eff. name */
4342 PACKS(&desc,"B",""); /* pad */
4344 (get_current_uid(conn) == sec_initial_uid())?
4345 USER_PRIV_ADMIN:USER_PRIV_USER);
4346 PACKI(&desc,"D",0); /* auth flags XXX */
4347 PACKI(&desc,"W",0); /* num logons */
4348 PACKI(&desc,"W",0); /* bad pw count */
4349 PACKI(&desc,"D",0); /* last logon */
4350 PACKI(&desc,"D",-1); /* last logoff */
4351 PACKI(&desc,"D",-1); /* logoff time */
4352 PACKI(&desc,"D",-1); /* kickoff time */
4353 PACKI(&desc,"D",0); /* password age */
4354 PACKI(&desc,"D",0); /* password can change */
4355 PACKI(&desc,"D",-1); /* password must change */
4359 fstrcpy(mypath,"\\\\");
4360 fstrcat(mypath,get_local_machine_name());
4362 PACKS(&desc,"z",mypath); /* computer */
4365 PACKS(&desc,"z",lp_workgroup());/* domain */
4366 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
4367 vuser->server_info->sam_account) : ""); /* script path */
4368 PACKI(&desc,"D",0x00000000); /* reserved */
4371 *rdata_len = desc.usedlen;
4373 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4377 SSVALS(*rparam,0,desc.errcode);
4379 SSVAL(*rparam,4,desc.neededlen);
4381 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4386 /****************************************************************************
4387 api_WAccessGetUserPerms
4388 ****************************************************************************/
4390 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
4391 char *param, int tpscnt,
4392 char *data, int tdscnt,
4393 int mdrcnt,int mprcnt,
4394 char **rdata,char **rparam,
4395 int *rdata_len,int *rparam_len)
4397 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4398 char *str2 = skip_string(param,tpscnt,str1);
4399 char *user = skip_string(param,tpscnt,str2);
4400 char *resource = skip_string(param,tpscnt,user);
4402 if (!str1 || !str2 || !user || !resource) {
4406 if (skip_string(param,tpscnt,resource) == NULL) {
4409 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4411 /* check it's a supported varient */
4412 if (strcmp(str1,"zzh") != 0) {
4415 if (strcmp(str2,"") != 0) {
4420 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4424 SSVALS(*rparam,0,0); /* errorcode */
4425 SSVAL(*rparam,2,0); /* converter word */
4426 SSVAL(*rparam,4,0x7f); /* permission flags */
4431 /****************************************************************************
4432 api_WPrintJobEnumerate
4433 ****************************************************************************/
4435 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
4436 char *param, int tpscnt,
4437 char *data, int tdscnt,
4438 int mdrcnt,int mprcnt,
4439 char **rdata,char **rparam,
4440 int *rdata_len,int *rparam_len)
4442 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4443 char *str2 = skip_string(param,tpscnt,str1);
4444 char *p = skip_string(param,tpscnt,str2);
4448 struct pack_desc desc;
4451 TALLOC_CTX *mem_ctx = talloc_tos();
4454 struct rpc_pipe_client *cli = NULL;
4455 struct policy_handle handle;
4456 struct spoolss_DevmodeContainer devmode_ctr;
4457 union spoolss_JobInfo info;
4459 if (!str1 || !str2 || !p) {
4463 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4465 memset((char *)&desc,'\0',sizeof(desc));
4466 memset((char *)&status,'\0',sizeof(status));
4468 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4470 /* check it's a supported varient */
4471 if (strcmp(str1,"WWrLh") != 0) {
4474 if (!check_printjob_info(&desc,uLevel,str2)) {
4478 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4482 ZERO_STRUCT(handle);
4484 status = rpc_connect_spoolss_pipe(conn, &cli);
4485 if (!NT_STATUS_IS_OK(status)) {
4486 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4487 nt_errstr(status)));
4488 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4492 ZERO_STRUCT(devmode_ctr);
4494 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4501 if (!NT_STATUS_IS_OK(status)) {
4502 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4505 if (!W_ERROR_IS_OK(werr)) {
4506 desc.errcode = W_ERROR_V(werr);
4510 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4516 if (!W_ERROR_IS_OK(werr)) {
4517 desc.errcode = W_ERROR_V(werr);
4522 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4527 desc.buflen = mdrcnt;
4530 * Don't return data but need to get correct length
4531 * init_package will return wrong size if buflen=0
4533 desc.buflen = getlen(desc.format);
4534 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4537 if (init_package(&desc,1,0)) {
4538 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4539 *rdata_len = desc.usedlen;
4541 desc.errcode = NERR_JobNotFound;
4545 if (cli && is_valid_policy_hnd(&handle)) {
4546 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4550 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4554 SSVALS(*rparam,0,desc.errcode);
4556 SSVAL(*rparam,4,desc.neededlen);
4560 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4565 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
4566 char *param, int tpscnt,
4567 char *data, int tdscnt,
4568 int mdrcnt,int mprcnt,
4569 char **rdata,char **rparam,
4570 int *rdata_len,int *rparam_len)
4572 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4573 char *str2 = skip_string(param,tpscnt,str1);
4574 char *p = skip_string(param,tpscnt,str2);
4578 struct pack_desc desc;
4580 TALLOC_CTX *mem_ctx = talloc_tos();
4583 struct rpc_pipe_client *cli = NULL;
4584 struct policy_handle handle;
4585 struct spoolss_DevmodeContainer devmode_ctr;
4587 union spoolss_JobInfo *info;
4589 if (!str1 || !str2 || !p) {
4593 memset((char *)&desc,'\0',sizeof(desc));
4595 p = skip_string(param,tpscnt,p);
4599 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4601 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4603 /* check it's a supported variant */
4604 if (strcmp(str1,"zWrLeh") != 0) {
4609 return False; /* defined only for uLevel 0,1,2 */
4612 if (!check_printjob_info(&desc,uLevel,str2)) {
4616 ZERO_STRUCT(handle);
4618 status = rpc_connect_spoolss_pipe(conn, &cli);
4619 if (!NT_STATUS_IS_OK(status)) {
4620 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4621 nt_errstr(status)));
4622 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4626 ZERO_STRUCT(devmode_ctr);
4628 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4632 SEC_FLAG_MAXIMUM_ALLOWED,
4635 if (!NT_STATUS_IS_OK(status)) {
4636 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4639 if (!W_ERROR_IS_OK(werr)) {
4640 desc.errcode = W_ERROR_V(werr);
4644 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4652 if (!W_ERROR_IS_OK(werr)) {
4653 desc.errcode = W_ERROR_V(werr);
4658 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4664 desc.buflen = mdrcnt;
4666 if (init_package(&desc,count,0)) {
4668 for (i = 0; i < count; i++) {
4669 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4670 if (desc.errcode == NERR_Success) {
4676 if (cli && is_valid_policy_hnd(&handle)) {
4677 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4680 *rdata_len = desc.usedlen;
4683 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4687 SSVALS(*rparam,0,desc.errcode);
4689 SSVAL(*rparam,4,succnt);
4690 SSVAL(*rparam,6,count);
4692 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4697 static int check_printdest_info(struct pack_desc* desc,
4698 int uLevel, char* id)
4700 desc->subformat = NULL;
4703 desc->format = "B9";
4706 desc->format = "B9B21WWzW";
4712 desc->format = "zzzWWzzzWW";
4715 DEBUG(0,("check_printdest_info: invalid level %d\n",
4719 if (id == NULL || strcmp(desc->format,id) != 0) {
4720 DEBUG(0,("check_printdest_info: invalid string %s\n",
4721 id ? id : "<NULL>" ));
4727 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
4728 struct pack_desc* desc)
4732 strncpy(buf, info2->printername, sizeof(buf)-1);
4733 buf[sizeof(buf)-1] = 0;
4737 PACKS(desc,"B9",buf); /* szName */
4739 PACKS(desc,"B21",""); /* szUserName */
4740 PACKI(desc,"W",0); /* uJobId */
4741 PACKI(desc,"W",0); /* fsStatus */
4742 PACKS(desc,"z",""); /* pszStatus */
4743 PACKI(desc,"W",0); /* time */
4747 if (uLevel == 2 || uLevel == 3) {
4748 PACKS(desc,"z",buf); /* pszPrinterName */
4750 PACKS(desc,"z",""); /* pszUserName */
4751 PACKS(desc,"z",""); /* pszLogAddr */
4752 PACKI(desc,"W",0); /* uJobId */
4753 PACKI(desc,"W",0); /* fsStatus */
4754 PACKS(desc,"z",""); /* pszStatus */
4755 PACKS(desc,"z",""); /* pszComment */
4756 PACKS(desc,"z","NULL"); /* pszDrivers */
4757 PACKI(desc,"W",0); /* time */
4758 PACKI(desc,"W",0); /* pad1 */
4763 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4764 char *param, int tpscnt,
4765 char *data, int tdscnt,
4766 int mdrcnt,int mprcnt,
4767 char **rdata,char **rparam,
4768 int *rdata_len,int *rparam_len)
4770 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4771 char *str2 = skip_string(param,tpscnt,str1);
4772 char *p = skip_string(param,tpscnt,str2);
4773 char* PrinterName = p;
4775 struct pack_desc desc;
4778 TALLOC_CTX *mem_ctx = talloc_tos();
4781 struct rpc_pipe_client *cli = NULL;
4782 struct policy_handle handle;
4783 struct spoolss_DevmodeContainer devmode_ctr;
4784 union spoolss_PrinterInfo info;
4786 if (!str1 || !str2 || !p) {
4790 memset((char *)&desc,'\0',sizeof(desc));
4792 p = skip_string(param,tpscnt,p);
4796 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4798 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4800 /* check it's a supported varient */
4801 if (strcmp(str1,"zWrLh") != 0) {
4804 if (!check_printdest_info(&desc,uLevel,str2)) {
4808 ZERO_STRUCT(handle);
4810 status = rpc_connect_spoolss_pipe(conn, &cli);
4811 if (!NT_STATUS_IS_OK(status)) {
4812 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4813 nt_errstr(status)));
4814 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4818 ZERO_STRUCT(devmode_ctr);
4820 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4824 SEC_FLAG_MAXIMUM_ALLOWED,
4827 if (!NT_STATUS_IS_OK(status)) {
4829 desc.errcode = NERR_DestNotFound;
4833 if (!W_ERROR_IS_OK(werr)) {
4835 desc.errcode = NERR_DestNotFound;
4840 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
4845 if (!W_ERROR_IS_OK(werr)) {
4847 desc.errcode = NERR_DestNotFound;
4853 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4858 desc.buflen = mdrcnt;
4861 * Don't return data but need to get correct length
4862 * init_package will return wrong size if buflen=0
4864 desc.buflen = getlen(desc.format);
4865 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4867 if (init_package(&desc,1,0)) {
4868 fill_printdest_info(&info.info2, uLevel,&desc);
4872 if (cli && is_valid_policy_hnd(&handle)) {
4873 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4876 *rdata_len = desc.usedlen;
4879 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4883 SSVALS(*rparam,0,desc.errcode);
4885 SSVAL(*rparam,4,desc.neededlen);
4887 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4893 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4894 char *param, int tpscnt,
4895 char *data, int tdscnt,
4896 int mdrcnt,int mprcnt,
4897 char **rdata,char **rparam,
4898 int *rdata_len,int *rparam_len)
4900 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4901 char *str2 = skip_string(param,tpscnt,str1);
4902 char *p = skip_string(param,tpscnt,str2);
4906 struct pack_desc desc;
4908 TALLOC_CTX *mem_ctx = talloc_tos();
4911 struct rpc_pipe_client *cli = NULL;
4912 union spoolss_PrinterInfo *info;
4915 if (!str1 || !str2 || !p) {
4919 memset((char *)&desc,'\0',sizeof(desc));
4921 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4923 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4925 /* check it's a supported varient */
4926 if (strcmp(str1,"WrLeh") != 0) {
4929 if (!check_printdest_info(&desc,uLevel,str2)) {
4935 status = rpc_connect_spoolss_pipe(conn, &cli);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
4938 nt_errstr(status)));
4939 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4943 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
4945 cli->srv_name_slash,
4950 if (!W_ERROR_IS_OK(werr)) {
4951 desc.errcode = W_ERROR_V(werr);
4953 desc.errcode = NERR_DestNotFound;
4961 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4968 desc.buflen = mdrcnt;
4969 if (init_package(&desc,queuecnt,0)) {
4972 for (i = 0; i < count; i++) {
4973 fill_printdest_info(&info[i].info2, uLevel,&desc);
4975 if (desc.errcode == NERR_Success) {
4981 *rdata_len = desc.usedlen;
4984 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4988 SSVALS(*rparam,0,desc.errcode);
4990 SSVAL(*rparam,4,succnt);
4991 SSVAL(*rparam,6,queuecnt);
4993 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4998 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4999 char *param, int tpscnt,
5000 char *data, int tdscnt,
5001 int mdrcnt,int mprcnt,
5002 char **rdata,char **rparam,
5003 int *rdata_len,int *rparam_len)
5005 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5006 char *str2 = skip_string(param,tpscnt,str1);
5007 char *p = skip_string(param,tpscnt,str2);
5010 struct pack_desc desc;
5012 if (!str1 || !str2 || !p) {
5016 memset((char *)&desc,'\0',sizeof(desc));
5018 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5020 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5022 /* check it's a supported varient */
5023 if (strcmp(str1,"WrLeh") != 0) {
5026 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5031 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5037 desc.buflen = mdrcnt;
5038 if (init_package(&desc,1,0)) {
5039 PACKS(&desc,"B41","NULL");
5042 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5044 *rdata_len = desc.usedlen;
5047 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5051 SSVALS(*rparam,0,desc.errcode);
5053 SSVAL(*rparam,4,succnt);
5056 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5061 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
5062 char *param, int tpscnt,
5063 char *data, int tdscnt,
5064 int mdrcnt,int mprcnt,
5065 char **rdata,char **rparam,
5066 int *rdata_len,int *rparam_len)
5068 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5069 char *str2 = skip_string(param,tpscnt,str1);
5070 char *p = skip_string(param,tpscnt,str2);
5073 struct pack_desc desc;
5075 if (!str1 || !str2 || !p) {
5078 memset((char *)&desc,'\0',sizeof(desc));
5080 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5082 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5084 /* check it's a supported varient */
5085 if (strcmp(str1,"WrLeh") != 0) {
5088 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5093 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5099 desc.buflen = mdrcnt;
5101 if (init_package(&desc,1,0)) {
5102 PACKS(&desc,"B13","lpd");
5105 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5107 *rdata_len = desc.usedlen;
5110 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5114 SSVALS(*rparam,0,desc.errcode);
5116 SSVAL(*rparam,4,succnt);
5119 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5124 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
5125 char *param, int tpscnt,
5126 char *data, int tdscnt,
5127 int mdrcnt,int mprcnt,
5128 char **rdata,char **rparam,
5129 int *rdata_len,int *rparam_len)
5131 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5132 char *str2 = skip_string(param,tpscnt,str1);
5133 char *p = skip_string(param,tpscnt,str2);
5136 struct pack_desc desc;
5138 if (!str1 || !str2 || !p) {
5142 memset((char *)&desc,'\0',sizeof(desc));
5144 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5146 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5148 /* check it's a supported varient */
5149 if (strcmp(str1,"WrLeh") != 0) {
5152 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5157 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5162 memset((char *)&desc,'\0',sizeof(desc));
5164 desc.buflen = mdrcnt;
5166 if (init_package(&desc,1,0)) {
5167 PACKS(&desc,"B13","lp0");
5170 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5172 *rdata_len = desc.usedlen;
5175 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5179 SSVALS(*rparam,0,desc.errcode);
5181 SSVAL(*rparam,4,succnt);
5184 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5189 /****************************************************************************
5191 ****************************************************************************/
5193 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
5194 char *param, int tpscnt,
5195 char *data, int tdscnt,
5196 int mdrcnt,int mprcnt,
5197 char **rdata,char **rparam,
5198 int *rdata_len,int *rparam_len)
5201 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5202 char *str2 = skip_string(param,tpscnt,str1);
5203 char *p = skip_string(param,tpscnt,str2);
5205 struct pack_desc desc;
5206 struct sessionid *session_list;
5207 int i, num_sessions;
5209 if (!str1 || !str2 || !p) {
5213 memset((char *)&desc,'\0',sizeof(desc));
5215 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5217 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5218 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5219 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5221 /* check it's a supported varient */
5222 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5225 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5229 num_sessions = list_sessions(talloc_tos(), &session_list);
5232 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5237 memset((char *)&desc,'\0',sizeof(desc));
5239 desc.buflen = mdrcnt;
5241 if (!init_package(&desc,num_sessions,0)) {
5245 for(i=0; i<num_sessions; i++) {
5246 PACKS(&desc, "z", session_list[i].remote_machine);
5247 PACKS(&desc, "z", session_list[i].username);
5248 PACKI(&desc, "W", 1); /* num conns */
5249 PACKI(&desc, "W", 0); /* num opens */
5250 PACKI(&desc, "W", 1); /* num users */
5251 PACKI(&desc, "D", 0); /* session time */
5252 PACKI(&desc, "D", 0); /* idle time */
5253 PACKI(&desc, "D", 0); /* flags */
5254 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5257 *rdata_len = desc.usedlen;
5260 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5264 SSVALS(*rparam,0,desc.errcode);
5265 SSVAL(*rparam,2,0); /* converter */
5266 SSVAL(*rparam,4,num_sessions); /* count */
5268 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5274 /****************************************************************************
5275 The buffer was too small.
5276 ****************************************************************************/
5278 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
5279 int mdrcnt, int mprcnt,
5280 char **rdata, char **rparam,
5281 int *rdata_len, int *rparam_len)
5283 *rparam_len = MIN(*rparam_len,mprcnt);
5284 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5291 SSVAL(*rparam,0,NERR_BufTooSmall);
5293 DEBUG(3,("Supplied buffer too small in API command\n"));
5298 /****************************************************************************
5299 The request is not supported.
5300 ****************************************************************************/
5302 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
5303 char *param, int tpscnt,
5304 char *data, int tdscnt,
5305 int mdrcnt, int mprcnt,
5306 char **rdata, char **rparam,
5307 int *rdata_len, int *rparam_len)
5310 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5317 SSVAL(*rparam,0,NERR_notsupported);
5318 SSVAL(*rparam,2,0); /* converter word */
5320 DEBUG(3,("Unsupported API command\n"));
5325 static const struct {
5328 bool (*fn)(connection_struct *, uint16,
5331 int,int,char **,char **,int *,int *);
5332 bool auth_user; /* Deny anonymous access? */
5333 } api_commands[] = {
5334 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5335 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5336 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5337 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5338 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5339 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5340 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5341 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5342 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5343 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5344 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5345 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5346 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5347 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5348 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5349 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5350 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5351 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5352 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5353 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5354 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5355 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5356 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5357 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5358 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5359 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5360 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5361 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5362 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5363 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5364 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5365 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5366 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5367 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5368 {NULL, -1, api_Unsupported}
5369 /* The following RAP calls are not implemented by Samba:
5371 RAP_WFileEnum2 - anon not OK
5376 /****************************************************************************
5377 Handle remote api calls.
5378 ****************************************************************************/
5380 void api_reply(connection_struct *conn, uint16 vuid,
5381 struct smb_request *req,
5382 char *data, char *params,
5383 int tdscnt, int tpscnt,
5384 int mdrcnt, int mprcnt)
5386 struct smbd_server_connection *sconn = smbd_server_conn;
5389 char *rparam = NULL;
5390 const char *name1 = NULL;
5391 const char *name2 = NULL;
5398 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5407 api_command = SVAL(params,0);
5408 /* Is there a string at position params+2 ? */
5409 if (skip_string(params,tpscnt,params+2)) {
5414 name2 = skip_string(params,tpscnt,params+2);
5419 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5423 tdscnt,tpscnt,mdrcnt,mprcnt));
5425 for (i=0;api_commands[i].name;i++) {
5426 if (api_commands[i].id == api_command && api_commands[i].fn) {
5427 DEBUG(3,("Doing %s\n",api_commands[i].name));
5432 /* Check whether this api call can be done anonymously */
5434 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5435 user_struct *user = get_valid_user_struct(sconn, vuid);
5437 if (!user || user->server_info->guest) {
5438 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5443 rdata = (char *)SMB_MALLOC(1024);
5445 memset(rdata,'\0',1024);
5448 rparam = (char *)SMB_MALLOC(1024);
5450 memset(rparam,'\0',1024);
5453 if(!rdata || !rparam) {
5454 DEBUG(0,("api_reply: malloc fail !\n"));
5457 reply_nterror(req, NT_STATUS_NO_MEMORY);
5461 reply = api_commands[i].fn(conn,
5463 params,tpscnt, /* params + length */
5464 data,tdscnt, /* data + length */
5466 &rdata,&rparam,&rdata_len,&rparam_len);
5469 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5470 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
5471 &rdata,&rparam,&rdata_len,&rparam_len);
5474 /* if we get False back then it's actually unsupported */
5476 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
5477 &rdata,&rparam,&rdata_len,&rparam_len);
5480 /* If api_Unsupported returns false we can't return anything. */
5482 send_trans_reply(conn, req, rparam, rparam_len,
5483 rdata, rdata_len, False);