2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
30 extern struct current_user current_user;
31 extern userdom_struct current_user_info;
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param, char *data,
54 int mdrcnt, int mprcnt,
55 char **rdata, char **rparam,
56 int *rdata_len, int *rparam_len);
57 static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
58 int mdrcnt, int mprcnt,
59 char **rdata, char **rparam,
60 int *rdata_len, int *rparam_len);
63 static int CopyExpanded(connection_struct *conn,
64 int snum, char **dst, char *src, int *n)
69 if (!src || !dst || !n || !(*dst)) {
73 StrnCpy(buf,src,sizeof(buf)/2);
74 pstring_sub(buf,"%S",lp_servicename(snum));
75 standard_sub_conn(conn,buf,sizeof(buf));
76 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
82 static int CopyAndAdvance(char **dst, char *src, int *n)
85 if (!src || !dst || !n || !(*dst)) {
88 l = push_ascii(*dst,src,*n, STR_TERMINATE);
94 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
100 StrnCpy(buf,s,sizeof(buf)/2);
101 pstring_sub(buf,"%S",lp_servicename(snum));
102 standard_sub_conn(conn,buf,sizeof(buf));
103 return strlen(buf) + 1;
106 static char *Expand(connection_struct *conn, int snum, char *s)
112 StrnCpy(buf,s,sizeof(buf)/2);
113 pstring_sub(buf,"%S",lp_servicename(snum));
114 standard_sub_conn(conn,buf,sizeof(buf));
118 /*******************************************************************
119 Check a API string for validity when we only need to check the prefix.
120 ******************************************************************/
122 static BOOL prefix_ok(const char *str, const char *prefix)
124 return(strncmp(str,prefix,strlen(prefix)) == 0);
128 const char *format; /* formatstring for structure */
129 const char *subformat; /* subformat for structure */
130 char *base; /* baseaddress of buffer */
131 int buflen; /* remaining size for fixed part; on init: length of base */
132 int subcount; /* count of substructures */
133 char *structbuf; /* pointer into buffer for remaining fixed part */
134 int stringlen; /* remaining size for variable part */
135 char *stringbuf; /* pointer into buffer for remaining variable part */
136 int neededlen; /* total needed size */
137 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
138 const char *curpos; /* current position; pointer into format or subformat */
142 static int get_counter(const char **p)
148 if (!isdigit((int)**p)) {
154 n = 10 * n + (i - '0');
162 static int getlen(const char *p)
171 case 'W': /* word (2 byte) */
174 case 'K': /* status word? (2 byte) */
177 case 'N': /* count of substructures (word) at end */
180 case 'D': /* double word (4 byte) */
181 case 'z': /* offset to zero terminated string (4 byte) */
182 case 'l': /* offset to user data (4 byte) */
185 case 'b': /* offset to data (with counter) (4 byte) */
189 case 'B': /* byte (with optional counter) */
190 n += get_counter(&p);
197 static BOOL init_package(struct pack_desc *p, int count, int subcount)
202 if (!p->format || !p->base) {
206 i = count * getlen(p->format);
208 i += subcount * getlen(p->subformat);
210 p->structbuf = p->base;
214 p->curpos = p->format;
220 * This is the old error code we used. Aparently
221 * WinNT/2k systems return ERRbuftoosmall (2123) and
222 * OS/2 needs this. I'm leaving this here so we can revert
225 p->errcode = ERRmoredata;
227 p->errcode = ERRbuftoosmall;
230 p->errcode = NERR_Success;
234 p->stringbuf = p->base + i;
236 return (p->errcode == NERR_Success);
239 static int package(struct pack_desc *p, ...)
242 int needed=0, stringneeded;
243 const char *str=NULL;
244 int is_string=0, stringused;
251 p->curpos = p->format;
253 p->curpos = p->subformat;
258 str = va_arg(args,char*);
259 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
268 switch( *p->curpos++ ) {
269 case 'W': /* word (2 byte) */
271 temp = va_arg(args,int);
272 if (p->buflen >= needed) {
273 SSVAL(p->structbuf,0,temp);
276 case 'K': /* status word? (2 byte) */
278 temp = va_arg(args,int);
279 if (p->buflen >= needed) {
280 SSVAL(p->structbuf,0,temp);
283 case 'N': /* count of substructures (word) at end */
285 p->subcount = va_arg(args,int);
286 if (p->buflen >= needed) {
287 SSVAL(p->structbuf,0,p->subcount);
290 case 'D': /* double word (4 byte) */
292 temp = va_arg(args,int);
293 if (p->buflen >= needed) {
294 SIVAL(p->structbuf,0,temp);
297 case 'B': /* byte (with optional counter) */
298 needed = get_counter(&p->curpos);
300 char *s = va_arg(args,char*);
301 if (p->buflen >= needed) {
302 StrnCpy(p->structbuf,s?s:"",needed-1);
306 case 'z': /* offset to zero terminated string (4 byte) */
307 str = va_arg(args,char*);
308 stringneeded = (str ? strlen(str)+1 : 0);
311 case 'l': /* offset to user data (4 byte) */
312 str = va_arg(args,char*);
313 stringneeded = va_arg(args,int);
316 case 'b': /* offset to data (with counter) (4 byte) */
317 str = va_arg(args,char*);
318 stringneeded = get_counter(&p->curpos);
324 if (stringneeded >= 0) {
326 if (p->buflen >= needed) {
327 stringused = stringneeded;
328 if (stringused > p->stringlen) {
329 stringused = (is_string ? p->stringlen : 0);
330 if (p->errcode == NERR_Success) {
331 p->errcode = ERRmoredata;
335 SIVAL(p->structbuf,0,0);
337 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
338 memcpy(p->stringbuf,str?str:"",stringused);
340 p->stringbuf[stringused-1] = '\0';
342 p->stringbuf += stringused;
343 p->stringlen -= stringused;
344 p->usedlen += stringused;
347 p->neededlen += stringneeded;
350 p->neededlen += needed;
351 if (p->buflen >= needed) {
352 p->structbuf += needed;
354 p->usedlen += needed;
356 if (p->errcode == NERR_Success) {
357 p->errcode = ERRmoredata;
364 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
365 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
367 #define PACK(desc,t,v) package(desc,v)
368 #define PACKl(desc,t,v,l) package(desc,v,l)
371 static void PACKI(struct pack_desc* desc, const char *t,int v)
376 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
381 /****************************************************************************
383 ****************************************************************************/
385 static void PackDriverData(struct pack_desc* desc)
387 char drivdata[4+4+32];
388 SIVAL(drivdata,0,sizeof drivdata); /* cb */
389 SIVAL(drivdata,4,1000); /* lVersion */
390 memset(drivdata+8,0,32); /* szDeviceName */
391 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
392 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
395 static int check_printq_info(struct pack_desc* desc,
396 unsigned int uLevel, char *id1, char *id2)
398 desc->subformat = NULL;
401 desc->format = "B13";
404 desc->format = "B13BWWWzzzzzWW";
407 desc->format = "B13BWWWzzzzzWN";
408 desc->subformat = "WB21BB16B10zWWzDDz";
411 desc->format = "zWWWWzzzzWWzzl";
414 desc->format = "zWWWWzzzzWNzzl";
415 desc->subformat = "WWzWWDDzz";
424 desc->format = "WzzzzzzzzN";
425 desc->subformat = "z";
430 if (strcmp(desc->format,id1) != 0) {
433 if (desc->subformat && strcmp(desc->subformat,id2) != 0) {
440 #define RAP_JOB_STATUS_QUEUED 0
441 #define RAP_JOB_STATUS_PAUSED 1
442 #define RAP_JOB_STATUS_SPOOLING 2
443 #define RAP_JOB_STATUS_PRINTING 3
444 #define RAP_JOB_STATUS_PRINTED 4
446 #define RAP_QUEUE_STATUS_PAUSED 1
447 #define RAP_QUEUE_STATUS_ERROR 2
449 /* turn a print job status into a on the wire status
451 static int printj_status(int v)
455 return RAP_JOB_STATUS_QUEUED;
457 return RAP_JOB_STATUS_PAUSED;
459 return RAP_JOB_STATUS_SPOOLING;
461 return RAP_JOB_STATUS_PRINTING;
466 /* turn a print queue status into a on the wire status
468 static int printq_status(int v)
474 return RAP_QUEUE_STATUS_PAUSED;
476 return RAP_QUEUE_STATUS_ERROR;
479 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
480 struct pack_desc *desc,
481 print_queue_struct *queue, int n)
483 time_t t = queue->time;
485 /* the client expects localtime */
486 t -= get_time_zone(t);
488 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
490 PACKS(desc,"B21",queue->fs_user); /* szUserName */
491 PACKS(desc,"B",""); /* pad */
492 PACKS(desc,"B16",""); /* szNotifyName */
493 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
494 PACKS(desc,"z",""); /* pszParms */
495 PACKI(desc,"W",n+1); /* uPosition */
496 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
497 PACKS(desc,"z",""); /* pszStatus */
498 PACKI(desc,"D",t); /* ulSubmitted */
499 PACKI(desc,"D",queue->size); /* ulSize */
500 PACKS(desc,"z",queue->fs_file); /* pszComment */
502 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
503 PACKI(desc,"W",queue->priority); /* uPriority */
504 PACKS(desc,"z",queue->fs_user); /* pszUserName */
505 PACKI(desc,"W",n+1); /* uPosition */
506 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
507 PACKI(desc,"D",t); /* ulSubmitted */
508 PACKI(desc,"D",queue->size); /* ulSize */
509 PACKS(desc,"z","Samba"); /* pszComment */
510 PACKS(desc,"z",queue->fs_file); /* pszDocument */
512 PACKS(desc,"z",""); /* pszNotifyName */
513 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
514 PACKS(desc,"z",""); /* pszParms */
515 PACKS(desc,"z",""); /* pszStatus */
516 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
517 PACKS(desc,"z","lpd"); /* pszQProcName */
518 PACKS(desc,"z",""); /* pszQProcParms */
519 PACKS(desc,"z","NULL"); /* pszDriverName */
520 PackDriverData(desc); /* pDriverData */
521 PACKS(desc,"z",""); /* pszPrinterName */
522 } else if (uLevel == 4) { /* OS2 */
523 PACKS(desc,"z",""); /* pszSpoolFileName */
524 PACKS(desc,"z",""); /* pszPortName */
525 PACKS(desc,"z",""); /* pszStatus */
526 PACKI(desc,"D",0); /* ulPagesSpooled */
527 PACKI(desc,"D",0); /* ulPagesSent */
528 PACKI(desc,"D",0); /* ulPagesPrinted */
529 PACKI(desc,"D",0); /* ulTimePrinted */
530 PACKI(desc,"D",0); /* ulExtendJobStatus */
531 PACKI(desc,"D",0); /* ulStartPage */
532 PACKI(desc,"D",0); /* ulEndPage */
537 /********************************************************************
538 Return a driver name given an snum.
539 Returns True if from tdb, False otherwise.
540 ********************************************************************/
542 static BOOL get_driver_name(int snum, pstring drivername)
544 NT_PRINTER_INFO_LEVEL *info = NULL;
547 get_a_printer (NULL, &info, 2, lp_servicename(snum));
549 pstrcpy( drivername, info->info_2->drivername);
551 free_a_printer(&info, 2);
557 /********************************************************************
558 Respond to the DosPrintQInfo command with a level of 52
559 This is used to get printer driver information for Win9x clients
560 ********************************************************************/
561 static void fill_printq_info_52(connection_struct *conn, int snum,
562 struct pack_desc* desc, int count )
566 NT_PRINTER_DRIVER_INFO_LEVEL driver;
567 NT_PRINTER_INFO_LEVEL *printer = NULL;
571 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
572 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
573 lp_servicename(snum)));
577 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
580 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
581 printer->info_2->drivername));
585 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
586 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
587 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
589 PACKI(desc, "W", 0x0400); /* don't know */
590 PACKS(desc, "z", driver.info_3->name); /* long printer name */
591 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
592 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
593 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
595 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
596 standard_sub_basic( "", location, sizeof(location)-1 );
597 PACKS(desc,"z", location); /* share to retrieve files */
599 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
600 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
601 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
603 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
604 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
605 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
606 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
607 DEBUG(3,("Driver Location: %s:\n",location));
608 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
609 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
610 PACKI(desc,"N",count); /* number of files to copy */
612 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
614 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
615 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
616 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
621 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
624 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
626 desc->errcode=NERR_Success;
630 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
631 desc->errcode=NERR_notsupported;
635 free_a_printer( &printer, 2 );
638 free_a_printer_driver( driver, 3 );
642 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
643 struct pack_desc* desc,
644 int count, print_queue_struct* queue,
645 print_status_struct* status)
650 PACKS(desc,"B13",SERVICE(snum));
655 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
658 PACKI(desc,"K",printq_status(status->status));
662 if (uLevel == 1 || uLevel == 2) {
663 PACKS(desc,"B",""); /* alignment */
664 PACKI(desc,"W",5); /* priority */
665 PACKI(desc,"W",0); /* start time */
666 PACKI(desc,"W",0); /* until time */
667 PACKS(desc,"z",""); /* pSepFile */
668 PACKS(desc,"z","lpd"); /* pPrProc */
669 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
670 PACKS(desc,"z",""); /* pParms */
672 PACKS(desc,"z","UNKNOWN PRINTER");
673 PACKI(desc,"W",LPSTAT_ERROR);
675 else if (!status || !status->message[0]) {
676 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
677 PACKI(desc,"W",LPSTAT_OK); /* status */
679 PACKS(desc,"z",status->message);
680 PACKI(desc,"W",printq_status(status->status)); /* status */
682 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
685 if (uLevel == 3 || uLevel == 4) {
688 PACKI(desc,"W",5); /* uPriority */
689 PACKI(desc,"W",0); /* uStarttime */
690 PACKI(desc,"W",0); /* uUntiltime */
691 PACKI(desc,"W",5); /* pad1 */
692 PACKS(desc,"z",""); /* pszSepFile */
693 PACKS(desc,"z","WinPrint"); /* pszPrProc */
694 PACKS(desc,"z",NULL); /* pszParms */
695 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
696 /* "don't ask" that it's done this way to fix corrupted
697 Win9X/ME printer comments. */
699 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
701 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
703 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
704 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
705 get_driver_name(snum,drivername);
706 PACKS(desc,"z",drivername); /* pszDriverName */
707 PackDriverData(desc); /* pDriverData */
710 if (uLevel == 2 || uLevel == 4) {
712 for (i=0;i<count;i++)
713 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
717 fill_printq_info_52( conn, snum, desc, count );
720 /* This function returns the number of files for a given driver */
721 static int get_printerdrivernumber(int snum)
724 NT_PRINTER_DRIVER_INFO_LEVEL driver;
725 NT_PRINTER_INFO_LEVEL *printer = NULL;
729 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
730 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
731 lp_servicename(snum)));
735 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
738 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
739 printer->info_2->drivername));
743 /* count the number of files */
744 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
749 free_a_printer( &printer, 2 );
752 free_a_printer_driver( driver, 3 );
757 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
758 uint16 vuid, char *param,char *data,
759 int mdrcnt,int mprcnt,
760 char **rdata,char **rparam,
761 int *rdata_len,int *rparam_len)
763 char *str1 = param+2;
764 char *str2 = skip_string(str1,1);
765 char *p = skip_string(str2,1);
771 struct pack_desc desc;
772 print_queue_struct *queue=NULL;
773 print_status_struct status;
776 memset((char *)&status,'\0',sizeof(status));
777 memset((char *)&desc,'\0',sizeof(desc));
779 p = skip_string(p,1);
783 /* remove any trailing username */
784 if ((p = strchr_m(QueueName,'%')))
787 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
789 /* check it's a supported varient */
790 if (!prefix_ok(str1,"zWrLh"))
792 if (!check_printq_info(&desc,uLevel,str2,str3)) {
794 * Patch from Scott Moomaw <scott@bridgewater.edu>
795 * to return the 'invalid info level' error if an
796 * unknown level was requested.
800 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
801 SSVALS(*rparam,0,ERRunknownlevel);
807 snum = find_service(QueueName);
808 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
812 count = get_printerdrivernumber(snum);
813 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
815 count = print_queue_status(snum, &queue,&status);
819 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
821 desc.buflen = mdrcnt;
824 * Don't return data but need to get correct length
825 * init_package will return wrong size if buflen=0
827 desc.buflen = getlen(desc.format);
828 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
831 if (init_package(&desc,1,count)) {
832 desc.subcount = count;
833 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
836 *rdata_len = desc.usedlen;
839 * We must set the return code to ERRbuftoosmall
840 * in order to support lanman style printing with Win NT/2k
843 if (!mdrcnt && lp_disable_spoolss())
844 desc.errcode = ERRbuftoosmall;
846 *rdata_len = desc.usedlen;
848 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
849 SSVALS(*rparam,0,desc.errcode);
851 SSVAL(*rparam,4,desc.neededlen);
853 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
861 /****************************************************************************
862 View list of all print jobs on all queues.
863 ****************************************************************************/
865 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
866 int mdrcnt, int mprcnt,
867 char **rdata, char** rparam,
868 int *rdata_len, int *rparam_len)
870 char *param_format = param+2;
871 char *output_format1 = skip_string(param_format,1);
872 char *p = skip_string(output_format1,1);
873 unsigned int uLevel = SVAL(p,0);
874 char *output_format2 = p + 4;
875 int services = lp_numservices();
877 struct pack_desc desc;
878 print_queue_struct **queue = NULL;
879 print_status_struct *status = NULL;
880 int *subcntarr = NULL;
881 int queuecnt = 0, subcnt = 0, succnt = 0;
883 memset((char *)&desc,'\0',sizeof(desc));
885 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
887 if (!prefix_ok(param_format,"WrLeh")) {
890 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
892 * Patch from Scott Moomaw <scott@bridgewater.edu>
893 * to return the 'invalid info level' error if an
894 * unknown level was requested.
898 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
899 SSVALS(*rparam,0,ERRunknownlevel);
905 for (i = 0; i < services; i++) {
906 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
911 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
912 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
915 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
916 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
917 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
920 memset(status,0,queuecnt*sizeof(print_status_struct));
921 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
922 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
928 for (i = 0; i < services; i++) {
929 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
930 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
931 subcnt += subcntarr[n];
937 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
943 desc.buflen = mdrcnt;
945 if (init_package(&desc,queuecnt,subcnt)) {
948 for (i = 0; i < services; i++) {
949 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
950 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
952 if (desc.errcode == NERR_Success) {
959 SAFE_FREE(subcntarr);
961 *rdata_len = desc.usedlen;
963 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
967 SSVALS(*rparam,0,desc.errcode);
969 SSVAL(*rparam,4,succnt);
970 SSVAL(*rparam,6,queuecnt);
972 for (i = 0; i < queuecnt; i++) {
985 SAFE_FREE(subcntarr);
986 for (i = 0; i < queuecnt; i++) {
997 /****************************************************************************
998 Get info level for a server list query.
999 ****************************************************************************/
1001 static BOOL check_server_info(int uLevel, char* id)
1005 if (strcmp(id,"B16") != 0) {
1010 if (strcmp(id,"B16BBDz") != 0) {
1020 struct srv_info_struct {
1028 /*******************************************************************
1029 Get server info lists from the files saved by nmbd. Return the
1031 ******************************************************************/
1033 static int get_server_info(uint32 servertype,
1034 struct srv_info_struct **servers,
1040 BOOL local_list_only;
1043 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1045 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1049 /* request for everything is code for request all servers */
1050 if (servertype == SV_TYPE_ALL)
1051 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1053 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1055 DEBUG(4,("Servertype search: %8x\n",servertype));
1057 for (i=0;lines[i];i++) {
1059 struct srv_info_struct *s;
1060 const char *ptr = lines[i];
1063 if (!*ptr) continue;
1065 if (count == alloced) {
1066 struct srv_info_struct *ts;
1069 ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1071 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1075 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1077 s = &(*servers)[count];
1079 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1080 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1081 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1082 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1083 /* this allows us to cope with an old nmbd */
1084 fstrcpy(s->domain,lp_workgroup());
1087 if (sscanf(stype,"%X",&s->type) != 1) {
1088 DEBUG(4,("r:host file "));
1092 /* Filter the servers/domains we return based on what was asked for. */
1094 /* Check to see if we are being asked for a local list only. */
1095 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1096 DEBUG(4,("r: local list only"));
1100 /* doesn't match up: don't want it */
1101 if (!(servertype & s->type)) {
1102 DEBUG(4,("r:serv type "));
1106 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1107 (s->type & SV_TYPE_DOMAIN_ENUM))
1109 DEBUG(4,("s: dom mismatch "));
1113 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1118 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1119 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1123 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1124 s->name, s->type, s->comment, s->domain));
1126 s->server_added = True;
1131 DEBUG(4,("%20s %8x %25s %15s\n",
1132 s->name, s->type, s->comment, s->domain));
1136 file_lines_free(lines);
1140 /*******************************************************************
1141 Fill in a server info structure.
1142 ******************************************************************/
1144 static int fill_srv_info(struct srv_info_struct *service,
1145 int uLevel, char **buf, int *buflen,
1146 char **stringbuf, int *stringspace, char *baseaddr)
1155 case 0: struct_len = 16; break;
1156 case 1: struct_len = 26; break;
1166 len = strlen(service->comment)+1;
1170 if (buflen) *buflen = struct_len;
1171 if (stringspace) *stringspace = len;
1172 return struct_len + len;
1177 if (*buflen < struct_len) return -1;
1185 p2 = p + struct_len;
1186 l2 = *buflen - struct_len;
1188 if (!baseaddr) baseaddr = p;
1193 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1197 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1198 SIVAL(p,18,service->type);
1199 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1200 len += CopyAndAdvance(&p2,service->comment,&l2);
1206 *buf = p + struct_len;
1207 *buflen -= struct_len;
1220 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1222 return(strcmp(s1->name,s2->name));
1225 /****************************************************************************
1226 View list of servers available (or possibly domains). The info is
1227 extracted from lists saved by nmbd on the local host.
1228 ****************************************************************************/
1230 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1231 int mdrcnt, int mprcnt, char **rdata,
1232 char **rparam, int *rdata_len, int *rparam_len)
1234 char *str1 = param+2;
1235 char *str2 = skip_string(str1,1);
1236 char *p = skip_string(str2,1);
1237 int uLevel = SVAL(p,0);
1238 int buf_len = SVAL(p,2);
1239 uint32 servertype = IVAL(p,4);
1241 int data_len, fixed_len, string_len;
1242 int f_len = 0, s_len = 0;
1243 struct srv_info_struct *servers=NULL;
1244 int counted=0,total=0;
1247 BOOL domain_request;
1250 /* If someone sets all the bits they don't really mean to set
1251 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1254 if (servertype == SV_TYPE_ALL)
1255 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1257 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1258 any other bit (they may just set this bit on it's own) they
1259 want all the locally seen servers. However this bit can be
1260 set on its own so set the requested servers to be
1261 ALL - DOMAIN_ENUM. */
1263 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1264 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1266 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1267 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1271 if (!prefix_ok(str1,"WrLehD")) return False;
1272 if (!check_server_info(uLevel,str2)) return False;
1274 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1275 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1276 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1278 if (strcmp(str1, "WrLehDz") == 0) {
1279 pull_ascii_fstring(domain, p);
1281 fstrcpy(domain, lp_workgroup());
1284 if (lp_browse_list())
1285 total = get_server_info(servertype,&servers,domain);
1287 data_len = fixed_len = string_len = 0;
1291 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1294 char *lastname=NULL;
1296 for (i=0;i<total;i++)
1298 struct srv_info_struct *s = &servers[i];
1299 if (lastname && strequal(lastname,s->name)) continue;
1301 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1302 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1303 s->name, s->type, s->comment, s->domain));
1305 if (data_len <= buf_len) {
1308 string_len += s_len;
1315 *rdata_len = fixed_len + string_len;
1316 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1317 memset(*rdata,'\0',*rdata_len);
1319 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1325 char *lastname=NULL;
1326 int count2 = counted;
1327 for (i = 0; i < total && count2;i++)
1329 struct srv_info_struct *s = &servers[i];
1330 if (lastname && strequal(lastname,s->name)) continue;
1332 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1333 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1334 s->name, s->type, s->comment, s->domain));
1340 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1341 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1343 SSVAL(*rparam,4,counted);
1344 SSVAL(*rparam,6,counted+missed);
1348 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1349 domain,uLevel,counted,counted+missed));
1354 /****************************************************************************
1355 command 0x34 - suspected of being a "Lookup Names" stub api
1356 ****************************************************************************/
1358 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1359 int mdrcnt, int mprcnt, char **rdata,
1360 char **rparam, int *rdata_len, int *rparam_len)
1362 char *str1 = param+2;
1363 char *str2 = skip_string(str1,1);
1364 char *p = skip_string(str2,1);
1365 int uLevel = SVAL(p,0);
1366 int buf_len = SVAL(p,2);
1370 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1371 str1, str2, p, uLevel, buf_len));
1373 if (!prefix_ok(str1,"zWrLeh")) return False;
1378 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1380 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1382 SSVAL(*rparam,4,counted);
1383 SSVAL(*rparam,6,counted+missed);
1388 /****************************************************************************
1389 get info about a share
1390 ****************************************************************************/
1392 static BOOL check_share_info(int uLevel, char* id)
1396 if (strcmp(id,"B13") != 0) return False;
1399 if (strcmp(id,"B13BWz") != 0) return False;
1402 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1405 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1407 default: return False;
1412 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1413 char** buf, int* buflen,
1414 char** stringbuf, int* stringspace, char* baseaddr)
1423 case 0: struct_len = 13; break;
1424 case 1: struct_len = 20; break;
1425 case 2: struct_len = 40; break;
1426 case 91: struct_len = 68; break;
1434 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1435 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1436 if (buflen) *buflen = struct_len;
1437 if (stringspace) *stringspace = len;
1438 return struct_len + len;
1443 if ((*buflen) < struct_len) return -1;
1451 p2 = p + struct_len;
1452 l2 = (*buflen) - struct_len;
1454 if (!baseaddr) baseaddr = p;
1456 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1462 type = STYPE_DISKTREE;
1463 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1464 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1465 SSVAL(p,14,type); /* device type */
1466 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1467 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1472 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1473 SSVALS(p,22,-1); /* max uses */
1474 SSVAL(p,24,1); /* current uses */
1475 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1476 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1477 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1482 memset(p+40,0,SHPWLEN+2);
1494 (*buf) = p + struct_len;
1495 (*buflen) -= struct_len;
1497 (*stringspace) = l2;
1507 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1508 int mdrcnt,int mprcnt,
1509 char **rdata,char **rparam,
1510 int *rdata_len,int *rparam_len)
1512 char *str1 = param+2;
1513 char *str2 = skip_string(str1,1);
1514 char *netname = skip_string(str2,1);
1515 char *p = skip_string(netname,1);
1516 int uLevel = SVAL(p,0);
1517 int snum = find_service(netname);
1519 if (snum < 0) return False;
1521 /* check it's a supported varient */
1522 if (!prefix_ok(str1,"zWrLh")) return False;
1523 if (!check_share_info(uLevel,str2)) return False;
1525 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1527 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1528 if (*rdata_len < 0) return False;
1531 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1532 SSVAL(*rparam,0,NERR_Success);
1533 SSVAL(*rparam,2,0); /* converter word */
1534 SSVAL(*rparam,4,*rdata_len);
1539 /****************************************************************************
1540 View the list of available shares.
1542 This function is the server side of the NetShareEnum() RAP call.
1543 It fills the return buffer with share names and share comments.
1544 Note that the return buffer normally (in all known cases) allows only
1545 twelve byte strings for share names (plus one for a nul terminator).
1546 Share names longer than 12 bytes must be skipped.
1547 ****************************************************************************/
1549 static BOOL api_RNetShareEnum( connection_struct *conn,
1560 char *str1 = param+2;
1561 char *str2 = skip_string(str1,1);
1562 char *p = skip_string(str2,1);
1563 int uLevel = SVAL(p,0);
1564 int buf_len = SVAL(p,2);
1566 int count=lp_numservices();
1567 int total=0,counted=0;
1568 BOOL missed = False;
1570 int data_len, fixed_len, string_len;
1571 int f_len = 0, s_len = 0;
1573 if (!prefix_ok(str1,"WrLeh")) return False;
1574 if (!check_share_info(uLevel,str2)) return False;
1576 data_len = fixed_len = string_len = 0;
1577 for (i=0;i<count;i++) {
1578 fstring servicename_dos;
1579 if (!(lp_browseable(i) && lp_snum_ok(i)))
1581 push_ascii_fstring(servicename_dos, lp_servicename(i));
1582 if( lp_browseable( i )
1584 && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
1587 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1588 if (data_len <= buf_len)
1592 string_len += s_len;
1598 *rdata_len = fixed_len + string_len;
1599 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1600 memset(*rdata,0,*rdata_len);
1602 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1606 for( i = 0; i < count; i++ )
1608 fstring servicename_dos;
1609 if (!(lp_browseable(i) && lp_snum_ok(i)))
1611 push_ascii_fstring(servicename_dos, lp_servicename(i));
1612 if( lp_browseable( i )
1614 && (strlen(servicename_dos) < 13) )
1616 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1622 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1623 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1625 SSVAL(*rparam,4,counted);
1626 SSVAL(*rparam,6,total);
1628 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1629 counted,total,uLevel,
1630 buf_len,*rdata_len,mdrcnt));
1634 /****************************************************************************
1636 ****************************************************************************/
1638 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1639 int mdrcnt,int mprcnt,
1640 char **rdata,char **rparam,
1641 int *rdata_len,int *rparam_len)
1643 char *str1 = param+2;
1644 char *str2 = skip_string(str1,1);
1645 char *p = skip_string(str2,1);
1646 int uLevel = SVAL(p,0);
1650 char *command, *cmdname;
1651 unsigned int offset;
1655 /* check it's a supported varient */
1656 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1657 if (!check_share_info(uLevel,str2)) return False;
1658 if (uLevel != 2) return False;
1660 pull_ascii_fstring(sharename,data);
1661 snum = find_service(sharename);
1662 if (snum >= 0) { /* already exists */
1667 /* only support disk share adds */
1668 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1670 offset = IVAL(data, 16);
1671 if (offset >= mdrcnt) {
1672 res = ERRinvalidparam;
1675 pull_ascii_fstring(comment, offset? (data+offset) : "");
1677 offset = IVAL(data, 26);
1678 if (offset >= mdrcnt) {
1679 res = ERRinvalidparam;
1682 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1684 string_replace(sharename, '"', ' ');
1685 string_replace(pathname, '"', ' ');
1686 string_replace(comment, '"', ' ');
1688 cmdname = lp_add_share_cmd();
1690 if (!cmdname || *cmdname == '\0') return False;
1692 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1693 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1696 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1697 if ((res = smbrun(command, NULL)) != 0) {
1698 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1704 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1706 } else return False;
1709 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1710 SSVAL(*rparam,0,NERR_Success);
1711 SSVAL(*rparam,2,0); /* converter word */
1712 SSVAL(*rparam,4,*rdata_len);
1719 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1721 SSVAL(*rparam,0,res);
1726 /****************************************************************************
1727 view list of groups available
1728 ****************************************************************************/
1730 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1731 int mdrcnt,int mprcnt,
1732 char **rdata,char **rparam,
1733 int *rdata_len,int *rparam_len)
1737 int resume_context, cli_buf_size;
1738 char *str1 = param+2;
1739 char *str2 = skip_string(str1,1);
1740 char *p = skip_string(str2,1);
1742 struct pdb_search *search;
1743 struct samr_displayentry *entries;
1747 if (strcmp(str1,"WrLeh") != 0)
1751 * W-> resume context (number of users to skip)
1752 * r -> return parameter pointer to receive buffer
1753 * L -> length of receive buffer
1754 * e -> return parameter number of entries
1755 * h -> return parameter total number of users
1757 if (strcmp("B21",str2) != 0)
1760 /* get list of domain groups SID_DOMAIN_GRP=2 */
1762 search = pdb_search_groups();
1765 if (search == NULL) {
1766 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1770 resume_context = SVAL(p,0);
1771 cli_buf_size=SVAL(p+2,0);
1772 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1773 "%d\n", resume_context, cli_buf_size));
1776 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1780 *rdata_len = cli_buf_size;
1781 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1785 for(i=0; i<num_entries; i++) {
1787 fstrcpy(name, entries[i].account_name);
1788 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1789 /* truncate the name at 21 chars. */
1790 memcpy(p, name, 21);
1791 DEBUG(10,("adding entry %d group %s\n", i, p));
1793 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1796 /* set overflow error */
1797 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1803 pdb_search_destroy(search);
1805 *rdata_len = PTR_DIFF(p,*rdata);
1808 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1810 SSVAL(*rparam, 0, errflags);
1811 SSVAL(*rparam, 2, 0); /* converter word */
1812 SSVAL(*rparam, 4, i); /* is this right?? */
1813 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1818 /*******************************************************************
1819 Get groups that a user is a member of.
1820 ******************************************************************/
1822 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1823 int mdrcnt,int mprcnt,
1824 char **rdata,char **rparam,
1825 int *rdata_len,int *rparam_len)
1827 char *str1 = param+2;
1828 char *str2 = skip_string(str1,1);
1829 char *UserName = skip_string(str2,1);
1830 char *p = skip_string(UserName,1);
1831 int uLevel = SVAL(p,0);
1832 const char *level_string;
1834 SAM_ACCOUNT *sampw = NULL;
1842 enum SID_NAME_USE grp_type;
1843 struct passwd *passwd;
1847 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1849 /* check it's a supported varient */
1851 if ( strcmp(str1,"zWrLeh") != 0 )
1856 level_string = "B21";
1862 if (strcmp(level_string,str2) != 0)
1865 *rdata_len = mdrcnt + 1024;
1866 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1868 SSVAL(*rparam,0,NERR_Success);
1869 SSVAL(*rparam,2,0); /* converter word */
1873 /* Lookup the user information; This should only be one of
1874 our accounts (not remote domains) */
1876 passwd = getpwnam_alloc(UserName);
1881 pdb_init_sam( &sampw );
1883 become_root(); /* ROOT BLOCK */
1885 if ( !pdb_getsampwnam(sampw, UserName) )
1891 result = pdb_enum_group_memberships(pdb_get_username(sampw),
1893 &sids, &gids, &num_groups);
1895 if (!NT_STATUS_IS_OK(result))
1898 for (i=0; i<num_groups; i++) {
1900 if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
1901 pstrcpy(p, grp_name);
1909 *rdata_len = PTR_DIFF(p,*rdata);
1911 SSVAL(*rparam,4,count); /* is this right?? */
1912 SSVAL(*rparam,6,count); /* is this right?? */
1917 unbecome_root(); /* END ROOT BLOCK */
1919 pdb_free_sam( &sampw );
1920 passwd_free(&passwd);
1925 /*******************************************************************
1927 ******************************************************************/
1929 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1930 int mdrcnt,int mprcnt,
1931 char **rdata,char **rparam,
1932 int *rdata_len,int *rparam_len)
1937 int i, resume_context, cli_buf_size;
1938 struct pdb_search *search;
1939 struct samr_displayentry *users;
1941 char *str1 = param+2;
1942 char *str2 = skip_string(str1,1);
1943 char *p = skip_string(str2,1);
1945 if (strcmp(str1,"WrLeh") != 0)
1948 * W-> resume context (number of users to skip)
1949 * r -> return parameter pointer to receive buffer
1950 * L -> length of receive buffer
1951 * e -> return parameter number of entries
1952 * h -> return parameter total number of users
1955 resume_context = SVAL(p,0);
1956 cli_buf_size=SVAL(p+2,0);
1957 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
1958 resume_context, cli_buf_size));
1961 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1963 /* check it's a supported varient */
1964 if (strcmp("B21",str2) != 0)
1967 *rdata_len = cli_buf_size;
1968 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1973 search = pdb_search_users(ACB_NORMAL);
1975 if (search == NULL) {
1976 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1981 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
1985 errflags=NERR_Success;
1987 for (i=0; i<num_users; i++) {
1988 const char *name = users[i].account_name;
1990 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
1992 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
1993 "%s\n",count_sent,p));
1997 /* set overflow error */
1998 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
1999 "username %s\n",count_sent,name));
2005 pdb_search_destroy(search);
2007 *rdata_len = PTR_DIFF(p,*rdata);
2009 SSVAL(*rparam,0,errflags);
2010 SSVAL(*rparam,2,0); /* converter word */
2011 SSVAL(*rparam,4,count_sent); /* is this right?? */
2012 SSVAL(*rparam,6,num_users); /* is this right?? */
2017 /****************************************************************************
2018 Get the time of day info.
2019 ****************************************************************************/
2021 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
2022 int mdrcnt,int mprcnt,
2023 char **rdata,char **rparam,
2024 int *rdata_len,int *rparam_len)
2028 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2031 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2033 SSVAL(*rparam,0,NERR_Success);
2034 SSVAL(*rparam,2,0); /* converter word */
2040 time_t unixdate = time(NULL);
2042 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2043 by NT in a "net time" operation,
2044 it seems to ignore the one below */
2046 /* the client expects to get localtime, not GMT, in this bit
2047 (I think, this needs testing) */
2048 t = localtime(&unixdate);
2050 SIVAL(p,4,0); /* msecs ? */
2051 SCVAL(p,8,t->tm_hour);
2052 SCVAL(p,9,t->tm_min);
2053 SCVAL(p,10,t->tm_sec);
2054 SCVAL(p,11,0); /* hundredths of seconds */
2055 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2056 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2057 SCVAL(p,16,t->tm_mday);
2058 SCVAL(p,17,t->tm_mon + 1);
2059 SSVAL(p,18,1900+t->tm_year);
2060 SCVAL(p,20,t->tm_wday);
2065 /****************************************************************************
2066 Set the user password.
2067 *****************************************************************************/
2069 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2070 int mdrcnt,int mprcnt,
2071 char **rdata,char **rparam,
2072 int *rdata_len,int *rparam_len)
2074 char *p = skip_string(param+2,2);
2076 fstring pass1,pass2;
2078 pull_ascii_fstring(user,p);
2080 p = skip_string(p,1);
2082 memset(pass1,'\0',sizeof(pass1));
2083 memset(pass2,'\0',sizeof(pass2));
2085 memcpy(pass2,p+16,16);
2088 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2092 SSVAL(*rparam,0,NERR_badpass);
2093 SSVAL(*rparam,2,0); /* converter word */
2095 DEBUG(3,("Set password for <%s>\n",user));
2098 * Attempt to verify the old password against smbpasswd entries
2099 * Win98 clients send old and new password in plaintext for this call.
2103 auth_serversupplied_info *server_info = NULL;
2104 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2106 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2109 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2110 SSVAL(*rparam,0,NERR_Success);
2114 free_server_info(&server_info);
2116 data_blob_clear_free(&password);
2120 * If the plaintext change failed, attempt
2121 * the old encrypted method. NT will generate this
2122 * after trying the samr method. Note that this
2123 * method is done as a last resort as this
2124 * password change method loses the NT password hash
2125 * and cannot change the UNIX password as no plaintext
2129 if(SVAL(*rparam,0) != NERR_Success) {
2130 SAM_ACCOUNT *hnd = NULL;
2132 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2134 if (change_lanman_password(hnd,(uchar *)pass2)) {
2135 SSVAL(*rparam,0,NERR_Success);
2142 memset((char *)pass1,'\0',sizeof(fstring));
2143 memset((char *)pass2,'\0',sizeof(fstring));
2148 /****************************************************************************
2149 Set the user password (SamOEM version - gets plaintext).
2150 ****************************************************************************/
2152 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2153 int mdrcnt,int mprcnt,
2154 char **rdata,char **rparam,
2155 int *rdata_len,int *rparam_len)
2158 char *p = param + 2;
2160 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2164 SSVAL(*rparam,0,NERR_badpass);
2167 * Check the parameter definition is correct.
2170 if(!strequal(param + 2, "zsT")) {
2171 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2174 p = skip_string(p, 1);
2176 if(!strequal(p, "B516B16")) {
2177 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2180 p = skip_string(p,1);
2181 p += pull_ascii_fstring(user,p);
2183 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2186 * Pass the user through the NT -> unix user mapping
2190 (void)map_username(user);
2192 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2193 SSVAL(*rparam,0,NERR_Success);
2199 /****************************************************************************
2202 ****************************************************************************/
2204 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2205 int mdrcnt,int mprcnt,
2206 char **rdata,char **rparam,
2207 int *rdata_len,int *rparam_len)
2209 int function = SVAL(param,0);
2210 char *str1 = param+2;
2211 char *str2 = skip_string(str1,1);
2212 char *p = skip_string(str2,1);
2217 WERROR werr = WERR_OK;
2219 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2222 /* check it's a supported varient */
2223 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2227 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2230 if (!print_job_exists(sharename, jobid)) {
2231 errcode = NERR_JobNotFound;
2235 snum = lp_servicenumber( sharename);
2237 errcode = NERR_DestNotFound;
2241 errcode = NERR_notsupported;
2244 case 81: /* delete */
2245 if (print_job_delete(¤t_user, snum, jobid, &werr))
2246 errcode = NERR_Success;
2248 case 82: /* pause */
2249 if (print_job_pause(¤t_user, snum, jobid, &werr))
2250 errcode = NERR_Success;
2252 case 83: /* resume */
2253 if (print_job_resume(¤t_user, snum, jobid, &werr))
2254 errcode = NERR_Success;
2258 if (!W_ERROR_IS_OK(werr))
2259 errcode = W_ERROR_V(werr);
2262 SSVAL(*rparam,0,errcode);
2263 SSVAL(*rparam,2,0); /* converter word */
2268 /****************************************************************************
2269 Purge a print queue - or pause or resume it.
2270 ****************************************************************************/
2272 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2273 int mdrcnt,int mprcnt,
2274 char **rdata,char **rparam,
2275 int *rdata_len,int *rparam_len)
2277 int function = SVAL(param,0);
2278 char *str1 = param+2;
2279 char *str2 = skip_string(str1,1);
2280 char *QueueName = skip_string(str2,1);
2281 int errcode = NERR_notsupported;
2283 WERROR werr = WERR_OK;
2285 /* check it's a supported varient */
2286 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2290 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2293 snum = print_queue_snum(QueueName);
2296 errcode = NERR_JobNotFound;
2301 case 74: /* Pause queue */
2302 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2304 case 75: /* Resume queue */
2305 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2307 case 103: /* Purge */
2308 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2312 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2315 SSVAL(*rparam,0,errcode);
2316 SSVAL(*rparam,2,0); /* converter word */
2321 /****************************************************************************
2322 set the property of a print job (undocumented?)
2323 ? function = 0xb -> set name of print job
2324 ? function = 0x6 -> move print job up/down
2325 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2326 or <WWsTP> <WB21BB16B10zWWzDDz>
2327 ****************************************************************************/
2329 static int check_printjob_info(struct pack_desc* desc,
2330 int uLevel, char* id)
2332 desc->subformat = NULL;
2334 case 0: desc->format = "W"; break;
2335 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2336 case 2: desc->format = "WWzWWDDzz"; break;
2337 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2338 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2339 default: return False;
2341 if (strcmp(desc->format,id) != 0) return False;
2345 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2346 int mdrcnt,int mprcnt,
2347 char **rdata,char **rparam,
2348 int *rdata_len,int *rparam_len)
2350 struct pack_desc desc;
2351 char *str1 = param+2;
2352 char *str2 = skip_string(str1,1);
2353 char *p = skip_string(str2,1);
2357 int uLevel = SVAL(p,2);
2358 int function = SVAL(p,4);
2361 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2364 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2366 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2367 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2374 /* check it's a supported varient */
2375 if ((strcmp(str1,"WWsTP")) ||
2376 (!check_printjob_info(&desc,uLevel,str2)))
2379 if (!print_job_exists(sharename, jobid)) {
2380 errcode=NERR_JobNotFound;
2384 errcode = NERR_notsupported;
2388 /* change job place in the queue,
2389 data gives the new place */
2390 place = SVAL(data,0);
2391 if (print_job_set_place(snum, jobid, place)) {
2392 errcode=NERR_Success;
2397 /* change print job name, data gives the name */
2398 if (print_job_set_name(snum, jobid, data)) {
2399 errcode=NERR_Success;
2408 SSVALS(*rparam,0,errcode);
2409 SSVAL(*rparam,2,0); /* converter word */
2415 /****************************************************************************
2416 Get info about the server.
2417 ****************************************************************************/
2419 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2420 int mdrcnt,int mprcnt,
2421 char **rdata,char **rparam,
2422 int *rdata_len,int *rparam_len)
2424 char *str1 = param+2;
2425 char *str2 = skip_string(str1,1);
2426 char *p = skip_string(str2,1);
2427 int uLevel = SVAL(p,0);
2431 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2433 /* check it's a supported varient */
2434 if (!prefix_ok(str1,"WrLh")) return False;
2437 if (strcmp(str2,"B16") != 0) return False;
2441 if (strcmp(str2,"B16BBDz") != 0) return False;
2445 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2450 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2455 if (strcmp(str2,"DN") != 0) return False;
2459 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2462 default: return False;
2465 *rdata_len = mdrcnt;
2466 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2469 p2 = p + struct_len;
2471 srvstr_push(NULL, p,get_local_machine_name(),16,
2472 STR_ASCII|STR_UPPER|STR_TERMINATE);
2477 struct srv_info_struct *servers=NULL;
2480 uint32 servertype= lp_default_server_announce();
2482 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2484 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2485 for (i=0;i<count;i++) {
2486 if (strequal(servers[i].name,get_local_machine_name())) {
2487 servertype = servers[i].type;
2488 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2494 SCVAL(p,0,lp_major_announce_version());
2495 SCVAL(p,1,lp_minor_announce_version());
2496 SIVAL(p,2,servertype);
2498 if (mdrcnt == struct_len) {
2501 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2502 standard_sub_conn(conn,comment,sizeof(comment));
2503 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2504 p2 = skip_string(p2,1);
2509 return False; /* not yet implemented */
2512 *rdata_len = PTR_DIFF(p2,*rdata);
2515 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2516 SSVAL(*rparam,0,NERR_Success);
2517 SSVAL(*rparam,2,0); /* converter word */
2518 SSVAL(*rparam,4,*rdata_len);
2523 /****************************************************************************
2524 Get info about the server.
2525 ****************************************************************************/
2527 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2528 int mdrcnt,int mprcnt,
2529 char **rdata,char **rparam,
2530 int *rdata_len,int *rparam_len)
2532 char *str1 = param+2;
2533 char *str2 = skip_string(str1,1);
2534 char *p = skip_string(str2,1);
2536 int level = SVAL(p,0);
2538 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2541 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2543 /* check it's a supported varient */
2544 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2547 *rdata_len = mdrcnt + 1024;
2548 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2550 SSVAL(*rparam,0,NERR_Success);
2551 SSVAL(*rparam,2,0); /* converter word */
2557 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2558 pstrcpy(p2,get_local_machine_name());
2560 p2 = skip_string(p2,1);
2563 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2564 pstrcpy(p2,current_user_info.smb_name);
2565 p2 = skip_string(p2,1);
2568 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2569 pstrcpy(p2,lp_workgroup());
2571 p2 = skip_string(p2,1);
2574 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2575 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2578 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2579 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2580 p2 = skip_string(p2,1);
2583 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2585 p2 = skip_string(p2,1);
2588 *rdata_len = PTR_DIFF(p2,*rdata);
2590 SSVAL(*rparam,4,*rdata_len);
2595 /****************************************************************************
2596 get info about a user
2598 struct user_info_11 {
2599 char usri11_name[21]; 0-20
2601 char *usri11_comment; 22-25
2602 char *usri11_usr_comment; 26-29
2603 unsigned short usri11_priv; 30-31
2604 unsigned long usri11_auth_flags; 32-35
2605 long usri11_password_age; 36-39
2606 char *usri11_homedir; 40-43
2607 char *usri11_parms; 44-47
2608 long usri11_last_logon; 48-51
2609 long usri11_last_logoff; 52-55
2610 unsigned short usri11_bad_pw_count; 56-57
2611 unsigned short usri11_num_logons; 58-59
2612 char *usri11_logon_server; 60-63
2613 unsigned short usri11_country_code; 64-65
2614 char *usri11_workstations; 66-69
2615 unsigned long usri11_max_storage; 70-73
2616 unsigned short usri11_units_per_week; 74-75
2617 unsigned char *usri11_logon_hours; 76-79
2618 unsigned short usri11_code_page; 80-81
2623 usri11_name specifies the user name for which information is retireved
2625 usri11_pad aligns the next data structure element to a word boundary
2627 usri11_comment is a null terminated ASCII comment
2629 usri11_user_comment is a null terminated ASCII comment about the user
2631 usri11_priv specifies the level of the privilege assigned to the user.
2632 The possible values are:
2634 Name Value Description
2635 USER_PRIV_GUEST 0 Guest privilege
2636 USER_PRIV_USER 1 User privilege
2637 USER_PRV_ADMIN 2 Administrator privilege
2639 usri11_auth_flags specifies the account operator privileges. The
2640 possible values are:
2642 Name Value Description
2643 AF_OP_PRINT 0 Print operator
2646 Leach, Naik [Page 28]
2650 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2653 AF_OP_COMM 1 Communications operator
2654 AF_OP_SERVER 2 Server operator
2655 AF_OP_ACCOUNTS 3 Accounts operator
2658 usri11_password_age specifies how many seconds have elapsed since the
2659 password was last changed.
2661 usri11_home_dir points to a null terminated ASCII string that contains
2662 the path name of the user's home directory.
2664 usri11_parms points to a null terminated ASCII string that is set
2665 aside for use by applications.
2667 usri11_last_logon specifies the time when the user last logged on.
2668 This value is stored as the number of seconds elapsed since
2669 00:00:00, January 1, 1970.
2671 usri11_last_logoff specifies the time when the user last logged off.
2672 This value is stored as the number of seconds elapsed since
2673 00:00:00, January 1, 1970. A value of 0 means the last logoff
2676 usri11_bad_pw_count specifies the number of incorrect passwords
2677 entered since the last successful logon.
2679 usri11_log1_num_logons specifies the number of times this user has
2680 logged on. A value of -1 means the number of logons is unknown.
2682 usri11_logon_server points to a null terminated ASCII string that
2683 contains the name of the server to which logon requests are sent.
2684 A null string indicates logon requests should be sent to the
2687 usri11_country_code specifies the country code for the user's language
2690 usri11_workstations points to a null terminated ASCII string that
2691 contains the names of workstations the user may log on from.
2692 There may be up to 8 workstations, with the names separated by
2693 commas. A null strings indicates there are no restrictions.
2695 usri11_max_storage specifies the maximum amount of disk space the user
2696 can occupy. A value of 0xffffffff indicates there are no
2699 usri11_units_per_week specifies the equal number of time units into
2700 which a week is divided. This value must be equal to 168.
2702 usri11_logon_hours points to a 21 byte (168 bits) string that
2703 specifies the time during which the user can log on. Each bit
2704 represents one unique hour in a week. The first bit (bit 0, word
2705 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2709 Leach, Naik [Page 29]
2713 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2716 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2717 are no restrictions.
2719 usri11_code_page specifies the code page for the user's language of
2722 All of the pointers in this data structure need to be treated
2723 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2724 to be ignored. The converter word returned in the parameters section
2725 needs to be subtracted from the lower 16 bits to calculate an offset
2726 into the return buffer where this ASCII string resides.
2728 There is no auxiliary data in the response.
2730 ****************************************************************************/
2732 #define usri11_name 0
2733 #define usri11_pad 21
2734 #define usri11_comment 22
2735 #define usri11_usr_comment 26
2736 #define usri11_full_name 30
2737 #define usri11_priv 34
2738 #define usri11_auth_flags 36
2739 #define usri11_password_age 40
2740 #define usri11_homedir 44
2741 #define usri11_parms 48
2742 #define usri11_last_logon 52
2743 #define usri11_last_logoff 56
2744 #define usri11_bad_pw_count 60
2745 #define usri11_num_logons 62
2746 #define usri11_logon_server 64
2747 #define usri11_country_code 68
2748 #define usri11_workstations 70
2749 #define usri11_max_storage 74
2750 #define usri11_units_per_week 78
2751 #define usri11_logon_hours 80
2752 #define usri11_code_page 84
2753 #define usri11_end 86
2755 #define USER_PRIV_GUEST 0
2756 #define USER_PRIV_USER 1
2757 #define USER_PRIV_ADMIN 2
2759 #define AF_OP_PRINT 0
2760 #define AF_OP_COMM 1
2761 #define AF_OP_SERVER 2
2762 #define AF_OP_ACCOUNTS 3
2765 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2766 int mdrcnt,int mprcnt,
2767 char **rdata,char **rparam,
2768 int *rdata_len,int *rparam_len)
2770 char *str1 = param+2;
2771 char *str2 = skip_string(str1,1);
2772 char *UserName = skip_string(str2,1);
2773 char *p = skip_string(UserName,1);
2774 int uLevel = SVAL(p,0);
2776 const char *level_string;
2778 /* get NIS home of a previously validated user - simeon */
2779 /* With share level security vuid will always be zero.
2780 Don't depend on vuser being non-null !!. JRA */
2781 user_struct *vuser = get_valid_user_struct(vuid);
2783 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2784 vuser->user.unix_name));
2788 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2790 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2792 /* check it's a supported variant */
2793 if (strcmp(str1,"zWrLh") != 0) {
2797 case 0: level_string = "B21"; break;
2798 case 1: level_string = "B21BB16DWzzWz"; break;
2799 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2800 case 10: level_string = "B21Bzzz"; break;
2801 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2802 default: return False;
2805 if (strcmp(level_string,str2) != 0) {
2809 *rdata_len = mdrcnt + 1024;
2810 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2812 SSVAL(*rparam,0,NERR_Success);
2813 SSVAL(*rparam,2,0); /* converter word */
2816 p2 = p + usri11_end;
2819 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2822 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2827 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2828 pstrcpy(p2,"Comment");
2829 p2 = skip_string(p2,1);
2831 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2832 pstrcpy(p2,"UserComment");
2833 p2 = skip_string(p2,1);
2835 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2836 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2837 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2838 p2 = skip_string(p2,1);
2842 /* modelled after NTAS 3.51 reply */
2843 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2844 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2845 SIVALS(p,usri11_password_age,-1); /* password age */
2846 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2847 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2848 p2 = skip_string(p2,1);
2849 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2851 p2 = skip_string(p2,1);
2852 SIVAL(p,usri11_last_logon,0); /* last logon */
2853 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2854 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2855 SSVALS(p,usri11_num_logons,-1); /* num logons */
2856 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2857 pstrcpy(p2,"\\\\*");
2858 p2 = skip_string(p2,1);
2859 SSVAL(p,usri11_country_code,0); /* country code */
2861 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2863 p2 = skip_string(p2,1);
2865 SIVALS(p,usri11_max_storage,-1); /* max storage */
2866 SSVAL(p,usri11_units_per_week,168); /* units per week */
2867 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2869 /* a simple way to get logon hours at all times. */
2871 SCVAL(p2,21,0); /* fix zero termination */
2872 p2 = skip_string(p2,1);
2874 SSVAL(p,usri11_code_page,0); /* code page */
2877 if (uLevel == 1 || uLevel == 2) {
2878 memset(p+22,' ',16); /* password */
2879 SIVALS(p,38,-1); /* password age */
2881 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2882 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2883 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2884 p2 = skip_string(p2,1);
2885 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2887 SSVAL(p,52,0); /* flags */
2888 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2889 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2890 p2 = skip_string(p2,1);
2892 SIVAL(p,60,0); /* auth_flags */
2893 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2894 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2895 p2 = skip_string(p2,1);
2896 SIVAL(p,68,0); /* urs_comment */
2897 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2899 p2 = skip_string(p2,1);
2900 SIVAL(p,76,0); /* workstations */
2901 SIVAL(p,80,0); /* last_logon */
2902 SIVAL(p,84,0); /* last_logoff */
2903 SIVALS(p,88,-1); /* acct_expires */
2904 SIVALS(p,92,-1); /* max_storage */
2905 SSVAL(p,96,168); /* units_per_week */
2906 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2909 SSVALS(p,102,-1); /* bad_pw_count */
2910 SSVALS(p,104,-1); /* num_logons */
2911 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2912 pstrcpy(p2,"\\\\%L");
2913 standard_sub_conn(conn, p2,0);
2914 p2 = skip_string(p2,1);
2915 SSVAL(p,110,49); /* country_code */
2916 SSVAL(p,112,860); /* code page */
2920 *rdata_len = PTR_DIFF(p2,*rdata);
2922 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2927 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2928 int mdrcnt,int mprcnt,
2929 char **rdata,char **rparam,
2930 int *rdata_len,int *rparam_len)
2932 char *str1 = param+2;
2933 char *str2 = skip_string(str1,1);
2934 char *p = skip_string(str2,1);
2936 struct pack_desc desc;
2938 /* With share level security vuid will always be zero.
2939 Don't depend on vuser being non-null !!. JRA */
2940 user_struct *vuser = get_valid_user_struct(vuid);
2942 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2943 vuser->user.unix_name));
2948 memset((char *)&desc,'\0',sizeof(desc));
2950 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2952 /* check it's a supported varient */
2953 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2954 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2955 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2957 desc.buflen = mdrcnt;
2958 desc.subformat = NULL;
2961 if (init_package(&desc,1,0))
2963 PACKI(&desc,"W",0); /* code */
2964 PACKS(&desc,"B21",name); /* eff. name */
2965 PACKS(&desc,"B",""); /* pad */
2967 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2968 PACKI(&desc,"D",0); /* auth flags XXX */
2969 PACKI(&desc,"W",0); /* num logons */
2970 PACKI(&desc,"W",0); /* bad pw count */
2971 PACKI(&desc,"D",0); /* last logon */
2972 PACKI(&desc,"D",-1); /* last logoff */
2973 PACKI(&desc,"D",-1); /* logoff time */
2974 PACKI(&desc,"D",-1); /* kickoff time */
2975 PACKI(&desc,"D",0); /* password age */
2976 PACKI(&desc,"D",0); /* password can change */
2977 PACKI(&desc,"D",-1); /* password must change */
2980 fstrcpy(mypath,"\\\\");
2981 fstrcat(mypath,get_local_machine_name());
2983 PACKS(&desc,"z",mypath); /* computer */
2985 PACKS(&desc,"z",lp_workgroup());/* domain */
2987 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2989 PACKI(&desc,"D",0x00000000); /* reserved */
2992 *rdata_len = desc.usedlen;
2994 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2995 SSVALS(*rparam,0,desc.errcode);
2997 SSVAL(*rparam,4,desc.neededlen);
2999 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3003 /****************************************************************************
3004 api_WAccessGetUserPerms
3005 ****************************************************************************/
3007 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
3008 int mdrcnt,int mprcnt,
3009 char **rdata,char **rparam,
3010 int *rdata_len,int *rparam_len)
3012 char *str1 = param+2;
3013 char *str2 = skip_string(str1,1);
3014 char *user = skip_string(str2,1);
3015 char *resource = skip_string(user,1);
3017 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3019 /* check it's a supported varient */
3020 if (strcmp(str1,"zzh") != 0) return False;
3021 if (strcmp(str2,"") != 0) return False;
3024 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3025 SSVALS(*rparam,0,0); /* errorcode */
3026 SSVAL(*rparam,2,0); /* converter word */
3027 SSVAL(*rparam,4,0x7f); /* permission flags */
3032 /****************************************************************************
3033 api_WPrintJobEnumerate
3034 ****************************************************************************/
3036 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3037 int mdrcnt,int mprcnt,
3038 char **rdata,char **rparam,
3039 int *rdata_len,int *rparam_len)
3041 char *str1 = param+2;
3042 char *str2 = skip_string(str1,1);
3043 char *p = skip_string(str2,1);
3050 struct pack_desc desc;
3051 print_queue_struct *queue=NULL;
3052 print_status_struct status;
3057 memset((char *)&desc,'\0',sizeof(desc));
3058 memset((char *)&status,'\0',sizeof(status));
3060 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3062 /* check it's a supported varient */
3063 if (strcmp(str1,"WWrLh") != 0) return False;
3064 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3066 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3069 snum = lp_servicenumber( sharename);
3070 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3072 count = print_queue_status(snum,&queue,&status);
3073 for (i = 0; i < count; i++) {
3074 if (queue[i].job == jobid) break;
3078 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3080 desc.buflen = mdrcnt;
3083 * Don't return data but need to get correct length
3084 * init_package will return wrong size if buflen=0
3086 desc.buflen = getlen(desc.format);
3087 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3090 if (init_package(&desc,1,0)) {
3092 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3093 *rdata_len = desc.usedlen;
3096 desc.errcode = NERR_JobNotFound;
3102 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3103 SSVALS(*rparam,0,desc.errcode);
3105 SSVAL(*rparam,4,desc.neededlen);
3110 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3114 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3115 int mdrcnt,int mprcnt,
3116 char **rdata,char **rparam,
3117 int *rdata_len,int *rparam_len)
3119 char *str1 = param+2;
3120 char *str2 = skip_string(str1,1);
3121 char *p = skip_string(str2,1);
3127 struct pack_desc desc;
3128 print_queue_struct *queue=NULL;
3129 print_status_struct status;
3131 memset((char *)&desc,'\0',sizeof(desc));
3132 memset((char *)&status,'\0',sizeof(status));
3134 p = skip_string(p,1);
3137 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3139 /* check it's a supported variant */
3140 if (strcmp(str1,"zWrLeh") != 0)
3144 return False; /* defined only for uLevel 0,1,2 */
3146 if (!check_printjob_info(&desc,uLevel,str2))
3149 snum = find_service(name);
3150 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
3153 count = print_queue_status(snum,&queue,&status);
3154 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3156 desc.buflen = mdrcnt;
3158 if (init_package(&desc,count,0)) {
3160 for (i = 0; i < count; i++) {
3161 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3162 if (desc.errcode == NERR_Success) succnt = i+1;
3166 *rdata_len = desc.usedlen;
3169 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3170 SSVALS(*rparam,0,desc.errcode);
3172 SSVAL(*rparam,4,succnt);
3173 SSVAL(*rparam,6,count);
3177 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3181 static int check_printdest_info(struct pack_desc* desc,
3182 int uLevel, char* id)
3184 desc->subformat = NULL;
3186 case 0: desc->format = "B9"; break;
3187 case 1: desc->format = "B9B21WWzW"; break;
3188 case 2: desc->format = "z"; break;
3189 case 3: desc->format = "zzzWWzzzWW"; break;
3190 default: return False;
3192 if (strcmp(desc->format,id) != 0) return False;
3196 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3197 struct pack_desc* desc)
3200 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3201 buf[sizeof(buf)-1] = 0;
3204 PACKS(desc,"B9",buf); /* szName */
3206 PACKS(desc,"B21",""); /* szUserName */
3207 PACKI(desc,"W",0); /* uJobId */
3208 PACKI(desc,"W",0); /* fsStatus */
3209 PACKS(desc,"z",""); /* pszStatus */
3210 PACKI(desc,"W",0); /* time */
3213 if (uLevel == 2 || uLevel == 3) {
3214 PACKS(desc,"z",buf); /* pszPrinterName */
3216 PACKS(desc,"z",""); /* pszUserName */
3217 PACKS(desc,"z",""); /* pszLogAddr */
3218 PACKI(desc,"W",0); /* uJobId */
3219 PACKI(desc,"W",0); /* fsStatus */
3220 PACKS(desc,"z",""); /* pszStatus */
3221 PACKS(desc,"z",""); /* pszComment */
3222 PACKS(desc,"z","NULL"); /* pszDrivers */
3223 PACKI(desc,"W",0); /* time */
3224 PACKI(desc,"W",0); /* pad1 */
3229 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3230 int mdrcnt,int mprcnt,
3231 char **rdata,char **rparam,
3232 int *rdata_len,int *rparam_len)
3234 char *str1 = param+2;
3235 char *str2 = skip_string(str1,1);
3236 char *p = skip_string(str2,1);
3237 char* PrinterName = p;
3239 struct pack_desc desc;
3243 memset((char *)&desc,'\0',sizeof(desc));
3245 p = skip_string(p,1);
3248 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3250 /* check it's a supported varient */
3251 if (strcmp(str1,"zWrLh") != 0) return False;
3252 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3254 snum = find_service(PrinterName);
3255 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3257 desc.errcode = NERR_DestNotFound;
3262 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3264 desc.buflen = mdrcnt;
3267 * Don't return data but need to get correct length
3268 * init_package will return wrong size if buflen=0
3270 desc.buflen = getlen(desc.format);
3271 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3273 if (init_package(&desc,1,0)) {
3274 fill_printdest_info(conn,snum,uLevel,&desc);
3276 *rdata_len = desc.usedlen;
3280 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3281 SSVALS(*rparam,0,desc.errcode);
3283 SSVAL(*rparam,4,desc.neededlen);
3285 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3290 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3291 int mdrcnt,int mprcnt,
3292 char **rdata,char **rparam,
3293 int *rdata_len,int *rparam_len)
3295 char *str1 = param+2;
3296 char *str2 = skip_string(str1,1);
3297 char *p = skip_string(str2,1);
3301 struct pack_desc desc;
3302 int services = lp_numservices();
3304 memset((char *)&desc,'\0',sizeof(desc));
3308 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3310 /* check it's a supported varient */
3311 if (strcmp(str1,"WrLeh") != 0) return False;
3312 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3315 for (i = 0; i < services; i++)
3316 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3319 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3321 desc.buflen = mdrcnt;
3322 if (init_package(&desc,queuecnt,0)) {
3325 for (i = 0; i < services; i++) {
3326 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3327 fill_printdest_info(conn,i,uLevel,&desc);
3329 if (desc.errcode == NERR_Success) succnt = n;
3334 *rdata_len = desc.usedlen;
3337 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3338 SSVALS(*rparam,0,desc.errcode);
3340 SSVAL(*rparam,4,succnt);
3341 SSVAL(*rparam,6,queuecnt);
3343 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3347 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3348 int mdrcnt,int mprcnt,
3349 char **rdata,char **rparam,
3350 int *rdata_len,int *rparam_len)
3352 char *str1 = param+2;
3353 char *str2 = skip_string(str1,1);
3354 char *p = skip_string(str2,1);
3357 struct pack_desc desc;
3359 memset((char *)&desc,'\0',sizeof(desc));
3363 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3365 /* check it's a supported varient */
3366 if (strcmp(str1,"WrLeh") != 0) return False;
3367 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3369 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3371 desc.buflen = mdrcnt;
3372 if (init_package(&desc,1,0)) {
3373 PACKS(&desc,"B41","NULL");
3376 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3378 *rdata_len = desc.usedlen;
3381 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3382 SSVALS(*rparam,0,desc.errcode);
3384 SSVAL(*rparam,4,succnt);
3387 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3391 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3392 int mdrcnt,int mprcnt,
3393 char **rdata,char **rparam,
3394 int *rdata_len,int *rparam_len)
3396 char *str1 = param+2;
3397 char *str2 = skip_string(str1,1);
3398 char *p = skip_string(str2,1);
3401 struct pack_desc desc;
3403 memset((char *)&desc,'\0',sizeof(desc));
3407 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3409 /* check it's a supported varient */
3410 if (strcmp(str1,"WrLeh") != 0) return False;
3411 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3413 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3415 desc.buflen = mdrcnt;
3417 if (init_package(&desc,1,0)) {
3418 PACKS(&desc,"B13","lpd");
3421 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3423 *rdata_len = desc.usedlen;
3426 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3427 SSVALS(*rparam,0,desc.errcode);
3429 SSVAL(*rparam,4,succnt);
3432 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3436 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3437 int mdrcnt,int mprcnt,
3438 char **rdata,char **rparam,
3439 int *rdata_len,int *rparam_len)
3441 char *str1 = param+2;
3442 char *str2 = skip_string(str1,1);
3443 char *p = skip_string(str2,1);
3446 struct pack_desc desc;
3448 memset((char *)&desc,'\0',sizeof(desc));
3452 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3454 /* check it's a supported varient */
3455 if (strcmp(str1,"WrLeh") != 0) return False;
3456 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3458 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3459 memset((char *)&desc,'\0',sizeof(desc));
3461 desc.buflen = mdrcnt;
3463 if (init_package(&desc,1,0)) {
3464 PACKS(&desc,"B13","lp0");
3467 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3469 *rdata_len = desc.usedlen;
3472 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3473 SSVALS(*rparam,0,desc.errcode);
3475 SSVAL(*rparam,4,succnt);
3478 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3483 /****************************************************************************
3485 ****************************************************************************/
3486 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3487 int mdrcnt,int mprcnt,
3488 char **rdata,char **rparam,
3489 int *rdata_len,int *rparam_len)
3492 char *str1 = param+2;
3493 char *str2 = skip_string(str1,1);
3494 char *p = skip_string(str2,1);
3496 struct pack_desc desc;
3497 struct sessionid *session_list;
3498 int i, num_sessions;
3500 memset((char *)&desc,'\0',sizeof(desc));
3504 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3505 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3506 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3508 /* check it's a supported varient */
3509 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3510 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3512 num_sessions = list_sessions(&session_list);
3514 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3515 memset((char *)&desc,'\0',sizeof(desc));
3517 desc.buflen = mdrcnt;
3519 if (!init_package(&desc,num_sessions,0)) {
3523 for(i=0; i<num_sessions; i++) {
3524 PACKS(&desc, "z", session_list[i].remote_machine);
3525 PACKS(&desc, "z", session_list[i].username);
3526 PACKI(&desc, "W", 1); /* num conns */
3527 PACKI(&desc, "W", 0); /* num opens */
3528 PACKI(&desc, "W", 1); /* num users */
3529 PACKI(&desc, "D", 0); /* session time */
3530 PACKI(&desc, "D", 0); /* idle time */
3531 PACKI(&desc, "D", 0); /* flags */
3532 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3535 *rdata_len = desc.usedlen;
3538 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3539 SSVALS(*rparam,0,desc.errcode);
3540 SSVAL(*rparam,2,0); /* converter */
3541 SSVAL(*rparam,4,num_sessions); /* count */
3543 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3548 /****************************************************************************
3549 The buffer was too small.
3550 ****************************************************************************/
3552 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
3553 int mdrcnt, int mprcnt,
3554 char **rdata, char **rparam,
3555 int *rdata_len, int *rparam_len)
3557 *rparam_len = MIN(*rparam_len,mprcnt);
3558 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3562 SSVAL(*rparam,0,NERR_BufTooSmall);
3564 DEBUG(3,("Supplied buffer too small in API command\n"));
3569 /****************************************************************************
3570 The request is not supported.
3571 ****************************************************************************/
3573 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
3574 int mdrcnt, int mprcnt,
3575 char **rdata, char **rparam,
3576 int *rdata_len, int *rparam_len)
3579 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3583 SSVAL(*rparam,0,NERR_notsupported);
3584 SSVAL(*rparam,2,0); /* converter word */
3586 DEBUG(3,("Unsupported API command\n"));
3591 static const struct {
3594 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3595 int,int,char **,char **,int *,int *);
3596 BOOL auth_user; /* Deny anonymous access? */
3597 } api_commands[] = {
3598 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3599 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3600 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3601 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3602 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3603 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3604 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3605 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3606 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3607 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3608 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3609 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3610 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3611 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3612 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3613 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3614 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3615 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3616 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3617 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3618 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3619 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3620 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3621 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3622 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3623 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3624 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3625 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3626 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3627 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3628 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3629 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3630 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3631 {NULL, -1, api_Unsupported}
3632 /* The following RAP calls are not implemented by Samba:
3634 RAP_WFileEnum2 - anon not OK
3639 /****************************************************************************
3640 Handle remote api calls
3641 ****************************************************************************/
3643 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3644 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3648 char *rparam = NULL;
3655 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3659 api_command = SVAL(params,0);
3661 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3664 skip_string(params+2,1),
3665 tdscnt,tpscnt,mdrcnt,mprcnt));
3667 for (i=0;api_commands[i].name;i++) {
3668 if (api_commands[i].id == api_command && api_commands[i].fn) {
3669 DEBUG(3,("Doing %s\n",api_commands[i].name));
3674 /* Check whether this api call can be done anonymously */
3676 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3677 user_struct *user = get_valid_user_struct(vuid);
3679 if (!user || user->guest) {
3680 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3684 rdata = (char *)SMB_MALLOC(1024);
3686 memset(rdata,'\0',1024);
3689 rparam = (char *)SMB_MALLOC(1024);
3691 memset(rparam,'\0',1024);
3694 if(!rdata || !rparam) {
3695 DEBUG(0,("api_reply: malloc fail !\n"));
3701 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3702 &rdata,&rparam,&rdata_len,&rparam_len);
3705 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
3706 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3707 &rdata,&rparam,&rdata_len,&rparam_len);
3710 /* if we get False back then it's actually unsupported */
3712 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3713 &rdata,&rparam,&rdata_len,&rparam_len);
3716 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);