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
35 extern fstring local_machine;
37 #define NERR_Success 0
38 #define NERR_badpass 86
39 #define NERR_notsupported 50
41 #define NERR_BASE (2100)
42 #define NERR_BufTooSmall (NERR_BASE+23)
43 #define NERR_JobNotFound (NERR_BASE+51)
44 #define NERR_DestNotFound (NERR_BASE+52)
46 #define ACCESS_READ 0x01
47 #define ACCESS_WRITE 0x02
48 #define ACCESS_CREATE 0x04
50 #define SHPWLEN 8 /* share password length */
52 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
53 int mdrcnt,int mprcnt,
54 char **rdata,char **rparam,
55 int *rdata_len,int *rparam_len);
56 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
57 int mdrcnt,int mprcnt,
58 char **rdata,char **rparam,
59 int *rdata_len,int *rparam_len);
62 static int CopyExpanded(connection_struct *conn,
63 int snum, char** dst, char* src, int* n)
68 if (!src || !dst || !n || !(*dst)) return(0);
70 StrnCpy(buf,src,sizeof(buf)/2);
71 pstring_sub(buf,"%S",lp_servicename(snum));
72 standard_sub_conn(conn,buf,sizeof(buf));
73 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
79 static int CopyAndAdvance(char** dst, char* src, int* n)
82 if (!src || !dst || !n || !(*dst)) return(0);
83 l = push_ascii(*dst,src,*n, STR_TERMINATE);
89 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
93 StrnCpy(buf,s,sizeof(buf)/2);
94 pstring_sub(buf,"%S",lp_servicename(snum));
95 standard_sub_conn(conn,buf,sizeof(buf));
96 return strlen(buf) + 1;
99 static char* Expand(connection_struct *conn, int snum, char* s)
102 if (!s) return(NULL);
103 StrnCpy(buf,s,sizeof(buf)/2);
104 pstring_sub(buf,"%S",lp_servicename(snum));
105 standard_sub_conn(conn,buf,sizeof(buf));
109 /*******************************************************************
110 check a API string for validity when we only need to check the prefix
111 ******************************************************************/
112 static BOOL prefix_ok(const char *str, const char *prefix)
114 return(strncmp(str,prefix,strlen(prefix)) == 0);
118 const char* format; /* formatstring for structure */
119 const char* subformat; /* subformat for structure */
120 char* base; /* baseaddress of buffer */
121 int buflen; /* remaining size for fixed part; on init: length of base */
122 int subcount; /* count of substructures */
123 char* structbuf; /* pointer into buffer for remaining fixed part */
124 int stringlen; /* remaining size for variable part */
125 char* stringbuf; /* pointer into buffer for remaining variable part */
126 int neededlen; /* total needed size */
127 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
128 const char* curpos; /* current position; pointer into format or subformat */
132 static int get_counter(const char** p)
135 if (!p || !(*p)) return(1);
136 if (!isdigit((int)**p)) return 1;
140 n = 10 * n + (i - '0');
147 static int getlen(const char* p)
153 case 'W': /* word (2 byte) */
156 case 'K': /* status word? (2 byte) */
159 case 'N': /* count of substructures (word) at end */
162 case 'D': /* double word (4 byte) */
163 case 'z': /* offset to zero terminated string (4 byte) */
164 case 'l': /* offset to user data (4 byte) */
167 case 'b': /* offset to data (with counter) (4 byte) */
171 case 'B': /* byte (with optional counter) */
172 n += get_counter(&p);
179 static BOOL init_package(struct pack_desc* p, int count, int subcount)
184 if (!p->format || !p->base) return(False);
186 i = count * getlen(p->format);
187 if (p->subformat) i += subcount * getlen(p->subformat);
188 p->structbuf = p->base;
192 p->curpos = p->format;
198 * This is the old error code we used. Aparently
199 * WinNT/2k systems return ERRbuftoosmall (2123) and
200 * OS/2 needs this. I'm leaving this here so we can revert
203 p->errcode = ERRmoredata;
205 p->errcode = ERRbuftoosmall;
209 p->errcode = NERR_Success;
212 p->stringbuf = p->base + i;
214 return(p->errcode == NERR_Success);
217 static int package(struct pack_desc* p, ...)
220 int needed=0, stringneeded;
221 const char* str=NULL;
222 int is_string=0, stringused;
229 p->curpos = p->format;
231 p->curpos = p->subformat;
236 str = va_arg(args,char*);
237 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
246 switch( *p->curpos++ ) {
247 case 'W': /* word (2 byte) */
249 temp = va_arg(args,int);
250 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
252 case 'K': /* status word? (2 byte) */
254 temp = va_arg(args,int);
255 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
257 case 'N': /* count of substructures (word) at end */
259 p->subcount = va_arg(args,int);
260 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
262 case 'D': /* double word (4 byte) */
264 temp = va_arg(args,int);
265 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
267 case 'B': /* byte (with optional counter) */
268 needed = get_counter(&p->curpos);
270 char *s = va_arg(args,char*);
271 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
274 case 'z': /* offset to zero terminated string (4 byte) */
275 str = va_arg(args,char*);
276 stringneeded = (str ? strlen(str)+1 : 0);
279 case 'l': /* offset to user data (4 byte) */
280 str = va_arg(args,char*);
281 stringneeded = va_arg(args,int);
284 case 'b': /* offset to data (with counter) (4 byte) */
285 str = va_arg(args,char*);
286 stringneeded = get_counter(&p->curpos);
291 if (stringneeded >= 0) {
293 if (p->buflen >= needed) {
294 stringused = stringneeded;
295 if (stringused > p->stringlen) {
296 stringused = (is_string ? p->stringlen : 0);
297 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
300 SIVAL(p->structbuf,0,0);
302 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
303 memcpy(p->stringbuf,str?str:"",stringused);
304 if (is_string) p->stringbuf[stringused-1] = '\0';
305 p->stringbuf += stringused;
306 p->stringlen -= stringused;
307 p->usedlen += stringused;
310 p->neededlen += stringneeded;
312 p->neededlen += needed;
313 if (p->buflen >= needed) {
314 p->structbuf += needed;
316 p->usedlen += needed;
319 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
325 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
326 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
328 #define PACK(desc,t,v) package(desc,v)
329 #define PACKl(desc,t,v,l) package(desc,v,l)
332 static void PACKI(struct pack_desc* desc, const char *t,int v)
337 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
343 /****************************************************************************
345 ****************************************************************************/
346 static void PackDriverData(struct pack_desc* desc)
348 char drivdata[4+4+32];
349 SIVAL(drivdata,0,sizeof drivdata); /* cb */
350 SIVAL(drivdata,4,1000); /* lVersion */
351 memset(drivdata+8,0,32); /* szDeviceName */
352 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
353 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
356 static int check_printq_info(struct pack_desc* desc,
357 int uLevel, char *id1, char *id2)
359 desc->subformat = NULL;
362 desc->format = "B13";
365 desc->format = "B13BWWWzzzzzWW";
368 desc->format = "B13BWWWzzzzzWN";
369 desc->subformat = "WB21BB16B10zWWzDDz";
372 desc->format = "zWWWWzzzzWWzzl";
375 desc->format = "zWWWWzzzzWNzzl";
376 desc->subformat = "WWzWWDDzz";
385 desc->format = "WzzzzzzzzN";
386 desc->subformat = "z";
388 default: return False;
390 if (strcmp(desc->format,id1) != 0) return False;
391 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
396 #define RAP_JOB_STATUS_QUEUED 0
397 #define RAP_JOB_STATUS_PAUSED 1
398 #define RAP_JOB_STATUS_SPOOLING 2
399 #define RAP_JOB_STATUS_PRINTING 3
400 #define RAP_JOB_STATUS_PRINTED 4
402 #define RAP_QUEUE_STATUS_PAUSED 1
403 #define RAP_QUEUE_STATUS_ERROR 2
405 /* turn a print job status into a on the wire status
407 static int printj_status(int v)
411 return RAP_JOB_STATUS_QUEUED;
413 return RAP_JOB_STATUS_PAUSED;
415 return RAP_JOB_STATUS_SPOOLING;
417 return RAP_JOB_STATUS_PRINTING;
422 /* turn a print queue status into a on the wire status
424 static int printq_status(int v)
430 return RAP_QUEUE_STATUS_PAUSED;
432 return RAP_QUEUE_STATUS_ERROR;
435 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
436 struct pack_desc* desc,
437 print_queue_struct* queue, int n)
439 time_t t = queue->time;
441 /* the client expects localtime */
444 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
446 PACKS(desc,"B21",queue->fs_user); /* szUserName */
447 PACKS(desc,"B",""); /* pad */
448 PACKS(desc,"B16",""); /* szNotifyName */
449 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
450 PACKS(desc,"z",""); /* pszParms */
451 PACKI(desc,"W",n+1); /* uPosition */
452 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
453 PACKS(desc,"z",""); /* pszStatus */
454 PACKI(desc,"D",t); /* ulSubmitted */
455 PACKI(desc,"D",queue->size); /* ulSize */
456 PACKS(desc,"z",queue->fs_file); /* pszComment */
458 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
459 PACKI(desc,"W",queue->priority); /* uPriority */
460 PACKS(desc,"z",queue->fs_user); /* pszUserName */
461 PACKI(desc,"W",n+1); /* uPosition */
462 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
463 PACKI(desc,"D",t); /* ulSubmitted */
464 PACKI(desc,"D",queue->size); /* ulSize */
465 PACKS(desc,"z","Samba"); /* pszComment */
466 PACKS(desc,"z",queue->fs_file); /* pszDocument */
468 PACKS(desc,"z",""); /* pszNotifyName */
469 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
470 PACKS(desc,"z",""); /* pszParms */
471 PACKS(desc,"z",""); /* pszStatus */
472 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
473 PACKS(desc,"z","lpd"); /* pszQProcName */
474 PACKS(desc,"z",""); /* pszQProcParms */
475 PACKS(desc,"z","NULL"); /* pszDriverName */
476 PackDriverData(desc); /* pDriverData */
477 PACKS(desc,"z",""); /* pszPrinterName */
478 } else if (uLevel == 4) { /* OS2 */
479 PACKS(desc,"z",""); /* pszSpoolFileName */
480 PACKS(desc,"z",""); /* pszPortName */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKI(desc,"D",0); /* ulPagesSpooled */
483 PACKI(desc,"D",0); /* ulPagesSent */
484 PACKI(desc,"D",0); /* ulPagesPrinted */
485 PACKI(desc,"D",0); /* ulTimePrinted */
486 PACKI(desc,"D",0); /* ulExtendJobStatus */
487 PACKI(desc,"D",0); /* ulStartPage */
488 PACKI(desc,"D",0); /* ulEndPage */
493 /********************************************************************
494 Return a driver name given an snum.
495 Returns True if from tdb, False otherwise.
496 ********************************************************************/
498 static BOOL get_driver_name(int snum, pstring drivername)
500 NT_PRINTER_INFO_LEVEL *info = NULL;
503 get_a_printer (NULL, &info, 2, lp_servicename(snum));
505 pstrcpy( drivername, info->info_2->drivername);
507 free_a_printer(&info, 2);
513 /********************************************************************
514 Respond to the DosPrintQInfo command with a level of 52
515 This is used to get printer driver information for Win9x clients
516 ********************************************************************/
517 static void fill_printq_info_52(connection_struct *conn, int snum,
518 struct pack_desc* desc, int count )
522 NT_PRINTER_DRIVER_INFO_LEVEL driver;
523 NT_PRINTER_INFO_LEVEL *printer = NULL;
527 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
528 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
529 lp_servicename(snum)));
533 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
536 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
537 printer->info_2->drivername));
541 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
542 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
543 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
545 PACKI(desc, "W", 0x0400); /* don't know */
546 PACKS(desc, "z", driver.info_3->name); /* long printer name */
547 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
548 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
549 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
551 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
552 standard_sub_basic( "", location, sizeof(location)-1 );
553 PACKS(desc,"z", location); /* share to retrieve files */
555 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
556 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
557 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
559 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
560 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
561 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
562 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
563 DEBUG(3,("Driver Location: %s:\n",location));
564 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
565 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
566 PACKI(desc,"N",count); /* number of files to copy */
568 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
570 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
571 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
572 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
577 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
580 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
582 desc->errcode=NERR_Success;
586 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
587 desc->errcode=NERR_notsupported;
591 free_a_printer( &printer, 2 );
594 free_a_printer_driver( driver, 3 );
598 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
599 struct pack_desc* desc,
600 int count, print_queue_struct* queue,
601 print_status_struct* status)
606 PACKS(desc,"B13",SERVICE(snum));
611 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
614 PACKI(desc,"K",printq_status(status->status));
618 if (uLevel == 1 || uLevel == 2) {
619 PACKS(desc,"B",""); /* alignment */
620 PACKI(desc,"W",5); /* priority */
621 PACKI(desc,"W",0); /* start time */
622 PACKI(desc,"W",0); /* until time */
623 PACKS(desc,"z",""); /* pSepFile */
624 PACKS(desc,"z","lpd"); /* pPrProc */
625 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
626 PACKS(desc,"z",""); /* pParms */
628 PACKS(desc,"z","UNKNOWN PRINTER");
629 PACKI(desc,"W",LPSTAT_ERROR);
631 else if (!status || !status->message[0]) {
632 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
633 PACKI(desc,"W",LPSTAT_OK); /* status */
635 PACKS(desc,"z",status->message);
636 PACKI(desc,"W",printq_status(status->status)); /* status */
638 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
641 if (uLevel == 3 || uLevel == 4) {
644 PACKI(desc,"W",5); /* uPriority */
645 PACKI(desc,"W",0); /* uStarttime */
646 PACKI(desc,"W",0); /* uUntiltime */
647 PACKI(desc,"W",5); /* pad1 */
648 PACKS(desc,"z",""); /* pszSepFile */
649 PACKS(desc,"z","WinPrint"); /* pszPrProc */
650 PACKS(desc,"z",NULL); /* pszParms */
651 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
652 /* "don't ask" that it's done this way to fix corrupted
653 Win9X/ME printer comments. */
655 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
657 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
659 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
660 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
661 get_driver_name(snum,drivername);
662 PACKS(desc,"z",drivername); /* pszDriverName */
663 PackDriverData(desc); /* pDriverData */
666 if (uLevel == 2 || uLevel == 4) {
668 for (i=0;i<count;i++)
669 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
673 fill_printq_info_52( conn, snum, desc, count );
676 /* This function returns the number of files for a given driver */
677 static int get_printerdrivernumber(int snum)
680 NT_PRINTER_DRIVER_INFO_LEVEL driver;
681 NT_PRINTER_INFO_LEVEL *printer = NULL;
685 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
686 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
687 lp_servicename(snum)));
691 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
694 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
695 printer->info_2->drivername));
699 /* count the number of files */
700 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
705 free_a_printer( &printer, 2 );
708 free_a_printer_driver( driver, 3 );
713 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
714 uint16 vuid, char *param,char *data,
715 int mdrcnt,int mprcnt,
716 char **rdata,char **rparam,
717 int *rdata_len,int *rparam_len)
719 char *str1 = param+2;
720 char *str2 = skip_string(str1,1);
721 char *p = skip_string(str2,1);
727 struct pack_desc desc;
728 print_queue_struct *queue=NULL;
729 print_status_struct status;
732 memset((char *)&status,'\0',sizeof(status));
733 memset((char *)&desc,'\0',sizeof(desc));
735 p = skip_string(p,1);
739 /* remove any trailing username */
740 if ((p = strchr_m(QueueName,'%')))
743 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
745 /* check it's a supported varient */
746 if (!prefix_ok(str1,"zWrLh"))
748 if (!check_printq_info(&desc,uLevel,str2,str3)) {
750 * Patch from Scott Moomaw <scott@bridgewater.edu>
751 * to return the 'invalid info level' error if an
752 * unknown level was requested.
756 *rparam = REALLOC(*rparam,*rparam_len);
757 SSVALS(*rparam,0,ERRunknownlevel);
763 snum = lp_servicenumber(QueueName);
764 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
765 int pnum = lp_servicenumber(PRINTERS_NAME);
767 lp_add_printer(QueueName,pnum);
768 snum = lp_servicenumber(QueueName);
772 if (snum < 0 || !VALID_SNUM(snum))
776 count = get_printerdrivernumber(snum);
777 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
779 count = print_queue_status(snum, &queue,&status);
783 *rdata = REALLOC(*rdata,mdrcnt);
785 desc.buflen = mdrcnt;
788 * Don't return data but need to get correct length
789 * init_package will return wrong size if buflen=0
791 desc.buflen = getlen(desc.format);
792 desc.base = tmpdata = (char *) malloc (desc.buflen);
795 if (init_package(&desc,1,count)) {
796 desc.subcount = count;
797 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
800 *rdata_len = desc.usedlen;
803 * We must set the return code to ERRbuftoosmall
804 * in order to support lanman style printing with Win NT/2k
807 if (!mdrcnt && lp_disable_spoolss())
808 desc.errcode = ERRbuftoosmall;
810 *rdata_len = desc.usedlen;
812 *rparam = REALLOC(*rparam,*rparam_len);
813 SSVALS(*rparam,0,desc.errcode);
815 SSVAL(*rparam,4,desc.neededlen);
817 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
825 /****************************************************************************
826 View list of all print jobs on all queues.
827 ****************************************************************************/
829 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
830 int mdrcnt, int mprcnt,
831 char **rdata, char** rparam,
832 int *rdata_len, int *rparam_len)
834 char *param_format = param+2;
835 char *output_format1 = skip_string(param_format,1);
836 char *p = skip_string(output_format1,1);
837 int uLevel = SVAL(p,0);
838 char *output_format2 = p + 4;
839 int services = lp_numservices();
841 struct pack_desc desc;
842 print_queue_struct **queue = NULL;
843 print_status_struct *status = NULL;
844 int* subcntarr = NULL;
845 int queuecnt, subcnt=0, succnt=0;
847 memset((char *)&desc,'\0',sizeof(desc));
849 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
851 if (!prefix_ok(param_format,"WrLeh")) return False;
852 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
854 * Patch from Scott Moomaw <scott@bridgewater.edu>
855 * to return the 'invalid info level' error if an
856 * unknown level was requested.
860 *rparam = REALLOC(*rparam,*rparam_len);
861 SSVALS(*rparam,0,ERRunknownlevel);
868 for (i = 0; i < services; i++)
869 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
872 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
873 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
876 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
877 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
878 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
881 memset(status,0,queuecnt*sizeof(print_status_struct));
882 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
883 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
888 for (i = 0; i < services; i++)
889 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
890 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
891 subcnt += subcntarr[n];
895 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
897 desc.buflen = mdrcnt;
899 if (init_package(&desc,queuecnt,subcnt)) {
902 for (i = 0; i < services; i++)
903 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
904 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
906 if (desc.errcode == NERR_Success) succnt = n;
910 SAFE_FREE(subcntarr);
912 *rdata_len = desc.usedlen;
914 *rparam = REALLOC(*rparam,*rparam_len);
915 SSVALS(*rparam,0,desc.errcode);
917 SSVAL(*rparam,4,succnt);
918 SSVAL(*rparam,6,queuecnt);
920 for (i = 0; i < queuecnt; i++) {
921 if (queue) SAFE_FREE(queue[i]);
930 /****************************************************************************
931 get info level for a server list query
932 ****************************************************************************/
933 static BOOL check_server_info(int uLevel, char* id)
937 if (strcmp(id,"B16") != 0) return False;
940 if (strcmp(id,"B16BBDz") != 0) return False;
948 struct srv_info_struct
958 /*******************************************************************
959 get server info lists from the files saved by nmbd. Return the
961 ******************************************************************/
962 static int get_server_info(uint32 servertype,
963 struct srv_info_struct **servers,
969 BOOL local_list_only;
972 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
974 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
978 /* request for everything is code for request all servers */
979 if (servertype == SV_TYPE_ALL)
980 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
982 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
984 DEBUG(4,("Servertype search: %8x\n",servertype));
986 for (i=0;lines[i];i++) {
988 struct srv_info_struct *s;
989 const char *ptr = lines[i];
994 if (count == alloced) {
995 struct srv_info_struct *ts;
998 ts = (struct srv_info_struct *)
999 Realloc(*servers,sizeof(**servers)*alloced);
1001 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1005 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1007 s = &(*servers)[count];
1009 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1010 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1011 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1012 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1013 /* this allows us to cope with an old nmbd */
1014 fstrcpy(s->domain,lp_workgroup());
1017 if (sscanf(stype,"%X",&s->type) != 1) {
1018 DEBUG(4,("r:host file "));
1022 /* Filter the servers/domains we return based on what was asked for. */
1024 /* Check to see if we are being asked for a local list only. */
1025 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1026 DEBUG(4,("r: local list only"));
1030 /* doesn't match up: don't want it */
1031 if (!(servertype & s->type)) {
1032 DEBUG(4,("r:serv type "));
1036 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1037 (s->type & SV_TYPE_DOMAIN_ENUM))
1039 DEBUG(4,("s: dom mismatch "));
1043 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1048 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1049 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1053 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1054 s->name, s->type, s->comment, s->domain));
1056 s->server_added = True;
1061 DEBUG(4,("%20s %8x %25s %15s\n",
1062 s->name, s->type, s->comment, s->domain));
1066 file_lines_free(lines);
1071 /*******************************************************************
1072 fill in a server info structure
1073 ******************************************************************/
1074 static int fill_srv_info(struct srv_info_struct *service,
1075 int uLevel, char **buf, int *buflen,
1076 char **stringbuf, int *stringspace, char *baseaddr)
1085 case 0: struct_len = 16; break;
1086 case 1: struct_len = 26; break;
1096 len = strlen(service->comment)+1;
1100 if (buflen) *buflen = struct_len;
1101 if (stringspace) *stringspace = len;
1102 return struct_len + len;
1107 if (*buflen < struct_len) return -1;
1115 p2 = p + struct_len;
1116 l2 = *buflen - struct_len;
1118 if (!baseaddr) baseaddr = p;
1123 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1127 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1128 SIVAL(p,18,service->type);
1129 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1130 len += CopyAndAdvance(&p2,service->comment,&l2);
1136 *buf = p + struct_len;
1137 *buflen -= struct_len;
1150 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1152 return(strcmp(s1->name,s2->name));
1155 /****************************************************************************
1156 view list of servers available (or possibly domains). The info is
1157 extracted from lists saved by nmbd on the local host
1158 ****************************************************************************/
1159 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1160 int mdrcnt, int mprcnt, char **rdata,
1161 char **rparam, int *rdata_len, int *rparam_len)
1163 char *str1 = param+2;
1164 char *str2 = skip_string(str1,1);
1165 char *p = skip_string(str2,1);
1166 int uLevel = SVAL(p,0);
1167 int buf_len = SVAL(p,2);
1168 uint32 servertype = IVAL(p,4);
1170 int data_len, fixed_len, string_len;
1171 int f_len = 0, s_len = 0;
1172 struct srv_info_struct *servers=NULL;
1173 int counted=0,total=0;
1176 BOOL domain_request;
1179 /* If someone sets all the bits they don't really mean to set
1180 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1183 if (servertype == SV_TYPE_ALL)
1184 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1186 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1187 any other bit (they may just set this bit on it's own) they
1188 want all the locally seen servers. However this bit can be
1189 set on its own so set the requested servers to be
1190 ALL - DOMAIN_ENUM. */
1192 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1193 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1195 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1196 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1200 if (!prefix_ok(str1,"WrLehD")) return False;
1201 if (!check_server_info(uLevel,str2)) return False;
1203 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1204 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1205 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1207 if (strcmp(str1, "WrLehDz") == 0) {
1208 pull_ascii_fstring(domain, p);
1210 fstrcpy(domain, lp_workgroup());
1213 if (lp_browse_list())
1214 total = get_server_info(servertype,&servers,domain);
1216 data_len = fixed_len = string_len = 0;
1220 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1223 char *lastname=NULL;
1225 for (i=0;i<total;i++)
1227 struct srv_info_struct *s = &servers[i];
1228 if (lastname && strequal(lastname,s->name)) continue;
1230 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1231 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1232 s->name, s->type, s->comment, s->domain));
1234 if (data_len <= buf_len) {
1237 string_len += s_len;
1244 *rdata_len = fixed_len + string_len;
1245 *rdata = REALLOC(*rdata,*rdata_len);
1246 memset(*rdata,'\0',*rdata_len);
1248 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1254 char *lastname=NULL;
1255 int count2 = counted;
1256 for (i = 0; i < total && count2;i++)
1258 struct srv_info_struct *s = &servers[i];
1259 if (lastname && strequal(lastname,s->name)) continue;
1261 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1262 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1263 s->name, s->type, s->comment, s->domain));
1269 *rparam = REALLOC(*rparam,*rparam_len);
1270 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1272 SSVAL(*rparam,4,counted);
1273 SSVAL(*rparam,6,counted+missed);
1277 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1278 domain,uLevel,counted,counted+missed));
1283 /****************************************************************************
1284 command 0x34 - suspected of being a "Lookup Names" stub api
1285 ****************************************************************************/
1286 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1287 int mdrcnt, int mprcnt, char **rdata,
1288 char **rparam, int *rdata_len, int *rparam_len)
1290 char *str1 = param+2;
1291 char *str2 = skip_string(str1,1);
1292 char *p = skip_string(str2,1);
1293 int uLevel = SVAL(p,0);
1294 int buf_len = SVAL(p,2);
1298 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1299 str1, str2, p, uLevel, buf_len));
1301 if (!prefix_ok(str1,"zWrLeh")) return False;
1306 *rparam = REALLOC(*rparam,*rparam_len);
1308 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1310 SSVAL(*rparam,4,counted);
1311 SSVAL(*rparam,6,counted+missed);
1316 /****************************************************************************
1317 get info about a share
1318 ****************************************************************************/
1319 static BOOL check_share_info(int uLevel, char* id)
1323 if (strcmp(id,"B13") != 0) return False;
1326 if (strcmp(id,"B13BWz") != 0) return False;
1329 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1332 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1334 default: return False;
1339 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1340 char** buf, int* buflen,
1341 char** stringbuf, int* stringspace, char* baseaddr)
1350 case 0: struct_len = 13; break;
1351 case 1: struct_len = 20; break;
1352 case 2: struct_len = 40; break;
1353 case 91: struct_len = 68; break;
1361 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1362 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1363 if (buflen) *buflen = struct_len;
1364 if (stringspace) *stringspace = len;
1365 return struct_len + len;
1370 if ((*buflen) < struct_len) return -1;
1378 p2 = p + struct_len;
1379 l2 = (*buflen) - struct_len;
1381 if (!baseaddr) baseaddr = p;
1383 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1389 type = STYPE_DISKTREE;
1390 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1391 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1392 SSVAL(p,14,type); /* device type */
1393 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1394 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1399 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1400 SSVALS(p,22,-1); /* max uses */
1401 SSVAL(p,24,1); /* current uses */
1402 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1403 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1404 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1409 memset(p+40,0,SHPWLEN+2);
1421 (*buf) = p + struct_len;
1422 (*buflen) -= struct_len;
1424 (*stringspace) = l2;
1434 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1435 int mdrcnt,int mprcnt,
1436 char **rdata,char **rparam,
1437 int *rdata_len,int *rparam_len)
1439 char *str1 = param+2;
1440 char *str2 = skip_string(str1,1);
1441 char *netname = skip_string(str2,1);
1442 char *p = skip_string(netname,1);
1443 int uLevel = SVAL(p,0);
1444 int snum = find_service(netname);
1446 if (snum < 0) return False;
1448 /* check it's a supported varient */
1449 if (!prefix_ok(str1,"zWrLh")) return False;
1450 if (!check_share_info(uLevel,str2)) return False;
1452 *rdata = REALLOC(*rdata,mdrcnt);
1454 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1455 if (*rdata_len < 0) return False;
1458 *rparam = REALLOC(*rparam,*rparam_len);
1459 SSVAL(*rparam,0,NERR_Success);
1460 SSVAL(*rparam,2,0); /* converter word */
1461 SSVAL(*rparam,4,*rdata_len);
1466 /****************************************************************************
1467 View the list of available shares.
1469 This function is the server side of the NetShareEnum() RAP call.
1470 It fills the return buffer with share names and share comments.
1471 Note that the return buffer normally (in all known cases) allows only
1472 twelve byte strings for share names (plus one for a nul terminator).
1473 Share names longer than 12 bytes must be skipped.
1474 ****************************************************************************/
1475 static BOOL api_RNetShareEnum( connection_struct *conn,
1486 char *str1 = param+2;
1487 char *str2 = skip_string(str1,1);
1488 char *p = skip_string(str2,1);
1489 int uLevel = SVAL(p,0);
1490 int buf_len = SVAL(p,2);
1492 int count=lp_numservices();
1493 int total=0,counted=0;
1494 BOOL missed = False;
1496 int data_len, fixed_len, string_len;
1497 int f_len = 0, s_len = 0;
1499 if (!prefix_ok(str1,"WrLeh")) return False;
1500 if (!check_share_info(uLevel,str2)) return False;
1502 data_len = fixed_len = string_len = 0;
1503 for (i=0;i<count;i++) {
1504 fstring servicename_dos;
1505 push_ascii_fstring(servicename_dos, lp_servicename(i));
1506 if( lp_browseable( i )
1508 && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
1511 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1512 if (data_len <= buf_len)
1516 string_len += s_len;
1522 *rdata_len = fixed_len + string_len;
1523 *rdata = REALLOC(*rdata,*rdata_len);
1524 memset(*rdata,0,*rdata_len);
1526 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1530 for( i = 0; i < count; i++ )
1532 fstring servicename_dos;
1533 push_ascii_fstring(servicename_dos, lp_servicename(i));
1534 if( lp_browseable( i )
1536 && (strlen(servicename_dos) < 13) )
1538 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1544 *rparam = REALLOC(*rparam,*rparam_len);
1545 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1547 SSVAL(*rparam,4,counted);
1548 SSVAL(*rparam,6,total);
1550 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1551 counted,total,uLevel,
1552 buf_len,*rdata_len,mdrcnt));
1554 } /* api_RNetShareEnum */
1556 /****************************************************************************
1558 ****************************************************************************/
1559 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1560 int mdrcnt,int mprcnt,
1561 char **rdata,char **rparam,
1562 int *rdata_len,int *rparam_len)
1564 char *str1 = param+2;
1565 char *str2 = skip_string(str1,1);
1566 char *p = skip_string(str2,1);
1567 int uLevel = SVAL(p,0);
1571 char *command, *cmdname;
1572 unsigned int offset;
1576 /* check it's a supported varient */
1577 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1578 if (!check_share_info(uLevel,str2)) return False;
1579 if (uLevel != 2) return False;
1581 pull_ascii_fstring(sharename,data);
1582 snum = find_service(sharename);
1583 if (snum >= 0) { /* already exists */
1588 /* only support disk share adds */
1589 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1591 offset = IVAL(data, 16);
1592 if (offset >= mdrcnt) {
1593 res = ERRinvalidparam;
1596 pull_ascii_fstring(comment, offset? (data+offset) : "");
1598 offset = IVAL(data, 26);
1599 if (offset >= mdrcnt) {
1600 res = ERRinvalidparam;
1603 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1605 string_replace(sharename, '"', ' ');
1606 string_replace(pathname, '"', ' ');
1607 string_replace(comment, '"', ' ');
1609 cmdname = lp_add_share_cmd();
1611 if (!cmdname || *cmdname == '\0') return False;
1613 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1614 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1617 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1618 if ((res = smbrun(command, NULL)) != 0) {
1619 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1625 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1627 } else return False;
1630 *rparam = REALLOC(*rparam,*rparam_len);
1631 SSVAL(*rparam,0,NERR_Success);
1632 SSVAL(*rparam,2,0); /* converter word */
1633 SSVAL(*rparam,4,*rdata_len);
1640 *rparam = REALLOC(*rparam,*rparam_len);
1642 SSVAL(*rparam,0,res);
1648 /****************************************************************************
1649 view list of groups available
1650 ****************************************************************************/
1651 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1652 int mdrcnt,int mprcnt,
1653 char **rdata,char **rparam,
1654 int *rdata_len,int *rparam_len)
1658 int resume_context, cli_buf_size;
1659 char *str1 = param+2;
1660 char *str2 = skip_string(str1,1);
1661 char *p = skip_string(str2,1);
1664 GROUP_MAP *group_list;
1667 if (strcmp(str1,"WrLeh") != 0)
1671 * W-> resume context (number of users to skip)
1672 * r -> return parameter pointer to receive buffer
1673 * L -> length of receive buffer
1674 * e -> return parameter number of entries
1675 * h -> return parameter total number of users
1677 if (strcmp("B21",str2) != 0)
1680 /* get list of domain groups SID_DOMAIN_GRP=2 */
1682 ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
1686 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1690 resume_context = SVAL(p,0);
1691 cli_buf_size=SVAL(p+2,0);
1692 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1694 *rdata_len = cli_buf_size;
1695 *rdata = REALLOC(*rdata,*rdata_len);
1699 for(i=resume_context; i<num_entries; i++) {
1700 char* name=group_list[i].nt_name;
1701 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1702 /* truncate the name at 21 chars. */
1703 memcpy(p, name, 21);
1704 DEBUG(10,("adding entry %d group %s\n", i, p));
1707 /* set overflow error */
1708 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1714 *rdata_len = PTR_DIFF(p,*rdata);
1717 *rparam = REALLOC(*rparam,*rparam_len);
1719 SSVAL(*rparam, 0, errflags);
1720 SSVAL(*rparam, 2, 0); /* converter word */
1721 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1722 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1727 /*******************************************************************
1728 get groups that a user is a member of
1729 ******************************************************************/
1730 static BOOL api_NetUserGetGroups(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)
1735 char *str1 = param+2;
1736 char *str2 = skip_string(str1,1);
1737 char *UserName = skip_string(str2,1);
1738 char *p = skip_string(UserName,1);
1739 int uLevel = SVAL(p,0);
1740 const char *level_string;
1742 SAM_ACCOUNT *sampw = NULL;
1750 enum SID_NAME_USE grp_type;
1751 struct passwd *passwd;
1755 *rparam = REALLOC(*rparam,*rparam_len);
1757 /* check it's a supported varient */
1759 if ( strcmp(str1,"zWrLeh") != 0 )
1764 level_string = "B21";
1770 if (strcmp(level_string,str2) != 0)
1773 *rdata_len = mdrcnt + 1024;
1774 *rdata = REALLOC(*rdata,*rdata_len);
1776 SSVAL(*rparam,0,NERR_Success);
1777 SSVAL(*rparam,2,0); /* converter word */
1781 /* Lookup the user information; This should only be one of
1782 our accounts (not remote domains) */
1784 passwd = getpwnam_alloc(UserName);
1789 pdb_init_sam( &sampw );
1791 become_root(); /* ROOT BLOCK */
1793 if ( !pdb_getsampwnam(sampw, UserName) )
1799 result = pdb_enum_group_memberships(pdb_get_username(sampw),
1801 &sids, &gids, &num_groups);
1803 if (!NT_STATUS_IS_OK(result))
1806 for (i=0; i<num_groups; i++) {
1808 if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
1809 pstrcpy(p, grp_name);
1817 *rdata_len = PTR_DIFF(p,*rdata);
1819 SSVAL(*rparam,4,count); /* is this right?? */
1820 SSVAL(*rparam,6,count); /* is this right?? */
1825 unbecome_root(); /* END ROOT BLOCK */
1827 pdb_free_sam( &sampw );
1828 passwd_free(&passwd);
1833 /*******************************************************************
1835 ******************************************************************/
1836 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1837 int mdrcnt,int mprcnt,
1838 char **rdata,char **rparam,
1839 int *rdata_len,int *rparam_len)
1841 SAM_ACCOUNT *pwd=NULL;
1845 int resume_context, cli_buf_size;
1847 char *str1 = param+2;
1848 char *str2 = skip_string(str1,1);
1849 char *p = skip_string(str2,1);
1851 if (strcmp(str1,"WrLeh") != 0)
1854 * W-> resume context (number of users to skip)
1855 * r -> return parameter pointer to receive buffer
1856 * L -> length of receive buffer
1857 * e -> return parameter number of entries
1858 * h -> return parameter total number of users
1861 resume_context = SVAL(p,0);
1862 cli_buf_size=SVAL(p+2,0);
1863 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1866 *rparam = REALLOC(*rparam,*rparam_len);
1868 /* check it's a supported varient */
1869 if (strcmp("B21",str2) != 0)
1872 *rdata_len = cli_buf_size;
1873 *rdata = REALLOC(*rdata,*rdata_len);
1877 /* to get user list enumerations for NetUserEnum in B21 format */
1880 /* Open the passgrp file - not for update. */
1882 if(!pdb_setsampwent(False)) {
1883 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1887 errflags=NERR_Success;
1889 while ( pdb_getsampwent(pwd) ) {
1890 const char *name=pdb_get_username(pwd);
1891 if ((name) && (*(name+strlen(name)-1)!='$')) {
1893 if(count_total>=resume_context) {
1894 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1896 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1900 /* set overflow error */
1901 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1914 *rdata_len = PTR_DIFF(p,*rdata);
1916 SSVAL(*rparam,0,errflags);
1917 SSVAL(*rparam,2,0); /* converter word */
1918 SSVAL(*rparam,4,count_sent); /* is this right?? */
1919 SSVAL(*rparam,6,count_total); /* is this right?? */
1926 /****************************************************************************
1927 get the time of day info
1928 ****************************************************************************/
1929 static BOOL api_NetRemoteTOD(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)
1936 *rparam = REALLOC(*rparam,*rparam_len);
1939 *rdata = REALLOC(*rdata,*rdata_len);
1941 SSVAL(*rparam,0,NERR_Success);
1942 SSVAL(*rparam,2,0); /* converter word */
1948 time_t unixdate = time(NULL);
1950 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1951 by NT in a "net time" operation,
1952 it seems to ignore the one below */
1954 /* the client expects to get localtime, not GMT, in this bit
1955 (I think, this needs testing) */
1956 t = LocalTime(&unixdate);
1958 SIVAL(p,4,0); /* msecs ? */
1959 SCVAL(p,8,t->tm_hour);
1960 SCVAL(p,9,t->tm_min);
1961 SCVAL(p,10,t->tm_sec);
1962 SCVAL(p,11,0); /* hundredths of seconds */
1963 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1964 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1965 SCVAL(p,16,t->tm_mday);
1966 SCVAL(p,17,t->tm_mon + 1);
1967 SSVAL(p,18,1900+t->tm_year);
1968 SCVAL(p,20,t->tm_wday);
1975 /****************************************************************************
1976 Set the user password.
1977 *****************************************************************************/
1979 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1980 int mdrcnt,int mprcnt,
1981 char **rdata,char **rparam,
1982 int *rdata_len,int *rparam_len)
1984 char *p = skip_string(param+2,2);
1986 fstring pass1,pass2;
1988 pull_ascii_fstring(user,p);
1990 p = skip_string(p,1);
1992 memset(pass1,'\0',sizeof(pass1));
1993 memset(pass2,'\0',sizeof(pass2));
1995 memcpy(pass2,p+16,16);
1998 *rparam = REALLOC(*rparam,*rparam_len);
2002 SSVAL(*rparam,0,NERR_badpass);
2003 SSVAL(*rparam,2,0); /* converter word */
2005 DEBUG(3,("Set password for <%s>\n",user));
2008 * Attempt to verify the old password against smbpasswd entries
2009 * Win98 clients send old and new password in plaintext for this call.
2013 auth_serversupplied_info *server_info = NULL;
2014 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2016 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2019 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2020 SSVAL(*rparam,0,NERR_Success);
2024 free_server_info(&server_info);
2026 data_blob_clear_free(&password);
2030 * If the plaintext change failed, attempt
2031 * the old encrypted method. NT will generate this
2032 * after trying the samr method. Note that this
2033 * method is done as a last resort as this
2034 * password change method loses the NT password hash
2035 * and cannot change the UNIX password as no plaintext
2039 if(SVAL(*rparam,0) != NERR_Success) {
2040 SAM_ACCOUNT *hnd = NULL;
2042 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2044 if (change_lanman_password(hnd,(uchar *)pass2)) {
2045 SSVAL(*rparam,0,NERR_Success);
2052 memset((char *)pass1,'\0',sizeof(fstring));
2053 memset((char *)pass2,'\0',sizeof(fstring));
2058 /****************************************************************************
2059 Set the user password (SamOEM version - gets plaintext).
2060 ****************************************************************************/
2062 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2063 int mdrcnt,int mprcnt,
2064 char **rdata,char **rparam,
2065 int *rdata_len,int *rparam_len)
2068 char *p = param + 2;
2070 *rparam = REALLOC(*rparam,*rparam_len);
2074 SSVAL(*rparam,0,NERR_badpass);
2077 * Check the parameter definition is correct.
2080 if(!strequal(param + 2, "zsT")) {
2081 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2084 p = skip_string(p, 1);
2086 if(!strequal(p, "B516B16")) {
2087 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2090 p = skip_string(p,1);
2091 p += pull_ascii_fstring(user,p);
2093 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2096 * Pass the user through the NT -> unix user mapping
2100 (void)map_username(user);
2102 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2103 SSVAL(*rparam,0,NERR_Success);
2109 /****************************************************************************
2112 ****************************************************************************/
2113 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2114 int mdrcnt,int mprcnt,
2115 char **rdata,char **rparam,
2116 int *rdata_len,int *rparam_len)
2118 int function = SVAL(param,0);
2119 char *str1 = param+2;
2120 char *str2 = skip_string(str1,1);
2121 char *p = skip_string(str2,1);
2126 extern struct current_user current_user;
2127 WERROR werr = WERR_OK;
2129 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2132 /* check it's a supported varient */
2133 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2137 *rparam = REALLOC(*rparam,*rparam_len);
2140 if (!print_job_exists(sharename, jobid)) {
2141 errcode = NERR_JobNotFound;
2145 errcode = NERR_notsupported;
2148 case 81: /* delete */
2149 if (print_job_delete(¤t_user, snum, jobid, &werr))
2150 errcode = NERR_Success;
2152 case 82: /* pause */
2153 if (print_job_pause(¤t_user, snum, jobid, &werr))
2154 errcode = NERR_Success;
2156 case 83: /* resume */
2157 if (print_job_resume(¤t_user, snum, jobid, &werr))
2158 errcode = NERR_Success;
2162 if (!W_ERROR_IS_OK(werr))
2163 errcode = W_ERROR_V(werr);
2166 SSVAL(*rparam,0,errcode);
2167 SSVAL(*rparam,2,0); /* converter word */
2172 /****************************************************************************
2173 Purge a print queue - or pause or resume it.
2174 ****************************************************************************/
2175 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2176 int mdrcnt,int mprcnt,
2177 char **rdata,char **rparam,
2178 int *rdata_len,int *rparam_len)
2180 int function = SVAL(param,0);
2181 char *str1 = param+2;
2182 char *str2 = skip_string(str1,1);
2183 char *QueueName = skip_string(str2,1);
2184 int errcode = NERR_notsupported;
2186 WERROR werr = WERR_OK;
2187 extern struct current_user current_user;
2189 /* check it's a supported varient */
2190 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2194 *rparam = REALLOC(*rparam,*rparam_len);
2197 snum = print_queue_snum(QueueName);
2200 errcode = NERR_JobNotFound;
2205 case 74: /* Pause queue */
2206 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2208 case 75: /* Resume queue */
2209 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2211 case 103: /* Purge */
2212 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2216 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2219 SSVAL(*rparam,0,errcode);
2220 SSVAL(*rparam,2,0); /* converter word */
2226 /****************************************************************************
2227 set the property of a print job (undocumented?)
2228 ? function = 0xb -> set name of print job
2229 ? function = 0x6 -> move print job up/down
2230 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2231 or <WWsTP> <WB21BB16B10zWWzDDz>
2232 ****************************************************************************/
2233 static int check_printjob_info(struct pack_desc* desc,
2234 int uLevel, char* id)
2236 desc->subformat = NULL;
2238 case 0: desc->format = "W"; break;
2239 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2240 case 2: desc->format = "WWzWWDDzz"; break;
2241 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2242 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2243 default: return False;
2245 if (strcmp(desc->format,id) != 0) return False;
2249 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2250 int mdrcnt,int mprcnt,
2251 char **rdata,char **rparam,
2252 int *rdata_len,int *rparam_len)
2254 struct pack_desc desc;
2255 char *str1 = param+2;
2256 char *str2 = skip_string(str1,1);
2257 char *p = skip_string(str2,1);
2261 int uLevel = SVAL(p,2);
2262 int function = SVAL(p,4);
2265 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2268 *rparam = REALLOC(*rparam,*rparam_len);
2270 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2271 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2278 /* check it's a supported varient */
2279 if ((strcmp(str1,"WWsTP")) ||
2280 (!check_printjob_info(&desc,uLevel,str2)))
2283 if (!print_job_exists(sharename, jobid)) {
2284 errcode=NERR_JobNotFound;
2288 errcode = NERR_notsupported;
2292 /* change job place in the queue,
2293 data gives the new place */
2294 place = SVAL(data,0);
2295 if (print_job_set_place(snum, jobid, place)) {
2296 errcode=NERR_Success;
2301 /* change print job name, data gives the name */
2302 if (print_job_set_name(snum, jobid, data)) {
2303 errcode=NERR_Success;
2312 SSVALS(*rparam,0,errcode);
2313 SSVAL(*rparam,2,0); /* converter word */
2319 /****************************************************************************
2320 get info about the server
2321 ****************************************************************************/
2322 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2323 int mdrcnt,int mprcnt,
2324 char **rdata,char **rparam,
2325 int *rdata_len,int *rparam_len)
2327 char *str1 = param+2;
2328 char *str2 = skip_string(str1,1);
2329 char *p = skip_string(str2,1);
2330 int uLevel = SVAL(p,0);
2334 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2336 /* check it's a supported varient */
2337 if (!prefix_ok(str1,"WrLh")) return False;
2340 if (strcmp(str2,"B16") != 0) return False;
2344 if (strcmp(str2,"B16BBDz") != 0) return False;
2348 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2353 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2358 if (strcmp(str2,"DN") != 0) return False;
2362 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2365 default: return False;
2368 *rdata_len = mdrcnt;
2369 *rdata = REALLOC(*rdata,*rdata_len);
2372 p2 = p + struct_len;
2374 srvstr_push(NULL, p,local_machine,16,
2375 STR_ASCII|STR_UPPER|STR_TERMINATE);
2380 struct srv_info_struct *servers=NULL;
2383 uint32 servertype= lp_default_server_announce();
2385 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2387 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2388 for (i=0;i<count;i++) {
2389 if (strequal(servers[i].name,local_machine)) {
2390 servertype = servers[i].type;
2391 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2397 SCVAL(p,0,lp_major_announce_version());
2398 SCVAL(p,1,lp_minor_announce_version());
2399 SIVAL(p,2,servertype);
2401 if (mdrcnt == struct_len) {
2404 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2405 standard_sub_conn(conn,comment,sizeof(comment));
2406 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2407 p2 = skip_string(p2,1);
2412 return False; /* not yet implemented */
2415 *rdata_len = PTR_DIFF(p2,*rdata);
2418 *rparam = REALLOC(*rparam,*rparam_len);
2419 SSVAL(*rparam,0,NERR_Success);
2420 SSVAL(*rparam,2,0); /* converter word */
2421 SSVAL(*rparam,4,*rdata_len);
2427 /****************************************************************************
2428 get info about the server
2429 ****************************************************************************/
2430 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2431 int mdrcnt,int mprcnt,
2432 char **rdata,char **rparam,
2433 int *rdata_len,int *rparam_len)
2435 char *str1 = param+2;
2436 char *str2 = skip_string(str1,1);
2437 char *p = skip_string(str2,1);
2439 extern userdom_struct current_user_info;
2440 int level = SVAL(p,0);
2442 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2445 *rparam = REALLOC(*rparam,*rparam_len);
2447 /* check it's a supported varient */
2448 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2451 *rdata_len = mdrcnt + 1024;
2452 *rdata = REALLOC(*rdata,*rdata_len);
2454 SSVAL(*rparam,0,NERR_Success);
2455 SSVAL(*rparam,2,0); /* converter word */
2461 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2462 pstrcpy(p2,local_machine);
2464 p2 = skip_string(p2,1);
2467 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2468 pstrcpy(p2,current_user_info.smb_name);
2469 p2 = skip_string(p2,1);
2472 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2473 pstrcpy(p2,lp_workgroup());
2475 p2 = skip_string(p2,1);
2478 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2479 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2482 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2483 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2484 p2 = skip_string(p2,1);
2487 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2489 p2 = skip_string(p2,1);
2492 *rdata_len = PTR_DIFF(p2,*rdata);
2494 SSVAL(*rparam,4,*rdata_len);
2499 /****************************************************************************
2500 get info about a user
2502 struct user_info_11 {
2503 char usri11_name[21]; 0-20
2505 char *usri11_comment; 22-25
2506 char *usri11_usr_comment; 26-29
2507 unsigned short usri11_priv; 30-31
2508 unsigned long usri11_auth_flags; 32-35
2509 long usri11_password_age; 36-39
2510 char *usri11_homedir; 40-43
2511 char *usri11_parms; 44-47
2512 long usri11_last_logon; 48-51
2513 long usri11_last_logoff; 52-55
2514 unsigned short usri11_bad_pw_count; 56-57
2515 unsigned short usri11_num_logons; 58-59
2516 char *usri11_logon_server; 60-63
2517 unsigned short usri11_country_code; 64-65
2518 char *usri11_workstations; 66-69
2519 unsigned long usri11_max_storage; 70-73
2520 unsigned short usri11_units_per_week; 74-75
2521 unsigned char *usri11_logon_hours; 76-79
2522 unsigned short usri11_code_page; 80-81
2527 usri11_name specifies the user name for which information is retireved
2529 usri11_pad aligns the next data structure element to a word boundary
2531 usri11_comment is a null terminated ASCII comment
2533 usri11_user_comment is a null terminated ASCII comment about the user
2535 usri11_priv specifies the level of the privilege assigned to the user.
2536 The possible values are:
2538 Name Value Description
2539 USER_PRIV_GUEST 0 Guest privilege
2540 USER_PRIV_USER 1 User privilege
2541 USER_PRV_ADMIN 2 Administrator privilege
2543 usri11_auth_flags specifies the account operator privileges. The
2544 possible values are:
2546 Name Value Description
2547 AF_OP_PRINT 0 Print operator
2550 Leach, Naik [Page 28]
2554 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2557 AF_OP_COMM 1 Communications operator
2558 AF_OP_SERVER 2 Server operator
2559 AF_OP_ACCOUNTS 3 Accounts operator
2562 usri11_password_age specifies how many seconds have elapsed since the
2563 password was last changed.
2565 usri11_home_dir points to a null terminated ASCII string that contains
2566 the path name of the user's home directory.
2568 usri11_parms points to a null terminated ASCII string that is set
2569 aside for use by applications.
2571 usri11_last_logon specifies the time when the user last logged on.
2572 This value is stored as the number of seconds elapsed since
2573 00:00:00, January 1, 1970.
2575 usri11_last_logoff specifies the time when the user last logged off.
2576 This value is stored as the number of seconds elapsed since
2577 00:00:00, January 1, 1970. A value of 0 means the last logoff
2580 usri11_bad_pw_count specifies the number of incorrect passwords
2581 entered since the last successful logon.
2583 usri11_log1_num_logons specifies the number of times this user has
2584 logged on. A value of -1 means the number of logons is unknown.
2586 usri11_logon_server points to a null terminated ASCII string that
2587 contains the name of the server to which logon requests are sent.
2588 A null string indicates logon requests should be sent to the
2591 usri11_country_code specifies the country code for the user's language
2594 usri11_workstations points to a null terminated ASCII string that
2595 contains the names of workstations the user may log on from.
2596 There may be up to 8 workstations, with the names separated by
2597 commas. A null strings indicates there are no restrictions.
2599 usri11_max_storage specifies the maximum amount of disk space the user
2600 can occupy. A value of 0xffffffff indicates there are no
2603 usri11_units_per_week specifies the equal number of time units into
2604 which a week is divided. This value must be equal to 168.
2606 usri11_logon_hours points to a 21 byte (168 bits) string that
2607 specifies the time during which the user can log on. Each bit
2608 represents one unique hour in a week. The first bit (bit 0, word
2609 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2613 Leach, Naik [Page 29]
2617 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2620 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2621 are no restrictions.
2623 usri11_code_page specifies the code page for the user's language of
2626 All of the pointers in this data structure need to be treated
2627 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2628 to be ignored. The converter word returned in the parameters section
2629 needs to be subtracted from the lower 16 bits to calculate an offset
2630 into the return buffer where this ASCII string resides.
2632 There is no auxiliary data in the response.
2634 ****************************************************************************/
2636 #define usri11_name 0
2637 #define usri11_pad 21
2638 #define usri11_comment 22
2639 #define usri11_usr_comment 26
2640 #define usri11_full_name 30
2641 #define usri11_priv 34
2642 #define usri11_auth_flags 36
2643 #define usri11_password_age 40
2644 #define usri11_homedir 44
2645 #define usri11_parms 48
2646 #define usri11_last_logon 52
2647 #define usri11_last_logoff 56
2648 #define usri11_bad_pw_count 60
2649 #define usri11_num_logons 62
2650 #define usri11_logon_server 64
2651 #define usri11_country_code 68
2652 #define usri11_workstations 70
2653 #define usri11_max_storage 74
2654 #define usri11_units_per_week 78
2655 #define usri11_logon_hours 80
2656 #define usri11_code_page 84
2657 #define usri11_end 86
2659 #define USER_PRIV_GUEST 0
2660 #define USER_PRIV_USER 1
2661 #define USER_PRIV_ADMIN 2
2663 #define AF_OP_PRINT 0
2664 #define AF_OP_COMM 1
2665 #define AF_OP_SERVER 2
2666 #define AF_OP_ACCOUNTS 3
2669 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2670 int mdrcnt,int mprcnt,
2671 char **rdata,char **rparam,
2672 int *rdata_len,int *rparam_len)
2674 char *str1 = param+2;
2675 char *str2 = skip_string(str1,1);
2676 char *UserName = skip_string(str2,1);
2677 char *p = skip_string(UserName,1);
2678 int uLevel = SVAL(p,0);
2680 const char *level_string;
2682 /* get NIS home of a previously validated user - simeon */
2683 /* With share level security vuid will always be zero.
2684 Don't depend on vuser being non-null !!. JRA */
2685 user_struct *vuser = get_valid_user_struct(vuid);
2687 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2688 vuser->user.unix_name));
2691 *rparam = REALLOC(*rparam,*rparam_len);
2693 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2695 /* check it's a supported variant */
2696 if (strcmp(str1,"zWrLh") != 0) return False;
2699 case 0: level_string = "B21"; break;
2700 case 1: level_string = "B21BB16DWzzWz"; break;
2701 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2702 case 10: level_string = "B21Bzzz"; break;
2703 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2704 default: return False;
2707 if (strcmp(level_string,str2) != 0) return False;
2709 *rdata_len = mdrcnt + 1024;
2710 *rdata = REALLOC(*rdata,*rdata_len);
2712 SSVAL(*rparam,0,NERR_Success);
2713 SSVAL(*rparam,2,0); /* converter word */
2716 p2 = p + usri11_end;
2719 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2723 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2728 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2729 pstrcpy(p2,"Comment");
2730 p2 = skip_string(p2,1);
2732 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2733 pstrcpy(p2,"UserComment");
2734 p2 = skip_string(p2,1);
2736 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2737 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2738 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2739 p2 = skip_string(p2,1);
2742 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2744 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2745 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2746 SIVALS(p,usri11_password_age,-1); /* password age */
2747 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2748 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2749 p2 = skip_string(p2,1);
2750 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2752 p2 = skip_string(p2,1);
2753 SIVAL(p,usri11_last_logon,0); /* last logon */
2754 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2755 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2756 SSVALS(p,usri11_num_logons,-1); /* num logons */
2757 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2758 pstrcpy(p2,"\\\\*");
2759 p2 = skip_string(p2,1);
2760 SSVAL(p,usri11_country_code,0); /* country code */
2762 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2764 p2 = skip_string(p2,1);
2766 SIVALS(p,usri11_max_storage,-1); /* max storage */
2767 SSVAL(p,usri11_units_per_week,168); /* units per week */
2768 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2770 /* a simple way to get logon hours at all times. */
2772 SCVAL(p2,21,0); /* fix zero termination */
2773 p2 = skip_string(p2,1);
2775 SSVAL(p,usri11_code_page,0); /* code page */
2777 if (uLevel == 1 || uLevel == 2)
2779 memset(p+22,' ',16); /* password */
2780 SIVALS(p,38,-1); /* password age */
2782 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2783 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2784 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2785 p2 = skip_string(p2,1);
2786 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2788 SSVAL(p,52,0); /* flags */
2789 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2790 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2791 p2 = skip_string(p2,1);
2794 SIVAL(p,60,0); /* auth_flags */
2795 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2796 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2797 p2 = skip_string(p2,1);
2798 SIVAL(p,68,0); /* urs_comment */
2799 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2801 p2 = skip_string(p2,1);
2802 SIVAL(p,76,0); /* workstations */
2803 SIVAL(p,80,0); /* last_logon */
2804 SIVAL(p,84,0); /* last_logoff */
2805 SIVALS(p,88,-1); /* acct_expires */
2806 SIVALS(p,92,-1); /* max_storage */
2807 SSVAL(p,96,168); /* units_per_week */
2808 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2811 SSVALS(p,102,-1); /* bad_pw_count */
2812 SSVALS(p,104,-1); /* num_logons */
2813 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2814 pstrcpy(p2,"\\\\%L");
2815 standard_sub_conn(conn, p2,0);
2816 p2 = skip_string(p2,1);
2817 SSVAL(p,110,49); /* country_code */
2818 SSVAL(p,112,860); /* code page */
2822 *rdata_len = PTR_DIFF(p2,*rdata);
2824 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2829 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2830 int mdrcnt,int mprcnt,
2831 char **rdata,char **rparam,
2832 int *rdata_len,int *rparam_len)
2834 char *str1 = param+2;
2835 char *str2 = skip_string(str1,1);
2836 char *p = skip_string(str2,1);
2838 struct pack_desc desc;
2840 /* With share level security vuid will always be zero.
2841 Don't depend on vuser being non-null !!. JRA */
2842 user_struct *vuser = get_valid_user_struct(vuid);
2844 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2845 vuser->user.unix_name));
2850 memset((char *)&desc,'\0',sizeof(desc));
2852 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2854 /* check it's a supported varient */
2855 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2856 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2857 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2859 desc.buflen = mdrcnt;
2860 desc.subformat = NULL;
2863 if (init_package(&desc,1,0))
2865 PACKI(&desc,"W",0); /* code */
2866 PACKS(&desc,"B21",name); /* eff. name */
2867 PACKS(&desc,"B",""); /* pad */
2869 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2870 PACKI(&desc,"D",0); /* auth flags XXX */
2871 PACKI(&desc,"W",0); /* num logons */
2872 PACKI(&desc,"W",0); /* bad pw count */
2873 PACKI(&desc,"D",0); /* last logon */
2874 PACKI(&desc,"D",-1); /* last logoff */
2875 PACKI(&desc,"D",-1); /* logoff time */
2876 PACKI(&desc,"D",-1); /* kickoff time */
2877 PACKI(&desc,"D",0); /* password age */
2878 PACKI(&desc,"D",0); /* password can change */
2879 PACKI(&desc,"D",-1); /* password must change */
2882 fstrcpy(mypath,"\\\\");
2883 fstrcat(mypath,local_machine);
2885 PACKS(&desc,"z",mypath); /* computer */
2887 PACKS(&desc,"z",lp_workgroup());/* domain */
2889 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2891 PACKI(&desc,"D",0x00000000); /* reserved */
2894 *rdata_len = desc.usedlen;
2896 *rparam = REALLOC(*rparam,*rparam_len);
2897 SSVALS(*rparam,0,desc.errcode);
2899 SSVAL(*rparam,4,desc.neededlen);
2901 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2906 /****************************************************************************
2907 api_WAccessGetUserPerms
2908 ****************************************************************************/
2909 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2910 int mdrcnt,int mprcnt,
2911 char **rdata,char **rparam,
2912 int *rdata_len,int *rparam_len)
2914 char *str1 = param+2;
2915 char *str2 = skip_string(str1,1);
2916 char *user = skip_string(str2,1);
2917 char *resource = skip_string(user,1);
2919 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2921 /* check it's a supported varient */
2922 if (strcmp(str1,"zzh") != 0) return False;
2923 if (strcmp(str2,"") != 0) return False;
2926 *rparam = REALLOC(*rparam,*rparam_len);
2927 SSVALS(*rparam,0,0); /* errorcode */
2928 SSVAL(*rparam,2,0); /* converter word */
2929 SSVAL(*rparam,4,0x7f); /* permission flags */
2934 /****************************************************************************
2935 api_WPrintJobEnumerate
2936 ****************************************************************************/
2937 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2938 int mdrcnt,int mprcnt,
2939 char **rdata,char **rparam,
2940 int *rdata_len,int *rparam_len)
2942 char *str1 = param+2;
2943 char *str2 = skip_string(str1,1);
2944 char *p = skip_string(str2,1);
2951 struct pack_desc desc;
2952 print_queue_struct *queue=NULL;
2953 print_status_struct status;
2958 memset((char *)&desc,'\0',sizeof(desc));
2959 memset((char *)&status,'\0',sizeof(status));
2961 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2963 /* check it's a supported varient */
2964 if (strcmp(str1,"WWrLh") != 0) return False;
2965 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2967 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2970 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2972 count = print_queue_status(snum,&queue,&status);
2973 for (i = 0; i < count; i++) {
2974 if (queue[i].job == jobid) break;
2978 *rdata = REALLOC(*rdata,mdrcnt);
2980 desc.buflen = mdrcnt;
2983 * Don't return data but need to get correct length
2984 * init_package will return wrong size if buflen=0
2986 desc.buflen = getlen(desc.format);
2987 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2990 if (init_package(&desc,1,0)) {
2992 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2993 *rdata_len = desc.usedlen;
2996 desc.errcode = NERR_JobNotFound;
3002 *rparam = REALLOC(*rparam,*rparam_len);
3003 SSVALS(*rparam,0,desc.errcode);
3005 SSVAL(*rparam,4,desc.neededlen);
3010 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3014 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3015 int mdrcnt,int mprcnt,
3016 char **rdata,char **rparam,
3017 int *rdata_len,int *rparam_len)
3019 char *str1 = param+2;
3020 char *str2 = skip_string(str1,1);
3021 char *p = skip_string(str2,1);
3027 struct pack_desc desc;
3028 print_queue_struct *queue=NULL;
3029 print_status_struct status;
3031 memset((char *)&desc,'\0',sizeof(desc));
3032 memset((char *)&status,'\0',sizeof(status));
3034 p = skip_string(p,1);
3037 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3039 /* check it's a supported variant */
3040 if (strcmp(str1,"zWrLeh") != 0) return False;
3041 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3042 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3044 snum = lp_servicenumber(name);
3045 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3046 int pnum = lp_servicenumber(PRINTERS_NAME);
3048 lp_add_printer(name,pnum);
3049 snum = lp_servicenumber(name);
3053 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3055 count = print_queue_status(snum,&queue,&status);
3056 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3058 desc.buflen = mdrcnt;
3060 if (init_package(&desc,count,0)) {
3062 for (i = 0; i < count; i++) {
3063 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3064 if (desc.errcode == NERR_Success) succnt = i+1;
3068 *rdata_len = desc.usedlen;
3071 *rparam = REALLOC(*rparam,*rparam_len);
3072 SSVALS(*rparam,0,desc.errcode);
3074 SSVAL(*rparam,4,succnt);
3075 SSVAL(*rparam,6,count);
3079 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3083 static int check_printdest_info(struct pack_desc* desc,
3084 int uLevel, char* id)
3086 desc->subformat = NULL;
3088 case 0: desc->format = "B9"; break;
3089 case 1: desc->format = "B9B21WWzW"; break;
3090 case 2: desc->format = "z"; break;
3091 case 3: desc->format = "zzzWWzzzWW"; break;
3092 default: return False;
3094 if (strcmp(desc->format,id) != 0) return False;
3098 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3099 struct pack_desc* desc)
3102 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3103 buf[sizeof(buf)-1] = 0;
3106 PACKS(desc,"B9",buf); /* szName */
3108 PACKS(desc,"B21",""); /* szUserName */
3109 PACKI(desc,"W",0); /* uJobId */
3110 PACKI(desc,"W",0); /* fsStatus */
3111 PACKS(desc,"z",""); /* pszStatus */
3112 PACKI(desc,"W",0); /* time */
3115 if (uLevel == 2 || uLevel == 3) {
3116 PACKS(desc,"z",buf); /* pszPrinterName */
3118 PACKS(desc,"z",""); /* pszUserName */
3119 PACKS(desc,"z",""); /* pszLogAddr */
3120 PACKI(desc,"W",0); /* uJobId */
3121 PACKI(desc,"W",0); /* fsStatus */
3122 PACKS(desc,"z",""); /* pszStatus */
3123 PACKS(desc,"z",""); /* pszComment */
3124 PACKS(desc,"z","NULL"); /* pszDrivers */
3125 PACKI(desc,"W",0); /* time */
3126 PACKI(desc,"W",0); /* pad1 */
3131 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3132 int mdrcnt,int mprcnt,
3133 char **rdata,char **rparam,
3134 int *rdata_len,int *rparam_len)
3136 char *str1 = param+2;
3137 char *str2 = skip_string(str1,1);
3138 char *p = skip_string(str2,1);
3139 char* PrinterName = p;
3141 struct pack_desc desc;
3145 memset((char *)&desc,'\0',sizeof(desc));
3147 p = skip_string(p,1);
3150 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3152 /* check it's a supported varient */
3153 if (strcmp(str1,"zWrLh") != 0) return False;
3154 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3156 snum = lp_servicenumber(PrinterName);
3157 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3158 int pnum = lp_servicenumber(PRINTERS_NAME);
3160 lp_add_printer(PrinterName,pnum);
3161 snum = lp_servicenumber(PrinterName);
3167 desc.errcode = NERR_DestNotFound;
3172 *rdata = REALLOC(*rdata,mdrcnt);
3174 desc.buflen = mdrcnt;
3177 * Don't return data but need to get correct length
3178 * init_package will return wrong size if buflen=0
3180 desc.buflen = getlen(desc.format);
3181 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3183 if (init_package(&desc,1,0)) {
3184 fill_printdest_info(conn,snum,uLevel,&desc);
3186 *rdata_len = desc.usedlen;
3190 *rparam = REALLOC(*rparam,*rparam_len);
3191 SSVALS(*rparam,0,desc.errcode);
3193 SSVAL(*rparam,4,desc.neededlen);
3195 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3200 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3201 int mdrcnt,int mprcnt,
3202 char **rdata,char **rparam,
3203 int *rdata_len,int *rparam_len)
3205 char *str1 = param+2;
3206 char *str2 = skip_string(str1,1);
3207 char *p = skip_string(str2,1);
3211 struct pack_desc desc;
3212 int services = lp_numservices();
3214 memset((char *)&desc,'\0',sizeof(desc));
3218 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3220 /* check it's a supported varient */
3221 if (strcmp(str1,"WrLeh") != 0) return False;
3222 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3225 for (i = 0; i < services; i++)
3226 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3229 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3231 desc.buflen = mdrcnt;
3232 if (init_package(&desc,queuecnt,0)) {
3235 for (i = 0; i < services; i++) {
3236 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3237 fill_printdest_info(conn,i,uLevel,&desc);
3239 if (desc.errcode == NERR_Success) succnt = n;
3244 *rdata_len = desc.usedlen;
3247 *rparam = REALLOC(*rparam,*rparam_len);
3248 SSVALS(*rparam,0,desc.errcode);
3250 SSVAL(*rparam,4,succnt);
3251 SSVAL(*rparam,6,queuecnt);
3253 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3257 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3258 int mdrcnt,int mprcnt,
3259 char **rdata,char **rparam,
3260 int *rdata_len,int *rparam_len)
3262 char *str1 = param+2;
3263 char *str2 = skip_string(str1,1);
3264 char *p = skip_string(str2,1);
3267 struct pack_desc desc;
3269 memset((char *)&desc,'\0',sizeof(desc));
3273 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3275 /* check it's a supported varient */
3276 if (strcmp(str1,"WrLeh") != 0) return False;
3277 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3279 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3281 desc.buflen = mdrcnt;
3282 if (init_package(&desc,1,0)) {
3283 PACKS(&desc,"B41","NULL");
3286 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3288 *rdata_len = desc.usedlen;
3291 *rparam = REALLOC(*rparam,*rparam_len);
3292 SSVALS(*rparam,0,desc.errcode);
3294 SSVAL(*rparam,4,succnt);
3297 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3301 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3302 int mdrcnt,int mprcnt,
3303 char **rdata,char **rparam,
3304 int *rdata_len,int *rparam_len)
3306 char *str1 = param+2;
3307 char *str2 = skip_string(str1,1);
3308 char *p = skip_string(str2,1);
3311 struct pack_desc desc;
3313 memset((char *)&desc,'\0',sizeof(desc));
3317 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3319 /* check it's a supported varient */
3320 if (strcmp(str1,"WrLeh") != 0) return False;
3321 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3323 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3325 desc.buflen = mdrcnt;
3327 if (init_package(&desc,1,0)) {
3328 PACKS(&desc,"B13","lpd");
3331 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3333 *rdata_len = desc.usedlen;
3336 *rparam = REALLOC(*rparam,*rparam_len);
3337 SSVALS(*rparam,0,desc.errcode);
3339 SSVAL(*rparam,4,succnt);
3342 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3346 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3347 int mdrcnt,int mprcnt,
3348 char **rdata,char **rparam,
3349 int *rdata_len,int *rparam_len)
3351 char *str1 = param+2;
3352 char *str2 = skip_string(str1,1);
3353 char *p = skip_string(str2,1);
3356 struct pack_desc desc;
3358 memset((char *)&desc,'\0',sizeof(desc));
3362 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3364 /* check it's a supported varient */
3365 if (strcmp(str1,"WrLeh") != 0) return False;
3366 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3368 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3369 memset((char *)&desc,'\0',sizeof(desc));
3371 desc.buflen = mdrcnt;
3373 if (init_package(&desc,1,0)) {
3374 PACKS(&desc,"B13","lp0");
3377 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3379 *rdata_len = desc.usedlen;
3382 *rparam = REALLOC(*rparam,*rparam_len);
3383 SSVALS(*rparam,0,desc.errcode);
3385 SSVAL(*rparam,4,succnt);
3388 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3393 /****************************************************************************
3395 ****************************************************************************/
3396 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3397 int mdrcnt,int mprcnt,
3398 char **rdata,char **rparam,
3399 int *rdata_len,int *rparam_len)
3402 char *str1 = param+2;
3403 char *str2 = skip_string(str1,1);
3404 char *p = skip_string(str2,1);
3406 struct pack_desc desc;
3407 struct sessionid *session_list;
3408 int i, num_sessions;
3410 memset((char *)&desc,'\0',sizeof(desc));
3414 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3415 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3416 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3418 /* check it's a supported varient */
3419 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3420 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3422 num_sessions = list_sessions(&session_list);
3424 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3425 memset((char *)&desc,'\0',sizeof(desc));
3427 desc.buflen = mdrcnt;
3429 if (!init_package(&desc,num_sessions,0)) {
3433 for(i=0; i<num_sessions; i++) {
3434 PACKS(&desc, "z", session_list[i].remote_machine);
3435 PACKS(&desc, "z", session_list[i].username);
3436 PACKI(&desc, "W", 1); /* num conns */
3437 PACKI(&desc, "W", 0); /* num opens */
3438 PACKI(&desc, "W", 1); /* num users */
3439 PACKI(&desc, "D", 0); /* session time */
3440 PACKI(&desc, "D", 0); /* idle time */
3441 PACKI(&desc, "D", 0); /* flags */
3442 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3445 *rdata_len = desc.usedlen;
3448 *rparam = REALLOC(*rparam,*rparam_len);
3449 SSVALS(*rparam,0,desc.errcode);
3450 SSVAL(*rparam,2,0); /* converter */
3451 SSVAL(*rparam,4,num_sessions); /* count */
3453 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3458 /****************************************************************************
3459 The buffer was too small
3460 ****************************************************************************/
3462 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3463 int mdrcnt,int mprcnt,
3464 char **rdata,char **rparam,
3465 int *rdata_len,int *rparam_len)
3467 *rparam_len = MIN(*rparam_len,mprcnt);
3468 *rparam = REALLOC(*rparam,*rparam_len);
3472 SSVAL(*rparam,0,NERR_BufTooSmall);
3474 DEBUG(3,("Supplied buffer too small in API command\n"));
3480 /****************************************************************************
3481 The request is not supported
3482 ****************************************************************************/
3484 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3485 int mdrcnt,int mprcnt,
3486 char **rdata,char **rparam,
3487 int *rdata_len,int *rparam_len)
3490 *rparam = REALLOC(*rparam,*rparam_len);
3494 SSVAL(*rparam,0,NERR_notsupported);
3495 SSVAL(*rparam,2,0); /* converter word */
3497 DEBUG(3,("Unsupported API command\n"));
3509 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3510 int,int,char **,char **,int *,int *);
3511 BOOL auth_user; /* Deny anonymous access? */
3512 } api_commands[] = {
3513 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3514 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3515 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3516 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3517 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3518 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3519 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3520 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3521 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3522 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3523 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3524 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3525 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3526 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3527 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3528 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3529 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3530 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3531 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3532 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3533 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3534 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3535 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3536 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3537 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3538 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3539 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3540 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3541 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3542 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3543 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3544 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3545 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3546 {NULL, -1, api_Unsupported}};
3548 /* The following RAP calls are not implemented by Samba:
3550 RAP_WFileEnum2 - anon not OK
3553 /****************************************************************************
3554 Handle remote api calls
3555 ****************************************************************************/
3557 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3558 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3562 char *rparam = NULL;
3569 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3573 api_command = SVAL(params,0);
3575 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3578 skip_string(params+2,1),
3579 tdscnt,tpscnt,mdrcnt,mprcnt));
3581 for (i=0;api_commands[i].name;i++) {
3582 if (api_commands[i].id == api_command && api_commands[i].fn) {
3583 DEBUG(3,("Doing %s\n",api_commands[i].name));
3588 /* Check whether this api call can be done anonymously */
3590 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3591 user_struct *user = get_valid_user_struct(vuid);
3593 if (!user || user->guest)
3594 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3597 rdata = (char *)malloc(1024);
3599 memset(rdata,'\0',1024);
3601 rparam = (char *)malloc(1024);
3603 memset(rparam,'\0',1024);
3605 if(!rdata || !rparam) {
3606 DEBUG(0,("api_reply: malloc fail !\n"));
3610 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3611 &rdata,&rparam,&rdata_len,&rparam_len);
3614 if (rdata_len > mdrcnt ||
3615 rparam_len > mprcnt) {
3616 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3617 &rdata,&rparam,&rdata_len,&rparam_len);
3620 /* if we get False back then it's actually unsupported */
3622 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3623 &rdata,&rparam,&rdata_len,&rparam_len);
3625 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);