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);
782 char *p = skip_string(param,tpscnt,str2);
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);
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);
909 char *p = skip_string(param,tpscnt,output_format1);
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) {
924 memset((char *)&desc,'\0',sizeof(desc));
926 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
928 if (!prefix_ok(param_format,"WrLeh")) {
931 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
933 * Patch from Scott Moomaw <scott@bridgewater.edu>
934 * to return the 'invalid info level' error if an
935 * unknown level was requested.
939 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
943 SSVALS(*rparam,0,ERRunknownlevel);
949 for (i = 0; i < services; i++) {
950 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
955 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
956 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
959 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
960 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
961 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
964 memset(status,0,queuecnt*sizeof(print_status_struct));
965 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
966 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
972 for (i = 0; i < services; i++) {
973 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
974 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
975 subcnt += subcntarr[n];
981 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
987 desc.buflen = mdrcnt;
989 if (init_package(&desc,queuecnt,subcnt)) {
992 for (i = 0; i < services; i++) {
993 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
994 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
996 if (desc.errcode == NERR_Success) {
1003 SAFE_FREE(subcntarr);
1005 *rdata_len = desc.usedlen;
1007 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1011 SSVALS(*rparam,0,desc.errcode);
1013 SSVAL(*rparam,4,succnt);
1014 SSVAL(*rparam,6,queuecnt);
1016 for (i = 0; i < queuecnt; i++) {
1018 SAFE_FREE(queue[i]);
1029 SAFE_FREE(subcntarr);
1030 for (i = 0; i < queuecnt; i++) {
1032 SAFE_FREE(queue[i]);
1041 /****************************************************************************
1042 Get info level for a server list query.
1043 ****************************************************************************/
1045 static BOOL check_server_info(int uLevel, char* id)
1049 if (strcmp(id,"B16") != 0) {
1054 if (strcmp(id,"B16BBDz") != 0) {
1064 struct srv_info_struct {
1072 /*******************************************************************
1073 Get server info lists from the files saved by nmbd. Return the
1075 ******************************************************************/
1077 static int get_server_info(uint32 servertype,
1078 struct srv_info_struct **servers,
1084 BOOL local_list_only;
1087 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1089 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1093 /* request for everything is code for request all servers */
1094 if (servertype == SV_TYPE_ALL) {
1095 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1098 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1100 DEBUG(4,("Servertype search: %8x\n",servertype));
1102 for (i=0;lines[i];i++) {
1104 struct srv_info_struct *s;
1105 const char *ptr = lines[i];
1112 if (count == alloced) {
1114 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1116 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1117 file_lines_free(lines);
1120 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1122 s = &(*servers)[count];
1124 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1127 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1130 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1133 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1134 /* this allows us to cope with an old nmbd */
1135 fstrcpy(s->domain,lp_workgroup());
1138 if (sscanf(stype,"%X",&s->type) != 1) {
1139 DEBUG(4,("r:host file "));
1143 /* Filter the servers/domains we return based on what was asked for. */
1145 /* Check to see if we are being asked for a local list only. */
1146 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1147 DEBUG(4,("r: local list only"));
1151 /* doesn't match up: don't want it */
1152 if (!(servertype & s->type)) {
1153 DEBUG(4,("r:serv type "));
1157 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1158 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1159 DEBUG(4,("s: dom mismatch "));
1163 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1167 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1168 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1171 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1172 s->name, s->type, s->comment, s->domain));
1173 s->server_added = True;
1176 DEBUG(4,("%20s %8x %25s %15s\n",
1177 s->name, s->type, s->comment, s->domain));
1181 file_lines_free(lines);
1185 /*******************************************************************
1186 Fill in a server info structure.
1187 ******************************************************************/
1189 static int fill_srv_info(struct srv_info_struct *service,
1190 int uLevel, char **buf, int *buflen,
1191 char **stringbuf, int *stringspace, char *baseaddr)
1214 len = strlen(service->comment)+1;
1218 *buflen = struct_len;
1220 return struct_len + len;
1225 if (*buflen < struct_len) {
1232 p2 = p + struct_len;
1233 l2 = *buflen - struct_len;
1241 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1245 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1246 SIVAL(p,18,service->type);
1247 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1248 len += CopyAndAdvance(&p2,service->comment,&l2);
1253 *buf = p + struct_len;
1254 *buflen -= struct_len;
1265 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1267 return(strcmp(s1->name,s2->name));
1270 /****************************************************************************
1271 View list of servers available (or possibly domains). The info is
1272 extracted from lists saved by nmbd on the local host.
1273 ****************************************************************************/
1275 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1276 char *param, int tpscnt,
1277 char *data, int tdscnt,
1278 int mdrcnt, int mprcnt, char **rdata,
1279 char **rparam, int *rdata_len, int *rparam_len)
1281 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1282 char *str2 = skip_string(param,tpscnt,str1);
1283 char *p = skip_string(param,tpscnt,str2);
1284 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1285 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1286 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1288 int data_len, fixed_len, string_len;
1289 int f_len = 0, s_len = 0;
1290 struct srv_info_struct *servers=NULL;
1291 int counted=0,total=0;
1294 BOOL domain_request;
1297 if (!str1 || !str2 || !p) {
1301 /* If someone sets all the bits they don't really mean to set
1302 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1305 if (servertype == SV_TYPE_ALL) {
1306 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1309 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1310 any other bit (they may just set this bit on it's own) they
1311 want all the locally seen servers. However this bit can be
1312 set on its own so set the requested servers to be
1313 ALL - DOMAIN_ENUM. */
1315 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1316 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1319 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1320 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1324 if (!prefix_ok(str1,"WrLehD")) {
1327 if (!check_server_info(uLevel,str2)) {
1331 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1332 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1333 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1335 if (strcmp(str1, "WrLehDz") == 0) {
1336 if (skip_string(param,tpscnt,p) == NULL) {
1339 pull_ascii_fstring(domain, p);
1341 fstrcpy(domain, lp_workgroup());
1344 if (lp_browse_list()) {
1345 total = get_server_info(servertype,&servers,domain);
1348 data_len = fixed_len = string_len = 0;
1352 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1356 char *lastname=NULL;
1358 for (i=0;i<total;i++) {
1359 struct srv_info_struct *s = &servers[i];
1361 if (lastname && strequal(lastname,s->name)) {
1365 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1366 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1367 s->name, s->type, s->comment, s->domain));
1369 if (data_len <= buf_len) {
1372 string_len += s_len;
1379 *rdata_len = fixed_len + string_len;
1380 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1384 memset(*rdata,'\0',*rdata_len);
1386 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1392 char *lastname=NULL;
1393 int count2 = counted;
1395 for (i = 0; i < total && count2;i++) {
1396 struct srv_info_struct *s = &servers[i];
1398 if (lastname && strequal(lastname,s->name)) {
1402 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1403 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1404 s->name, s->type, s->comment, s->domain));
1410 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1414 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1416 SSVAL(*rparam,4,counted);
1417 SSVAL(*rparam,6,counted+missed);
1421 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1422 domain,uLevel,counted,counted+missed));
1427 /****************************************************************************
1428 command 0x34 - suspected of being a "Lookup Names" stub api
1429 ****************************************************************************/
1431 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1432 char *param, int tpscnt,
1433 char *data, int tdscnt,
1434 int mdrcnt, int mprcnt, char **rdata,
1435 char **rparam, int *rdata_len, int *rparam_len)
1437 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1438 char *str2 = skip_string(param,tpscnt,str1);
1439 char *p = skip_string(param,tpscnt,str2);
1440 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1441 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1445 if (!str1 || !str2 || !p) {
1449 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1450 str1, str2, p, uLevel, buf_len));
1452 if (!prefix_ok(str1,"zWrLeh")) {
1459 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1464 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1466 SSVAL(*rparam,4,counted);
1467 SSVAL(*rparam,6,counted+missed);
1472 /****************************************************************************
1473 get info about a share
1474 ****************************************************************************/
1476 static BOOL check_share_info(int uLevel, char* id)
1480 if (strcmp(id,"B13") != 0) {
1485 if (strcmp(id,"B13BWz") != 0) {
1490 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1495 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1505 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1506 char** buf, int* buflen,
1507 char** stringbuf, int* stringspace, char* baseaddr)
1537 len += StrlenExpanded(conn,snum,lp_comment(snum));
1540 len += strlen(lp_pathname(snum)) + 1;
1543 *buflen = struct_len;
1548 return struct_len + len;
1553 if ((*buflen) < struct_len) {
1561 p2 = p + struct_len;
1562 l2 = (*buflen) - struct_len;
1569 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1575 type = STYPE_DISKTREE;
1576 if (lp_print_ok(snum)) {
1577 type = STYPE_PRINTQ;
1579 if (strequal("IPC",lp_fstype(snum))) {
1582 SSVAL(p,14,type); /* device type */
1583 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1584 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1588 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1589 SSVALS(p,22,-1); /* max uses */
1590 SSVAL(p,24,1); /* current uses */
1591 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1592 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1593 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1597 memset(p+40,0,SHPWLEN+2);
1608 (*buf) = p + struct_len;
1609 (*buflen) -= struct_len;
1611 (*stringspace) = l2;
1620 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1621 char *param, int tpscnt,
1622 char *data, int tdscnt,
1623 int mdrcnt,int mprcnt,
1624 char **rdata,char **rparam,
1625 int *rdata_len,int *rparam_len)
1627 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1628 char *str2 = skip_string(param,tpscnt,str1);
1629 char *netname = skip_string(param,tpscnt,str2);
1630 char *p = skip_string(param,tpscnt,netname);
1631 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1634 if (!str1 || !str2 || !netname || !p) {
1638 snum = find_service(netname);
1643 /* check it's a supported varient */
1644 if (!prefix_ok(str1,"zWrLh")) {
1647 if (!check_share_info(uLevel,str2)) {
1651 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1656 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1657 if (*rdata_len < 0) {
1662 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1666 SSVAL(*rparam,0,NERR_Success);
1667 SSVAL(*rparam,2,0); /* converter word */
1668 SSVAL(*rparam,4,*rdata_len);
1673 /****************************************************************************
1674 View the list of available shares.
1676 This function is the server side of the NetShareEnum() RAP call.
1677 It fills the return buffer with share names and share comments.
1678 Note that the return buffer normally (in all known cases) allows only
1679 twelve byte strings for share names (plus one for a nul terminator).
1680 Share names longer than 12 bytes must be skipped.
1681 ****************************************************************************/
1683 static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1684 char *param, int tpscnt,
1685 char *data, int tdscnt,
1693 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1694 char *str2 = skip_string(param,tpscnt,str1);
1695 char *p = skip_string(param,tpscnt,str2);
1696 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1697 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1700 int total=0,counted=0;
1701 BOOL missed = False;
1703 int data_len, fixed_len, string_len;
1704 int f_len = 0, s_len = 0;
1706 if (!str1 || !str2 || !p) {
1710 if (!prefix_ok(str1,"WrLeh")) {
1713 if (!check_share_info(uLevel,str2)) {
1717 /* Ensure all the usershares are loaded. */
1719 load_registry_shares();
1720 count = load_usershare_shares();
1723 data_len = fixed_len = string_len = 0;
1724 for (i=0;i<count;i++) {
1725 fstring servicename_dos;
1726 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1729 push_ascii_fstring(servicename_dos, lp_servicename(i));
1730 /* Maximum name length = 13. */
1731 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1733 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1734 if (data_len <= buf_len) {
1737 string_len += s_len;
1744 *rdata_len = fixed_len + string_len;
1745 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1749 memset(*rdata,0,*rdata_len);
1751 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1756 for( i = 0; i < count; i++ ) {
1757 fstring servicename_dos;
1758 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1762 push_ascii_fstring(servicename_dos, lp_servicename(i));
1763 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1764 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1771 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1775 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1777 SSVAL(*rparam,4,counted);
1778 SSVAL(*rparam,6,total);
1780 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1781 counted,total,uLevel,
1782 buf_len,*rdata_len,mdrcnt));
1787 /****************************************************************************
1789 ****************************************************************************/
1791 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1792 char *param, int tpscnt,
1793 char *data, int tdscnt,
1794 int mdrcnt,int mprcnt,
1795 char **rdata,char **rparam,
1796 int *rdata_len,int *rparam_len)
1798 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1799 char *str2 = skip_string(param,tpscnt,str1);
1800 char *p = skip_string(param,tpscnt,str2);
1801 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1805 char *command, *cmdname;
1806 unsigned int offset;
1810 if (!str1 || !str2 || !p) {
1814 /* check it's a supported varient */
1815 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1818 if (!check_share_info(uLevel,str2)) {
1825 /* Do we have a string ? */
1826 if (skip_string(data,mdrcnt,data) == NULL) {
1829 pull_ascii_fstring(sharename,data);
1830 snum = find_service(sharename);
1831 if (snum >= 0) { /* already exists */
1840 /* only support disk share adds */
1841 if (SVAL(data,14)!=STYPE_DISKTREE) {
1845 offset = IVAL(data, 16);
1846 if (offset >= mdrcnt) {
1847 res = ERRinvalidparam;
1851 /* Do we have a string ? */
1852 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1855 pull_ascii_fstring(comment, offset? (data+offset) : "");
1857 offset = IVAL(data, 26);
1859 if (offset >= mdrcnt) {
1860 res = ERRinvalidparam;
1864 /* Do we have a string ? */
1865 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1868 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1870 string_replace(sharename, '"', ' ');
1871 string_replace(pathname, '"', ' ');
1872 string_replace(comment, '"', ' ');
1874 cmdname = lp_add_share_cmd();
1876 if (!cmdname || *cmdname == '\0') {
1880 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1881 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1884 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1886 if ((res = smbrun(command, NULL)) != 0) {
1887 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1893 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1900 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1904 SSVAL(*rparam,0,NERR_Success);
1905 SSVAL(*rparam,2,0); /* converter word */
1906 SSVAL(*rparam,4,*rdata_len);
1914 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1919 SSVAL(*rparam,0,res);
1924 /****************************************************************************
1925 view list of groups available
1926 ****************************************************************************/
1928 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
1929 char *param, int tpscnt,
1930 char *data, int tdscnt,
1931 int mdrcnt,int mprcnt,
1932 char **rdata,char **rparam,
1933 int *rdata_len,int *rparam_len)
1937 int resume_context, cli_buf_size;
1938 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1939 char *str2 = skip_string(param,tpscnt,str1);
1940 char *p = skip_string(param,tpscnt,str2);
1942 struct pdb_search *search;
1943 struct samr_displayentry *entries;
1947 if (!str1 || !str2 || !p) {
1951 if (strcmp(str1,"WrLeh") != 0) {
1956 * W-> resume context (number of users to skip)
1957 * r -> return parameter pointer to receive buffer
1958 * L -> length of receive buffer
1959 * e -> return parameter number of entries
1960 * h -> return parameter total number of users
1963 if (strcmp("B21",str2) != 0) {
1967 /* get list of domain groups SID_DOMAIN_GRP=2 */
1969 search = pdb_search_groups();
1972 if (search == NULL) {
1973 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1977 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
1978 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
1979 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1980 "%d\n", resume_context, cli_buf_size));
1983 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1987 *rdata_len = cli_buf_size;
1988 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1995 for(i=0; i<num_entries; i++) {
1997 fstrcpy(name, entries[i].account_name);
1998 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1999 /* truncate the name at 21 chars. */
2000 memcpy(p, name, 21);
2001 DEBUG(10,("adding entry %d group %s\n", i, p));
2003 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2006 /* set overflow error */
2007 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2013 pdb_search_destroy(search);
2015 *rdata_len = PTR_DIFF(p,*rdata);
2018 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2022 SSVAL(*rparam, 0, errflags);
2023 SSVAL(*rparam, 2, 0); /* converter word */
2024 SSVAL(*rparam, 4, i); /* is this right?? */
2025 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2030 /*******************************************************************
2031 Get groups that a user is a member of.
2032 ******************************************************************/
2034 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2035 char *param, int tpscnt,
2036 char *data, int tdscnt,
2037 int mdrcnt,int mprcnt,
2038 char **rdata,char **rparam,
2039 int *rdata_len,int *rparam_len)
2041 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2042 char *str2 = skip_string(param,tpscnt,str1);
2043 char *UserName = skip_string(param,tpscnt,str2);
2044 char *p = skip_string(param,tpscnt,UserName);
2045 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2046 const char *level_string;
2048 struct samu *sampw = NULL;
2056 enum lsa_SidType type;
2057 TALLOC_CTX *mem_ctx;
2059 if (!str1 || !str2 || !UserName || !p) {
2064 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2069 /* check it's a supported varient */
2071 if ( strcmp(str1,"zWrLeh") != 0 )
2076 level_string = "B21";
2082 if (strcmp(level_string,str2) != 0)
2085 *rdata_len = mdrcnt + 1024;
2086 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2090 SSVAL(*rparam,0,NERR_Success);
2091 SSVAL(*rparam,2,0); /* converter word */
2095 mem_ctx = talloc_new(NULL);
2096 if (mem_ctx == NULL) {
2097 DEBUG(0, ("talloc_new failed\n"));
2101 if ( !(sampw = samu_new(mem_ctx)) ) {
2102 DEBUG(0, ("samu_new() failed!\n"));
2103 TALLOC_FREE(mem_ctx);
2107 /* Lookup the user information; This should only be one of
2108 our accounts (not remote domains) */
2110 become_root(); /* ROOT BLOCK */
2112 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2113 NULL, NULL, &user_sid, &type)) {
2114 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2118 if (type != SID_NAME_USER) {
2119 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2120 sid_type_lookup(type)));
2124 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2125 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2126 sid_string_static(&user_sid), UserName));
2134 result = pdb_enum_group_memberships(mem_ctx, sampw,
2135 &sids, &gids, &num_groups);
2137 if (!NT_STATUS_IS_OK(result)) {
2138 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2143 for (i=0; i<num_groups; i++) {
2145 const char *grp_name;
2147 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2148 pstrcpy(p, grp_name);
2154 *rdata_len = PTR_DIFF(p,*rdata);
2156 SSVAL(*rparam,4,count); /* is this right?? */
2157 SSVAL(*rparam,6,count); /* is this right?? */
2162 unbecome_root(); /* END ROOT BLOCK */
2164 TALLOC_FREE(mem_ctx);
2169 /*******************************************************************
2171 ******************************************************************/
2173 static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2174 char *param, int tpscnt,
2175 char *data, int tdscnt,
2176 int mdrcnt,int mprcnt,
2177 char **rdata,char **rparam,
2178 int *rdata_len,int *rparam_len)
2183 int i, resume_context, cli_buf_size;
2184 struct pdb_search *search;
2185 struct samr_displayentry *users;
2187 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2188 char *str2 = skip_string(param,tpscnt,str1);
2189 char *p = skip_string(param,tpscnt,str2);
2191 if (!str1 || !str2 || !p) {
2195 if (strcmp(str1,"WrLeh") != 0)
2198 * W-> resume context (number of users to skip)
2199 * r -> return parameter pointer to receive buffer
2200 * L -> length of receive buffer
2201 * e -> return parameter number of entries
2202 * h -> return parameter total number of users
2205 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2206 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2207 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2208 resume_context, cli_buf_size));
2211 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2216 /* check it's a supported varient */
2217 if (strcmp("B21",str2) != 0)
2220 *rdata_len = cli_buf_size;
2221 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2229 search = pdb_search_users(ACB_NORMAL);
2231 if (search == NULL) {
2232 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2237 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2241 errflags=NERR_Success;
2243 for (i=0; i<num_users; i++) {
2244 const char *name = users[i].account_name;
2246 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2248 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2249 "%s\n",count_sent,p));
2253 /* set overflow error */
2254 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2255 "username %s\n",count_sent,name));
2261 pdb_search_destroy(search);
2263 *rdata_len = PTR_DIFF(p,*rdata);
2265 SSVAL(*rparam,0,errflags);
2266 SSVAL(*rparam,2,0); /* converter word */
2267 SSVAL(*rparam,4,count_sent); /* is this right?? */
2268 SSVAL(*rparam,6,num_users); /* is this right?? */
2273 /****************************************************************************
2274 Get the time of day info.
2275 ****************************************************************************/
2277 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2278 char *param, int tpscnt,
2279 char *data, int tdscnt,
2280 int mdrcnt,int mprcnt,
2281 char **rdata,char **rparam,
2282 int *rdata_len,int *rparam_len)
2285 time_t unixdate = time(NULL);
2289 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2295 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2300 SSVAL(*rparam,0,NERR_Success);
2301 SSVAL(*rparam,2,0); /* converter word */
2305 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2306 by NT in a "net time" operation,
2307 it seems to ignore the one below */
2309 /* the client expects to get localtime, not GMT, in this bit
2310 (I think, this needs testing) */
2311 t = localtime(&unixdate);
2316 SIVAL(p,4,0); /* msecs ? */
2317 SCVAL(p,8,t->tm_hour);
2318 SCVAL(p,9,t->tm_min);
2319 SCVAL(p,10,t->tm_sec);
2320 SCVAL(p,11,0); /* hundredths of seconds */
2321 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2322 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2323 SCVAL(p,16,t->tm_mday);
2324 SCVAL(p,17,t->tm_mon + 1);
2325 SSVAL(p,18,1900+t->tm_year);
2326 SCVAL(p,20,t->tm_wday);
2331 /****************************************************************************
2332 Set the user password.
2333 *****************************************************************************/
2335 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
2336 char *param, int tpscnt,
2337 char *data, int tdscnt,
2338 int mdrcnt,int mprcnt,
2339 char **rdata,char **rparam,
2340 int *rdata_len,int *rparam_len)
2342 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2345 fstring pass1,pass2;
2347 /* Skip 2 strings. */
2348 p = skip_string(param,tpscnt,np);
2349 p = skip_string(param,tpscnt,p);
2355 /* Do we have a string ? */
2356 if (skip_string(param,tpscnt,p) == NULL) {
2359 pull_ascii_fstring(user,p);
2361 p = skip_string(param,tpscnt,p);
2366 memset(pass1,'\0',sizeof(pass1));
2367 memset(pass2,'\0',sizeof(pass2));
2368 if (!is_offset_safe(param,tpscnt,p,32)) {
2372 memcpy(pass2,p+16,16);
2375 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2382 SSVAL(*rparam,0,NERR_badpass);
2383 SSVAL(*rparam,2,0); /* converter word */
2385 DEBUG(3,("Set password for <%s>\n",user));
2388 * Attempt to verify the old password against smbpasswd entries
2389 * Win98 clients send old and new password in plaintext for this call.
2393 auth_serversupplied_info *server_info = NULL;
2394 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2396 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2399 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2400 SSVAL(*rparam,0,NERR_Success);
2404 TALLOC_FREE(server_info);
2406 data_blob_clear_free(&password);
2410 * If the plaintext change failed, attempt
2411 * the old encrypted method. NT will generate this
2412 * after trying the samr method. Note that this
2413 * method is done as a last resort as this
2414 * password change method loses the NT password hash
2415 * and cannot change the UNIX password as no plaintext
2419 if(SVAL(*rparam,0) != NERR_Success) {
2420 struct samu *hnd = NULL;
2422 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2424 if (change_lanman_password(hnd,(uchar *)pass2)) {
2425 SSVAL(*rparam,0,NERR_Success);
2432 memset((char *)pass1,'\0',sizeof(fstring));
2433 memset((char *)pass2,'\0',sizeof(fstring));
2438 /****************************************************************************
2439 Set the user password (SamOEM version - gets plaintext).
2440 ****************************************************************************/
2442 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2443 char *param, int tpscnt,
2444 char *data, int tdscnt,
2445 int mdrcnt,int mprcnt,
2446 char **rdata,char **rparam,
2447 int *rdata_len,int *rparam_len)
2450 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2452 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2462 SSVAL(*rparam,0,NERR_badpass);
2465 * Check the parameter definition is correct.
2468 /* Do we have a string ? */
2469 if (skip_string(param,tpscnt,p) == 0) {
2472 if(!strequal(p, "zsT")) {
2473 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2476 p = skip_string(param, tpscnt, p);
2481 /* Do we have a string ? */
2482 if (skip_string(param,tpscnt,p) == 0) {
2485 if(!strequal(p, "B516B16")) {
2486 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2489 p = skip_string(param,tpscnt,p);
2493 /* Do we have a string ? */
2494 if (skip_string(param,tpscnt,p) == 0) {
2497 p += pull_ascii_fstring(user,p);
2499 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2502 * Pass the user through the NT -> unix user mapping
2506 (void)map_username(user);
2508 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2509 SSVAL(*rparam,0,NERR_Success);
2515 /****************************************************************************
2518 ****************************************************************************/
2520 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2521 char *param, int tpscnt,
2522 char *data, int tdscnt,
2523 int mdrcnt,int mprcnt,
2524 char **rdata,char **rparam,
2525 int *rdata_len,int *rparam_len)
2527 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2528 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2529 char *str2 = skip_string(param,tpscnt,str1);
2530 char *p = skip_string(param,tpscnt,str2);
2535 WERROR werr = WERR_OK;
2537 if (!str1 || !str2 || !p) {
2540 if (!is_offset_safe(param,tpscnt,p,2)) {
2543 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2546 /* check it's a supported varient */
2547 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2551 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2557 if (!print_job_exists(sharename, jobid)) {
2558 errcode = NERR_JobNotFound;
2562 snum = lp_servicenumber( sharename);
2564 errcode = NERR_DestNotFound;
2568 errcode = NERR_notsupported;
2571 case 81: /* delete */
2572 if (print_job_delete(¤t_user, snum, jobid, &werr))
2573 errcode = NERR_Success;
2575 case 82: /* pause */
2576 if (print_job_pause(¤t_user, snum, jobid, &werr))
2577 errcode = NERR_Success;
2579 case 83: /* resume */
2580 if (print_job_resume(¤t_user, snum, jobid, &werr))
2581 errcode = NERR_Success;
2585 if (!W_ERROR_IS_OK(werr))
2586 errcode = W_ERROR_V(werr);
2589 SSVAL(*rparam,0,errcode);
2590 SSVAL(*rparam,2,0); /* converter word */
2595 /****************************************************************************
2596 Purge a print queue - or pause or resume it.
2597 ****************************************************************************/
2599 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2600 char *param, int tpscnt,
2601 char *data, int tdscnt,
2602 int mdrcnt,int mprcnt,
2603 char **rdata,char **rparam,
2604 int *rdata_len,int *rparam_len)
2606 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2607 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2608 char *str2 = skip_string(param,tpscnt,str1);
2609 char *QueueName = skip_string(param,tpscnt,str2);
2610 int errcode = NERR_notsupported;
2612 WERROR werr = WERR_OK;
2614 if (!str1 || !str2 || !QueueName) {
2618 /* check it's a supported varient */
2619 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2623 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2629 if (skip_string(param,tpscnt,QueueName) == NULL) {
2632 snum = print_queue_snum(QueueName);
2635 errcode = NERR_JobNotFound;
2640 case 74: /* Pause queue */
2641 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2643 case 75: /* Resume queue */
2644 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2646 case 103: /* Purge */
2647 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2651 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2654 SSVAL(*rparam,0,errcode);
2655 SSVAL(*rparam,2,0); /* converter word */
2660 /****************************************************************************
2661 set the property of a print job (undocumented?)
2662 ? function = 0xb -> set name of print job
2663 ? function = 0x6 -> move print job up/down
2664 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2665 or <WWsTP> <WB21BB16B10zWWzDDz>
2666 ****************************************************************************/
2668 static int check_printjob_info(struct pack_desc* desc,
2669 int uLevel, char* id)
2671 desc->subformat = NULL;
2673 case 0: desc->format = "W"; break;
2674 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2675 case 2: desc->format = "WWzWWDDzz"; break;
2676 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2677 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2678 default: return False;
2680 if (strcmp(desc->format,id) != 0) return False;
2684 static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2685 char *param, int tpscnt,
2686 char *data, int tdscnt,
2687 int mdrcnt,int mprcnt,
2688 char **rdata,char **rparam,
2689 int *rdata_len,int *rparam_len)
2691 struct pack_desc desc;
2692 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2693 char *str2 = skip_string(param,tpscnt,str1);
2694 char *p = skip_string(param,tpscnt,str2);
2697 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2698 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2701 if (!str1 || !str2 || !p) {
2704 if (!is_offset_safe(param,tpscnt,p,2)) {
2707 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2710 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2715 if (!share_defined(sharename)) {
2716 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2723 /* check it's a supported varient */
2724 if ((strcmp(str1,"WWsTP")) ||
2725 (!check_printjob_info(&desc,uLevel,str2)))
2728 if (!print_job_exists(sharename, jobid)) {
2729 errcode=NERR_JobNotFound;
2733 errcode = NERR_notsupported;
2737 /* change job place in the queue,
2738 data gives the new place */
2739 place = SVAL(data,0);
2740 if (print_job_set_place(sharename, jobid, place)) {
2741 errcode=NERR_Success;
2746 /* change print job name, data gives the name */
2747 if (print_job_set_name(sharename, jobid, data)) {
2748 errcode=NERR_Success;
2757 SSVALS(*rparam,0,errcode);
2758 SSVAL(*rparam,2,0); /* converter word */
2764 /****************************************************************************
2765 Get info about the server.
2766 ****************************************************************************/
2768 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2769 char *param, int tpscnt,
2770 char *data, int tdscnt,
2771 int mdrcnt,int mprcnt,
2772 char **rdata,char **rparam,
2773 int *rdata_len,int *rparam_len)
2775 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2776 char *str2 = skip_string(param,tpscnt,str1);
2777 char *p = skip_string(param,tpscnt,str2);
2778 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2782 if (!str1 || !str2 || !p) {
2786 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2788 /* check it's a supported varient */
2789 if (!prefix_ok(str1,"WrLh")) {
2795 if (strcmp(str2,"B16") != 0) {
2801 if (strcmp(str2,"B16BBDz") != 0) {
2807 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2813 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2819 if (strcmp(str2,"DN") != 0) {
2825 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2834 *rdata_len = mdrcnt;
2835 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2841 p2 = p + struct_len;
2843 srvstr_push(NULL, p,global_myname(),16,
2844 STR_ASCII|STR_UPPER|STR_TERMINATE);
2848 struct srv_info_struct *servers=NULL;
2851 uint32 servertype= lp_default_server_announce();
2853 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2855 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2856 for (i=0;i<count;i++) {
2857 if (strequal(servers[i].name,global_myname())) {
2858 servertype = servers[i].type;
2859 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2866 SCVAL(p,0,lp_major_announce_version());
2867 SCVAL(p,1,lp_minor_announce_version());
2868 SIVAL(p,2,servertype);
2870 if (mdrcnt == struct_len) {
2873 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2874 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2875 conn->connectpath, conn->gid,
2876 get_current_username(),
2877 current_user_info.domain,
2878 comment, sizeof(comment));
2879 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2880 p2 = skip_string(*rdata,*rdata_len,p2);
2888 return False; /* not yet implemented */
2891 *rdata_len = PTR_DIFF(p2,*rdata);
2894 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2898 SSVAL(*rparam,0,NERR_Success);
2899 SSVAL(*rparam,2,0); /* converter word */
2900 SSVAL(*rparam,4,*rdata_len);
2905 /****************************************************************************
2906 Get info about the server.
2907 ****************************************************************************/
2909 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
2910 char *param, int tpscnt,
2911 char *data, int tdscnt,
2912 int mdrcnt,int mprcnt,
2913 char **rdata,char **rparam,
2914 int *rdata_len,int *rparam_len)
2916 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2917 char *str2 = skip_string(param,tpscnt,str1);
2918 char *p = skip_string(param,tpscnt,str2);
2920 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
2922 if (!str1 || !str2 || !p) {
2926 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2929 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2934 /* check it's a supported varient */
2935 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2939 *rdata_len = mdrcnt + 1024;
2940 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2945 SSVAL(*rparam,0,NERR_Success);
2946 SSVAL(*rparam,2,0); /* converter word */
2949 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
2954 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2955 pstrcpy(p2,get_local_machine_name());
2957 p2 = skip_string(*rdata,*rdata_len,p2);
2963 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2964 pstrcpy(p2,current_user_info.smb_name);
2965 p2 = skip_string(*rdata,*rdata_len,p2);
2971 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2972 pstrcpy(p2,lp_workgroup());
2974 p2 = skip_string(*rdata,*rdata_len,p2);
2980 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2981 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2984 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2985 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2986 p2 = skip_string(*rdata,*rdata_len,p2);
2992 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2994 p2 = skip_string(*rdata,*rdata_len,p2);
3000 *rdata_len = PTR_DIFF(p2,*rdata);
3002 SSVAL(*rparam,4,*rdata_len);
3007 /****************************************************************************
3008 get info about a user
3010 struct user_info_11 {
3011 char usri11_name[21]; 0-20
3013 char *usri11_comment; 22-25
3014 char *usri11_usr_comment; 26-29
3015 unsigned short usri11_priv; 30-31
3016 unsigned long usri11_auth_flags; 32-35
3017 long usri11_password_age; 36-39
3018 char *usri11_homedir; 40-43
3019 char *usri11_parms; 44-47
3020 long usri11_last_logon; 48-51
3021 long usri11_last_logoff; 52-55
3022 unsigned short usri11_bad_pw_count; 56-57
3023 unsigned short usri11_num_logons; 58-59
3024 char *usri11_logon_server; 60-63
3025 unsigned short usri11_country_code; 64-65
3026 char *usri11_workstations; 66-69
3027 unsigned long usri11_max_storage; 70-73
3028 unsigned short usri11_units_per_week; 74-75
3029 unsigned char *usri11_logon_hours; 76-79
3030 unsigned short usri11_code_page; 80-81
3035 usri11_name specifies the user name for which information is retireved
3037 usri11_pad aligns the next data structure element to a word boundary
3039 usri11_comment is a null terminated ASCII comment
3041 usri11_user_comment is a null terminated ASCII comment about the user
3043 usri11_priv specifies the level of the privilege assigned to the user.
3044 The possible values are:
3046 Name Value Description
3047 USER_PRIV_GUEST 0 Guest privilege
3048 USER_PRIV_USER 1 User privilege
3049 USER_PRV_ADMIN 2 Administrator privilege
3051 usri11_auth_flags specifies the account operator privileges. The
3052 possible values are:
3054 Name Value Description
3055 AF_OP_PRINT 0 Print operator
3058 Leach, Naik [Page 28]
3062 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3065 AF_OP_COMM 1 Communications operator
3066 AF_OP_SERVER 2 Server operator
3067 AF_OP_ACCOUNTS 3 Accounts operator
3070 usri11_password_age specifies how many seconds have elapsed since the
3071 password was last changed.
3073 usri11_home_dir points to a null terminated ASCII string that contains
3074 the path name of the user's home directory.
3076 usri11_parms points to a null terminated ASCII string that is set
3077 aside for use by applications.
3079 usri11_last_logon specifies the time when the user last logged on.
3080 This value is stored as the number of seconds elapsed since
3081 00:00:00, January 1, 1970.
3083 usri11_last_logoff specifies the time when the user last logged off.
3084 This value is stored as the number of seconds elapsed since
3085 00:00:00, January 1, 1970. A value of 0 means the last logoff
3088 usri11_bad_pw_count specifies the number of incorrect passwords
3089 entered since the last successful logon.
3091 usri11_log1_num_logons specifies the number of times this user has
3092 logged on. A value of -1 means the number of logons is unknown.
3094 usri11_logon_server points to a null terminated ASCII string that
3095 contains the name of the server to which logon requests are sent.
3096 A null string indicates logon requests should be sent to the
3099 usri11_country_code specifies the country code for the user's language
3102 usri11_workstations points to a null terminated ASCII string that
3103 contains the names of workstations the user may log on from.
3104 There may be up to 8 workstations, with the names separated by
3105 commas. A null strings indicates there are no restrictions.
3107 usri11_max_storage specifies the maximum amount of disk space the user
3108 can occupy. A value of 0xffffffff indicates there are no
3111 usri11_units_per_week specifies the equal number of time units into
3112 which a week is divided. This value must be equal to 168.
3114 usri11_logon_hours points to a 21 byte (168 bits) string that
3115 specifies the time during which the user can log on. Each bit
3116 represents one unique hour in a week. The first bit (bit 0, word
3117 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3121 Leach, Naik [Page 29]
3125 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3128 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3129 are no restrictions.
3131 usri11_code_page specifies the code page for the user's language of
3134 All of the pointers in this data structure need to be treated
3135 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3136 to be ignored. The converter word returned in the parameters section
3137 needs to be subtracted from the lower 16 bits to calculate an offset
3138 into the return buffer where this ASCII string resides.
3140 There is no auxiliary data in the response.
3142 ****************************************************************************/
3144 #define usri11_name 0
3145 #define usri11_pad 21
3146 #define usri11_comment 22
3147 #define usri11_usr_comment 26
3148 #define usri11_full_name 30
3149 #define usri11_priv 34
3150 #define usri11_auth_flags 36
3151 #define usri11_password_age 40
3152 #define usri11_homedir 44
3153 #define usri11_parms 48
3154 #define usri11_last_logon 52
3155 #define usri11_last_logoff 56
3156 #define usri11_bad_pw_count 60
3157 #define usri11_num_logons 62
3158 #define usri11_logon_server 64
3159 #define usri11_country_code 68
3160 #define usri11_workstations 70
3161 #define usri11_max_storage 74
3162 #define usri11_units_per_week 78
3163 #define usri11_logon_hours 80
3164 #define usri11_code_page 84
3165 #define usri11_end 86
3167 #define USER_PRIV_GUEST 0
3168 #define USER_PRIV_USER 1
3169 #define USER_PRIV_ADMIN 2
3171 #define AF_OP_PRINT 0
3172 #define AF_OP_COMM 1
3173 #define AF_OP_SERVER 2
3174 #define AF_OP_ACCOUNTS 3
3177 static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3178 char *param, int tpscnt,
3179 char *data, int tdscnt,
3180 int mdrcnt,int mprcnt,
3181 char **rdata,char **rparam,
3182 int *rdata_len,int *rparam_len)
3184 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3185 char *str2 = skip_string(param,tpscnt,str1);
3186 char *UserName = skip_string(param,tpscnt,str2);
3187 char *p = skip_string(param,tpscnt,UserName);
3188 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3190 const char *level_string;
3192 /* get NIS home of a previously validated user - simeon */
3193 /* With share level security vuid will always be zero.
3194 Don't depend on vuser being non-null !!. JRA */
3195 user_struct *vuser = get_valid_user_struct(vuid);
3197 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3198 vuser->user.unix_name));
3201 if (!str1 || !str2 || !UserName || !p) {
3206 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3211 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3213 /* check it's a supported variant */
3214 if (strcmp(str1,"zWrLh") != 0) {
3218 case 0: level_string = "B21"; break;
3219 case 1: level_string = "B21BB16DWzzWz"; break;
3220 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3221 case 10: level_string = "B21Bzzz"; break;
3222 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3223 default: return False;
3226 if (strcmp(level_string,str2) != 0) {
3230 *rdata_len = mdrcnt + 1024;
3231 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3236 SSVAL(*rparam,0,NERR_Success);
3237 SSVAL(*rparam,2,0); /* converter word */
3240 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3246 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3249 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3254 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3255 pstrcpy(p2,"Comment");
3256 p2 = skip_string(*rdata,*rdata_len,p2);
3261 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3262 pstrcpy(p2,"UserComment");
3263 p2 = skip_string(*rdata,*rdata_len,p2);
3268 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3269 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3270 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3271 p2 = skip_string(*rdata,*rdata_len,p2);
3278 /* modelled after NTAS 3.51 reply */
3279 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3280 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3281 SIVALS(p,usri11_password_age,-1); /* password age */
3282 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3283 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3284 p2 = skip_string(*rdata,*rdata_len,p2);
3288 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3290 p2 = skip_string(*rdata,*rdata_len,p2);
3294 SIVAL(p,usri11_last_logon,0); /* last logon */
3295 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3296 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3297 SSVALS(p,usri11_num_logons,-1); /* num logons */
3298 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3299 pstrcpy(p2,"\\\\*");
3300 p2 = skip_string(*rdata,*rdata_len,p2);
3304 SSVAL(p,usri11_country_code,0); /* country code */
3306 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3308 p2 = skip_string(*rdata,*rdata_len,p2);
3313 SIVALS(p,usri11_max_storage,-1); /* max storage */
3314 SSVAL(p,usri11_units_per_week,168); /* units per week */
3315 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3317 /* a simple way to get logon hours at all times. */
3319 SCVAL(p2,21,0); /* fix zero termination */
3320 p2 = skip_string(*rdata,*rdata_len,p2);
3325 SSVAL(p,usri11_code_page,0); /* code page */
3328 if (uLevel == 1 || uLevel == 2) {
3329 memset(p+22,' ',16); /* password */
3330 SIVALS(p,38,-1); /* password age */
3332 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3333 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3334 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3335 p2 = skip_string(*rdata,*rdata_len,p2);
3339 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3341 SSVAL(p,52,0); /* flags */
3342 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3343 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3344 p2 = skip_string(*rdata,*rdata_len,p2);
3349 SIVAL(p,60,0); /* auth_flags */
3350 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3351 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3352 p2 = skip_string(*rdata,*rdata_len,p2);
3356 SIVAL(p,68,0); /* urs_comment */
3357 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3359 p2 = skip_string(*rdata,*rdata_len,p2);
3363 SIVAL(p,76,0); /* workstations */
3364 SIVAL(p,80,0); /* last_logon */
3365 SIVAL(p,84,0); /* last_logoff */
3366 SIVALS(p,88,-1); /* acct_expires */
3367 SIVALS(p,92,-1); /* max_storage */
3368 SSVAL(p,96,168); /* units_per_week */
3369 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3372 SSVALS(p,102,-1); /* bad_pw_count */
3373 SSVALS(p,104,-1); /* num_logons */
3374 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3377 pstrcpy(tmp, "\\\\%L");
3378 standard_sub_basic("", "", tmp, sizeof(tmp));
3381 p2 = skip_string(*rdata,*rdata_len,p2);
3385 SSVAL(p,110,49); /* country_code */
3386 SSVAL(p,112,860); /* code page */
3390 *rdata_len = PTR_DIFF(p2,*rdata);
3392 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3397 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3398 char *param, int tpscnt,
3399 char *data, int tdscnt,
3400 int mdrcnt,int mprcnt,
3401 char **rdata,char **rparam,
3402 int *rdata_len,int *rparam_len)
3404 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3405 char *str2 = skip_string(param,tpscnt,str1);
3406 char *p = skip_string(param,tpscnt,str2);
3408 struct pack_desc desc;
3410 /* With share level security vuid will always be zero.
3411 Don't depend on vuser being non-null !!. JRA */
3412 user_struct *vuser = get_valid_user_struct(vuid);
3414 if (!str1 || !str2 || !p) {
3419 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3420 vuser->user.unix_name));
3423 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3424 name = get_safe_str_ptr(param,tpscnt,p,2);
3429 memset((char *)&desc,'\0',sizeof(desc));
3431 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3433 /* check it's a supported varient */
3434 if (strcmp(str1,"OOWb54WrLh") != 0) {
3437 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3441 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3448 desc.buflen = mdrcnt;
3449 desc.subformat = NULL;
3452 if (init_package(&desc,1,0)) {
3453 PACKI(&desc,"W",0); /* code */
3454 PACKS(&desc,"B21",name); /* eff. name */
3455 PACKS(&desc,"B",""); /* pad */
3456 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3457 PACKI(&desc,"D",0); /* auth flags XXX */
3458 PACKI(&desc,"W",0); /* num logons */
3459 PACKI(&desc,"W",0); /* bad pw count */
3460 PACKI(&desc,"D",0); /* last logon */
3461 PACKI(&desc,"D",-1); /* last logoff */
3462 PACKI(&desc,"D",-1); /* logoff time */
3463 PACKI(&desc,"D",-1); /* kickoff time */
3464 PACKI(&desc,"D",0); /* password age */
3465 PACKI(&desc,"D",0); /* password can change */
3466 PACKI(&desc,"D",-1); /* password must change */
3470 fstrcpy(mypath,"\\\\");
3471 fstrcat(mypath,get_local_machine_name());
3473 PACKS(&desc,"z",mypath); /* computer */
3476 PACKS(&desc,"z",lp_workgroup());/* domain */
3477 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3478 PACKI(&desc,"D",0x00000000); /* reserved */
3481 *rdata_len = desc.usedlen;
3483 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3487 SSVALS(*rparam,0,desc.errcode);
3489 SSVAL(*rparam,4,desc.neededlen);
3491 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3496 /****************************************************************************
3497 api_WAccessGetUserPerms
3498 ****************************************************************************/
3500 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3501 char *param, int tpscnt,
3502 char *data, int tdscnt,
3503 int mdrcnt,int mprcnt,
3504 char **rdata,char **rparam,
3505 int *rdata_len,int *rparam_len)
3507 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3508 char *str2 = skip_string(param,tpscnt,str1);
3509 char *user = skip_string(param,tpscnt,str2);
3510 char *resource = skip_string(param,tpscnt,user);
3512 if (!str1 || !str2 || !user || !resource) {
3516 if (skip_string(param,tpscnt,resource) == NULL) {
3519 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3521 /* check it's a supported varient */
3522 if (strcmp(str1,"zzh") != 0) {
3525 if (strcmp(str2,"") != 0) {
3530 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3534 SSVALS(*rparam,0,0); /* errorcode */
3535 SSVAL(*rparam,2,0); /* converter word */
3536 SSVAL(*rparam,4,0x7f); /* permission flags */
3541 /****************************************************************************
3542 api_WPrintJobEnumerate
3543 ****************************************************************************/
3545 static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3546 char *param, int tpscnt,
3547 char *data, int tdscnt,
3548 int mdrcnt,int mprcnt,
3549 char **rdata,char **rparam,
3550 int *rdata_len,int *rparam_len)
3552 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3553 char *str2 = skip_string(param,tpscnt,str1);
3554 char *p = skip_string(param,tpscnt,str2);
3561 struct pack_desc desc;
3562 print_queue_struct *queue=NULL;
3563 print_status_struct status;
3566 if (!str1 || !str2 || !p) {
3570 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3572 memset((char *)&desc,'\0',sizeof(desc));
3573 memset((char *)&status,'\0',sizeof(status));
3575 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3577 /* check it's a supported varient */
3578 if (strcmp(str1,"WWrLh") != 0) {
3581 if (!check_printjob_info(&desc,uLevel,str2)) {
3585 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3589 snum = lp_servicenumber( sharename);
3590 if (snum < 0 || !VALID_SNUM(snum)) {
3594 count = print_queue_status(snum,&queue,&status);
3595 for (i = 0; i < count; i++) {
3596 if (queue[i].job == jobid) {
3602 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3607 desc.buflen = mdrcnt;
3610 * Don't return data but need to get correct length
3611 * init_package will return wrong size if buflen=0
3613 desc.buflen = getlen(desc.format);
3614 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3617 if (init_package(&desc,1,0)) {
3619 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3620 *rdata_len = desc.usedlen;
3622 desc.errcode = NERR_JobNotFound;
3628 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3632 SSVALS(*rparam,0,desc.errcode);
3634 SSVAL(*rparam,4,desc.neededlen);
3639 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3644 static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3645 char *param, int tpscnt,
3646 char *data, int tdscnt,
3647 int mdrcnt,int mprcnt,
3648 char **rdata,char **rparam,
3649 int *rdata_len,int *rparam_len)
3651 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3652 char *str2 = skip_string(param,tpscnt,str1);
3653 char *p = skip_string(param,tpscnt,str2);
3659 struct pack_desc desc;
3660 print_queue_struct *queue=NULL;
3661 print_status_struct status;
3663 if (!str1 || !str2 || !p) {
3667 memset((char *)&desc,'\0',sizeof(desc));
3668 memset((char *)&status,'\0',sizeof(status));
3670 p = skip_string(param,tpscnt,p);
3674 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3676 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3678 /* check it's a supported variant */
3679 if (strcmp(str1,"zWrLeh") != 0) {
3684 return False; /* defined only for uLevel 0,1,2 */
3687 if (!check_printjob_info(&desc,uLevel,str2)) {
3691 snum = find_service(name);
3692 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3696 count = print_queue_status(snum,&queue,&status);
3698 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3704 desc.buflen = mdrcnt;
3706 if (init_package(&desc,count,0)) {
3708 for (i = 0; i < count; i++) {
3709 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3710 if (desc.errcode == NERR_Success) {
3716 *rdata_len = desc.usedlen;
3719 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3723 SSVALS(*rparam,0,desc.errcode);
3725 SSVAL(*rparam,4,succnt);
3726 SSVAL(*rparam,6,count);
3730 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3735 static int check_printdest_info(struct pack_desc* desc,
3736 int uLevel, char* id)
3738 desc->subformat = NULL;
3741 desc->format = "B9";
3744 desc->format = "B9B21WWzW";
3750 desc->format = "zzzWWzzzWW";
3755 if (strcmp(desc->format,id) != 0) {
3761 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3762 struct pack_desc* desc)
3766 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3767 buf[sizeof(buf)-1] = 0;
3771 PACKS(desc,"B9",buf); /* szName */
3773 PACKS(desc,"B21",""); /* szUserName */
3774 PACKI(desc,"W",0); /* uJobId */
3775 PACKI(desc,"W",0); /* fsStatus */
3776 PACKS(desc,"z",""); /* pszStatus */
3777 PACKI(desc,"W",0); /* time */
3781 if (uLevel == 2 || uLevel == 3) {
3782 PACKS(desc,"z",buf); /* pszPrinterName */
3784 PACKS(desc,"z",""); /* pszUserName */
3785 PACKS(desc,"z",""); /* pszLogAddr */
3786 PACKI(desc,"W",0); /* uJobId */
3787 PACKI(desc,"W",0); /* fsStatus */
3788 PACKS(desc,"z",""); /* pszStatus */
3789 PACKS(desc,"z",""); /* pszComment */
3790 PACKS(desc,"z","NULL"); /* pszDrivers */
3791 PACKI(desc,"W",0); /* time */
3792 PACKI(desc,"W",0); /* pad1 */
3797 static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3798 char *param, int tpscnt,
3799 char *data, int tdscnt,
3800 int mdrcnt,int mprcnt,
3801 char **rdata,char **rparam,
3802 int *rdata_len,int *rparam_len)
3804 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3805 char *str2 = skip_string(param,tpscnt,str1);
3806 char *p = skip_string(param,tpscnt,str2);
3807 char* PrinterName = p;
3809 struct pack_desc desc;
3813 if (!str1 || !str2 || !p) {
3817 memset((char *)&desc,'\0',sizeof(desc));
3819 p = skip_string(param,tpscnt,p);
3823 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3825 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3827 /* check it's a supported varient */
3828 if (strcmp(str1,"zWrLh") != 0) {
3831 if (!check_printdest_info(&desc,uLevel,str2)) {
3835 snum = find_service(PrinterName);
3836 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3838 desc.errcode = NERR_DestNotFound;
3842 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3847 desc.buflen = mdrcnt;
3850 * Don't return data but need to get correct length
3851 * init_package will return wrong size if buflen=0
3853 desc.buflen = getlen(desc.format);
3854 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3856 if (init_package(&desc,1,0)) {
3857 fill_printdest_info(conn,snum,uLevel,&desc);
3859 *rdata_len = desc.usedlen;
3863 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3867 SSVALS(*rparam,0,desc.errcode);
3869 SSVAL(*rparam,4,desc.neededlen);
3871 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3877 static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
3878 char *param, int tpscnt,
3879 char *data, int tdscnt,
3880 int mdrcnt,int mprcnt,
3881 char **rdata,char **rparam,
3882 int *rdata_len,int *rparam_len)
3884 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3885 char *str2 = skip_string(param,tpscnt,str1);
3886 char *p = skip_string(param,tpscnt,str2);
3890 struct pack_desc desc;
3891 int services = lp_numservices();
3893 if (!str1 || !str2 || !p) {
3897 memset((char *)&desc,'\0',sizeof(desc));
3899 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3901 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3903 /* check it's a supported varient */
3904 if (strcmp(str1,"WrLeh") != 0) {
3907 if (!check_printdest_info(&desc,uLevel,str2)) {
3912 for (i = 0; i < services; i++) {
3913 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3919 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3926 desc.buflen = mdrcnt;
3927 if (init_package(&desc,queuecnt,0)) {
3930 for (i = 0; i < services; i++) {
3931 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3932 fill_printdest_info(conn,i,uLevel,&desc);
3934 if (desc.errcode == NERR_Success) {
3941 *rdata_len = desc.usedlen;
3944 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3948 SSVALS(*rparam,0,desc.errcode);
3950 SSVAL(*rparam,4,succnt);
3951 SSVAL(*rparam,6,queuecnt);
3953 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3958 static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
3959 char *param, int tpscnt,
3960 char *data, int tdscnt,
3961 int mdrcnt,int mprcnt,
3962 char **rdata,char **rparam,
3963 int *rdata_len,int *rparam_len)
3965 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3966 char *str2 = skip_string(param,tpscnt,str1);
3967 char *p = skip_string(param,tpscnt,str2);
3970 struct pack_desc desc;
3972 if (!str1 || !str2 || !p) {
3976 memset((char *)&desc,'\0',sizeof(desc));
3978 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3980 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3982 /* check it's a supported varient */
3983 if (strcmp(str1,"WrLeh") != 0) {
3986 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
3991 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3997 desc.buflen = mdrcnt;
3998 if (init_package(&desc,1,0)) {
3999 PACKS(&desc,"B41","NULL");
4002 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4004 *rdata_len = desc.usedlen;
4007 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4011 SSVALS(*rparam,0,desc.errcode);
4013 SSVAL(*rparam,4,succnt);
4016 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4021 static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4022 char *param, int tpscnt,
4023 char *data, int tdscnt,
4024 int mdrcnt,int mprcnt,
4025 char **rdata,char **rparam,
4026 int *rdata_len,int *rparam_len)
4028 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4029 char *str2 = skip_string(param,tpscnt,str1);
4030 char *p = skip_string(param,tpscnt,str2);
4033 struct pack_desc desc;
4035 if (!str1 || !str2 || !p) {
4038 memset((char *)&desc,'\0',sizeof(desc));
4040 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4042 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4044 /* check it's a supported varient */
4045 if (strcmp(str1,"WrLeh") != 0) {
4048 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4053 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4059 desc.buflen = mdrcnt;
4061 if (init_package(&desc,1,0)) {
4062 PACKS(&desc,"B13","lpd");
4065 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4067 *rdata_len = desc.usedlen;
4070 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4074 SSVALS(*rparam,0,desc.errcode);
4076 SSVAL(*rparam,4,succnt);
4079 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4084 static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4085 char *param, int tpscnt,
4086 char *data, int tdscnt,
4087 int mdrcnt,int mprcnt,
4088 char **rdata,char **rparam,
4089 int *rdata_len,int *rparam_len)
4091 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4092 char *str2 = skip_string(param,tpscnt,str1);
4093 char *p = skip_string(param,tpscnt,str2);
4096 struct pack_desc desc;
4098 if (!str1 || !str2 || !p) {
4102 memset((char *)&desc,'\0',sizeof(desc));
4104 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4106 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4108 /* check it's a supported varient */
4109 if (strcmp(str1,"WrLeh") != 0) {
4112 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4117 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4122 memset((char *)&desc,'\0',sizeof(desc));
4124 desc.buflen = mdrcnt;
4126 if (init_package(&desc,1,0)) {
4127 PACKS(&desc,"B13","lp0");
4130 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4132 *rdata_len = desc.usedlen;
4135 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4139 SSVALS(*rparam,0,desc.errcode);
4141 SSVAL(*rparam,4,succnt);
4144 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4149 /****************************************************************************
4151 ****************************************************************************/
4153 static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4154 char *param, int tpscnt,
4155 char *data, int tdscnt,
4156 int mdrcnt,int mprcnt,
4157 char **rdata,char **rparam,
4158 int *rdata_len,int *rparam_len)
4161 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4162 char *str2 = skip_string(param,tpscnt,str1);
4163 char *p = skip_string(param,tpscnt,str2);
4165 struct pack_desc desc;
4166 struct sessionid *session_list;
4167 int i, num_sessions;
4169 if (!str1 || !str2 || !p) {
4173 memset((char *)&desc,'\0',sizeof(desc));
4175 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4177 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4178 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4179 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4181 /* check it's a supported varient */
4182 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4185 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4189 num_sessions = list_sessions(&session_list);
4192 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
4197 memset((char *)&desc,'\0',sizeof(desc));
4199 desc.buflen = mdrcnt;
4201 if (!init_package(&desc,num_sessions,0)) {
4205 for(i=0; i<num_sessions; i++) {
4206 PACKS(&desc, "z", session_list[i].remote_machine);
4207 PACKS(&desc, "z", session_list[i].username);
4208 PACKI(&desc, "W", 1); /* num conns */
4209 PACKI(&desc, "W", 0); /* num opens */
4210 PACKI(&desc, "W", 1); /* num users */
4211 PACKI(&desc, "D", 0); /* session time */
4212 PACKI(&desc, "D", 0); /* idle time */
4213 PACKI(&desc, "D", 0); /* flags */
4214 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4217 *rdata_len = desc.usedlen;
4220 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4224 SSVALS(*rparam,0,desc.errcode);
4225 SSVAL(*rparam,2,0); /* converter */
4226 SSVAL(*rparam,4,num_sessions); /* count */
4228 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4234 /****************************************************************************
4235 The buffer was too small.
4236 ****************************************************************************/
4238 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4239 int mdrcnt, int mprcnt,
4240 char **rdata, char **rparam,
4241 int *rdata_len, int *rparam_len)
4243 *rparam_len = MIN(*rparam_len,mprcnt);
4244 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4251 SSVAL(*rparam,0,NERR_BufTooSmall);
4253 DEBUG(3,("Supplied buffer too small in API command\n"));
4258 /****************************************************************************
4259 The request is not supported.
4260 ****************************************************************************/
4262 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
4263 char *param, int tpscnt,
4264 char *data, int tdscnt,
4265 int mdrcnt, int mprcnt,
4266 char **rdata, char **rparam,
4267 int *rdata_len, int *rparam_len)
4270 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
4277 SSVAL(*rparam,0,NERR_notsupported);
4278 SSVAL(*rparam,2,0); /* converter word */
4280 DEBUG(3,("Unsupported API command\n"));
4285 static const struct {
4288 BOOL (*fn)(connection_struct *, uint16,
4291 int,int,char **,char **,int *,int *);
4292 BOOL auth_user; /* Deny anonymous access? */
4293 } api_commands[] = {
4294 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4295 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4296 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4297 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4298 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4299 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4300 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4301 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4302 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4303 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4304 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4305 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4306 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4307 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4308 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4309 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4310 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4311 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4312 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4313 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4314 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4315 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4316 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4317 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4318 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4319 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4320 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4321 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4322 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4323 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4324 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4325 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4326 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4327 {NULL, -1, api_Unsupported}
4328 /* The following RAP calls are not implemented by Samba:
4330 RAP_WFileEnum2 - anon not OK
4335 /****************************************************************************
4336 Handle remote api calls
4337 ****************************************************************************/
4339 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4340 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4344 char *rparam = NULL;
4345 const char *name1 = NULL;
4346 const char *name2 = NULL;
4353 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4360 api_command = SVAL(params,0);
4361 /* Is there a string at position params+2 ? */
4362 if (skip_string(params,tpscnt,params+2)) {
4367 name2 = skip_string(params,tpscnt,params+2);
4372 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4376 tdscnt,tpscnt,mdrcnt,mprcnt));
4378 for (i=0;api_commands[i].name;i++) {
4379 if (api_commands[i].id == api_command && api_commands[i].fn) {
4380 DEBUG(3,("Doing %s\n",api_commands[i].name));
4385 /* Check whether this api call can be done anonymously */
4387 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4388 user_struct *user = get_valid_user_struct(vuid);
4390 if (!user || user->guest) {
4391 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4395 rdata = (char *)SMB_MALLOC(1024);
4397 memset(rdata,'\0',1024);
4400 rparam = (char *)SMB_MALLOC(1024);
4402 memset(rparam,'\0',1024);
4405 if(!rdata || !rparam) {
4406 DEBUG(0,("api_reply: malloc fail !\n"));
4412 reply = api_commands[i].fn(conn,
4414 params,tpscnt, /* params + length */
4415 data,tdscnt, /* data + length */
4417 &rdata,&rparam,&rdata_len,&rparam_len);
4420 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4421 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4422 &rdata,&rparam,&rdata_len,&rparam_len);
4425 /* if we get False back then it's actually unsupported */
4427 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4428 &rdata,&rparam,&rdata_len,&rparam_len);
4431 /* If api_Unsupported returns false we can't return anything. */
4433 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);