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";
446 if (strcmp(desc->format,id1) != 0) {
449 if (desc->subformat && strcmp(desc->subformat,id2) != 0) {
456 #define RAP_JOB_STATUS_QUEUED 0
457 #define RAP_JOB_STATUS_PAUSED 1
458 #define RAP_JOB_STATUS_SPOOLING 2
459 #define RAP_JOB_STATUS_PRINTING 3
460 #define RAP_JOB_STATUS_PRINTED 4
462 #define RAP_QUEUE_STATUS_PAUSED 1
463 #define RAP_QUEUE_STATUS_ERROR 2
465 /* turn a print job status into a on the wire status
467 static int printj_status(int v)
471 return RAP_JOB_STATUS_QUEUED;
473 return RAP_JOB_STATUS_PAUSED;
475 return RAP_JOB_STATUS_SPOOLING;
477 return RAP_JOB_STATUS_PRINTING;
482 /* turn a print queue status into a on the wire status
484 static int printq_status(int v)
490 return RAP_QUEUE_STATUS_PAUSED;
492 return RAP_QUEUE_STATUS_ERROR;
495 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
496 struct pack_desc *desc,
497 print_queue_struct *queue, int n)
499 time_t t = queue->time;
501 /* the client expects localtime */
502 t -= get_time_zone(t);
504 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
506 PACKS(desc,"B21",queue->fs_user); /* szUserName */
507 PACKS(desc,"B",""); /* pad */
508 PACKS(desc,"B16",""); /* szNotifyName */
509 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
510 PACKS(desc,"z",""); /* pszParms */
511 PACKI(desc,"W",n+1); /* uPosition */
512 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
513 PACKS(desc,"z",""); /* pszStatus */
514 PACKI(desc,"D",t); /* ulSubmitted */
515 PACKI(desc,"D",queue->size); /* ulSize */
516 PACKS(desc,"z",queue->fs_file); /* pszComment */
518 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
519 PACKI(desc,"W",queue->priority); /* uPriority */
520 PACKS(desc,"z",queue->fs_user); /* pszUserName */
521 PACKI(desc,"W",n+1); /* uPosition */
522 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
523 PACKI(desc,"D",t); /* ulSubmitted */
524 PACKI(desc,"D",queue->size); /* ulSize */
525 PACKS(desc,"z","Samba"); /* pszComment */
526 PACKS(desc,"z",queue->fs_file); /* pszDocument */
528 PACKS(desc,"z",""); /* pszNotifyName */
529 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
530 PACKS(desc,"z",""); /* pszParms */
531 PACKS(desc,"z",""); /* pszStatus */
532 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
533 PACKS(desc,"z","lpd"); /* pszQProcName */
534 PACKS(desc,"z",""); /* pszQProcParms */
535 PACKS(desc,"z","NULL"); /* pszDriverName */
536 PackDriverData(desc); /* pDriverData */
537 PACKS(desc,"z",""); /* pszPrinterName */
538 } else if (uLevel == 4) { /* OS2 */
539 PACKS(desc,"z",""); /* pszSpoolFileName */
540 PACKS(desc,"z",""); /* pszPortName */
541 PACKS(desc,"z",""); /* pszStatus */
542 PACKI(desc,"D",0); /* ulPagesSpooled */
543 PACKI(desc,"D",0); /* ulPagesSent */
544 PACKI(desc,"D",0); /* ulPagesPrinted */
545 PACKI(desc,"D",0); /* ulTimePrinted */
546 PACKI(desc,"D",0); /* ulExtendJobStatus */
547 PACKI(desc,"D",0); /* ulStartPage */
548 PACKI(desc,"D",0); /* ulEndPage */
553 /********************************************************************
554 Return a driver name given an snum.
555 Returns True if from tdb, False otherwise.
556 ********************************************************************/
558 static BOOL get_driver_name(int snum, pstring drivername)
560 NT_PRINTER_INFO_LEVEL *info = NULL;
563 get_a_printer (NULL, &info, 2, lp_servicename(snum));
565 pstrcpy( drivername, info->info_2->drivername);
567 free_a_printer(&info, 2);
573 /********************************************************************
574 Respond to the DosPrintQInfo command with a level of 52
575 This is used to get printer driver information for Win9x clients
576 ********************************************************************/
577 static void fill_printq_info_52(connection_struct *conn, int snum,
578 struct pack_desc* desc, int count )
582 NT_PRINTER_DRIVER_INFO_LEVEL driver;
583 NT_PRINTER_INFO_LEVEL *printer = NULL;
587 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
588 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
589 lp_servicename(snum)));
593 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
596 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
597 printer->info_2->drivername));
601 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
602 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
603 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
605 PACKI(desc, "W", 0x0400); /* don't know */
606 PACKS(desc, "z", driver.info_3->name); /* long printer name */
607 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
608 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
609 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
611 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
612 standard_sub_basic( "", "", location, sizeof(location)-1 );
613 PACKS(desc,"z", location); /* share to retrieve files */
615 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
616 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
617 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
619 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
620 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
621 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
622 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
623 DEBUG(3,("Driver Location: %s:\n",location));
624 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
625 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
626 PACKI(desc,"N",count); /* number of files to copy */
628 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
630 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
631 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
632 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
637 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
640 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
642 desc->errcode=NERR_Success;
646 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
647 desc->errcode=NERR_notsupported;
651 free_a_printer( &printer, 2 );
654 free_a_printer_driver( driver, 3 );
658 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
659 struct pack_desc* desc,
660 int count, print_queue_struct* queue,
661 print_status_struct* status)
666 PACKS(desc,"B13",SERVICE(snum));
671 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
674 PACKI(desc,"K",printq_status(status->status));
678 if (uLevel == 1 || uLevel == 2) {
679 PACKS(desc,"B",""); /* alignment */
680 PACKI(desc,"W",5); /* priority */
681 PACKI(desc,"W",0); /* start time */
682 PACKI(desc,"W",0); /* until time */
683 PACKS(desc,"z",""); /* pSepFile */
684 PACKS(desc,"z","lpd"); /* pPrProc */
685 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
686 PACKS(desc,"z",""); /* pParms */
688 PACKS(desc,"z","UNKNOWN PRINTER");
689 PACKI(desc,"W",LPSTAT_ERROR);
691 else if (!status || !status->message[0]) {
692 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
693 PACKI(desc,"W",LPSTAT_OK); /* status */
695 PACKS(desc,"z",status->message);
696 PACKI(desc,"W",printq_status(status->status)); /* status */
698 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
701 if (uLevel == 3 || uLevel == 4) {
704 PACKI(desc,"W",5); /* uPriority */
705 PACKI(desc,"W",0); /* uStarttime */
706 PACKI(desc,"W",0); /* uUntiltime */
707 PACKI(desc,"W",5); /* pad1 */
708 PACKS(desc,"z",""); /* pszSepFile */
709 PACKS(desc,"z","WinPrint"); /* pszPrProc */
710 PACKS(desc,"z",NULL); /* pszParms */
711 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
712 /* "don't ask" that it's done this way to fix corrupted
713 Win9X/ME printer comments. */
715 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
717 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
719 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
720 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
721 get_driver_name(snum,drivername);
722 PACKS(desc,"z",drivername); /* pszDriverName */
723 PackDriverData(desc); /* pDriverData */
726 if (uLevel == 2 || uLevel == 4) {
728 for (i=0;i<count;i++)
729 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
733 fill_printq_info_52( conn, snum, desc, count );
736 /* This function returns the number of files for a given driver */
737 static int get_printerdrivernumber(int snum)
740 NT_PRINTER_DRIVER_INFO_LEVEL driver;
741 NT_PRINTER_INFO_LEVEL *printer = NULL;
745 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
746 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
747 lp_servicename(snum)));
751 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
754 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
755 printer->info_2->drivername));
759 /* count the number of files */
760 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
765 free_a_printer( &printer, 2 );
768 free_a_printer_driver( driver, 3 );
773 static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
774 char *param, int tpscnt,
775 char *data, int tdscnt,
776 int mdrcnt,int mprcnt,
777 char **rdata,char **rparam,
778 int *rdata_len,int *rparam_len)
780 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
781 char *str2 = skip_string(param,tpscnt,str1,1);
782 char *p = skip_string(param,tpscnt,str2,1);
788 struct pack_desc desc;
789 print_queue_struct *queue=NULL;
790 print_status_struct status;
793 if (!str1 || !str2 || !p) {
796 memset((char *)&status,'\0',sizeof(status));
797 memset((char *)&desc,'\0',sizeof(desc));
799 p = skip_string(param,tpscnt,p,1);
803 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
804 str3 = get_safe_str_ptr(param,tpscnt,p,4);
809 /* remove any trailing username */
810 if ((p = strchr_m(QueueName,'%')))
813 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
815 /* check it's a supported varient */
816 if (!prefix_ok(str1,"zWrLh"))
818 if (!check_printq_info(&desc,uLevel,str2,str3)) {
820 * Patch from Scott Moomaw <scott@bridgewater.edu>
821 * to return the 'invalid info level' error if an
822 * unknown level was requested.
826 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
830 SSVALS(*rparam,0,ERRunknownlevel);
836 snum = find_service(QueueName);
837 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
841 count = get_printerdrivernumber(snum);
842 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
844 count = print_queue_status(snum, &queue,&status);
848 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
853 desc.buflen = mdrcnt;
856 * Don't return data but need to get correct length
857 * init_package will return wrong size if buflen=0
859 desc.buflen = getlen(desc.format);
860 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
863 if (init_package(&desc,1,count)) {
864 desc.subcount = count;
865 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
868 *rdata_len = desc.usedlen;
871 * We must set the return code to ERRbuftoosmall
872 * in order to support lanman style printing with Win NT/2k
875 if (!mdrcnt && lp_disable_spoolss())
876 desc.errcode = ERRbuftoosmall;
878 *rdata_len = desc.usedlen;
880 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
884 SSVALS(*rparam,0,desc.errcode);
886 SSVAL(*rparam,4,desc.neededlen);
888 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
896 /****************************************************************************
897 View list of all print jobs on all queues.
898 ****************************************************************************/
900 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
901 char *param, int tpscnt,
902 char *data, int tdscnt,
903 int mdrcnt, int mprcnt,
904 char **rdata, char** rparam,
905 int *rdata_len, int *rparam_len)
907 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
908 char *output_format1 = skip_string(param,tpscnt,param_format,1);
909 char *p = skip_string(param,tpscnt,output_format1,1);
910 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
911 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
912 int services = lp_numservices();
914 struct pack_desc desc;
915 print_queue_struct **queue = NULL;
916 print_status_struct *status = NULL;
917 int *subcntarr = NULL;
918 int queuecnt = 0, subcnt = 0, succnt = 0;
920 if (!param_format || !output_format1 || !p || !output_format2) {
925 output_format2 = p + 4;
927 memset((char *)&desc,'\0',sizeof(desc));
929 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
931 if (!prefix_ok(param_format,"WrLeh")) {
934 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
936 * Patch from Scott Moomaw <scott@bridgewater.edu>
937 * to return the 'invalid info level' error if an
938 * unknown level was requested.
942 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
946 SSVALS(*rparam,0,ERRunknownlevel);
952 for (i = 0; i < services; i++) {
953 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
958 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
959 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
962 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
963 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
964 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
967 memset(status,0,queuecnt*sizeof(print_status_struct));
968 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
969 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
975 for (i = 0; i < services; i++) {
976 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
977 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
978 subcnt += subcntarr[n];
984 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
990 desc.buflen = mdrcnt;
992 if (init_package(&desc,queuecnt,subcnt)) {
995 for (i = 0; i < services; i++) {
996 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
997 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
999 if (desc.errcode == NERR_Success) {
1006 SAFE_FREE(subcntarr);
1008 *rdata_len = desc.usedlen;
1010 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1014 SSVALS(*rparam,0,desc.errcode);
1016 SSVAL(*rparam,4,succnt);
1017 SSVAL(*rparam,6,queuecnt);
1019 for (i = 0; i < queuecnt; i++) {
1021 SAFE_FREE(queue[i]);
1032 SAFE_FREE(subcntarr);
1033 for (i = 0; i < queuecnt; i++) {
1035 SAFE_FREE(queue[i]);
1044 /****************************************************************************
1045 Get info level for a server list query.
1046 ****************************************************************************/
1048 static BOOL check_server_info(int uLevel, char* id)
1052 if (strcmp(id,"B16") != 0) {
1057 if (strcmp(id,"B16BBDz") != 0) {
1067 struct srv_info_struct {
1075 /*******************************************************************
1076 Get server info lists from the files saved by nmbd. Return the
1078 ******************************************************************/
1080 static int get_server_info(uint32 servertype,
1081 struct srv_info_struct **servers,
1087 BOOL local_list_only;
1090 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1092 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1096 /* request for everything is code for request all servers */
1097 if (servertype == SV_TYPE_ALL) {
1098 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1101 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1103 DEBUG(4,("Servertype search: %8x\n",servertype));
1105 for (i=0;lines[i];i++) {
1107 struct srv_info_struct *s;
1108 const char *ptr = lines[i];
1115 if (count == alloced) {
1117 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1119 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1120 file_lines_free(lines);
1123 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1125 s = &(*servers)[count];
1127 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1130 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1133 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1136 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1137 /* this allows us to cope with an old nmbd */
1138 fstrcpy(s->domain,lp_workgroup());
1141 if (sscanf(stype,"%X",&s->type) != 1) {
1142 DEBUG(4,("r:host file "));
1146 /* Filter the servers/domains we return based on what was asked for. */
1148 /* Check to see if we are being asked for a local list only. */
1149 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1150 DEBUG(4,("r: local list only"));
1154 /* doesn't match up: don't want it */
1155 if (!(servertype & s->type)) {
1156 DEBUG(4,("r:serv type "));
1160 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1161 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1162 DEBUG(4,("s: dom mismatch "));
1166 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1170 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1171 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1174 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1175 s->name, s->type, s->comment, s->domain));
1176 s->server_added = True;
1179 DEBUG(4,("%20s %8x %25s %15s\n",
1180 s->name, s->type, s->comment, s->domain));
1184 file_lines_free(lines);
1188 /*******************************************************************
1189 Fill in a server info structure.
1190 ******************************************************************/
1192 static int fill_srv_info(struct srv_info_struct *service,
1193 int uLevel, char **buf, int *buflen,
1194 char **stringbuf, int *stringspace, char *baseaddr)
1217 len = strlen(service->comment)+1;
1221 *buflen = struct_len;
1223 return struct_len + len;
1228 if (*buflen < struct_len) {
1235 p2 = p + struct_len;
1236 l2 = *buflen - struct_len;
1244 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1248 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1249 SIVAL(p,18,service->type);
1250 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1251 len += CopyAndAdvance(&p2,service->comment,&l2);
1256 *buf = p + struct_len;
1257 *buflen -= struct_len;
1268 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1270 return(strcmp(s1->name,s2->name));
1273 /****************************************************************************
1274 View list of servers available (or possibly domains). The info is
1275 extracted from lists saved by nmbd on the local host.
1276 ****************************************************************************/
1278 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1279 char *param, int tpscnt,
1280 char *data, int tdscnt,
1281 int mdrcnt, int mprcnt, char **rdata,
1282 char **rparam, int *rdata_len, int *rparam_len)
1284 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1285 char *str2 = skip_string(param,tpscnt,str1,1);
1286 char *p = skip_string(param,tpscnt,str2,1);
1287 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1288 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1289 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1291 int data_len, fixed_len, string_len;
1292 int f_len = 0, s_len = 0;
1293 struct srv_info_struct *servers=NULL;
1294 int counted=0,total=0;
1297 BOOL domain_request;
1300 if (!str1 || !str2 || !p) {
1304 /* If someone sets all the bits they don't really mean to set
1305 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1308 if (servertype == SV_TYPE_ALL) {
1309 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1312 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1313 any other bit (they may just set this bit on it's own) they
1314 want all the locally seen servers. However this bit can be
1315 set on its own so set the requested servers to be
1316 ALL - DOMAIN_ENUM. */
1318 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1319 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1322 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1323 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1327 if (!prefix_ok(str1,"WrLehD")) {
1330 if (!check_server_info(uLevel,str2)) {
1334 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1335 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1336 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1338 if (strcmp(str1, "WrLehDz") == 0) {
1339 if (skip_string(param,tpscnt,p,1) == NULL) {
1342 pull_ascii_fstring(domain, p);
1344 fstrcpy(domain, lp_workgroup());
1347 if (lp_browse_list()) {
1348 total = get_server_info(servertype,&servers,domain);
1351 data_len = fixed_len = string_len = 0;
1355 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1359 char *lastname=NULL;
1361 for (i=0;i<total;i++) {
1362 struct srv_info_struct *s = &servers[i];
1364 if (lastname && strequal(lastname,s->name)) {
1368 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1369 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1370 s->name, s->type, s->comment, s->domain));
1372 if (data_len <= buf_len) {
1375 string_len += s_len;
1382 *rdata_len = fixed_len + string_len;
1383 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1387 memset(*rdata,'\0',*rdata_len);
1389 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1395 char *lastname=NULL;
1396 int count2 = counted;
1398 for (i = 0; i < total && count2;i++) {
1399 struct srv_info_struct *s = &servers[i];
1401 if (lastname && strequal(lastname,s->name)) {
1405 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1406 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1407 s->name, s->type, s->comment, s->domain));
1413 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1417 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1419 SSVAL(*rparam,4,counted);
1420 SSVAL(*rparam,6,counted+missed);
1424 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1425 domain,uLevel,counted,counted+missed));
1430 /****************************************************************************
1431 command 0x34 - suspected of being a "Lookup Names" stub api
1432 ****************************************************************************/
1434 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1435 char *param, int tpscnt,
1436 char *data, int tdscnt,
1437 int mdrcnt, int mprcnt, char **rdata,
1438 char **rparam, int *rdata_len, int *rparam_len)
1440 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1441 char *str2 = skip_string(param,tpscnt,str1,1);
1442 char *p = skip_string(param,tpscnt,str2,1);
1443 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1444 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1448 if (!str1 || !str2 || !p) {
1452 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1453 str1, str2, p, uLevel, buf_len));
1455 if (!prefix_ok(str1,"zWrLeh")) {
1462 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1467 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1469 SSVAL(*rparam,4,counted);
1470 SSVAL(*rparam,6,counted+missed);
1475 /****************************************************************************
1476 get info about a share
1477 ****************************************************************************/
1479 static BOOL check_share_info(int uLevel, char* id)
1483 if (strcmp(id,"B13") != 0) {
1488 if (strcmp(id,"B13BWz") != 0) {
1493 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1498 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1508 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1509 char** buf, int* buflen,
1510 char** stringbuf, int* stringspace, char* baseaddr)
1540 len += StrlenExpanded(conn,snum,lp_comment(snum));
1543 len += strlen(lp_pathname(snum)) + 1;
1546 *buflen = struct_len;
1551 return struct_len + len;
1556 if ((*buflen) < struct_len) {
1564 p2 = p + struct_len;
1565 l2 = (*buflen) - struct_len;
1572 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1578 type = STYPE_DISKTREE;
1579 if (lp_print_ok(snum)) {
1580 type = STYPE_PRINTQ;
1582 if (strequal("IPC",lp_fstype(snum))) {
1585 SSVAL(p,14,type); /* device type */
1586 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1587 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1591 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1592 SSVALS(p,22,-1); /* max uses */
1593 SSVAL(p,24,1); /* current uses */
1594 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1595 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1596 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1600 memset(p+40,0,SHPWLEN+2);
1611 (*buf) = p + struct_len;
1612 (*buflen) -= struct_len;
1614 (*stringspace) = l2;
1623 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1624 char *param, int tpscnt,
1625 char *data, int tdscnt,
1626 int mdrcnt,int mprcnt,
1627 char **rdata,char **rparam,
1628 int *rdata_len,int *rparam_len)
1630 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1631 char *str2 = skip_string(param,tpscnt,str1,1);
1632 char *netname = skip_string(param,tpscnt,str2,1);
1633 char *p = skip_string(param,tpscnt,netname,1);
1634 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1637 if (!str1 || !str2 || !netname || !p) {
1641 snum = find_service(netname);
1646 /* check it's a supported varient */
1647 if (!prefix_ok(str1,"zWrLh")) {
1650 if (!check_share_info(uLevel,str2)) {
1654 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1659 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1660 if (*rdata_len < 0) {
1665 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1669 SSVAL(*rparam,0,NERR_Success);
1670 SSVAL(*rparam,2,0); /* converter word */
1671 SSVAL(*rparam,4,*rdata_len);
1676 /****************************************************************************
1677 View the list of available shares.
1679 This function is the server side of the NetShareEnum() RAP call.
1680 It fills the return buffer with share names and share comments.
1681 Note that the return buffer normally (in all known cases) allows only
1682 twelve byte strings for share names (plus one for a nul terminator).
1683 Share names longer than 12 bytes must be skipped.
1684 ****************************************************************************/
1686 static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1687 char *param, int tpscnt,
1688 char *data, int tdscnt,
1696 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1697 char *str2 = skip_string(param,tpscnt,str1,1);
1698 char *p = skip_string(param,tpscnt,str2,1);
1699 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1700 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1703 int total=0,counted=0;
1704 BOOL missed = False;
1706 int data_len, fixed_len, string_len;
1707 int f_len = 0, s_len = 0;
1709 if (!str1 || !str2 || !p) {
1713 if (!prefix_ok(str1,"WrLeh")) {
1716 if (!check_share_info(uLevel,str2)) {
1720 /* Ensure all the usershares are loaded. */
1722 load_registry_shares();
1723 count = load_usershare_shares();
1726 data_len = fixed_len = string_len = 0;
1727 for (i=0;i<count;i++) {
1728 fstring servicename_dos;
1729 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1732 push_ascii_fstring(servicename_dos, lp_servicename(i));
1733 /* Maximum name length = 13. */
1734 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1736 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1737 if (data_len <= buf_len) {
1740 string_len += s_len;
1747 *rdata_len = fixed_len + string_len;
1748 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1752 memset(*rdata,0,*rdata_len);
1754 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1759 for( i = 0; i < count; i++ ) {
1760 fstring servicename_dos;
1761 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1765 push_ascii_fstring(servicename_dos, lp_servicename(i));
1766 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1767 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1774 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1778 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1780 SSVAL(*rparam,4,counted);
1781 SSVAL(*rparam,6,total);
1783 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1784 counted,total,uLevel,
1785 buf_len,*rdata_len,mdrcnt));
1790 /****************************************************************************
1792 ****************************************************************************/
1794 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1795 char *param, int tpscnt,
1796 char *data, int tdscnt,
1797 int mdrcnt,int mprcnt,
1798 char **rdata,char **rparam,
1799 int *rdata_len,int *rparam_len)
1801 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1802 char *str2 = skip_string(param,tpscnt,str1,1);
1803 char *p = skip_string(param,tpscnt,str2,1);
1804 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1808 char *command, *cmdname;
1809 unsigned int offset;
1813 if (!str1 || !str2 || !p) {
1817 /* check it's a supported varient */
1818 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1821 if (!check_share_info(uLevel,str2)) {
1828 /* Do we have a string ? */
1829 if (skip_string(data,mdrcnt,data,1) == NULL) {
1832 pull_ascii_fstring(sharename,data);
1833 snum = find_service(sharename);
1834 if (snum >= 0) { /* already exists */
1843 /* only support disk share adds */
1844 if (SVAL(data,14)!=STYPE_DISKTREE) {
1848 offset = IVAL(data, 16);
1849 if (offset >= mdrcnt) {
1850 res = ERRinvalidparam;
1854 /* Do we have a string ? */
1855 if (skip_string(data,mdrcnt,data+offset,1) == NULL) {
1858 pull_ascii_fstring(comment, offset? (data+offset) : "");
1860 offset = IVAL(data, 26);
1862 if (offset >= mdrcnt) {
1863 res = ERRinvalidparam;
1867 /* Do we have a string ? */
1868 if (skip_string(data,mdrcnt,data+offset,1) == NULL) {
1871 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1873 string_replace(sharename, '"', ' ');
1874 string_replace(pathname, '"', ' ');
1875 string_replace(comment, '"', ' ');
1877 cmdname = lp_add_share_cmd();
1879 if (!cmdname || *cmdname == '\0') {
1883 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1884 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1887 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1889 if ((res = smbrun(command, NULL)) != 0) {
1890 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1896 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1903 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1907 SSVAL(*rparam,0,NERR_Success);
1908 SSVAL(*rparam,2,0); /* converter word */
1909 SSVAL(*rparam,4,*rdata_len);
1917 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1922 SSVAL(*rparam,0,res);
1927 /****************************************************************************
1928 view list of groups available
1929 ****************************************************************************/
1931 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
1932 char *param, int tpscnt,
1933 char *data, int tdscnt,
1934 int mdrcnt,int mprcnt,
1935 char **rdata,char **rparam,
1936 int *rdata_len,int *rparam_len)
1940 int resume_context, cli_buf_size;
1941 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1942 char *str2 = skip_string(param,tpscnt,str1,1);
1943 char *p = skip_string(param,tpscnt,str2,1);
1945 struct pdb_search *search;
1946 struct samr_displayentry *entries;
1950 if (!str1 || !str2 || !p) {
1954 if (strcmp(str1,"WrLeh") != 0) {
1959 * W-> resume context (number of users to skip)
1960 * r -> return parameter pointer to receive buffer
1961 * L -> length of receive buffer
1962 * e -> return parameter number of entries
1963 * h -> return parameter total number of users
1966 if (strcmp("B21",str2) != 0) {
1970 /* get list of domain groups SID_DOMAIN_GRP=2 */
1972 search = pdb_search_groups();
1975 if (search == NULL) {
1976 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1980 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
1981 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
1982 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1983 "%d\n", resume_context, cli_buf_size));
1986 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1990 *rdata_len = cli_buf_size;
1991 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1998 for(i=0; i<num_entries; i++) {
2000 fstrcpy(name, entries[i].account_name);
2001 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2002 /* truncate the name at 21 chars. */
2003 memcpy(p, name, 21);
2004 DEBUG(10,("adding entry %d group %s\n", i, p));
2006 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2009 /* set overflow error */
2010 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2016 pdb_search_destroy(search);
2018 *rdata_len = PTR_DIFF(p,*rdata);
2021 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2025 SSVAL(*rparam, 0, errflags);
2026 SSVAL(*rparam, 2, 0); /* converter word */
2027 SSVAL(*rparam, 4, i); /* is this right?? */
2028 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2033 /*******************************************************************
2034 Get groups that a user is a member of.
2035 ******************************************************************/
2037 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2038 char *param, int tpscnt,
2039 char *data, int tdscnt,
2040 int mdrcnt,int mprcnt,
2041 char **rdata,char **rparam,
2042 int *rdata_len,int *rparam_len)
2044 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2045 char *str2 = skip_string(param,tpscnt,str1,1);
2046 char *UserName = skip_string(param,tpscnt,str2,1);
2047 char *p = skip_string(param,tpscnt,UserName,1);
2048 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2049 const char *level_string;
2051 struct samu *sampw = NULL;
2059 enum lsa_SidType type;
2060 TALLOC_CTX *mem_ctx;
2062 if (!str1 || !str2 || !UserName || !p) {
2067 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2072 /* check it's a supported varient */
2074 if ( strcmp(str1,"zWrLeh") != 0 )
2079 level_string = "B21";
2085 if (strcmp(level_string,str2) != 0)
2088 *rdata_len = mdrcnt + 1024;
2089 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2093 SSVAL(*rparam,0,NERR_Success);
2094 SSVAL(*rparam,2,0); /* converter word */
2098 mem_ctx = talloc_new(NULL);
2099 if (mem_ctx == NULL) {
2100 DEBUG(0, ("talloc_new failed\n"));
2104 if ( !(sampw = samu_new(mem_ctx)) ) {
2105 DEBUG(0, ("samu_new() failed!\n"));
2106 TALLOC_FREE(mem_ctx);
2110 /* Lookup the user information; This should only be one of
2111 our accounts (not remote domains) */
2113 become_root(); /* ROOT BLOCK */
2115 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2116 NULL, NULL, &user_sid, &type)) {
2117 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2121 if (type != SID_NAME_USER) {
2122 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2123 sid_type_lookup(type)));
2127 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2128 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2129 sid_string_static(&user_sid), UserName));
2137 result = pdb_enum_group_memberships(mem_ctx, sampw,
2138 &sids, &gids, &num_groups);
2140 if (!NT_STATUS_IS_OK(result)) {
2141 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2146 for (i=0; i<num_groups; i++) {
2148 const char *grp_name;
2150 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2151 pstrcpy(p, grp_name);
2157 *rdata_len = PTR_DIFF(p,*rdata);
2159 SSVAL(*rparam,4,count); /* is this right?? */
2160 SSVAL(*rparam,6,count); /* is this right?? */
2165 unbecome_root(); /* END ROOT BLOCK */
2167 TALLOC_FREE(mem_ctx);
2172 /*******************************************************************
2174 ******************************************************************/
2176 static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2177 char *param, int tpscnt,
2178 char *data, int tdscnt,
2179 int mdrcnt,int mprcnt,
2180 char **rdata,char **rparam,
2181 int *rdata_len,int *rparam_len)
2186 int i, resume_context, cli_buf_size;
2187 struct pdb_search *search;
2188 struct samr_displayentry *users;
2190 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2191 char *str2 = skip_string(param,tpscnt,str1,1);
2192 char *p = skip_string(param,tpscnt,str2,1);
2194 if (!str1 || !str2 || !p) {
2198 if (strcmp(str1,"WrLeh") != 0)
2201 * W-> resume context (number of users to skip)
2202 * r -> return parameter pointer to receive buffer
2203 * L -> length of receive buffer
2204 * e -> return parameter number of entries
2205 * h -> return parameter total number of users
2208 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2209 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2210 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2211 resume_context, cli_buf_size));
2214 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2219 /* check it's a supported varient */
2220 if (strcmp("B21",str2) != 0)
2223 *rdata_len = cli_buf_size;
2224 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2232 search = pdb_search_users(ACB_NORMAL);
2234 if (search == NULL) {
2235 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2240 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2244 errflags=NERR_Success;
2246 for (i=0; i<num_users; i++) {
2247 const char *name = users[i].account_name;
2249 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2251 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2252 "%s\n",count_sent,p));
2256 /* set overflow error */
2257 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2258 "username %s\n",count_sent,name));
2264 pdb_search_destroy(search);
2266 *rdata_len = PTR_DIFF(p,*rdata);
2268 SSVAL(*rparam,0,errflags);
2269 SSVAL(*rparam,2,0); /* converter word */
2270 SSVAL(*rparam,4,count_sent); /* is this right?? */
2271 SSVAL(*rparam,6,num_users); /* is this right?? */
2276 /****************************************************************************
2277 Get the time of day info.
2278 ****************************************************************************/
2280 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2281 char *param, int tpscnt,
2282 char *data, int tdscnt,
2283 int mdrcnt,int mprcnt,
2284 char **rdata,char **rparam,
2285 int *rdata_len,int *rparam_len)
2288 time_t unixdate = time(NULL);
2292 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2298 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2303 SSVAL(*rparam,0,NERR_Success);
2304 SSVAL(*rparam,2,0); /* converter word */
2308 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2309 by NT in a "net time" operation,
2310 it seems to ignore the one below */
2312 /* the client expects to get localtime, not GMT, in this bit
2313 (I think, this needs testing) */
2314 t = localtime(&unixdate);
2319 SIVAL(p,4,0); /* msecs ? */
2320 SCVAL(p,8,t->tm_hour);
2321 SCVAL(p,9,t->tm_min);
2322 SCVAL(p,10,t->tm_sec);
2323 SCVAL(p,11,0); /* hundredths of seconds */
2324 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2325 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2326 SCVAL(p,16,t->tm_mday);
2327 SCVAL(p,17,t->tm_mon + 1);
2328 SSVAL(p,18,1900+t->tm_year);
2329 SCVAL(p,20,t->tm_wday);
2334 /****************************************************************************
2335 Set the user password.
2336 *****************************************************************************/
2338 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
2339 char *param, int tpscnt,
2340 char *data, int tdscnt,
2341 int mdrcnt,int mprcnt,
2342 char **rdata,char **rparam,
2343 int *rdata_len,int *rparam_len)
2345 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2346 char *p = skip_string(param,tpscnt,np,2);
2348 fstring pass1,pass2;
2354 /* Do we have a string ? */
2355 if (skip_string(param,tpscnt,p,1) == NULL) {
2358 pull_ascii_fstring(user,p);
2360 p = skip_string(param,tpscnt,p,1);
2365 memset(pass1,'\0',sizeof(pass1));
2366 memset(pass2,'\0',sizeof(pass2));
2367 if (!is_offset_safe(param,tpscnt,p,32)) {
2371 memcpy(pass2,p+16,16);
2374 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2381 SSVAL(*rparam,0,NERR_badpass);
2382 SSVAL(*rparam,2,0); /* converter word */
2384 DEBUG(3,("Set password for <%s>\n",user));
2387 * Attempt to verify the old password against smbpasswd entries
2388 * Win98 clients send old and new password in plaintext for this call.
2392 auth_serversupplied_info *server_info = NULL;
2393 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2395 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2398 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2399 SSVAL(*rparam,0,NERR_Success);
2403 TALLOC_FREE(server_info);
2405 data_blob_clear_free(&password);
2409 * If the plaintext change failed, attempt
2410 * the old encrypted method. NT will generate this
2411 * after trying the samr method. Note that this
2412 * method is done as a last resort as this
2413 * password change method loses the NT password hash
2414 * and cannot change the UNIX password as no plaintext
2418 if(SVAL(*rparam,0) != NERR_Success) {
2419 struct samu *hnd = NULL;
2421 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2423 if (change_lanman_password(hnd,(uchar *)pass2)) {
2424 SSVAL(*rparam,0,NERR_Success);
2431 memset((char *)pass1,'\0',sizeof(fstring));
2432 memset((char *)pass2,'\0',sizeof(fstring));
2437 /****************************************************************************
2438 Set the user password (SamOEM version - gets plaintext).
2439 ****************************************************************************/
2441 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2442 char *param, int tpscnt,
2443 char *data, int tdscnt,
2444 int mdrcnt,int mprcnt,
2445 char **rdata,char **rparam,
2446 int *rdata_len,int *rparam_len)
2449 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2451 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2461 SSVAL(*rparam,0,NERR_badpass);
2464 * Check the parameter definition is correct.
2467 /* Do we have a string ? */
2468 if (skip_string(param,tpscnt,p,1) == 0) {
2471 if(!strequal(p, "zsT")) {
2472 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2475 p = skip_string(param, tpscnt, p, 1);
2480 /* Do we have a string ? */
2481 if (skip_string(param,tpscnt,p,1) == 0) {
2484 if(!strequal(p, "B516B16")) {
2485 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2488 p = skip_string(param,tpscnt,p,1);
2492 /* Do we have a string ? */
2493 if (skip_string(param,tpscnt,p,1) == 0) {
2496 p += pull_ascii_fstring(user,p);
2498 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2501 * Pass the user through the NT -> unix user mapping
2505 (void)map_username(user);
2507 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2508 SSVAL(*rparam,0,NERR_Success);
2514 /****************************************************************************
2517 ****************************************************************************/
2519 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2520 char *param, int tpscnt,
2521 char *data, int tdscnt,
2522 int mdrcnt,int mprcnt,
2523 char **rdata,char **rparam,
2524 int *rdata_len,int *rparam_len)
2526 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2527 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2528 char *str2 = skip_string(param,tpscnt,str1,1);
2529 char *p = skip_string(param,tpscnt,str2,1);
2534 WERROR werr = WERR_OK;
2536 if (!str1 || !str2 || !p) {
2539 if (!is_offset_safe(param,tpscnt,p,2)) {
2542 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2545 /* check it's a supported varient */
2546 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2550 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2556 if (!print_job_exists(sharename, jobid)) {
2557 errcode = NERR_JobNotFound;
2561 snum = lp_servicenumber( sharename);
2563 errcode = NERR_DestNotFound;
2567 errcode = NERR_notsupported;
2570 case 81: /* delete */
2571 if (print_job_delete(¤t_user, snum, jobid, &werr))
2572 errcode = NERR_Success;
2574 case 82: /* pause */
2575 if (print_job_pause(¤t_user, snum, jobid, &werr))
2576 errcode = NERR_Success;
2578 case 83: /* resume */
2579 if (print_job_resume(¤t_user, snum, jobid, &werr))
2580 errcode = NERR_Success;
2584 if (!W_ERROR_IS_OK(werr))
2585 errcode = W_ERROR_V(werr);
2588 SSVAL(*rparam,0,errcode);
2589 SSVAL(*rparam,2,0); /* converter word */
2594 /****************************************************************************
2595 Purge a print queue - or pause or resume it.
2596 ****************************************************************************/
2598 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2599 char *param, int tpscnt,
2600 char *data, int tdscnt,
2601 int mdrcnt,int mprcnt,
2602 char **rdata,char **rparam,
2603 int *rdata_len,int *rparam_len)
2605 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2606 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2607 char *str2 = skip_string(param,tpscnt,str1,1);
2608 char *QueueName = skip_string(param,tpscnt,str2,1);
2609 int errcode = NERR_notsupported;
2611 WERROR werr = WERR_OK;
2613 if (!str1 || !str2 || !QueueName) {
2617 /* check it's a supported varient */
2618 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2622 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2628 if (skip_string(param,tpscnt,QueueName,1) == NULL) {
2631 snum = print_queue_snum(QueueName);
2634 errcode = NERR_JobNotFound;
2639 case 74: /* Pause queue */
2640 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2642 case 75: /* Resume queue */
2643 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2645 case 103: /* Purge */
2646 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2650 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2653 SSVAL(*rparam,0,errcode);
2654 SSVAL(*rparam,2,0); /* converter word */
2659 /****************************************************************************
2660 set the property of a print job (undocumented?)
2661 ? function = 0xb -> set name of print job
2662 ? function = 0x6 -> move print job up/down
2663 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2664 or <WWsTP> <WB21BB16B10zWWzDDz>
2665 ****************************************************************************/
2667 static int check_printjob_info(struct pack_desc* desc,
2668 int uLevel, char* id)
2670 desc->subformat = NULL;
2672 case 0: desc->format = "W"; break;
2673 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2674 case 2: desc->format = "WWzWWDDzz"; break;
2675 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2676 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2677 default: return False;
2679 if (strcmp(desc->format,id) != 0) return False;
2683 static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2684 char *param, int tpscnt,
2685 char *data, int tdscnt,
2686 int mdrcnt,int mprcnt,
2687 char **rdata,char **rparam,
2688 int *rdata_len,int *rparam_len)
2690 struct pack_desc desc;
2691 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2692 char *str2 = skip_string(param,tpscnt,str1,1);
2693 char *p = skip_string(param,tpscnt,str2,1);
2696 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2697 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2700 if (!str1 || !str2 || !p) {
2703 if (!is_offset_safe(param,tpscnt,p,2)) {
2706 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2709 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2714 if (!share_defined(sharename)) {
2715 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2722 /* check it's a supported varient */
2723 if ((strcmp(str1,"WWsTP")) ||
2724 (!check_printjob_info(&desc,uLevel,str2)))
2727 if (!print_job_exists(sharename, jobid)) {
2728 errcode=NERR_JobNotFound;
2732 errcode = NERR_notsupported;
2736 /* change job place in the queue,
2737 data gives the new place */
2738 place = SVAL(data,0);
2739 if (print_job_set_place(sharename, jobid, place)) {
2740 errcode=NERR_Success;
2745 /* change print job name, data gives the name */
2746 if (print_job_set_name(sharename, jobid, data)) {
2747 errcode=NERR_Success;
2756 SSVALS(*rparam,0,errcode);
2757 SSVAL(*rparam,2,0); /* converter word */
2763 /****************************************************************************
2764 Get info about the server.
2765 ****************************************************************************/
2767 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2768 char *param, int tpscnt,
2769 char *data, int tdscnt,
2770 int mdrcnt,int mprcnt,
2771 char **rdata,char **rparam,
2772 int *rdata_len,int *rparam_len)
2774 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2775 char *str2 = skip_string(param,tpscnt,str1,1);
2776 char *p = skip_string(param,tpscnt,str2,1);
2777 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2781 if (!str1 || !str2 || !p) {
2785 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2787 /* check it's a supported varient */
2788 if (!prefix_ok(str1,"WrLh")) {
2794 if (strcmp(str2,"B16") != 0) {
2800 if (strcmp(str2,"B16BBDz") != 0) {
2806 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2812 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2818 if (strcmp(str2,"DN") != 0) {
2824 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2833 *rdata_len = mdrcnt;
2834 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2840 p2 = p + struct_len;
2842 srvstr_push(NULL, p,global_myname(),16,
2843 STR_ASCII|STR_UPPER|STR_TERMINATE);
2847 struct srv_info_struct *servers=NULL;
2850 uint32 servertype= lp_default_server_announce();
2852 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2854 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2855 for (i=0;i<count;i++) {
2856 if (strequal(servers[i].name,global_myname())) {
2857 servertype = servers[i].type;
2858 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2865 SCVAL(p,0,lp_major_announce_version());
2866 SCVAL(p,1,lp_minor_announce_version());
2867 SIVAL(p,2,servertype);
2869 if (mdrcnt == struct_len) {
2872 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2873 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2874 conn->connectpath, conn->gid,
2875 get_current_username(),
2876 current_user_info.domain,
2877 comment, sizeof(comment));
2878 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2879 p2 = skip_string(*rdata,*rdata_len,p2,1);
2887 return False; /* not yet implemented */
2890 *rdata_len = PTR_DIFF(p2,*rdata);
2893 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2897 SSVAL(*rparam,0,NERR_Success);
2898 SSVAL(*rparam,2,0); /* converter word */
2899 SSVAL(*rparam,4,*rdata_len);
2904 /****************************************************************************
2905 Get info about the server.
2906 ****************************************************************************/
2908 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
2909 char *param, int tpscnt,
2910 char *data, int tdscnt,
2911 int mdrcnt,int mprcnt,
2912 char **rdata,char **rparam,
2913 int *rdata_len,int *rparam_len)
2915 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2916 char *str2 = skip_string(param,tpscnt,str1,1);
2917 char *p = skip_string(param,tpscnt,str2,1);
2919 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
2921 if (!str1 || !str2 || !p) {
2925 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2928 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2933 /* check it's a supported varient */
2934 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2938 *rdata_len = mdrcnt + 1024;
2939 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2944 SSVAL(*rparam,0,NERR_Success);
2945 SSVAL(*rparam,2,0); /* converter word */
2948 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
2953 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2954 pstrcpy(p2,get_local_machine_name());
2956 p2 = skip_string(*rdata,*rdata_len,p2,1);
2962 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2963 pstrcpy(p2,current_user_info.smb_name);
2964 p2 = skip_string(*rdata,*rdata_len,p2,1);
2970 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2971 pstrcpy(p2,lp_workgroup());
2973 p2 = skip_string(*rdata,*rdata_len,p2,1);
2979 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2980 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2983 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2984 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2985 p2 = skip_string(*rdata,*rdata_len,p2,1);
2991 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2993 p2 = skip_string(*rdata,*rdata_len,p2,1);
2999 *rdata_len = PTR_DIFF(p2,*rdata);
3001 SSVAL(*rparam,4,*rdata_len);
3006 /****************************************************************************
3007 get info about a user
3009 struct user_info_11 {
3010 char usri11_name[21]; 0-20
3012 char *usri11_comment; 22-25
3013 char *usri11_usr_comment; 26-29
3014 unsigned short usri11_priv; 30-31
3015 unsigned long usri11_auth_flags; 32-35
3016 long usri11_password_age; 36-39
3017 char *usri11_homedir; 40-43
3018 char *usri11_parms; 44-47
3019 long usri11_last_logon; 48-51
3020 long usri11_last_logoff; 52-55
3021 unsigned short usri11_bad_pw_count; 56-57
3022 unsigned short usri11_num_logons; 58-59
3023 char *usri11_logon_server; 60-63
3024 unsigned short usri11_country_code; 64-65
3025 char *usri11_workstations; 66-69
3026 unsigned long usri11_max_storage; 70-73
3027 unsigned short usri11_units_per_week; 74-75
3028 unsigned char *usri11_logon_hours; 76-79
3029 unsigned short usri11_code_page; 80-81
3034 usri11_name specifies the user name for which information is retireved
3036 usri11_pad aligns the next data structure element to a word boundary
3038 usri11_comment is a null terminated ASCII comment
3040 usri11_user_comment is a null terminated ASCII comment about the user
3042 usri11_priv specifies the level of the privilege assigned to the user.
3043 The possible values are:
3045 Name Value Description
3046 USER_PRIV_GUEST 0 Guest privilege
3047 USER_PRIV_USER 1 User privilege
3048 USER_PRV_ADMIN 2 Administrator privilege
3050 usri11_auth_flags specifies the account operator privileges. The
3051 possible values are:
3053 Name Value Description
3054 AF_OP_PRINT 0 Print operator
3057 Leach, Naik [Page 28]
3061 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3064 AF_OP_COMM 1 Communications operator
3065 AF_OP_SERVER 2 Server operator
3066 AF_OP_ACCOUNTS 3 Accounts operator
3069 usri11_password_age specifies how many seconds have elapsed since the
3070 password was last changed.
3072 usri11_home_dir points to a null terminated ASCII string that contains
3073 the path name of the user's home directory.
3075 usri11_parms points to a null terminated ASCII string that is set
3076 aside for use by applications.
3078 usri11_last_logon specifies the time when the user last logged on.
3079 This value is stored as the number of seconds elapsed since
3080 00:00:00, January 1, 1970.
3082 usri11_last_logoff specifies the time when the user last logged off.
3083 This value is stored as the number of seconds elapsed since
3084 00:00:00, January 1, 1970. A value of 0 means the last logoff
3087 usri11_bad_pw_count specifies the number of incorrect passwords
3088 entered since the last successful logon.
3090 usri11_log1_num_logons specifies the number of times this user has
3091 logged on. A value of -1 means the number of logons is unknown.
3093 usri11_logon_server points to a null terminated ASCII string that
3094 contains the name of the server to which logon requests are sent.
3095 A null string indicates logon requests should be sent to the
3098 usri11_country_code specifies the country code for the user's language
3101 usri11_workstations points to a null terminated ASCII string that
3102 contains the names of workstations the user may log on from.
3103 There may be up to 8 workstations, with the names separated by
3104 commas. A null strings indicates there are no restrictions.
3106 usri11_max_storage specifies the maximum amount of disk space the user
3107 can occupy. A value of 0xffffffff indicates there are no
3110 usri11_units_per_week specifies the equal number of time units into
3111 which a week is divided. This value must be equal to 168.
3113 usri11_logon_hours points to a 21 byte (168 bits) string that
3114 specifies the time during which the user can log on. Each bit
3115 represents one unique hour in a week. The first bit (bit 0, word
3116 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3120 Leach, Naik [Page 29]
3124 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3127 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3128 are no restrictions.
3130 usri11_code_page specifies the code page for the user's language of
3133 All of the pointers in this data structure need to be treated
3134 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3135 to be ignored. The converter word returned in the parameters section
3136 needs to be subtracted from the lower 16 bits to calculate an offset
3137 into the return buffer where this ASCII string resides.
3139 There is no auxiliary data in the response.
3141 ****************************************************************************/
3143 #define usri11_name 0
3144 #define usri11_pad 21
3145 #define usri11_comment 22
3146 #define usri11_usr_comment 26
3147 #define usri11_full_name 30
3148 #define usri11_priv 34
3149 #define usri11_auth_flags 36
3150 #define usri11_password_age 40
3151 #define usri11_homedir 44
3152 #define usri11_parms 48
3153 #define usri11_last_logon 52
3154 #define usri11_last_logoff 56
3155 #define usri11_bad_pw_count 60
3156 #define usri11_num_logons 62
3157 #define usri11_logon_server 64
3158 #define usri11_country_code 68
3159 #define usri11_workstations 70
3160 #define usri11_max_storage 74
3161 #define usri11_units_per_week 78
3162 #define usri11_logon_hours 80
3163 #define usri11_code_page 84
3164 #define usri11_end 86
3166 #define USER_PRIV_GUEST 0
3167 #define USER_PRIV_USER 1
3168 #define USER_PRIV_ADMIN 2
3170 #define AF_OP_PRINT 0
3171 #define AF_OP_COMM 1
3172 #define AF_OP_SERVER 2
3173 #define AF_OP_ACCOUNTS 3
3176 static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3177 char *param, int tpscnt,
3178 char *data, int tdscnt,
3179 int mdrcnt,int mprcnt,
3180 char **rdata,char **rparam,
3181 int *rdata_len,int *rparam_len)
3183 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3184 char *str2 = skip_string(param,tpscnt,str1,1);
3185 char *UserName = skip_string(param,tpscnt,str2,1);
3186 char *p = skip_string(param,tpscnt,UserName,1);
3187 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3189 const char *level_string;
3191 /* get NIS home of a previously validated user - simeon */
3192 /* With share level security vuid will always be zero.
3193 Don't depend on vuser being non-null !!. JRA */
3194 user_struct *vuser = get_valid_user_struct(vuid);
3196 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3197 vuser->user.unix_name));
3200 if (!str1 || !str2 || !UserName || !p) {
3205 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3210 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3212 /* check it's a supported variant */
3213 if (strcmp(str1,"zWrLh") != 0) {
3217 case 0: level_string = "B21"; break;
3218 case 1: level_string = "B21BB16DWzzWz"; break;
3219 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3220 case 10: level_string = "B21Bzzz"; break;
3221 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3222 default: return False;
3225 if (strcmp(level_string,str2) != 0) {
3229 *rdata_len = mdrcnt + 1024;
3230 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3235 SSVAL(*rparam,0,NERR_Success);
3236 SSVAL(*rparam,2,0); /* converter word */
3239 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3245 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3248 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3253 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3254 pstrcpy(p2,"Comment");
3255 p2 = skip_string(*rdata,*rdata_len,p2,1);
3260 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3261 pstrcpy(p2,"UserComment");
3262 p2 = skip_string(*rdata,*rdata_len,p2,1);
3267 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3268 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3269 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3270 p2 = skip_string(*rdata,*rdata_len,p2,1);
3277 /* modelled after NTAS 3.51 reply */
3278 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3279 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3280 SIVALS(p,usri11_password_age,-1); /* password age */
3281 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3282 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3283 p2 = skip_string(*rdata,*rdata_len,p2,1);
3287 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3289 p2 = skip_string(*rdata,*rdata_len,p2,1);
3293 SIVAL(p,usri11_last_logon,0); /* last logon */
3294 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3295 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3296 SSVALS(p,usri11_num_logons,-1); /* num logons */
3297 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3298 pstrcpy(p2,"\\\\*");
3299 p2 = skip_string(*rdata,*rdata_len,p2,1);
3303 SSVAL(p,usri11_country_code,0); /* country code */
3305 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3307 p2 = skip_string(*rdata,*rdata_len,p2,1);
3312 SIVALS(p,usri11_max_storage,-1); /* max storage */
3313 SSVAL(p,usri11_units_per_week,168); /* units per week */
3314 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3316 /* a simple way to get logon hours at all times. */
3318 SCVAL(p2,21,0); /* fix zero termination */
3319 p2 = skip_string(*rdata,*rdata_len,p2,1);
3324 SSVAL(p,usri11_code_page,0); /* code page */
3327 if (uLevel == 1 || uLevel == 2) {
3328 memset(p+22,' ',16); /* password */
3329 SIVALS(p,38,-1); /* password age */
3331 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3332 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3333 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3334 p2 = skip_string(*rdata,*rdata_len,p2,1);
3338 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3340 SSVAL(p,52,0); /* flags */
3341 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3342 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3343 p2 = skip_string(*rdata,*rdata_len,p2,1);
3348 SIVAL(p,60,0); /* auth_flags */
3349 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3350 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3351 p2 = skip_string(*rdata,*rdata_len,p2,1);
3355 SIVAL(p,68,0); /* urs_comment */
3356 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3358 p2 = skip_string(*rdata,*rdata_len,p2,1);
3362 SIVAL(p,76,0); /* workstations */
3363 SIVAL(p,80,0); /* last_logon */
3364 SIVAL(p,84,0); /* last_logoff */
3365 SIVALS(p,88,-1); /* acct_expires */
3366 SIVALS(p,92,-1); /* max_storage */
3367 SSVAL(p,96,168); /* units_per_week */
3368 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3371 SSVALS(p,102,-1); /* bad_pw_count */
3372 SSVALS(p,104,-1); /* num_logons */
3373 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3376 pstrcpy(tmp, "\\\\%L");
3377 standard_sub_basic("", "", tmp, sizeof(tmp));
3380 p2 = skip_string(*rdata,*rdata_len,p2,1);
3384 SSVAL(p,110,49); /* country_code */
3385 SSVAL(p,112,860); /* code page */
3389 *rdata_len = PTR_DIFF(p2,*rdata);
3391 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3396 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3397 char *param, int tpscnt,
3398 char *data, int tdscnt,
3399 int mdrcnt,int mprcnt,
3400 char **rdata,char **rparam,
3401 int *rdata_len,int *rparam_len)
3403 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3404 char *str2 = skip_string(param,tpscnt,str1,1);
3405 char *p = skip_string(param,tpscnt,str2,1);
3407 struct pack_desc desc;
3409 /* With share level security vuid will always be zero.
3410 Don't depend on vuser being non-null !!. JRA */
3411 user_struct *vuser = get_valid_user_struct(vuid);
3413 if (!str1 || !str2 || !p) {
3418 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3419 vuser->user.unix_name));
3422 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3423 name = get_safe_str_ptr(param,tpscnt,p,2);
3428 memset((char *)&desc,'\0',sizeof(desc));
3430 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3432 /* check it's a supported varient */
3433 if (strcmp(str1,"OOWb54WrLh") != 0) {
3436 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3440 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3447 desc.buflen = mdrcnt;
3448 desc.subformat = NULL;
3451 if (init_package(&desc,1,0)) {
3452 PACKI(&desc,"W",0); /* code */
3453 PACKS(&desc,"B21",name); /* eff. name */
3454 PACKS(&desc,"B",""); /* pad */
3455 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3456 PACKI(&desc,"D",0); /* auth flags XXX */
3457 PACKI(&desc,"W",0); /* num logons */
3458 PACKI(&desc,"W",0); /* bad pw count */
3459 PACKI(&desc,"D",0); /* last logon */
3460 PACKI(&desc,"D",-1); /* last logoff */
3461 PACKI(&desc,"D",-1); /* logoff time */
3462 PACKI(&desc,"D",-1); /* kickoff time */
3463 PACKI(&desc,"D",0); /* password age */
3464 PACKI(&desc,"D",0); /* password can change */
3465 PACKI(&desc,"D",-1); /* password must change */
3469 fstrcpy(mypath,"\\\\");
3470 fstrcat(mypath,get_local_machine_name());
3472 PACKS(&desc,"z",mypath); /* computer */
3475 PACKS(&desc,"z",lp_workgroup());/* domain */
3476 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3477 PACKI(&desc,"D",0x00000000); /* reserved */
3480 *rdata_len = desc.usedlen;
3482 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3486 SSVALS(*rparam,0,desc.errcode);
3488 SSVAL(*rparam,4,desc.neededlen);
3490 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3495 /****************************************************************************
3496 api_WAccessGetUserPerms
3497 ****************************************************************************/
3499 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3500 char *param, int tpscnt,
3501 char *data, int tdscnt,
3502 int mdrcnt,int mprcnt,
3503 char **rdata,char **rparam,
3504 int *rdata_len,int *rparam_len)
3506 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3507 char *str2 = skip_string(param,tpscnt,str1,1);
3508 char *user = skip_string(param,tpscnt,str2,1);
3509 char *resource = skip_string(param,tpscnt,user,1);
3511 if (!str1 || !str2 || !user || !resource) {
3515 if (skip_string(param,tpscnt,resource,1) == NULL) {
3518 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3520 /* check it's a supported varient */
3521 if (strcmp(str1,"zzh") != 0) {
3524 if (strcmp(str2,"") != 0) {
3529 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3533 SSVALS(*rparam,0,0); /* errorcode */
3534 SSVAL(*rparam,2,0); /* converter word */
3535 SSVAL(*rparam,4,0x7f); /* permission flags */
3540 /****************************************************************************
3541 api_WPrintJobEnumerate
3542 ****************************************************************************/
3544 static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3545 char *param, int tpscnt,
3546 char *data, int tdscnt,
3547 int mdrcnt,int mprcnt,
3548 char **rdata,char **rparam,
3549 int *rdata_len,int *rparam_len)
3551 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3552 char *str2 = skip_string(param,tpscnt,str1,1);
3553 char *p = skip_string(param,tpscnt,str2,1);
3560 struct pack_desc desc;
3561 print_queue_struct *queue=NULL;
3562 print_status_struct status;
3565 if (!str1 || !str2 || !p) {
3569 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3571 memset((char *)&desc,'\0',sizeof(desc));
3572 memset((char *)&status,'\0',sizeof(status));
3574 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3576 /* check it's a supported varient */
3577 if (strcmp(str1,"WWrLh") != 0) {
3580 if (!check_printjob_info(&desc,uLevel,str2)) {
3584 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3588 snum = lp_servicenumber( sharename);
3589 if (snum < 0 || !VALID_SNUM(snum)) {
3593 count = print_queue_status(snum,&queue,&status);
3594 for (i = 0; i < count; i++) {
3595 if (queue[i].job == jobid) {
3601 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3606 desc.buflen = mdrcnt;
3609 * Don't return data but need to get correct length
3610 * init_package will return wrong size if buflen=0
3612 desc.buflen = getlen(desc.format);
3613 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3616 if (init_package(&desc,1,0)) {
3618 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3619 *rdata_len = desc.usedlen;
3621 desc.errcode = NERR_JobNotFound;
3627 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3631 SSVALS(*rparam,0,desc.errcode);
3633 SSVAL(*rparam,4,desc.neededlen);
3638 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3643 static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3644 char *param, int tpscnt,
3645 char *data, int tdscnt,
3646 int mdrcnt,int mprcnt,
3647 char **rdata,char **rparam,
3648 int *rdata_len,int *rparam_len)
3650 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3651 char *str2 = skip_string(param,tpscnt,str1,1);
3652 char *p = skip_string(param,tpscnt,str2,1);
3658 struct pack_desc desc;
3659 print_queue_struct *queue=NULL;
3660 print_status_struct status;
3662 if (!str1 || !str2 || !p) {
3666 memset((char *)&desc,'\0',sizeof(desc));
3667 memset((char *)&status,'\0',sizeof(status));
3669 p = skip_string(param,tpscnt,p,1);
3673 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3675 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3677 /* check it's a supported variant */
3678 if (strcmp(str1,"zWrLeh") != 0) {
3683 return False; /* defined only for uLevel 0,1,2 */
3686 if (!check_printjob_info(&desc,uLevel,str2)) {
3690 snum = find_service(name);
3691 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3695 count = print_queue_status(snum,&queue,&status);
3697 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3703 desc.buflen = mdrcnt;
3705 if (init_package(&desc,count,0)) {
3707 for (i = 0; i < count; i++) {
3708 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3709 if (desc.errcode == NERR_Success) {
3715 *rdata_len = desc.usedlen;
3718 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3722 SSVALS(*rparam,0,desc.errcode);
3724 SSVAL(*rparam,4,succnt);
3725 SSVAL(*rparam,6,count);
3729 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3734 static int check_printdest_info(struct pack_desc* desc,
3735 int uLevel, char* id)
3737 desc->subformat = NULL;
3740 desc->format = "B9";
3743 desc->format = "B9B21WWzW";
3749 desc->format = "zzzWWzzzWW";
3754 if (strcmp(desc->format,id) != 0) {
3760 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3761 struct pack_desc* desc)
3765 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3766 buf[sizeof(buf)-1] = 0;
3770 PACKS(desc,"B9",buf); /* szName */
3772 PACKS(desc,"B21",""); /* szUserName */
3773 PACKI(desc,"W",0); /* uJobId */
3774 PACKI(desc,"W",0); /* fsStatus */
3775 PACKS(desc,"z",""); /* pszStatus */
3776 PACKI(desc,"W",0); /* time */
3780 if (uLevel == 2 || uLevel == 3) {
3781 PACKS(desc,"z",buf); /* pszPrinterName */
3783 PACKS(desc,"z",""); /* pszUserName */
3784 PACKS(desc,"z",""); /* pszLogAddr */
3785 PACKI(desc,"W",0); /* uJobId */
3786 PACKI(desc,"W",0); /* fsStatus */
3787 PACKS(desc,"z",""); /* pszStatus */
3788 PACKS(desc,"z",""); /* pszComment */
3789 PACKS(desc,"z","NULL"); /* pszDrivers */
3790 PACKI(desc,"W",0); /* time */
3791 PACKI(desc,"W",0); /* pad1 */
3796 static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3797 char *param, int tpscnt,
3798 char *data, int tdscnt,
3799 int mdrcnt,int mprcnt,
3800 char **rdata,char **rparam,
3801 int *rdata_len,int *rparam_len)
3803 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3804 char *str2 = skip_string(param,tpscnt,str1,1);
3805 char *p = skip_string(param,tpscnt,str2,1);
3806 char* PrinterName = p;
3808 struct pack_desc desc;
3812 if (!str1 || !str2 || !p) {
3816 memset((char *)&desc,'\0',sizeof(desc));
3818 p = skip_string(param,tpscnt,p,1);
3822 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3824 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3826 /* check it's a supported varient */
3827 if (strcmp(str1,"zWrLh") != 0) {
3830 if (!check_printdest_info(&desc,uLevel,str2)) {
3834 snum = find_service(PrinterName);
3835 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3837 desc.errcode = NERR_DestNotFound;
3841 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3846 desc.buflen = mdrcnt;
3849 * Don't return data but need to get correct length
3850 * init_package will return wrong size if buflen=0
3852 desc.buflen = getlen(desc.format);
3853 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3855 if (init_package(&desc,1,0)) {
3856 fill_printdest_info(conn,snum,uLevel,&desc);
3858 *rdata_len = desc.usedlen;
3862 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3866 SSVALS(*rparam,0,desc.errcode);
3868 SSVAL(*rparam,4,desc.neededlen);
3870 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3876 static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
3877 char *param, int tpscnt,
3878 char *data, int tdscnt,
3879 int mdrcnt,int mprcnt,
3880 char **rdata,char **rparam,
3881 int *rdata_len,int *rparam_len)
3883 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3884 char *str2 = skip_string(param,tpscnt,str1,1);
3885 char *p = skip_string(param,tpscnt,str2,1);
3889 struct pack_desc desc;
3890 int services = lp_numservices();
3892 if (!str1 || !str2 || !p) {
3896 memset((char *)&desc,'\0',sizeof(desc));
3898 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3900 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3902 /* check it's a supported varient */
3903 if (strcmp(str1,"WrLeh") != 0) {
3906 if (!check_printdest_info(&desc,uLevel,str2)) {
3911 for (i = 0; i < services; i++) {
3912 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3918 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3925 desc.buflen = mdrcnt;
3926 if (init_package(&desc,queuecnt,0)) {
3929 for (i = 0; i < services; i++) {
3930 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3931 fill_printdest_info(conn,i,uLevel,&desc);
3933 if (desc.errcode == NERR_Success) {
3940 *rdata_len = desc.usedlen;
3943 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3947 SSVALS(*rparam,0,desc.errcode);
3949 SSVAL(*rparam,4,succnt);
3950 SSVAL(*rparam,6,queuecnt);
3952 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3957 static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
3958 char *param, int tpscnt,
3959 char *data, int tdscnt,
3960 int mdrcnt,int mprcnt,
3961 char **rdata,char **rparam,
3962 int *rdata_len,int *rparam_len)
3964 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3965 char *str2 = skip_string(param,tpscnt,str1,1);
3966 char *p = skip_string(param,tpscnt,str2,1);
3969 struct pack_desc desc;
3971 if (!str1 || !str2 || !p) {
3975 memset((char *)&desc,'\0',sizeof(desc));
3977 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3979 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3981 /* check it's a supported varient */
3982 if (strcmp(str1,"WrLeh") != 0) {
3985 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
3990 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3996 desc.buflen = mdrcnt;
3997 if (init_package(&desc,1,0)) {
3998 PACKS(&desc,"B41","NULL");
4001 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4003 *rdata_len = desc.usedlen;
4006 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4010 SSVALS(*rparam,0,desc.errcode);
4012 SSVAL(*rparam,4,succnt);
4015 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4020 static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4021 char *param, int tpscnt,
4022 char *data, int tdscnt,
4023 int mdrcnt,int mprcnt,
4024 char **rdata,char **rparam,
4025 int *rdata_len,int *rparam_len)
4027 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4028 char *str2 = skip_string(param,tpscnt,str1,1);
4029 char *p = skip_string(param,tpscnt,str2,1);
4032 struct pack_desc desc;
4034 if (!str1 || !str2 || !p) {
4037 memset((char *)&desc,'\0',sizeof(desc));
4039 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4041 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4043 /* check it's a supported varient */
4044 if (strcmp(str1,"WrLeh") != 0) {
4047 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4052 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4058 desc.buflen = mdrcnt;
4060 if (init_package(&desc,1,0)) {
4061 PACKS(&desc,"B13","lpd");
4064 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4066 *rdata_len = desc.usedlen;
4069 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4073 SSVALS(*rparam,0,desc.errcode);
4075 SSVAL(*rparam,4,succnt);
4078 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4083 static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4084 char *param, int tpscnt,
4085 char *data, int tdscnt,
4086 int mdrcnt,int mprcnt,
4087 char **rdata,char **rparam,
4088 int *rdata_len,int *rparam_len)
4090 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4091 char *str2 = skip_string(param,tpscnt,str1,1);
4092 char *p = skip_string(param,tpscnt,str2,1);
4095 struct pack_desc desc;
4097 if (!str1 || !str2 || !p) {
4101 memset((char *)&desc,'\0',sizeof(desc));
4103 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4105 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4107 /* check it's a supported varient */
4108 if (strcmp(str1,"WrLeh") != 0) {
4111 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4116 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4121 memset((char *)&desc,'\0',sizeof(desc));
4123 desc.buflen = mdrcnt;
4125 if (init_package(&desc,1,0)) {
4126 PACKS(&desc,"B13","lp0");
4129 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4131 *rdata_len = desc.usedlen;
4134 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4138 SSVALS(*rparam,0,desc.errcode);
4140 SSVAL(*rparam,4,succnt);
4143 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4148 /****************************************************************************
4150 ****************************************************************************/
4152 static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4153 char *param, int tpscnt,
4154 char *data, int tdscnt,
4155 int mdrcnt,int mprcnt,
4156 char **rdata,char **rparam,
4157 int *rdata_len,int *rparam_len)
4160 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4161 char *str2 = skip_string(param,tpscnt,str1,1);
4162 char *p = skip_string(param,tpscnt,str2,1);
4164 struct pack_desc desc;
4165 struct sessionid *session_list;
4166 int i, num_sessions;
4168 if (!str1 || !str2 || !p) {
4172 memset((char *)&desc,'\0',sizeof(desc));
4174 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4176 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4177 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4178 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4180 /* check it's a supported varient */
4181 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4184 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4188 num_sessions = list_sessions(&session_list);
4191 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4196 memset((char *)&desc,'\0',sizeof(desc));
4198 desc.buflen = mdrcnt;
4200 if (!init_package(&desc,num_sessions,0)) {
4204 for(i=0; i<num_sessions; i++) {
4205 PACKS(&desc, "z", session_list[i].remote_machine);
4206 PACKS(&desc, "z", session_list[i].username);
4207 PACKI(&desc, "W", 1); /* num conns */
4208 PACKI(&desc, "W", 0); /* num opens */
4209 PACKI(&desc, "W", 1); /* num users */
4210 PACKI(&desc, "D", 0); /* session time */
4211 PACKI(&desc, "D", 0); /* idle time */
4212 PACKI(&desc, "D", 0); /* flags */
4213 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4216 *rdata_len = desc.usedlen;
4219 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4223 SSVALS(*rparam,0,desc.errcode);
4224 SSVAL(*rparam,2,0); /* converter */
4225 SSVAL(*rparam,4,num_sessions); /* count */
4227 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4233 /****************************************************************************
4234 The buffer was too small.
4235 ****************************************************************************/
4237 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4238 int mdrcnt, int mprcnt,
4239 char **rdata, char **rparam,
4240 int *rdata_len, int *rparam_len)
4242 *rparam_len = MIN(*rparam_len,mprcnt);
4243 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4250 SSVAL(*rparam,0,NERR_BufTooSmall);
4252 DEBUG(3,("Supplied buffer too small in API command\n"));
4257 /****************************************************************************
4258 The request is not supported.
4259 ****************************************************************************/
4261 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
4262 char *param, int tpscnt,
4263 char *data, int tdscnt,
4264 int mdrcnt, int mprcnt,
4265 char **rdata, char **rparam,
4266 int *rdata_len, int *rparam_len)
4269 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4276 SSVAL(*rparam,0,NERR_notsupported);
4277 SSVAL(*rparam,2,0); /* converter word */
4279 DEBUG(3,("Unsupported API command\n"));
4284 static const struct {
4287 BOOL (*fn)(connection_struct *, uint16,
4290 int,int,char **,char **,int *,int *);
4291 BOOL auth_user; /* Deny anonymous access? */
4292 } api_commands[] = {
4293 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4294 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4295 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4296 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4297 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4298 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4299 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4300 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4301 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4302 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4303 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4304 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4305 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4306 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4307 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4308 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4309 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4310 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4311 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4312 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4313 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4314 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4315 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4316 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4317 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4318 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4319 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4320 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4321 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4322 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4323 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4324 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4325 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4326 {NULL, -1, api_Unsupported}
4327 /* The following RAP calls are not implemented by Samba:
4329 RAP_WFileEnum2 - anon not OK
4334 /****************************************************************************
4335 Handle remote api calls
4336 ****************************************************************************/
4338 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4339 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4343 char *rparam = NULL;
4344 const char *name1 = NULL;
4345 const char *name2 = NULL;
4352 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4359 api_command = SVAL(params,0);
4360 /* Is there a string at position params+2 ? */
4361 if (skip_string(params,tpscnt,params+2,1)) {
4366 name2 = skip_string(params,tpscnt,params+2,1);
4371 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4375 tdscnt,tpscnt,mdrcnt,mprcnt));
4377 for (i=0;api_commands[i].name;i++) {
4378 if (api_commands[i].id == api_command && api_commands[i].fn) {
4379 DEBUG(3,("Doing %s\n",api_commands[i].name));
4384 /* Check whether this api call can be done anonymously */
4386 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4387 user_struct *user = get_valid_user_struct(vuid);
4389 if (!user || user->guest) {
4390 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4394 rdata = (char *)SMB_MALLOC(1024);
4396 memset(rdata,'\0',1024);
4399 rparam = (char *)SMB_MALLOC(1024);
4401 memset(rparam,'\0',1024);
4404 if(!rdata || !rparam) {
4405 DEBUG(0,("api_reply: malloc fail !\n"));
4411 reply = api_commands[i].fn(conn,
4413 params,tpscnt, /* params + length */
4414 data,tdscnt, /* data + length */
4416 &rdata,&rparam,&rdata_len,&rparam_len);
4419 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4420 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4421 &rdata,&rparam,&rdata_len,&rparam_len);
4424 /* if we get False back then it's actually unsupported */
4426 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4427 &rdata,&rparam,&rdata_len,&rparam_len);
4430 /* If api_Unsupported returns false we can't return anything. */
4432 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);