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);
804 SSVALS(*rparam,0,ERRunknownlevel);
810 snum = find_service(QueueName);
811 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
815 count = get_printerdrivernumber(snum);
816 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
818 count = print_queue_status(snum, &queue,&status);
822 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
827 desc.buflen = mdrcnt;
830 * Don't return data but need to get correct length
831 * init_package will return wrong size if buflen=0
833 desc.buflen = getlen(desc.format);
834 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
837 if (init_package(&desc,1,count)) {
838 desc.subcount = count;
839 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
842 *rdata_len = desc.usedlen;
845 * We must set the return code to ERRbuftoosmall
846 * in order to support lanman style printing with Win NT/2k
849 if (!mdrcnt && lp_disable_spoolss())
850 desc.errcode = ERRbuftoosmall;
852 *rdata_len = desc.usedlen;
854 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
858 SSVALS(*rparam,0,desc.errcode);
860 SSVAL(*rparam,4,desc.neededlen);
862 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
870 /****************************************************************************
871 View list of all print jobs on all queues.
872 ****************************************************************************/
874 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
875 int mdrcnt, int mprcnt,
876 char **rdata, char** rparam,
877 int *rdata_len, int *rparam_len)
879 char *param_format = param+2;
880 char *output_format1 = skip_string(param_format,1);
881 char *p = skip_string(output_format1,1);
882 unsigned int uLevel = SVAL(p,0);
883 char *output_format2 = p + 4;
884 int services = lp_numservices();
886 struct pack_desc desc;
887 print_queue_struct **queue = NULL;
888 print_status_struct *status = NULL;
889 int *subcntarr = NULL;
890 int queuecnt = 0, subcnt = 0, succnt = 0;
892 memset((char *)&desc,'\0',sizeof(desc));
894 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
896 if (!prefix_ok(param_format,"WrLeh")) {
899 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
901 * Patch from Scott Moomaw <scott@bridgewater.edu>
902 * to return the 'invalid info level' error if an
903 * unknown level was requested.
907 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
911 SSVALS(*rparam,0,ERRunknownlevel);
917 for (i = 0; i < services; i++) {
918 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
923 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
924 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
927 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
928 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
929 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
932 memset(status,0,queuecnt*sizeof(print_status_struct));
933 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
934 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
940 for (i = 0; i < services; i++) {
941 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
942 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
943 subcnt += subcntarr[n];
949 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
955 desc.buflen = mdrcnt;
957 if (init_package(&desc,queuecnt,subcnt)) {
960 for (i = 0; i < services; i++) {
961 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
962 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
964 if (desc.errcode == NERR_Success) {
971 SAFE_FREE(subcntarr);
973 *rdata_len = desc.usedlen;
975 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
979 SSVALS(*rparam,0,desc.errcode);
981 SSVAL(*rparam,4,succnt);
982 SSVAL(*rparam,6,queuecnt);
984 for (i = 0; i < queuecnt; i++) {
997 SAFE_FREE(subcntarr);
998 for (i = 0; i < queuecnt; i++) {
1000 SAFE_FREE(queue[i]);
1009 /****************************************************************************
1010 Get info level for a server list query.
1011 ****************************************************************************/
1013 static BOOL check_server_info(int uLevel, char* id)
1017 if (strcmp(id,"B16") != 0) {
1022 if (strcmp(id,"B16BBDz") != 0) {
1032 struct srv_info_struct {
1040 /*******************************************************************
1041 Get server info lists from the files saved by nmbd. Return the
1043 ******************************************************************/
1045 static int get_server_info(uint32 servertype,
1046 struct srv_info_struct **servers,
1052 BOOL local_list_only;
1055 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1057 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1061 /* request for everything is code for request all servers */
1062 if (servertype == SV_TYPE_ALL) {
1063 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1066 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1068 DEBUG(4,("Servertype search: %8x\n",servertype));
1070 for (i=0;lines[i];i++) {
1072 struct srv_info_struct *s;
1073 const char *ptr = lines[i];
1080 if (count == alloced) {
1082 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1084 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1087 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1089 s = &(*servers)[count];
1091 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1094 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1097 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1100 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1101 /* this allows us to cope with an old nmbd */
1102 fstrcpy(s->domain,lp_workgroup());
1105 if (sscanf(stype,"%X",&s->type) != 1) {
1106 DEBUG(4,("r:host file "));
1110 /* Filter the servers/domains we return based on what was asked for. */
1112 /* Check to see if we are being asked for a local list only. */
1113 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1114 DEBUG(4,("r: local list only"));
1118 /* doesn't match up: don't want it */
1119 if (!(servertype & s->type)) {
1120 DEBUG(4,("r:serv type "));
1124 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1125 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1126 DEBUG(4,("s: dom mismatch "));
1130 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1134 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1135 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1138 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1139 s->name, s->type, s->comment, s->domain));
1140 s->server_added = True;
1143 DEBUG(4,("%20s %8x %25s %15s\n",
1144 s->name, s->type, s->comment, s->domain));
1148 file_lines_free(lines);
1152 /*******************************************************************
1153 Fill in a server info structure.
1154 ******************************************************************/
1156 static int fill_srv_info(struct srv_info_struct *service,
1157 int uLevel, char **buf, int *buflen,
1158 char **stringbuf, int *stringspace, char *baseaddr)
1181 len = strlen(service->comment)+1;
1186 *buflen = struct_len;
1191 return struct_len + len;
1196 if (*buflen < struct_len) {
1203 p2 = p + struct_len;
1204 l2 = *buflen - struct_len;
1212 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1216 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1217 SIVAL(p,18,service->type);
1218 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1219 len += CopyAndAdvance(&p2,service->comment,&l2);
1224 *buf = p + struct_len;
1225 *buflen -= struct_len;
1236 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1238 return(strcmp(s1->name,s2->name));
1241 /****************************************************************************
1242 View list of servers available (or possibly domains). The info is
1243 extracted from lists saved by nmbd on the local host.
1244 ****************************************************************************/
1246 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1247 int mdrcnt, int mprcnt, char **rdata,
1248 char **rparam, int *rdata_len, int *rparam_len)
1250 char *str1 = param+2;
1251 char *str2 = skip_string(str1,1);
1252 char *p = skip_string(str2,1);
1253 int uLevel = SVAL(p,0);
1254 int buf_len = SVAL(p,2);
1255 uint32 servertype = IVAL(p,4);
1257 int data_len, fixed_len, string_len;
1258 int f_len = 0, s_len = 0;
1259 struct srv_info_struct *servers=NULL;
1260 int counted=0,total=0;
1263 BOOL domain_request;
1266 /* If someone sets all the bits they don't really mean to set
1267 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1270 if (servertype == SV_TYPE_ALL) {
1271 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1274 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1275 any other bit (they may just set this bit on it's own) they
1276 want all the locally seen servers. However this bit can be
1277 set on its own so set the requested servers to be
1278 ALL - DOMAIN_ENUM. */
1280 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1281 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1284 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1285 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1289 if (!prefix_ok(str1,"WrLehD")) {
1292 if (!check_server_info(uLevel,str2)) {
1296 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1297 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1298 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1300 if (strcmp(str1, "WrLehDz") == 0) {
1301 pull_ascii_fstring(domain, p);
1303 fstrcpy(domain, lp_workgroup());
1306 if (lp_browse_list()) {
1307 total = get_server_info(servertype,&servers,domain);
1310 data_len = fixed_len = string_len = 0;
1314 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1318 char *lastname=NULL;
1320 for (i=0;i<total;i++) {
1321 struct srv_info_struct *s = &servers[i];
1323 if (lastname && strequal(lastname,s->name)) {
1327 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1328 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1329 s->name, s->type, s->comment, s->domain));
1331 if (data_len <= buf_len) {
1334 string_len += s_len;
1341 *rdata_len = fixed_len + string_len;
1342 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1346 memset(*rdata,'\0',*rdata_len);
1348 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1354 char *lastname=NULL;
1355 int count2 = counted;
1357 for (i = 0; i < total && count2;i++) {
1358 struct srv_info_struct *s = &servers[i];
1360 if (lastname && strequal(lastname,s->name)) {
1364 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1365 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1366 s->name, s->type, s->comment, s->domain));
1372 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1376 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1378 SSVAL(*rparam,4,counted);
1379 SSVAL(*rparam,6,counted+missed);
1383 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1384 domain,uLevel,counted,counted+missed));
1389 /****************************************************************************
1390 command 0x34 - suspected of being a "Lookup Names" stub api
1391 ****************************************************************************/
1393 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1394 int mdrcnt, int mprcnt, char **rdata,
1395 char **rparam, int *rdata_len, int *rparam_len)
1397 char *str1 = param+2;
1398 char *str2 = skip_string(str1,1);
1399 char *p = skip_string(str2,1);
1400 int uLevel = SVAL(p,0);
1401 int buf_len = SVAL(p,2);
1405 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1406 str1, str2, p, uLevel, buf_len));
1408 if (!prefix_ok(str1,"zWrLeh")) {
1415 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1420 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1422 SSVAL(*rparam,4,counted);
1423 SSVAL(*rparam,6,counted+missed);
1428 /****************************************************************************
1429 get info about a share
1430 ****************************************************************************/
1432 static BOOL check_share_info(int uLevel, char* id)
1436 if (strcmp(id,"B13") != 0) {
1441 if (strcmp(id,"B13BWz") != 0) {
1446 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1451 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1461 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1462 char** buf, int* buflen,
1463 char** stringbuf, int* stringspace, char* baseaddr)
1493 len += StrlenExpanded(conn,snum,lp_comment(snum));
1496 len += strlen(lp_pathname(snum)) + 1;
1499 *buflen = struct_len;
1504 return struct_len + len;
1509 if ((*buflen) < struct_len) {
1517 p2 = p + struct_len;
1518 l2 = (*buflen) - struct_len;
1525 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1531 type = STYPE_DISKTREE;
1532 if (lp_print_ok(snum)) {
1533 type = STYPE_PRINTQ;
1535 if (strequal("IPC",lp_fstype(snum))) {
1538 SSVAL(p,14,type); /* device type */
1539 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1540 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1544 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1545 SSVALS(p,22,-1); /* max uses */
1546 SSVAL(p,24,1); /* current uses */
1547 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1548 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1549 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1553 memset(p+40,0,SHPWLEN+2);
1564 (*buf) = p + struct_len;
1565 (*buflen) -= struct_len;
1567 (*stringspace) = l2;
1576 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1577 int mdrcnt,int mprcnt,
1578 char **rdata,char **rparam,
1579 int *rdata_len,int *rparam_len)
1581 char *str1 = param+2;
1582 char *str2 = skip_string(str1,1);
1583 char *netname = skip_string(str2,1);
1584 char *p = skip_string(netname,1);
1585 int uLevel = SVAL(p,0);
1586 int snum = find_service(netname);
1592 /* check it's a supported varient */
1593 if (!prefix_ok(str1,"zWrLh")) {
1596 if (!check_share_info(uLevel,str2)) {
1600 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1605 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1606 if (*rdata_len < 0) {
1611 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1615 SSVAL(*rparam,0,NERR_Success);
1616 SSVAL(*rparam,2,0); /* converter word */
1617 SSVAL(*rparam,4,*rdata_len);
1622 /****************************************************************************
1623 View the list of available shares.
1625 This function is the server side of the NetShareEnum() RAP call.
1626 It fills the return buffer with share names and share comments.
1627 Note that the return buffer normally (in all known cases) allows only
1628 twelve byte strings for share names (plus one for a nul terminator).
1629 Share names longer than 12 bytes must be skipped.
1630 ****************************************************************************/
1632 static BOOL api_RNetShareEnum( connection_struct *conn,
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);
1647 int buf_len = SVAL(p,2);
1650 int total=0,counted=0;
1651 BOOL missed = False;
1653 int data_len, fixed_len, string_len;
1654 int f_len = 0, s_len = 0;
1656 if (!prefix_ok(str1,"WrLeh")) {
1659 if (!check_share_info(uLevel,str2)) {
1663 /* Ensure all the usershares are loaded. */
1665 count = load_usershare_shares();
1668 data_len = fixed_len = string_len = 0;
1669 for (i=0;i<count;i++) {
1670 fstring servicename_dos;
1671 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1674 push_ascii_fstring(servicename_dos, lp_servicename(i));
1675 /* Maximum name length = 13. */
1676 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1678 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1679 if (data_len <= buf_len) {
1682 string_len += s_len;
1689 *rdata_len = fixed_len + string_len;
1690 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1694 memset(*rdata,0,*rdata_len);
1696 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1701 for( i = 0; i < count; i++ ) {
1702 fstring servicename_dos;
1703 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1707 push_ascii_fstring(servicename_dos, lp_servicename(i));
1708 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1709 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1716 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1720 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1722 SSVAL(*rparam,4,counted);
1723 SSVAL(*rparam,6,total);
1725 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1726 counted,total,uLevel,
1727 buf_len,*rdata_len,mdrcnt));
1732 /****************************************************************************
1734 ****************************************************************************/
1736 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1737 int mdrcnt,int mprcnt,
1738 char **rdata,char **rparam,
1739 int *rdata_len,int *rparam_len)
1741 char *str1 = param+2;
1742 char *str2 = skip_string(str1,1);
1743 char *p = skip_string(str2,1);
1744 int uLevel = SVAL(p,0);
1748 char *command, *cmdname;
1749 unsigned int offset;
1753 /* check it's a supported varient */
1754 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1757 if (!check_share_info(uLevel,str2)) {
1764 pull_ascii_fstring(sharename,data);
1765 snum = find_service(sharename);
1766 if (snum >= 0) { /* already exists */
1771 /* only support disk share adds */
1772 if (SVAL(data,14)!=STYPE_DISKTREE) {
1776 offset = IVAL(data, 16);
1777 if (offset >= mdrcnt) {
1778 res = ERRinvalidparam;
1782 pull_ascii_fstring(comment, offset? (data+offset) : "");
1784 offset = IVAL(data, 26);
1786 if (offset >= mdrcnt) {
1787 res = ERRinvalidparam;
1791 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1793 string_replace(sharename, '"', ' ');
1794 string_replace(pathname, '"', ' ');
1795 string_replace(comment, '"', ' ');
1797 cmdname = lp_add_share_cmd();
1799 if (!cmdname || *cmdname == '\0') {
1803 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1804 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1807 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1809 if ((res = smbrun(command, NULL)) != 0) {
1810 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1816 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1823 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1827 SSVAL(*rparam,0,NERR_Success);
1828 SSVAL(*rparam,2,0); /* converter word */
1829 SSVAL(*rparam,4,*rdata_len);
1837 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1842 SSVAL(*rparam,0,res);
1847 /****************************************************************************
1848 view list of groups available
1849 ****************************************************************************/
1851 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1852 int mdrcnt,int mprcnt,
1853 char **rdata,char **rparam,
1854 int *rdata_len,int *rparam_len)
1858 int resume_context, cli_buf_size;
1859 char *str1 = param+2;
1860 char *str2 = skip_string(str1,1);
1861 char *p = skip_string(str2,1);
1863 struct pdb_search *search;
1864 struct samr_displayentry *entries;
1868 if (strcmp(str1,"WrLeh") != 0) {
1873 * W-> resume context (number of users to skip)
1874 * r -> return parameter pointer to receive buffer
1875 * L -> length of receive buffer
1876 * e -> return parameter number of entries
1877 * h -> return parameter total number of users
1880 if (strcmp("B21",str2) != 0) {
1884 /* get list of domain groups SID_DOMAIN_GRP=2 */
1886 search = pdb_search_groups();
1889 if (search == NULL) {
1890 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1894 resume_context = SVAL(p,0);
1895 cli_buf_size=SVAL(p+2,0);
1896 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1897 "%d\n", resume_context, cli_buf_size));
1900 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1904 *rdata_len = cli_buf_size;
1905 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1912 for(i=0; i<num_entries; i++) {
1914 fstrcpy(name, entries[i].account_name);
1915 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1916 /* truncate the name at 21 chars. */
1917 memcpy(p, name, 21);
1918 DEBUG(10,("adding entry %d group %s\n", i, p));
1920 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1923 /* set overflow error */
1924 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1930 pdb_search_destroy(search);
1932 *rdata_len = PTR_DIFF(p,*rdata);
1935 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1939 SSVAL(*rparam, 0, errflags);
1940 SSVAL(*rparam, 2, 0); /* converter word */
1941 SSVAL(*rparam, 4, i); /* is this right?? */
1942 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1947 /*******************************************************************
1948 Get groups that a user is a member of.
1949 ******************************************************************/
1951 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1952 int mdrcnt,int mprcnt,
1953 char **rdata,char **rparam,
1954 int *rdata_len,int *rparam_len)
1956 char *str1 = param+2;
1957 char *str2 = skip_string(str1,1);
1958 char *UserName = skip_string(str2,1);
1959 char *p = skip_string(UserName,1);
1960 int uLevel = SVAL(p,0);
1961 const char *level_string;
1963 struct samu *sampw = NULL;
1971 enum SID_NAME_USE type;
1972 TALLOC_CTX *mem_ctx;
1975 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1980 /* check it's a supported varient */
1982 if ( strcmp(str1,"zWrLeh") != 0 )
1987 level_string = "B21";
1993 if (strcmp(level_string,str2) != 0)
1996 *rdata_len = mdrcnt + 1024;
1997 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2001 SSVAL(*rparam,0,NERR_Success);
2002 SSVAL(*rparam,2,0); /* converter word */
2006 mem_ctx = talloc_new(NULL);
2007 if (mem_ctx == NULL) {
2008 DEBUG(0, ("talloc_new failed\n"));
2012 /* Lookup the user information; This should only be one of
2013 our accounts (not remote domains) */
2015 become_root(); /* ROOT BLOCK */
2017 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2018 NULL, NULL, &user_sid, &type)) {
2019 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2023 if (type != SID_NAME_USER) {
2024 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2025 sid_type_lookup(type)));
2029 if ( !(sampw = samu_new(mem_ctx)) ) {
2030 DEBUG(0, ("samu_new() failed!\n"));
2034 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2035 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2036 sid_string_static(&user_sid), UserName));
2044 result = pdb_enum_group_memberships(mem_ctx, sampw,
2045 &sids, &gids, &num_groups);
2047 if (!NT_STATUS_IS_OK(result)) {
2048 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2053 for (i=0; i<num_groups; i++) {
2055 const char *grp_name;
2057 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2058 pstrcpy(p, grp_name);
2064 *rdata_len = PTR_DIFF(p,*rdata);
2066 SSVAL(*rparam,4,count); /* is this right?? */
2067 SSVAL(*rparam,6,count); /* is this right?? */
2072 unbecome_root(); /* END ROOT BLOCK */
2074 TALLOC_FREE(mem_ctx);
2079 /*******************************************************************
2081 ******************************************************************/
2083 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2084 int mdrcnt,int mprcnt,
2085 char **rdata,char **rparam,
2086 int *rdata_len,int *rparam_len)
2091 int i, resume_context, cli_buf_size;
2092 struct pdb_search *search;
2093 struct samr_displayentry *users;
2095 char *str1 = param+2;
2096 char *str2 = skip_string(str1,1);
2097 char *p = skip_string(str2,1);
2099 if (strcmp(str1,"WrLeh") != 0)
2102 * W-> resume context (number of users to skip)
2103 * r -> return parameter pointer to receive buffer
2104 * L -> length of receive buffer
2105 * e -> return parameter number of entries
2106 * h -> return parameter total number of users
2109 resume_context = SVAL(p,0);
2110 cli_buf_size=SVAL(p+2,0);
2111 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2112 resume_context, cli_buf_size));
2115 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2120 /* check it's a supported varient */
2121 if (strcmp("B21",str2) != 0)
2124 *rdata_len = cli_buf_size;
2125 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2133 search = pdb_search_users(ACB_NORMAL);
2135 if (search == NULL) {
2136 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2141 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2145 errflags=NERR_Success;
2147 for (i=0; i<num_users; i++) {
2148 const char *name = users[i].account_name;
2150 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2152 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2153 "%s\n",count_sent,p));
2157 /* set overflow error */
2158 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2159 "username %s\n",count_sent,name));
2165 pdb_search_destroy(search);
2167 *rdata_len = PTR_DIFF(p,*rdata);
2169 SSVAL(*rparam,0,errflags);
2170 SSVAL(*rparam,2,0); /* converter word */
2171 SSVAL(*rparam,4,count_sent); /* is this right?? */
2172 SSVAL(*rparam,6,num_users); /* is this right?? */
2177 /****************************************************************************
2178 Get the time of day info.
2179 ****************************************************************************/
2181 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
2182 int mdrcnt,int mprcnt,
2183 char **rdata,char **rparam,
2184 int *rdata_len,int *rparam_len)
2187 time_t unixdate = time(NULL);
2191 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2197 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2202 SSVAL(*rparam,0,NERR_Success);
2203 SSVAL(*rparam,2,0); /* converter word */
2207 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2208 by NT in a "net time" operation,
2209 it seems to ignore the one below */
2211 /* the client expects to get localtime, not GMT, in this bit
2212 (I think, this needs testing) */
2213 t = localtime(&unixdate);
2215 SIVAL(p,4,0); /* msecs ? */
2216 SCVAL(p,8,t->tm_hour);
2217 SCVAL(p,9,t->tm_min);
2218 SCVAL(p,10,t->tm_sec);
2219 SCVAL(p,11,0); /* hundredths of seconds */
2220 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2221 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2222 SCVAL(p,16,t->tm_mday);
2223 SCVAL(p,17,t->tm_mon + 1);
2224 SSVAL(p,18,1900+t->tm_year);
2225 SCVAL(p,20,t->tm_wday);
2230 /****************************************************************************
2231 Set the user password.
2232 *****************************************************************************/
2234 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2235 int mdrcnt,int mprcnt,
2236 char **rdata,char **rparam,
2237 int *rdata_len,int *rparam_len)
2239 char *p = skip_string(param+2,2);
2241 fstring pass1,pass2;
2243 pull_ascii_fstring(user,p);
2245 p = skip_string(p,1);
2247 memset(pass1,'\0',sizeof(pass1));
2248 memset(pass2,'\0',sizeof(pass2));
2250 memcpy(pass2,p+16,16);
2253 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2260 SSVAL(*rparam,0,NERR_badpass);
2261 SSVAL(*rparam,2,0); /* converter word */
2263 DEBUG(3,("Set password for <%s>\n",user));
2266 * Attempt to verify the old password against smbpasswd entries
2267 * Win98 clients send old and new password in plaintext for this call.
2271 auth_serversupplied_info *server_info = NULL;
2272 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2274 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2277 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2278 SSVAL(*rparam,0,NERR_Success);
2282 TALLOC_FREE(server_info);
2284 data_blob_clear_free(&password);
2288 * If the plaintext change failed, attempt
2289 * the old encrypted method. NT will generate this
2290 * after trying the samr method. Note that this
2291 * method is done as a last resort as this
2292 * password change method loses the NT password hash
2293 * and cannot change the UNIX password as no plaintext
2297 if(SVAL(*rparam,0) != NERR_Success) {
2298 struct samu *hnd = NULL;
2300 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2302 if (change_lanman_password(hnd,(uchar *)pass2)) {
2303 SSVAL(*rparam,0,NERR_Success);
2310 memset((char *)pass1,'\0',sizeof(fstring));
2311 memset((char *)pass2,'\0',sizeof(fstring));
2316 /****************************************************************************
2317 Set the user password (SamOEM version - gets plaintext).
2318 ****************************************************************************/
2320 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2321 int mdrcnt,int mprcnt,
2322 char **rdata,char **rparam,
2323 int *rdata_len,int *rparam_len)
2326 char *p = param + 2;
2328 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2335 SSVAL(*rparam,0,NERR_badpass);
2338 * Check the parameter definition is correct.
2341 if(!strequal(param + 2, "zsT")) {
2342 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2345 p = skip_string(p, 1);
2347 if(!strequal(p, "B516B16")) {
2348 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2351 p = skip_string(p,1);
2352 p += pull_ascii_fstring(user,p);
2354 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2357 * Pass the user through the NT -> unix user mapping
2361 (void)map_username(user);
2363 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2364 SSVAL(*rparam,0,NERR_Success);
2370 /****************************************************************************
2373 ****************************************************************************/
2375 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2376 int mdrcnt,int mprcnt,
2377 char **rdata,char **rparam,
2378 int *rdata_len,int *rparam_len)
2380 int function = SVAL(param,0);
2381 char *str1 = param+2;
2382 char *str2 = skip_string(str1,1);
2383 char *p = skip_string(str2,1);
2388 WERROR werr = WERR_OK;
2390 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2393 /* check it's a supported varient */
2394 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2398 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2404 if (!print_job_exists(sharename, jobid)) {
2405 errcode = NERR_JobNotFound;
2409 snum = lp_servicenumber( sharename);
2411 errcode = NERR_DestNotFound;
2415 errcode = NERR_notsupported;
2418 case 81: /* delete */
2419 if (print_job_delete(¤t_user, snum, jobid, &werr))
2420 errcode = NERR_Success;
2422 case 82: /* pause */
2423 if (print_job_pause(¤t_user, snum, jobid, &werr))
2424 errcode = NERR_Success;
2426 case 83: /* resume */
2427 if (print_job_resume(¤t_user, snum, jobid, &werr))
2428 errcode = NERR_Success;
2432 if (!W_ERROR_IS_OK(werr))
2433 errcode = W_ERROR_V(werr);
2436 SSVAL(*rparam,0,errcode);
2437 SSVAL(*rparam,2,0); /* converter word */
2442 /****************************************************************************
2443 Purge a print queue - or pause or resume it.
2444 ****************************************************************************/
2446 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2447 int mdrcnt,int mprcnt,
2448 char **rdata,char **rparam,
2449 int *rdata_len,int *rparam_len)
2451 int function = SVAL(param,0);
2452 char *str1 = param+2;
2453 char *str2 = skip_string(str1,1);
2454 char *QueueName = skip_string(str2,1);
2455 int errcode = NERR_notsupported;
2457 WERROR werr = WERR_OK;
2459 /* check it's a supported varient */
2460 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2464 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2470 snum = print_queue_snum(QueueName);
2473 errcode = NERR_JobNotFound;
2478 case 74: /* Pause queue */
2479 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2481 case 75: /* Resume queue */
2482 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2484 case 103: /* Purge */
2485 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2489 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2492 SSVAL(*rparam,0,errcode);
2493 SSVAL(*rparam,2,0); /* converter word */
2498 /****************************************************************************
2499 set the property of a print job (undocumented?)
2500 ? function = 0xb -> set name of print job
2501 ? function = 0x6 -> move print job up/down
2502 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2503 or <WWsTP> <WB21BB16B10zWWzDDz>
2504 ****************************************************************************/
2506 static int check_printjob_info(struct pack_desc* desc,
2507 int uLevel, char* id)
2509 desc->subformat = NULL;
2511 case 0: desc->format = "W"; break;
2512 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2513 case 2: desc->format = "WWzWWDDzz"; break;
2514 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2515 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2516 default: return False;
2518 if (strcmp(desc->format,id) != 0) return False;
2522 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2523 int mdrcnt,int mprcnt,
2524 char **rdata,char **rparam,
2525 int *rdata_len,int *rparam_len)
2527 struct pack_desc desc;
2528 char *str1 = param+2;
2529 char *str2 = skip_string(str1,1);
2530 char *p = skip_string(str2,1);
2534 int uLevel = SVAL(p,2);
2535 int function = SVAL(p,4);
2538 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2541 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2546 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2547 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2554 /* check it's a supported varient */
2555 if ((strcmp(str1,"WWsTP")) ||
2556 (!check_printjob_info(&desc,uLevel,str2)))
2559 if (!print_job_exists(sharename, jobid)) {
2560 errcode=NERR_JobNotFound;
2564 errcode = NERR_notsupported;
2568 /* change job place in the queue,
2569 data gives the new place */
2570 place = SVAL(data,0);
2571 if (print_job_set_place(snum, jobid, place)) {
2572 errcode=NERR_Success;
2577 /* change print job name, data gives the name */
2578 if (print_job_set_name(snum, jobid, data)) {
2579 errcode=NERR_Success;
2588 SSVALS(*rparam,0,errcode);
2589 SSVAL(*rparam,2,0); /* converter word */
2595 /****************************************************************************
2596 Get info about the server.
2597 ****************************************************************************/
2599 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2600 int mdrcnt,int mprcnt,
2601 char **rdata,char **rparam,
2602 int *rdata_len,int *rparam_len)
2604 char *str1 = param+2;
2605 char *str2 = skip_string(str1,1);
2606 char *p = skip_string(str2,1);
2607 int uLevel = SVAL(p,0);
2611 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2613 /* check it's a supported varient */
2614 if (!prefix_ok(str1,"WrLh")) {
2620 if (strcmp(str2,"B16") != 0) {
2626 if (strcmp(str2,"B16BBDz") != 0) {
2632 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2638 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2644 if (strcmp(str2,"DN") != 0) {
2650 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2659 *rdata_len = mdrcnt;
2660 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2666 p2 = p + struct_len;
2668 srvstr_push(NULL, p,get_local_machine_name(),16,
2669 STR_ASCII|STR_UPPER|STR_TERMINATE);
2673 struct srv_info_struct *servers=NULL;
2676 uint32 servertype= lp_default_server_announce();
2678 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2680 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2681 for (i=0;i<count;i++) {
2682 if (strequal(servers[i].name,get_local_machine_name())) {
2683 servertype = servers[i].type;
2684 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2691 SCVAL(p,0,lp_major_announce_version());
2692 SCVAL(p,1,lp_minor_announce_version());
2693 SIVAL(p,2,servertype);
2695 if (mdrcnt == struct_len) {
2698 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2699 standard_sub_conn(conn,comment,sizeof(comment));
2700 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2701 p2 = skip_string(p2,1);
2706 return False; /* not yet implemented */
2709 *rdata_len = PTR_DIFF(p2,*rdata);
2712 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2716 SSVAL(*rparam,0,NERR_Success);
2717 SSVAL(*rparam,2,0); /* converter word */
2718 SSVAL(*rparam,4,*rdata_len);
2723 /****************************************************************************
2724 Get info about the server.
2725 ****************************************************************************/
2727 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2728 int mdrcnt,int mprcnt,
2729 char **rdata,char **rparam,
2730 int *rdata_len,int *rparam_len)
2732 char *str1 = param+2;
2733 char *str2 = skip_string(str1,1);
2734 char *p = skip_string(str2,1);
2736 int level = SVAL(p,0);
2738 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2741 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2746 /* check it's a supported varient */
2747 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2751 *rdata_len = mdrcnt + 1024;
2752 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2757 SSVAL(*rparam,0,NERR_Success);
2758 SSVAL(*rparam,2,0); /* converter word */
2763 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2764 pstrcpy(p2,get_local_machine_name());
2766 p2 = skip_string(p2,1);
2769 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2770 pstrcpy(p2,current_user_info.smb_name);
2771 p2 = skip_string(p2,1);
2774 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2775 pstrcpy(p2,lp_workgroup());
2777 p2 = skip_string(p2,1);
2780 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2781 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2784 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2785 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2786 p2 = skip_string(p2,1);
2789 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2791 p2 = skip_string(p2,1);
2794 *rdata_len = PTR_DIFF(p2,*rdata);
2796 SSVAL(*rparam,4,*rdata_len);
2801 /****************************************************************************
2802 get info about a user
2804 struct user_info_11 {
2805 char usri11_name[21]; 0-20
2807 char *usri11_comment; 22-25
2808 char *usri11_usr_comment; 26-29
2809 unsigned short usri11_priv; 30-31
2810 unsigned long usri11_auth_flags; 32-35
2811 long usri11_password_age; 36-39
2812 char *usri11_homedir; 40-43
2813 char *usri11_parms; 44-47
2814 long usri11_last_logon; 48-51
2815 long usri11_last_logoff; 52-55
2816 unsigned short usri11_bad_pw_count; 56-57
2817 unsigned short usri11_num_logons; 58-59
2818 char *usri11_logon_server; 60-63
2819 unsigned short usri11_country_code; 64-65
2820 char *usri11_workstations; 66-69
2821 unsigned long usri11_max_storage; 70-73
2822 unsigned short usri11_units_per_week; 74-75
2823 unsigned char *usri11_logon_hours; 76-79
2824 unsigned short usri11_code_page; 80-81
2829 usri11_name specifies the user name for which information is retireved
2831 usri11_pad aligns the next data structure element to a word boundary
2833 usri11_comment is a null terminated ASCII comment
2835 usri11_user_comment is a null terminated ASCII comment about the user
2837 usri11_priv specifies the level of the privilege assigned to the user.
2838 The possible values are:
2840 Name Value Description
2841 USER_PRIV_GUEST 0 Guest privilege
2842 USER_PRIV_USER 1 User privilege
2843 USER_PRV_ADMIN 2 Administrator privilege
2845 usri11_auth_flags specifies the account operator privileges. The
2846 possible values are:
2848 Name Value Description
2849 AF_OP_PRINT 0 Print operator
2852 Leach, Naik [Page 28]
2856 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2859 AF_OP_COMM 1 Communications operator
2860 AF_OP_SERVER 2 Server operator
2861 AF_OP_ACCOUNTS 3 Accounts operator
2864 usri11_password_age specifies how many seconds have elapsed since the
2865 password was last changed.
2867 usri11_home_dir points to a null terminated ASCII string that contains
2868 the path name of the user's home directory.
2870 usri11_parms points to a null terminated ASCII string that is set
2871 aside for use by applications.
2873 usri11_last_logon specifies the time when the user last logged on.
2874 This value is stored as the number of seconds elapsed since
2875 00:00:00, January 1, 1970.
2877 usri11_last_logoff specifies the time when the user last logged off.
2878 This value is stored as the number of seconds elapsed since
2879 00:00:00, January 1, 1970. A value of 0 means the last logoff
2882 usri11_bad_pw_count specifies the number of incorrect passwords
2883 entered since the last successful logon.
2885 usri11_log1_num_logons specifies the number of times this user has
2886 logged on. A value of -1 means the number of logons is unknown.
2888 usri11_logon_server points to a null terminated ASCII string that
2889 contains the name of the server to which logon requests are sent.
2890 A null string indicates logon requests should be sent to the
2893 usri11_country_code specifies the country code for the user's language
2896 usri11_workstations points to a null terminated ASCII string that
2897 contains the names of workstations the user may log on from.
2898 There may be up to 8 workstations, with the names separated by
2899 commas. A null strings indicates there are no restrictions.
2901 usri11_max_storage specifies the maximum amount of disk space the user
2902 can occupy. A value of 0xffffffff indicates there are no
2905 usri11_units_per_week specifies the equal number of time units into
2906 which a week is divided. This value must be equal to 168.
2908 usri11_logon_hours points to a 21 byte (168 bits) string that
2909 specifies the time during which the user can log on. Each bit
2910 represents one unique hour in a week. The first bit (bit 0, word
2911 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2915 Leach, Naik [Page 29]
2919 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2922 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2923 are no restrictions.
2925 usri11_code_page specifies the code page for the user's language of
2928 All of the pointers in this data structure need to be treated
2929 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2930 to be ignored. The converter word returned in the parameters section
2931 needs to be subtracted from the lower 16 bits to calculate an offset
2932 into the return buffer where this ASCII string resides.
2934 There is no auxiliary data in the response.
2936 ****************************************************************************/
2938 #define usri11_name 0
2939 #define usri11_pad 21
2940 #define usri11_comment 22
2941 #define usri11_usr_comment 26
2942 #define usri11_full_name 30
2943 #define usri11_priv 34
2944 #define usri11_auth_flags 36
2945 #define usri11_password_age 40
2946 #define usri11_homedir 44
2947 #define usri11_parms 48
2948 #define usri11_last_logon 52
2949 #define usri11_last_logoff 56
2950 #define usri11_bad_pw_count 60
2951 #define usri11_num_logons 62
2952 #define usri11_logon_server 64
2953 #define usri11_country_code 68
2954 #define usri11_workstations 70
2955 #define usri11_max_storage 74
2956 #define usri11_units_per_week 78
2957 #define usri11_logon_hours 80
2958 #define usri11_code_page 84
2959 #define usri11_end 86
2961 #define USER_PRIV_GUEST 0
2962 #define USER_PRIV_USER 1
2963 #define USER_PRIV_ADMIN 2
2965 #define AF_OP_PRINT 0
2966 #define AF_OP_COMM 1
2967 #define AF_OP_SERVER 2
2968 #define AF_OP_ACCOUNTS 3
2971 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2972 int mdrcnt,int mprcnt,
2973 char **rdata,char **rparam,
2974 int *rdata_len,int *rparam_len)
2976 char *str1 = param+2;
2977 char *str2 = skip_string(str1,1);
2978 char *UserName = skip_string(str2,1);
2979 char *p = skip_string(UserName,1);
2980 int uLevel = SVAL(p,0);
2982 const char *level_string;
2984 /* get NIS home of a previously validated user - simeon */
2985 /* With share level security vuid will always be zero.
2986 Don't depend on vuser being non-null !!. JRA */
2987 user_struct *vuser = get_valid_user_struct(vuid);
2989 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2990 vuser->user.unix_name));
2994 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2999 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3001 /* check it's a supported variant */
3002 if (strcmp(str1,"zWrLh") != 0) {
3006 case 0: level_string = "B21"; break;
3007 case 1: level_string = "B21BB16DWzzWz"; break;
3008 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3009 case 10: level_string = "B21Bzzz"; break;
3010 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3011 default: return False;
3014 if (strcmp(level_string,str2) != 0) {
3018 *rdata_len = mdrcnt + 1024;
3019 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3024 SSVAL(*rparam,0,NERR_Success);
3025 SSVAL(*rparam,2,0); /* converter word */
3028 p2 = p + usri11_end;
3031 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3034 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3039 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3040 pstrcpy(p2,"Comment");
3041 p2 = skip_string(p2,1);
3043 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3044 pstrcpy(p2,"UserComment");
3045 p2 = skip_string(p2,1);
3047 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3048 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3049 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3050 p2 = skip_string(p2,1);
3054 /* modelled after NTAS 3.51 reply */
3055 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3056 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3057 SIVALS(p,usri11_password_age,-1); /* password age */
3058 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3059 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3060 p2 = skip_string(p2,1);
3061 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3063 p2 = skip_string(p2,1);
3064 SIVAL(p,usri11_last_logon,0); /* last logon */
3065 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3066 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3067 SSVALS(p,usri11_num_logons,-1); /* num logons */
3068 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3069 pstrcpy(p2,"\\\\*");
3070 p2 = skip_string(p2,1);
3071 SSVAL(p,usri11_country_code,0); /* country code */
3073 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3075 p2 = skip_string(p2,1);
3077 SIVALS(p,usri11_max_storage,-1); /* max storage */
3078 SSVAL(p,usri11_units_per_week,168); /* units per week */
3079 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3081 /* a simple way to get logon hours at all times. */
3083 SCVAL(p2,21,0); /* fix zero termination */
3084 p2 = skip_string(p2,1);
3086 SSVAL(p,usri11_code_page,0); /* code page */
3089 if (uLevel == 1 || uLevel == 2) {
3090 memset(p+22,' ',16); /* password */
3091 SIVALS(p,38,-1); /* password age */
3093 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3094 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3095 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3096 p2 = skip_string(p2,1);
3097 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3099 SSVAL(p,52,0); /* flags */
3100 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3101 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3102 p2 = skip_string(p2,1);
3104 SIVAL(p,60,0); /* auth_flags */
3105 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3106 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3107 p2 = skip_string(p2,1);
3108 SIVAL(p,68,0); /* urs_comment */
3109 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3111 p2 = skip_string(p2,1);
3112 SIVAL(p,76,0); /* workstations */
3113 SIVAL(p,80,0); /* last_logon */
3114 SIVAL(p,84,0); /* last_logoff */
3115 SIVALS(p,88,-1); /* acct_expires */
3116 SIVALS(p,92,-1); /* max_storage */
3117 SSVAL(p,96,168); /* units_per_week */
3118 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3121 SSVALS(p,102,-1); /* bad_pw_count */
3122 SSVALS(p,104,-1); /* num_logons */
3123 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3124 pstrcpy(p2,"\\\\%L");
3125 standard_sub_conn(conn, p2,0);
3126 p2 = skip_string(p2,1);
3127 SSVAL(p,110,49); /* country_code */
3128 SSVAL(p,112,860); /* code page */
3132 *rdata_len = PTR_DIFF(p2,*rdata);
3134 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3139 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
3140 int mdrcnt,int mprcnt,
3141 char **rdata,char **rparam,
3142 int *rdata_len,int *rparam_len)
3144 char *str1 = param+2;
3145 char *str2 = skip_string(str1,1);
3146 char *p = skip_string(str2,1);
3148 struct pack_desc desc;
3150 /* With share level security vuid will always be zero.
3151 Don't depend on vuser being non-null !!. JRA */
3152 user_struct *vuser = get_valid_user_struct(vuid);
3155 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3156 vuser->user.unix_name));
3162 memset((char *)&desc,'\0',sizeof(desc));
3164 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3166 /* check it's a supported varient */
3167 if (strcmp(str1,"OOWb54WrLh") != 0) {
3170 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3174 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3181 desc.buflen = mdrcnt;
3182 desc.subformat = NULL;
3185 if (init_package(&desc,1,0)) {
3186 PACKI(&desc,"W",0); /* code */
3187 PACKS(&desc,"B21",name); /* eff. name */
3188 PACKS(&desc,"B",""); /* pad */
3189 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3190 PACKI(&desc,"D",0); /* auth flags XXX */
3191 PACKI(&desc,"W",0); /* num logons */
3192 PACKI(&desc,"W",0); /* bad pw count */
3193 PACKI(&desc,"D",0); /* last logon */
3194 PACKI(&desc,"D",-1); /* last logoff */
3195 PACKI(&desc,"D",-1); /* logoff time */
3196 PACKI(&desc,"D",-1); /* kickoff time */
3197 PACKI(&desc,"D",0); /* password age */
3198 PACKI(&desc,"D",0); /* password can change */
3199 PACKI(&desc,"D",-1); /* password must change */
3203 fstrcpy(mypath,"\\\\");
3204 fstrcat(mypath,get_local_machine_name());
3206 PACKS(&desc,"z",mypath); /* computer */
3209 PACKS(&desc,"z",lp_workgroup());/* domain */
3210 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3211 PACKI(&desc,"D",0x00000000); /* reserved */
3214 *rdata_len = desc.usedlen;
3216 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3220 SSVALS(*rparam,0,desc.errcode);
3222 SSVAL(*rparam,4,desc.neededlen);
3224 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3229 /****************************************************************************
3230 api_WAccessGetUserPerms
3231 ****************************************************************************/
3233 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
3234 int mdrcnt,int mprcnt,
3235 char **rdata,char **rparam,
3236 int *rdata_len,int *rparam_len)
3238 char *str1 = param+2;
3239 char *str2 = skip_string(str1,1);
3240 char *user = skip_string(str2,1);
3241 char *resource = skip_string(user,1);
3243 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3245 /* check it's a supported varient */
3246 if (strcmp(str1,"zzh") != 0) {
3249 if (strcmp(str2,"") != 0) {
3254 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3258 SSVALS(*rparam,0,0); /* errorcode */
3259 SSVAL(*rparam,2,0); /* converter word */
3260 SSVAL(*rparam,4,0x7f); /* permission flags */
3265 /****************************************************************************
3266 api_WPrintJobEnumerate
3267 ****************************************************************************/
3269 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3270 int mdrcnt,int mprcnt,
3271 char **rdata,char **rparam,
3272 int *rdata_len,int *rparam_len)
3274 char *str1 = param+2;
3275 char *str2 = skip_string(str1,1);
3276 char *p = skip_string(str2,1);
3283 struct pack_desc desc;
3284 print_queue_struct *queue=NULL;
3285 print_status_struct status;
3290 memset((char *)&desc,'\0',sizeof(desc));
3291 memset((char *)&status,'\0',sizeof(status));
3293 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3295 /* check it's a supported varient */
3296 if (strcmp(str1,"WWrLh") != 0) {
3299 if (!check_printjob_info(&desc,uLevel,str2)) {
3303 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3307 snum = lp_servicenumber( sharename);
3308 if (snum < 0 || !VALID_SNUM(snum)) {
3312 count = print_queue_status(snum,&queue,&status);
3313 for (i = 0; i < count; i++) {
3314 if (queue[i].job == jobid) {
3320 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3325 desc.buflen = mdrcnt;
3328 * Don't return data but need to get correct length
3329 * init_package will return wrong size if buflen=0
3331 desc.buflen = getlen(desc.format);
3332 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3335 if (init_package(&desc,1,0)) {
3337 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3338 *rdata_len = desc.usedlen;
3340 desc.errcode = NERR_JobNotFound;
3346 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3350 SSVALS(*rparam,0,desc.errcode);
3352 SSVAL(*rparam,4,desc.neededlen);
3357 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3362 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3363 int mdrcnt,int mprcnt,
3364 char **rdata,char **rparam,
3365 int *rdata_len,int *rparam_len)
3367 char *str1 = param+2;
3368 char *str2 = skip_string(str1,1);
3369 char *p = skip_string(str2,1);
3375 struct pack_desc desc;
3376 print_queue_struct *queue=NULL;
3377 print_status_struct status;
3379 memset((char *)&desc,'\0',sizeof(desc));
3380 memset((char *)&status,'\0',sizeof(status));
3382 p = skip_string(p,1);
3385 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3387 /* check it's a supported variant */
3388 if (strcmp(str1,"zWrLeh") != 0) {
3393 return False; /* defined only for uLevel 0,1,2 */
3396 if (!check_printjob_info(&desc,uLevel,str2)) {
3400 snum = find_service(name);
3401 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3405 count = print_queue_status(snum,&queue,&status);
3407 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3413 desc.buflen = mdrcnt;
3415 if (init_package(&desc,count,0)) {
3417 for (i = 0; i < count; i++) {
3418 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3419 if (desc.errcode == NERR_Success) {
3425 *rdata_len = desc.usedlen;
3428 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3432 SSVALS(*rparam,0,desc.errcode);
3434 SSVAL(*rparam,4,succnt);
3435 SSVAL(*rparam,6,count);
3439 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3444 static int check_printdest_info(struct pack_desc* desc,
3445 int uLevel, char* id)
3447 desc->subformat = NULL;
3450 desc->format = "B9";
3453 desc->format = "B9B21WWzW";
3459 desc->format = "zzzWWzzzWW";
3464 if (strcmp(desc->format,id) != 0) {
3470 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3471 struct pack_desc* desc)
3475 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3476 buf[sizeof(buf)-1] = 0;
3480 PACKS(desc,"B9",buf); /* szName */
3482 PACKS(desc,"B21",""); /* szUserName */
3483 PACKI(desc,"W",0); /* uJobId */
3484 PACKI(desc,"W",0); /* fsStatus */
3485 PACKS(desc,"z",""); /* pszStatus */
3486 PACKI(desc,"W",0); /* time */
3490 if (uLevel == 2 || uLevel == 3) {
3491 PACKS(desc,"z",buf); /* pszPrinterName */
3493 PACKS(desc,"z",""); /* pszUserName */
3494 PACKS(desc,"z",""); /* pszLogAddr */
3495 PACKI(desc,"W",0); /* uJobId */
3496 PACKI(desc,"W",0); /* fsStatus */
3497 PACKS(desc,"z",""); /* pszStatus */
3498 PACKS(desc,"z",""); /* pszComment */
3499 PACKS(desc,"z","NULL"); /* pszDrivers */
3500 PACKI(desc,"W",0); /* time */
3501 PACKI(desc,"W",0); /* pad1 */
3506 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3507 int mdrcnt,int mprcnt,
3508 char **rdata,char **rparam,
3509 int *rdata_len,int *rparam_len)
3511 char *str1 = param+2;
3512 char *str2 = skip_string(str1,1);
3513 char *p = skip_string(str2,1);
3514 char* PrinterName = p;
3516 struct pack_desc desc;
3520 memset((char *)&desc,'\0',sizeof(desc));
3522 p = skip_string(p,1);
3525 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3527 /* check it's a supported varient */
3528 if (strcmp(str1,"zWrLh") != 0) {
3531 if (!check_printdest_info(&desc,uLevel,str2)) {
3535 snum = find_service(PrinterName);
3536 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3538 desc.errcode = NERR_DestNotFound;
3542 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3547 desc.buflen = mdrcnt;
3550 * Don't return data but need to get correct length
3551 * init_package will return wrong size if buflen=0
3553 desc.buflen = getlen(desc.format);
3554 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3556 if (init_package(&desc,1,0)) {
3557 fill_printdest_info(conn,snum,uLevel,&desc);
3559 *rdata_len = desc.usedlen;
3563 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3567 SSVALS(*rparam,0,desc.errcode);
3569 SSVAL(*rparam,4,desc.neededlen);
3571 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3577 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3578 int mdrcnt,int mprcnt,
3579 char **rdata,char **rparam,
3580 int *rdata_len,int *rparam_len)
3582 char *str1 = param+2;
3583 char *str2 = skip_string(str1,1);
3584 char *p = skip_string(str2,1);
3588 struct pack_desc desc;
3589 int services = lp_numservices();
3591 memset((char *)&desc,'\0',sizeof(desc));
3595 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3597 /* check it's a supported varient */
3598 if (strcmp(str1,"WrLeh") != 0) {
3601 if (!check_printdest_info(&desc,uLevel,str2)) {
3606 for (i = 0; i < services; i++) {
3607 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3613 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3620 desc.buflen = mdrcnt;
3621 if (init_package(&desc,queuecnt,0)) {
3624 for (i = 0; i < services; i++) {
3625 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3626 fill_printdest_info(conn,i,uLevel,&desc);
3628 if (desc.errcode == NERR_Success) {
3635 *rdata_len = desc.usedlen;
3638 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3642 SSVALS(*rparam,0,desc.errcode);
3644 SSVAL(*rparam,4,succnt);
3645 SSVAL(*rparam,6,queuecnt);
3647 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3652 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3653 int mdrcnt,int mprcnt,
3654 char **rdata,char **rparam,
3655 int *rdata_len,int *rparam_len)
3657 char *str1 = param+2;
3658 char *str2 = skip_string(str1,1);
3659 char *p = skip_string(str2,1);
3662 struct pack_desc desc;
3664 memset((char *)&desc,'\0',sizeof(desc));
3668 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3670 /* check it's a supported varient */
3671 if (strcmp(str1,"WrLeh") != 0) {
3674 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
3679 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3685 desc.buflen = mdrcnt;
3686 if (init_package(&desc,1,0)) {
3687 PACKS(&desc,"B41","NULL");
3690 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3692 *rdata_len = desc.usedlen;
3695 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3699 SSVALS(*rparam,0,desc.errcode);
3701 SSVAL(*rparam,4,succnt);
3704 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3709 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3710 int mdrcnt,int mprcnt,
3711 char **rdata,char **rparam,
3712 int *rdata_len,int *rparam_len)
3714 char *str1 = param+2;
3715 char *str2 = skip_string(str1,1);
3716 char *p = skip_string(str2,1);
3719 struct pack_desc desc;
3721 memset((char *)&desc,'\0',sizeof(desc));
3725 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3727 /* check it's a supported varient */
3728 if (strcmp(str1,"WrLeh") != 0) {
3731 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
3736 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3742 desc.buflen = mdrcnt;
3744 if (init_package(&desc,1,0)) {
3745 PACKS(&desc,"B13","lpd");
3748 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3750 *rdata_len = desc.usedlen;
3753 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3757 SSVALS(*rparam,0,desc.errcode);
3759 SSVAL(*rparam,4,succnt);
3762 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3767 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3768 int mdrcnt,int mprcnt,
3769 char **rdata,char **rparam,
3770 int *rdata_len,int *rparam_len)
3772 char *str1 = param+2;
3773 char *str2 = skip_string(str1,1);
3774 char *p = skip_string(str2,1);
3777 struct pack_desc desc;
3779 memset((char *)&desc,'\0',sizeof(desc));
3783 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3785 /* check it's a supported varient */
3786 if (strcmp(str1,"WrLeh") != 0) {
3789 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
3794 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3799 memset((char *)&desc,'\0',sizeof(desc));
3801 desc.buflen = mdrcnt;
3803 if (init_package(&desc,1,0)) {
3804 PACKS(&desc,"B13","lp0");
3807 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3809 *rdata_len = desc.usedlen;
3812 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3816 SSVALS(*rparam,0,desc.errcode);
3818 SSVAL(*rparam,4,succnt);
3821 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3827 /****************************************************************************
3829 ****************************************************************************/
3830 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3831 int mdrcnt,int mprcnt,
3832 char **rdata,char **rparam,
3833 int *rdata_len,int *rparam_len)
3836 char *str1 = param+2;
3837 char *str2 = skip_string(str1,1);
3838 char *p = skip_string(str2,1);
3840 struct pack_desc desc;
3841 struct sessionid *session_list;
3842 int i, num_sessions;
3844 memset((char *)&desc,'\0',sizeof(desc));
3848 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3849 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3850 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3852 /* check it's a supported varient */
3853 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
3856 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
3860 num_sessions = list_sessions(&session_list);
3863 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3868 memset((char *)&desc,'\0',sizeof(desc));
3870 desc.buflen = mdrcnt;
3872 if (!init_package(&desc,num_sessions,0)) {
3876 for(i=0; i<num_sessions; i++) {
3877 PACKS(&desc, "z", session_list[i].remote_machine);
3878 PACKS(&desc, "z", session_list[i].username);
3879 PACKI(&desc, "W", 1); /* num conns */
3880 PACKI(&desc, "W", 0); /* num opens */
3881 PACKI(&desc, "W", 1); /* num users */
3882 PACKI(&desc, "D", 0); /* session time */
3883 PACKI(&desc, "D", 0); /* idle time */
3884 PACKI(&desc, "D", 0); /* flags */
3885 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3888 *rdata_len = desc.usedlen;
3891 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3895 SSVALS(*rparam,0,desc.errcode);
3896 SSVAL(*rparam,2,0); /* converter */
3897 SSVAL(*rparam,4,num_sessions); /* count */
3899 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3905 /****************************************************************************
3906 The buffer was too small.
3907 ****************************************************************************/
3909 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
3910 int mdrcnt, int mprcnt,
3911 char **rdata, char **rparam,
3912 int *rdata_len, int *rparam_len)
3914 *rparam_len = MIN(*rparam_len,mprcnt);
3915 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3922 SSVAL(*rparam,0,NERR_BufTooSmall);
3924 DEBUG(3,("Supplied buffer too small in API command\n"));
3929 /****************************************************************************
3930 The request is not supported.
3931 ****************************************************************************/
3933 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
3934 int mdrcnt, int mprcnt,
3935 char **rdata, char **rparam,
3936 int *rdata_len, int *rparam_len)
3939 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3946 SSVAL(*rparam,0,NERR_notsupported);
3947 SSVAL(*rparam,2,0); /* converter word */
3949 DEBUG(3,("Unsupported API command\n"));
3954 static const struct {
3957 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3958 int,int,char **,char **,int *,int *);
3959 BOOL auth_user; /* Deny anonymous access? */
3960 } api_commands[] = {
3961 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3962 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3963 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3964 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3965 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3966 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3967 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3968 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3969 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3970 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3971 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3972 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3973 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3974 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3975 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3976 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3977 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3978 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3979 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3980 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3981 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3982 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3983 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3984 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3985 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3986 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3987 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3988 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3989 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3990 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3991 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3992 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3993 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3994 {NULL, -1, api_Unsupported}
3995 /* The following RAP calls are not implemented by Samba:
3997 RAP_WFileEnum2 - anon not OK
4002 /****************************************************************************
4003 Handle remote api calls
4004 ****************************************************************************/
4006 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4007 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4011 char *rparam = NULL;
4018 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4022 api_command = SVAL(params,0);
4024 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4027 skip_string(params+2,1),
4028 tdscnt,tpscnt,mdrcnt,mprcnt));
4030 for (i=0;api_commands[i].name;i++) {
4031 if (api_commands[i].id == api_command && api_commands[i].fn) {
4032 DEBUG(3,("Doing %s\n",api_commands[i].name));
4037 /* Check whether this api call can be done anonymously */
4039 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4040 user_struct *user = get_valid_user_struct(vuid);
4042 if (!user || user->guest) {
4043 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4047 rdata = (char *)SMB_MALLOC(1024);
4049 memset(rdata,'\0',1024);
4052 rparam = (char *)SMB_MALLOC(1024);
4054 memset(rparam,'\0',1024);
4057 if(!rdata || !rparam) {
4058 DEBUG(0,("api_reply: malloc fail !\n"));
4064 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
4065 &rdata,&rparam,&rdata_len,&rparam_len);
4068 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4069 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4070 &rdata,&rparam,&rdata_len,&rparam_len);
4073 /* if we get False back then it's actually unsupported */
4075 reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
4076 &rdata,&rparam,&rdata_len,&rparam_len);
4079 /* If api_Unsupported returns false we can't return anything. */
4081 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);