2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/srv_samr.h"
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 /* Limit size of ipc replies */
55 static char *smb_realloc_limit(void *ptr, size_t size)
59 size = MAX((size),4*1024);
60 val = (char *)SMB_REALLOC(ptr,size);
62 memset(val,'\0',size);
67 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
68 char *param, int tpscnt,
69 char *data, int tdscnt,
70 int mdrcnt, int mprcnt,
71 char **rdata, char **rparam,
72 int *rdata_len, int *rparam_len);
74 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
75 int mdrcnt, int mprcnt,
76 char **rdata, char **rparam,
77 int *rdata_len, int *rparam_len);
80 static int CopyExpanded(connection_struct *conn,
81 int snum, char **dst, char *src, int *p_space_remaining)
83 TALLOC_CTX *ctx = talloc_tos();
87 if (!src || !dst || !p_space_remaining || !(*dst) ||
88 *p_space_remaining <= 0) {
92 buf = talloc_strdup(ctx, src);
94 *p_space_remaining = 0;
97 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
99 *p_space_remaining = 0;
102 buf = talloc_sub_advanced(ctx,
103 lp_servicename(SNUM(conn)),
104 conn->server_info->unix_name,
106 conn->server_info->utok.gid,
107 conn->server_info->sanitized_username,
108 pdb_get_domain(conn->server_info->sam_account),
111 *p_space_remaining = 0;
114 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
119 (*p_space_remaining) -= l;
123 static int CopyAndAdvance(char **dst, char *src, int *n)
126 if (!src || !dst || !n || !(*dst)) {
129 l = push_ascii(*dst,src,*n, STR_TERMINATE);
138 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
140 TALLOC_CTX *ctx = talloc_tos();
145 buf = talloc_strdup(ctx,s);
149 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
153 buf = talloc_sub_advanced(ctx,
154 lp_servicename(SNUM(conn)),
155 conn->server_info->unix_name,
157 conn->server_info->utok.gid,
158 conn->server_info->sanitized_username,
159 pdb_get_domain(conn->server_info->sam_account),
164 return strlen(buf) + 1;
167 static char *Expand(connection_struct *conn, int snum, char *s)
169 TALLOC_CTX *ctx = talloc_tos();
175 buf = talloc_strdup(ctx,s);
179 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
183 return talloc_sub_advanced(ctx,
184 lp_servicename(SNUM(conn)),
185 conn->server_info->unix_name,
187 conn->server_info->utok.gid,
188 conn->server_info->sanitized_username,
189 pdb_get_domain(conn->server_info->sam_account),
193 /*******************************************************************
194 Check a API string for validity when we only need to check the prefix.
195 ******************************************************************/
197 static bool prefix_ok(const char *str, const char *prefix)
199 return(strncmp(str,prefix,strlen(prefix)) == 0);
203 const char *format; /* formatstring for structure */
204 const char *subformat; /* subformat for structure */
205 char *base; /* baseaddress of buffer */
206 int buflen; /* remaining size for fixed part; on init: length of base */
207 int subcount; /* count of substructures */
208 char *structbuf; /* pointer into buffer for remaining fixed part */
209 int stringlen; /* remaining size for variable part */
210 char *stringbuf; /* pointer into buffer for remaining variable part */
211 int neededlen; /* total needed size */
212 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
213 const char *curpos; /* current position; pointer into format or subformat */
217 static int get_counter(const char **p)
223 if (!isdigit((int)**p)) {
229 n = 10 * n + (i - '0');
237 static int getlen(const char *p)
246 case 'W': /* word (2 byte) */
249 case 'K': /* status word? (2 byte) */
252 case 'N': /* count of substructures (word) at end */
255 case 'D': /* double word (4 byte) */
256 case 'z': /* offset to zero terminated string (4 byte) */
257 case 'l': /* offset to user data (4 byte) */
260 case 'b': /* offset to data (with counter) (4 byte) */
264 case 'B': /* byte (with optional counter) */
265 n += get_counter(&p);
272 static bool init_package(struct pack_desc *p, int count, int subcount)
277 if (!p->format || !p->base) {
281 i = count * getlen(p->format);
283 i += subcount * getlen(p->subformat);
285 p->structbuf = p->base;
289 p->curpos = p->format;
295 * This is the old error code we used. Aparently
296 * WinNT/2k systems return ERRbuftoosmall (2123) and
297 * OS/2 needs this. I'm leaving this here so we can revert
300 p->errcode = ERRmoredata;
302 p->errcode = ERRbuftoosmall;
305 p->errcode = NERR_Success;
309 p->stringbuf = p->base + i;
311 return (p->errcode == NERR_Success);
314 static int package(struct pack_desc *p, ...)
317 int needed=0, stringneeded;
318 const char *str=NULL;
319 int is_string=0, stringused;
326 p->curpos = p->format;
328 p->curpos = p->subformat;
333 str = va_arg(args,char*);
334 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
343 switch( *p->curpos++ ) {
344 case 'W': /* word (2 byte) */
346 temp = va_arg(args,int);
347 if (p->buflen >= needed) {
348 SSVAL(p->structbuf,0,temp);
351 case 'K': /* status word? (2 byte) */
353 temp = va_arg(args,int);
354 if (p->buflen >= needed) {
355 SSVAL(p->structbuf,0,temp);
358 case 'N': /* count of substructures (word) at end */
360 p->subcount = va_arg(args,int);
361 if (p->buflen >= needed) {
362 SSVAL(p->structbuf,0,p->subcount);
365 case 'D': /* double word (4 byte) */
367 temp = va_arg(args,int);
368 if (p->buflen >= needed) {
369 SIVAL(p->structbuf,0,temp);
372 case 'B': /* byte (with optional counter) */
373 needed = get_counter(&p->curpos);
375 char *s = va_arg(args,char*);
376 if (p->buflen >= needed) {
377 StrnCpy(p->structbuf,s?s:"",needed-1);
381 case 'z': /* offset to zero terminated string (4 byte) */
382 str = va_arg(args,char*);
383 stringneeded = (str ? strlen(str)+1 : 0);
386 case 'l': /* offset to user data (4 byte) */
387 str = va_arg(args,char*);
388 stringneeded = va_arg(args,int);
391 case 'b': /* offset to data (with counter) (4 byte) */
392 str = va_arg(args,char*);
393 stringneeded = get_counter(&p->curpos);
399 if (stringneeded >= 0) {
401 if (p->buflen >= needed) {
402 stringused = stringneeded;
403 if (stringused > p->stringlen) {
404 stringused = (is_string ? p->stringlen : 0);
405 if (p->errcode == NERR_Success) {
406 p->errcode = ERRmoredata;
410 SIVAL(p->structbuf,0,0);
412 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
413 memcpy(p->stringbuf,str?str:"",stringused);
415 p->stringbuf[stringused-1] = '\0';
417 p->stringbuf += stringused;
418 p->stringlen -= stringused;
419 p->usedlen += stringused;
422 p->neededlen += stringneeded;
425 p->neededlen += needed;
426 if (p->buflen >= needed) {
427 p->structbuf += needed;
429 p->usedlen += needed;
431 if (p->errcode == NERR_Success) {
432 p->errcode = ERRmoredata;
439 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
440 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
442 #define PACK(desc,t,v) package(desc,v)
443 #define PACKl(desc,t,v,l) package(desc,v,l)
446 static void PACKI(struct pack_desc* desc, const char *t,int v)
451 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
456 /****************************************************************************
458 ****************************************************************************/
460 static void PackDriverData(struct pack_desc* desc)
462 char drivdata[4+4+32];
463 SIVAL(drivdata,0,sizeof drivdata); /* cb */
464 SIVAL(drivdata,4,1000); /* lVersion */
465 memset(drivdata+8,0,32); /* szDeviceName */
466 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
467 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
470 static int check_printq_info(struct pack_desc* desc,
471 unsigned int uLevel, char *id1, char *id2)
473 desc->subformat = NULL;
476 desc->format = "B13";
479 desc->format = "B13BWWWzzzzzWW";
482 desc->format = "B13BWWWzzzzzWN";
483 desc->subformat = "WB21BB16B10zWWzDDz";
486 desc->format = "zWWWWzzzzWWzzl";
489 desc->format = "zWWWWzzzzWNzzl";
490 desc->subformat = "WWzWWDDzz";
499 desc->format = "WzzzzzzzzN";
500 desc->subformat = "z";
503 DEBUG(0,("check_printq_info: invalid level %d\n",
507 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
508 DEBUG(0,("check_printq_info: invalid format %s\n",
509 id1 ? id1 : "<NULL>" ));
512 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
513 DEBUG(0,("check_printq_info: invalid subformat %s\n",
514 id2 ? id2 : "<NULL>" ));
521 #define RAP_JOB_STATUS_QUEUED 0
522 #define RAP_JOB_STATUS_PAUSED 1
523 #define RAP_JOB_STATUS_SPOOLING 2
524 #define RAP_JOB_STATUS_PRINTING 3
525 #define RAP_JOB_STATUS_PRINTED 4
527 #define RAP_QUEUE_STATUS_PAUSED 1
528 #define RAP_QUEUE_STATUS_ERROR 2
530 /* turn a print job status into a on the wire status
532 static int printj_status(int v)
536 return RAP_JOB_STATUS_QUEUED;
538 return RAP_JOB_STATUS_PAUSED;
540 return RAP_JOB_STATUS_SPOOLING;
542 return RAP_JOB_STATUS_PRINTING;
547 /* turn a print queue status into a on the wire status
549 static int printq_status(int v)
555 return RAP_QUEUE_STATUS_PAUSED;
557 return RAP_QUEUE_STATUS_ERROR;
560 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
561 struct pack_desc *desc,
562 print_queue_struct *queue, int n)
564 time_t t = queue->time;
566 /* the client expects localtime */
567 t -= get_time_zone(t);
569 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
571 PACKS(desc,"B21",queue->fs_user); /* szUserName */
572 PACKS(desc,"B",""); /* pad */
573 PACKS(desc,"B16",""); /* szNotifyName */
574 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
575 PACKS(desc,"z",""); /* pszParms */
576 PACKI(desc,"W",n+1); /* uPosition */
577 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
578 PACKS(desc,"z",""); /* pszStatus */
579 PACKI(desc,"D",t); /* ulSubmitted */
580 PACKI(desc,"D",queue->size); /* ulSize */
581 PACKS(desc,"z",queue->fs_file); /* pszComment */
583 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
584 PACKI(desc,"W",queue->priority); /* uPriority */
585 PACKS(desc,"z",queue->fs_user); /* pszUserName */
586 PACKI(desc,"W",n+1); /* uPosition */
587 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
588 PACKI(desc,"D",t); /* ulSubmitted */
589 PACKI(desc,"D",queue->size); /* ulSize */
590 PACKS(desc,"z","Samba"); /* pszComment */
591 PACKS(desc,"z",queue->fs_file); /* pszDocument */
593 PACKS(desc,"z",""); /* pszNotifyName */
594 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
595 PACKS(desc,"z",""); /* pszParms */
596 PACKS(desc,"z",""); /* pszStatus */
597 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
598 PACKS(desc,"z","lpd"); /* pszQProcName */
599 PACKS(desc,"z",""); /* pszQProcParms */
600 PACKS(desc,"z","NULL"); /* pszDriverName */
601 PackDriverData(desc); /* pDriverData */
602 PACKS(desc,"z",""); /* pszPrinterName */
603 } else if (uLevel == 4) { /* OS2 */
604 PACKS(desc,"z",""); /* pszSpoolFileName */
605 PACKS(desc,"z",""); /* pszPortName */
606 PACKS(desc,"z",""); /* pszStatus */
607 PACKI(desc,"D",0); /* ulPagesSpooled */
608 PACKI(desc,"D",0); /* ulPagesSent */
609 PACKI(desc,"D",0); /* ulPagesPrinted */
610 PACKI(desc,"D",0); /* ulTimePrinted */
611 PACKI(desc,"D",0); /* ulExtendJobStatus */
612 PACKI(desc,"D",0); /* ulStartPage */
613 PACKI(desc,"D",0); /* ulEndPage */
618 /********************************************************************
619 Return a driver name given an snum.
620 Returns True if from tdb, False otherwise.
621 ********************************************************************/
623 static bool get_driver_name(int snum, char **pp_drivername)
625 NT_PRINTER_INFO_LEVEL *info = NULL;
628 get_a_printer (NULL, &info, 2, lp_servicename(snum));
630 *pp_drivername = talloc_strdup(talloc_tos(),
631 info->info_2->drivername);
633 free_a_printer(&info, 2);
634 if (!*pp_drivername) {
642 /********************************************************************
643 Respond to the DosPrintQInfo command with a level of 52
644 This is used to get printer driver information for Win9x clients
645 ********************************************************************/
646 static void fill_printq_info_52(connection_struct *conn, int snum,
647 struct pack_desc* desc, int count )
651 struct spoolss_DriverInfo8 *driver = NULL;
652 NT_PRINTER_INFO_LEVEL *printer = NULL;
654 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
655 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
656 lp_servicename(snum)));
660 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
663 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
664 printer->info_2->drivername));
668 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
669 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
670 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
672 PACKI(desc, "W", 0x0400); /* don't know */
673 PACKS(desc, "z", driver->driver_name); /* long printer name */
674 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
675 PACKS(desc, "z", driver->data_file); /* Datafile name */
676 PACKS(desc, "z", driver->monitor_name); /* language monitor */
678 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
679 standard_sub_basic( "", "", location, sizeof(location)-1 );
680 PACKS(desc,"z", location); /* share to retrieve files */
682 PACKS(desc,"z", driver->default_datatype); /* default data type */
683 PACKS(desc,"z", driver->help_file); /* helpfile name */
684 PACKS(desc,"z", driver->driver_path); /* driver name */
686 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
687 DEBUG(3,("Driver: %s:\n",driver->driver_path));
688 DEBUG(3,("Data File: %s:\n",driver->data_file));
689 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
690 DEBUG(3,("Driver Location: %s:\n",location));
691 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
692 DEBUG(3,("Help File: %s:\n",driver->help_file));
693 PACKI(desc,"N",count); /* number of files to copy */
695 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
697 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
698 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
699 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
704 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
707 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
709 desc->errcode=NERR_Success;
713 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
714 desc->errcode=NERR_notsupported;
718 free_a_printer( &printer, 2 );
720 free_a_printer_driver(driver);
724 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
725 struct pack_desc* desc,
726 int count, print_queue_struct* queue,
727 print_status_struct* status)
732 PACKS(desc,"B13",SERVICE(snum));
737 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
740 PACKI(desc,"K",printq_status(status->status));
744 if (uLevel == 1 || uLevel == 2) {
745 PACKS(desc,"B",""); /* alignment */
746 PACKI(desc,"W",5); /* priority */
747 PACKI(desc,"W",0); /* start time */
748 PACKI(desc,"W",0); /* until time */
749 PACKS(desc,"z",""); /* pSepFile */
750 PACKS(desc,"z","lpd"); /* pPrProc */
751 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
752 PACKS(desc,"z",""); /* pParms */
754 PACKS(desc,"z","UNKNOWN PRINTER");
755 PACKI(desc,"W",LPSTAT_ERROR);
757 else if (!status || !status->message[0]) {
758 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
759 PACKI(desc,"W",LPSTAT_OK); /* status */
761 PACKS(desc,"z",status->message);
762 PACKI(desc,"W",printq_status(status->status)); /* status */
764 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
767 if (uLevel == 3 || uLevel == 4) {
768 char *drivername = NULL;
770 PACKI(desc,"W",5); /* uPriority */
771 PACKI(desc,"W",0); /* uStarttime */
772 PACKI(desc,"W",0); /* uUntiltime */
773 PACKI(desc,"W",5); /* pad1 */
774 PACKS(desc,"z",""); /* pszSepFile */
775 PACKS(desc,"z","WinPrint"); /* pszPrProc */
776 PACKS(desc,"z",NULL); /* pszParms */
777 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
778 /* "don't ask" that it's done this way to fix corrupted
779 Win9X/ME printer comments. */
781 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
783 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
785 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
786 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
787 get_driver_name(snum,&drivername);
791 PACKS(desc,"z",drivername); /* pszDriverName */
792 PackDriverData(desc); /* pDriverData */
795 if (uLevel == 2 || uLevel == 4) {
797 for (i=0;i<count;i++)
798 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
802 fill_printq_info_52( conn, snum, desc, count );
805 /* This function returns the number of files for a given driver */
806 static int get_printerdrivernumber(int snum)
809 struct spoolss_DriverInfo8 *driver;
810 NT_PRINTER_INFO_LEVEL *printer = NULL;
814 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
815 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
816 lp_servicename(snum)));
820 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
823 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
824 printer->info_2->drivername));
828 /* count the number of files */
829 while (driver->dependent_files && *driver->dependent_files[result])
833 free_a_printer( &printer, 2 );
835 free_a_printer_driver(driver);
840 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
841 char *param, int tpscnt,
842 char *data, int tdscnt,
843 int mdrcnt,int mprcnt,
844 char **rdata,char **rparam,
845 int *rdata_len,int *rparam_len)
847 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
848 char *str2 = skip_string(param,tpscnt,str1);
849 char *p = skip_string(param,tpscnt,str2);
855 struct pack_desc desc;
856 print_queue_struct *queue=NULL;
857 print_status_struct status;
860 if (!str1 || !str2 || !p) {
863 memset((char *)&status,'\0',sizeof(status));
864 memset((char *)&desc,'\0',sizeof(desc));
866 p = skip_string(param,tpscnt,p);
870 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
871 str3 = get_safe_str_ptr(param,tpscnt,p,4);
872 /* str3 may be null here and is checked in check_printq_info(). */
874 /* remove any trailing username */
875 if ((p = strchr_m(QueueName,'%')))
878 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
880 /* check it's a supported varient */
881 if (!prefix_ok(str1,"zWrLh"))
883 if (!check_printq_info(&desc,uLevel,str2,str3)) {
885 * Patch from Scott Moomaw <scott@bridgewater.edu>
886 * to return the 'invalid info level' error if an
887 * unknown level was requested.
891 *rparam = smb_realloc_limit(*rparam,*rparam_len);
895 SSVALS(*rparam,0,ERRunknownlevel);
901 snum = find_service(QueueName);
902 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
906 count = get_printerdrivernumber(snum);
907 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
909 count = print_queue_status(snum, &queue,&status);
913 *rdata = smb_realloc_limit(*rdata,mdrcnt);
919 desc.buflen = mdrcnt;
922 * Don't return data but need to get correct length
923 * init_package will return wrong size if buflen=0
925 desc.buflen = getlen(desc.format);
926 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
929 if (init_package(&desc,1,count)) {
930 desc.subcount = count;
931 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
934 *rdata_len = desc.usedlen;
937 * We must set the return code to ERRbuftoosmall
938 * in order to support lanman style printing with Win NT/2k
941 if (!mdrcnt && lp_disable_spoolss())
942 desc.errcode = ERRbuftoosmall;
944 *rdata_len = desc.usedlen;
946 *rparam = smb_realloc_limit(*rparam,*rparam_len);
952 SSVALS(*rparam,0,desc.errcode);
954 SSVAL(*rparam,4,desc.neededlen);
956 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
964 /****************************************************************************
965 View list of all print jobs on all queues.
966 ****************************************************************************/
968 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
969 char *param, int tpscnt,
970 char *data, int tdscnt,
971 int mdrcnt, int mprcnt,
972 char **rdata, char** rparam,
973 int *rdata_len, int *rparam_len)
975 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
976 char *output_format1 = skip_string(param,tpscnt,param_format);
977 char *p = skip_string(param,tpscnt,output_format1);
978 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
979 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
980 int services = lp_numservices();
982 struct pack_desc desc;
983 print_queue_struct **queue = NULL;
984 print_status_struct *status = NULL;
985 int *subcntarr = NULL;
986 int queuecnt = 0, subcnt = 0, succnt = 0;
988 if (!param_format || !output_format1 || !p) {
992 memset((char *)&desc,'\0',sizeof(desc));
994 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
996 if (!prefix_ok(param_format,"WrLeh")) {
999 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1001 * Patch from Scott Moomaw <scott@bridgewater.edu>
1002 * to return the 'invalid info level' error if an
1003 * unknown level was requested.
1007 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1011 SSVALS(*rparam,0,ERRunknownlevel);
1017 for (i = 0; i < services; i++) {
1018 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1023 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1024 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1027 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1028 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1029 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1032 memset(status,0,queuecnt*sizeof(print_status_struct));
1033 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1034 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1040 for (i = 0; i < services; i++) {
1041 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1042 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1043 subcnt += subcntarr[n];
1049 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1055 desc.buflen = mdrcnt;
1057 if (init_package(&desc,queuecnt,subcnt)) {
1060 for (i = 0; i < services; i++) {
1061 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1062 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1064 if (desc.errcode == NERR_Success) {
1071 SAFE_FREE(subcntarr);
1073 *rdata_len = desc.usedlen;
1075 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1079 SSVALS(*rparam,0,desc.errcode);
1081 SSVAL(*rparam,4,succnt);
1082 SSVAL(*rparam,6,queuecnt);
1084 for (i = 0; i < queuecnt; i++) {
1086 SAFE_FREE(queue[i]);
1097 SAFE_FREE(subcntarr);
1098 for (i = 0; i < queuecnt; i++) {
1100 SAFE_FREE(queue[i]);
1109 /****************************************************************************
1110 Get info level for a server list query.
1111 ****************************************************************************/
1113 static bool check_server_info(int uLevel, char* id)
1117 if (strcmp(id,"B16") != 0) {
1122 if (strcmp(id,"B16BBDz") != 0) {
1132 struct srv_info_struct {
1140 /*******************************************************************
1141 Get server info lists from the files saved by nmbd. Return the
1143 ******************************************************************/
1145 static int get_server_info(uint32 servertype,
1146 struct srv_info_struct **servers,
1152 bool local_list_only;
1155 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1157 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1161 /* request for everything is code for request all servers */
1162 if (servertype == SV_TYPE_ALL) {
1163 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1166 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1168 DEBUG(4,("Servertype search: %8x\n",servertype));
1170 for (i=0;lines[i];i++) {
1172 struct srv_info_struct *s;
1173 const char *ptr = lines[i];
1175 TALLOC_CTX *frame = NULL;
1182 if (count == alloced) {
1184 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1186 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1190 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1192 s = &(*servers)[count];
1194 frame = talloc_stackframe();
1196 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1200 fstrcpy(s->name, p);
1203 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1209 s->comment[0] = '\0';
1210 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1214 fstrcpy(s->comment, p);
1215 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1217 s->domain[0] = '\0';
1218 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1219 /* this allows us to cope with an old nmbd */
1220 fstrcpy(s->domain,lp_workgroup());
1222 fstrcpy(s->domain, p);
1226 if (sscanf(stype,"%X",&s->type) != 1) {
1227 DEBUG(4,("r:host file "));
1231 /* Filter the servers/domains we return based on what was asked for. */
1233 /* Check to see if we are being asked for a local list only. */
1234 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1235 DEBUG(4,("r: local list only"));
1239 /* doesn't match up: don't want it */
1240 if (!(servertype & s->type)) {
1241 DEBUG(4,("r:serv type "));
1245 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1246 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1247 DEBUG(4,("s: dom mismatch "));
1251 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1255 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1256 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1259 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1260 s->name, s->type, s->comment, s->domain));
1261 s->server_added = True;
1264 DEBUG(4,("%20s %8x %25s %15s\n",
1265 s->name, s->type, s->comment, s->domain));
1273 /*******************************************************************
1274 Fill in a server info structure.
1275 ******************************************************************/
1277 static int fill_srv_info(struct srv_info_struct *service,
1278 int uLevel, char **buf, int *buflen,
1279 char **stringbuf, int *stringspace, char *baseaddr)
1302 len = strlen(service->comment)+1;
1306 *buflen = struct_len;
1308 return struct_len + len;
1313 if (*buflen < struct_len) {
1320 p2 = p + struct_len;
1321 l2 = *buflen - struct_len;
1329 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1333 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1334 SIVAL(p,18,service->type);
1335 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1336 len += CopyAndAdvance(&p2,service->comment,&l2);
1341 *buf = p + struct_len;
1342 *buflen -= struct_len;
1353 static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1355 return(strcmp(s1->name,s2->name));
1358 /****************************************************************************
1359 View list of servers available (or possibly domains). The info is
1360 extracted from lists saved by nmbd on the local host.
1361 ****************************************************************************/
1363 static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
1364 char *param, int tpscnt,
1365 char *data, int tdscnt,
1366 int mdrcnt, int mprcnt, char **rdata,
1367 char **rparam, int *rdata_len, int *rparam_len)
1369 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1370 char *str2 = skip_string(param,tpscnt,str1);
1371 char *p = skip_string(param,tpscnt,str2);
1372 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1373 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1374 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1376 int data_len, fixed_len, string_len;
1377 int f_len = 0, s_len = 0;
1378 struct srv_info_struct *servers=NULL;
1379 int counted=0,total=0;
1382 bool domain_request;
1385 if (!str1 || !str2 || !p) {
1389 /* If someone sets all the bits they don't really mean to set
1390 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1393 if (servertype == SV_TYPE_ALL) {
1394 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1397 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1398 any other bit (they may just set this bit on its own) they
1399 want all the locally seen servers. However this bit can be
1400 set on its own so set the requested servers to be
1401 ALL - DOMAIN_ENUM. */
1403 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1404 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1407 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1408 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1412 if (!prefix_ok(str1,"WrLehD")) {
1415 if (!check_server_info(uLevel,str2)) {
1419 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1420 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1421 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1423 if (strcmp(str1, "WrLehDz") == 0) {
1424 if (skip_string(param,tpscnt,p) == NULL) {
1427 pull_ascii_fstring(domain, p);
1429 fstrcpy(domain, lp_workgroup());
1432 DEBUG(4, ("domain [%s]\n", domain));
1434 if (lp_browse_list()) {
1435 total = get_server_info(servertype,&servers,domain);
1438 data_len = fixed_len = string_len = 0;
1442 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1446 char *lastname=NULL;
1448 for (i=0;i<total;i++) {
1449 struct srv_info_struct *s = &servers[i];
1451 if (lastname && strequal(lastname,s->name)) {
1455 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1456 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1457 i, s->name, s->type, s->comment, s->domain));
1459 if (data_len <= buf_len) {
1462 string_len += s_len;
1469 *rdata_len = fixed_len + string_len;
1470 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1475 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1481 char *lastname=NULL;
1482 int count2 = counted;
1484 for (i = 0; i < total && count2;i++) {
1485 struct srv_info_struct *s = &servers[i];
1487 if (lastname && strequal(lastname,s->name)) {
1491 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1492 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1493 i, s->name, s->type, s->comment, s->domain));
1499 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1503 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1505 SSVAL(*rparam,4,counted);
1506 SSVAL(*rparam,6,counted+missed);
1510 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1511 domain,uLevel,counted,counted+missed));
1516 /****************************************************************************
1517 command 0x34 - suspected of being a "Lookup Names" stub api
1518 ****************************************************************************/
1520 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1521 char *param, int tpscnt,
1522 char *data, int tdscnt,
1523 int mdrcnt, int mprcnt, char **rdata,
1524 char **rparam, int *rdata_len, int *rparam_len)
1526 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1527 char *str2 = skip_string(param,tpscnt,str1);
1528 char *p = skip_string(param,tpscnt,str2);
1529 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1530 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1534 if (!str1 || !str2 || !p) {
1538 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1539 str1, str2, p, uLevel, buf_len));
1541 if (!prefix_ok(str1,"zWrLeh")) {
1548 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1553 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1555 SSVAL(*rparam,4,counted);
1556 SSVAL(*rparam,6,counted+missed);
1561 /****************************************************************************
1562 get info about a share
1563 ****************************************************************************/
1565 static bool check_share_info(int uLevel, char* id)
1569 if (strcmp(id,"B13") != 0) {
1574 /* Level-2 descriptor is allowed (and ignored) */
1575 if (strcmp(id,"B13BWz") != 0 &&
1576 strcmp(id,"B13BWzWWWzB9B") != 0) {
1581 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1586 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1596 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1597 char** buf, int* buflen,
1598 char** stringbuf, int* stringspace, char* baseaddr)
1627 len += StrlenExpanded(conn,snum,lp_comment(snum));
1630 len += strlen(lp_pathname(snum)) + 1;
1633 *buflen = struct_len;
1638 return struct_len + len;
1643 if ((*buflen) < struct_len) {
1651 p2 = p + struct_len;
1652 l2 = (*buflen) - struct_len;
1659 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1665 type = STYPE_DISKTREE;
1666 if (lp_print_ok(snum)) {
1667 type = STYPE_PRINTQ;
1669 if (strequal("IPC",lp_fstype(snum))) {
1672 SSVAL(p,14,type); /* device type */
1673 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1674 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1678 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1679 SSVALS(p,22,-1); /* max uses */
1680 SSVAL(p,24,1); /* current uses */
1681 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1682 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1683 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1687 memset(p+40,0,SHPWLEN+2);
1698 (*buf) = p + struct_len;
1699 (*buflen) -= struct_len;
1701 (*stringspace) = l2;
1710 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1711 char *param, int tpscnt,
1712 char *data, int tdscnt,
1713 int mdrcnt,int mprcnt,
1714 char **rdata,char **rparam,
1715 int *rdata_len,int *rparam_len)
1717 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1718 char *str2 = skip_string(param,tpscnt,str1);
1719 char *netname = skip_string(param,tpscnt,str2);
1720 char *p = skip_string(param,tpscnt,netname);
1721 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1724 if (!str1 || !str2 || !netname || !p) {
1728 snum = find_service(netname);
1733 /* check it's a supported varient */
1734 if (!prefix_ok(str1,"zWrLh")) {
1737 if (!check_share_info(uLevel,str2)) {
1741 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1746 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1747 if (*rdata_len < 0) {
1752 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1756 SSVAL(*rparam,0,NERR_Success);
1757 SSVAL(*rparam,2,0); /* converter word */
1758 SSVAL(*rparam,4,*rdata_len);
1763 /****************************************************************************
1764 View the list of available shares.
1766 This function is the server side of the NetShareEnum() RAP call.
1767 It fills the return buffer with share names and share comments.
1768 Note that the return buffer normally (in all known cases) allows only
1769 twelve byte strings for share names (plus one for a nul terminator).
1770 Share names longer than 12 bytes must be skipped.
1771 ****************************************************************************/
1773 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1774 char *param, int tpscnt,
1775 char *data, int tdscnt,
1783 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1784 char *str2 = skip_string(param,tpscnt,str1);
1785 char *p = skip_string(param,tpscnt,str2);
1786 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1787 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1790 int total=0,counted=0;
1791 bool missed = False;
1793 int data_len, fixed_len, string_len;
1794 int f_len = 0, s_len = 0;
1796 if (!str1 || !str2 || !p) {
1800 if (!prefix_ok(str1,"WrLeh")) {
1803 if (!check_share_info(uLevel,str2)) {
1807 /* Ensure all the usershares are loaded. */
1809 load_registry_shares();
1810 count = load_usershare_shares();
1813 data_len = fixed_len = string_len = 0;
1814 for (i=0;i<count;i++) {
1815 fstring servicename_dos;
1816 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1819 push_ascii_fstring(servicename_dos, lp_servicename(i));
1820 /* Maximum name length = 13. */
1821 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1823 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1824 if (data_len <= buf_len) {
1827 string_len += s_len;
1834 *rdata_len = fixed_len + string_len;
1835 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1840 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1845 for( i = 0; i < count; i++ ) {
1846 fstring servicename_dos;
1847 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1851 push_ascii_fstring(servicename_dos, lp_servicename(i));
1852 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1853 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1860 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1864 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1866 SSVAL(*rparam,4,counted);
1867 SSVAL(*rparam,6,total);
1869 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1870 counted,total,uLevel,
1871 buf_len,*rdata_len,mdrcnt));
1876 /****************************************************************************
1878 ****************************************************************************/
1880 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1881 char *param, int tpscnt,
1882 char *data, int tdscnt,
1883 int mdrcnt,int mprcnt,
1884 char **rdata,char **rparam,
1885 int *rdata_len,int *rparam_len)
1887 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1888 char *str2 = skip_string(param,tpscnt,str1);
1889 char *p = skip_string(param,tpscnt,str2);
1890 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1893 char *pathname = NULL;
1894 char *command, *cmdname;
1895 unsigned int offset;
1898 size_t converted_size;
1900 if (!str1 || !str2 || !p) {
1904 /* check it's a supported varient */
1905 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1908 if (!check_share_info(uLevel,str2)) {
1915 /* Do we have a string ? */
1916 if (skip_string(data,mdrcnt,data) == NULL) {
1919 pull_ascii_fstring(sharename,data);
1920 snum = find_service(sharename);
1921 if (snum >= 0) { /* already exists */
1930 /* only support disk share adds */
1931 if (SVAL(data,14)!=STYPE_DISKTREE) {
1935 offset = IVAL(data, 16);
1936 if (offset >= mdrcnt) {
1937 res = ERRinvalidparam;
1941 /* Do we have a string ? */
1942 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1945 pull_ascii_fstring(comment, offset? (data+offset) : "");
1947 offset = IVAL(data, 26);
1949 if (offset >= mdrcnt) {
1950 res = ERRinvalidparam;
1954 /* Do we have a string ? */
1955 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1959 if (!pull_ascii_talloc(talloc_tos(), &pathname,
1960 offset ? (data+offset) : "", &converted_size))
1962 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1970 string_replace(sharename, '"', ' ');
1971 string_replace(pathname, '"', ' ');
1972 string_replace(comment, '"', ' ');
1974 cmdname = lp_add_share_cmd();
1976 if (!cmdname || *cmdname == '\0') {
1980 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1981 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
1982 pathname, comment) == -1) {
1986 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1988 if ((res = smbrun(command, NULL)) != 0) {
1989 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1996 message_send_all(smbd_messaging_context(),
1997 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
2001 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2005 SSVAL(*rparam,0,NERR_Success);
2006 SSVAL(*rparam,2,0); /* converter word */
2007 SSVAL(*rparam,4,*rdata_len);
2015 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2020 SSVAL(*rparam,0,res);
2025 /****************************************************************************
2026 view list of groups available
2027 ****************************************************************************/
2029 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2030 char *param, int tpscnt,
2031 char *data, int tdscnt,
2032 int mdrcnt,int mprcnt,
2033 char **rdata,char **rparam,
2034 int *rdata_len,int *rparam_len)
2038 int resume_context, cli_buf_size;
2039 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2040 char *str2 = skip_string(param,tpscnt,str1);
2041 char *p = skip_string(param,tpscnt,str2);
2043 uint32_t num_groups;
2044 uint32_t resume_handle;
2045 struct rpc_pipe_client *samr_pipe;
2046 struct policy_handle samr_handle, domain_handle;
2049 if (!str1 || !str2 || !p) {
2053 if (strcmp(str1,"WrLeh") != 0) {
2058 * W-> resume context (number of users to skip)
2059 * r -> return parameter pointer to receive buffer
2060 * L -> length of receive buffer
2061 * e -> return parameter number of entries
2062 * h -> return parameter total number of users
2065 if (strcmp("B21",str2) != 0) {
2069 status = rpc_pipe_open_internal(
2070 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2071 conn->server_info, &samr_pipe);
2072 if (!NT_STATUS_IS_OK(status)) {
2073 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2074 nt_errstr(status)));
2078 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2079 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2080 if (!NT_STATUS_IS_OK(status)) {
2081 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2082 nt_errstr(status)));
2086 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2087 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2088 get_global_sam_sid(), &domain_handle);
2089 if (!NT_STATUS_IS_OK(status)) {
2090 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2091 nt_errstr(status)));
2092 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2096 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2097 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2098 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2099 "%d\n", resume_context, cli_buf_size));
2101 *rdata_len = cli_buf_size;
2102 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2109 errflags = NERR_Success;
2114 struct samr_SamArray *sam_entries;
2115 uint32_t num_entries;
2117 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2122 if (!NT_STATUS_IS_OK(status)) {
2123 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2124 "%s\n", nt_errstr(status)));
2128 if (num_entries == 0) {
2129 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2130 "no entries -- done\n"));
2134 for(i=0; i<num_entries; i++) {
2137 name = sam_entries->entries[i].name.string;
2139 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2140 /* set overflow error */
2141 DEBUG(3,("overflow on entry %d group %s\n", i,
2147 /* truncate the name at 21 chars. */
2149 strlcpy(p, name, 21);
2150 DEBUG(10,("adding entry %d group %s\n", i, p));
2152 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2157 if (errflags != NERR_Success) {
2161 TALLOC_FREE(sam_entries);
2164 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2165 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2167 *rdata_len = PTR_DIFF(p,*rdata);
2170 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2174 SSVAL(*rparam, 0, errflags);
2175 SSVAL(*rparam, 2, 0); /* converter word */
2176 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2177 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2182 /*******************************************************************
2183 Get groups that a user is a member of.
2184 ******************************************************************/
2186 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2187 char *param, int tpscnt,
2188 char *data, int tdscnt,
2189 int mdrcnt,int mprcnt,
2190 char **rdata,char **rparam,
2191 int *rdata_len,int *rparam_len)
2193 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2194 char *str2 = skip_string(param,tpscnt,str1);
2195 char *UserName = skip_string(param,tpscnt,str2);
2196 char *p = skip_string(param,tpscnt,UserName);
2197 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2198 const char *level_string;
2204 struct rpc_pipe_client *samr_pipe;
2205 struct policy_handle samr_handle, domain_handle, user_handle;
2206 struct lsa_String name;
2207 struct lsa_Strings names;
2208 struct samr_Ids type, rid;
2209 struct samr_RidWithAttributeArray *rids;
2212 if (!str1 || !str2 || !UserName || !p) {
2217 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2222 /* check it's a supported varient */
2224 if ( strcmp(str1,"zWrLeh") != 0 )
2229 level_string = "B21";
2235 if (strcmp(level_string,str2) != 0)
2238 *rdata_len = mdrcnt + 1024;
2239 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2244 SSVAL(*rparam,0,NERR_Success);
2245 SSVAL(*rparam,2,0); /* converter word */
2248 endp = *rdata + *rdata_len;
2250 status = rpc_pipe_open_internal(
2251 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2252 conn->server_info, &samr_pipe);
2253 if (!NT_STATUS_IS_OK(status)) {
2254 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2255 nt_errstr(status)));
2259 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2260 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2261 if (!NT_STATUS_IS_OK(status)) {
2262 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2263 nt_errstr(status)));
2267 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2268 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2269 get_global_sam_sid(), &domain_handle);
2270 if (!NT_STATUS_IS_OK(status)) {
2271 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2272 nt_errstr(status)));
2276 name.string = UserName;
2278 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2279 &domain_handle, 1, &name,
2281 if (!NT_STATUS_IS_OK(status)) {
2282 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2283 nt_errstr(status)));
2287 if (type.ids[0] != SID_NAME_USER) {
2288 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2289 sid_type_lookup(type.ids[0])));
2293 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2295 SAMR_USER_ACCESS_GET_GROUPS,
2296 rid.ids[0], &user_handle);
2297 if (!NT_STATUS_IS_OK(status)) {
2298 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2299 nt_errstr(status)));
2303 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2304 &user_handle, &rids);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2307 nt_errstr(status)));
2311 for (i=0; i<rids->count; i++) {
2313 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2315 1, &rids->rids[i].rid,
2317 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2318 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2324 *rdata_len = PTR_DIFF(p,*rdata);
2326 SSVAL(*rparam,4,count); /* is this right?? */
2327 SSVAL(*rparam,6,count); /* is this right?? */
2332 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2334 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2336 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2341 /*******************************************************************
2343 ******************************************************************/
2345 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2346 char *param, int tpscnt,
2347 char *data, int tdscnt,
2348 int mdrcnt,int mprcnt,
2349 char **rdata,char **rparam,
2350 int *rdata_len,int *rparam_len)
2355 int i, resume_context, cli_buf_size;
2356 uint32_t resume_handle;
2358 struct rpc_pipe_client *samr_pipe;
2359 struct policy_handle samr_handle, domain_handle;
2362 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2363 char *str2 = skip_string(param,tpscnt,str1);
2364 char *p = skip_string(param,tpscnt,str2);
2367 if (!str1 || !str2 || !p) {
2371 if (strcmp(str1,"WrLeh") != 0)
2374 * W-> resume context (number of users to skip)
2375 * r -> return parameter pointer to receive buffer
2376 * L -> length of receive buffer
2377 * e -> return parameter number of entries
2378 * h -> return parameter total number of users
2381 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2382 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2383 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2384 resume_context, cli_buf_size));
2387 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2392 /* check it's a supported varient */
2393 if (strcmp("B21",str2) != 0)
2396 *rdata_len = cli_buf_size;
2397 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2403 endp = *rdata + *rdata_len;
2405 status = rpc_pipe_open_internal(
2406 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2407 conn->server_info, &samr_pipe);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2410 nt_errstr(status)));
2414 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2415 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2416 if (!NT_STATUS_IS_OK(status)) {
2417 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2418 nt_errstr(status)));
2422 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2423 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2424 get_global_sam_sid(), &domain_handle);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2427 nt_errstr(status)));
2428 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2432 errflags=NERR_Success;
2437 struct samr_SamArray *sam_entries;
2438 uint32_t num_entries;
2440 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2446 if (!NT_STATUS_IS_OK(status)) {
2447 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2448 "%s\n", nt_errstr(status)));
2452 if (num_entries == 0) {
2453 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2454 "no entries -- done\n"));
2458 for (i=0; i<num_entries; i++) {
2461 name = sam_entries->entries[i].name.string;
2463 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2464 &&(strlen(name)<=21)) {
2465 strlcpy(p,name,PTR_DIFF(endp,p));
2466 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2467 "username %s\n",count_sent,p));
2471 /* set overflow error */
2472 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2473 "username %s\n",count_sent,name));
2479 if (errflags != NERR_Success) {
2483 TALLOC_FREE(sam_entries);
2486 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2487 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2489 *rdata_len = PTR_DIFF(p,*rdata);
2491 SSVAL(*rparam,0,errflags);
2492 SSVAL(*rparam,2,0); /* converter word */
2493 SSVAL(*rparam,4,count_sent); /* is this right?? */
2494 SSVAL(*rparam,6,num_users); /* is this right?? */
2499 /****************************************************************************
2500 Get the time of day info.
2501 ****************************************************************************/
2503 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2504 char *param, int tpscnt,
2505 char *data, int tdscnt,
2506 int mdrcnt,int mprcnt,
2507 char **rdata,char **rparam,
2508 int *rdata_len,int *rparam_len)
2511 time_t unixdate = time(NULL);
2515 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2521 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2526 SSVAL(*rparam,0,NERR_Success);
2527 SSVAL(*rparam,2,0); /* converter word */
2531 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2532 by NT in a "net time" operation,
2533 it seems to ignore the one below */
2535 /* the client expects to get localtime, not GMT, in this bit
2536 (I think, this needs testing) */
2537 t = localtime(&unixdate);
2542 SIVAL(p,4,0); /* msecs ? */
2543 SCVAL(p,8,t->tm_hour);
2544 SCVAL(p,9,t->tm_min);
2545 SCVAL(p,10,t->tm_sec);
2546 SCVAL(p,11,0); /* hundredths of seconds */
2547 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2548 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2549 SCVAL(p,16,t->tm_mday);
2550 SCVAL(p,17,t->tm_mon + 1);
2551 SSVAL(p,18,1900+t->tm_year);
2552 SCVAL(p,20,t->tm_wday);
2557 /****************************************************************************
2558 Set the user password.
2559 *****************************************************************************/
2561 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2562 char *param, int tpscnt,
2563 char *data, int tdscnt,
2564 int mdrcnt,int mprcnt,
2565 char **rdata,char **rparam,
2566 int *rdata_len,int *rparam_len)
2568 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2571 fstring pass1,pass2;
2573 /* Skip 2 strings. */
2574 p = skip_string(param,tpscnt,np);
2575 p = skip_string(param,tpscnt,p);
2581 /* Do we have a string ? */
2582 if (skip_string(param,tpscnt,p) == NULL) {
2585 pull_ascii_fstring(user,p);
2587 p = skip_string(param,tpscnt,p);
2592 memset(pass1,'\0',sizeof(pass1));
2593 memset(pass2,'\0',sizeof(pass2));
2595 * We use 31 here not 32 as we're checking
2596 * the last byte we want to access is safe.
2598 if (!is_offset_safe(param,tpscnt,p,31)) {
2602 memcpy(pass2,p+16,16);
2605 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2612 SSVAL(*rparam,0,NERR_badpass);
2613 SSVAL(*rparam,2,0); /* converter word */
2615 DEBUG(3,("Set password for <%s>\n",user));
2618 * Attempt to verify the old password against smbpasswd entries
2619 * Win98 clients send old and new password in plaintext for this call.
2623 struct auth_serversupplied_info *server_info = NULL;
2624 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2626 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2629 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2630 SSVAL(*rparam,0,NERR_Success);
2634 TALLOC_FREE(server_info);
2636 data_blob_clear_free(&password);
2640 * If the plaintext change failed, attempt
2641 * the old encrypted method. NT will generate this
2642 * after trying the samr method. Note that this
2643 * method is done as a last resort as this
2644 * password change method loses the NT password hash
2645 * and cannot change the UNIX password as no plaintext
2649 if(SVAL(*rparam,0) != NERR_Success) {
2650 struct samu *hnd = NULL;
2652 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2654 if (change_lanman_password(hnd,(uchar *)pass2)) {
2655 SSVAL(*rparam,0,NERR_Success);
2662 memset((char *)pass1,'\0',sizeof(fstring));
2663 memset((char *)pass2,'\0',sizeof(fstring));
2668 /****************************************************************************
2669 Set the user password (SamOEM version - gets plaintext).
2670 ****************************************************************************/
2672 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2673 char *param, int tpscnt,
2674 char *data, int tdscnt,
2675 int mdrcnt,int mprcnt,
2676 char **rdata,char **rparam,
2677 int *rdata_len,int *rparam_len)
2679 struct smbd_server_connection *sconn = smbd_server_conn;
2681 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2683 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2693 SSVAL(*rparam,0,NERR_badpass);
2696 * Check the parameter definition is correct.
2699 /* Do we have a string ? */
2700 if (skip_string(param,tpscnt,p) == 0) {
2703 if(!strequal(p, "zsT")) {
2704 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2707 p = skip_string(param, tpscnt, p);
2712 /* Do we have a string ? */
2713 if (skip_string(param,tpscnt,p) == 0) {
2716 if(!strequal(p, "B516B16")) {
2717 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2720 p = skip_string(param,tpscnt,p);
2724 /* Do we have a string ? */
2725 if (skip_string(param,tpscnt,p) == 0) {
2728 p += pull_ascii_fstring(user,p);
2730 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2733 * Pass the user through the NT -> unix user mapping
2737 (void)map_username(sconn, user);
2739 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2740 SSVAL(*rparam,0,NERR_Success);
2746 /****************************************************************************
2749 ****************************************************************************/
2751 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2752 char *param, int tpscnt,
2753 char *data, int tdscnt,
2754 int mdrcnt,int mprcnt,
2755 char **rdata,char **rparam,
2756 int *rdata_len,int *rparam_len)
2758 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2759 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2760 char *str2 = skip_string(param,tpscnt,str1);
2761 char *p = skip_string(param,tpscnt,str2);
2766 WERROR werr = WERR_OK;
2768 if (!str1 || !str2 || !p) {
2772 * We use 1 here not 2 as we're checking
2773 * the last byte we want to access is safe.
2775 if (!is_offset_safe(param,tpscnt,p,1)) {
2778 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2781 /* check it's a supported varient */
2782 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2786 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2792 if (!print_job_exists(sharename, jobid)) {
2793 errcode = NERR_JobNotFound;
2797 snum = lp_servicenumber( sharename);
2799 errcode = NERR_DestNotFound;
2803 errcode = NERR_notsupported;
2806 case 81: /* delete */
2807 if (print_job_delete(conn->server_info, snum, jobid, &werr))
2808 errcode = NERR_Success;
2810 case 82: /* pause */
2811 if (print_job_pause(conn->server_info, snum, jobid, &werr))
2812 errcode = NERR_Success;
2814 case 83: /* resume */
2815 if (print_job_resume(conn->server_info, snum, jobid, &werr))
2816 errcode = NERR_Success;
2820 if (!W_ERROR_IS_OK(werr))
2821 errcode = W_ERROR_V(werr);
2824 SSVAL(*rparam,0,errcode);
2825 SSVAL(*rparam,2,0); /* converter word */
2830 /****************************************************************************
2831 Purge a print queue - or pause or resume it.
2832 ****************************************************************************/
2834 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2835 char *param, int tpscnt,
2836 char *data, int tdscnt,
2837 int mdrcnt,int mprcnt,
2838 char **rdata,char **rparam,
2839 int *rdata_len,int *rparam_len)
2841 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2842 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2843 char *str2 = skip_string(param,tpscnt,str1);
2844 char *QueueName = skip_string(param,tpscnt,str2);
2845 int errcode = NERR_notsupported;
2847 WERROR werr = WERR_OK;
2849 if (!str1 || !str2 || !QueueName) {
2853 /* check it's a supported varient */
2854 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2858 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2864 if (skip_string(param,tpscnt,QueueName) == NULL) {
2867 snum = print_queue_snum(QueueName);
2870 errcode = NERR_JobNotFound;
2875 case 74: /* Pause queue */
2876 werr = print_queue_pause(conn->server_info, snum);
2878 case 75: /* Resume queue */
2879 werr = print_queue_resume(conn->server_info, snum);
2881 case 103: /* Purge */
2882 werr = print_queue_purge(conn->server_info, snum);
2885 werr = WERR_NOT_SUPPORTED;
2889 errcode = W_ERROR_V(werr);
2892 SSVAL(*rparam,0,errcode);
2893 SSVAL(*rparam,2,0); /* converter word */
2898 /****************************************************************************
2899 set the property of a print job (undocumented?)
2900 ? function = 0xb -> set name of print job
2901 ? function = 0x6 -> move print job up/down
2902 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2903 or <WWsTP> <WB21BB16B10zWWzDDz>
2904 ****************************************************************************/
2906 static int check_printjob_info(struct pack_desc* desc,
2907 int uLevel, char* id)
2909 desc->subformat = NULL;
2911 case 0: desc->format = "W"; break;
2912 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2913 case 2: desc->format = "WWzWWDDzz"; break;
2914 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2915 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2917 DEBUG(0,("check_printjob_info: invalid level %d\n",
2921 if (id == NULL || strcmp(desc->format,id) != 0) {
2922 DEBUG(0,("check_printjob_info: invalid format %s\n",
2923 id ? id : "<NULL>" ));
2929 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2930 char *param, int tpscnt,
2931 char *data, int tdscnt,
2932 int mdrcnt,int mprcnt,
2933 char **rdata,char **rparam,
2934 int *rdata_len,int *rparam_len)
2936 struct pack_desc desc;
2937 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2938 char *str2 = skip_string(param,tpscnt,str1);
2939 char *p = skip_string(param,tpscnt,str2);
2942 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2943 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2946 if (!str1 || !str2 || !p) {
2950 * We use 1 here not 2 as we're checking
2951 * the last byte we want to access is safe.
2953 if (!is_offset_safe(param,tpscnt,p,1)) {
2956 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2959 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2964 if (!share_defined(sharename)) {
2965 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2972 /* check it's a supported varient */
2973 if ((strcmp(str1,"WWsTP")) ||
2974 (!check_printjob_info(&desc,uLevel,str2)))
2977 if (!print_job_exists(sharename, jobid)) {
2978 errcode=NERR_JobNotFound;
2982 errcode = NERR_notsupported;
2986 /* change job place in the queue,
2987 data gives the new place */
2988 place = SVAL(data,0);
2989 if (print_job_set_place(sharename, jobid, place)) {
2990 errcode=NERR_Success;
2995 /* change print job name, data gives the name */
2996 if (print_job_set_name(sharename, jobid, data)) {
2997 errcode=NERR_Success;
3006 SSVALS(*rparam,0,errcode);
3007 SSVAL(*rparam,2,0); /* converter word */
3013 /****************************************************************************
3014 Get info about the server.
3015 ****************************************************************************/
3017 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3018 char *param, int tpscnt,
3019 char *data, int tdscnt,
3020 int mdrcnt,int mprcnt,
3021 char **rdata,char **rparam,
3022 int *rdata_len,int *rparam_len)
3024 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3025 char *str2 = skip_string(param,tpscnt,str1);
3026 char *p = skip_string(param,tpscnt,str2);
3027 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3031 if (!str1 || !str2 || !p) {
3035 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3037 /* check it's a supported varient */
3038 if (!prefix_ok(str1,"WrLh")) {
3044 if (strcmp(str2,"B16") != 0) {
3050 if (strcmp(str2,"B16BBDz") != 0) {
3056 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3062 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3068 if (strcmp(str2,"DN") != 0) {
3074 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3083 *rdata_len = mdrcnt;
3084 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3090 p2 = p + struct_len;
3092 srvstr_push(NULL, 0, p,global_myname(),16,
3093 STR_ASCII|STR_UPPER|STR_TERMINATE);
3097 struct srv_info_struct *servers=NULL;
3099 char *comment = NULL;
3100 TALLOC_CTX *ctx = talloc_tos();
3101 uint32 servertype= lp_default_server_announce();
3103 comment = talloc_strdup(ctx,lp_serverstring());
3108 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3109 for (i=0;i<count;i++) {
3110 if (strequal(servers[i].name,global_myname())) {
3111 servertype = servers[i].type;
3112 TALLOC_FREE(comment);
3113 comment = talloc_strdup(ctx,
3114 servers[i].comment);
3124 SCVAL(p,0,lp_major_announce_version());
3125 SCVAL(p,1,lp_minor_announce_version());
3126 SIVAL(p,2,servertype);
3128 if (mdrcnt == struct_len) {
3131 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3132 comment = talloc_sub_advanced(
3134 lp_servicename(SNUM(conn)),
3135 conn->server_info->unix_name,
3137 conn->server_info->utok.gid,
3138 conn->server_info->sanitized_username,
3139 pdb_get_domain(conn->server_info->sam_account),
3144 if (mdrcnt - struct_len <= 0) {
3149 MIN(mdrcnt - struct_len,
3150 MAX_SERVER_STRING_LENGTH),
3152 p2 = skip_string(*rdata,*rdata_len,p2);
3160 return False; /* not yet implemented */
3163 *rdata_len = PTR_DIFF(p2,*rdata);
3166 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3170 SSVAL(*rparam,0,NERR_Success);
3171 SSVAL(*rparam,2,0); /* converter word */
3172 SSVAL(*rparam,4,*rdata_len);
3177 /****************************************************************************
3178 Get info about the server.
3179 ****************************************************************************/
3181 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3182 char *param, int tpscnt,
3183 char *data, int tdscnt,
3184 int mdrcnt,int mprcnt,
3185 char **rdata,char **rparam,
3186 int *rdata_len,int *rparam_len)
3188 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3189 char *str2 = skip_string(param,tpscnt,str1);
3190 char *p = skip_string(param,tpscnt,str2);
3193 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3195 if (!str1 || !str2 || !p) {
3199 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3202 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3207 /* check it's a supported varient */
3208 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3212 *rdata_len = mdrcnt + 1024;
3213 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3218 SSVAL(*rparam,0,NERR_Success);
3219 SSVAL(*rparam,2,0); /* converter word */
3222 endp = *rdata + *rdata_len;
3224 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3229 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3230 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3232 p2 = skip_string(*rdata,*rdata_len,p2);
3238 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3239 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3240 p2 = skip_string(*rdata,*rdata_len,p2);
3246 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3247 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3249 p2 = skip_string(*rdata,*rdata_len,p2);
3255 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3256 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3259 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3260 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3261 p2 = skip_string(*rdata,*rdata_len,p2);
3267 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3268 strlcpy(p2,"",PTR_DIFF(endp,p2));
3269 p2 = skip_string(*rdata,*rdata_len,p2);
3275 *rdata_len = PTR_DIFF(p2,*rdata);
3277 SSVAL(*rparam,4,*rdata_len);
3282 /****************************************************************************
3283 get info about a user
3285 struct user_info_11 {
3286 char usri11_name[21]; 0-20
3288 char *usri11_comment; 22-25
3289 char *usri11_usr_comment; 26-29
3290 unsigned short usri11_priv; 30-31
3291 unsigned long usri11_auth_flags; 32-35
3292 long usri11_password_age; 36-39
3293 char *usri11_homedir; 40-43
3294 char *usri11_parms; 44-47
3295 long usri11_last_logon; 48-51
3296 long usri11_last_logoff; 52-55
3297 unsigned short usri11_bad_pw_count; 56-57
3298 unsigned short usri11_num_logons; 58-59
3299 char *usri11_logon_server; 60-63
3300 unsigned short usri11_country_code; 64-65
3301 char *usri11_workstations; 66-69
3302 unsigned long usri11_max_storage; 70-73
3303 unsigned short usri11_units_per_week; 74-75
3304 unsigned char *usri11_logon_hours; 76-79
3305 unsigned short usri11_code_page; 80-81
3310 usri11_name specifies the user name for which information is retrieved
3312 usri11_pad aligns the next data structure element to a word boundary
3314 usri11_comment is a null terminated ASCII comment
3316 usri11_user_comment is a null terminated ASCII comment about the user
3318 usri11_priv specifies the level of the privilege assigned to the user.
3319 The possible values are:
3321 Name Value Description
3322 USER_PRIV_GUEST 0 Guest privilege
3323 USER_PRIV_USER 1 User privilege
3324 USER_PRV_ADMIN 2 Administrator privilege
3326 usri11_auth_flags specifies the account operator privileges. The
3327 possible values are:
3329 Name Value Description
3330 AF_OP_PRINT 0 Print operator
3333 Leach, Naik [Page 28]
3337 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3340 AF_OP_COMM 1 Communications operator
3341 AF_OP_SERVER 2 Server operator
3342 AF_OP_ACCOUNTS 3 Accounts operator
3345 usri11_password_age specifies how many seconds have elapsed since the
3346 password was last changed.
3348 usri11_home_dir points to a null terminated ASCII string that contains
3349 the path name of the user's home directory.
3351 usri11_parms points to a null terminated ASCII string that is set
3352 aside for use by applications.
3354 usri11_last_logon specifies the time when the user last logged on.
3355 This value is stored as the number of seconds elapsed since
3356 00:00:00, January 1, 1970.
3358 usri11_last_logoff specifies the time when the user last logged off.
3359 This value is stored as the number of seconds elapsed since
3360 00:00:00, January 1, 1970. A value of 0 means the last logoff
3363 usri11_bad_pw_count specifies the number of incorrect passwords
3364 entered since the last successful logon.
3366 usri11_log1_num_logons specifies the number of times this user has
3367 logged on. A value of -1 means the number of logons is unknown.
3369 usri11_logon_server points to a null terminated ASCII string that
3370 contains the name of the server to which logon requests are sent.
3371 A null string indicates logon requests should be sent to the
3374 usri11_country_code specifies the country code for the user's language
3377 usri11_workstations points to a null terminated ASCII string that
3378 contains the names of workstations the user may log on from.
3379 There may be up to 8 workstations, with the names separated by
3380 commas. A null strings indicates there are no restrictions.
3382 usri11_max_storage specifies the maximum amount of disk space the user
3383 can occupy. A value of 0xffffffff indicates there are no
3386 usri11_units_per_week specifies the equal number of time units into
3387 which a week is divided. This value must be equal to 168.
3389 usri11_logon_hours points to a 21 byte (168 bits) string that
3390 specifies the time during which the user can log on. Each bit
3391 represents one unique hour in a week. The first bit (bit 0, word
3392 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3396 Leach, Naik [Page 29]
3400 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3403 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3404 are no restrictions.
3406 usri11_code_page specifies the code page for the user's language of
3409 All of the pointers in this data structure need to be treated
3410 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3411 to be ignored. The converter word returned in the parameters section
3412 needs to be subtracted from the lower 16 bits to calculate an offset
3413 into the return buffer where this ASCII string resides.
3415 There is no auxiliary data in the response.
3417 ****************************************************************************/
3419 #define usri11_name 0
3420 #define usri11_pad 21
3421 #define usri11_comment 22
3422 #define usri11_usr_comment 26
3423 #define usri11_full_name 30
3424 #define usri11_priv 34
3425 #define usri11_auth_flags 36
3426 #define usri11_password_age 40
3427 #define usri11_homedir 44
3428 #define usri11_parms 48
3429 #define usri11_last_logon 52
3430 #define usri11_last_logoff 56
3431 #define usri11_bad_pw_count 60
3432 #define usri11_num_logons 62
3433 #define usri11_logon_server 64
3434 #define usri11_country_code 68
3435 #define usri11_workstations 70
3436 #define usri11_max_storage 74
3437 #define usri11_units_per_week 78
3438 #define usri11_logon_hours 80
3439 #define usri11_code_page 84
3440 #define usri11_end 86
3442 #define USER_PRIV_GUEST 0
3443 #define USER_PRIV_USER 1
3444 #define USER_PRIV_ADMIN 2
3446 #define AF_OP_PRINT 0
3447 #define AF_OP_COMM 1
3448 #define AF_OP_SERVER 2
3449 #define AF_OP_ACCOUNTS 3
3452 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3453 char *param, int tpscnt,
3454 char *data, int tdscnt,
3455 int mdrcnt,int mprcnt,
3456 char **rdata,char **rparam,
3457 int *rdata_len,int *rparam_len)
3459 struct smbd_server_connection *sconn = smbd_server_conn;
3460 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3461 char *str2 = skip_string(param,tpscnt,str1);
3462 char *UserName = skip_string(param,tpscnt,str2);
3463 char *p = skip_string(param,tpscnt,UserName);
3464 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3467 const char *level_string;
3469 /* get NIS home of a previously validated user - simeon */
3470 /* With share level security vuid will always be zero.
3471 Don't depend on vuser being non-null !!. JRA */
3472 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3474 DEBUG(3,(" Username of UID %d is %s\n",
3475 (int)vuser->server_info->utok.uid,
3476 vuser->server_info->unix_name));
3479 if (!str1 || !str2 || !UserName || !p) {
3484 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3489 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3491 /* check it's a supported variant */
3492 if (strcmp(str1,"zWrLh") != 0) {
3496 case 0: level_string = "B21"; break;
3497 case 1: level_string = "B21BB16DWzzWz"; break;
3498 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3499 case 10: level_string = "B21Bzzz"; break;
3500 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3501 default: return False;
3504 if (strcmp(level_string,str2) != 0) {
3508 *rdata_len = mdrcnt + 1024;
3509 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3514 SSVAL(*rparam,0,NERR_Success);
3515 SSVAL(*rparam,2,0); /* converter word */
3518 endp = *rdata + *rdata_len;
3519 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3525 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3528 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3533 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3534 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3535 p2 = skip_string(*rdata,*rdata_len,p2);
3540 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3541 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3542 p2 = skip_string(*rdata,*rdata_len,p2);
3547 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3548 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3549 strlcpy(p2,((vuser != NULL)
3550 ? pdb_get_fullname(vuser->server_info->sam_account)
3551 : UserName),PTR_DIFF(endp,p2));
3552 p2 = skip_string(*rdata,*rdata_len,p2);
3559 const char *homedir = "";
3560 if (vuser != NULL) {
3561 homedir = pdb_get_homedir(
3562 vuser->server_info->sam_account);
3564 /* modelled after NTAS 3.51 reply */
3565 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3566 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3567 SIVALS(p,usri11_password_age,-1); /* password age */
3568 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3569 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3570 p2 = skip_string(*rdata,*rdata_len,p2);
3574 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3575 strlcpy(p2,"",PTR_DIFF(endp,p2));
3576 p2 = skip_string(*rdata,*rdata_len,p2);
3580 SIVAL(p,usri11_last_logon,0); /* last logon */
3581 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3582 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3583 SSVALS(p,usri11_num_logons,-1); /* num logons */
3584 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3585 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3586 p2 = skip_string(*rdata,*rdata_len,p2);
3590 SSVAL(p,usri11_country_code,0); /* country code */
3592 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3593 strlcpy(p2,"",PTR_DIFF(endp,p2));
3594 p2 = skip_string(*rdata,*rdata_len,p2);
3599 SIVALS(p,usri11_max_storage,-1); /* max storage */
3600 SSVAL(p,usri11_units_per_week,168); /* units per week */
3601 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3603 /* a simple way to get logon hours at all times. */
3605 SCVAL(p2,21,0); /* fix zero termination */
3606 p2 = skip_string(*rdata,*rdata_len,p2);
3611 SSVAL(p,usri11_code_page,0); /* code page */
3614 if (uLevel == 1 || uLevel == 2) {
3615 memset(p+22,' ',16); /* password */
3616 SIVALS(p,38,-1); /* password age */
3618 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3619 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3620 strlcpy(p2, vuser ? pdb_get_homedir(
3621 vuser->server_info->sam_account) : "",
3623 p2 = skip_string(*rdata,*rdata_len,p2);
3627 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3629 SSVAL(p,52,0); /* flags */
3630 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3631 strlcpy(p2, vuser ? pdb_get_logon_script(
3632 vuser->server_info->sam_account) : "",
3634 p2 = skip_string(*rdata,*rdata_len,p2);
3639 SIVAL(p,60,0); /* auth_flags */
3640 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3641 strlcpy(p2,((vuser != NULL)
3642 ? pdb_get_fullname(vuser->server_info->sam_account)
3643 : UserName),PTR_DIFF(endp,p2));
3644 p2 = skip_string(*rdata,*rdata_len,p2);
3648 SIVAL(p,68,0); /* urs_comment */
3649 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3650 strlcpy(p2,"",PTR_DIFF(endp,p2));
3651 p2 = skip_string(*rdata,*rdata_len,p2);
3655 SIVAL(p,76,0); /* workstations */
3656 SIVAL(p,80,0); /* last_logon */
3657 SIVAL(p,84,0); /* last_logoff */
3658 SIVALS(p,88,-1); /* acct_expires */
3659 SIVALS(p,92,-1); /* max_storage */
3660 SSVAL(p,96,168); /* units_per_week */
3661 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3664 SSVALS(p,102,-1); /* bad_pw_count */
3665 SSVALS(p,104,-1); /* num_logons */
3666 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3668 TALLOC_CTX *ctx = talloc_tos();
3669 int space_rem = *rdata_len - (p2 - *rdata);
3672 if (space_rem <= 0) {
3675 tmp = talloc_strdup(ctx, "\\\\%L");
3679 tmp = talloc_sub_basic(ctx,
3692 p2 = skip_string(*rdata,*rdata_len,p2);
3696 SSVAL(p,110,49); /* country_code */
3697 SSVAL(p,112,860); /* code page */
3701 *rdata_len = PTR_DIFF(p2,*rdata);
3703 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3708 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3709 char *param, int tpscnt,
3710 char *data, int tdscnt,
3711 int mdrcnt,int mprcnt,
3712 char **rdata,char **rparam,
3713 int *rdata_len,int *rparam_len)
3715 struct smbd_server_connection *sconn = smbd_server_conn;
3716 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3717 char *str2 = skip_string(param,tpscnt,str1);
3718 char *p = skip_string(param,tpscnt,str2);
3720 struct pack_desc desc;
3722 /* With share level security vuid will always be zero.
3723 Don't depend on vuser being non-null !!. JRA */
3724 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3726 if (!str1 || !str2 || !p) {
3731 DEBUG(3,(" Username of UID %d is %s\n",
3732 (int)vuser->server_info->utok.uid,
3733 vuser->server_info->unix_name));
3736 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3737 name = get_safe_str_ptr(param,tpscnt,p,2);
3742 memset((char *)&desc,'\0',sizeof(desc));
3744 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3746 /* check it's a supported varient */
3747 if (strcmp(str1,"OOWb54WrLh") != 0) {
3750 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3754 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3761 desc.buflen = mdrcnt;
3762 desc.subformat = NULL;
3765 if (init_package(&desc,1,0)) {
3766 PACKI(&desc,"W",0); /* code */
3767 PACKS(&desc,"B21",name); /* eff. name */
3768 PACKS(&desc,"B",""); /* pad */
3769 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3770 PACKI(&desc,"D",0); /* auth flags XXX */
3771 PACKI(&desc,"W",0); /* num logons */
3772 PACKI(&desc,"W",0); /* bad pw count */
3773 PACKI(&desc,"D",0); /* last logon */
3774 PACKI(&desc,"D",-1); /* last logoff */
3775 PACKI(&desc,"D",-1); /* logoff time */
3776 PACKI(&desc,"D",-1); /* kickoff time */
3777 PACKI(&desc,"D",0); /* password age */
3778 PACKI(&desc,"D",0); /* password can change */
3779 PACKI(&desc,"D",-1); /* password must change */
3783 fstrcpy(mypath,"\\\\");
3784 fstrcat(mypath,get_local_machine_name());
3786 PACKS(&desc,"z",mypath); /* computer */
3789 PACKS(&desc,"z",lp_workgroup());/* domain */
3790 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
3791 vuser->server_info->sam_account) : ""); /* script path */
3792 PACKI(&desc,"D",0x00000000); /* reserved */
3795 *rdata_len = desc.usedlen;
3797 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3801 SSVALS(*rparam,0,desc.errcode);
3803 SSVAL(*rparam,4,desc.neededlen);
3805 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3810 /****************************************************************************
3811 api_WAccessGetUserPerms
3812 ****************************************************************************/
3814 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3815 char *param, int tpscnt,
3816 char *data, int tdscnt,
3817 int mdrcnt,int mprcnt,
3818 char **rdata,char **rparam,
3819 int *rdata_len,int *rparam_len)
3821 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3822 char *str2 = skip_string(param,tpscnt,str1);
3823 char *user = skip_string(param,tpscnt,str2);
3824 char *resource = skip_string(param,tpscnt,user);
3826 if (!str1 || !str2 || !user || !resource) {
3830 if (skip_string(param,tpscnt,resource) == NULL) {
3833 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3835 /* check it's a supported varient */
3836 if (strcmp(str1,"zzh") != 0) {
3839 if (strcmp(str2,"") != 0) {
3844 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3848 SSVALS(*rparam,0,0); /* errorcode */
3849 SSVAL(*rparam,2,0); /* converter word */
3850 SSVAL(*rparam,4,0x7f); /* permission flags */
3855 /****************************************************************************
3856 api_WPrintJobEnumerate
3857 ****************************************************************************/
3859 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3860 char *param, int tpscnt,
3861 char *data, int tdscnt,
3862 int mdrcnt,int mprcnt,
3863 char **rdata,char **rparam,
3864 int *rdata_len,int *rparam_len)
3866 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3867 char *str2 = skip_string(param,tpscnt,str1);
3868 char *p = skip_string(param,tpscnt,str2);
3875 struct pack_desc desc;
3876 print_queue_struct *queue=NULL;
3877 print_status_struct status;
3880 if (!str1 || !str2 || !p) {
3884 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3886 memset((char *)&desc,'\0',sizeof(desc));
3887 memset((char *)&status,'\0',sizeof(status));
3889 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3891 /* check it's a supported varient */
3892 if (strcmp(str1,"WWrLh") != 0) {
3895 if (!check_printjob_info(&desc,uLevel,str2)) {
3899 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3903 snum = lp_servicenumber( sharename);
3904 if (snum < 0 || !VALID_SNUM(snum)) {
3908 count = print_queue_status(snum,&queue,&status);
3909 for (i = 0; i < count; i++) {
3910 if (queue[i].job == jobid) {
3916 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3921 desc.buflen = mdrcnt;
3924 * Don't return data but need to get correct length
3925 * init_package will return wrong size if buflen=0
3927 desc.buflen = getlen(desc.format);
3928 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3931 if (init_package(&desc,1,0)) {
3933 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3934 *rdata_len = desc.usedlen;
3936 desc.errcode = NERR_JobNotFound;
3942 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3946 SSVALS(*rparam,0,desc.errcode);
3948 SSVAL(*rparam,4,desc.neededlen);
3953 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3958 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3959 char *param, int tpscnt,
3960 char *data, int tdscnt,
3961 int mdrcnt,int mprcnt,
3962 char **rdata,char **rparam,
3963 int *rdata_len,int *rparam_len)
3965 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3966 char *str2 = skip_string(param,tpscnt,str1);
3967 char *p = skip_string(param,tpscnt,str2);
3973 struct pack_desc desc;
3974 print_queue_struct *queue=NULL;
3975 print_status_struct status;
3977 if (!str1 || !str2 || !p) {
3981 memset((char *)&desc,'\0',sizeof(desc));
3982 memset((char *)&status,'\0',sizeof(status));
3984 p = skip_string(param,tpscnt,p);
3988 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3990 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3992 /* check it's a supported variant */
3993 if (strcmp(str1,"zWrLeh") != 0) {
3998 return False; /* defined only for uLevel 0,1,2 */
4001 if (!check_printjob_info(&desc,uLevel,str2)) {
4005 snum = find_service(name);
4006 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4010 count = print_queue_status(snum,&queue,&status);
4012 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4018 desc.buflen = mdrcnt;
4020 if (init_package(&desc,count,0)) {
4022 for (i = 0; i < count; i++) {
4023 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4024 if (desc.errcode == NERR_Success) {
4030 *rdata_len = desc.usedlen;
4033 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4037 SSVALS(*rparam,0,desc.errcode);
4039 SSVAL(*rparam,4,succnt);
4040 SSVAL(*rparam,6,count);
4044 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4049 static int check_printdest_info(struct pack_desc* desc,
4050 int uLevel, char* id)
4052 desc->subformat = NULL;
4055 desc->format = "B9";
4058 desc->format = "B9B21WWzW";
4064 desc->format = "zzzWWzzzWW";
4067 DEBUG(0,("check_printdest_info: invalid level %d\n",
4071 if (id == NULL || strcmp(desc->format,id) != 0) {
4072 DEBUG(0,("check_printdest_info: invalid string %s\n",
4073 id ? id : "<NULL>" ));
4079 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
4080 struct pack_desc* desc)
4084 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
4085 buf[sizeof(buf)-1] = 0;
4089 PACKS(desc,"B9",buf); /* szName */
4091 PACKS(desc,"B21",""); /* szUserName */
4092 PACKI(desc,"W",0); /* uJobId */
4093 PACKI(desc,"W",0); /* fsStatus */
4094 PACKS(desc,"z",""); /* pszStatus */
4095 PACKI(desc,"W",0); /* time */
4099 if (uLevel == 2 || uLevel == 3) {
4100 PACKS(desc,"z",buf); /* pszPrinterName */
4102 PACKS(desc,"z",""); /* pszUserName */
4103 PACKS(desc,"z",""); /* pszLogAddr */
4104 PACKI(desc,"W",0); /* uJobId */
4105 PACKI(desc,"W",0); /* fsStatus */
4106 PACKS(desc,"z",""); /* pszStatus */
4107 PACKS(desc,"z",""); /* pszComment */
4108 PACKS(desc,"z","NULL"); /* pszDrivers */
4109 PACKI(desc,"W",0); /* time */
4110 PACKI(desc,"W",0); /* pad1 */
4115 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4116 char *param, int tpscnt,
4117 char *data, int tdscnt,
4118 int mdrcnt,int mprcnt,
4119 char **rdata,char **rparam,
4120 int *rdata_len,int *rparam_len)
4122 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4123 char *str2 = skip_string(param,tpscnt,str1);
4124 char *p = skip_string(param,tpscnt,str2);
4125 char* PrinterName = p;
4127 struct pack_desc desc;
4131 if (!str1 || !str2 || !p) {
4135 memset((char *)&desc,'\0',sizeof(desc));
4137 p = skip_string(param,tpscnt,p);
4141 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4143 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4145 /* check it's a supported varient */
4146 if (strcmp(str1,"zWrLh") != 0) {
4149 if (!check_printdest_info(&desc,uLevel,str2)) {
4153 snum = find_service(PrinterName);
4154 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4156 desc.errcode = NERR_DestNotFound;
4160 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4165 desc.buflen = mdrcnt;
4168 * Don't return data but need to get correct length
4169 * init_package will return wrong size if buflen=0
4171 desc.buflen = getlen(desc.format);
4172 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4174 if (init_package(&desc,1,0)) {
4175 fill_printdest_info(conn,snum,uLevel,&desc);
4177 *rdata_len = desc.usedlen;
4181 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4185 SSVALS(*rparam,0,desc.errcode);
4187 SSVAL(*rparam,4,desc.neededlen);
4189 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4195 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4196 char *param, int tpscnt,
4197 char *data, int tdscnt,
4198 int mdrcnt,int mprcnt,
4199 char **rdata,char **rparam,
4200 int *rdata_len,int *rparam_len)
4202 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4203 char *str2 = skip_string(param,tpscnt,str1);
4204 char *p = skip_string(param,tpscnt,str2);
4208 struct pack_desc desc;
4209 int services = lp_numservices();
4211 if (!str1 || !str2 || !p) {
4215 memset((char *)&desc,'\0',sizeof(desc));
4217 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4219 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4221 /* check it's a supported varient */
4222 if (strcmp(str1,"WrLeh") != 0) {
4225 if (!check_printdest_info(&desc,uLevel,str2)) {
4230 for (i = 0; i < services; i++) {
4231 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4237 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4244 desc.buflen = mdrcnt;
4245 if (init_package(&desc,queuecnt,0)) {
4248 for (i = 0; i < services; i++) {
4249 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4250 fill_printdest_info(conn,i,uLevel,&desc);
4252 if (desc.errcode == NERR_Success) {
4259 *rdata_len = desc.usedlen;
4262 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4266 SSVALS(*rparam,0,desc.errcode);
4268 SSVAL(*rparam,4,succnt);
4269 SSVAL(*rparam,6,queuecnt);
4271 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4276 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4277 char *param, int tpscnt,
4278 char *data, int tdscnt,
4279 int mdrcnt,int mprcnt,
4280 char **rdata,char **rparam,
4281 int *rdata_len,int *rparam_len)
4283 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4284 char *str2 = skip_string(param,tpscnt,str1);
4285 char *p = skip_string(param,tpscnt,str2);
4288 struct pack_desc desc;
4290 if (!str1 || !str2 || !p) {
4294 memset((char *)&desc,'\0',sizeof(desc));
4296 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4298 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4300 /* check it's a supported varient */
4301 if (strcmp(str1,"WrLeh") != 0) {
4304 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4309 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4315 desc.buflen = mdrcnt;
4316 if (init_package(&desc,1,0)) {
4317 PACKS(&desc,"B41","NULL");
4320 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4322 *rdata_len = desc.usedlen;
4325 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4329 SSVALS(*rparam,0,desc.errcode);
4331 SSVAL(*rparam,4,succnt);
4334 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4339 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4340 char *param, int tpscnt,
4341 char *data, int tdscnt,
4342 int mdrcnt,int mprcnt,
4343 char **rdata,char **rparam,
4344 int *rdata_len,int *rparam_len)
4346 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4347 char *str2 = skip_string(param,tpscnt,str1);
4348 char *p = skip_string(param,tpscnt,str2);
4351 struct pack_desc desc;
4353 if (!str1 || !str2 || !p) {
4356 memset((char *)&desc,'\0',sizeof(desc));
4358 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4360 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4362 /* check it's a supported varient */
4363 if (strcmp(str1,"WrLeh") != 0) {
4366 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4371 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4377 desc.buflen = mdrcnt;
4379 if (init_package(&desc,1,0)) {
4380 PACKS(&desc,"B13","lpd");
4383 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4385 *rdata_len = desc.usedlen;
4388 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4392 SSVALS(*rparam,0,desc.errcode);
4394 SSVAL(*rparam,4,succnt);
4397 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4402 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4403 char *param, int tpscnt,
4404 char *data, int tdscnt,
4405 int mdrcnt,int mprcnt,
4406 char **rdata,char **rparam,
4407 int *rdata_len,int *rparam_len)
4409 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4410 char *str2 = skip_string(param,tpscnt,str1);
4411 char *p = skip_string(param,tpscnt,str2);
4414 struct pack_desc desc;
4416 if (!str1 || !str2 || !p) {
4420 memset((char *)&desc,'\0',sizeof(desc));
4422 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4424 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4426 /* check it's a supported varient */
4427 if (strcmp(str1,"WrLeh") != 0) {
4430 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4435 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4440 memset((char *)&desc,'\0',sizeof(desc));
4442 desc.buflen = mdrcnt;
4444 if (init_package(&desc,1,0)) {
4445 PACKS(&desc,"B13","lp0");
4448 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4450 *rdata_len = desc.usedlen;
4453 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4457 SSVALS(*rparam,0,desc.errcode);
4459 SSVAL(*rparam,4,succnt);
4462 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4467 /****************************************************************************
4469 ****************************************************************************/
4471 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4472 char *param, int tpscnt,
4473 char *data, int tdscnt,
4474 int mdrcnt,int mprcnt,
4475 char **rdata,char **rparam,
4476 int *rdata_len,int *rparam_len)
4479 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4480 char *str2 = skip_string(param,tpscnt,str1);
4481 char *p = skip_string(param,tpscnt,str2);
4483 struct pack_desc desc;
4484 struct sessionid *session_list;
4485 int i, num_sessions;
4487 if (!str1 || !str2 || !p) {
4491 memset((char *)&desc,'\0',sizeof(desc));
4493 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4495 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4496 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4497 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4499 /* check it's a supported varient */
4500 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4503 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4507 num_sessions = list_sessions(talloc_tos(), &session_list);
4510 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4515 memset((char *)&desc,'\0',sizeof(desc));
4517 desc.buflen = mdrcnt;
4519 if (!init_package(&desc,num_sessions,0)) {
4523 for(i=0; i<num_sessions; i++) {
4524 PACKS(&desc, "z", session_list[i].remote_machine);
4525 PACKS(&desc, "z", session_list[i].username);
4526 PACKI(&desc, "W", 1); /* num conns */
4527 PACKI(&desc, "W", 0); /* num opens */
4528 PACKI(&desc, "W", 1); /* num users */
4529 PACKI(&desc, "D", 0); /* session time */
4530 PACKI(&desc, "D", 0); /* idle time */
4531 PACKI(&desc, "D", 0); /* flags */
4532 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4535 *rdata_len = desc.usedlen;
4538 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4542 SSVALS(*rparam,0,desc.errcode);
4543 SSVAL(*rparam,2,0); /* converter */
4544 SSVAL(*rparam,4,num_sessions); /* count */
4546 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4552 /****************************************************************************
4553 The buffer was too small.
4554 ****************************************************************************/
4556 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4557 int mdrcnt, int mprcnt,
4558 char **rdata, char **rparam,
4559 int *rdata_len, int *rparam_len)
4561 *rparam_len = MIN(*rparam_len,mprcnt);
4562 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4569 SSVAL(*rparam,0,NERR_BufTooSmall);
4571 DEBUG(3,("Supplied buffer too small in API command\n"));
4576 /****************************************************************************
4577 The request is not supported.
4578 ****************************************************************************/
4580 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4581 char *param, int tpscnt,
4582 char *data, int tdscnt,
4583 int mdrcnt, int mprcnt,
4584 char **rdata, char **rparam,
4585 int *rdata_len, int *rparam_len)
4588 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4595 SSVAL(*rparam,0,NERR_notsupported);
4596 SSVAL(*rparam,2,0); /* converter word */
4598 DEBUG(3,("Unsupported API command\n"));
4603 static const struct {
4606 bool (*fn)(connection_struct *, uint16,
4609 int,int,char **,char **,int *,int *);
4610 bool auth_user; /* Deny anonymous access? */
4611 } api_commands[] = {
4612 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4613 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4614 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4615 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4616 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4617 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4618 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4619 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4620 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4621 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4622 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4623 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4624 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4625 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4626 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4627 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4628 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4629 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4630 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4631 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4632 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4633 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4634 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4635 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4636 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
4637 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4638 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4639 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4640 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4641 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4642 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4643 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4644 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4645 {NULL, -1, api_Unsupported}
4646 /* The following RAP calls are not implemented by Samba:
4648 RAP_WFileEnum2 - anon not OK
4653 /****************************************************************************
4654 Handle remote api calls.
4655 ****************************************************************************/
4657 void api_reply(connection_struct *conn, uint16 vuid,
4658 struct smb_request *req,
4659 char *data, char *params,
4660 int tdscnt, int tpscnt,
4661 int mdrcnt, int mprcnt)
4663 struct smbd_server_connection *sconn = smbd_server_conn;
4666 char *rparam = NULL;
4667 const char *name1 = NULL;
4668 const char *name2 = NULL;
4675 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4684 api_command = SVAL(params,0);
4685 /* Is there a string at position params+2 ? */
4686 if (skip_string(params,tpscnt,params+2)) {
4691 name2 = skip_string(params,tpscnt,params+2);
4696 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4700 tdscnt,tpscnt,mdrcnt,mprcnt));
4702 for (i=0;api_commands[i].name;i++) {
4703 if (api_commands[i].id == api_command && api_commands[i].fn) {
4704 DEBUG(3,("Doing %s\n",api_commands[i].name));
4709 /* Check whether this api call can be done anonymously */
4711 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4712 user_struct *user = get_valid_user_struct(sconn, vuid);
4714 if (!user || user->server_info->guest) {
4715 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4720 rdata = (char *)SMB_MALLOC(1024);
4722 memset(rdata,'\0',1024);
4725 rparam = (char *)SMB_MALLOC(1024);
4727 memset(rparam,'\0',1024);
4730 if(!rdata || !rparam) {
4731 DEBUG(0,("api_reply: malloc fail !\n"));
4734 reply_nterror(req, NT_STATUS_NO_MEMORY);
4738 reply = api_commands[i].fn(conn,
4740 params,tpscnt, /* params + length */
4741 data,tdscnt, /* data + length */
4743 &rdata,&rparam,&rdata_len,&rparam_len);
4746 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4747 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4748 &rdata,&rparam,&rdata_len,&rparam_len);
4751 /* if we get False back then it's actually unsupported */
4753 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4754 &rdata,&rparam,&rdata_len,&rparam_len);
4757 /* If api_Unsupported returns false we can't return anything. */
4759 send_trans_reply(conn, req, rparam, rparam_len,
4760 rdata, rdata_len, False);