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"
36 #define NERR_Success 0
37 #define NERR_badpass 86
38 #define NERR_notsupported 50
40 #define NERR_BASE (2100)
41 #define NERR_BufTooSmall (NERR_BASE+23)
42 #define NERR_JobNotFound (NERR_BASE+51)
43 #define NERR_DestNotFound (NERR_BASE+52)
45 #define ACCESS_READ 0x01
46 #define ACCESS_WRITE 0x02
47 #define ACCESS_CREATE 0x04
49 #define SHPWLEN 8 /* share password length */
51 /* Limit size of ipc replies */
53 static char *smb_realloc_limit(void *ptr, size_t size)
57 size = MAX((size),4*1024);
58 val = (char *)SMB_REALLOC(ptr,size);
60 memset(val,'\0',size);
65 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
66 char *param, int tpscnt,
67 char *data, int tdscnt,
68 int mdrcnt, int mprcnt,
69 char **rdata, char **rparam,
70 int *rdata_len, int *rparam_len);
72 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
73 int mdrcnt, int mprcnt,
74 char **rdata, char **rparam,
75 int *rdata_len, int *rparam_len);
78 static int CopyExpanded(connection_struct *conn,
79 int snum, char **dst, char *src, int *p_space_remaining)
81 TALLOC_CTX *ctx = talloc_tos();
85 if (!src || !dst || !p_space_remaining || !(*dst) ||
86 *p_space_remaining <= 0) {
90 buf = talloc_strdup(ctx, src);
92 *p_space_remaining = 0;
95 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
97 *p_space_remaining = 0;
100 buf = talloc_sub_advanced(ctx,
101 lp_servicename(SNUM(conn)),
102 conn->server_info->unix_name,
104 conn->server_info->utok.gid,
105 conn->server_info->sanitized_username,
106 pdb_get_domain(conn->server_info->sam_account),
109 *p_space_remaining = 0;
112 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
117 (*p_space_remaining) -= l;
121 static int CopyAndAdvance(char **dst, char *src, int *n)
124 if (!src || !dst || !n || !(*dst)) {
127 l = push_ascii(*dst,src,*n, STR_TERMINATE);
136 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
138 TALLOC_CTX *ctx = talloc_tos();
143 buf = talloc_strdup(ctx,s);
147 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
151 buf = talloc_sub_advanced(ctx,
152 lp_servicename(SNUM(conn)),
153 conn->server_info->unix_name,
155 conn->server_info->utok.gid,
156 conn->server_info->sanitized_username,
157 pdb_get_domain(conn->server_info->sam_account),
162 return strlen(buf) + 1;
165 static char *Expand(connection_struct *conn, int snum, char *s)
167 TALLOC_CTX *ctx = talloc_tos();
173 buf = talloc_strdup(ctx,s);
177 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
181 return talloc_sub_advanced(ctx,
182 lp_servicename(SNUM(conn)),
183 conn->server_info->unix_name,
185 conn->server_info->utok.gid,
186 conn->server_info->sanitized_username,
187 pdb_get_domain(conn->server_info->sam_account),
191 /*******************************************************************
192 Check a API string for validity when we only need to check the prefix.
193 ******************************************************************/
195 static bool prefix_ok(const char *str, const char *prefix)
197 return(strncmp(str,prefix,strlen(prefix)) == 0);
201 const char *format; /* formatstring for structure */
202 const char *subformat; /* subformat for structure */
203 char *base; /* baseaddress of buffer */
204 int buflen; /* remaining size for fixed part; on init: length of base */
205 int subcount; /* count of substructures */
206 char *structbuf; /* pointer into buffer for remaining fixed part */
207 int stringlen; /* remaining size for variable part */
208 char *stringbuf; /* pointer into buffer for remaining variable part */
209 int neededlen; /* total needed size */
210 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
211 const char *curpos; /* current position; pointer into format or subformat */
215 static int get_counter(const char **p)
221 if (!isdigit((int)**p)) {
227 n = 10 * n + (i - '0');
235 static int getlen(const char *p)
244 case 'W': /* word (2 byte) */
247 case 'K': /* status word? (2 byte) */
250 case 'N': /* count of substructures (word) at end */
253 case 'D': /* double word (4 byte) */
254 case 'z': /* offset to zero terminated string (4 byte) */
255 case 'l': /* offset to user data (4 byte) */
258 case 'b': /* offset to data (with counter) (4 byte) */
262 case 'B': /* byte (with optional counter) */
263 n += get_counter(&p);
270 static bool init_package(struct pack_desc *p, int count, int subcount)
275 if (!p->format || !p->base) {
279 i = count * getlen(p->format);
281 i += subcount * getlen(p->subformat);
283 p->structbuf = p->base;
287 p->curpos = p->format;
293 * This is the old error code we used. Aparently
294 * WinNT/2k systems return ERRbuftoosmall (2123) and
295 * OS/2 needs this. I'm leaving this here so we can revert
298 p->errcode = ERRmoredata;
300 p->errcode = ERRbuftoosmall;
303 p->errcode = NERR_Success;
307 p->stringbuf = p->base + i;
309 return (p->errcode == NERR_Success);
312 static int package(struct pack_desc *p, ...)
315 int needed=0, stringneeded;
316 const char *str=NULL;
317 int is_string=0, stringused;
324 p->curpos = p->format;
326 p->curpos = p->subformat;
331 str = va_arg(args,char*);
332 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
341 switch( *p->curpos++ ) {
342 case 'W': /* word (2 byte) */
344 temp = va_arg(args,int);
345 if (p->buflen >= needed) {
346 SSVAL(p->structbuf,0,temp);
349 case 'K': /* status word? (2 byte) */
351 temp = va_arg(args,int);
352 if (p->buflen >= needed) {
353 SSVAL(p->structbuf,0,temp);
356 case 'N': /* count of substructures (word) at end */
358 p->subcount = va_arg(args,int);
359 if (p->buflen >= needed) {
360 SSVAL(p->structbuf,0,p->subcount);
363 case 'D': /* double word (4 byte) */
365 temp = va_arg(args,int);
366 if (p->buflen >= needed) {
367 SIVAL(p->structbuf,0,temp);
370 case 'B': /* byte (with optional counter) */
371 needed = get_counter(&p->curpos);
373 char *s = va_arg(args,char*);
374 if (p->buflen >= needed) {
375 StrnCpy(p->structbuf,s?s:"",needed-1);
379 case 'z': /* offset to zero terminated string (4 byte) */
380 str = va_arg(args,char*);
381 stringneeded = (str ? strlen(str)+1 : 0);
384 case 'l': /* offset to user data (4 byte) */
385 str = va_arg(args,char*);
386 stringneeded = va_arg(args,int);
389 case 'b': /* offset to data (with counter) (4 byte) */
390 str = va_arg(args,char*);
391 stringneeded = get_counter(&p->curpos);
397 if (stringneeded >= 0) {
399 if (p->buflen >= needed) {
400 stringused = stringneeded;
401 if (stringused > p->stringlen) {
402 stringused = (is_string ? p->stringlen : 0);
403 if (p->errcode == NERR_Success) {
404 p->errcode = ERRmoredata;
408 SIVAL(p->structbuf,0,0);
410 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
411 memcpy(p->stringbuf,str?str:"",stringused);
413 p->stringbuf[stringused-1] = '\0';
415 p->stringbuf += stringused;
416 p->stringlen -= stringused;
417 p->usedlen += stringused;
420 p->neededlen += stringneeded;
423 p->neededlen += needed;
424 if (p->buflen >= needed) {
425 p->structbuf += needed;
427 p->usedlen += needed;
429 if (p->errcode == NERR_Success) {
430 p->errcode = ERRmoredata;
437 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
438 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
440 #define PACK(desc,t,v) package(desc,v)
441 #define PACKl(desc,t,v,l) package(desc,v,l)
444 static void PACKI(struct pack_desc* desc, const char *t,int v)
449 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
454 /****************************************************************************
456 ****************************************************************************/
458 static void PackDriverData(struct pack_desc* desc)
460 char drivdata[4+4+32];
461 SIVAL(drivdata,0,sizeof drivdata); /* cb */
462 SIVAL(drivdata,4,1000); /* lVersion */
463 memset(drivdata+8,0,32); /* szDeviceName */
464 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
465 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
468 static int check_printq_info(struct pack_desc* desc,
469 unsigned int uLevel, char *id1, char *id2)
471 desc->subformat = NULL;
474 desc->format = "B13";
477 desc->format = "B13BWWWzzzzzWW";
480 desc->format = "B13BWWWzzzzzWN";
481 desc->subformat = "WB21BB16B10zWWzDDz";
484 desc->format = "zWWWWzzzzWWzzl";
487 desc->format = "zWWWWzzzzWNzzl";
488 desc->subformat = "WWzWWDDzz";
497 desc->format = "WzzzzzzzzN";
498 desc->subformat = "z";
501 DEBUG(0,("check_printq_info: invalid level %d\n",
505 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
506 DEBUG(0,("check_printq_info: invalid format %s\n",
507 id1 ? id1 : "<NULL>" ));
510 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
511 DEBUG(0,("check_printq_info: invalid subformat %s\n",
512 id2 ? id2 : "<NULL>" ));
519 #define RAP_JOB_STATUS_QUEUED 0
520 #define RAP_JOB_STATUS_PAUSED 1
521 #define RAP_JOB_STATUS_SPOOLING 2
522 #define RAP_JOB_STATUS_PRINTING 3
523 #define RAP_JOB_STATUS_PRINTED 4
525 #define RAP_QUEUE_STATUS_PAUSED 1
526 #define RAP_QUEUE_STATUS_ERROR 2
528 /* turn a print job status into a on the wire status
530 static int printj_status(int v)
534 return RAP_JOB_STATUS_QUEUED;
536 return RAP_JOB_STATUS_PAUSED;
538 return RAP_JOB_STATUS_SPOOLING;
540 return RAP_JOB_STATUS_PRINTING;
545 /* turn a print queue status into a on the wire status
547 static int printq_status(int v)
553 return RAP_QUEUE_STATUS_PAUSED;
555 return RAP_QUEUE_STATUS_ERROR;
558 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
559 struct pack_desc *desc,
560 print_queue_struct *queue, int n)
562 time_t t = queue->time;
564 /* the client expects localtime */
565 t -= get_time_zone(t);
567 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
569 PACKS(desc,"B21",queue->fs_user); /* szUserName */
570 PACKS(desc,"B",""); /* pad */
571 PACKS(desc,"B16",""); /* szNotifyName */
572 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
573 PACKS(desc,"z",""); /* pszParms */
574 PACKI(desc,"W",n+1); /* uPosition */
575 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
576 PACKS(desc,"z",""); /* pszStatus */
577 PACKI(desc,"D",t); /* ulSubmitted */
578 PACKI(desc,"D",queue->size); /* ulSize */
579 PACKS(desc,"z",queue->fs_file); /* pszComment */
581 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
582 PACKI(desc,"W",queue->priority); /* uPriority */
583 PACKS(desc,"z",queue->fs_user); /* pszUserName */
584 PACKI(desc,"W",n+1); /* uPosition */
585 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
586 PACKI(desc,"D",t); /* ulSubmitted */
587 PACKI(desc,"D",queue->size); /* ulSize */
588 PACKS(desc,"z","Samba"); /* pszComment */
589 PACKS(desc,"z",queue->fs_file); /* pszDocument */
591 PACKS(desc,"z",""); /* pszNotifyName */
592 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
593 PACKS(desc,"z",""); /* pszParms */
594 PACKS(desc,"z",""); /* pszStatus */
595 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
596 PACKS(desc,"z","lpd"); /* pszQProcName */
597 PACKS(desc,"z",""); /* pszQProcParms */
598 PACKS(desc,"z","NULL"); /* pszDriverName */
599 PackDriverData(desc); /* pDriverData */
600 PACKS(desc,"z",""); /* pszPrinterName */
601 } else if (uLevel == 4) { /* OS2 */
602 PACKS(desc,"z",""); /* pszSpoolFileName */
603 PACKS(desc,"z",""); /* pszPortName */
604 PACKS(desc,"z",""); /* pszStatus */
605 PACKI(desc,"D",0); /* ulPagesSpooled */
606 PACKI(desc,"D",0); /* ulPagesSent */
607 PACKI(desc,"D",0); /* ulPagesPrinted */
608 PACKI(desc,"D",0); /* ulTimePrinted */
609 PACKI(desc,"D",0); /* ulExtendJobStatus */
610 PACKI(desc,"D",0); /* ulStartPage */
611 PACKI(desc,"D",0); /* ulEndPage */
616 /********************************************************************
617 Return a driver name given an snum.
618 Returns True if from tdb, False otherwise.
619 ********************************************************************/
621 static bool get_driver_name(int snum, char **pp_drivername)
623 NT_PRINTER_INFO_LEVEL *info = NULL;
626 get_a_printer (NULL, &info, 2, lp_servicename(snum));
628 *pp_drivername = talloc_strdup(talloc_tos(),
629 info->info_2->drivername);
631 free_a_printer(&info, 2);
632 if (!*pp_drivername) {
640 /********************************************************************
641 Respond to the DosPrintQInfo command with a level of 52
642 This is used to get printer driver information for Win9x clients
643 ********************************************************************/
644 static void fill_printq_info_52(connection_struct *conn, int snum,
645 struct pack_desc* desc, int count )
649 union spoolss_DriverInfo *driver = NULL;
650 NT_PRINTER_INFO_LEVEL *printer = NULL;
652 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
653 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
654 lp_servicename(snum)));
658 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, 3, printer->info_2->drivername,
661 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
662 printer->info_2->drivername));
666 trim_string((char *)driver->info3.driver_path, "\\print$\\WIN40\\0\\", 0);
667 trim_string((char *)driver->info3.data_file, "\\print$\\WIN40\\0\\", 0);
668 trim_string((char *)driver->info3.help_file, "\\print$\\WIN40\\0\\", 0);
670 PACKI(desc, "W", 0x0400); /* don't know */
671 PACKS(desc, "z", driver->info3.driver_name); /* long printer name */
672 PACKS(desc, "z", driver->info3.driver_path); /* Driverfile Name */
673 PACKS(desc, "z", driver->info3.data_file); /* Datafile name */
674 PACKS(desc, "z", driver->info3.monitor_name); /* language monitor */
676 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
677 standard_sub_basic( "", "", location, sizeof(location)-1 );
678 PACKS(desc,"z", location); /* share to retrieve files */
680 PACKS(desc,"z", driver->info3.default_datatype); /* default data type */
681 PACKS(desc,"z", driver->info3.help_file); /* helpfile name */
682 PACKS(desc,"z", driver->info3.driver_path); /* driver name */
684 DEBUG(3,("Printer Driver Name: %s:\n",driver->info3.driver_name));
685 DEBUG(3,("Driver: %s:\n",driver->info3.driver_path));
686 DEBUG(3,("Data File: %s:\n",driver->info3.data_file));
687 DEBUG(3,("Language Monitor: %s:\n",driver->info3.monitor_name));
688 DEBUG(3,("Driver Location: %s:\n",location));
689 DEBUG(3,("Data Type: %s:\n",driver->info3.default_datatype));
690 DEBUG(3,("Help File: %s:\n",driver->info3.help_file));
691 PACKI(desc,"N",count); /* number of files to copy */
693 for ( i=0; i<count && driver->info3.dependent_files && *driver->info3.dependent_files[i]; i++)
695 trim_string((char *)driver->info3.dependent_files[i], "\\print$\\WIN40\\0\\", 0);
696 PACKS(desc,"z",driver->info3.dependent_files[i]); /* driver files to copy */
697 DEBUG(3,("Dependent File: %s:\n", driver->info3.dependent_files[i]));
702 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
705 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
707 desc->errcode=NERR_Success;
711 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
712 desc->errcode=NERR_notsupported;
716 free_a_printer( &printer, 2 );
718 free_a_printer_driver(driver);
722 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
723 struct pack_desc* desc,
724 int count, print_queue_struct* queue,
725 print_status_struct* status)
730 PACKS(desc,"B13",SERVICE(snum));
735 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
738 PACKI(desc,"K",printq_status(status->status));
742 if (uLevel == 1 || uLevel == 2) {
743 PACKS(desc,"B",""); /* alignment */
744 PACKI(desc,"W",5); /* priority */
745 PACKI(desc,"W",0); /* start time */
746 PACKI(desc,"W",0); /* until time */
747 PACKS(desc,"z",""); /* pSepFile */
748 PACKS(desc,"z","lpd"); /* pPrProc */
749 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
750 PACKS(desc,"z",""); /* pParms */
752 PACKS(desc,"z","UNKNOWN PRINTER");
753 PACKI(desc,"W",LPSTAT_ERROR);
755 else if (!status || !status->message[0]) {
756 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
757 PACKI(desc,"W",LPSTAT_OK); /* status */
759 PACKS(desc,"z",status->message);
760 PACKI(desc,"W",printq_status(status->status)); /* status */
762 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
765 if (uLevel == 3 || uLevel == 4) {
766 char *drivername = NULL;
768 PACKI(desc,"W",5); /* uPriority */
769 PACKI(desc,"W",0); /* uStarttime */
770 PACKI(desc,"W",0); /* uUntiltime */
771 PACKI(desc,"W",5); /* pad1 */
772 PACKS(desc,"z",""); /* pszSepFile */
773 PACKS(desc,"z","WinPrint"); /* pszPrProc */
774 PACKS(desc,"z",NULL); /* pszParms */
775 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
776 /* "don't ask" that it's done this way to fix corrupted
777 Win9X/ME printer comments. */
779 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
781 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
783 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
784 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
785 get_driver_name(snum,&drivername);
789 PACKS(desc,"z",drivername); /* pszDriverName */
790 PackDriverData(desc); /* pDriverData */
793 if (uLevel == 2 || uLevel == 4) {
795 for (i=0;i<count;i++)
796 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
800 fill_printq_info_52( conn, snum, desc, count );
803 /* This function returns the number of files for a given driver */
804 static int get_printerdrivernumber(int snum)
807 union spoolss_DriverInfo *driver;
808 NT_PRINTER_INFO_LEVEL *printer = NULL;
812 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
813 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
814 lp_servicename(snum)));
818 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, 3, printer->info_2->drivername,
821 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
822 printer->info_2->drivername));
826 /* count the number of files */
827 while (driver->info3.dependent_files && *driver->info3.dependent_files[result])
831 free_a_printer( &printer, 2 );
833 free_a_printer_driver(driver);
838 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
839 char *param, int tpscnt,
840 char *data, int tdscnt,
841 int mdrcnt,int mprcnt,
842 char **rdata,char **rparam,
843 int *rdata_len,int *rparam_len)
845 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
846 char *str2 = skip_string(param,tpscnt,str1);
847 char *p = skip_string(param,tpscnt,str2);
853 struct pack_desc desc;
854 print_queue_struct *queue=NULL;
855 print_status_struct status;
858 if (!str1 || !str2 || !p) {
861 memset((char *)&status,'\0',sizeof(status));
862 memset((char *)&desc,'\0',sizeof(desc));
864 p = skip_string(param,tpscnt,p);
868 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
869 str3 = get_safe_str_ptr(param,tpscnt,p,4);
870 /* str3 may be null here and is checked in check_printq_info(). */
872 /* remove any trailing username */
873 if ((p = strchr_m(QueueName,'%')))
876 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
878 /* check it's a supported varient */
879 if (!prefix_ok(str1,"zWrLh"))
881 if (!check_printq_info(&desc,uLevel,str2,str3)) {
883 * Patch from Scott Moomaw <scott@bridgewater.edu>
884 * to return the 'invalid info level' error if an
885 * unknown level was requested.
889 *rparam = smb_realloc_limit(*rparam,*rparam_len);
893 SSVALS(*rparam,0,ERRunknownlevel);
899 snum = find_service(QueueName);
900 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
904 count = get_printerdrivernumber(snum);
905 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
907 count = print_queue_status(snum, &queue,&status);
911 *rdata = smb_realloc_limit(*rdata,mdrcnt);
917 desc.buflen = mdrcnt;
920 * Don't return data but need to get correct length
921 * init_package will return wrong size if buflen=0
923 desc.buflen = getlen(desc.format);
924 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
927 if (init_package(&desc,1,count)) {
928 desc.subcount = count;
929 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
932 *rdata_len = desc.usedlen;
935 * We must set the return code to ERRbuftoosmall
936 * in order to support lanman style printing with Win NT/2k
939 if (!mdrcnt && lp_disable_spoolss())
940 desc.errcode = ERRbuftoosmall;
942 *rdata_len = desc.usedlen;
944 *rparam = smb_realloc_limit(*rparam,*rparam_len);
950 SSVALS(*rparam,0,desc.errcode);
952 SSVAL(*rparam,4,desc.neededlen);
954 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
962 /****************************************************************************
963 View list of all print jobs on all queues.
964 ****************************************************************************/
966 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
967 char *param, int tpscnt,
968 char *data, int tdscnt,
969 int mdrcnt, int mprcnt,
970 char **rdata, char** rparam,
971 int *rdata_len, int *rparam_len)
973 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
974 char *output_format1 = skip_string(param,tpscnt,param_format);
975 char *p = skip_string(param,tpscnt,output_format1);
976 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
977 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
978 int services = lp_numservices();
980 struct pack_desc desc;
981 print_queue_struct **queue = NULL;
982 print_status_struct *status = NULL;
983 int *subcntarr = NULL;
984 int queuecnt = 0, subcnt = 0, succnt = 0;
986 if (!param_format || !output_format1 || !p) {
990 memset((char *)&desc,'\0',sizeof(desc));
992 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
994 if (!prefix_ok(param_format,"WrLeh")) {
997 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
999 * Patch from Scott Moomaw <scott@bridgewater.edu>
1000 * to return the 'invalid info level' error if an
1001 * unknown level was requested.
1005 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1009 SSVALS(*rparam,0,ERRunknownlevel);
1015 for (i = 0; i < services; i++) {
1016 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1021 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1022 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1025 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1026 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1027 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1030 memset(status,0,queuecnt*sizeof(print_status_struct));
1031 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1032 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1038 for (i = 0; i < services; i++) {
1039 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1040 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1041 subcnt += subcntarr[n];
1047 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1053 desc.buflen = mdrcnt;
1055 if (init_package(&desc,queuecnt,subcnt)) {
1058 for (i = 0; i < services; i++) {
1059 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1060 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1062 if (desc.errcode == NERR_Success) {
1069 SAFE_FREE(subcntarr);
1071 *rdata_len = desc.usedlen;
1073 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1077 SSVALS(*rparam,0,desc.errcode);
1079 SSVAL(*rparam,4,succnt);
1080 SSVAL(*rparam,6,queuecnt);
1082 for (i = 0; i < queuecnt; i++) {
1084 SAFE_FREE(queue[i]);
1095 SAFE_FREE(subcntarr);
1096 for (i = 0; i < queuecnt; i++) {
1098 SAFE_FREE(queue[i]);
1107 /****************************************************************************
1108 Get info level for a server list query.
1109 ****************************************************************************/
1111 static bool check_server_info(int uLevel, char* id)
1115 if (strcmp(id,"B16") != 0) {
1120 if (strcmp(id,"B16BBDz") != 0) {
1130 struct srv_info_struct {
1138 /*******************************************************************
1139 Get server info lists from the files saved by nmbd. Return the
1141 ******************************************************************/
1143 static int get_server_info(uint32 servertype,
1144 struct srv_info_struct **servers,
1150 bool local_list_only;
1153 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1155 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1159 /* request for everything is code for request all servers */
1160 if (servertype == SV_TYPE_ALL) {
1161 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1164 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1166 DEBUG(4,("Servertype search: %8x\n",servertype));
1168 for (i=0;lines[i];i++) {
1170 struct srv_info_struct *s;
1171 const char *ptr = lines[i];
1173 TALLOC_CTX *frame = NULL;
1180 if (count == alloced) {
1182 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1184 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1188 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1190 s = &(*servers)[count];
1192 frame = talloc_stackframe();
1194 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1198 fstrcpy(s->name, p);
1201 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1207 s->comment[0] = '\0';
1208 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1212 fstrcpy(s->comment, p);
1213 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1215 s->domain[0] = '\0';
1216 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1217 /* this allows us to cope with an old nmbd */
1218 fstrcpy(s->domain,lp_workgroup());
1220 fstrcpy(s->domain, p);
1224 if (sscanf(stype,"%X",&s->type) != 1) {
1225 DEBUG(4,("r:host file "));
1229 /* Filter the servers/domains we return based on what was asked for. */
1231 /* Check to see if we are being asked for a local list only. */
1232 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1233 DEBUG(4,("r: local list only"));
1237 /* doesn't match up: don't want it */
1238 if (!(servertype & s->type)) {
1239 DEBUG(4,("r:serv type "));
1243 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1244 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1245 DEBUG(4,("s: dom mismatch "));
1249 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1253 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1254 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1257 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1258 s->name, s->type, s->comment, s->domain));
1259 s->server_added = True;
1262 DEBUG(4,("%20s %8x %25s %15s\n",
1263 s->name, s->type, s->comment, s->domain));
1271 /*******************************************************************
1272 Fill in a server info structure.
1273 ******************************************************************/
1275 static int fill_srv_info(struct srv_info_struct *service,
1276 int uLevel, char **buf, int *buflen,
1277 char **stringbuf, int *stringspace, char *baseaddr)
1300 len = strlen(service->comment)+1;
1304 *buflen = struct_len;
1306 return struct_len + len;
1311 if (*buflen < struct_len) {
1318 p2 = p + struct_len;
1319 l2 = *buflen - struct_len;
1327 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1331 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1332 SIVAL(p,18,service->type);
1333 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1334 len += CopyAndAdvance(&p2,service->comment,&l2);
1339 *buf = p + struct_len;
1340 *buflen -= struct_len;
1351 static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1353 return(strcmp(s1->name,s2->name));
1356 /****************************************************************************
1357 View list of servers available (or possibly domains). The info is
1358 extracted from lists saved by nmbd on the local host.
1359 ****************************************************************************/
1361 static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1362 char *param, int tpscnt,
1363 char *data, int tdscnt,
1364 int mdrcnt, int mprcnt, char **rdata,
1365 char **rparam, int *rdata_len, int *rparam_len)
1367 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1368 char *str2 = skip_string(param,tpscnt,str1);
1369 char *p = skip_string(param,tpscnt,str2);
1370 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1371 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1372 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1374 int data_len, fixed_len, string_len;
1375 int f_len = 0, s_len = 0;
1376 struct srv_info_struct *servers=NULL;
1377 int counted=0,total=0;
1380 bool domain_request;
1383 if (!str1 || !str2 || !p) {
1387 /* If someone sets all the bits they don't really mean to set
1388 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1391 if (servertype == SV_TYPE_ALL) {
1392 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1395 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1396 any other bit (they may just set this bit on its own) they
1397 want all the locally seen servers. However this bit can be
1398 set on its own so set the requested servers to be
1399 ALL - DOMAIN_ENUM. */
1401 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1402 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1405 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1406 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1410 if (!prefix_ok(str1,"WrLehD")) {
1413 if (!check_server_info(uLevel,str2)) {
1417 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1418 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1419 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1421 if (strcmp(str1, "WrLehDz") == 0) {
1422 if (skip_string(param,tpscnt,p) == NULL) {
1425 pull_ascii_fstring(domain, p);
1427 fstrcpy(domain, lp_workgroup());
1430 if (lp_browse_list()) {
1431 total = get_server_info(servertype,&servers,domain);
1434 data_len = fixed_len = string_len = 0;
1438 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1442 char *lastname=NULL;
1444 for (i=0;i<total;i++) {
1445 struct srv_info_struct *s = &servers[i];
1447 if (lastname && strequal(lastname,s->name)) {
1451 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1452 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1453 s->name, s->type, s->comment, s->domain));
1455 if (data_len <= buf_len) {
1458 string_len += s_len;
1465 *rdata_len = fixed_len + string_len;
1466 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1471 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1477 char *lastname=NULL;
1478 int count2 = counted;
1480 for (i = 0; i < total && count2;i++) {
1481 struct srv_info_struct *s = &servers[i];
1483 if (lastname && strequal(lastname,s->name)) {
1487 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1488 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1489 s->name, s->type, s->comment, s->domain));
1495 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1499 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1501 SSVAL(*rparam,4,counted);
1502 SSVAL(*rparam,6,counted+missed);
1506 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1507 domain,uLevel,counted,counted+missed));
1512 /****************************************************************************
1513 command 0x34 - suspected of being a "Lookup Names" stub api
1514 ****************************************************************************/
1516 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1517 char *param, int tpscnt,
1518 char *data, int tdscnt,
1519 int mdrcnt, int mprcnt, char **rdata,
1520 char **rparam, int *rdata_len, int *rparam_len)
1522 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1523 char *str2 = skip_string(param,tpscnt,str1);
1524 char *p = skip_string(param,tpscnt,str2);
1525 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1526 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1530 if (!str1 || !str2 || !p) {
1534 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1535 str1, str2, p, uLevel, buf_len));
1537 if (!prefix_ok(str1,"zWrLeh")) {
1544 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1549 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1551 SSVAL(*rparam,4,counted);
1552 SSVAL(*rparam,6,counted+missed);
1557 /****************************************************************************
1558 get info about a share
1559 ****************************************************************************/
1561 static bool check_share_info(int uLevel, char* id)
1565 if (strcmp(id,"B13") != 0) {
1570 if (strcmp(id,"B13BWz") != 0) {
1575 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1580 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1590 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1591 char** buf, int* buflen,
1592 char** stringbuf, int* stringspace, char* baseaddr)
1621 len += StrlenExpanded(conn,snum,lp_comment(snum));
1624 len += strlen(lp_pathname(snum)) + 1;
1627 *buflen = struct_len;
1632 return struct_len + len;
1637 if ((*buflen) < struct_len) {
1645 p2 = p + struct_len;
1646 l2 = (*buflen) - struct_len;
1653 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1659 type = STYPE_DISKTREE;
1660 if (lp_print_ok(snum)) {
1661 type = STYPE_PRINTQ;
1663 if (strequal("IPC",lp_fstype(snum))) {
1666 SSVAL(p,14,type); /* device type */
1667 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1668 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1672 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1673 SSVALS(p,22,-1); /* max uses */
1674 SSVAL(p,24,1); /* current uses */
1675 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1676 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1677 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1681 memset(p+40,0,SHPWLEN+2);
1692 (*buf) = p + struct_len;
1693 (*buflen) -= struct_len;
1695 (*stringspace) = l2;
1704 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1705 char *param, int tpscnt,
1706 char *data, int tdscnt,
1707 int mdrcnt,int mprcnt,
1708 char **rdata,char **rparam,
1709 int *rdata_len,int *rparam_len)
1711 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1712 char *str2 = skip_string(param,tpscnt,str1);
1713 char *netname = skip_string(param,tpscnt,str2);
1714 char *p = skip_string(param,tpscnt,netname);
1715 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1718 if (!str1 || !str2 || !netname || !p) {
1722 snum = find_service(netname);
1727 /* check it's a supported varient */
1728 if (!prefix_ok(str1,"zWrLh")) {
1731 if (!check_share_info(uLevel,str2)) {
1735 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1740 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1741 if (*rdata_len < 0) {
1746 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1750 SSVAL(*rparam,0,NERR_Success);
1751 SSVAL(*rparam,2,0); /* converter word */
1752 SSVAL(*rparam,4,*rdata_len);
1757 /****************************************************************************
1758 View the list of available shares.
1760 This function is the server side of the NetShareEnum() RAP call.
1761 It fills the return buffer with share names and share comments.
1762 Note that the return buffer normally (in all known cases) allows only
1763 twelve byte strings for share names (plus one for a nul terminator).
1764 Share names longer than 12 bytes must be skipped.
1765 ****************************************************************************/
1767 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1768 char *param, int tpscnt,
1769 char *data, int tdscnt,
1777 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1778 char *str2 = skip_string(param,tpscnt,str1);
1779 char *p = skip_string(param,tpscnt,str2);
1780 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1781 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1784 int total=0,counted=0;
1785 bool missed = False;
1787 int data_len, fixed_len, string_len;
1788 int f_len = 0, s_len = 0;
1790 if (!str1 || !str2 || !p) {
1794 if (!prefix_ok(str1,"WrLeh")) {
1797 if (!check_share_info(uLevel,str2)) {
1801 /* Ensure all the usershares are loaded. */
1803 load_registry_shares();
1804 count = load_usershare_shares();
1807 data_len = fixed_len = string_len = 0;
1808 for (i=0;i<count;i++) {
1809 fstring servicename_dos;
1810 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1813 push_ascii_fstring(servicename_dos, lp_servicename(i));
1814 /* Maximum name length = 13. */
1815 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1817 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1818 if (data_len <= buf_len) {
1821 string_len += s_len;
1828 *rdata_len = fixed_len + string_len;
1829 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1834 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1839 for( i = 0; i < count; i++ ) {
1840 fstring servicename_dos;
1841 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1845 push_ascii_fstring(servicename_dos, lp_servicename(i));
1846 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1847 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1854 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1858 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1860 SSVAL(*rparam,4,counted);
1861 SSVAL(*rparam,6,total);
1863 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1864 counted,total,uLevel,
1865 buf_len,*rdata_len,mdrcnt));
1870 /****************************************************************************
1872 ****************************************************************************/
1874 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1875 char *param, int tpscnt,
1876 char *data, int tdscnt,
1877 int mdrcnt,int mprcnt,
1878 char **rdata,char **rparam,
1879 int *rdata_len,int *rparam_len)
1881 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1882 char *str2 = skip_string(param,tpscnt,str1);
1883 char *p = skip_string(param,tpscnt,str2);
1884 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1887 char *pathname = NULL;
1888 char *command, *cmdname;
1889 unsigned int offset;
1892 size_t converted_size;
1894 if (!str1 || !str2 || !p) {
1898 /* check it's a supported varient */
1899 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1902 if (!check_share_info(uLevel,str2)) {
1909 /* Do we have a string ? */
1910 if (skip_string(data,mdrcnt,data) == NULL) {
1913 pull_ascii_fstring(sharename,data);
1914 snum = find_service(sharename);
1915 if (snum >= 0) { /* already exists */
1924 /* only support disk share adds */
1925 if (SVAL(data,14)!=STYPE_DISKTREE) {
1929 offset = IVAL(data, 16);
1930 if (offset >= mdrcnt) {
1931 res = ERRinvalidparam;
1935 /* Do we have a string ? */
1936 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1939 pull_ascii_fstring(comment, offset? (data+offset) : "");
1941 offset = IVAL(data, 26);
1943 if (offset >= mdrcnt) {
1944 res = ERRinvalidparam;
1948 /* Do we have a string ? */
1949 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1953 if (!pull_ascii_talloc(talloc_tos(), &pathname,
1954 offset ? (data+offset) : "", &converted_size))
1956 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1964 string_replace(sharename, '"', ' ');
1965 string_replace(pathname, '"', ' ');
1966 string_replace(comment, '"', ' ');
1968 cmdname = lp_add_share_cmd();
1970 if (!cmdname || *cmdname == '\0') {
1974 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1975 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
1976 pathname, comment) == -1) {
1980 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1982 if ((res = smbrun(command, NULL)) != 0) {
1983 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1990 message_send_all(smbd_messaging_context(),
1991 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1995 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1999 SSVAL(*rparam,0,NERR_Success);
2000 SSVAL(*rparam,2,0); /* converter word */
2001 SSVAL(*rparam,4,*rdata_len);
2009 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2014 SSVAL(*rparam,0,res);
2019 /****************************************************************************
2020 view list of groups available
2021 ****************************************************************************/
2023 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2024 char *param, int tpscnt,
2025 char *data, int tdscnt,
2026 int mdrcnt,int mprcnt,
2027 char **rdata,char **rparam,
2028 int *rdata_len,int *rparam_len)
2032 int resume_context, cli_buf_size;
2033 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2034 char *str2 = skip_string(param,tpscnt,str1);
2035 char *p = skip_string(param,tpscnt,str2);
2037 uint32_t num_groups;
2038 uint32_t resume_handle;
2039 struct rpc_pipe_client *samr_pipe;
2040 struct policy_handle samr_handle, domain_handle;
2043 if (!str1 || !str2 || !p) {
2047 if (strcmp(str1,"WrLeh") != 0) {
2052 * W-> resume context (number of users to skip)
2053 * r -> return parameter pointer to receive buffer
2054 * L -> length of receive buffer
2055 * e -> return parameter number of entries
2056 * h -> return parameter total number of users
2059 if (strcmp("B21",str2) != 0) {
2063 status = rpc_pipe_open_internal(
2064 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2065 conn->server_info, &samr_pipe);
2066 if (!NT_STATUS_IS_OK(status)) {
2067 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2068 nt_errstr(status)));
2072 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2073 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2074 if (!NT_STATUS_IS_OK(status)) {
2075 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2076 nt_errstr(status)));
2080 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2081 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2082 get_global_sam_sid(), &domain_handle);
2083 if (!NT_STATUS_IS_OK(status)) {
2084 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2085 nt_errstr(status)));
2086 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2090 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2091 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2092 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2093 "%d\n", resume_context, cli_buf_size));
2095 *rdata_len = cli_buf_size;
2096 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2103 errflags = NERR_Success;
2108 struct samr_SamArray *sam_entries;
2109 uint32_t num_entries;
2111 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2116 if (!NT_STATUS_IS_OK(status)) {
2117 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2118 "%s\n", nt_errstr(status)));
2122 if (num_entries == 0) {
2123 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2124 "no entries -- done\n"));
2128 for(i=0; i<num_entries; i++) {
2131 name = sam_entries->entries[i].name.string;
2133 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2134 /* set overflow error */
2135 DEBUG(3,("overflow on entry %d group %s\n", i,
2141 /* truncate the name at 21 chars. */
2143 strlcpy(p, name, 21);
2144 DEBUG(10,("adding entry %d group %s\n", i, p));
2146 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2151 if (errflags != NERR_Success) {
2155 TALLOC_FREE(sam_entries);
2158 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2159 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2161 *rdata_len = PTR_DIFF(p,*rdata);
2164 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2168 SSVAL(*rparam, 0, errflags);
2169 SSVAL(*rparam, 2, 0); /* converter word */
2170 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2171 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2176 /*******************************************************************
2177 Get groups that a user is a member of.
2178 ******************************************************************/
2180 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2181 char *param, int tpscnt,
2182 char *data, int tdscnt,
2183 int mdrcnt,int mprcnt,
2184 char **rdata,char **rparam,
2185 int *rdata_len,int *rparam_len)
2187 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2188 char *str2 = skip_string(param,tpscnt,str1);
2189 char *UserName = skip_string(param,tpscnt,str2);
2190 char *p = skip_string(param,tpscnt,UserName);
2191 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2192 const char *level_string;
2198 struct rpc_pipe_client *samr_pipe;
2199 struct policy_handle samr_handle, domain_handle, user_handle;
2200 struct lsa_String name;
2201 struct lsa_Strings names;
2202 struct samr_Ids type, rid;
2203 struct samr_RidWithAttributeArray *rids;
2206 if (!str1 || !str2 || !UserName || !p) {
2211 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2216 /* check it's a supported varient */
2218 if ( strcmp(str1,"zWrLeh") != 0 )
2223 level_string = "B21";
2229 if (strcmp(level_string,str2) != 0)
2232 *rdata_len = mdrcnt + 1024;
2233 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2238 SSVAL(*rparam,0,NERR_Success);
2239 SSVAL(*rparam,2,0); /* converter word */
2242 endp = *rdata + *rdata_len;
2244 status = rpc_pipe_open_internal(
2245 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2246 conn->server_info, &samr_pipe);
2247 if (!NT_STATUS_IS_OK(status)) {
2248 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2249 nt_errstr(status)));
2253 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2254 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2255 if (!NT_STATUS_IS_OK(status)) {
2256 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2257 nt_errstr(status)));
2261 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2262 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2263 get_global_sam_sid(), &domain_handle);
2264 if (!NT_STATUS_IS_OK(status)) {
2265 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2266 nt_errstr(status)));
2270 name.string = UserName;
2272 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2273 &domain_handle, 1, &name,
2275 if (!NT_STATUS_IS_OK(status)) {
2276 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2277 nt_errstr(status)));
2281 if (type.ids[0] != SID_NAME_USER) {
2282 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2283 sid_type_lookup(type.ids[0])));
2287 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2289 SAMR_USER_ACCESS_GET_GROUPS,
2290 rid.ids[0], &user_handle);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2293 nt_errstr(status)));
2297 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2298 &user_handle, &rids);
2299 if (!NT_STATUS_IS_OK(status)) {
2300 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2301 nt_errstr(status)));
2305 for (i=0; i<rids->count; i++) {
2307 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2309 1, &rids->rids[i].rid,
2311 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2312 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2318 *rdata_len = PTR_DIFF(p,*rdata);
2320 SSVAL(*rparam,4,count); /* is this right?? */
2321 SSVAL(*rparam,6,count); /* is this right?? */
2326 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2328 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2330 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2335 /*******************************************************************
2337 ******************************************************************/
2339 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2340 char *param, int tpscnt,
2341 char *data, int tdscnt,
2342 int mdrcnt,int mprcnt,
2343 char **rdata,char **rparam,
2344 int *rdata_len,int *rparam_len)
2349 int i, resume_context, cli_buf_size;
2350 uint32_t resume_handle;
2352 struct rpc_pipe_client *samr_pipe;
2353 struct policy_handle samr_handle, domain_handle;
2356 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2357 char *str2 = skip_string(param,tpscnt,str1);
2358 char *p = skip_string(param,tpscnt,str2);
2361 if (!str1 || !str2 || !p) {
2365 if (strcmp(str1,"WrLeh") != 0)
2368 * W-> resume context (number of users to skip)
2369 * r -> return parameter pointer to receive buffer
2370 * L -> length of receive buffer
2371 * e -> return parameter number of entries
2372 * h -> return parameter total number of users
2375 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2376 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2377 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2378 resume_context, cli_buf_size));
2381 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2386 /* check it's a supported varient */
2387 if (strcmp("B21",str2) != 0)
2390 *rdata_len = cli_buf_size;
2391 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2397 endp = *rdata + *rdata_len;
2399 status = rpc_pipe_open_internal(
2400 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2401 conn->server_info, &samr_pipe);
2402 if (!NT_STATUS_IS_OK(status)) {
2403 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2404 nt_errstr(status)));
2408 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2409 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2410 if (!NT_STATUS_IS_OK(status)) {
2411 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2412 nt_errstr(status)));
2416 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2417 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2418 get_global_sam_sid(), &domain_handle);
2419 if (!NT_STATUS_IS_OK(status)) {
2420 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2421 nt_errstr(status)));
2422 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2426 errflags=NERR_Success;
2431 struct samr_SamArray *sam_entries;
2432 uint32_t num_entries;
2434 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2440 if (!NT_STATUS_IS_OK(status)) {
2441 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2442 "%s\n", nt_errstr(status)));
2446 if (num_entries == 0) {
2447 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2448 "no entries -- done\n"));
2452 for (i=0; i<num_entries; i++) {
2455 name = sam_entries->entries[i].name.string;
2457 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2458 &&(strlen(name)<=21)) {
2459 strlcpy(p,name,PTR_DIFF(endp,p));
2460 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2461 "username %s\n",count_sent,p));
2465 /* set overflow error */
2466 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2467 "username %s\n",count_sent,name));
2473 if (errflags != NERR_Success) {
2477 TALLOC_FREE(sam_entries);
2480 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2481 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2483 *rdata_len = PTR_DIFF(p,*rdata);
2485 SSVAL(*rparam,0,errflags);
2486 SSVAL(*rparam,2,0); /* converter word */
2487 SSVAL(*rparam,4,count_sent); /* is this right?? */
2488 SSVAL(*rparam,6,num_users); /* is this right?? */
2493 /****************************************************************************
2494 Get the time of day info.
2495 ****************************************************************************/
2497 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2498 char *param, int tpscnt,
2499 char *data, int tdscnt,
2500 int mdrcnt,int mprcnt,
2501 char **rdata,char **rparam,
2502 int *rdata_len,int *rparam_len)
2505 time_t unixdate = time(NULL);
2509 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2515 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2520 SSVAL(*rparam,0,NERR_Success);
2521 SSVAL(*rparam,2,0); /* converter word */
2525 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2526 by NT in a "net time" operation,
2527 it seems to ignore the one below */
2529 /* the client expects to get localtime, not GMT, in this bit
2530 (I think, this needs testing) */
2531 t = localtime(&unixdate);
2536 SIVAL(p,4,0); /* msecs ? */
2537 SCVAL(p,8,t->tm_hour);
2538 SCVAL(p,9,t->tm_min);
2539 SCVAL(p,10,t->tm_sec);
2540 SCVAL(p,11,0); /* hundredths of seconds */
2541 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2542 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2543 SCVAL(p,16,t->tm_mday);
2544 SCVAL(p,17,t->tm_mon + 1);
2545 SSVAL(p,18,1900+t->tm_year);
2546 SCVAL(p,20,t->tm_wday);
2551 /****************************************************************************
2552 Set the user password.
2553 *****************************************************************************/
2555 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2556 char *param, int tpscnt,
2557 char *data, int tdscnt,
2558 int mdrcnt,int mprcnt,
2559 char **rdata,char **rparam,
2560 int *rdata_len,int *rparam_len)
2562 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2565 fstring pass1,pass2;
2567 /* Skip 2 strings. */
2568 p = skip_string(param,tpscnt,np);
2569 p = skip_string(param,tpscnt,p);
2575 /* Do we have a string ? */
2576 if (skip_string(param,tpscnt,p) == NULL) {
2579 pull_ascii_fstring(user,p);
2581 p = skip_string(param,tpscnt,p);
2586 memset(pass1,'\0',sizeof(pass1));
2587 memset(pass2,'\0',sizeof(pass2));
2589 * We use 31 here not 32 as we're checking
2590 * the last byte we want to access is safe.
2592 if (!is_offset_safe(param,tpscnt,p,31)) {
2596 memcpy(pass2,p+16,16);
2599 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2606 SSVAL(*rparam,0,NERR_badpass);
2607 SSVAL(*rparam,2,0); /* converter word */
2609 DEBUG(3,("Set password for <%s>\n",user));
2612 * Attempt to verify the old password against smbpasswd entries
2613 * Win98 clients send old and new password in plaintext for this call.
2617 auth_serversupplied_info *server_info = NULL;
2618 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2620 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2623 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2624 SSVAL(*rparam,0,NERR_Success);
2628 TALLOC_FREE(server_info);
2630 data_blob_clear_free(&password);
2634 * If the plaintext change failed, attempt
2635 * the old encrypted method. NT will generate this
2636 * after trying the samr method. Note that this
2637 * method is done as a last resort as this
2638 * password change method loses the NT password hash
2639 * and cannot change the UNIX password as no plaintext
2643 if(SVAL(*rparam,0) != NERR_Success) {
2644 struct samu *hnd = NULL;
2646 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2648 if (change_lanman_password(hnd,(uchar *)pass2)) {
2649 SSVAL(*rparam,0,NERR_Success);
2656 memset((char *)pass1,'\0',sizeof(fstring));
2657 memset((char *)pass2,'\0',sizeof(fstring));
2662 /****************************************************************************
2663 Set the user password (SamOEM version - gets plaintext).
2664 ****************************************************************************/
2666 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2667 char *param, int tpscnt,
2668 char *data, int tdscnt,
2669 int mdrcnt,int mprcnt,
2670 char **rdata,char **rparam,
2671 int *rdata_len,int *rparam_len)
2673 struct smbd_server_connection *sconn = smbd_server_conn;
2675 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2677 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2687 SSVAL(*rparam,0,NERR_badpass);
2690 * Check the parameter definition is correct.
2693 /* Do we have a string ? */
2694 if (skip_string(param,tpscnt,p) == 0) {
2697 if(!strequal(p, "zsT")) {
2698 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2701 p = skip_string(param, tpscnt, p);
2706 /* Do we have a string ? */
2707 if (skip_string(param,tpscnt,p) == 0) {
2710 if(!strequal(p, "B516B16")) {
2711 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2714 p = skip_string(param,tpscnt,p);
2718 /* Do we have a string ? */
2719 if (skip_string(param,tpscnt,p) == 0) {
2722 p += pull_ascii_fstring(user,p);
2724 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2727 * Pass the user through the NT -> unix user mapping
2731 (void)map_username(sconn, user);
2733 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2734 SSVAL(*rparam,0,NERR_Success);
2740 /****************************************************************************
2743 ****************************************************************************/
2745 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2746 char *param, int tpscnt,
2747 char *data, int tdscnt,
2748 int mdrcnt,int mprcnt,
2749 char **rdata,char **rparam,
2750 int *rdata_len,int *rparam_len)
2752 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2753 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2754 char *str2 = skip_string(param,tpscnt,str1);
2755 char *p = skip_string(param,tpscnt,str2);
2760 WERROR werr = WERR_OK;
2762 if (!str1 || !str2 || !p) {
2766 * We use 1 here not 2 as we're checking
2767 * the last byte we want to access is safe.
2769 if (!is_offset_safe(param,tpscnt,p,1)) {
2772 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2775 /* check it's a supported varient */
2776 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2780 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2786 if (!print_job_exists(sharename, jobid)) {
2787 errcode = NERR_JobNotFound;
2791 snum = lp_servicenumber( sharename);
2793 errcode = NERR_DestNotFound;
2797 errcode = NERR_notsupported;
2800 case 81: /* delete */
2801 if (print_job_delete(conn->server_info, snum, jobid, &werr))
2802 errcode = NERR_Success;
2804 case 82: /* pause */
2805 if (print_job_pause(conn->server_info, snum, jobid, &werr))
2806 errcode = NERR_Success;
2808 case 83: /* resume */
2809 if (print_job_resume(conn->server_info, snum, jobid, &werr))
2810 errcode = NERR_Success;
2814 if (!W_ERROR_IS_OK(werr))
2815 errcode = W_ERROR_V(werr);
2818 SSVAL(*rparam,0,errcode);
2819 SSVAL(*rparam,2,0); /* converter word */
2824 /****************************************************************************
2825 Purge a print queue - or pause or resume it.
2826 ****************************************************************************/
2828 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2829 char *param, int tpscnt,
2830 char *data, int tdscnt,
2831 int mdrcnt,int mprcnt,
2832 char **rdata,char **rparam,
2833 int *rdata_len,int *rparam_len)
2835 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2836 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2837 char *str2 = skip_string(param,tpscnt,str1);
2838 char *QueueName = skip_string(param,tpscnt,str2);
2839 int errcode = NERR_notsupported;
2841 WERROR werr = WERR_OK;
2843 if (!str1 || !str2 || !QueueName) {
2847 /* check it's a supported varient */
2848 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2852 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2858 if (skip_string(param,tpscnt,QueueName) == NULL) {
2861 snum = print_queue_snum(QueueName);
2864 errcode = NERR_JobNotFound;
2869 case 74: /* Pause queue */
2870 werr = print_queue_pause(conn->server_info, snum);
2872 case 75: /* Resume queue */
2873 werr = print_queue_resume(conn->server_info, snum);
2875 case 103: /* Purge */
2876 werr = print_queue_purge(conn->server_info, snum);
2879 werr = WERR_NOT_SUPPORTED;
2883 errcode = W_ERROR_V(werr);
2886 SSVAL(*rparam,0,errcode);
2887 SSVAL(*rparam,2,0); /* converter word */
2892 /****************************************************************************
2893 set the property of a print job (undocumented?)
2894 ? function = 0xb -> set name of print job
2895 ? function = 0x6 -> move print job up/down
2896 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2897 or <WWsTP> <WB21BB16B10zWWzDDz>
2898 ****************************************************************************/
2900 static int check_printjob_info(struct pack_desc* desc,
2901 int uLevel, char* id)
2903 desc->subformat = NULL;
2905 case 0: desc->format = "W"; break;
2906 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2907 case 2: desc->format = "WWzWWDDzz"; break;
2908 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2909 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2911 DEBUG(0,("check_printjob_info: invalid level %d\n",
2915 if (id == NULL || strcmp(desc->format,id) != 0) {
2916 DEBUG(0,("check_printjob_info: invalid format %s\n",
2917 id ? id : "<NULL>" ));
2923 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2924 char *param, int tpscnt,
2925 char *data, int tdscnt,
2926 int mdrcnt,int mprcnt,
2927 char **rdata,char **rparam,
2928 int *rdata_len,int *rparam_len)
2930 struct pack_desc desc;
2931 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2932 char *str2 = skip_string(param,tpscnt,str1);
2933 char *p = skip_string(param,tpscnt,str2);
2936 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2937 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2940 if (!str1 || !str2 || !p) {
2944 * We use 1 here not 2 as we're checking
2945 * the last byte we want to access is safe.
2947 if (!is_offset_safe(param,tpscnt,p,1)) {
2950 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2953 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2958 if (!share_defined(sharename)) {
2959 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2966 /* check it's a supported varient */
2967 if ((strcmp(str1,"WWsTP")) ||
2968 (!check_printjob_info(&desc,uLevel,str2)))
2971 if (!print_job_exists(sharename, jobid)) {
2972 errcode=NERR_JobNotFound;
2976 errcode = NERR_notsupported;
2980 /* change job place in the queue,
2981 data gives the new place */
2982 place = SVAL(data,0);
2983 if (print_job_set_place(sharename, jobid, place)) {
2984 errcode=NERR_Success;
2989 /* change print job name, data gives the name */
2990 if (print_job_set_name(sharename, jobid, data)) {
2991 errcode=NERR_Success;
3000 SSVALS(*rparam,0,errcode);
3001 SSVAL(*rparam,2,0); /* converter word */
3007 /****************************************************************************
3008 Get info about the server.
3009 ****************************************************************************/
3011 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3012 char *param, int tpscnt,
3013 char *data, int tdscnt,
3014 int mdrcnt,int mprcnt,
3015 char **rdata,char **rparam,
3016 int *rdata_len,int *rparam_len)
3018 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3019 char *str2 = skip_string(param,tpscnt,str1);
3020 char *p = skip_string(param,tpscnt,str2);
3021 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3025 if (!str1 || !str2 || !p) {
3029 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3031 /* check it's a supported varient */
3032 if (!prefix_ok(str1,"WrLh")) {
3038 if (strcmp(str2,"B16") != 0) {
3044 if (strcmp(str2,"B16BBDz") != 0) {
3050 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3056 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3062 if (strcmp(str2,"DN") != 0) {
3068 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3077 *rdata_len = mdrcnt;
3078 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3084 p2 = p + struct_len;
3086 srvstr_push(NULL, 0, p,global_myname(),16,
3087 STR_ASCII|STR_UPPER|STR_TERMINATE);
3091 struct srv_info_struct *servers=NULL;
3093 char *comment = NULL;
3094 TALLOC_CTX *ctx = talloc_tos();
3095 uint32 servertype= lp_default_server_announce();
3097 comment = talloc_strdup(ctx,lp_serverstring());
3102 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3103 for (i=0;i<count;i++) {
3104 if (strequal(servers[i].name,global_myname())) {
3105 servertype = servers[i].type;
3106 TALLOC_FREE(comment);
3107 comment = talloc_strdup(ctx,
3108 servers[i].comment);
3118 SCVAL(p,0,lp_major_announce_version());
3119 SCVAL(p,1,lp_minor_announce_version());
3120 SIVAL(p,2,servertype);
3122 if (mdrcnt == struct_len) {
3125 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3126 comment = talloc_sub_advanced(
3128 lp_servicename(SNUM(conn)),
3129 conn->server_info->unix_name,
3131 conn->server_info->utok.gid,
3132 conn->server_info->sanitized_username,
3133 pdb_get_domain(conn->server_info->sam_account),
3138 if (mdrcnt - struct_len <= 0) {
3143 MIN(mdrcnt - struct_len,
3144 MAX_SERVER_STRING_LENGTH),
3146 p2 = skip_string(*rdata,*rdata_len,p2);
3154 return False; /* not yet implemented */
3157 *rdata_len = PTR_DIFF(p2,*rdata);
3160 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3164 SSVAL(*rparam,0,NERR_Success);
3165 SSVAL(*rparam,2,0); /* converter word */
3166 SSVAL(*rparam,4,*rdata_len);
3171 /****************************************************************************
3172 Get info about the server.
3173 ****************************************************************************/
3175 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3176 char *param, int tpscnt,
3177 char *data, int tdscnt,
3178 int mdrcnt,int mprcnt,
3179 char **rdata,char **rparam,
3180 int *rdata_len,int *rparam_len)
3182 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3183 char *str2 = skip_string(param,tpscnt,str1);
3184 char *p = skip_string(param,tpscnt,str2);
3187 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3189 if (!str1 || !str2 || !p) {
3193 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3196 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3201 /* check it's a supported varient */
3202 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3206 *rdata_len = mdrcnt + 1024;
3207 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3212 SSVAL(*rparam,0,NERR_Success);
3213 SSVAL(*rparam,2,0); /* converter word */
3216 endp = *rdata + *rdata_len;
3218 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3223 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3224 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3226 p2 = skip_string(*rdata,*rdata_len,p2);
3232 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3233 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3234 p2 = skip_string(*rdata,*rdata_len,p2);
3240 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3241 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3243 p2 = skip_string(*rdata,*rdata_len,p2);
3249 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3250 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3253 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3254 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3255 p2 = skip_string(*rdata,*rdata_len,p2);
3261 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3262 strlcpy(p2,"",PTR_DIFF(endp,p2));
3263 p2 = skip_string(*rdata,*rdata_len,p2);
3269 *rdata_len = PTR_DIFF(p2,*rdata);
3271 SSVAL(*rparam,4,*rdata_len);
3276 /****************************************************************************
3277 get info about a user
3279 struct user_info_11 {
3280 char usri11_name[21]; 0-20
3282 char *usri11_comment; 22-25
3283 char *usri11_usr_comment; 26-29
3284 unsigned short usri11_priv; 30-31
3285 unsigned long usri11_auth_flags; 32-35
3286 long usri11_password_age; 36-39
3287 char *usri11_homedir; 40-43
3288 char *usri11_parms; 44-47
3289 long usri11_last_logon; 48-51
3290 long usri11_last_logoff; 52-55
3291 unsigned short usri11_bad_pw_count; 56-57
3292 unsigned short usri11_num_logons; 58-59
3293 char *usri11_logon_server; 60-63
3294 unsigned short usri11_country_code; 64-65
3295 char *usri11_workstations; 66-69
3296 unsigned long usri11_max_storage; 70-73
3297 unsigned short usri11_units_per_week; 74-75
3298 unsigned char *usri11_logon_hours; 76-79
3299 unsigned short usri11_code_page; 80-81
3304 usri11_name specifies the user name for which information is retrieved
3306 usri11_pad aligns the next data structure element to a word boundary
3308 usri11_comment is a null terminated ASCII comment
3310 usri11_user_comment is a null terminated ASCII comment about the user
3312 usri11_priv specifies the level of the privilege assigned to the user.
3313 The possible values are:
3315 Name Value Description
3316 USER_PRIV_GUEST 0 Guest privilege
3317 USER_PRIV_USER 1 User privilege
3318 USER_PRV_ADMIN 2 Administrator privilege
3320 usri11_auth_flags specifies the account operator privileges. The
3321 possible values are:
3323 Name Value Description
3324 AF_OP_PRINT 0 Print operator
3327 Leach, Naik [Page 28]
3331 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3334 AF_OP_COMM 1 Communications operator
3335 AF_OP_SERVER 2 Server operator
3336 AF_OP_ACCOUNTS 3 Accounts operator
3339 usri11_password_age specifies how many seconds have elapsed since the
3340 password was last changed.
3342 usri11_home_dir points to a null terminated ASCII string that contains
3343 the path name of the user's home directory.
3345 usri11_parms points to a null terminated ASCII string that is set
3346 aside for use by applications.
3348 usri11_last_logon specifies the time when the user last logged on.
3349 This value is stored as the number of seconds elapsed since
3350 00:00:00, January 1, 1970.
3352 usri11_last_logoff specifies the time when the user last logged off.
3353 This value is stored as the number of seconds elapsed since
3354 00:00:00, January 1, 1970. A value of 0 means the last logoff
3357 usri11_bad_pw_count specifies the number of incorrect passwords
3358 entered since the last successful logon.
3360 usri11_log1_num_logons specifies the number of times this user has
3361 logged on. A value of -1 means the number of logons is unknown.
3363 usri11_logon_server points to a null terminated ASCII string that
3364 contains the name of the server to which logon requests are sent.
3365 A null string indicates logon requests should be sent to the
3368 usri11_country_code specifies the country code for the user's language
3371 usri11_workstations points to a null terminated ASCII string that
3372 contains the names of workstations the user may log on from.
3373 There may be up to 8 workstations, with the names separated by
3374 commas. A null strings indicates there are no restrictions.
3376 usri11_max_storage specifies the maximum amount of disk space the user
3377 can occupy. A value of 0xffffffff indicates there are no
3380 usri11_units_per_week specifies the equal number of time units into
3381 which a week is divided. This value must be equal to 168.
3383 usri11_logon_hours points to a 21 byte (168 bits) string that
3384 specifies the time during which the user can log on. Each bit
3385 represents one unique hour in a week. The first bit (bit 0, word
3386 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3390 Leach, Naik [Page 29]
3394 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3397 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3398 are no restrictions.
3400 usri11_code_page specifies the code page for the user's language of
3403 All of the pointers in this data structure need to be treated
3404 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3405 to be ignored. The converter word returned in the parameters section
3406 needs to be subtracted from the lower 16 bits to calculate an offset
3407 into the return buffer where this ASCII string resides.
3409 There is no auxiliary data in the response.
3411 ****************************************************************************/
3413 #define usri11_name 0
3414 #define usri11_pad 21
3415 #define usri11_comment 22
3416 #define usri11_usr_comment 26
3417 #define usri11_full_name 30
3418 #define usri11_priv 34
3419 #define usri11_auth_flags 36
3420 #define usri11_password_age 40
3421 #define usri11_homedir 44
3422 #define usri11_parms 48
3423 #define usri11_last_logon 52
3424 #define usri11_last_logoff 56
3425 #define usri11_bad_pw_count 60
3426 #define usri11_num_logons 62
3427 #define usri11_logon_server 64
3428 #define usri11_country_code 68
3429 #define usri11_workstations 70
3430 #define usri11_max_storage 74
3431 #define usri11_units_per_week 78
3432 #define usri11_logon_hours 80
3433 #define usri11_code_page 84
3434 #define usri11_end 86
3436 #define USER_PRIV_GUEST 0
3437 #define USER_PRIV_USER 1
3438 #define USER_PRIV_ADMIN 2
3440 #define AF_OP_PRINT 0
3441 #define AF_OP_COMM 1
3442 #define AF_OP_SERVER 2
3443 #define AF_OP_ACCOUNTS 3
3446 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3447 char *param, int tpscnt,
3448 char *data, int tdscnt,
3449 int mdrcnt,int mprcnt,
3450 char **rdata,char **rparam,
3451 int *rdata_len,int *rparam_len)
3453 struct smbd_server_connection *sconn = smbd_server_conn;
3454 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3455 char *str2 = skip_string(param,tpscnt,str1);
3456 char *UserName = skip_string(param,tpscnt,str2);
3457 char *p = skip_string(param,tpscnt,UserName);
3458 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3461 const char *level_string;
3463 /* get NIS home of a previously validated user - simeon */
3464 /* With share level security vuid will always be zero.
3465 Don't depend on vuser being non-null !!. JRA */
3466 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3468 DEBUG(3,(" Username of UID %d is %s\n",
3469 (int)vuser->server_info->utok.uid,
3470 vuser->server_info->unix_name));
3473 if (!str1 || !str2 || !UserName || !p) {
3478 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3483 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3485 /* check it's a supported variant */
3486 if (strcmp(str1,"zWrLh") != 0) {
3490 case 0: level_string = "B21"; break;
3491 case 1: level_string = "B21BB16DWzzWz"; break;
3492 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3493 case 10: level_string = "B21Bzzz"; break;
3494 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3495 default: return False;
3498 if (strcmp(level_string,str2) != 0) {
3502 *rdata_len = mdrcnt + 1024;
3503 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3508 SSVAL(*rparam,0,NERR_Success);
3509 SSVAL(*rparam,2,0); /* converter word */
3512 endp = *rdata + *rdata_len;
3513 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3519 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3522 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3527 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3528 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3529 p2 = skip_string(*rdata,*rdata_len,p2);
3534 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3535 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3536 p2 = skip_string(*rdata,*rdata_len,p2);
3541 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3542 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3543 strlcpy(p2,((vuser != NULL)
3544 ? pdb_get_fullname(vuser->server_info->sam_account)
3545 : UserName),PTR_DIFF(endp,p2));
3546 p2 = skip_string(*rdata,*rdata_len,p2);
3553 const char *homedir = "";
3554 if (vuser != NULL) {
3555 homedir = pdb_get_homedir(
3556 vuser->server_info->sam_account);
3558 /* modelled after NTAS 3.51 reply */
3559 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3560 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3561 SIVALS(p,usri11_password_age,-1); /* password age */
3562 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3563 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3564 p2 = skip_string(*rdata,*rdata_len,p2);
3568 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3569 strlcpy(p2,"",PTR_DIFF(endp,p2));
3570 p2 = skip_string(*rdata,*rdata_len,p2);
3574 SIVAL(p,usri11_last_logon,0); /* last logon */
3575 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3576 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3577 SSVALS(p,usri11_num_logons,-1); /* num logons */
3578 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3579 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3580 p2 = skip_string(*rdata,*rdata_len,p2);
3584 SSVAL(p,usri11_country_code,0); /* country code */
3586 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3587 strlcpy(p2,"",PTR_DIFF(endp,p2));
3588 p2 = skip_string(*rdata,*rdata_len,p2);
3593 SIVALS(p,usri11_max_storage,-1); /* max storage */
3594 SSVAL(p,usri11_units_per_week,168); /* units per week */
3595 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3597 /* a simple way to get logon hours at all times. */
3599 SCVAL(p2,21,0); /* fix zero termination */
3600 p2 = skip_string(*rdata,*rdata_len,p2);
3605 SSVAL(p,usri11_code_page,0); /* code page */
3608 if (uLevel == 1 || uLevel == 2) {
3609 memset(p+22,' ',16); /* password */
3610 SIVALS(p,38,-1); /* password age */
3612 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3613 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3614 strlcpy(p2, vuser ? pdb_get_homedir(
3615 vuser->server_info->sam_account) : "",
3617 p2 = skip_string(*rdata,*rdata_len,p2);
3621 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3623 SSVAL(p,52,0); /* flags */
3624 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3625 strlcpy(p2, vuser ? pdb_get_logon_script(
3626 vuser->server_info->sam_account) : "",
3628 p2 = skip_string(*rdata,*rdata_len,p2);
3633 SIVAL(p,60,0); /* auth_flags */
3634 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3635 strlcpy(p2,((vuser != NULL)
3636 ? pdb_get_fullname(vuser->server_info->sam_account)
3637 : UserName),PTR_DIFF(endp,p2));
3638 p2 = skip_string(*rdata,*rdata_len,p2);
3642 SIVAL(p,68,0); /* urs_comment */
3643 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3644 strlcpy(p2,"",PTR_DIFF(endp,p2));
3645 p2 = skip_string(*rdata,*rdata_len,p2);
3649 SIVAL(p,76,0); /* workstations */
3650 SIVAL(p,80,0); /* last_logon */
3651 SIVAL(p,84,0); /* last_logoff */
3652 SIVALS(p,88,-1); /* acct_expires */
3653 SIVALS(p,92,-1); /* max_storage */
3654 SSVAL(p,96,168); /* units_per_week */
3655 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3658 SSVALS(p,102,-1); /* bad_pw_count */
3659 SSVALS(p,104,-1); /* num_logons */
3660 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3662 TALLOC_CTX *ctx = talloc_tos();
3663 int space_rem = *rdata_len - (p2 - *rdata);
3666 if (space_rem <= 0) {
3669 tmp = talloc_strdup(ctx, "\\\\%L");
3673 tmp = talloc_sub_basic(ctx,
3686 p2 = skip_string(*rdata,*rdata_len,p2);
3690 SSVAL(p,110,49); /* country_code */
3691 SSVAL(p,112,860); /* code page */
3695 *rdata_len = PTR_DIFF(p2,*rdata);
3697 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3702 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3703 char *param, int tpscnt,
3704 char *data, int tdscnt,
3705 int mdrcnt,int mprcnt,
3706 char **rdata,char **rparam,
3707 int *rdata_len,int *rparam_len)
3709 struct smbd_server_connection *sconn = smbd_server_conn;
3710 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3711 char *str2 = skip_string(param,tpscnt,str1);
3712 char *p = skip_string(param,tpscnt,str2);
3714 struct pack_desc desc;
3716 /* With share level security vuid will always be zero.
3717 Don't depend on vuser being non-null !!. JRA */
3718 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3720 if (!str1 || !str2 || !p) {
3725 DEBUG(3,(" Username of UID %d is %s\n",
3726 (int)vuser->server_info->utok.uid,
3727 vuser->server_info->unix_name));
3730 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3731 name = get_safe_str_ptr(param,tpscnt,p,2);
3736 memset((char *)&desc,'\0',sizeof(desc));
3738 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3740 /* check it's a supported varient */
3741 if (strcmp(str1,"OOWb54WrLh") != 0) {
3744 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3748 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3755 desc.buflen = mdrcnt;
3756 desc.subformat = NULL;
3759 if (init_package(&desc,1,0)) {
3760 PACKI(&desc,"W",0); /* code */
3761 PACKS(&desc,"B21",name); /* eff. name */
3762 PACKS(&desc,"B",""); /* pad */
3763 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3764 PACKI(&desc,"D",0); /* auth flags XXX */
3765 PACKI(&desc,"W",0); /* num logons */
3766 PACKI(&desc,"W",0); /* bad pw count */
3767 PACKI(&desc,"D",0); /* last logon */
3768 PACKI(&desc,"D",-1); /* last logoff */
3769 PACKI(&desc,"D",-1); /* logoff time */
3770 PACKI(&desc,"D",-1); /* kickoff time */
3771 PACKI(&desc,"D",0); /* password age */
3772 PACKI(&desc,"D",0); /* password can change */
3773 PACKI(&desc,"D",-1); /* password must change */
3777 fstrcpy(mypath,"\\\\");
3778 fstrcat(mypath,get_local_machine_name());
3780 PACKS(&desc,"z",mypath); /* computer */
3783 PACKS(&desc,"z",lp_workgroup());/* domain */
3784 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
3785 vuser->server_info->sam_account) : ""); /* script path */
3786 PACKI(&desc,"D",0x00000000); /* reserved */
3789 *rdata_len = desc.usedlen;
3791 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3795 SSVALS(*rparam,0,desc.errcode);
3797 SSVAL(*rparam,4,desc.neededlen);
3799 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3804 /****************************************************************************
3805 api_WAccessGetUserPerms
3806 ****************************************************************************/
3808 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3809 char *param, int tpscnt,
3810 char *data, int tdscnt,
3811 int mdrcnt,int mprcnt,
3812 char **rdata,char **rparam,
3813 int *rdata_len,int *rparam_len)
3815 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3816 char *str2 = skip_string(param,tpscnt,str1);
3817 char *user = skip_string(param,tpscnt,str2);
3818 char *resource = skip_string(param,tpscnt,user);
3820 if (!str1 || !str2 || !user || !resource) {
3824 if (skip_string(param,tpscnt,resource) == NULL) {
3827 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3829 /* check it's a supported varient */
3830 if (strcmp(str1,"zzh") != 0) {
3833 if (strcmp(str2,"") != 0) {
3838 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3842 SSVALS(*rparam,0,0); /* errorcode */
3843 SSVAL(*rparam,2,0); /* converter word */
3844 SSVAL(*rparam,4,0x7f); /* permission flags */
3849 /****************************************************************************
3850 api_WPrintJobEnumerate
3851 ****************************************************************************/
3853 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3854 char *param, int tpscnt,
3855 char *data, int tdscnt,
3856 int mdrcnt,int mprcnt,
3857 char **rdata,char **rparam,
3858 int *rdata_len,int *rparam_len)
3860 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3861 char *str2 = skip_string(param,tpscnt,str1);
3862 char *p = skip_string(param,tpscnt,str2);
3869 struct pack_desc desc;
3870 print_queue_struct *queue=NULL;
3871 print_status_struct status;
3874 if (!str1 || !str2 || !p) {
3878 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3880 memset((char *)&desc,'\0',sizeof(desc));
3881 memset((char *)&status,'\0',sizeof(status));
3883 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3885 /* check it's a supported varient */
3886 if (strcmp(str1,"WWrLh") != 0) {
3889 if (!check_printjob_info(&desc,uLevel,str2)) {
3893 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3897 snum = lp_servicenumber( sharename);
3898 if (snum < 0 || !VALID_SNUM(snum)) {
3902 count = print_queue_status(snum,&queue,&status);
3903 for (i = 0; i < count; i++) {
3904 if (queue[i].job == jobid) {
3910 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3915 desc.buflen = mdrcnt;
3918 * Don't return data but need to get correct length
3919 * init_package will return wrong size if buflen=0
3921 desc.buflen = getlen(desc.format);
3922 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3925 if (init_package(&desc,1,0)) {
3927 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3928 *rdata_len = desc.usedlen;
3930 desc.errcode = NERR_JobNotFound;
3936 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3940 SSVALS(*rparam,0,desc.errcode);
3942 SSVAL(*rparam,4,desc.neededlen);
3947 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3952 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3953 char *param, int tpscnt,
3954 char *data, int tdscnt,
3955 int mdrcnt,int mprcnt,
3956 char **rdata,char **rparam,
3957 int *rdata_len,int *rparam_len)
3959 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3960 char *str2 = skip_string(param,tpscnt,str1);
3961 char *p = skip_string(param,tpscnt,str2);
3967 struct pack_desc desc;
3968 print_queue_struct *queue=NULL;
3969 print_status_struct status;
3971 if (!str1 || !str2 || !p) {
3975 memset((char *)&desc,'\0',sizeof(desc));
3976 memset((char *)&status,'\0',sizeof(status));
3978 p = skip_string(param,tpscnt,p);
3982 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3984 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3986 /* check it's a supported variant */
3987 if (strcmp(str1,"zWrLeh") != 0) {
3992 return False; /* defined only for uLevel 0,1,2 */
3995 if (!check_printjob_info(&desc,uLevel,str2)) {
3999 snum = find_service(name);
4000 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4004 count = print_queue_status(snum,&queue,&status);
4006 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4012 desc.buflen = mdrcnt;
4014 if (init_package(&desc,count,0)) {
4016 for (i = 0; i < count; i++) {
4017 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4018 if (desc.errcode == NERR_Success) {
4024 *rdata_len = desc.usedlen;
4027 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4031 SSVALS(*rparam,0,desc.errcode);
4033 SSVAL(*rparam,4,succnt);
4034 SSVAL(*rparam,6,count);
4038 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4043 static int check_printdest_info(struct pack_desc* desc,
4044 int uLevel, char* id)
4046 desc->subformat = NULL;
4049 desc->format = "B9";
4052 desc->format = "B9B21WWzW";
4058 desc->format = "zzzWWzzzWW";
4061 DEBUG(0,("check_printdest_info: invalid level %d\n",
4065 if (id == NULL || strcmp(desc->format,id) != 0) {
4066 DEBUG(0,("check_printdest_info: invalid string %s\n",
4067 id ? id : "<NULL>" ));
4073 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
4074 struct pack_desc* desc)
4078 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
4079 buf[sizeof(buf)-1] = 0;
4083 PACKS(desc,"B9",buf); /* szName */
4085 PACKS(desc,"B21",""); /* szUserName */
4086 PACKI(desc,"W",0); /* uJobId */
4087 PACKI(desc,"W",0); /* fsStatus */
4088 PACKS(desc,"z",""); /* pszStatus */
4089 PACKI(desc,"W",0); /* time */
4093 if (uLevel == 2 || uLevel == 3) {
4094 PACKS(desc,"z",buf); /* pszPrinterName */
4096 PACKS(desc,"z",""); /* pszUserName */
4097 PACKS(desc,"z",""); /* pszLogAddr */
4098 PACKI(desc,"W",0); /* uJobId */
4099 PACKI(desc,"W",0); /* fsStatus */
4100 PACKS(desc,"z",""); /* pszStatus */
4101 PACKS(desc,"z",""); /* pszComment */
4102 PACKS(desc,"z","NULL"); /* pszDrivers */
4103 PACKI(desc,"W",0); /* time */
4104 PACKI(desc,"W",0); /* pad1 */
4109 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4110 char *param, int tpscnt,
4111 char *data, int tdscnt,
4112 int mdrcnt,int mprcnt,
4113 char **rdata,char **rparam,
4114 int *rdata_len,int *rparam_len)
4116 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4117 char *str2 = skip_string(param,tpscnt,str1);
4118 char *p = skip_string(param,tpscnt,str2);
4119 char* PrinterName = p;
4121 struct pack_desc desc;
4125 if (!str1 || !str2 || !p) {
4129 memset((char *)&desc,'\0',sizeof(desc));
4131 p = skip_string(param,tpscnt,p);
4135 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4137 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4139 /* check it's a supported varient */
4140 if (strcmp(str1,"zWrLh") != 0) {
4143 if (!check_printdest_info(&desc,uLevel,str2)) {
4147 snum = find_service(PrinterName);
4148 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4150 desc.errcode = NERR_DestNotFound;
4154 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4159 desc.buflen = mdrcnt;
4162 * Don't return data but need to get correct length
4163 * init_package will return wrong size if buflen=0
4165 desc.buflen = getlen(desc.format);
4166 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4168 if (init_package(&desc,1,0)) {
4169 fill_printdest_info(conn,snum,uLevel,&desc);
4171 *rdata_len = desc.usedlen;
4175 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4179 SSVALS(*rparam,0,desc.errcode);
4181 SSVAL(*rparam,4,desc.neededlen);
4183 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4189 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4190 char *param, int tpscnt,
4191 char *data, int tdscnt,
4192 int mdrcnt,int mprcnt,
4193 char **rdata,char **rparam,
4194 int *rdata_len,int *rparam_len)
4196 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4197 char *str2 = skip_string(param,tpscnt,str1);
4198 char *p = skip_string(param,tpscnt,str2);
4202 struct pack_desc desc;
4203 int services = lp_numservices();
4205 if (!str1 || !str2 || !p) {
4209 memset((char *)&desc,'\0',sizeof(desc));
4211 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4213 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4215 /* check it's a supported varient */
4216 if (strcmp(str1,"WrLeh") != 0) {
4219 if (!check_printdest_info(&desc,uLevel,str2)) {
4224 for (i = 0; i < services; i++) {
4225 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4231 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4238 desc.buflen = mdrcnt;
4239 if (init_package(&desc,queuecnt,0)) {
4242 for (i = 0; i < services; i++) {
4243 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4244 fill_printdest_info(conn,i,uLevel,&desc);
4246 if (desc.errcode == NERR_Success) {
4253 *rdata_len = desc.usedlen;
4256 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4260 SSVALS(*rparam,0,desc.errcode);
4262 SSVAL(*rparam,4,succnt);
4263 SSVAL(*rparam,6,queuecnt);
4265 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4270 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4271 char *param, int tpscnt,
4272 char *data, int tdscnt,
4273 int mdrcnt,int mprcnt,
4274 char **rdata,char **rparam,
4275 int *rdata_len,int *rparam_len)
4277 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4278 char *str2 = skip_string(param,tpscnt,str1);
4279 char *p = skip_string(param,tpscnt,str2);
4282 struct pack_desc desc;
4284 if (!str1 || !str2 || !p) {
4288 memset((char *)&desc,'\0',sizeof(desc));
4290 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4292 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4294 /* check it's a supported varient */
4295 if (strcmp(str1,"WrLeh") != 0) {
4298 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4303 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4309 desc.buflen = mdrcnt;
4310 if (init_package(&desc,1,0)) {
4311 PACKS(&desc,"B41","NULL");
4314 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4316 *rdata_len = desc.usedlen;
4319 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4323 SSVALS(*rparam,0,desc.errcode);
4325 SSVAL(*rparam,4,succnt);
4328 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4333 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4334 char *param, int tpscnt,
4335 char *data, int tdscnt,
4336 int mdrcnt,int mprcnt,
4337 char **rdata,char **rparam,
4338 int *rdata_len,int *rparam_len)
4340 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4341 char *str2 = skip_string(param,tpscnt,str1);
4342 char *p = skip_string(param,tpscnt,str2);
4345 struct pack_desc desc;
4347 if (!str1 || !str2 || !p) {
4350 memset((char *)&desc,'\0',sizeof(desc));
4352 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4354 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4356 /* check it's a supported varient */
4357 if (strcmp(str1,"WrLeh") != 0) {
4360 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4365 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4371 desc.buflen = mdrcnt;
4373 if (init_package(&desc,1,0)) {
4374 PACKS(&desc,"B13","lpd");
4377 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4379 *rdata_len = desc.usedlen;
4382 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4386 SSVALS(*rparam,0,desc.errcode);
4388 SSVAL(*rparam,4,succnt);
4391 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4396 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4397 char *param, int tpscnt,
4398 char *data, int tdscnt,
4399 int mdrcnt,int mprcnt,
4400 char **rdata,char **rparam,
4401 int *rdata_len,int *rparam_len)
4403 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4404 char *str2 = skip_string(param,tpscnt,str1);
4405 char *p = skip_string(param,tpscnt,str2);
4408 struct pack_desc desc;
4410 if (!str1 || !str2 || !p) {
4414 memset((char *)&desc,'\0',sizeof(desc));
4416 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4418 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4420 /* check it's a supported varient */
4421 if (strcmp(str1,"WrLeh") != 0) {
4424 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4429 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4434 memset((char *)&desc,'\0',sizeof(desc));
4436 desc.buflen = mdrcnt;
4438 if (init_package(&desc,1,0)) {
4439 PACKS(&desc,"B13","lp0");
4442 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4444 *rdata_len = desc.usedlen;
4447 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4451 SSVALS(*rparam,0,desc.errcode);
4453 SSVAL(*rparam,4,succnt);
4456 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4461 /****************************************************************************
4463 ****************************************************************************/
4465 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4466 char *param, int tpscnt,
4467 char *data, int tdscnt,
4468 int mdrcnt,int mprcnt,
4469 char **rdata,char **rparam,
4470 int *rdata_len,int *rparam_len)
4473 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4474 char *str2 = skip_string(param,tpscnt,str1);
4475 char *p = skip_string(param,tpscnt,str2);
4477 struct pack_desc desc;
4478 struct sessionid *session_list;
4479 int i, num_sessions;
4481 if (!str1 || !str2 || !p) {
4485 memset((char *)&desc,'\0',sizeof(desc));
4487 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4489 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4490 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4491 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4493 /* check it's a supported varient */
4494 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4497 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4501 num_sessions = list_sessions(talloc_tos(), &session_list);
4504 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4509 memset((char *)&desc,'\0',sizeof(desc));
4511 desc.buflen = mdrcnt;
4513 if (!init_package(&desc,num_sessions,0)) {
4517 for(i=0; i<num_sessions; i++) {
4518 PACKS(&desc, "z", session_list[i].remote_machine);
4519 PACKS(&desc, "z", session_list[i].username);
4520 PACKI(&desc, "W", 1); /* num conns */
4521 PACKI(&desc, "W", 0); /* num opens */
4522 PACKI(&desc, "W", 1); /* num users */
4523 PACKI(&desc, "D", 0); /* session time */
4524 PACKI(&desc, "D", 0); /* idle time */
4525 PACKI(&desc, "D", 0); /* flags */
4526 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4529 *rdata_len = desc.usedlen;
4532 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4536 SSVALS(*rparam,0,desc.errcode);
4537 SSVAL(*rparam,2,0); /* converter */
4538 SSVAL(*rparam,4,num_sessions); /* count */
4540 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4546 /****************************************************************************
4547 The buffer was too small.
4548 ****************************************************************************/
4550 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4551 int mdrcnt, int mprcnt,
4552 char **rdata, char **rparam,
4553 int *rdata_len, int *rparam_len)
4555 *rparam_len = MIN(*rparam_len,mprcnt);
4556 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4563 SSVAL(*rparam,0,NERR_BufTooSmall);
4565 DEBUG(3,("Supplied buffer too small in API command\n"));
4570 /****************************************************************************
4571 The request is not supported.
4572 ****************************************************************************/
4574 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4575 char *param, int tpscnt,
4576 char *data, int tdscnt,
4577 int mdrcnt, int mprcnt,
4578 char **rdata, char **rparam,
4579 int *rdata_len, int *rparam_len)
4582 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4589 SSVAL(*rparam,0,NERR_notsupported);
4590 SSVAL(*rparam,2,0); /* converter word */
4592 DEBUG(3,("Unsupported API command\n"));
4597 static const struct {
4600 bool (*fn)(connection_struct *, uint16,
4603 int,int,char **,char **,int *,int *);
4604 bool auth_user; /* Deny anonymous access? */
4605 } api_commands[] = {
4606 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4607 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4608 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4609 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4610 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4611 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4612 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4613 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4614 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4615 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4616 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4617 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4618 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4619 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4620 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4621 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4622 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4623 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4624 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4625 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4626 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4627 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4628 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4629 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4630 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4631 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4632 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4633 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4634 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4635 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4636 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4637 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4638 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4639 {NULL, -1, api_Unsupported}
4640 /* The following RAP calls are not implemented by Samba:
4642 RAP_WFileEnum2 - anon not OK
4647 /****************************************************************************
4648 Handle remote api calls.
4649 ****************************************************************************/
4651 void api_reply(connection_struct *conn, uint16 vuid,
4652 struct smb_request *req,
4653 char *data, char *params,
4654 int tdscnt, int tpscnt,
4655 int mdrcnt, int mprcnt)
4657 struct smbd_server_connection *sconn = smbd_server_conn;
4660 char *rparam = NULL;
4661 const char *name1 = NULL;
4662 const char *name2 = NULL;
4669 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4678 api_command = SVAL(params,0);
4679 /* Is there a string at position params+2 ? */
4680 if (skip_string(params,tpscnt,params+2)) {
4685 name2 = skip_string(params,tpscnt,params+2);
4690 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4694 tdscnt,tpscnt,mdrcnt,mprcnt));
4696 for (i=0;api_commands[i].name;i++) {
4697 if (api_commands[i].id == api_command && api_commands[i].fn) {
4698 DEBUG(3,("Doing %s\n",api_commands[i].name));
4703 /* Check whether this api call can be done anonymously */
4705 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4706 user_struct *user = get_valid_user_struct(sconn, vuid);
4708 if (!user || user->server_info->guest) {
4709 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4714 rdata = (char *)SMB_MALLOC(1024);
4716 memset(rdata,'\0',1024);
4719 rparam = (char *)SMB_MALLOC(1024);
4721 memset(rparam,'\0',1024);
4724 if(!rdata || !rparam) {
4725 DEBUG(0,("api_reply: malloc fail !\n"));
4728 reply_nterror(req, NT_STATUS_NO_MEMORY);
4732 reply = api_commands[i].fn(conn,
4734 params,tpscnt, /* params + length */
4735 data,tdscnt, /* data + length */
4737 &rdata,&rparam,&rdata_len,&rparam_len);
4740 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4741 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4742 &rdata,&rparam,&rdata_len,&rparam_len);
4745 /* if we get False back then it's actually unsupported */
4747 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4748 &rdata,&rparam,&rdata_len,&rparam_len);
4751 /* If api_Unsupported returns false we can't return anything. */
4753 send_trans_reply(conn, req, rparam, rparam_len,
4754 rdata, rdata_len, False);