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
30 extern struct current_user current_user;
31 extern userdom_struct current_user_info;
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 *n)
86 if (!src || !dst || !n || !(*dst)) {
90 StrnCpy(buf,src,sizeof(buf)/2);
91 pstring_sub(buf,"%S",lp_servicename(snum));
92 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
93 conn->connectpath, conn->gid,
94 get_current_username(),
95 current_user_info.domain,
97 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
103 static int CopyAndAdvance(char **dst, char *src, int *n)
106 if (!src || !dst || !n || !(*dst)) {
109 l = push_ascii(*dst,src,*n, STR_TERMINATE);
115 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
121 StrnCpy(buf,s,sizeof(buf)/2);
122 pstring_sub(buf,"%S",lp_servicename(snum));
123 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
124 conn->connectpath, conn->gid,
125 get_current_username(),
126 current_user_info.domain,
128 return strlen(buf) + 1;
131 static char *Expand(connection_struct *conn, int snum, char *s)
137 StrnCpy(buf,s,sizeof(buf)/2);
138 pstring_sub(buf,"%S",lp_servicename(snum));
139 return talloc_sub_advanced(talloc_tos(), lp_servicename(SNUM(conn)),
140 conn->user, conn->connectpath, conn->gid,
141 get_current_username(),
142 current_user_info.domain, buf);
145 /*******************************************************************
146 Check a API string for validity when we only need to check the prefix.
147 ******************************************************************/
149 static BOOL prefix_ok(const char *str, const char *prefix)
151 return(strncmp(str,prefix,strlen(prefix)) == 0);
155 const char *format; /* formatstring for structure */
156 const char *subformat; /* subformat for structure */
157 char *base; /* baseaddress of buffer */
158 int buflen; /* remaining size for fixed part; on init: length of base */
159 int subcount; /* count of substructures */
160 char *structbuf; /* pointer into buffer for remaining fixed part */
161 int stringlen; /* remaining size for variable part */
162 char *stringbuf; /* pointer into buffer for remaining variable part */
163 int neededlen; /* total needed size */
164 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
165 const char *curpos; /* current position; pointer into format or subformat */
169 static int get_counter(const char **p)
175 if (!isdigit((int)**p)) {
181 n = 10 * n + (i - '0');
189 static int getlen(const char *p)
198 case 'W': /* word (2 byte) */
201 case 'K': /* status word? (2 byte) */
204 case 'N': /* count of substructures (word) at end */
207 case 'D': /* double word (4 byte) */
208 case 'z': /* offset to zero terminated string (4 byte) */
209 case 'l': /* offset to user data (4 byte) */
212 case 'b': /* offset to data (with counter) (4 byte) */
216 case 'B': /* byte (with optional counter) */
217 n += get_counter(&p);
224 static BOOL init_package(struct pack_desc *p, int count, int subcount)
229 if (!p->format || !p->base) {
233 i = count * getlen(p->format);
235 i += subcount * getlen(p->subformat);
237 p->structbuf = p->base;
241 p->curpos = p->format;
247 * This is the old error code we used. Aparently
248 * WinNT/2k systems return ERRbuftoosmall (2123) and
249 * OS/2 needs this. I'm leaving this here so we can revert
252 p->errcode = ERRmoredata;
254 p->errcode = ERRbuftoosmall;
257 p->errcode = NERR_Success;
261 p->stringbuf = p->base + i;
263 return (p->errcode == NERR_Success);
266 static int package(struct pack_desc *p, ...)
269 int needed=0, stringneeded;
270 const char *str=NULL;
271 int is_string=0, stringused;
278 p->curpos = p->format;
280 p->curpos = p->subformat;
285 str = va_arg(args,char*);
286 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
295 switch( *p->curpos++ ) {
296 case 'W': /* word (2 byte) */
298 temp = va_arg(args,int);
299 if (p->buflen >= needed) {
300 SSVAL(p->structbuf,0,temp);
303 case 'K': /* status word? (2 byte) */
305 temp = va_arg(args,int);
306 if (p->buflen >= needed) {
307 SSVAL(p->structbuf,0,temp);
310 case 'N': /* count of substructures (word) at end */
312 p->subcount = va_arg(args,int);
313 if (p->buflen >= needed) {
314 SSVAL(p->structbuf,0,p->subcount);
317 case 'D': /* double word (4 byte) */
319 temp = va_arg(args,int);
320 if (p->buflen >= needed) {
321 SIVAL(p->structbuf,0,temp);
324 case 'B': /* byte (with optional counter) */
325 needed = get_counter(&p->curpos);
327 char *s = va_arg(args,char*);
328 if (p->buflen >= needed) {
329 StrnCpy(p->structbuf,s?s:"",needed-1);
333 case 'z': /* offset to zero terminated string (4 byte) */
334 str = va_arg(args,char*);
335 stringneeded = (str ? strlen(str)+1 : 0);
338 case 'l': /* offset to user data (4 byte) */
339 str = va_arg(args,char*);
340 stringneeded = va_arg(args,int);
343 case 'b': /* offset to data (with counter) (4 byte) */
344 str = va_arg(args,char*);
345 stringneeded = get_counter(&p->curpos);
351 if (stringneeded >= 0) {
353 if (p->buflen >= needed) {
354 stringused = stringneeded;
355 if (stringused > p->stringlen) {
356 stringused = (is_string ? p->stringlen : 0);
357 if (p->errcode == NERR_Success) {
358 p->errcode = ERRmoredata;
362 SIVAL(p->structbuf,0,0);
364 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
365 memcpy(p->stringbuf,str?str:"",stringused);
367 p->stringbuf[stringused-1] = '\0';
369 p->stringbuf += stringused;
370 p->stringlen -= stringused;
371 p->usedlen += stringused;
374 p->neededlen += stringneeded;
377 p->neededlen += needed;
378 if (p->buflen >= needed) {
379 p->structbuf += needed;
381 p->usedlen += needed;
383 if (p->errcode == NERR_Success) {
384 p->errcode = ERRmoredata;
391 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
392 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
394 #define PACK(desc,t,v) package(desc,v)
395 #define PACKl(desc,t,v,l) package(desc,v,l)
398 static void PACKI(struct pack_desc* desc, const char *t,int v)
403 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
408 /****************************************************************************
410 ****************************************************************************/
412 static void PackDriverData(struct pack_desc* desc)
414 char drivdata[4+4+32];
415 SIVAL(drivdata,0,sizeof drivdata); /* cb */
416 SIVAL(drivdata,4,1000); /* lVersion */
417 memset(drivdata+8,0,32); /* szDeviceName */
418 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
419 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
422 static int check_printq_info(struct pack_desc* desc,
423 unsigned int uLevel, char *id1, char *id2)
425 desc->subformat = NULL;
428 desc->format = "B13";
431 desc->format = "B13BWWWzzzzzWW";
434 desc->format = "B13BWWWzzzzzWN";
435 desc->subformat = "WB21BB16B10zWWzDDz";
438 desc->format = "zWWWWzzzzWWzzl";
441 desc->format = "zWWWWzzzzWNzzl";
442 desc->subformat = "WWzWWDDzz";
451 desc->format = "WzzzzzzzzN";
452 desc->subformat = "z";
455 DEBUG(0,("check_printq_info: invalid level %d\n",
459 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
460 DEBUG(0,("check_printq_info: invalid format %s\n",
461 id1 ? id1 : "<NULL>" ));
464 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
465 DEBUG(0,("check_printq_info: invalid subformat %s\n",
466 id2 ? id2 : "<NULL>" ));
473 #define RAP_JOB_STATUS_QUEUED 0
474 #define RAP_JOB_STATUS_PAUSED 1
475 #define RAP_JOB_STATUS_SPOOLING 2
476 #define RAP_JOB_STATUS_PRINTING 3
477 #define RAP_JOB_STATUS_PRINTED 4
479 #define RAP_QUEUE_STATUS_PAUSED 1
480 #define RAP_QUEUE_STATUS_ERROR 2
482 /* turn a print job status into a on the wire status
484 static int printj_status(int v)
488 return RAP_JOB_STATUS_QUEUED;
490 return RAP_JOB_STATUS_PAUSED;
492 return RAP_JOB_STATUS_SPOOLING;
494 return RAP_JOB_STATUS_PRINTING;
499 /* turn a print queue status into a on the wire status
501 static int printq_status(int v)
507 return RAP_QUEUE_STATUS_PAUSED;
509 return RAP_QUEUE_STATUS_ERROR;
512 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
513 struct pack_desc *desc,
514 print_queue_struct *queue, int n)
516 time_t t = queue->time;
518 /* the client expects localtime */
519 t -= get_time_zone(t);
521 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
523 PACKS(desc,"B21",queue->fs_user); /* szUserName */
524 PACKS(desc,"B",""); /* pad */
525 PACKS(desc,"B16",""); /* szNotifyName */
526 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
527 PACKS(desc,"z",""); /* pszParms */
528 PACKI(desc,"W",n+1); /* uPosition */
529 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
530 PACKS(desc,"z",""); /* pszStatus */
531 PACKI(desc,"D",t); /* ulSubmitted */
532 PACKI(desc,"D",queue->size); /* ulSize */
533 PACKS(desc,"z",queue->fs_file); /* pszComment */
535 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
536 PACKI(desc,"W",queue->priority); /* uPriority */
537 PACKS(desc,"z",queue->fs_user); /* pszUserName */
538 PACKI(desc,"W",n+1); /* uPosition */
539 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
540 PACKI(desc,"D",t); /* ulSubmitted */
541 PACKI(desc,"D",queue->size); /* ulSize */
542 PACKS(desc,"z","Samba"); /* pszComment */
543 PACKS(desc,"z",queue->fs_file); /* pszDocument */
545 PACKS(desc,"z",""); /* pszNotifyName */
546 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
547 PACKS(desc,"z",""); /* pszParms */
548 PACKS(desc,"z",""); /* pszStatus */
549 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
550 PACKS(desc,"z","lpd"); /* pszQProcName */
551 PACKS(desc,"z",""); /* pszQProcParms */
552 PACKS(desc,"z","NULL"); /* pszDriverName */
553 PackDriverData(desc); /* pDriverData */
554 PACKS(desc,"z",""); /* pszPrinterName */
555 } else if (uLevel == 4) { /* OS2 */
556 PACKS(desc,"z",""); /* pszSpoolFileName */
557 PACKS(desc,"z",""); /* pszPortName */
558 PACKS(desc,"z",""); /* pszStatus */
559 PACKI(desc,"D",0); /* ulPagesSpooled */
560 PACKI(desc,"D",0); /* ulPagesSent */
561 PACKI(desc,"D",0); /* ulPagesPrinted */
562 PACKI(desc,"D",0); /* ulTimePrinted */
563 PACKI(desc,"D",0); /* ulExtendJobStatus */
564 PACKI(desc,"D",0); /* ulStartPage */
565 PACKI(desc,"D",0); /* ulEndPage */
570 /********************************************************************
571 Return a driver name given an snum.
572 Returns True if from tdb, False otherwise.
573 ********************************************************************/
575 static BOOL get_driver_name(int snum, pstring drivername)
577 NT_PRINTER_INFO_LEVEL *info = NULL;
580 get_a_printer (NULL, &info, 2, lp_servicename(snum));
582 pstrcpy( drivername, info->info_2->drivername);
584 free_a_printer(&info, 2);
590 /********************************************************************
591 Respond to the DosPrintQInfo command with a level of 52
592 This is used to get printer driver information for Win9x clients
593 ********************************************************************/
594 static void fill_printq_info_52(connection_struct *conn, int snum,
595 struct pack_desc* desc, int count )
599 NT_PRINTER_DRIVER_INFO_LEVEL driver;
600 NT_PRINTER_INFO_LEVEL *printer = NULL;
604 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
605 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
606 lp_servicename(snum)));
610 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
613 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
614 printer->info_2->drivername));
618 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
619 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
620 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
622 PACKI(desc, "W", 0x0400); /* don't know */
623 PACKS(desc, "z", driver.info_3->name); /* long printer name */
624 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
625 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
626 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
628 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
629 standard_sub_basic( "", "", location, sizeof(location)-1 );
630 PACKS(desc,"z", location); /* share to retrieve files */
632 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
633 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
634 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
636 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
637 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
638 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
639 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
640 DEBUG(3,("Driver Location: %s:\n",location));
641 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
642 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
643 PACKI(desc,"N",count); /* number of files to copy */
645 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
647 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
648 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
649 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
654 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
657 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
659 desc->errcode=NERR_Success;
663 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
664 desc->errcode=NERR_notsupported;
668 free_a_printer( &printer, 2 );
671 free_a_printer_driver( driver, 3 );
675 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
676 struct pack_desc* desc,
677 int count, print_queue_struct* queue,
678 print_status_struct* status)
683 PACKS(desc,"B13",SERVICE(snum));
688 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
691 PACKI(desc,"K",printq_status(status->status));
695 if (uLevel == 1 || uLevel == 2) {
696 PACKS(desc,"B",""); /* alignment */
697 PACKI(desc,"W",5); /* priority */
698 PACKI(desc,"W",0); /* start time */
699 PACKI(desc,"W",0); /* until time */
700 PACKS(desc,"z",""); /* pSepFile */
701 PACKS(desc,"z","lpd"); /* pPrProc */
702 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
703 PACKS(desc,"z",""); /* pParms */
705 PACKS(desc,"z","UNKNOWN PRINTER");
706 PACKI(desc,"W",LPSTAT_ERROR);
708 else if (!status || !status->message[0]) {
709 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
710 PACKI(desc,"W",LPSTAT_OK); /* status */
712 PACKS(desc,"z",status->message);
713 PACKI(desc,"W",printq_status(status->status)); /* status */
715 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
718 if (uLevel == 3 || uLevel == 4) {
721 PACKI(desc,"W",5); /* uPriority */
722 PACKI(desc,"W",0); /* uStarttime */
723 PACKI(desc,"W",0); /* uUntiltime */
724 PACKI(desc,"W",5); /* pad1 */
725 PACKS(desc,"z",""); /* pszSepFile */
726 PACKS(desc,"z","WinPrint"); /* pszPrProc */
727 PACKS(desc,"z",NULL); /* pszParms */
728 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
729 /* "don't ask" that it's done this way to fix corrupted
730 Win9X/ME printer comments. */
732 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
734 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
736 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
737 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
738 get_driver_name(snum,drivername);
739 PACKS(desc,"z",drivername); /* pszDriverName */
740 PackDriverData(desc); /* pDriverData */
743 if (uLevel == 2 || uLevel == 4) {
745 for (i=0;i<count;i++)
746 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
750 fill_printq_info_52( conn, snum, desc, count );
753 /* This function returns the number of files for a given driver */
754 static int get_printerdrivernumber(int snum)
757 NT_PRINTER_DRIVER_INFO_LEVEL driver;
758 NT_PRINTER_INFO_LEVEL *printer = NULL;
762 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
763 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
764 lp_servicename(snum)));
768 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
771 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
772 printer->info_2->drivername));
776 /* count the number of files */
777 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
782 free_a_printer( &printer, 2 );
785 free_a_printer_driver( driver, 3 );
790 static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
791 char *param, int tpscnt,
792 char *data, int tdscnt,
793 int mdrcnt,int mprcnt,
794 char **rdata,char **rparam,
795 int *rdata_len,int *rparam_len)
797 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
798 char *str2 = skip_string(param,tpscnt,str1);
799 char *p = skip_string(param,tpscnt,str2);
805 struct pack_desc desc;
806 print_queue_struct *queue=NULL;
807 print_status_struct status;
810 if (!str1 || !str2 || !p) {
813 memset((char *)&status,'\0',sizeof(status));
814 memset((char *)&desc,'\0',sizeof(desc));
816 p = skip_string(param,tpscnt,p);
820 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
821 str3 = get_safe_str_ptr(param,tpscnt,p,4);
822 /* str3 may be null here and is checked in check_printq_info(). */
824 /* remove any trailing username */
825 if ((p = strchr_m(QueueName,'%')))
828 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
830 /* check it's a supported varient */
831 if (!prefix_ok(str1,"zWrLh"))
833 if (!check_printq_info(&desc,uLevel,str2,str3)) {
835 * Patch from Scott Moomaw <scott@bridgewater.edu>
836 * to return the 'invalid info level' error if an
837 * unknown level was requested.
841 *rparam = smb_realloc_limit(*rparam,*rparam_len);
845 SSVALS(*rparam,0,ERRunknownlevel);
851 snum = find_service(QueueName);
852 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
856 count = get_printerdrivernumber(snum);
857 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
859 count = print_queue_status(snum, &queue,&status);
863 *rdata = smb_realloc_limit(*rdata,mdrcnt);
869 desc.buflen = mdrcnt;
872 * Don't return data but need to get correct length
873 * init_package will return wrong size if buflen=0
875 desc.buflen = getlen(desc.format);
876 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
879 if (init_package(&desc,1,count)) {
880 desc.subcount = count;
881 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
884 *rdata_len = desc.usedlen;
887 * We must set the return code to ERRbuftoosmall
888 * in order to support lanman style printing with Win NT/2k
891 if (!mdrcnt && lp_disable_spoolss())
892 desc.errcode = ERRbuftoosmall;
894 *rdata_len = desc.usedlen;
896 *rparam = smb_realloc_limit(*rparam,*rparam_len);
902 SSVALS(*rparam,0,desc.errcode);
904 SSVAL(*rparam,4,desc.neededlen);
906 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
914 /****************************************************************************
915 View list of all print jobs on all queues.
916 ****************************************************************************/
918 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
919 char *param, int tpscnt,
920 char *data, int tdscnt,
921 int mdrcnt, int mprcnt,
922 char **rdata, char** rparam,
923 int *rdata_len, int *rparam_len)
925 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
926 char *output_format1 = skip_string(param,tpscnt,param_format);
927 char *p = skip_string(param,tpscnt,output_format1);
928 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
929 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
930 int services = lp_numservices();
932 struct pack_desc desc;
933 print_queue_struct **queue = NULL;
934 print_status_struct *status = NULL;
935 int *subcntarr = NULL;
936 int queuecnt = 0, subcnt = 0, succnt = 0;
938 if (!param_format || !output_format1 || !p) {
942 memset((char *)&desc,'\0',sizeof(desc));
944 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
946 if (!prefix_ok(param_format,"WrLeh")) {
949 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
951 * Patch from Scott Moomaw <scott@bridgewater.edu>
952 * to return the 'invalid info level' error if an
953 * unknown level was requested.
957 *rparam = smb_realloc_limit(*rparam,*rparam_len);
961 SSVALS(*rparam,0,ERRunknownlevel);
967 for (i = 0; i < services; i++) {
968 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
973 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
974 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
977 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
978 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
979 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
982 memset(status,0,queuecnt*sizeof(print_status_struct));
983 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
984 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
990 for (i = 0; i < services; i++) {
991 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
992 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
993 subcnt += subcntarr[n];
999 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1005 desc.buflen = mdrcnt;
1007 if (init_package(&desc,queuecnt,subcnt)) {
1010 for (i = 0; i < services; i++) {
1011 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1012 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1014 if (desc.errcode == NERR_Success) {
1021 SAFE_FREE(subcntarr);
1023 *rdata_len = desc.usedlen;
1025 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1029 SSVALS(*rparam,0,desc.errcode);
1031 SSVAL(*rparam,4,succnt);
1032 SSVAL(*rparam,6,queuecnt);
1034 for (i = 0; i < queuecnt; i++) {
1036 SAFE_FREE(queue[i]);
1047 SAFE_FREE(subcntarr);
1048 for (i = 0; i < queuecnt; i++) {
1050 SAFE_FREE(queue[i]);
1059 /****************************************************************************
1060 Get info level for a server list query.
1061 ****************************************************************************/
1063 static BOOL check_server_info(int uLevel, char* id)
1067 if (strcmp(id,"B16") != 0) {
1072 if (strcmp(id,"B16BBDz") != 0) {
1082 struct srv_info_struct {
1090 /*******************************************************************
1091 Get server info lists from the files saved by nmbd. Return the
1093 ******************************************************************/
1095 static int get_server_info(uint32 servertype,
1096 struct srv_info_struct **servers,
1102 BOOL local_list_only;
1105 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1107 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1111 /* request for everything is code for request all servers */
1112 if (servertype == SV_TYPE_ALL) {
1113 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1116 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1118 DEBUG(4,("Servertype search: %8x\n",servertype));
1120 for (i=0;lines[i];i++) {
1122 struct srv_info_struct *s;
1123 const char *ptr = lines[i];
1130 if (count == alloced) {
1132 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1134 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1135 file_lines_free(lines);
1138 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1140 s = &(*servers)[count];
1142 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1145 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1148 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1151 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1152 /* this allows us to cope with an old nmbd */
1153 fstrcpy(s->domain,lp_workgroup());
1156 if (sscanf(stype,"%X",&s->type) != 1) {
1157 DEBUG(4,("r:host file "));
1161 /* Filter the servers/domains we return based on what was asked for. */
1163 /* Check to see if we are being asked for a local list only. */
1164 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1165 DEBUG(4,("r: local list only"));
1169 /* doesn't match up: don't want it */
1170 if (!(servertype & s->type)) {
1171 DEBUG(4,("r:serv type "));
1175 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1176 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1177 DEBUG(4,("s: dom mismatch "));
1181 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1185 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1186 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1189 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1190 s->name, s->type, s->comment, s->domain));
1191 s->server_added = True;
1194 DEBUG(4,("%20s %8x %25s %15s\n",
1195 s->name, s->type, s->comment, s->domain));
1199 file_lines_free(lines);
1203 /*******************************************************************
1204 Fill in a server info structure.
1205 ******************************************************************/
1207 static int fill_srv_info(struct srv_info_struct *service,
1208 int uLevel, char **buf, int *buflen,
1209 char **stringbuf, int *stringspace, char *baseaddr)
1232 len = strlen(service->comment)+1;
1236 *buflen = struct_len;
1238 return struct_len + len;
1243 if (*buflen < struct_len) {
1250 p2 = p + struct_len;
1251 l2 = *buflen - struct_len;
1259 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1263 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1264 SIVAL(p,18,service->type);
1265 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1266 len += CopyAndAdvance(&p2,service->comment,&l2);
1271 *buf = p + struct_len;
1272 *buflen -= struct_len;
1283 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1285 return(strcmp(s1->name,s2->name));
1288 /****************************************************************************
1289 View list of servers available (or possibly domains). The info is
1290 extracted from lists saved by nmbd on the local host.
1291 ****************************************************************************/
1293 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1294 char *param, int tpscnt,
1295 char *data, int tdscnt,
1296 int mdrcnt, int mprcnt, char **rdata,
1297 char **rparam, int *rdata_len, int *rparam_len)
1299 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1300 char *str2 = skip_string(param,tpscnt,str1);
1301 char *p = skip_string(param,tpscnt,str2);
1302 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1303 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1304 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1306 int data_len, fixed_len, string_len;
1307 int f_len = 0, s_len = 0;
1308 struct srv_info_struct *servers=NULL;
1309 int counted=0,total=0;
1312 BOOL domain_request;
1315 if (!str1 || !str2 || !p) {
1319 /* If someone sets all the bits they don't really mean to set
1320 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1323 if (servertype == SV_TYPE_ALL) {
1324 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1327 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1328 any other bit (they may just set this bit on it's own) they
1329 want all the locally seen servers. However this bit can be
1330 set on its own so set the requested servers to be
1331 ALL - DOMAIN_ENUM. */
1333 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1334 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1337 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1338 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1342 if (!prefix_ok(str1,"WrLehD")) {
1345 if (!check_server_info(uLevel,str2)) {
1349 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1350 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1351 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1353 if (strcmp(str1, "WrLehDz") == 0) {
1354 if (skip_string(param,tpscnt,p) == NULL) {
1357 pull_ascii_fstring(domain, p);
1359 fstrcpy(domain, lp_workgroup());
1362 if (lp_browse_list()) {
1363 total = get_server_info(servertype,&servers,domain);
1366 data_len = fixed_len = string_len = 0;
1370 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1374 char *lastname=NULL;
1376 for (i=0;i<total;i++) {
1377 struct srv_info_struct *s = &servers[i];
1379 if (lastname && strequal(lastname,s->name)) {
1383 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1384 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1385 s->name, s->type, s->comment, s->domain));
1387 if (data_len <= buf_len) {
1390 string_len += s_len;
1397 *rdata_len = fixed_len + string_len;
1398 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1403 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1409 char *lastname=NULL;
1410 int count2 = counted;
1412 for (i = 0; i < total && count2;i++) {
1413 struct srv_info_struct *s = &servers[i];
1415 if (lastname && strequal(lastname,s->name)) {
1419 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1420 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1421 s->name, s->type, s->comment, s->domain));
1427 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1431 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1433 SSVAL(*rparam,4,counted);
1434 SSVAL(*rparam,6,counted+missed);
1438 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1439 domain,uLevel,counted,counted+missed));
1444 /****************************************************************************
1445 command 0x34 - suspected of being a "Lookup Names" stub api
1446 ****************************************************************************/
1448 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1449 char *param, int tpscnt,
1450 char *data, int tdscnt,
1451 int mdrcnt, int mprcnt, char **rdata,
1452 char **rparam, int *rdata_len, int *rparam_len)
1454 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1455 char *str2 = skip_string(param,tpscnt,str1);
1456 char *p = skip_string(param,tpscnt,str2);
1457 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1458 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1462 if (!str1 || !str2 || !p) {
1466 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1467 str1, str2, p, uLevel, buf_len));
1469 if (!prefix_ok(str1,"zWrLeh")) {
1476 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1481 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1483 SSVAL(*rparam,4,counted);
1484 SSVAL(*rparam,6,counted+missed);
1489 /****************************************************************************
1490 get info about a share
1491 ****************************************************************************/
1493 static BOOL check_share_info(int uLevel, char* id)
1497 if (strcmp(id,"B13") != 0) {
1502 if (strcmp(id,"B13BWz") != 0) {
1507 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1512 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1522 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1523 char** buf, int* buflen,
1524 char** stringbuf, int* stringspace, char* baseaddr)
1554 len += StrlenExpanded(conn,snum,lp_comment(snum));
1557 len += strlen(lp_pathname(snum)) + 1;
1560 *buflen = struct_len;
1565 return struct_len + len;
1570 if ((*buflen) < struct_len) {
1578 p2 = p + struct_len;
1579 l2 = (*buflen) - struct_len;
1586 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1592 type = STYPE_DISKTREE;
1593 if (lp_print_ok(snum)) {
1594 type = STYPE_PRINTQ;
1596 if (strequal("IPC",lp_fstype(snum))) {
1599 SSVAL(p,14,type); /* device type */
1600 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1601 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1605 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1606 SSVALS(p,22,-1); /* max uses */
1607 SSVAL(p,24,1); /* current uses */
1608 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1609 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1610 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1614 memset(p+40,0,SHPWLEN+2);
1625 (*buf) = p + struct_len;
1626 (*buflen) -= struct_len;
1628 (*stringspace) = l2;
1637 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1638 char *param, int tpscnt,
1639 char *data, int tdscnt,
1640 int mdrcnt,int mprcnt,
1641 char **rdata,char **rparam,
1642 int *rdata_len,int *rparam_len)
1644 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1645 char *str2 = skip_string(param,tpscnt,str1);
1646 char *netname = skip_string(param,tpscnt,str2);
1647 char *p = skip_string(param,tpscnt,netname);
1648 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1651 if (!str1 || !str2 || !netname || !p) {
1655 snum = find_service(netname);
1660 /* check it's a supported varient */
1661 if (!prefix_ok(str1,"zWrLh")) {
1664 if (!check_share_info(uLevel,str2)) {
1668 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1673 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1674 if (*rdata_len < 0) {
1679 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1683 SSVAL(*rparam,0,NERR_Success);
1684 SSVAL(*rparam,2,0); /* converter word */
1685 SSVAL(*rparam,4,*rdata_len);
1690 /****************************************************************************
1691 View the list of available shares.
1693 This function is the server side of the NetShareEnum() RAP call.
1694 It fills the return buffer with share names and share comments.
1695 Note that the return buffer normally (in all known cases) allows only
1696 twelve byte strings for share names (plus one for a nul terminator).
1697 Share names longer than 12 bytes must be skipped.
1698 ****************************************************************************/
1700 static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1701 char *param, int tpscnt,
1702 char *data, int tdscnt,
1710 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1711 char *str2 = skip_string(param,tpscnt,str1);
1712 char *p = skip_string(param,tpscnt,str2);
1713 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1714 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1717 int total=0,counted=0;
1718 BOOL missed = False;
1720 int data_len, fixed_len, string_len;
1721 int f_len = 0, s_len = 0;
1723 if (!str1 || !str2 || !p) {
1727 if (!prefix_ok(str1,"WrLeh")) {
1730 if (!check_share_info(uLevel,str2)) {
1734 /* Ensure all the usershares are loaded. */
1736 load_registry_shares();
1737 count = load_usershare_shares();
1740 data_len = fixed_len = string_len = 0;
1741 for (i=0;i<count;i++) {
1742 fstring servicename_dos;
1743 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1746 push_ascii_fstring(servicename_dos, lp_servicename(i));
1747 /* Maximum name length = 13. */
1748 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1750 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1751 if (data_len <= buf_len) {
1754 string_len += s_len;
1761 *rdata_len = fixed_len + string_len;
1762 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1767 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1772 for( i = 0; i < count; i++ ) {
1773 fstring servicename_dos;
1774 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1778 push_ascii_fstring(servicename_dos, lp_servicename(i));
1779 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1780 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1787 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1791 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1793 SSVAL(*rparam,4,counted);
1794 SSVAL(*rparam,6,total);
1796 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1797 counted,total,uLevel,
1798 buf_len,*rdata_len,mdrcnt));
1803 /****************************************************************************
1805 ****************************************************************************/
1807 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1808 char *param, int tpscnt,
1809 char *data, int tdscnt,
1810 int mdrcnt,int mprcnt,
1811 char **rdata,char **rparam,
1812 int *rdata_len,int *rparam_len)
1814 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1815 char *str2 = skip_string(param,tpscnt,str1);
1816 char *p = skip_string(param,tpscnt,str2);
1817 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1821 char *command, *cmdname;
1822 unsigned int offset;
1826 if (!str1 || !str2 || !p) {
1830 /* check it's a supported varient */
1831 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1834 if (!check_share_info(uLevel,str2)) {
1841 /* Do we have a string ? */
1842 if (skip_string(data,mdrcnt,data) == NULL) {
1845 pull_ascii_fstring(sharename,data);
1846 snum = find_service(sharename);
1847 if (snum >= 0) { /* already exists */
1856 /* only support disk share adds */
1857 if (SVAL(data,14)!=STYPE_DISKTREE) {
1861 offset = IVAL(data, 16);
1862 if (offset >= mdrcnt) {
1863 res = ERRinvalidparam;
1867 /* Do we have a string ? */
1868 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1871 pull_ascii_fstring(comment, offset? (data+offset) : "");
1873 offset = IVAL(data, 26);
1875 if (offset >= mdrcnt) {
1876 res = ERRinvalidparam;
1880 /* Do we have a string ? */
1881 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1884 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1886 string_replace(sharename, '"', ' ');
1887 string_replace(pathname, '"', ' ');
1888 string_replace(comment, '"', ' ');
1890 cmdname = lp_add_share_cmd();
1892 if (!cmdname || *cmdname == '\0') {
1896 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1897 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1900 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1902 if ((res = smbrun(command, NULL)) != 0) {
1903 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1909 message_send_all(smbd_messaging_context(),
1910 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1917 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1921 SSVAL(*rparam,0,NERR_Success);
1922 SSVAL(*rparam,2,0); /* converter word */
1923 SSVAL(*rparam,4,*rdata_len);
1931 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1936 SSVAL(*rparam,0,res);
1941 /****************************************************************************
1942 view list of groups available
1943 ****************************************************************************/
1945 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
1946 char *param, int tpscnt,
1947 char *data, int tdscnt,
1948 int mdrcnt,int mprcnt,
1949 char **rdata,char **rparam,
1950 int *rdata_len,int *rparam_len)
1954 int resume_context, cli_buf_size;
1955 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1956 char *str2 = skip_string(param,tpscnt,str1);
1957 char *p = skip_string(param,tpscnt,str2);
1959 struct pdb_search *search;
1960 struct samr_displayentry *entries;
1964 if (!str1 || !str2 || !p) {
1968 if (strcmp(str1,"WrLeh") != 0) {
1973 * W-> resume context (number of users to skip)
1974 * r -> return parameter pointer to receive buffer
1975 * L -> length of receive buffer
1976 * e -> return parameter number of entries
1977 * h -> return parameter total number of users
1980 if (strcmp("B21",str2) != 0) {
1984 /* get list of domain groups SID_DOMAIN_GRP=2 */
1986 search = pdb_search_groups();
1989 if (search == NULL) {
1990 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1994 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
1995 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
1996 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1997 "%d\n", resume_context, cli_buf_size));
2000 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
2004 *rdata_len = cli_buf_size;
2005 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2012 for(i=0; i<num_entries; i++) {
2014 fstrcpy(name, entries[i].account_name);
2015 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2016 /* truncate the name at 21 chars. */
2017 memcpy(p, name, 21);
2018 DEBUG(10,("adding entry %d group %s\n", i, p));
2020 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2023 /* set overflow error */
2024 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2030 pdb_search_destroy(search);
2032 *rdata_len = PTR_DIFF(p,*rdata);
2035 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2039 SSVAL(*rparam, 0, errflags);
2040 SSVAL(*rparam, 2, 0); /* converter word */
2041 SSVAL(*rparam, 4, i); /* is this right?? */
2042 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2047 /*******************************************************************
2048 Get groups that a user is a member of.
2049 ******************************************************************/
2051 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2052 char *param, int tpscnt,
2053 char *data, int tdscnt,
2054 int mdrcnt,int mprcnt,
2055 char **rdata,char **rparam,
2056 int *rdata_len,int *rparam_len)
2058 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2059 char *str2 = skip_string(param,tpscnt,str1);
2060 char *UserName = skip_string(param,tpscnt,str2);
2061 char *p = skip_string(param,tpscnt,UserName);
2062 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2063 const char *level_string;
2065 struct samu *sampw = NULL;
2073 enum lsa_SidType type;
2074 TALLOC_CTX *mem_ctx;
2076 if (!str1 || !str2 || !UserName || !p) {
2081 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2086 /* check it's a supported varient */
2088 if ( strcmp(str1,"zWrLeh") != 0 )
2093 level_string = "B21";
2099 if (strcmp(level_string,str2) != 0)
2102 *rdata_len = mdrcnt + 1024;
2103 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2108 SSVAL(*rparam,0,NERR_Success);
2109 SSVAL(*rparam,2,0); /* converter word */
2113 mem_ctx = talloc_new(NULL);
2114 if (mem_ctx == NULL) {
2115 DEBUG(0, ("talloc_new failed\n"));
2119 if ( !(sampw = samu_new(mem_ctx)) ) {
2120 DEBUG(0, ("samu_new() failed!\n"));
2121 TALLOC_FREE(mem_ctx);
2125 /* Lookup the user information; This should only be one of
2126 our accounts (not remote domains) */
2128 become_root(); /* ROOT BLOCK */
2130 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2131 NULL, NULL, &user_sid, &type)) {
2132 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2136 if (type != SID_NAME_USER) {
2137 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2138 sid_type_lookup(type)));
2142 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2143 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2144 sid_string_static(&user_sid), UserName));
2152 result = pdb_enum_group_memberships(mem_ctx, sampw,
2153 &sids, &gids, &num_groups);
2155 if (!NT_STATUS_IS_OK(result)) {
2156 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2161 for (i=0; i<num_groups; i++) {
2163 const char *grp_name;
2165 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2166 pstrcpy(p, grp_name);
2172 *rdata_len = PTR_DIFF(p,*rdata);
2174 SSVAL(*rparam,4,count); /* is this right?? */
2175 SSVAL(*rparam,6,count); /* is this right?? */
2180 unbecome_root(); /* END ROOT BLOCK */
2182 TALLOC_FREE(mem_ctx);
2187 /*******************************************************************
2189 ******************************************************************/
2191 static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2192 char *param, int tpscnt,
2193 char *data, int tdscnt,
2194 int mdrcnt,int mprcnt,
2195 char **rdata,char **rparam,
2196 int *rdata_len,int *rparam_len)
2201 int i, resume_context, cli_buf_size;
2202 struct pdb_search *search;
2203 struct samr_displayentry *users;
2205 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2206 char *str2 = skip_string(param,tpscnt,str1);
2207 char *p = skip_string(param,tpscnt,str2);
2209 if (!str1 || !str2 || !p) {
2213 if (strcmp(str1,"WrLeh") != 0)
2216 * W-> resume context (number of users to skip)
2217 * r -> return parameter pointer to receive buffer
2218 * L -> length of receive buffer
2219 * e -> return parameter number of entries
2220 * h -> return parameter total number of users
2223 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2224 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2225 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2226 resume_context, cli_buf_size));
2229 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2234 /* check it's a supported varient */
2235 if (strcmp("B21",str2) != 0)
2238 *rdata_len = cli_buf_size;
2239 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2247 search = pdb_search_users(ACB_NORMAL);
2249 if (search == NULL) {
2250 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2255 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2259 errflags=NERR_Success;
2261 for (i=0; i<num_users; i++) {
2262 const char *name = users[i].account_name;
2264 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2266 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2267 "%s\n",count_sent,p));
2271 /* set overflow error */
2272 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2273 "username %s\n",count_sent,name));
2279 pdb_search_destroy(search);
2281 *rdata_len = PTR_DIFF(p,*rdata);
2283 SSVAL(*rparam,0,errflags);
2284 SSVAL(*rparam,2,0); /* converter word */
2285 SSVAL(*rparam,4,count_sent); /* is this right?? */
2286 SSVAL(*rparam,6,num_users); /* is this right?? */
2291 /****************************************************************************
2292 Get the time of day info.
2293 ****************************************************************************/
2295 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2296 char *param, int tpscnt,
2297 char *data, int tdscnt,
2298 int mdrcnt,int mprcnt,
2299 char **rdata,char **rparam,
2300 int *rdata_len,int *rparam_len)
2303 time_t unixdate = time(NULL);
2307 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2313 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2318 SSVAL(*rparam,0,NERR_Success);
2319 SSVAL(*rparam,2,0); /* converter word */
2323 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2324 by NT in a "net time" operation,
2325 it seems to ignore the one below */
2327 /* the client expects to get localtime, not GMT, in this bit
2328 (I think, this needs testing) */
2329 t = localtime(&unixdate);
2334 SIVAL(p,4,0); /* msecs ? */
2335 SCVAL(p,8,t->tm_hour);
2336 SCVAL(p,9,t->tm_min);
2337 SCVAL(p,10,t->tm_sec);
2338 SCVAL(p,11,0); /* hundredths of seconds */
2339 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2340 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2341 SCVAL(p,16,t->tm_mday);
2342 SCVAL(p,17,t->tm_mon + 1);
2343 SSVAL(p,18,1900+t->tm_year);
2344 SCVAL(p,20,t->tm_wday);
2349 /****************************************************************************
2350 Set the user password.
2351 *****************************************************************************/
2353 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
2354 char *param, int tpscnt,
2355 char *data, int tdscnt,
2356 int mdrcnt,int mprcnt,
2357 char **rdata,char **rparam,
2358 int *rdata_len,int *rparam_len)
2360 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2363 fstring pass1,pass2;
2365 /* Skip 2 strings. */
2366 p = skip_string(param,tpscnt,np);
2367 p = skip_string(param,tpscnt,p);
2373 /* Do we have a string ? */
2374 if (skip_string(param,tpscnt,p) == NULL) {
2377 pull_ascii_fstring(user,p);
2379 p = skip_string(param,tpscnt,p);
2384 memset(pass1,'\0',sizeof(pass1));
2385 memset(pass2,'\0',sizeof(pass2));
2387 * We use 31 here not 32 as we're checking
2388 * the last byte we want to access is safe.
2390 if (!is_offset_safe(param,tpscnt,p,31)) {
2394 memcpy(pass2,p+16,16);
2397 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2404 SSVAL(*rparam,0,NERR_badpass);
2405 SSVAL(*rparam,2,0); /* converter word */
2407 DEBUG(3,("Set password for <%s>\n",user));
2410 * Attempt to verify the old password against smbpasswd entries
2411 * Win98 clients send old and new password in plaintext for this call.
2415 auth_serversupplied_info *server_info = NULL;
2416 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2418 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2421 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2422 SSVAL(*rparam,0,NERR_Success);
2426 TALLOC_FREE(server_info);
2428 data_blob_clear_free(&password);
2432 * If the plaintext change failed, attempt
2433 * the old encrypted method. NT will generate this
2434 * after trying the samr method. Note that this
2435 * method is done as a last resort as this
2436 * password change method loses the NT password hash
2437 * and cannot change the UNIX password as no plaintext
2441 if(SVAL(*rparam,0) != NERR_Success) {
2442 struct samu *hnd = NULL;
2444 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2446 if (change_lanman_password(hnd,(uchar *)pass2)) {
2447 SSVAL(*rparam,0,NERR_Success);
2454 memset((char *)pass1,'\0',sizeof(fstring));
2455 memset((char *)pass2,'\0',sizeof(fstring));
2460 /****************************************************************************
2461 Set the user password (SamOEM version - gets plaintext).
2462 ****************************************************************************/
2464 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2465 char *param, int tpscnt,
2466 char *data, int tdscnt,
2467 int mdrcnt,int mprcnt,
2468 char **rdata,char **rparam,
2469 int *rdata_len,int *rparam_len)
2472 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2474 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2484 SSVAL(*rparam,0,NERR_badpass);
2487 * Check the parameter definition is correct.
2490 /* Do we have a string ? */
2491 if (skip_string(param,tpscnt,p) == 0) {
2494 if(!strequal(p, "zsT")) {
2495 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2498 p = skip_string(param, tpscnt, p);
2503 /* Do we have a string ? */
2504 if (skip_string(param,tpscnt,p) == 0) {
2507 if(!strequal(p, "B516B16")) {
2508 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2511 p = skip_string(param,tpscnt,p);
2515 /* Do we have a string ? */
2516 if (skip_string(param,tpscnt,p) == 0) {
2519 p += pull_ascii_fstring(user,p);
2521 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2524 * Pass the user through the NT -> unix user mapping
2528 (void)map_username(user);
2530 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2531 SSVAL(*rparam,0,NERR_Success);
2537 /****************************************************************************
2540 ****************************************************************************/
2542 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2543 char *param, int tpscnt,
2544 char *data, int tdscnt,
2545 int mdrcnt,int mprcnt,
2546 char **rdata,char **rparam,
2547 int *rdata_len,int *rparam_len)
2549 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2550 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2551 char *str2 = skip_string(param,tpscnt,str1);
2552 char *p = skip_string(param,tpscnt,str2);
2557 WERROR werr = WERR_OK;
2559 if (!str1 || !str2 || !p) {
2563 * We use 1 here not 2 as we're checking
2564 * the last byte we want to access is safe.
2566 if (!is_offset_safe(param,tpscnt,p,1)) {
2569 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2572 /* check it's a supported varient */
2573 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2577 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2583 if (!print_job_exists(sharename, jobid)) {
2584 errcode = NERR_JobNotFound;
2588 snum = lp_servicenumber( sharename);
2590 errcode = NERR_DestNotFound;
2594 errcode = NERR_notsupported;
2597 case 81: /* delete */
2598 if (print_job_delete(¤t_user, snum, jobid, &werr))
2599 errcode = NERR_Success;
2601 case 82: /* pause */
2602 if (print_job_pause(¤t_user, snum, jobid, &werr))
2603 errcode = NERR_Success;
2605 case 83: /* resume */
2606 if (print_job_resume(¤t_user, snum, jobid, &werr))
2607 errcode = NERR_Success;
2611 if (!W_ERROR_IS_OK(werr))
2612 errcode = W_ERROR_V(werr);
2615 SSVAL(*rparam,0,errcode);
2616 SSVAL(*rparam,2,0); /* converter word */
2621 /****************************************************************************
2622 Purge a print queue - or pause or resume it.
2623 ****************************************************************************/
2625 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2626 char *param, int tpscnt,
2627 char *data, int tdscnt,
2628 int mdrcnt,int mprcnt,
2629 char **rdata,char **rparam,
2630 int *rdata_len,int *rparam_len)
2632 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2633 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2634 char *str2 = skip_string(param,tpscnt,str1);
2635 char *QueueName = skip_string(param,tpscnt,str2);
2636 int errcode = NERR_notsupported;
2638 WERROR werr = WERR_OK;
2640 if (!str1 || !str2 || !QueueName) {
2644 /* check it's a supported varient */
2645 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2649 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2655 if (skip_string(param,tpscnt,QueueName) == NULL) {
2658 snum = print_queue_snum(QueueName);
2661 errcode = NERR_JobNotFound;
2666 case 74: /* Pause queue */
2667 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2669 case 75: /* Resume queue */
2670 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2672 case 103: /* Purge */
2673 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2677 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2680 SSVAL(*rparam,0,errcode);
2681 SSVAL(*rparam,2,0); /* converter word */
2686 /****************************************************************************
2687 set the property of a print job (undocumented?)
2688 ? function = 0xb -> set name of print job
2689 ? function = 0x6 -> move print job up/down
2690 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2691 or <WWsTP> <WB21BB16B10zWWzDDz>
2692 ****************************************************************************/
2694 static int check_printjob_info(struct pack_desc* desc,
2695 int uLevel, char* id)
2697 desc->subformat = NULL;
2699 case 0: desc->format = "W"; break;
2700 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2701 case 2: desc->format = "WWzWWDDzz"; break;
2702 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2703 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2705 DEBUG(0,("check_printjob_info: invalid level %d\n",
2709 if (id == NULL || strcmp(desc->format,id) != 0) {
2710 DEBUG(0,("check_printjob_info: invalid format %s\n",
2711 id ? id : "<NULL>" ));
2717 static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2718 char *param, int tpscnt,
2719 char *data, int tdscnt,
2720 int mdrcnt,int mprcnt,
2721 char **rdata,char **rparam,
2722 int *rdata_len,int *rparam_len)
2724 struct pack_desc desc;
2725 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2726 char *str2 = skip_string(param,tpscnt,str1);
2727 char *p = skip_string(param,tpscnt,str2);
2730 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2731 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2734 if (!str1 || !str2 || !p) {
2738 * We use 1 here not 2 as we're checking
2739 * the last byte we want to access is safe.
2741 if (!is_offset_safe(param,tpscnt,p,1)) {
2744 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2747 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2752 if (!share_defined(sharename)) {
2753 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2760 /* check it's a supported varient */
2761 if ((strcmp(str1,"WWsTP")) ||
2762 (!check_printjob_info(&desc,uLevel,str2)))
2765 if (!print_job_exists(sharename, jobid)) {
2766 errcode=NERR_JobNotFound;
2770 errcode = NERR_notsupported;
2774 /* change job place in the queue,
2775 data gives the new place */
2776 place = SVAL(data,0);
2777 if (print_job_set_place(sharename, jobid, place)) {
2778 errcode=NERR_Success;
2783 /* change print job name, data gives the name */
2784 if (print_job_set_name(sharename, jobid, data)) {
2785 errcode=NERR_Success;
2794 SSVALS(*rparam,0,errcode);
2795 SSVAL(*rparam,2,0); /* converter word */
2801 /****************************************************************************
2802 Get info about the server.
2803 ****************************************************************************/
2805 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2806 char *param, int tpscnt,
2807 char *data, int tdscnt,
2808 int mdrcnt,int mprcnt,
2809 char **rdata,char **rparam,
2810 int *rdata_len,int *rparam_len)
2812 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2813 char *str2 = skip_string(param,tpscnt,str1);
2814 char *p = skip_string(param,tpscnt,str2);
2815 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2819 if (!str1 || !str2 || !p) {
2823 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2825 /* check it's a supported varient */
2826 if (!prefix_ok(str1,"WrLh")) {
2832 if (strcmp(str2,"B16") != 0) {
2838 if (strcmp(str2,"B16BBDz") != 0) {
2844 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2850 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2856 if (strcmp(str2,"DN") != 0) {
2862 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2871 *rdata_len = mdrcnt;
2872 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2878 p2 = p + struct_len;
2880 srvstr_push(NULL, 0, p,global_myname(),16,
2881 STR_ASCII|STR_UPPER|STR_TERMINATE);
2885 struct srv_info_struct *servers=NULL;
2888 uint32 servertype= lp_default_server_announce();
2890 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2892 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2893 for (i=0;i<count;i++) {
2894 if (strequal(servers[i].name,global_myname())) {
2895 servertype = servers[i].type;
2896 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2903 SCVAL(p,0,lp_major_announce_version());
2904 SCVAL(p,1,lp_minor_announce_version());
2905 SIVAL(p,2,servertype);
2907 if (mdrcnt == struct_len) {
2910 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2911 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2912 conn->connectpath, conn->gid,
2913 get_current_username(),
2914 current_user_info.domain,
2915 comment, sizeof(comment));
2916 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2917 p2 = skip_string(*rdata,*rdata_len,p2);
2925 return False; /* not yet implemented */
2928 *rdata_len = PTR_DIFF(p2,*rdata);
2931 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2935 SSVAL(*rparam,0,NERR_Success);
2936 SSVAL(*rparam,2,0); /* converter word */
2937 SSVAL(*rparam,4,*rdata_len);
2942 /****************************************************************************
2943 Get info about the server.
2944 ****************************************************************************/
2946 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
2947 char *param, int tpscnt,
2948 char *data, int tdscnt,
2949 int mdrcnt,int mprcnt,
2950 char **rdata,char **rparam,
2951 int *rdata_len,int *rparam_len)
2953 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2954 char *str2 = skip_string(param,tpscnt,str1);
2955 char *p = skip_string(param,tpscnt,str2);
2957 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
2959 if (!str1 || !str2 || !p) {
2963 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2966 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2971 /* check it's a supported varient */
2972 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2976 *rdata_len = mdrcnt + 1024;
2977 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2982 SSVAL(*rparam,0,NERR_Success);
2983 SSVAL(*rparam,2,0); /* converter word */
2986 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
2991 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2992 pstrcpy(p2,get_local_machine_name());
2994 p2 = skip_string(*rdata,*rdata_len,p2);
3000 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3001 pstrcpy(p2,current_user_info.smb_name);
3002 p2 = skip_string(*rdata,*rdata_len,p2);
3008 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3009 pstrcpy(p2,lp_workgroup());
3011 p2 = skip_string(*rdata,*rdata_len,p2);
3017 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3018 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3021 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3022 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
3023 p2 = skip_string(*rdata,*rdata_len,p2);
3029 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3031 p2 = skip_string(*rdata,*rdata_len,p2);
3037 *rdata_len = PTR_DIFF(p2,*rdata);
3039 SSVAL(*rparam,4,*rdata_len);
3044 /****************************************************************************
3045 get info about a user
3047 struct user_info_11 {
3048 char usri11_name[21]; 0-20
3050 char *usri11_comment; 22-25
3051 char *usri11_usr_comment; 26-29
3052 unsigned short usri11_priv; 30-31
3053 unsigned long usri11_auth_flags; 32-35
3054 long usri11_password_age; 36-39
3055 char *usri11_homedir; 40-43
3056 char *usri11_parms; 44-47
3057 long usri11_last_logon; 48-51
3058 long usri11_last_logoff; 52-55
3059 unsigned short usri11_bad_pw_count; 56-57
3060 unsigned short usri11_num_logons; 58-59
3061 char *usri11_logon_server; 60-63
3062 unsigned short usri11_country_code; 64-65
3063 char *usri11_workstations; 66-69
3064 unsigned long usri11_max_storage; 70-73
3065 unsigned short usri11_units_per_week; 74-75
3066 unsigned char *usri11_logon_hours; 76-79
3067 unsigned short usri11_code_page; 80-81
3072 usri11_name specifies the user name for which information is retireved
3074 usri11_pad aligns the next data structure element to a word boundary
3076 usri11_comment is a null terminated ASCII comment
3078 usri11_user_comment is a null terminated ASCII comment about the user
3080 usri11_priv specifies the level of the privilege assigned to the user.
3081 The possible values are:
3083 Name Value Description
3084 USER_PRIV_GUEST 0 Guest privilege
3085 USER_PRIV_USER 1 User privilege
3086 USER_PRV_ADMIN 2 Administrator privilege
3088 usri11_auth_flags specifies the account operator privileges. The
3089 possible values are:
3091 Name Value Description
3092 AF_OP_PRINT 0 Print operator
3095 Leach, Naik [Page 28]
3099 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3102 AF_OP_COMM 1 Communications operator
3103 AF_OP_SERVER 2 Server operator
3104 AF_OP_ACCOUNTS 3 Accounts operator
3107 usri11_password_age specifies how many seconds have elapsed since the
3108 password was last changed.
3110 usri11_home_dir points to a null terminated ASCII string that contains
3111 the path name of the user's home directory.
3113 usri11_parms points to a null terminated ASCII string that is set
3114 aside for use by applications.
3116 usri11_last_logon specifies the time when the user last logged on.
3117 This value is stored as the number of seconds elapsed since
3118 00:00:00, January 1, 1970.
3120 usri11_last_logoff specifies the time when the user last logged off.
3121 This value is stored as the number of seconds elapsed since
3122 00:00:00, January 1, 1970. A value of 0 means the last logoff
3125 usri11_bad_pw_count specifies the number of incorrect passwords
3126 entered since the last successful logon.
3128 usri11_log1_num_logons specifies the number of times this user has
3129 logged on. A value of -1 means the number of logons is unknown.
3131 usri11_logon_server points to a null terminated ASCII string that
3132 contains the name of the server to which logon requests are sent.
3133 A null string indicates logon requests should be sent to the
3136 usri11_country_code specifies the country code for the user's language
3139 usri11_workstations points to a null terminated ASCII string that
3140 contains the names of workstations the user may log on from.
3141 There may be up to 8 workstations, with the names separated by
3142 commas. A null strings indicates there are no restrictions.
3144 usri11_max_storage specifies the maximum amount of disk space the user
3145 can occupy. A value of 0xffffffff indicates there are no
3148 usri11_units_per_week specifies the equal number of time units into
3149 which a week is divided. This value must be equal to 168.
3151 usri11_logon_hours points to a 21 byte (168 bits) string that
3152 specifies the time during which the user can log on. Each bit
3153 represents one unique hour in a week. The first bit (bit 0, word
3154 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3158 Leach, Naik [Page 29]
3162 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3165 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3166 are no restrictions.
3168 usri11_code_page specifies the code page for the user's language of
3171 All of the pointers in this data structure need to be treated
3172 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3173 to be ignored. The converter word returned in the parameters section
3174 needs to be subtracted from the lower 16 bits to calculate an offset
3175 into the return buffer where this ASCII string resides.
3177 There is no auxiliary data in the response.
3179 ****************************************************************************/
3181 #define usri11_name 0
3182 #define usri11_pad 21
3183 #define usri11_comment 22
3184 #define usri11_usr_comment 26
3185 #define usri11_full_name 30
3186 #define usri11_priv 34
3187 #define usri11_auth_flags 36
3188 #define usri11_password_age 40
3189 #define usri11_homedir 44
3190 #define usri11_parms 48
3191 #define usri11_last_logon 52
3192 #define usri11_last_logoff 56
3193 #define usri11_bad_pw_count 60
3194 #define usri11_num_logons 62
3195 #define usri11_logon_server 64
3196 #define usri11_country_code 68
3197 #define usri11_workstations 70
3198 #define usri11_max_storage 74
3199 #define usri11_units_per_week 78
3200 #define usri11_logon_hours 80
3201 #define usri11_code_page 84
3202 #define usri11_end 86
3204 #define USER_PRIV_GUEST 0
3205 #define USER_PRIV_USER 1
3206 #define USER_PRIV_ADMIN 2
3208 #define AF_OP_PRINT 0
3209 #define AF_OP_COMM 1
3210 #define AF_OP_SERVER 2
3211 #define AF_OP_ACCOUNTS 3
3214 static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3215 char *param, int tpscnt,
3216 char *data, int tdscnt,
3217 int mdrcnt,int mprcnt,
3218 char **rdata,char **rparam,
3219 int *rdata_len,int *rparam_len)
3221 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3222 char *str2 = skip_string(param,tpscnt,str1);
3223 char *UserName = skip_string(param,tpscnt,str2);
3224 char *p = skip_string(param,tpscnt,UserName);
3225 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3227 const char *level_string;
3229 /* get NIS home of a previously validated user - simeon */
3230 /* With share level security vuid will always be zero.
3231 Don't depend on vuser being non-null !!. JRA */
3232 user_struct *vuser = get_valid_user_struct(vuid);
3234 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3235 vuser->user.unix_name));
3238 if (!str1 || !str2 || !UserName || !p) {
3243 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3248 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3250 /* check it's a supported variant */
3251 if (strcmp(str1,"zWrLh") != 0) {
3255 case 0: level_string = "B21"; break;
3256 case 1: level_string = "B21BB16DWzzWz"; break;
3257 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3258 case 10: level_string = "B21Bzzz"; break;
3259 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3260 default: return False;
3263 if (strcmp(level_string,str2) != 0) {
3267 *rdata_len = mdrcnt + 1024;
3268 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3273 SSVAL(*rparam,0,NERR_Success);
3274 SSVAL(*rparam,2,0); /* converter word */
3277 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3283 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3286 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3291 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3292 pstrcpy(p2,"Comment");
3293 p2 = skip_string(*rdata,*rdata_len,p2);
3298 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3299 pstrcpy(p2,"UserComment");
3300 p2 = skip_string(*rdata,*rdata_len,p2);
3305 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3306 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3307 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3308 p2 = skip_string(*rdata,*rdata_len,p2);
3315 /* modelled after NTAS 3.51 reply */
3316 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3317 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3318 SIVALS(p,usri11_password_age,-1); /* password age */
3319 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3320 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3321 p2 = skip_string(*rdata,*rdata_len,p2);
3325 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3327 p2 = skip_string(*rdata,*rdata_len,p2);
3331 SIVAL(p,usri11_last_logon,0); /* last logon */
3332 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3333 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3334 SSVALS(p,usri11_num_logons,-1); /* num logons */
3335 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3336 pstrcpy(p2,"\\\\*");
3337 p2 = skip_string(*rdata,*rdata_len,p2);
3341 SSVAL(p,usri11_country_code,0); /* country code */
3343 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3345 p2 = skip_string(*rdata,*rdata_len,p2);
3350 SIVALS(p,usri11_max_storage,-1); /* max storage */
3351 SSVAL(p,usri11_units_per_week,168); /* units per week */
3352 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3354 /* a simple way to get logon hours at all times. */
3356 SCVAL(p2,21,0); /* fix zero termination */
3357 p2 = skip_string(*rdata,*rdata_len,p2);
3362 SSVAL(p,usri11_code_page,0); /* code page */
3365 if (uLevel == 1 || uLevel == 2) {
3366 memset(p+22,' ',16); /* password */
3367 SIVALS(p,38,-1); /* password age */
3369 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3370 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3371 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3372 p2 = skip_string(*rdata,*rdata_len,p2);
3376 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3378 SSVAL(p,52,0); /* flags */
3379 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3380 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3381 p2 = skip_string(*rdata,*rdata_len,p2);
3386 SIVAL(p,60,0); /* auth_flags */
3387 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3388 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3389 p2 = skip_string(*rdata,*rdata_len,p2);
3393 SIVAL(p,68,0); /* urs_comment */
3394 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3396 p2 = skip_string(*rdata,*rdata_len,p2);
3400 SIVAL(p,76,0); /* workstations */
3401 SIVAL(p,80,0); /* last_logon */
3402 SIVAL(p,84,0); /* last_logoff */
3403 SIVALS(p,88,-1); /* acct_expires */
3404 SIVALS(p,92,-1); /* max_storage */
3405 SSVAL(p,96,168); /* units_per_week */
3406 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3409 SSVALS(p,102,-1); /* bad_pw_count */
3410 SSVALS(p,104,-1); /* num_logons */
3411 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3414 pstrcpy(tmp, "\\\\%L");
3415 standard_sub_basic("", "", tmp, sizeof(tmp));
3418 p2 = skip_string(*rdata,*rdata_len,p2);
3422 SSVAL(p,110,49); /* country_code */
3423 SSVAL(p,112,860); /* code page */
3427 *rdata_len = PTR_DIFF(p2,*rdata);
3429 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3434 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3435 char *param, int tpscnt,
3436 char *data, int tdscnt,
3437 int mdrcnt,int mprcnt,
3438 char **rdata,char **rparam,
3439 int *rdata_len,int *rparam_len)
3441 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3442 char *str2 = skip_string(param,tpscnt,str1);
3443 char *p = skip_string(param,tpscnt,str2);
3445 struct pack_desc desc;
3447 /* With share level security vuid will always be zero.
3448 Don't depend on vuser being non-null !!. JRA */
3449 user_struct *vuser = get_valid_user_struct(vuid);
3451 if (!str1 || !str2 || !p) {
3456 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3457 vuser->user.unix_name));
3460 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3461 name = get_safe_str_ptr(param,tpscnt,p,2);
3466 memset((char *)&desc,'\0',sizeof(desc));
3468 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3470 /* check it's a supported varient */
3471 if (strcmp(str1,"OOWb54WrLh") != 0) {
3474 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3478 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3485 desc.buflen = mdrcnt;
3486 desc.subformat = NULL;
3489 if (init_package(&desc,1,0)) {
3490 PACKI(&desc,"W",0); /* code */
3491 PACKS(&desc,"B21",name); /* eff. name */
3492 PACKS(&desc,"B",""); /* pad */
3493 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3494 PACKI(&desc,"D",0); /* auth flags XXX */
3495 PACKI(&desc,"W",0); /* num logons */
3496 PACKI(&desc,"W",0); /* bad pw count */
3497 PACKI(&desc,"D",0); /* last logon */
3498 PACKI(&desc,"D",-1); /* last logoff */
3499 PACKI(&desc,"D",-1); /* logoff time */
3500 PACKI(&desc,"D",-1); /* kickoff time */
3501 PACKI(&desc,"D",0); /* password age */
3502 PACKI(&desc,"D",0); /* password can change */
3503 PACKI(&desc,"D",-1); /* password must change */
3507 fstrcpy(mypath,"\\\\");
3508 fstrcat(mypath,get_local_machine_name());
3510 PACKS(&desc,"z",mypath); /* computer */
3513 PACKS(&desc,"z",lp_workgroup());/* domain */
3514 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3515 PACKI(&desc,"D",0x00000000); /* reserved */
3518 *rdata_len = desc.usedlen;
3520 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3524 SSVALS(*rparam,0,desc.errcode);
3526 SSVAL(*rparam,4,desc.neededlen);
3528 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3533 /****************************************************************************
3534 api_WAccessGetUserPerms
3535 ****************************************************************************/
3537 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3538 char *param, int tpscnt,
3539 char *data, int tdscnt,
3540 int mdrcnt,int mprcnt,
3541 char **rdata,char **rparam,
3542 int *rdata_len,int *rparam_len)
3544 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3545 char *str2 = skip_string(param,tpscnt,str1);
3546 char *user = skip_string(param,tpscnt,str2);
3547 char *resource = skip_string(param,tpscnt,user);
3549 if (!str1 || !str2 || !user || !resource) {
3553 if (skip_string(param,tpscnt,resource) == NULL) {
3556 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3558 /* check it's a supported varient */
3559 if (strcmp(str1,"zzh") != 0) {
3562 if (strcmp(str2,"") != 0) {
3567 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3571 SSVALS(*rparam,0,0); /* errorcode */
3572 SSVAL(*rparam,2,0); /* converter word */
3573 SSVAL(*rparam,4,0x7f); /* permission flags */
3578 /****************************************************************************
3579 api_WPrintJobEnumerate
3580 ****************************************************************************/
3582 static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3583 char *param, int tpscnt,
3584 char *data, int tdscnt,
3585 int mdrcnt,int mprcnt,
3586 char **rdata,char **rparam,
3587 int *rdata_len,int *rparam_len)
3589 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3590 char *str2 = skip_string(param,tpscnt,str1);
3591 char *p = skip_string(param,tpscnt,str2);
3598 struct pack_desc desc;
3599 print_queue_struct *queue=NULL;
3600 print_status_struct status;
3603 if (!str1 || !str2 || !p) {
3607 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3609 memset((char *)&desc,'\0',sizeof(desc));
3610 memset((char *)&status,'\0',sizeof(status));
3612 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3614 /* check it's a supported varient */
3615 if (strcmp(str1,"WWrLh") != 0) {
3618 if (!check_printjob_info(&desc,uLevel,str2)) {
3622 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3626 snum = lp_servicenumber( sharename);
3627 if (snum < 0 || !VALID_SNUM(snum)) {
3631 count = print_queue_status(snum,&queue,&status);
3632 for (i = 0; i < count; i++) {
3633 if (queue[i].job == jobid) {
3639 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3644 desc.buflen = mdrcnt;
3647 * Don't return data but need to get correct length
3648 * init_package will return wrong size if buflen=0
3650 desc.buflen = getlen(desc.format);
3651 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3654 if (init_package(&desc,1,0)) {
3656 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3657 *rdata_len = desc.usedlen;
3659 desc.errcode = NERR_JobNotFound;
3665 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3669 SSVALS(*rparam,0,desc.errcode);
3671 SSVAL(*rparam,4,desc.neededlen);
3676 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3681 static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3682 char *param, int tpscnt,
3683 char *data, int tdscnt,
3684 int mdrcnt,int mprcnt,
3685 char **rdata,char **rparam,
3686 int *rdata_len,int *rparam_len)
3688 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3689 char *str2 = skip_string(param,tpscnt,str1);
3690 char *p = skip_string(param,tpscnt,str2);
3696 struct pack_desc desc;
3697 print_queue_struct *queue=NULL;
3698 print_status_struct status;
3700 if (!str1 || !str2 || !p) {
3704 memset((char *)&desc,'\0',sizeof(desc));
3705 memset((char *)&status,'\0',sizeof(status));
3707 p = skip_string(param,tpscnt,p);
3711 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3713 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3715 /* check it's a supported variant */
3716 if (strcmp(str1,"zWrLeh") != 0) {
3721 return False; /* defined only for uLevel 0,1,2 */
3724 if (!check_printjob_info(&desc,uLevel,str2)) {
3728 snum = find_service(name);
3729 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3733 count = print_queue_status(snum,&queue,&status);
3735 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3741 desc.buflen = mdrcnt;
3743 if (init_package(&desc,count,0)) {
3745 for (i = 0; i < count; i++) {
3746 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3747 if (desc.errcode == NERR_Success) {
3753 *rdata_len = desc.usedlen;
3756 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3760 SSVALS(*rparam,0,desc.errcode);
3762 SSVAL(*rparam,4,succnt);
3763 SSVAL(*rparam,6,count);
3767 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3772 static int check_printdest_info(struct pack_desc* desc,
3773 int uLevel, char* id)
3775 desc->subformat = NULL;
3778 desc->format = "B9";
3781 desc->format = "B9B21WWzW";
3787 desc->format = "zzzWWzzzWW";
3790 DEBUG(0,("check_printdest_info: invalid level %d\n",
3794 if (id == NULL || strcmp(desc->format,id) != 0) {
3795 DEBUG(0,("check_printdest_info: invalid string %s\n",
3796 id ? id : "<NULL>" ));
3802 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3803 struct pack_desc* desc)
3807 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3808 buf[sizeof(buf)-1] = 0;
3812 PACKS(desc,"B9",buf); /* szName */
3814 PACKS(desc,"B21",""); /* szUserName */
3815 PACKI(desc,"W",0); /* uJobId */
3816 PACKI(desc,"W",0); /* fsStatus */
3817 PACKS(desc,"z",""); /* pszStatus */
3818 PACKI(desc,"W",0); /* time */
3822 if (uLevel == 2 || uLevel == 3) {
3823 PACKS(desc,"z",buf); /* pszPrinterName */
3825 PACKS(desc,"z",""); /* pszUserName */
3826 PACKS(desc,"z",""); /* pszLogAddr */
3827 PACKI(desc,"W",0); /* uJobId */
3828 PACKI(desc,"W",0); /* fsStatus */
3829 PACKS(desc,"z",""); /* pszStatus */
3830 PACKS(desc,"z",""); /* pszComment */
3831 PACKS(desc,"z","NULL"); /* pszDrivers */
3832 PACKI(desc,"W",0); /* time */
3833 PACKI(desc,"W",0); /* pad1 */
3838 static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3839 char *param, int tpscnt,
3840 char *data, int tdscnt,
3841 int mdrcnt,int mprcnt,
3842 char **rdata,char **rparam,
3843 int *rdata_len,int *rparam_len)
3845 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3846 char *str2 = skip_string(param,tpscnt,str1);
3847 char *p = skip_string(param,tpscnt,str2);
3848 char* PrinterName = p;
3850 struct pack_desc desc;
3854 if (!str1 || !str2 || !p) {
3858 memset((char *)&desc,'\0',sizeof(desc));
3860 p = skip_string(param,tpscnt,p);
3864 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3866 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3868 /* check it's a supported varient */
3869 if (strcmp(str1,"zWrLh") != 0) {
3872 if (!check_printdest_info(&desc,uLevel,str2)) {
3876 snum = find_service(PrinterName);
3877 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3879 desc.errcode = NERR_DestNotFound;
3883 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3888 desc.buflen = mdrcnt;
3891 * Don't return data but need to get correct length
3892 * init_package will return wrong size if buflen=0
3894 desc.buflen = getlen(desc.format);
3895 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3897 if (init_package(&desc,1,0)) {
3898 fill_printdest_info(conn,snum,uLevel,&desc);
3900 *rdata_len = desc.usedlen;
3904 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3908 SSVALS(*rparam,0,desc.errcode);
3910 SSVAL(*rparam,4,desc.neededlen);
3912 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3918 static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
3919 char *param, int tpscnt,
3920 char *data, int tdscnt,
3921 int mdrcnt,int mprcnt,
3922 char **rdata,char **rparam,
3923 int *rdata_len,int *rparam_len)
3925 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3926 char *str2 = skip_string(param,tpscnt,str1);
3927 char *p = skip_string(param,tpscnt,str2);
3931 struct pack_desc desc;
3932 int services = lp_numservices();
3934 if (!str1 || !str2 || !p) {
3938 memset((char *)&desc,'\0',sizeof(desc));
3940 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3942 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3944 /* check it's a supported varient */
3945 if (strcmp(str1,"WrLeh") != 0) {
3948 if (!check_printdest_info(&desc,uLevel,str2)) {
3953 for (i = 0; i < services; i++) {
3954 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3960 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3967 desc.buflen = mdrcnt;
3968 if (init_package(&desc,queuecnt,0)) {
3971 for (i = 0; i < services; i++) {
3972 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3973 fill_printdest_info(conn,i,uLevel,&desc);
3975 if (desc.errcode == NERR_Success) {
3982 *rdata_len = desc.usedlen;
3985 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3989 SSVALS(*rparam,0,desc.errcode);
3991 SSVAL(*rparam,4,succnt);
3992 SSVAL(*rparam,6,queuecnt);
3994 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3999 static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4000 char *param, int tpscnt,
4001 char *data, int tdscnt,
4002 int mdrcnt,int mprcnt,
4003 char **rdata,char **rparam,
4004 int *rdata_len,int *rparam_len)
4006 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4007 char *str2 = skip_string(param,tpscnt,str1);
4008 char *p = skip_string(param,tpscnt,str2);
4011 struct pack_desc desc;
4013 if (!str1 || !str2 || !p) {
4017 memset((char *)&desc,'\0',sizeof(desc));
4019 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4021 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4023 /* check it's a supported varient */
4024 if (strcmp(str1,"WrLeh") != 0) {
4027 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4032 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4038 desc.buflen = mdrcnt;
4039 if (init_package(&desc,1,0)) {
4040 PACKS(&desc,"B41","NULL");
4043 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4045 *rdata_len = desc.usedlen;
4048 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4052 SSVALS(*rparam,0,desc.errcode);
4054 SSVAL(*rparam,4,succnt);
4057 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4062 static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4063 char *param, int tpscnt,
4064 char *data, int tdscnt,
4065 int mdrcnt,int mprcnt,
4066 char **rdata,char **rparam,
4067 int *rdata_len,int *rparam_len)
4069 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4070 char *str2 = skip_string(param,tpscnt,str1);
4071 char *p = skip_string(param,tpscnt,str2);
4074 struct pack_desc desc;
4076 if (!str1 || !str2 || !p) {
4079 memset((char *)&desc,'\0',sizeof(desc));
4081 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4083 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4085 /* check it's a supported varient */
4086 if (strcmp(str1,"WrLeh") != 0) {
4089 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4094 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4100 desc.buflen = mdrcnt;
4102 if (init_package(&desc,1,0)) {
4103 PACKS(&desc,"B13","lpd");
4106 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4108 *rdata_len = desc.usedlen;
4111 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4115 SSVALS(*rparam,0,desc.errcode);
4117 SSVAL(*rparam,4,succnt);
4120 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4125 static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4126 char *param, int tpscnt,
4127 char *data, int tdscnt,
4128 int mdrcnt,int mprcnt,
4129 char **rdata,char **rparam,
4130 int *rdata_len,int *rparam_len)
4132 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4133 char *str2 = skip_string(param,tpscnt,str1);
4134 char *p = skip_string(param,tpscnt,str2);
4137 struct pack_desc desc;
4139 if (!str1 || !str2 || !p) {
4143 memset((char *)&desc,'\0',sizeof(desc));
4145 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4147 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4149 /* check it's a supported varient */
4150 if (strcmp(str1,"WrLeh") != 0) {
4153 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4158 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4163 memset((char *)&desc,'\0',sizeof(desc));
4165 desc.buflen = mdrcnt;
4167 if (init_package(&desc,1,0)) {
4168 PACKS(&desc,"B13","lp0");
4171 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4173 *rdata_len = desc.usedlen;
4176 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4180 SSVALS(*rparam,0,desc.errcode);
4182 SSVAL(*rparam,4,succnt);
4185 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4190 /****************************************************************************
4192 ****************************************************************************/
4194 static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4195 char *param, int tpscnt,
4196 char *data, int tdscnt,
4197 int mdrcnt,int mprcnt,
4198 char **rdata,char **rparam,
4199 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);
4206 struct pack_desc desc;
4207 struct sessionid *session_list;
4208 int i, num_sessions;
4210 if (!str1 || !str2 || !p) {
4214 memset((char *)&desc,'\0',sizeof(desc));
4216 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4218 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4219 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4220 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4222 /* check it's a supported varient */
4223 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4226 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4230 num_sessions = list_sessions(talloc_tos(), &session_list);
4233 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4238 memset((char *)&desc,'\0',sizeof(desc));
4240 desc.buflen = mdrcnt;
4242 if (!init_package(&desc,num_sessions,0)) {
4246 for(i=0; i<num_sessions; i++) {
4247 PACKS(&desc, "z", session_list[i].remote_machine);
4248 PACKS(&desc, "z", session_list[i].username);
4249 PACKI(&desc, "W", 1); /* num conns */
4250 PACKI(&desc, "W", 0); /* num opens */
4251 PACKI(&desc, "W", 1); /* num users */
4252 PACKI(&desc, "D", 0); /* session time */
4253 PACKI(&desc, "D", 0); /* idle time */
4254 PACKI(&desc, "D", 0); /* flags */
4255 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4258 *rdata_len = desc.usedlen;
4261 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4265 SSVALS(*rparam,0,desc.errcode);
4266 SSVAL(*rparam,2,0); /* converter */
4267 SSVAL(*rparam,4,num_sessions); /* count */
4269 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4275 /****************************************************************************
4276 The buffer was too small.
4277 ****************************************************************************/
4279 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4280 int mdrcnt, int mprcnt,
4281 char **rdata, char **rparam,
4282 int *rdata_len, int *rparam_len)
4284 *rparam_len = MIN(*rparam_len,mprcnt);
4285 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4292 SSVAL(*rparam,0,NERR_BufTooSmall);
4294 DEBUG(3,("Supplied buffer too small in API command\n"));
4299 /****************************************************************************
4300 The request is not supported.
4301 ****************************************************************************/
4303 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
4304 char *param, int tpscnt,
4305 char *data, int tdscnt,
4306 int mdrcnt, int mprcnt,
4307 char **rdata, char **rparam,
4308 int *rdata_len, int *rparam_len)
4311 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4318 SSVAL(*rparam,0,NERR_notsupported);
4319 SSVAL(*rparam,2,0); /* converter word */
4321 DEBUG(3,("Unsupported API command\n"));
4326 static const struct {
4329 BOOL (*fn)(connection_struct *, uint16,
4332 int,int,char **,char **,int *,int *);
4333 BOOL auth_user; /* Deny anonymous access? */
4334 } api_commands[] = {
4335 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4336 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4337 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4338 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4339 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4340 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4341 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4342 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4343 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4344 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4345 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4346 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4347 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4348 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4349 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4350 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4351 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4352 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4353 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4354 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4355 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4356 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4357 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4358 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4359 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4360 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4361 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4362 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4363 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4364 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4365 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4366 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4367 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4368 {NULL, -1, api_Unsupported}
4369 /* The following RAP calls are not implemented by Samba:
4371 RAP_WFileEnum2 - anon not OK
4376 /****************************************************************************
4377 Handle remote api calls.
4378 ****************************************************************************/
4380 void api_reply(connection_struct *conn, uint16 vuid,
4381 struct smb_request *req,
4382 char *data, char *params,
4383 int tdscnt, int tpscnt,
4384 int mdrcnt, int mprcnt)
4388 char *rparam = NULL;
4389 const char *name1 = NULL;
4390 const char *name2 = NULL;
4397 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4406 api_command = SVAL(params,0);
4407 /* Is there a string at position params+2 ? */
4408 if (skip_string(params,tpscnt,params+2)) {
4413 name2 = skip_string(params,tpscnt,params+2);
4418 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4422 tdscnt,tpscnt,mdrcnt,mprcnt));
4424 for (i=0;api_commands[i].name;i++) {
4425 if (api_commands[i].id == api_command && api_commands[i].fn) {
4426 DEBUG(3,("Doing %s\n",api_commands[i].name));
4431 /* Check whether this api call can be done anonymously */
4433 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4434 user_struct *user = get_valid_user_struct(vuid);
4436 if (!user || user->guest) {
4437 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4442 rdata = (char *)SMB_MALLOC(1024);
4444 memset(rdata,'\0',1024);
4447 rparam = (char *)SMB_MALLOC(1024);
4449 memset(rparam,'\0',1024);
4452 if(!rdata || !rparam) {
4453 DEBUG(0,("api_reply: malloc fail !\n"));
4456 reply_nterror(req, NT_STATUS_NO_MEMORY);
4460 reply = api_commands[i].fn(conn,
4462 params,tpscnt, /* params + length */
4463 data,tdscnt, /* data + length */
4465 &rdata,&rparam,&rdata_len,&rparam_len);
4468 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4469 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4470 &rdata,&rparam,&rdata_len,&rparam_len);
4473 /* if we get False back then it's actually unsupported */
4475 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4476 &rdata,&rparam,&rdata_len,&rparam_len);
4479 /* If api_Unsupported returns false we can't return anything. */
4481 send_trans_reply(req, rparam, rparam_len,
4482 rdata, rdata_len, False);