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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
31 extern struct current_user current_user;
32 extern userdom_struct current_user_info;
39 #define NERR_Success 0
40 #define NERR_badpass 86
41 #define NERR_notsupported 50
43 #define NERR_BASE (2100)
44 #define NERR_BufTooSmall (NERR_BASE+23)
45 #define NERR_JobNotFound (NERR_BASE+51)
46 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ACCESS_READ 0x01
49 #define ACCESS_WRITE 0x02
50 #define ACCESS_CREATE 0x04
52 #define SHPWLEN 8 /* share password length */
54 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
55 char *param, int tpscnt,
56 char *data, int tdscnt,
57 int mdrcnt, int mprcnt,
58 char **rdata, char **rparam,
59 int *rdata_len, int *rparam_len);
61 static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
62 int mdrcnt, int mprcnt,
63 char **rdata, char **rparam,
64 int *rdata_len, int *rparam_len);
67 static int CopyExpanded(connection_struct *conn,
68 int snum, char **dst, char *src, int *n)
73 if (!src || !dst || !n || !(*dst)) {
77 StrnCpy(buf,src,sizeof(buf)/2);
78 pstring_sub(buf,"%S",lp_servicename(snum));
79 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
80 conn->connectpath, conn->gid,
81 get_current_username(),
82 current_user_info.domain,
84 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
90 static int CopyAndAdvance(char **dst, char *src, int *n)
93 if (!src || !dst || !n || !(*dst)) {
96 l = push_ascii(*dst,src,*n, STR_TERMINATE);
102 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
108 StrnCpy(buf,s,sizeof(buf)/2);
109 pstring_sub(buf,"%S",lp_servicename(snum));
110 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
111 conn->connectpath, conn->gid,
112 get_current_username(),
113 current_user_info.domain,
115 return strlen(buf) + 1;
118 static char *Expand(connection_struct *conn, int snum, char *s)
124 StrnCpy(buf,s,sizeof(buf)/2);
125 pstring_sub(buf,"%S",lp_servicename(snum));
126 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
127 conn->connectpath, conn->gid,
128 get_current_username(),
129 current_user_info.domain,
134 /*******************************************************************
135 Check a API string for validity when we only need to check the prefix.
136 ******************************************************************/
138 static BOOL prefix_ok(const char *str, const char *prefix)
140 return(strncmp(str,prefix,strlen(prefix)) == 0);
144 const char *format; /* formatstring for structure */
145 const char *subformat; /* subformat for structure */
146 char *base; /* baseaddress of buffer */
147 int buflen; /* remaining size for fixed part; on init: length of base */
148 int subcount; /* count of substructures */
149 char *structbuf; /* pointer into buffer for remaining fixed part */
150 int stringlen; /* remaining size for variable part */
151 char *stringbuf; /* pointer into buffer for remaining variable part */
152 int neededlen; /* total needed size */
153 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
154 const char *curpos; /* current position; pointer into format or subformat */
158 static int get_counter(const char **p)
164 if (!isdigit((int)**p)) {
170 n = 10 * n + (i - '0');
178 static int getlen(const char *p)
187 case 'W': /* word (2 byte) */
190 case 'K': /* status word? (2 byte) */
193 case 'N': /* count of substructures (word) at end */
196 case 'D': /* double word (4 byte) */
197 case 'z': /* offset to zero terminated string (4 byte) */
198 case 'l': /* offset to user data (4 byte) */
201 case 'b': /* offset to data (with counter) (4 byte) */
205 case 'B': /* byte (with optional counter) */
206 n += get_counter(&p);
213 static BOOL init_package(struct pack_desc *p, int count, int subcount)
218 if (!p->format || !p->base) {
222 i = count * getlen(p->format);
224 i += subcount * getlen(p->subformat);
226 p->structbuf = p->base;
230 p->curpos = p->format;
236 * This is the old error code we used. Aparently
237 * WinNT/2k systems return ERRbuftoosmall (2123) and
238 * OS/2 needs this. I'm leaving this here so we can revert
241 p->errcode = ERRmoredata;
243 p->errcode = ERRbuftoosmall;
246 p->errcode = NERR_Success;
250 p->stringbuf = p->base + i;
252 return (p->errcode == NERR_Success);
255 static int package(struct pack_desc *p, ...)
258 int needed=0, stringneeded;
259 const char *str=NULL;
260 int is_string=0, stringused;
267 p->curpos = p->format;
269 p->curpos = p->subformat;
274 str = va_arg(args,char*);
275 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
284 switch( *p->curpos++ ) {
285 case 'W': /* word (2 byte) */
287 temp = va_arg(args,int);
288 if (p->buflen >= needed) {
289 SSVAL(p->structbuf,0,temp);
292 case 'K': /* status word? (2 byte) */
294 temp = va_arg(args,int);
295 if (p->buflen >= needed) {
296 SSVAL(p->structbuf,0,temp);
299 case 'N': /* count of substructures (word) at end */
301 p->subcount = va_arg(args,int);
302 if (p->buflen >= needed) {
303 SSVAL(p->structbuf,0,p->subcount);
306 case 'D': /* double word (4 byte) */
308 temp = va_arg(args,int);
309 if (p->buflen >= needed) {
310 SIVAL(p->structbuf,0,temp);
313 case 'B': /* byte (with optional counter) */
314 needed = get_counter(&p->curpos);
316 char *s = va_arg(args,char*);
317 if (p->buflen >= needed) {
318 StrnCpy(p->structbuf,s?s:"",needed-1);
322 case 'z': /* offset to zero terminated string (4 byte) */
323 str = va_arg(args,char*);
324 stringneeded = (str ? strlen(str)+1 : 0);
327 case 'l': /* offset to user data (4 byte) */
328 str = va_arg(args,char*);
329 stringneeded = va_arg(args,int);
332 case 'b': /* offset to data (with counter) (4 byte) */
333 str = va_arg(args,char*);
334 stringneeded = get_counter(&p->curpos);
340 if (stringneeded >= 0) {
342 if (p->buflen >= needed) {
343 stringused = stringneeded;
344 if (stringused > p->stringlen) {
345 stringused = (is_string ? p->stringlen : 0);
346 if (p->errcode == NERR_Success) {
347 p->errcode = ERRmoredata;
351 SIVAL(p->structbuf,0,0);
353 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
354 memcpy(p->stringbuf,str?str:"",stringused);
356 p->stringbuf[stringused-1] = '\0';
358 p->stringbuf += stringused;
359 p->stringlen -= stringused;
360 p->usedlen += stringused;
363 p->neededlen += stringneeded;
366 p->neededlen += needed;
367 if (p->buflen >= needed) {
368 p->structbuf += needed;
370 p->usedlen += needed;
372 if (p->errcode == NERR_Success) {
373 p->errcode = ERRmoredata;
380 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
381 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
383 #define PACK(desc,t,v) package(desc,v)
384 #define PACKl(desc,t,v,l) package(desc,v,l)
387 static void PACKI(struct pack_desc* desc, const char *t,int v)
392 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
397 /****************************************************************************
399 ****************************************************************************/
401 static void PackDriverData(struct pack_desc* desc)
403 char drivdata[4+4+32];
404 SIVAL(drivdata,0,sizeof drivdata); /* cb */
405 SIVAL(drivdata,4,1000); /* lVersion */
406 memset(drivdata+8,0,32); /* szDeviceName */
407 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
408 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
411 static int check_printq_info(struct pack_desc* desc,
412 unsigned int uLevel, char *id1, char *id2)
414 desc->subformat = NULL;
417 desc->format = "B13";
420 desc->format = "B13BWWWzzzzzWW";
423 desc->format = "B13BWWWzzzzzWN";
424 desc->subformat = "WB21BB16B10zWWzDDz";
427 desc->format = "zWWWWzzzzWWzzl";
430 desc->format = "zWWWWzzzzWNzzl";
431 desc->subformat = "WWzWWDDzz";
440 desc->format = "WzzzzzzzzN";
441 desc->subformat = "z";
444 DEBUG(0,("check_printq_info: invalid level %d\n",
448 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
449 DEBUG(0,("check_printq_info: invalid format %s\n",
450 id1 ? id1 : "<NULL>" ));
453 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
454 DEBUG(0,("check_printq_info: invalid subformat %s\n",
455 id2 ? id2 : "<NULL>" ));
462 #define RAP_JOB_STATUS_QUEUED 0
463 #define RAP_JOB_STATUS_PAUSED 1
464 #define RAP_JOB_STATUS_SPOOLING 2
465 #define RAP_JOB_STATUS_PRINTING 3
466 #define RAP_JOB_STATUS_PRINTED 4
468 #define RAP_QUEUE_STATUS_PAUSED 1
469 #define RAP_QUEUE_STATUS_ERROR 2
471 /* turn a print job status into a on the wire status
473 static int printj_status(int v)
477 return RAP_JOB_STATUS_QUEUED;
479 return RAP_JOB_STATUS_PAUSED;
481 return RAP_JOB_STATUS_SPOOLING;
483 return RAP_JOB_STATUS_PRINTING;
488 /* turn a print queue status into a on the wire status
490 static int printq_status(int v)
496 return RAP_QUEUE_STATUS_PAUSED;
498 return RAP_QUEUE_STATUS_ERROR;
501 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
502 struct pack_desc *desc,
503 print_queue_struct *queue, int n)
505 time_t t = queue->time;
507 /* the client expects localtime */
508 t -= get_time_zone(t);
510 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
512 PACKS(desc,"B21",queue->fs_user); /* szUserName */
513 PACKS(desc,"B",""); /* pad */
514 PACKS(desc,"B16",""); /* szNotifyName */
515 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
516 PACKS(desc,"z",""); /* pszParms */
517 PACKI(desc,"W",n+1); /* uPosition */
518 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
519 PACKS(desc,"z",""); /* pszStatus */
520 PACKI(desc,"D",t); /* ulSubmitted */
521 PACKI(desc,"D",queue->size); /* ulSize */
522 PACKS(desc,"z",queue->fs_file); /* pszComment */
524 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
525 PACKI(desc,"W",queue->priority); /* uPriority */
526 PACKS(desc,"z",queue->fs_user); /* pszUserName */
527 PACKI(desc,"W",n+1); /* uPosition */
528 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
529 PACKI(desc,"D",t); /* ulSubmitted */
530 PACKI(desc,"D",queue->size); /* ulSize */
531 PACKS(desc,"z","Samba"); /* pszComment */
532 PACKS(desc,"z",queue->fs_file); /* pszDocument */
534 PACKS(desc,"z",""); /* pszNotifyName */
535 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
536 PACKS(desc,"z",""); /* pszParms */
537 PACKS(desc,"z",""); /* pszStatus */
538 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
539 PACKS(desc,"z","lpd"); /* pszQProcName */
540 PACKS(desc,"z",""); /* pszQProcParms */
541 PACKS(desc,"z","NULL"); /* pszDriverName */
542 PackDriverData(desc); /* pDriverData */
543 PACKS(desc,"z",""); /* pszPrinterName */
544 } else if (uLevel == 4) { /* OS2 */
545 PACKS(desc,"z",""); /* pszSpoolFileName */
546 PACKS(desc,"z",""); /* pszPortName */
547 PACKS(desc,"z",""); /* pszStatus */
548 PACKI(desc,"D",0); /* ulPagesSpooled */
549 PACKI(desc,"D",0); /* ulPagesSent */
550 PACKI(desc,"D",0); /* ulPagesPrinted */
551 PACKI(desc,"D",0); /* ulTimePrinted */
552 PACKI(desc,"D",0); /* ulExtendJobStatus */
553 PACKI(desc,"D",0); /* ulStartPage */
554 PACKI(desc,"D",0); /* ulEndPage */
559 /********************************************************************
560 Return a driver name given an snum.
561 Returns True if from tdb, False otherwise.
562 ********************************************************************/
564 static BOOL get_driver_name(int snum, pstring drivername)
566 NT_PRINTER_INFO_LEVEL *info = NULL;
569 get_a_printer (NULL, &info, 2, lp_servicename(snum));
571 pstrcpy( drivername, info->info_2->drivername);
573 free_a_printer(&info, 2);
579 /********************************************************************
580 Respond to the DosPrintQInfo command with a level of 52
581 This is used to get printer driver information for Win9x clients
582 ********************************************************************/
583 static void fill_printq_info_52(connection_struct *conn, int snum,
584 struct pack_desc* desc, int count )
588 NT_PRINTER_DRIVER_INFO_LEVEL driver;
589 NT_PRINTER_INFO_LEVEL *printer = NULL;
593 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
594 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
595 lp_servicename(snum)));
599 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
602 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
603 printer->info_2->drivername));
607 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
608 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
609 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
611 PACKI(desc, "W", 0x0400); /* don't know */
612 PACKS(desc, "z", driver.info_3->name); /* long printer name */
613 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
614 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
615 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
617 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
618 standard_sub_basic( "", "", location, sizeof(location)-1 );
619 PACKS(desc,"z", location); /* share to retrieve files */
621 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
622 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
623 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
625 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
626 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
627 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
628 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
629 DEBUG(3,("Driver Location: %s:\n",location));
630 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
631 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
632 PACKI(desc,"N",count); /* number of files to copy */
634 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
636 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
637 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
638 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
643 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
646 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
648 desc->errcode=NERR_Success;
652 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
653 desc->errcode=NERR_notsupported;
657 free_a_printer( &printer, 2 );
660 free_a_printer_driver( driver, 3 );
664 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
665 struct pack_desc* desc,
666 int count, print_queue_struct* queue,
667 print_status_struct* status)
672 PACKS(desc,"B13",SERVICE(snum));
677 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
680 PACKI(desc,"K",printq_status(status->status));
684 if (uLevel == 1 || uLevel == 2) {
685 PACKS(desc,"B",""); /* alignment */
686 PACKI(desc,"W",5); /* priority */
687 PACKI(desc,"W",0); /* start time */
688 PACKI(desc,"W",0); /* until time */
689 PACKS(desc,"z",""); /* pSepFile */
690 PACKS(desc,"z","lpd"); /* pPrProc */
691 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
692 PACKS(desc,"z",""); /* pParms */
694 PACKS(desc,"z","UNKNOWN PRINTER");
695 PACKI(desc,"W",LPSTAT_ERROR);
697 else if (!status || !status->message[0]) {
698 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
699 PACKI(desc,"W",LPSTAT_OK); /* status */
701 PACKS(desc,"z",status->message);
702 PACKI(desc,"W",printq_status(status->status)); /* status */
704 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
707 if (uLevel == 3 || uLevel == 4) {
710 PACKI(desc,"W",5); /* uPriority */
711 PACKI(desc,"W",0); /* uStarttime */
712 PACKI(desc,"W",0); /* uUntiltime */
713 PACKI(desc,"W",5); /* pad1 */
714 PACKS(desc,"z",""); /* pszSepFile */
715 PACKS(desc,"z","WinPrint"); /* pszPrProc */
716 PACKS(desc,"z",NULL); /* pszParms */
717 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
718 /* "don't ask" that it's done this way to fix corrupted
719 Win9X/ME printer comments. */
721 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
723 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
725 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
726 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
727 get_driver_name(snum,drivername);
728 PACKS(desc,"z",drivername); /* pszDriverName */
729 PackDriverData(desc); /* pDriverData */
732 if (uLevel == 2 || uLevel == 4) {
734 for (i=0;i<count;i++)
735 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
739 fill_printq_info_52( conn, snum, desc, count );
742 /* This function returns the number of files for a given driver */
743 static int get_printerdrivernumber(int snum)
746 NT_PRINTER_DRIVER_INFO_LEVEL driver;
747 NT_PRINTER_INFO_LEVEL *printer = NULL;
751 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
752 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
753 lp_servicename(snum)));
757 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
760 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
761 printer->info_2->drivername));
765 /* count the number of files */
766 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
771 free_a_printer( &printer, 2 );
774 free_a_printer_driver( driver, 3 );
779 static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
780 char *param, int tpscnt,
781 char *data, int tdscnt,
782 int mdrcnt,int mprcnt,
783 char **rdata,char **rparam,
784 int *rdata_len,int *rparam_len)
786 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
787 char *str2 = skip_string(param,tpscnt,str1);
788 char *p = skip_string(param,tpscnt,str2);
794 struct pack_desc desc;
795 print_queue_struct *queue=NULL;
796 print_status_struct status;
799 if (!str1 || !str2 || !p) {
802 memset((char *)&status,'\0',sizeof(status));
803 memset((char *)&desc,'\0',sizeof(desc));
805 p = skip_string(param,tpscnt,p);
809 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
810 str3 = get_safe_str_ptr(param,tpscnt,p,4);
811 /* str3 may be null here and is checked in check_printq_info(). */
813 /* remove any trailing username */
814 if ((p = strchr_m(QueueName,'%')))
817 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
819 /* check it's a supported varient */
820 if (!prefix_ok(str1,"zWrLh"))
822 if (!check_printq_info(&desc,uLevel,str2,str3)) {
824 * Patch from Scott Moomaw <scott@bridgewater.edu>
825 * to return the 'invalid info level' error if an
826 * unknown level was requested.
830 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
834 SSVALS(*rparam,0,ERRunknownlevel);
840 snum = find_service(QueueName);
841 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
845 count = get_printerdrivernumber(snum);
846 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
848 count = print_queue_status(snum, &queue,&status);
852 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
857 desc.buflen = mdrcnt;
860 * Don't return data but need to get correct length
861 * init_package will return wrong size if buflen=0
863 desc.buflen = getlen(desc.format);
864 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
867 if (init_package(&desc,1,count)) {
868 desc.subcount = count;
869 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
872 *rdata_len = desc.usedlen;
875 * We must set the return code to ERRbuftoosmall
876 * in order to support lanman style printing with Win NT/2k
879 if (!mdrcnt && lp_disable_spoolss())
880 desc.errcode = ERRbuftoosmall;
882 *rdata_len = desc.usedlen;
884 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
888 SSVALS(*rparam,0,desc.errcode);
890 SSVAL(*rparam,4,desc.neededlen);
892 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
900 /****************************************************************************
901 View list of all print jobs on all queues.
902 ****************************************************************************/
904 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
905 char *param, int tpscnt,
906 char *data, int tdscnt,
907 int mdrcnt, int mprcnt,
908 char **rdata, char** rparam,
909 int *rdata_len, int *rparam_len)
911 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
912 char *output_format1 = skip_string(param,tpscnt,param_format);
913 char *p = skip_string(param,tpscnt,output_format1);
914 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
915 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
916 int services = lp_numservices();
918 struct pack_desc desc;
919 print_queue_struct **queue = NULL;
920 print_status_struct *status = NULL;
921 int *subcntarr = NULL;
922 int queuecnt = 0, subcnt = 0, succnt = 0;
924 if (!param_format || !output_format1 || !p) {
928 memset((char *)&desc,'\0',sizeof(desc));
930 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
932 if (!prefix_ok(param_format,"WrLeh")) {
935 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
937 * Patch from Scott Moomaw <scott@bridgewater.edu>
938 * to return the 'invalid info level' error if an
939 * unknown level was requested.
943 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
947 SSVALS(*rparam,0,ERRunknownlevel);
953 for (i = 0; i < services; i++) {
954 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
959 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
960 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
963 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
964 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
965 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
968 memset(status,0,queuecnt*sizeof(print_status_struct));
969 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
970 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
976 for (i = 0; i < services; i++) {
977 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
978 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
979 subcnt += subcntarr[n];
985 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
991 desc.buflen = mdrcnt;
993 if (init_package(&desc,queuecnt,subcnt)) {
996 for (i = 0; i < services; i++) {
997 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
998 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1000 if (desc.errcode == NERR_Success) {
1007 SAFE_FREE(subcntarr);
1009 *rdata_len = desc.usedlen;
1011 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1015 SSVALS(*rparam,0,desc.errcode);
1017 SSVAL(*rparam,4,succnt);
1018 SSVAL(*rparam,6,queuecnt);
1020 for (i = 0; i < queuecnt; i++) {
1022 SAFE_FREE(queue[i]);
1033 SAFE_FREE(subcntarr);
1034 for (i = 0; i < queuecnt; i++) {
1036 SAFE_FREE(queue[i]);
1045 /****************************************************************************
1046 Get info level for a server list query.
1047 ****************************************************************************/
1049 static BOOL check_server_info(int uLevel, char* id)
1053 if (strcmp(id,"B16") != 0) {
1058 if (strcmp(id,"B16BBDz") != 0) {
1068 struct srv_info_struct {
1076 /*******************************************************************
1077 Get server info lists from the files saved by nmbd. Return the
1079 ******************************************************************/
1081 static int get_server_info(uint32 servertype,
1082 struct srv_info_struct **servers,
1088 BOOL local_list_only;
1091 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1093 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1097 /* request for everything is code for request all servers */
1098 if (servertype == SV_TYPE_ALL) {
1099 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1102 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1104 DEBUG(4,("Servertype search: %8x\n",servertype));
1106 for (i=0;lines[i];i++) {
1108 struct srv_info_struct *s;
1109 const char *ptr = lines[i];
1116 if (count == alloced) {
1118 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1120 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1121 file_lines_free(lines);
1124 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1126 s = &(*servers)[count];
1128 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1131 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1134 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1137 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1138 /* this allows us to cope with an old nmbd */
1139 fstrcpy(s->domain,lp_workgroup());
1142 if (sscanf(stype,"%X",&s->type) != 1) {
1143 DEBUG(4,("r:host file "));
1147 /* Filter the servers/domains we return based on what was asked for. */
1149 /* Check to see if we are being asked for a local list only. */
1150 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1151 DEBUG(4,("r: local list only"));
1155 /* doesn't match up: don't want it */
1156 if (!(servertype & s->type)) {
1157 DEBUG(4,("r:serv type "));
1161 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1162 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1163 DEBUG(4,("s: dom mismatch "));
1167 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1171 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1172 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1175 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1176 s->name, s->type, s->comment, s->domain));
1177 s->server_added = True;
1180 DEBUG(4,("%20s %8x %25s %15s\n",
1181 s->name, s->type, s->comment, s->domain));
1185 file_lines_free(lines);
1189 /*******************************************************************
1190 Fill in a server info structure.
1191 ******************************************************************/
1193 static int fill_srv_info(struct srv_info_struct *service,
1194 int uLevel, char **buf, int *buflen,
1195 char **stringbuf, int *stringspace, char *baseaddr)
1218 len = strlen(service->comment)+1;
1222 *buflen = struct_len;
1224 return struct_len + len;
1229 if (*buflen < struct_len) {
1236 p2 = p + struct_len;
1237 l2 = *buflen - struct_len;
1245 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1249 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1250 SIVAL(p,18,service->type);
1251 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1252 len += CopyAndAdvance(&p2,service->comment,&l2);
1257 *buf = p + struct_len;
1258 *buflen -= struct_len;
1269 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1271 return(strcmp(s1->name,s2->name));
1274 /****************************************************************************
1275 View list of servers available (or possibly domains). The info is
1276 extracted from lists saved by nmbd on the local host.
1277 ****************************************************************************/
1279 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1280 char *param, int tpscnt,
1281 char *data, int tdscnt,
1282 int mdrcnt, int mprcnt, char **rdata,
1283 char **rparam, int *rdata_len, int *rparam_len)
1285 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1286 char *str2 = skip_string(param,tpscnt,str1);
1287 char *p = skip_string(param,tpscnt,str2);
1288 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1289 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1290 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1292 int data_len, fixed_len, string_len;
1293 int f_len = 0, s_len = 0;
1294 struct srv_info_struct *servers=NULL;
1295 int counted=0,total=0;
1298 BOOL domain_request;
1301 if (!str1 || !str2 || !p) {
1305 /* If someone sets all the bits they don't really mean to set
1306 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1309 if (servertype == SV_TYPE_ALL) {
1310 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1313 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1314 any other bit (they may just set this bit on it's own) they
1315 want all the locally seen servers. However this bit can be
1316 set on its own so set the requested servers to be
1317 ALL - DOMAIN_ENUM. */
1319 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1320 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1323 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1324 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1328 if (!prefix_ok(str1,"WrLehD")) {
1331 if (!check_server_info(uLevel,str2)) {
1335 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1336 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1337 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1339 if (strcmp(str1, "WrLehDz") == 0) {
1340 if (skip_string(param,tpscnt,p) == NULL) {
1343 pull_ascii_fstring(domain, p);
1345 fstrcpy(domain, lp_workgroup());
1348 if (lp_browse_list()) {
1349 total = get_server_info(servertype,&servers,domain);
1352 data_len = fixed_len = string_len = 0;
1356 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1360 char *lastname=NULL;
1362 for (i=0;i<total;i++) {
1363 struct srv_info_struct *s = &servers[i];
1365 if (lastname && strequal(lastname,s->name)) {
1369 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1370 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1371 s->name, s->type, s->comment, s->domain));
1373 if (data_len <= buf_len) {
1376 string_len += s_len;
1383 *rdata_len = fixed_len + string_len;
1384 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1388 memset(*rdata,'\0',*rdata_len);
1390 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1396 char *lastname=NULL;
1397 int count2 = counted;
1399 for (i = 0; i < total && count2;i++) {
1400 struct srv_info_struct *s = &servers[i];
1402 if (lastname && strequal(lastname,s->name)) {
1406 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1407 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1408 s->name, s->type, s->comment, s->domain));
1414 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1418 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1420 SSVAL(*rparam,4,counted);
1421 SSVAL(*rparam,6,counted+missed);
1425 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1426 domain,uLevel,counted,counted+missed));
1431 /****************************************************************************
1432 command 0x34 - suspected of being a "Lookup Names" stub api
1433 ****************************************************************************/
1435 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1436 char *param, int tpscnt,
1437 char *data, int tdscnt,
1438 int mdrcnt, int mprcnt, char **rdata,
1439 char **rparam, int *rdata_len, int *rparam_len)
1441 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1442 char *str2 = skip_string(param,tpscnt,str1);
1443 char *p = skip_string(param,tpscnt,str2);
1444 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1445 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1449 if (!str1 || !str2 || !p) {
1453 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1454 str1, str2, p, uLevel, buf_len));
1456 if (!prefix_ok(str1,"zWrLeh")) {
1463 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1468 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1470 SSVAL(*rparam,4,counted);
1471 SSVAL(*rparam,6,counted+missed);
1476 /****************************************************************************
1477 get info about a share
1478 ****************************************************************************/
1480 static BOOL check_share_info(int uLevel, char* id)
1484 if (strcmp(id,"B13") != 0) {
1489 if (strcmp(id,"B13BWz") != 0) {
1494 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1499 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1509 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1510 char** buf, int* buflen,
1511 char** stringbuf, int* stringspace, char* baseaddr)
1541 len += StrlenExpanded(conn,snum,lp_comment(snum));
1544 len += strlen(lp_pathname(snum)) + 1;
1547 *buflen = struct_len;
1552 return struct_len + len;
1557 if ((*buflen) < struct_len) {
1565 p2 = p + struct_len;
1566 l2 = (*buflen) - struct_len;
1573 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1579 type = STYPE_DISKTREE;
1580 if (lp_print_ok(snum)) {
1581 type = STYPE_PRINTQ;
1583 if (strequal("IPC",lp_fstype(snum))) {
1586 SSVAL(p,14,type); /* device type */
1587 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1588 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1592 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1593 SSVALS(p,22,-1); /* max uses */
1594 SSVAL(p,24,1); /* current uses */
1595 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1596 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1597 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1601 memset(p+40,0,SHPWLEN+2);
1612 (*buf) = p + struct_len;
1613 (*buflen) -= struct_len;
1615 (*stringspace) = l2;
1624 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1625 char *param, int tpscnt,
1626 char *data, int tdscnt,
1627 int mdrcnt,int mprcnt,
1628 char **rdata,char **rparam,
1629 int *rdata_len,int *rparam_len)
1631 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1632 char *str2 = skip_string(param,tpscnt,str1);
1633 char *netname = skip_string(param,tpscnt,str2);
1634 char *p = skip_string(param,tpscnt,netname);
1635 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1638 if (!str1 || !str2 || !netname || !p) {
1642 snum = find_service(netname);
1647 /* check it's a supported varient */
1648 if (!prefix_ok(str1,"zWrLh")) {
1651 if (!check_share_info(uLevel,str2)) {
1655 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1660 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1661 if (*rdata_len < 0) {
1666 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1670 SSVAL(*rparam,0,NERR_Success);
1671 SSVAL(*rparam,2,0); /* converter word */
1672 SSVAL(*rparam,4,*rdata_len);
1677 /****************************************************************************
1678 View the list of available shares.
1680 This function is the server side of the NetShareEnum() RAP call.
1681 It fills the return buffer with share names and share comments.
1682 Note that the return buffer normally (in all known cases) allows only
1683 twelve byte strings for share names (plus one for a nul terminator).
1684 Share names longer than 12 bytes must be skipped.
1685 ****************************************************************************/
1687 static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1688 char *param, int tpscnt,
1689 char *data, int tdscnt,
1697 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1698 char *str2 = skip_string(param,tpscnt,str1);
1699 char *p = skip_string(param,tpscnt,str2);
1700 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1701 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1704 int total=0,counted=0;
1705 BOOL missed = False;
1707 int data_len, fixed_len, string_len;
1708 int f_len = 0, s_len = 0;
1710 if (!str1 || !str2 || !p) {
1714 if (!prefix_ok(str1,"WrLeh")) {
1717 if (!check_share_info(uLevel,str2)) {
1721 /* Ensure all the usershares are loaded. */
1723 load_registry_shares();
1724 count = load_usershare_shares();
1727 data_len = fixed_len = string_len = 0;
1728 for (i=0;i<count;i++) {
1729 fstring servicename_dos;
1730 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1733 push_ascii_fstring(servicename_dos, lp_servicename(i));
1734 /* Maximum name length = 13. */
1735 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1737 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1738 if (data_len <= buf_len) {
1741 string_len += s_len;
1748 *rdata_len = fixed_len + string_len;
1749 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1753 memset(*rdata,0,*rdata_len);
1755 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1760 for( i = 0; i < count; i++ ) {
1761 fstring servicename_dos;
1762 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1766 push_ascii_fstring(servicename_dos, lp_servicename(i));
1767 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1768 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1775 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1779 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1781 SSVAL(*rparam,4,counted);
1782 SSVAL(*rparam,6,total);
1784 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1785 counted,total,uLevel,
1786 buf_len,*rdata_len,mdrcnt));
1791 /****************************************************************************
1793 ****************************************************************************/
1795 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1796 char *param, int tpscnt,
1797 char *data, int tdscnt,
1798 int mdrcnt,int mprcnt,
1799 char **rdata,char **rparam,
1800 int *rdata_len,int *rparam_len)
1802 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1803 char *str2 = skip_string(param,tpscnt,str1);
1804 char *p = skip_string(param,tpscnt,str2);
1805 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1809 char *command, *cmdname;
1810 unsigned int offset;
1814 if (!str1 || !str2 || !p) {
1818 /* check it's a supported varient */
1819 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1822 if (!check_share_info(uLevel,str2)) {
1829 /* Do we have a string ? */
1830 if (skip_string(data,mdrcnt,data) == NULL) {
1833 pull_ascii_fstring(sharename,data);
1834 snum = find_service(sharename);
1835 if (snum >= 0) { /* already exists */
1844 /* only support disk share adds */
1845 if (SVAL(data,14)!=STYPE_DISKTREE) {
1849 offset = IVAL(data, 16);
1850 if (offset >= mdrcnt) {
1851 res = ERRinvalidparam;
1855 /* Do we have a string ? */
1856 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1859 pull_ascii_fstring(comment, offset? (data+offset) : "");
1861 offset = IVAL(data, 26);
1863 if (offset >= mdrcnt) {
1864 res = ERRinvalidparam;
1868 /* Do we have a string ? */
1869 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1872 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1874 string_replace(sharename, '"', ' ');
1875 string_replace(pathname, '"', ' ');
1876 string_replace(comment, '"', ' ');
1878 cmdname = lp_add_share_cmd();
1880 if (!cmdname || *cmdname == '\0') {
1884 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1885 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1888 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1890 if ((res = smbrun(command, NULL)) != 0) {
1891 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1897 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1904 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1908 SSVAL(*rparam,0,NERR_Success);
1909 SSVAL(*rparam,2,0); /* converter word */
1910 SSVAL(*rparam,4,*rdata_len);
1918 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1923 SSVAL(*rparam,0,res);
1928 /****************************************************************************
1929 view list of groups available
1930 ****************************************************************************/
1932 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
1933 char *param, int tpscnt,
1934 char *data, int tdscnt,
1935 int mdrcnt,int mprcnt,
1936 char **rdata,char **rparam,
1937 int *rdata_len,int *rparam_len)
1941 int resume_context, cli_buf_size;
1942 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1943 char *str2 = skip_string(param,tpscnt,str1);
1944 char *p = skip_string(param,tpscnt,str2);
1946 struct pdb_search *search;
1947 struct samr_displayentry *entries;
1951 if (!str1 || !str2 || !p) {
1955 if (strcmp(str1,"WrLeh") != 0) {
1960 * W-> resume context (number of users to skip)
1961 * r -> return parameter pointer to receive buffer
1962 * L -> length of receive buffer
1963 * e -> return parameter number of entries
1964 * h -> return parameter total number of users
1967 if (strcmp("B21",str2) != 0) {
1971 /* get list of domain groups SID_DOMAIN_GRP=2 */
1973 search = pdb_search_groups();
1976 if (search == NULL) {
1977 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1981 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
1982 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
1983 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1984 "%d\n", resume_context, cli_buf_size));
1987 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1991 *rdata_len = cli_buf_size;
1992 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1999 for(i=0; i<num_entries; i++) {
2001 fstrcpy(name, entries[i].account_name);
2002 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2003 /* truncate the name at 21 chars. */
2004 memcpy(p, name, 21);
2005 DEBUG(10,("adding entry %d group %s\n", i, p));
2007 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2010 /* set overflow error */
2011 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2017 pdb_search_destroy(search);
2019 *rdata_len = PTR_DIFF(p,*rdata);
2022 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2026 SSVAL(*rparam, 0, errflags);
2027 SSVAL(*rparam, 2, 0); /* converter word */
2028 SSVAL(*rparam, 4, i); /* is this right?? */
2029 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2034 /*******************************************************************
2035 Get groups that a user is a member of.
2036 ******************************************************************/
2038 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2039 char *param, int tpscnt,
2040 char *data, int tdscnt,
2041 int mdrcnt,int mprcnt,
2042 char **rdata,char **rparam,
2043 int *rdata_len,int *rparam_len)
2045 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2046 char *str2 = skip_string(param,tpscnt,str1);
2047 char *UserName = skip_string(param,tpscnt,str2);
2048 char *p = skip_string(param,tpscnt,UserName);
2049 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2050 const char *level_string;
2052 struct samu *sampw = NULL;
2060 enum lsa_SidType type;
2061 TALLOC_CTX *mem_ctx;
2063 if (!str1 || !str2 || !UserName || !p) {
2068 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2073 /* check it's a supported varient */
2075 if ( strcmp(str1,"zWrLeh") != 0 )
2080 level_string = "B21";
2086 if (strcmp(level_string,str2) != 0)
2089 *rdata_len = mdrcnt + 1024;
2090 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2094 SSVAL(*rparam,0,NERR_Success);
2095 SSVAL(*rparam,2,0); /* converter word */
2099 mem_ctx = talloc_new(NULL);
2100 if (mem_ctx == NULL) {
2101 DEBUG(0, ("talloc_new failed\n"));
2105 if ( !(sampw = samu_new(mem_ctx)) ) {
2106 DEBUG(0, ("samu_new() failed!\n"));
2107 TALLOC_FREE(mem_ctx);
2111 /* Lookup the user information; This should only be one of
2112 our accounts (not remote domains) */
2114 become_root(); /* ROOT BLOCK */
2116 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2117 NULL, NULL, &user_sid, &type)) {
2118 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2122 if (type != SID_NAME_USER) {
2123 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2124 sid_type_lookup(type)));
2128 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2129 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2130 sid_string_static(&user_sid), UserName));
2138 result = pdb_enum_group_memberships(mem_ctx, sampw,
2139 &sids, &gids, &num_groups);
2141 if (!NT_STATUS_IS_OK(result)) {
2142 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2147 for (i=0; i<num_groups; i++) {
2149 const char *grp_name;
2151 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2152 pstrcpy(p, grp_name);
2158 *rdata_len = PTR_DIFF(p,*rdata);
2160 SSVAL(*rparam,4,count); /* is this right?? */
2161 SSVAL(*rparam,6,count); /* is this right?? */
2166 unbecome_root(); /* END ROOT BLOCK */
2168 TALLOC_FREE(mem_ctx);
2173 /*******************************************************************
2175 ******************************************************************/
2177 static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2178 char *param, int tpscnt,
2179 char *data, int tdscnt,
2180 int mdrcnt,int mprcnt,
2181 char **rdata,char **rparam,
2182 int *rdata_len,int *rparam_len)
2187 int i, resume_context, cli_buf_size;
2188 struct pdb_search *search;
2189 struct samr_displayentry *users;
2191 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2192 char *str2 = skip_string(param,tpscnt,str1);
2193 char *p = skip_string(param,tpscnt,str2);
2195 if (!str1 || !str2 || !p) {
2199 if (strcmp(str1,"WrLeh") != 0)
2202 * W-> resume context (number of users to skip)
2203 * r -> return parameter pointer to receive buffer
2204 * L -> length of receive buffer
2205 * e -> return parameter number of entries
2206 * h -> return parameter total number of users
2209 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2210 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2211 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2212 resume_context, cli_buf_size));
2215 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2220 /* check it's a supported varient */
2221 if (strcmp("B21",str2) != 0)
2224 *rdata_len = cli_buf_size;
2225 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2233 search = pdb_search_users(ACB_NORMAL);
2235 if (search == NULL) {
2236 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2241 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2245 errflags=NERR_Success;
2247 for (i=0; i<num_users; i++) {
2248 const char *name = users[i].account_name;
2250 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2252 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2253 "%s\n",count_sent,p));
2257 /* set overflow error */
2258 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2259 "username %s\n",count_sent,name));
2265 pdb_search_destroy(search);
2267 *rdata_len = PTR_DIFF(p,*rdata);
2269 SSVAL(*rparam,0,errflags);
2270 SSVAL(*rparam,2,0); /* converter word */
2271 SSVAL(*rparam,4,count_sent); /* is this right?? */
2272 SSVAL(*rparam,6,num_users); /* is this right?? */
2277 /****************************************************************************
2278 Get the time of day info.
2279 ****************************************************************************/
2281 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2282 char *param, int tpscnt,
2283 char *data, int tdscnt,
2284 int mdrcnt,int mprcnt,
2285 char **rdata,char **rparam,
2286 int *rdata_len,int *rparam_len)
2289 time_t unixdate = time(NULL);
2293 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2299 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2304 SSVAL(*rparam,0,NERR_Success);
2305 SSVAL(*rparam,2,0); /* converter word */
2309 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2310 by NT in a "net time" operation,
2311 it seems to ignore the one below */
2313 /* the client expects to get localtime, not GMT, in this bit
2314 (I think, this needs testing) */
2315 t = localtime(&unixdate);
2320 SIVAL(p,4,0); /* msecs ? */
2321 SCVAL(p,8,t->tm_hour);
2322 SCVAL(p,9,t->tm_min);
2323 SCVAL(p,10,t->tm_sec);
2324 SCVAL(p,11,0); /* hundredths of seconds */
2325 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2326 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2327 SCVAL(p,16,t->tm_mday);
2328 SCVAL(p,17,t->tm_mon + 1);
2329 SSVAL(p,18,1900+t->tm_year);
2330 SCVAL(p,20,t->tm_wday);
2335 /****************************************************************************
2336 Set the user password.
2337 *****************************************************************************/
2339 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
2340 char *param, int tpscnt,
2341 char *data, int tdscnt,
2342 int mdrcnt,int mprcnt,
2343 char **rdata,char **rparam,
2344 int *rdata_len,int *rparam_len)
2346 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2349 fstring pass1,pass2;
2351 /* Skip 2 strings. */
2352 p = skip_string(param,tpscnt,np);
2353 p = skip_string(param,tpscnt,p);
2359 /* Do we have a string ? */
2360 if (skip_string(param,tpscnt,p) == NULL) {
2363 pull_ascii_fstring(user,p);
2365 p = skip_string(param,tpscnt,p);
2370 memset(pass1,'\0',sizeof(pass1));
2371 memset(pass2,'\0',sizeof(pass2));
2373 * We use 31 here not 32 as we're checking
2374 * the last byte we want to access is safe.
2376 if (!is_offset_safe(param,tpscnt,p,31)) {
2380 memcpy(pass2,p+16,16);
2383 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2390 SSVAL(*rparam,0,NERR_badpass);
2391 SSVAL(*rparam,2,0); /* converter word */
2393 DEBUG(3,("Set password for <%s>\n",user));
2396 * Attempt to verify the old password against smbpasswd entries
2397 * Win98 clients send old and new password in plaintext for this call.
2401 auth_serversupplied_info *server_info = NULL;
2402 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2404 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2407 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2408 SSVAL(*rparam,0,NERR_Success);
2412 TALLOC_FREE(server_info);
2414 data_blob_clear_free(&password);
2418 * If the plaintext change failed, attempt
2419 * the old encrypted method. NT will generate this
2420 * after trying the samr method. Note that this
2421 * method is done as a last resort as this
2422 * password change method loses the NT password hash
2423 * and cannot change the UNIX password as no plaintext
2427 if(SVAL(*rparam,0) != NERR_Success) {
2428 struct samu *hnd = NULL;
2430 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2432 if (change_lanman_password(hnd,(uchar *)pass2)) {
2433 SSVAL(*rparam,0,NERR_Success);
2440 memset((char *)pass1,'\0',sizeof(fstring));
2441 memset((char *)pass2,'\0',sizeof(fstring));
2446 /****************************************************************************
2447 Set the user password (SamOEM version - gets plaintext).
2448 ****************************************************************************/
2450 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2451 char *param, int tpscnt,
2452 char *data, int tdscnt,
2453 int mdrcnt,int mprcnt,
2454 char **rdata,char **rparam,
2455 int *rdata_len,int *rparam_len)
2458 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2460 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2470 SSVAL(*rparam,0,NERR_badpass);
2473 * Check the parameter definition is correct.
2476 /* Do we have a string ? */
2477 if (skip_string(param,tpscnt,p) == 0) {
2480 if(!strequal(p, "zsT")) {
2481 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2484 p = skip_string(param, tpscnt, p);
2489 /* Do we have a string ? */
2490 if (skip_string(param,tpscnt,p) == 0) {
2493 if(!strequal(p, "B516B16")) {
2494 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2497 p = skip_string(param,tpscnt,p);
2501 /* Do we have a string ? */
2502 if (skip_string(param,tpscnt,p) == 0) {
2505 p += pull_ascii_fstring(user,p);
2507 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2510 * Pass the user through the NT -> unix user mapping
2514 (void)map_username(user);
2516 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2517 SSVAL(*rparam,0,NERR_Success);
2523 /****************************************************************************
2526 ****************************************************************************/
2528 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2529 char *param, int tpscnt,
2530 char *data, int tdscnt,
2531 int mdrcnt,int mprcnt,
2532 char **rdata,char **rparam,
2533 int *rdata_len,int *rparam_len)
2535 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2536 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2537 char *str2 = skip_string(param,tpscnt,str1);
2538 char *p = skip_string(param,tpscnt,str2);
2543 WERROR werr = WERR_OK;
2545 if (!str1 || !str2 || !p) {
2549 * We use 1 here not 2 as we're checking
2550 * the last byte we want to access is safe.
2552 if (!is_offset_safe(param,tpscnt,p,1)) {
2555 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2558 /* check it's a supported varient */
2559 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2563 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2569 if (!print_job_exists(sharename, jobid)) {
2570 errcode = NERR_JobNotFound;
2574 snum = lp_servicenumber( sharename);
2576 errcode = NERR_DestNotFound;
2580 errcode = NERR_notsupported;
2583 case 81: /* delete */
2584 if (print_job_delete(¤t_user, snum, jobid, &werr))
2585 errcode = NERR_Success;
2587 case 82: /* pause */
2588 if (print_job_pause(¤t_user, snum, jobid, &werr))
2589 errcode = NERR_Success;
2591 case 83: /* resume */
2592 if (print_job_resume(¤t_user, snum, jobid, &werr))
2593 errcode = NERR_Success;
2597 if (!W_ERROR_IS_OK(werr))
2598 errcode = W_ERROR_V(werr);
2601 SSVAL(*rparam,0,errcode);
2602 SSVAL(*rparam,2,0); /* converter word */
2607 /****************************************************************************
2608 Purge a print queue - or pause or resume it.
2609 ****************************************************************************/
2611 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2612 char *param, int tpscnt,
2613 char *data, int tdscnt,
2614 int mdrcnt,int mprcnt,
2615 char **rdata,char **rparam,
2616 int *rdata_len,int *rparam_len)
2618 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2619 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2620 char *str2 = skip_string(param,tpscnt,str1);
2621 char *QueueName = skip_string(param,tpscnt,str2);
2622 int errcode = NERR_notsupported;
2624 WERROR werr = WERR_OK;
2626 if (!str1 || !str2 || !QueueName) {
2630 /* check it's a supported varient */
2631 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2635 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2641 if (skip_string(param,tpscnt,QueueName) == NULL) {
2644 snum = print_queue_snum(QueueName);
2647 errcode = NERR_JobNotFound;
2652 case 74: /* Pause queue */
2653 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2655 case 75: /* Resume queue */
2656 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2658 case 103: /* Purge */
2659 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2663 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2666 SSVAL(*rparam,0,errcode);
2667 SSVAL(*rparam,2,0); /* converter word */
2672 /****************************************************************************
2673 set the property of a print job (undocumented?)
2674 ? function = 0xb -> set name of print job
2675 ? function = 0x6 -> move print job up/down
2676 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2677 or <WWsTP> <WB21BB16B10zWWzDDz>
2678 ****************************************************************************/
2680 static int check_printjob_info(struct pack_desc* desc,
2681 int uLevel, char* id)
2683 desc->subformat = NULL;
2685 case 0: desc->format = "W"; break;
2686 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2687 case 2: desc->format = "WWzWWDDzz"; break;
2688 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2689 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2691 DEBUG(0,("check_printjob_info: invalid level %d\n",
2695 if (id == NULL || strcmp(desc->format,id) != 0) {
2696 DEBUG(0,("check_printjob_info: invalid format %s\n",
2697 id ? id : "<NULL>" ));
2703 static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2704 char *param, int tpscnt,
2705 char *data, int tdscnt,
2706 int mdrcnt,int mprcnt,
2707 char **rdata,char **rparam,
2708 int *rdata_len,int *rparam_len)
2710 struct pack_desc desc;
2711 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2712 char *str2 = skip_string(param,tpscnt,str1);
2713 char *p = skip_string(param,tpscnt,str2);
2716 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2717 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2720 if (!str1 || !str2 || !p) {
2724 * We use 1 here not 2 as we're checking
2725 * the last byte we want to access is safe.
2727 if (!is_offset_safe(param,tpscnt,p,1)) {
2730 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2733 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2738 if (!share_defined(sharename)) {
2739 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2746 /* check it's a supported varient */
2747 if ((strcmp(str1,"WWsTP")) ||
2748 (!check_printjob_info(&desc,uLevel,str2)))
2751 if (!print_job_exists(sharename, jobid)) {
2752 errcode=NERR_JobNotFound;
2756 errcode = NERR_notsupported;
2760 /* change job place in the queue,
2761 data gives the new place */
2762 place = SVAL(data,0);
2763 if (print_job_set_place(sharename, jobid, place)) {
2764 errcode=NERR_Success;
2769 /* change print job name, data gives the name */
2770 if (print_job_set_name(sharename, jobid, data)) {
2771 errcode=NERR_Success;
2780 SSVALS(*rparam,0,errcode);
2781 SSVAL(*rparam,2,0); /* converter word */
2787 /****************************************************************************
2788 Get info about the server.
2789 ****************************************************************************/
2791 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2792 char *param, int tpscnt,
2793 char *data, int tdscnt,
2794 int mdrcnt,int mprcnt,
2795 char **rdata,char **rparam,
2796 int *rdata_len,int *rparam_len)
2798 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2799 char *str2 = skip_string(param,tpscnt,str1);
2800 char *p = skip_string(param,tpscnt,str2);
2801 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2805 if (!str1 || !str2 || !p) {
2809 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2811 /* check it's a supported varient */
2812 if (!prefix_ok(str1,"WrLh")) {
2818 if (strcmp(str2,"B16") != 0) {
2824 if (strcmp(str2,"B16BBDz") != 0) {
2830 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2836 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2842 if (strcmp(str2,"DN") != 0) {
2848 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2857 *rdata_len = mdrcnt;
2858 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2864 p2 = p + struct_len;
2866 srvstr_push(NULL, p,global_myname(),16,
2867 STR_ASCII|STR_UPPER|STR_TERMINATE);
2871 struct srv_info_struct *servers=NULL;
2874 uint32 servertype= lp_default_server_announce();
2876 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2878 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2879 for (i=0;i<count;i++) {
2880 if (strequal(servers[i].name,global_myname())) {
2881 servertype = servers[i].type;
2882 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2889 SCVAL(p,0,lp_major_announce_version());
2890 SCVAL(p,1,lp_minor_announce_version());
2891 SIVAL(p,2,servertype);
2893 if (mdrcnt == struct_len) {
2896 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2897 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2898 conn->connectpath, conn->gid,
2899 get_current_username(),
2900 current_user_info.domain,
2901 comment, sizeof(comment));
2902 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2903 p2 = skip_string(*rdata,*rdata_len,p2);
2911 return False; /* not yet implemented */
2914 *rdata_len = PTR_DIFF(p2,*rdata);
2917 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2921 SSVAL(*rparam,0,NERR_Success);
2922 SSVAL(*rparam,2,0); /* converter word */
2923 SSVAL(*rparam,4,*rdata_len);
2928 /****************************************************************************
2929 Get info about the server.
2930 ****************************************************************************/
2932 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
2933 char *param, int tpscnt,
2934 char *data, int tdscnt,
2935 int mdrcnt,int mprcnt,
2936 char **rdata,char **rparam,
2937 int *rdata_len,int *rparam_len)
2939 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2940 char *str2 = skip_string(param,tpscnt,str1);
2941 char *p = skip_string(param,tpscnt,str2);
2943 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
2945 if (!str1 || !str2 || !p) {
2949 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2952 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2957 /* check it's a supported varient */
2958 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2962 *rdata_len = mdrcnt + 1024;
2963 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2968 SSVAL(*rparam,0,NERR_Success);
2969 SSVAL(*rparam,2,0); /* converter word */
2972 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
2977 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2978 pstrcpy(p2,get_local_machine_name());
2980 p2 = skip_string(*rdata,*rdata_len,p2);
2986 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2987 pstrcpy(p2,current_user_info.smb_name);
2988 p2 = skip_string(*rdata,*rdata_len,p2);
2994 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2995 pstrcpy(p2,lp_workgroup());
2997 p2 = skip_string(*rdata,*rdata_len,p2);
3003 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3004 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3007 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3008 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
3009 p2 = skip_string(*rdata,*rdata_len,p2);
3015 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3017 p2 = skip_string(*rdata,*rdata_len,p2);
3023 *rdata_len = PTR_DIFF(p2,*rdata);
3025 SSVAL(*rparam,4,*rdata_len);
3030 /****************************************************************************
3031 get info about a user
3033 struct user_info_11 {
3034 char usri11_name[21]; 0-20
3036 char *usri11_comment; 22-25
3037 char *usri11_usr_comment; 26-29
3038 unsigned short usri11_priv; 30-31
3039 unsigned long usri11_auth_flags; 32-35
3040 long usri11_password_age; 36-39
3041 char *usri11_homedir; 40-43
3042 char *usri11_parms; 44-47
3043 long usri11_last_logon; 48-51
3044 long usri11_last_logoff; 52-55
3045 unsigned short usri11_bad_pw_count; 56-57
3046 unsigned short usri11_num_logons; 58-59
3047 char *usri11_logon_server; 60-63
3048 unsigned short usri11_country_code; 64-65
3049 char *usri11_workstations; 66-69
3050 unsigned long usri11_max_storage; 70-73
3051 unsigned short usri11_units_per_week; 74-75
3052 unsigned char *usri11_logon_hours; 76-79
3053 unsigned short usri11_code_page; 80-81
3058 usri11_name specifies the user name for which information is retireved
3060 usri11_pad aligns the next data structure element to a word boundary
3062 usri11_comment is a null terminated ASCII comment
3064 usri11_user_comment is a null terminated ASCII comment about the user
3066 usri11_priv specifies the level of the privilege assigned to the user.
3067 The possible values are:
3069 Name Value Description
3070 USER_PRIV_GUEST 0 Guest privilege
3071 USER_PRIV_USER 1 User privilege
3072 USER_PRV_ADMIN 2 Administrator privilege
3074 usri11_auth_flags specifies the account operator privileges. The
3075 possible values are:
3077 Name Value Description
3078 AF_OP_PRINT 0 Print operator
3081 Leach, Naik [Page 28]
3085 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3088 AF_OP_COMM 1 Communications operator
3089 AF_OP_SERVER 2 Server operator
3090 AF_OP_ACCOUNTS 3 Accounts operator
3093 usri11_password_age specifies how many seconds have elapsed since the
3094 password was last changed.
3096 usri11_home_dir points to a null terminated ASCII string that contains
3097 the path name of the user's home directory.
3099 usri11_parms points to a null terminated ASCII string that is set
3100 aside for use by applications.
3102 usri11_last_logon specifies the time when the user last logged on.
3103 This value is stored as the number of seconds elapsed since
3104 00:00:00, January 1, 1970.
3106 usri11_last_logoff specifies the time when the user last logged off.
3107 This value is stored as the number of seconds elapsed since
3108 00:00:00, January 1, 1970. A value of 0 means the last logoff
3111 usri11_bad_pw_count specifies the number of incorrect passwords
3112 entered since the last successful logon.
3114 usri11_log1_num_logons specifies the number of times this user has
3115 logged on. A value of -1 means the number of logons is unknown.
3117 usri11_logon_server points to a null terminated ASCII string that
3118 contains the name of the server to which logon requests are sent.
3119 A null string indicates logon requests should be sent to the
3122 usri11_country_code specifies the country code for the user's language
3125 usri11_workstations points to a null terminated ASCII string that
3126 contains the names of workstations the user may log on from.
3127 There may be up to 8 workstations, with the names separated by
3128 commas. A null strings indicates there are no restrictions.
3130 usri11_max_storage specifies the maximum amount of disk space the user
3131 can occupy. A value of 0xffffffff indicates there are no
3134 usri11_units_per_week specifies the equal number of time units into
3135 which a week is divided. This value must be equal to 168.
3137 usri11_logon_hours points to a 21 byte (168 bits) string that
3138 specifies the time during which the user can log on. Each bit
3139 represents one unique hour in a week. The first bit (bit 0, word
3140 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3144 Leach, Naik [Page 29]
3148 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3151 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3152 are no restrictions.
3154 usri11_code_page specifies the code page for the user's language of
3157 All of the pointers in this data structure need to be treated
3158 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3159 to be ignored. The converter word returned in the parameters section
3160 needs to be subtracted from the lower 16 bits to calculate an offset
3161 into the return buffer where this ASCII string resides.
3163 There is no auxiliary data in the response.
3165 ****************************************************************************/
3167 #define usri11_name 0
3168 #define usri11_pad 21
3169 #define usri11_comment 22
3170 #define usri11_usr_comment 26
3171 #define usri11_full_name 30
3172 #define usri11_priv 34
3173 #define usri11_auth_flags 36
3174 #define usri11_password_age 40
3175 #define usri11_homedir 44
3176 #define usri11_parms 48
3177 #define usri11_last_logon 52
3178 #define usri11_last_logoff 56
3179 #define usri11_bad_pw_count 60
3180 #define usri11_num_logons 62
3181 #define usri11_logon_server 64
3182 #define usri11_country_code 68
3183 #define usri11_workstations 70
3184 #define usri11_max_storage 74
3185 #define usri11_units_per_week 78
3186 #define usri11_logon_hours 80
3187 #define usri11_code_page 84
3188 #define usri11_end 86
3190 #define USER_PRIV_GUEST 0
3191 #define USER_PRIV_USER 1
3192 #define USER_PRIV_ADMIN 2
3194 #define AF_OP_PRINT 0
3195 #define AF_OP_COMM 1
3196 #define AF_OP_SERVER 2
3197 #define AF_OP_ACCOUNTS 3
3200 static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3201 char *param, int tpscnt,
3202 char *data, int tdscnt,
3203 int mdrcnt,int mprcnt,
3204 char **rdata,char **rparam,
3205 int *rdata_len,int *rparam_len)
3207 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3208 char *str2 = skip_string(param,tpscnt,str1);
3209 char *UserName = skip_string(param,tpscnt,str2);
3210 char *p = skip_string(param,tpscnt,UserName);
3211 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3213 const char *level_string;
3215 /* get NIS home of a previously validated user - simeon */
3216 /* With share level security vuid will always be zero.
3217 Don't depend on vuser being non-null !!. JRA */
3218 user_struct *vuser = get_valid_user_struct(vuid);
3220 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3221 vuser->user.unix_name));
3224 if (!str1 || !str2 || !UserName || !p) {
3229 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3234 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3236 /* check it's a supported variant */
3237 if (strcmp(str1,"zWrLh") != 0) {
3241 case 0: level_string = "B21"; break;
3242 case 1: level_string = "B21BB16DWzzWz"; break;
3243 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3244 case 10: level_string = "B21Bzzz"; break;
3245 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3246 default: return False;
3249 if (strcmp(level_string,str2) != 0) {
3253 *rdata_len = mdrcnt + 1024;
3254 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3259 SSVAL(*rparam,0,NERR_Success);
3260 SSVAL(*rparam,2,0); /* converter word */
3263 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3269 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3272 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3277 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3278 pstrcpy(p2,"Comment");
3279 p2 = skip_string(*rdata,*rdata_len,p2);
3284 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3285 pstrcpy(p2,"UserComment");
3286 p2 = skip_string(*rdata,*rdata_len,p2);
3291 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3292 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3293 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3294 p2 = skip_string(*rdata,*rdata_len,p2);
3301 /* modelled after NTAS 3.51 reply */
3302 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3303 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3304 SIVALS(p,usri11_password_age,-1); /* password age */
3305 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3306 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3307 p2 = skip_string(*rdata,*rdata_len,p2);
3311 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3313 p2 = skip_string(*rdata,*rdata_len,p2);
3317 SIVAL(p,usri11_last_logon,0); /* last logon */
3318 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3319 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3320 SSVALS(p,usri11_num_logons,-1); /* num logons */
3321 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3322 pstrcpy(p2,"\\\\*");
3323 p2 = skip_string(*rdata,*rdata_len,p2);
3327 SSVAL(p,usri11_country_code,0); /* country code */
3329 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3331 p2 = skip_string(*rdata,*rdata_len,p2);
3336 SIVALS(p,usri11_max_storage,-1); /* max storage */
3337 SSVAL(p,usri11_units_per_week,168); /* units per week */
3338 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3340 /* a simple way to get logon hours at all times. */
3342 SCVAL(p2,21,0); /* fix zero termination */
3343 p2 = skip_string(*rdata,*rdata_len,p2);
3348 SSVAL(p,usri11_code_page,0); /* code page */
3351 if (uLevel == 1 || uLevel == 2) {
3352 memset(p+22,' ',16); /* password */
3353 SIVALS(p,38,-1); /* password age */
3355 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3356 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3357 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3358 p2 = skip_string(*rdata,*rdata_len,p2);
3362 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3364 SSVAL(p,52,0); /* flags */
3365 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3366 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3367 p2 = skip_string(*rdata,*rdata_len,p2);
3372 SIVAL(p,60,0); /* auth_flags */
3373 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3374 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3375 p2 = skip_string(*rdata,*rdata_len,p2);
3379 SIVAL(p,68,0); /* urs_comment */
3380 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3382 p2 = skip_string(*rdata,*rdata_len,p2);
3386 SIVAL(p,76,0); /* workstations */
3387 SIVAL(p,80,0); /* last_logon */
3388 SIVAL(p,84,0); /* last_logoff */
3389 SIVALS(p,88,-1); /* acct_expires */
3390 SIVALS(p,92,-1); /* max_storage */
3391 SSVAL(p,96,168); /* units_per_week */
3392 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3395 SSVALS(p,102,-1); /* bad_pw_count */
3396 SSVALS(p,104,-1); /* num_logons */
3397 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3400 pstrcpy(tmp, "\\\\%L");
3401 standard_sub_basic("", "", tmp, sizeof(tmp));
3404 p2 = skip_string(*rdata,*rdata_len,p2);
3408 SSVAL(p,110,49); /* country_code */
3409 SSVAL(p,112,860); /* code page */
3413 *rdata_len = PTR_DIFF(p2,*rdata);
3415 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3420 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3421 char *param, int tpscnt,
3422 char *data, int tdscnt,
3423 int mdrcnt,int mprcnt,
3424 char **rdata,char **rparam,
3425 int *rdata_len,int *rparam_len)
3427 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3428 char *str2 = skip_string(param,tpscnt,str1);
3429 char *p = skip_string(param,tpscnt,str2);
3431 struct pack_desc desc;
3433 /* With share level security vuid will always be zero.
3434 Don't depend on vuser being non-null !!. JRA */
3435 user_struct *vuser = get_valid_user_struct(vuid);
3437 if (!str1 || !str2 || !p) {
3442 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3443 vuser->user.unix_name));
3446 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3447 name = get_safe_str_ptr(param,tpscnt,p,2);
3452 memset((char *)&desc,'\0',sizeof(desc));
3454 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3456 /* check it's a supported varient */
3457 if (strcmp(str1,"OOWb54WrLh") != 0) {
3460 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3464 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3471 desc.buflen = mdrcnt;
3472 desc.subformat = NULL;
3475 if (init_package(&desc,1,0)) {
3476 PACKI(&desc,"W",0); /* code */
3477 PACKS(&desc,"B21",name); /* eff. name */
3478 PACKS(&desc,"B",""); /* pad */
3479 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3480 PACKI(&desc,"D",0); /* auth flags XXX */
3481 PACKI(&desc,"W",0); /* num logons */
3482 PACKI(&desc,"W",0); /* bad pw count */
3483 PACKI(&desc,"D",0); /* last logon */
3484 PACKI(&desc,"D",-1); /* last logoff */
3485 PACKI(&desc,"D",-1); /* logoff time */
3486 PACKI(&desc,"D",-1); /* kickoff time */
3487 PACKI(&desc,"D",0); /* password age */
3488 PACKI(&desc,"D",0); /* password can change */
3489 PACKI(&desc,"D",-1); /* password must change */
3493 fstrcpy(mypath,"\\\\");
3494 fstrcat(mypath,get_local_machine_name());
3496 PACKS(&desc,"z",mypath); /* computer */
3499 PACKS(&desc,"z",lp_workgroup());/* domain */
3500 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3501 PACKI(&desc,"D",0x00000000); /* reserved */
3504 *rdata_len = desc.usedlen;
3506 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3510 SSVALS(*rparam,0,desc.errcode);
3512 SSVAL(*rparam,4,desc.neededlen);
3514 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3519 /****************************************************************************
3520 api_WAccessGetUserPerms
3521 ****************************************************************************/
3523 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3524 char *param, int tpscnt,
3525 char *data, int tdscnt,
3526 int mdrcnt,int mprcnt,
3527 char **rdata,char **rparam,
3528 int *rdata_len,int *rparam_len)
3530 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3531 char *str2 = skip_string(param,tpscnt,str1);
3532 char *user = skip_string(param,tpscnt,str2);
3533 char *resource = skip_string(param,tpscnt,user);
3535 if (!str1 || !str2 || !user || !resource) {
3539 if (skip_string(param,tpscnt,resource) == NULL) {
3542 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3544 /* check it's a supported varient */
3545 if (strcmp(str1,"zzh") != 0) {
3548 if (strcmp(str2,"") != 0) {
3553 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3557 SSVALS(*rparam,0,0); /* errorcode */
3558 SSVAL(*rparam,2,0); /* converter word */
3559 SSVAL(*rparam,4,0x7f); /* permission flags */
3564 /****************************************************************************
3565 api_WPrintJobEnumerate
3566 ****************************************************************************/
3568 static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3569 char *param, int tpscnt,
3570 char *data, int tdscnt,
3571 int mdrcnt,int mprcnt,
3572 char **rdata,char **rparam,
3573 int *rdata_len,int *rparam_len)
3575 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3576 char *str2 = skip_string(param,tpscnt,str1);
3577 char *p = skip_string(param,tpscnt,str2);
3584 struct pack_desc desc;
3585 print_queue_struct *queue=NULL;
3586 print_status_struct status;
3589 if (!str1 || !str2 || !p) {
3593 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3595 memset((char *)&desc,'\0',sizeof(desc));
3596 memset((char *)&status,'\0',sizeof(status));
3598 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3600 /* check it's a supported varient */
3601 if (strcmp(str1,"WWrLh") != 0) {
3604 if (!check_printjob_info(&desc,uLevel,str2)) {
3608 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3612 snum = lp_servicenumber( sharename);
3613 if (snum < 0 || !VALID_SNUM(snum)) {
3617 count = print_queue_status(snum,&queue,&status);
3618 for (i = 0; i < count; i++) {
3619 if (queue[i].job == jobid) {
3625 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3630 desc.buflen = mdrcnt;
3633 * Don't return data but need to get correct length
3634 * init_package will return wrong size if buflen=0
3636 desc.buflen = getlen(desc.format);
3637 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3640 if (init_package(&desc,1,0)) {
3642 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3643 *rdata_len = desc.usedlen;
3645 desc.errcode = NERR_JobNotFound;
3651 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3655 SSVALS(*rparam,0,desc.errcode);
3657 SSVAL(*rparam,4,desc.neededlen);
3662 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3667 static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3668 char *param, int tpscnt,
3669 char *data, int tdscnt,
3670 int mdrcnt,int mprcnt,
3671 char **rdata,char **rparam,
3672 int *rdata_len,int *rparam_len)
3674 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3675 char *str2 = skip_string(param,tpscnt,str1);
3676 char *p = skip_string(param,tpscnt,str2);
3682 struct pack_desc desc;
3683 print_queue_struct *queue=NULL;
3684 print_status_struct status;
3686 if (!str1 || !str2 || !p) {
3690 memset((char *)&desc,'\0',sizeof(desc));
3691 memset((char *)&status,'\0',sizeof(status));
3693 p = skip_string(param,tpscnt,p);
3697 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3699 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3701 /* check it's a supported variant */
3702 if (strcmp(str1,"zWrLeh") != 0) {
3707 return False; /* defined only for uLevel 0,1,2 */
3710 if (!check_printjob_info(&desc,uLevel,str2)) {
3714 snum = find_service(name);
3715 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3719 count = print_queue_status(snum,&queue,&status);
3721 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3727 desc.buflen = mdrcnt;
3729 if (init_package(&desc,count,0)) {
3731 for (i = 0; i < count; i++) {
3732 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3733 if (desc.errcode == NERR_Success) {
3739 *rdata_len = desc.usedlen;
3742 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3746 SSVALS(*rparam,0,desc.errcode);
3748 SSVAL(*rparam,4,succnt);
3749 SSVAL(*rparam,6,count);
3753 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3758 static int check_printdest_info(struct pack_desc* desc,
3759 int uLevel, char* id)
3761 desc->subformat = NULL;
3764 desc->format = "B9";
3767 desc->format = "B9B21WWzW";
3773 desc->format = "zzzWWzzzWW";
3776 DEBUG(0,("check_printdest_info: invalid level %d\n",
3780 if (id == NULL || strcmp(desc->format,id) != 0) {
3781 DEBUG(0,("check_printdest_info: invalid string %s\n",
3782 id ? id : "<NULL>" ));
3788 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3789 struct pack_desc* desc)
3793 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3794 buf[sizeof(buf)-1] = 0;
3798 PACKS(desc,"B9",buf); /* szName */
3800 PACKS(desc,"B21",""); /* szUserName */
3801 PACKI(desc,"W",0); /* uJobId */
3802 PACKI(desc,"W",0); /* fsStatus */
3803 PACKS(desc,"z",""); /* pszStatus */
3804 PACKI(desc,"W",0); /* time */
3808 if (uLevel == 2 || uLevel == 3) {
3809 PACKS(desc,"z",buf); /* pszPrinterName */
3811 PACKS(desc,"z",""); /* pszUserName */
3812 PACKS(desc,"z",""); /* pszLogAddr */
3813 PACKI(desc,"W",0); /* uJobId */
3814 PACKI(desc,"W",0); /* fsStatus */
3815 PACKS(desc,"z",""); /* pszStatus */
3816 PACKS(desc,"z",""); /* pszComment */
3817 PACKS(desc,"z","NULL"); /* pszDrivers */
3818 PACKI(desc,"W",0); /* time */
3819 PACKI(desc,"W",0); /* pad1 */
3824 static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3825 char *param, int tpscnt,
3826 char *data, int tdscnt,
3827 int mdrcnt,int mprcnt,
3828 char **rdata,char **rparam,
3829 int *rdata_len,int *rparam_len)
3831 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3832 char *str2 = skip_string(param,tpscnt,str1);
3833 char *p = skip_string(param,tpscnt,str2);
3834 char* PrinterName = p;
3836 struct pack_desc desc;
3840 if (!str1 || !str2 || !p) {
3844 memset((char *)&desc,'\0',sizeof(desc));
3846 p = skip_string(param,tpscnt,p);
3850 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3852 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3854 /* check it's a supported varient */
3855 if (strcmp(str1,"zWrLh") != 0) {
3858 if (!check_printdest_info(&desc,uLevel,str2)) {
3862 snum = find_service(PrinterName);
3863 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3865 desc.errcode = NERR_DestNotFound;
3869 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3874 desc.buflen = mdrcnt;
3877 * Don't return data but need to get correct length
3878 * init_package will return wrong size if buflen=0
3880 desc.buflen = getlen(desc.format);
3881 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3883 if (init_package(&desc,1,0)) {
3884 fill_printdest_info(conn,snum,uLevel,&desc);
3886 *rdata_len = desc.usedlen;
3890 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3894 SSVALS(*rparam,0,desc.errcode);
3896 SSVAL(*rparam,4,desc.neededlen);
3898 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3904 static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
3905 char *param, int tpscnt,
3906 char *data, int tdscnt,
3907 int mdrcnt,int mprcnt,
3908 char **rdata,char **rparam,
3909 int *rdata_len,int *rparam_len)
3911 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3912 char *str2 = skip_string(param,tpscnt,str1);
3913 char *p = skip_string(param,tpscnt,str2);
3917 struct pack_desc desc;
3918 int services = lp_numservices();
3920 if (!str1 || !str2 || !p) {
3924 memset((char *)&desc,'\0',sizeof(desc));
3926 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3928 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3930 /* check it's a supported varient */
3931 if (strcmp(str1,"WrLeh") != 0) {
3934 if (!check_printdest_info(&desc,uLevel,str2)) {
3939 for (i = 0; i < services; i++) {
3940 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3946 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3953 desc.buflen = mdrcnt;
3954 if (init_package(&desc,queuecnt,0)) {
3957 for (i = 0; i < services; i++) {
3958 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3959 fill_printdest_info(conn,i,uLevel,&desc);
3961 if (desc.errcode == NERR_Success) {
3968 *rdata_len = desc.usedlen;
3971 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3975 SSVALS(*rparam,0,desc.errcode);
3977 SSVAL(*rparam,4,succnt);
3978 SSVAL(*rparam,6,queuecnt);
3980 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3985 static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
3986 char *param, int tpscnt,
3987 char *data, int tdscnt,
3988 int mdrcnt,int mprcnt,
3989 char **rdata,char **rparam,
3990 int *rdata_len,int *rparam_len)
3992 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3993 char *str2 = skip_string(param,tpscnt,str1);
3994 char *p = skip_string(param,tpscnt,str2);
3997 struct pack_desc desc;
3999 if (!str1 || !str2 || !p) {
4003 memset((char *)&desc,'\0',sizeof(desc));
4005 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4007 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4009 /* check it's a supported varient */
4010 if (strcmp(str1,"WrLeh") != 0) {
4013 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4018 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4024 desc.buflen = mdrcnt;
4025 if (init_package(&desc,1,0)) {
4026 PACKS(&desc,"B41","NULL");
4029 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4031 *rdata_len = desc.usedlen;
4034 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4038 SSVALS(*rparam,0,desc.errcode);
4040 SSVAL(*rparam,4,succnt);
4043 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4048 static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4049 char *param, int tpscnt,
4050 char *data, int tdscnt,
4051 int mdrcnt,int mprcnt,
4052 char **rdata,char **rparam,
4053 int *rdata_len,int *rparam_len)
4055 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4056 char *str2 = skip_string(param,tpscnt,str1);
4057 char *p = skip_string(param,tpscnt,str2);
4060 struct pack_desc desc;
4062 if (!str1 || !str2 || !p) {
4065 memset((char *)&desc,'\0',sizeof(desc));
4067 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4069 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4071 /* check it's a supported varient */
4072 if (strcmp(str1,"WrLeh") != 0) {
4075 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4080 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4086 desc.buflen = mdrcnt;
4088 if (init_package(&desc,1,0)) {
4089 PACKS(&desc,"B13","lpd");
4092 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4094 *rdata_len = desc.usedlen;
4097 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4101 SSVALS(*rparam,0,desc.errcode);
4103 SSVAL(*rparam,4,succnt);
4106 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4111 static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4112 char *param, int tpscnt,
4113 char *data, int tdscnt,
4114 int mdrcnt,int mprcnt,
4115 char **rdata,char **rparam,
4116 int *rdata_len,int *rparam_len)
4118 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4119 char *str2 = skip_string(param,tpscnt,str1);
4120 char *p = skip_string(param,tpscnt,str2);
4123 struct pack_desc desc;
4125 if (!str1 || !str2 || !p) {
4129 memset((char *)&desc,'\0',sizeof(desc));
4131 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4133 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4135 /* check it's a supported varient */
4136 if (strcmp(str1,"WrLeh") != 0) {
4139 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4144 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4149 memset((char *)&desc,'\0',sizeof(desc));
4151 desc.buflen = mdrcnt;
4153 if (init_package(&desc,1,0)) {
4154 PACKS(&desc,"B13","lp0");
4157 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4159 *rdata_len = desc.usedlen;
4162 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4166 SSVALS(*rparam,0,desc.errcode);
4168 SSVAL(*rparam,4,succnt);
4171 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4176 /****************************************************************************
4178 ****************************************************************************/
4180 static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4181 char *param, int tpscnt,
4182 char *data, int tdscnt,
4183 int mdrcnt,int mprcnt,
4184 char **rdata,char **rparam,
4185 int *rdata_len,int *rparam_len)
4188 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4189 char *str2 = skip_string(param,tpscnt,str1);
4190 char *p = skip_string(param,tpscnt,str2);
4192 struct pack_desc desc;
4193 struct sessionid *session_list;
4194 int i, num_sessions;
4196 if (!str1 || !str2 || !p) {
4200 memset((char *)&desc,'\0',sizeof(desc));
4202 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4204 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4205 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4206 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4208 /* check it's a supported varient */
4209 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4212 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4216 num_sessions = list_sessions(&session_list);
4219 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4224 memset((char *)&desc,'\0',sizeof(desc));
4226 desc.buflen = mdrcnt;
4228 if (!init_package(&desc,num_sessions,0)) {
4232 for(i=0; i<num_sessions; i++) {
4233 PACKS(&desc, "z", session_list[i].remote_machine);
4234 PACKS(&desc, "z", session_list[i].username);
4235 PACKI(&desc, "W", 1); /* num conns */
4236 PACKI(&desc, "W", 0); /* num opens */
4237 PACKI(&desc, "W", 1); /* num users */
4238 PACKI(&desc, "D", 0); /* session time */
4239 PACKI(&desc, "D", 0); /* idle time */
4240 PACKI(&desc, "D", 0); /* flags */
4241 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4244 *rdata_len = desc.usedlen;
4247 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4251 SSVALS(*rparam,0,desc.errcode);
4252 SSVAL(*rparam,2,0); /* converter */
4253 SSVAL(*rparam,4,num_sessions); /* count */
4255 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4261 /****************************************************************************
4262 The buffer was too small.
4263 ****************************************************************************/
4265 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4266 int mdrcnt, int mprcnt,
4267 char **rdata, char **rparam,
4268 int *rdata_len, int *rparam_len)
4270 *rparam_len = MIN(*rparam_len,mprcnt);
4271 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4278 SSVAL(*rparam,0,NERR_BufTooSmall);
4280 DEBUG(3,("Supplied buffer too small in API command\n"));
4285 /****************************************************************************
4286 The request is not supported.
4287 ****************************************************************************/
4289 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
4290 char *param, int tpscnt,
4291 char *data, int tdscnt,
4292 int mdrcnt, int mprcnt,
4293 char **rdata, char **rparam,
4294 int *rdata_len, int *rparam_len)
4297 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4304 SSVAL(*rparam,0,NERR_notsupported);
4305 SSVAL(*rparam,2,0); /* converter word */
4307 DEBUG(3,("Unsupported API command\n"));
4312 static const struct {
4315 BOOL (*fn)(connection_struct *, uint16,
4318 int,int,char **,char **,int *,int *);
4319 BOOL auth_user; /* Deny anonymous access? */
4320 } api_commands[] = {
4321 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4322 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4323 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4324 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4325 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4326 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4327 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4328 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4329 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4330 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4331 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4332 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4333 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4334 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4335 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4336 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4337 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4338 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4339 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4340 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4341 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4342 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4343 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4344 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4345 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4346 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4347 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4348 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4349 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4350 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4351 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4352 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4353 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4354 {NULL, -1, api_Unsupported}
4355 /* The following RAP calls are not implemented by Samba:
4357 RAP_WFileEnum2 - anon not OK
4362 /****************************************************************************
4363 Handle remote api calls.
4364 ****************************************************************************/
4366 int api_reply(connection_struct *conn,
4379 char *rparam = NULL;
4380 const char *name1 = NULL;
4381 const char *name2 = NULL;
4388 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4395 api_command = SVAL(params,0);
4396 /* Is there a string at position params+2 ? */
4397 if (skip_string(params,tpscnt,params+2)) {
4402 name2 = skip_string(params,tpscnt,params+2);
4407 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4411 tdscnt,tpscnt,mdrcnt,mprcnt));
4413 for (i=0;api_commands[i].name;i++) {
4414 if (api_commands[i].id == api_command && api_commands[i].fn) {
4415 DEBUG(3,("Doing %s\n",api_commands[i].name));
4420 /* Check whether this api call can be done anonymously */
4422 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4423 user_struct *user = get_valid_user_struct(vuid);
4425 if (!user || user->guest) {
4426 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4430 rdata = (char *)SMB_MALLOC(1024);
4432 memset(rdata,'\0',1024);
4435 rparam = (char *)SMB_MALLOC(1024);
4437 memset(rparam,'\0',1024);
4440 if(!rdata || !rparam) {
4441 DEBUG(0,("api_reply: malloc fail !\n"));
4447 reply = api_commands[i].fn(conn,
4449 params,tpscnt, /* params + length */
4450 data,tdscnt, /* data + length */
4452 &rdata,&rparam,&rdata_len,&rparam_len);
4455 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4456 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4457 &rdata,&rparam,&rdata_len,&rparam_len);
4460 /* if we get False back then it's actually unsupported */
4462 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4463 &rdata,&rparam,&rdata_len,&rparam_len);
4466 /* If api_Unsupported returns false we can't return anything. */
4468 send_trans_reply(inbuf,