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(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, "\\\\");
552 fstrcat(location, get_called_name());
553 fstrcat(location, "\\print$\\WIN40\\0");
554 PACKS(desc,"z", location); /* share to retrieve files */
556 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
557 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
558 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
560 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
561 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
562 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
563 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
564 DEBUG(3,("Driver Location: %s:\n",location));
565 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
566 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
567 PACKI(desc,"N",count); /* number of files to copy */
569 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
571 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
572 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
573 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
578 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
581 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
583 desc->errcode=NERR_Success;
587 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
588 desc->errcode=NERR_notsupported;
592 free_a_printer( &printer, 2 );
595 free_a_printer_driver( driver, 3 );
599 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
600 struct pack_desc* desc,
601 int count, print_queue_struct* queue,
602 print_status_struct* status)
607 PACKS(desc,"B13",SERVICE(snum));
612 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
615 PACKI(desc,"K",printq_status(status->status));
619 if (uLevel == 1 || uLevel == 2) {
620 PACKS(desc,"B",""); /* alignment */
621 PACKI(desc,"W",5); /* priority */
622 PACKI(desc,"W",0); /* start time */
623 PACKI(desc,"W",0); /* until time */
624 PACKS(desc,"z",""); /* pSepFile */
625 PACKS(desc,"z","lpd"); /* pPrProc */
626 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
627 PACKS(desc,"z",""); /* pParms */
629 PACKS(desc,"z","UNKNOWN PRINTER");
630 PACKI(desc,"W",LPSTAT_ERROR);
632 else if (!status || !status->message[0]) {
633 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
634 PACKI(desc,"W",LPSTAT_OK); /* status */
636 PACKS(desc,"z",status->message);
637 PACKI(desc,"W",printq_status(status->status)); /* status */
639 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
642 if (uLevel == 3 || uLevel == 4) {
645 PACKI(desc,"W",5); /* uPriority */
646 PACKI(desc,"W",0); /* uStarttime */
647 PACKI(desc,"W",0); /* uUntiltime */
648 PACKI(desc,"W",5); /* pad1 */
649 PACKS(desc,"z",""); /* pszSepFile */
650 PACKS(desc,"z","WinPrint"); /* pszPrProc */
651 PACKS(desc,"z",NULL); /* pszParms */
652 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
653 /* "don't ask" that it's done this way to fix corrupted
654 Win9X/ME printer comments. */
656 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
658 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
660 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
661 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
662 get_driver_name(snum,drivername);
663 PACKS(desc,"z",drivername); /* pszDriverName */
664 PackDriverData(desc); /* pDriverData */
667 if (uLevel == 2 || uLevel == 4) {
669 for (i=0;i<count;i++)
670 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
674 fill_printq_info_52( conn, snum, desc, count );
677 /* This function returns the number of files for a given driver */
678 static int get_printerdrivernumber(int snum)
681 NT_PRINTER_DRIVER_INFO_LEVEL driver;
682 NT_PRINTER_INFO_LEVEL *printer = NULL;
686 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
687 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
688 lp_servicename(snum)));
692 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
695 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
696 printer->info_2->drivername));
700 /* count the number of files */
701 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
706 free_a_printer( &printer, 2 );
709 free_a_printer_driver( driver, 3 );
714 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
715 uint16 vuid, char *param,char *data,
716 int mdrcnt,int mprcnt,
717 char **rdata,char **rparam,
718 int *rdata_len,int *rparam_len)
720 char *str1 = param+2;
721 char *str2 = skip_string(str1,1);
722 char *p = skip_string(str2,1);
728 struct pack_desc desc;
729 print_queue_struct *queue=NULL;
730 print_status_struct status;
733 memset((char *)&status,'\0',sizeof(status));
734 memset((char *)&desc,'\0',sizeof(desc));
736 p = skip_string(p,1);
740 /* remove any trailing username */
741 if ((p = strchr_m(QueueName,'%')))
744 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
746 /* check it's a supported varient */
747 if (!prefix_ok(str1,"zWrLh"))
749 if (!check_printq_info(&desc,uLevel,str2,str3)) {
751 * Patch from Scott Moomaw <scott@bridgewater.edu>
752 * to return the 'invalid info level' error if an
753 * unknown level was requested.
757 *rparam = REALLOC(*rparam,*rparam_len);
758 SSVALS(*rparam,0,ERRunknownlevel);
764 snum = lp_servicenumber(QueueName);
765 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
766 int pnum = lp_servicenumber(PRINTERS_NAME);
768 lp_add_printer(QueueName,pnum);
769 snum = lp_servicenumber(QueueName);
773 if (snum < 0 || !VALID_SNUM(snum))
777 count = get_printerdrivernumber(snum);
778 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
780 count = print_queue_status(snum, &queue,&status);
784 *rdata = REALLOC(*rdata,mdrcnt);
786 desc.buflen = mdrcnt;
789 * Don't return data but need to get correct length
790 * init_package will return wrong size if buflen=0
792 desc.buflen = getlen(desc.format);
793 desc.base = tmpdata = (char *) malloc (desc.buflen);
796 if (init_package(&desc,1,count)) {
797 desc.subcount = count;
798 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
801 *rdata_len = desc.usedlen;
804 * We must set the return code to ERRbuftoosmall
805 * in order to support lanman style printing with Win NT/2k
808 if (!mdrcnt && lp_disable_spoolss())
809 desc.errcode = ERRbuftoosmall;
811 *rdata_len = desc.usedlen;
813 *rparam = REALLOC(*rparam,*rparam_len);
814 SSVALS(*rparam,0,desc.errcode);
816 SSVAL(*rparam,4,desc.neededlen);
818 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
826 /****************************************************************************
827 View list of all print jobs on all queues.
828 ****************************************************************************/
830 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
831 int mdrcnt, int mprcnt,
832 char **rdata, char** rparam,
833 int *rdata_len, int *rparam_len)
835 char *param_format = param+2;
836 char *output_format1 = skip_string(param_format,1);
837 char *p = skip_string(output_format1,1);
838 int uLevel = SVAL(p,0);
839 char *output_format2 = p + 4;
840 int services = lp_numservices();
842 struct pack_desc desc;
843 print_queue_struct **queue = NULL;
844 print_status_struct *status = NULL;
845 int* subcntarr = NULL;
846 int queuecnt, subcnt=0, succnt=0;
848 memset((char *)&desc,'\0',sizeof(desc));
850 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
852 if (!prefix_ok(param_format,"WrLeh")) return False;
853 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
855 * Patch from Scott Moomaw <scott@bridgewater.edu>
856 * to return the 'invalid info level' error if an
857 * unknown level was requested.
861 *rparam = REALLOC(*rparam,*rparam_len);
862 SSVALS(*rparam,0,ERRunknownlevel);
869 for (i = 0; i < services; i++)
870 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
873 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
874 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
877 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
878 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
879 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
882 memset(status,0,queuecnt*sizeof(print_status_struct));
883 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
884 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
889 for (i = 0; i < services; i++)
890 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
891 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
892 subcnt += subcntarr[n];
896 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
898 desc.buflen = mdrcnt;
900 if (init_package(&desc,queuecnt,subcnt)) {
903 for (i = 0; i < services; i++)
904 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
905 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
907 if (desc.errcode == NERR_Success) succnt = n;
911 SAFE_FREE(subcntarr);
913 *rdata_len = desc.usedlen;
915 *rparam = REALLOC(*rparam,*rparam_len);
916 SSVALS(*rparam,0,desc.errcode);
918 SSVAL(*rparam,4,succnt);
919 SSVAL(*rparam,6,queuecnt);
921 for (i = 0; i < queuecnt; i++) {
922 if (queue) SAFE_FREE(queue[i]);
931 /****************************************************************************
932 get info level for a server list query
933 ****************************************************************************/
934 static BOOL check_server_info(int uLevel, char* id)
938 if (strcmp(id,"B16") != 0) return False;
941 if (strcmp(id,"B16BBDz") != 0) return False;
949 struct srv_info_struct
959 /*******************************************************************
960 get server info lists from the files saved by nmbd. Return the
962 ******************************************************************/
963 static int get_server_info(uint32 servertype,
964 struct srv_info_struct **servers,
970 BOOL local_list_only;
973 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
975 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
979 /* request for everything is code for request all servers */
980 if (servertype == SV_TYPE_ALL)
981 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
983 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
985 DEBUG(4,("Servertype search: %8x\n",servertype));
987 for (i=0;lines[i];i++) {
989 struct srv_info_struct *s;
990 const char *ptr = lines[i];
995 if (count == alloced) {
996 struct srv_info_struct *ts;
999 ts = (struct srv_info_struct *)
1000 Realloc(*servers,sizeof(**servers)*alloced);
1002 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1006 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1008 s = &(*servers)[count];
1010 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1011 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1012 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1013 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1014 /* this allows us to cope with an old nmbd */
1015 fstrcpy(s->domain,lp_workgroup());
1018 if (sscanf(stype,"%X",&s->type) != 1) {
1019 DEBUG(4,("r:host file "));
1023 /* Filter the servers/domains we return based on what was asked for. */
1025 /* Check to see if we are being asked for a local list only. */
1026 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1027 DEBUG(4,("r: local list only"));
1031 /* doesn't match up: don't want it */
1032 if (!(servertype & s->type)) {
1033 DEBUG(4,("r:serv type "));
1037 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1038 (s->type & SV_TYPE_DOMAIN_ENUM))
1040 DEBUG(4,("s: dom mismatch "));
1044 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1049 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1050 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1054 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1055 s->name, s->type, s->comment, s->domain));
1057 s->server_added = True;
1062 DEBUG(4,("%20s %8x %25s %15s\n",
1063 s->name, s->type, s->comment, s->domain));
1067 file_lines_free(lines);
1072 /*******************************************************************
1073 fill in a server info structure
1074 ******************************************************************/
1075 static int fill_srv_info(struct srv_info_struct *service,
1076 int uLevel, char **buf, int *buflen,
1077 char **stringbuf, int *stringspace, char *baseaddr)
1086 case 0: struct_len = 16; break;
1087 case 1: struct_len = 26; break;
1097 len = strlen(service->comment)+1;
1101 if (buflen) *buflen = struct_len;
1102 if (stringspace) *stringspace = len;
1103 return struct_len + len;
1108 if (*buflen < struct_len) return -1;
1116 p2 = p + struct_len;
1117 l2 = *buflen - struct_len;
1119 if (!baseaddr) baseaddr = p;
1124 push_ascii(p,service->name, 15, STR_TERMINATE);
1128 push_ascii(p,service->name,15, STR_TERMINATE);
1129 SIVAL(p,18,service->type);
1130 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1131 len += CopyAndAdvance(&p2,service->comment,&l2);
1137 *buf = p + struct_len;
1138 *buflen -= struct_len;
1151 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1153 return(strcmp(s1->name,s2->name));
1156 /****************************************************************************
1157 view list of servers available (or possibly domains). The info is
1158 extracted from lists saved by nmbd on the local host
1159 ****************************************************************************/
1160 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1161 int mdrcnt, int mprcnt, char **rdata,
1162 char **rparam, int *rdata_len, int *rparam_len)
1164 char *str1 = param+2;
1165 char *str2 = skip_string(str1,1);
1166 char *p = skip_string(str2,1);
1167 int uLevel = SVAL(p,0);
1168 int buf_len = SVAL(p,2);
1169 uint32 servertype = IVAL(p,4);
1171 int data_len, fixed_len, string_len;
1172 int f_len = 0, s_len = 0;
1173 struct srv_info_struct *servers=NULL;
1174 int counted=0,total=0;
1177 BOOL domain_request;
1180 /* If someone sets all the bits they don't really mean to set
1181 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1184 if (servertype == SV_TYPE_ALL)
1185 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1187 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1188 any other bit (they may just set this bit on it's own) they
1189 want all the locally seen servers. However this bit can be
1190 set on its own so set the requested servers to be
1191 ALL - DOMAIN_ENUM. */
1193 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1194 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1196 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1197 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1201 if (!prefix_ok(str1,"WrLehD")) return False;
1202 if (!check_server_info(uLevel,str2)) return False;
1204 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1205 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1206 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1208 if (strcmp(str1, "WrLehDz") == 0) {
1209 pull_ascii_fstring(domain, p);
1211 fstrcpy(domain, lp_workgroup());
1214 if (lp_browse_list())
1215 total = get_server_info(servertype,&servers,domain);
1217 data_len = fixed_len = string_len = 0;
1221 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1224 char *lastname=NULL;
1226 for (i=0;i<total;i++)
1228 struct srv_info_struct *s = &servers[i];
1229 if (lastname && strequal(lastname,s->name)) continue;
1231 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1232 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1233 s->name, s->type, s->comment, s->domain));
1235 if (data_len <= buf_len) {
1238 string_len += s_len;
1245 *rdata_len = fixed_len + string_len;
1246 *rdata = REALLOC(*rdata,*rdata_len);
1247 memset(*rdata,'\0',*rdata_len);
1249 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1255 char *lastname=NULL;
1256 int count2 = counted;
1257 for (i = 0; i < total && count2;i++)
1259 struct srv_info_struct *s = &servers[i];
1260 if (lastname && strequal(lastname,s->name)) continue;
1262 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1263 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1264 s->name, s->type, s->comment, s->domain));
1270 *rparam = REALLOC(*rparam,*rparam_len);
1271 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1273 SSVAL(*rparam,4,counted);
1274 SSVAL(*rparam,6,counted+missed);
1278 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1279 domain,uLevel,counted,counted+missed));
1284 /****************************************************************************
1285 command 0x34 - suspected of being a "Lookup Names" stub api
1286 ****************************************************************************/
1287 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1288 int mdrcnt, int mprcnt, char **rdata,
1289 char **rparam, int *rdata_len, int *rparam_len)
1291 char *str1 = param+2;
1292 char *str2 = skip_string(str1,1);
1293 char *p = skip_string(str2,1);
1294 int uLevel = SVAL(p,0);
1295 int buf_len = SVAL(p,2);
1299 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1300 str1, str2, p, uLevel, buf_len));
1302 if (!prefix_ok(str1,"zWrLeh")) return False;
1307 *rparam = REALLOC(*rparam,*rparam_len);
1309 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1311 SSVAL(*rparam,4,counted);
1312 SSVAL(*rparam,6,counted+missed);
1317 /****************************************************************************
1318 get info about a share
1319 ****************************************************************************/
1320 static BOOL check_share_info(int uLevel, char* id)
1324 if (strcmp(id,"B13") != 0) return False;
1327 if (strcmp(id,"B13BWz") != 0) return False;
1330 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1333 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1335 default: return False;
1340 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1341 char** buf, int* buflen,
1342 char** stringbuf, int* stringspace, char* baseaddr)
1351 case 0: struct_len = 13; break;
1352 case 1: struct_len = 20; break;
1353 case 2: struct_len = 40; break;
1354 case 91: struct_len = 68; break;
1362 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1363 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1364 if (buflen) *buflen = struct_len;
1365 if (stringspace) *stringspace = len;
1366 return struct_len + len;
1371 if ((*buflen) < struct_len) return -1;
1379 p2 = p + struct_len;
1380 l2 = (*buflen) - struct_len;
1382 if (!baseaddr) baseaddr = p;
1384 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1390 type = STYPE_DISKTREE;
1391 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1392 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1393 SSVAL(p,14,type); /* device type */
1394 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1395 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1400 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1401 SSVALS(p,22,-1); /* max uses */
1402 SSVAL(p,24,1); /* current uses */
1403 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1404 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1405 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1410 memset(p+40,0,SHPWLEN+2);
1422 (*buf) = p + struct_len;
1423 (*buflen) -= struct_len;
1425 (*stringspace) = l2;
1435 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1436 int mdrcnt,int mprcnt,
1437 char **rdata,char **rparam,
1438 int *rdata_len,int *rparam_len)
1440 char *str1 = param+2;
1441 char *str2 = skip_string(str1,1);
1442 char *netname = skip_string(str2,1);
1443 char *p = skip_string(netname,1);
1444 int uLevel = SVAL(p,0);
1445 int snum = find_service(netname);
1447 if (snum < 0) return False;
1449 /* check it's a supported varient */
1450 if (!prefix_ok(str1,"zWrLh")) return False;
1451 if (!check_share_info(uLevel,str2)) return False;
1453 *rdata = REALLOC(*rdata,mdrcnt);
1455 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1456 if (*rdata_len < 0) return False;
1459 *rparam = REALLOC(*rparam,*rparam_len);
1460 SSVAL(*rparam,0,NERR_Success);
1461 SSVAL(*rparam,2,0); /* converter word */
1462 SSVAL(*rparam,4,*rdata_len);
1467 /****************************************************************************
1468 view list of shares available
1469 ****************************************************************************/
1470 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1471 int mdrcnt,int mprcnt,
1472 char **rdata,char **rparam,
1473 int *rdata_len,int *rparam_len)
1475 char *str1 = param+2;
1476 char *str2 = skip_string(str1,1);
1477 char *p = skip_string(str2,1);
1478 int uLevel = SVAL(p,0);
1479 int buf_len = SVAL(p,2);
1481 int count=lp_numservices();
1482 int total=0,counted=0;
1483 BOOL missed = False;
1485 int data_len, fixed_len, string_len;
1486 int f_len = 0, s_len = 0;
1488 if (!prefix_ok(str1,"WrLeh")) return False;
1489 if (!check_share_info(uLevel,str2)) return False;
1491 data_len = fixed_len = string_len = 0;
1492 for (i=0;i<count;i++)
1493 if (lp_browseable(i) && lp_snum_ok(i))
1496 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1497 if (data_len <= buf_len)
1501 string_len += s_len;
1506 *rdata_len = fixed_len + string_len;
1507 *rdata = REALLOC(*rdata,*rdata_len);
1508 memset(*rdata,0,*rdata_len);
1510 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1514 for (i = 0; i < count;i++)
1515 if (lp_browseable(i) && lp_snum_ok(i))
1516 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1520 *rparam = REALLOC(*rparam,*rparam_len);
1521 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1523 SSVAL(*rparam,4,counted);
1524 SSVAL(*rparam,6,total);
1526 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1527 counted,total,uLevel,
1528 buf_len,*rdata_len,mdrcnt));
1532 /****************************************************************************
1534 ****************************************************************************/
1535 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1536 int mdrcnt,int mprcnt,
1537 char **rdata,char **rparam,
1538 int *rdata_len,int *rparam_len)
1540 char *str1 = param+2;
1541 char *str2 = skip_string(str1,1);
1542 char *p = skip_string(str2,1);
1543 int uLevel = SVAL(p,0);
1547 char *command, *cmdname;
1548 unsigned int offset;
1552 /* check it's a supported varient */
1553 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1554 if (!check_share_info(uLevel,str2)) return False;
1555 if (uLevel != 2) return False;
1557 pull_ascii_fstring(sharename,data);
1558 snum = find_service(sharename);
1559 if (snum >= 0) { /* already exists */
1564 /* only support disk share adds */
1565 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1567 offset = IVAL(data, 16);
1568 if (offset >= mdrcnt) {
1569 res = ERRinvalidparam;
1572 pull_ascii_fstring(comment, offset? (data+offset) : "");
1574 offset = IVAL(data, 26);
1575 if (offset >= mdrcnt) {
1576 res = ERRinvalidparam;
1579 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1581 string_replace(sharename, '"', ' ');
1582 string_replace(pathname, '"', ' ');
1583 string_replace(comment, '"', ' ');
1585 cmdname = lp_add_share_cmd();
1587 if (!cmdname || *cmdname == '\0') return False;
1589 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1590 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1593 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1594 if ((res = smbrun(command, NULL)) != 0) {
1595 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1601 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1603 } else return False;
1606 *rparam = REALLOC(*rparam,*rparam_len);
1607 SSVAL(*rparam,0,NERR_Success);
1608 SSVAL(*rparam,2,0); /* converter word */
1609 SSVAL(*rparam,4,*rdata_len);
1616 *rparam = REALLOC(*rparam,*rparam_len);
1618 SSVAL(*rparam,0,res);
1624 /****************************************************************************
1625 view list of groups available
1626 ****************************************************************************/
1627 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1628 int mdrcnt,int mprcnt,
1629 char **rdata,char **rparam,
1630 int *rdata_len,int *rparam_len)
1634 int resume_context, cli_buf_size;
1635 char *str1 = param+2;
1636 char *str2 = skip_string(str1,1);
1637 char *p = skip_string(str2,1);
1640 GROUP_MAP *group_list;
1643 if (strcmp(str1,"WrLeh") != 0)
1647 * W-> resume context (number of users to skip)
1648 * r -> return parameter pointer to receive buffer
1649 * L -> length of receive buffer
1650 * e -> return parameter number of entries
1651 * h -> return parameter total number of users
1653 if (strcmp("B21",str2) != 0)
1656 /* get list of domain groups SID_DOMAIN_GRP=2 */
1658 ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
1662 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1666 resume_context = SVAL(p,0);
1667 cli_buf_size=SVAL(p+2,0);
1668 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1670 *rdata_len = cli_buf_size;
1671 *rdata = REALLOC(*rdata,*rdata_len);
1675 for(i=resume_context; i<num_entries; i++) {
1676 char* name=group_list[i].nt_name;
1677 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1678 /* truncate the name at 21 chars. */
1679 memcpy(p, name, 21);
1680 DEBUG(10,("adding entry %d group %s\n", i, p));
1683 /* set overflow error */
1684 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1690 *rdata_len = PTR_DIFF(p,*rdata);
1693 *rparam = REALLOC(*rparam,*rparam_len);
1695 SSVAL(*rparam, 0, errflags);
1696 SSVAL(*rparam, 2, 0); /* converter word */
1697 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1698 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1703 /*******************************************************************
1704 get groups that a user is a member of
1705 ******************************************************************/
1706 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1707 int mdrcnt,int mprcnt,
1708 char **rdata,char **rparam,
1709 int *rdata_len,int *rparam_len)
1711 char *str1 = param+2;
1712 char *str2 = skip_string(str1,1);
1713 char *UserName = skip_string(str2,1);
1714 char *p = skip_string(UserName,1);
1715 int uLevel = SVAL(p,0);
1716 const char *level_string;
1718 SAM_ACCOUNT *sampw = NULL;
1720 DOM_GID *gids = NULL;
1725 enum SID_NAME_USE grp_type;
1726 DOM_SID sid, dom_sid;
1729 *rparam = REALLOC(*rparam,*rparam_len);
1731 /* check it's a supported varient */
1733 if ( strcmp(str1,"zWrLeh") != 0 )
1738 level_string = "B21";
1744 if (strcmp(level_string,str2) != 0)
1747 *rdata_len = mdrcnt + 1024;
1748 *rdata = REALLOC(*rdata,*rdata_len);
1750 SSVAL(*rparam,0,NERR_Success);
1751 SSVAL(*rparam,2,0); /* converter word */
1755 /* Lookup the user information; This should only be one of
1756 our accounts (not remote domains) */
1758 pdb_init_sam( &sampw );
1760 become_root(); /* ROOT BLOCK */
1762 if ( !pdb_getsampwnam(sampw, UserName) )
1765 /* this next set of code is horribly inefficient, but since
1766 it is rarely called, I'm going to leave it like this since
1767 it easier to follow --jerry */
1769 /* get the list of group SIDs */
1771 if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
1772 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1776 /* convert to names (we don't support universal groups so the domain
1777 can only be ours) */
1779 sid_copy( &dom_sid, get_global_sam_sid() );
1780 for (i=0; i<num_groups; i++) {
1782 /* make the DOM_GID into a DOM_SID and then lookup
1785 sid_copy( &sid, &dom_sid );
1786 sid_append_rid( &sid, gids[i].g_rid );
1788 if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
1789 pstrcpy(p, grp_name);
1795 *rdata_len = PTR_DIFF(p,*rdata);
1797 SSVAL(*rparam,4,count); /* is this right?? */
1798 SSVAL(*rparam,6,count); /* is this right?? */
1803 unbecome_root(); /* END ROOT BLOCK */
1805 pdb_free_sam( &sampw );
1810 /*******************************************************************
1812 ******************************************************************/
1813 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1814 int mdrcnt,int mprcnt,
1815 char **rdata,char **rparam,
1816 int *rdata_len,int *rparam_len)
1818 SAM_ACCOUNT *pwd=NULL;
1822 int resume_context, cli_buf_size;
1824 char *str1 = param+2;
1825 char *str2 = skip_string(str1,1);
1826 char *p = skip_string(str2,1);
1828 if (strcmp(str1,"WrLeh") != 0)
1831 * W-> resume context (number of users to skip)
1832 * r -> return parameter pointer to receive buffer
1833 * L -> length of receive buffer
1834 * e -> return parameter number of entries
1835 * h -> return parameter total number of users
1838 resume_context = SVAL(p,0);
1839 cli_buf_size=SVAL(p+2,0);
1840 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1843 *rparam = REALLOC(*rparam,*rparam_len);
1845 /* check it's a supported varient */
1846 if (strcmp("B21",str2) != 0)
1849 *rdata_len = cli_buf_size;
1850 *rdata = REALLOC(*rdata,*rdata_len);
1854 /* to get user list enumerations for NetUserEnum in B21 format */
1857 /* Open the passgrp file - not for update. */
1859 if(!pdb_setsampwent(False)) {
1860 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1864 errflags=NERR_Success;
1866 while ( pdb_getsampwent(pwd) ) {
1867 const char *name=pdb_get_username(pwd);
1868 if ((name) && (*(name+strlen(name)-1)!='$')) {
1870 if(count_total>=resume_context) {
1871 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1873 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1877 /* set overflow error */
1878 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1891 *rdata_len = PTR_DIFF(p,*rdata);
1893 SSVAL(*rparam,0,errflags);
1894 SSVAL(*rparam,2,0); /* converter word */
1895 SSVAL(*rparam,4,count_sent); /* is this right?? */
1896 SSVAL(*rparam,6,count_total); /* is this right?? */
1903 /****************************************************************************
1904 get the time of day info
1905 ****************************************************************************/
1906 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1907 int mdrcnt,int mprcnt,
1908 char **rdata,char **rparam,
1909 int *rdata_len,int *rparam_len)
1913 *rparam = REALLOC(*rparam,*rparam_len);
1916 *rdata = REALLOC(*rdata,*rdata_len);
1918 SSVAL(*rparam,0,NERR_Success);
1919 SSVAL(*rparam,2,0); /* converter word */
1925 time_t unixdate = time(NULL);
1927 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1928 by NT in a "net time" operation,
1929 it seems to ignore the one below */
1931 /* the client expects to get localtime, not GMT, in this bit
1932 (I think, this needs testing) */
1933 t = LocalTime(&unixdate);
1935 SIVAL(p,4,0); /* msecs ? */
1936 SCVAL(p,8,t->tm_hour);
1937 SCVAL(p,9,t->tm_min);
1938 SCVAL(p,10,t->tm_sec);
1939 SCVAL(p,11,0); /* hundredths of seconds */
1940 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1941 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1942 SCVAL(p,16,t->tm_mday);
1943 SCVAL(p,17,t->tm_mon + 1);
1944 SSVAL(p,18,1900+t->tm_year);
1945 SCVAL(p,20,t->tm_wday);
1952 /****************************************************************************
1953 Set the user password.
1954 *****************************************************************************/
1956 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1957 int mdrcnt,int mprcnt,
1958 char **rdata,char **rparam,
1959 int *rdata_len,int *rparam_len)
1961 char *p = skip_string(param+2,2);
1963 fstring pass1,pass2;
1965 pull_ascii_fstring(user,p);
1967 p = skip_string(p,1);
1969 memset(pass1,'\0',sizeof(pass1));
1970 memset(pass2,'\0',sizeof(pass2));
1972 memcpy(pass2,p+16,16);
1975 *rparam = REALLOC(*rparam,*rparam_len);
1979 SSVAL(*rparam,0,NERR_badpass);
1980 SSVAL(*rparam,2,0); /* converter word */
1982 DEBUG(3,("Set password for <%s>\n",user));
1985 * Attempt to verify the old password against smbpasswd entries
1986 * Win98 clients send old and new password in plaintext for this call.
1990 auth_serversupplied_info *server_info = NULL;
1991 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
1993 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1996 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
1997 SSVAL(*rparam,0,NERR_Success);
2001 free_server_info(&server_info);
2003 data_blob_clear_free(&password);
2007 * If the plaintext change failed, attempt
2008 * the old encrypted method. NT will generate this
2009 * after trying the samr method. Note that this
2010 * method is done as a last resort as this
2011 * password change method loses the NT password hash
2012 * and cannot change the UNIX password as no plaintext
2016 if(SVAL(*rparam,0) != NERR_Success) {
2017 SAM_ACCOUNT *hnd = NULL;
2019 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2021 if (change_lanman_password(hnd,(uchar *)pass2)) {
2022 SSVAL(*rparam,0,NERR_Success);
2029 memset((char *)pass1,'\0',sizeof(fstring));
2030 memset((char *)pass2,'\0',sizeof(fstring));
2035 /****************************************************************************
2036 Set the user password (SamOEM version - gets plaintext).
2037 ****************************************************************************/
2039 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2040 int mdrcnt,int mprcnt,
2041 char **rdata,char **rparam,
2042 int *rdata_len,int *rparam_len)
2045 char *p = param + 2;
2047 *rparam = REALLOC(*rparam,*rparam_len);
2051 SSVAL(*rparam,0,NERR_badpass);
2054 * Check the parameter definition is correct.
2057 if(!strequal(param + 2, "zsT")) {
2058 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2061 p = skip_string(p, 1);
2063 if(!strequal(p, "B516B16")) {
2064 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2067 p = skip_string(p,1);
2068 p += pull_ascii_fstring(user,p);
2070 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2073 * Pass the user through the NT -> unix user mapping
2077 (void)map_username(user);
2079 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2080 SSVAL(*rparam,0,NERR_Success);
2086 /****************************************************************************
2089 ****************************************************************************/
2090 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2091 int mdrcnt,int mprcnt,
2092 char **rdata,char **rparam,
2093 int *rdata_len,int *rparam_len)
2095 int function = SVAL(param,0);
2096 char *str1 = param+2;
2097 char *str2 = skip_string(str1,1);
2098 char *p = skip_string(str2,1);
2102 extern struct current_user current_user;
2103 WERROR werr = WERR_OK;
2105 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2108 /* check it's a supported varient */
2109 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2113 *rparam = REALLOC(*rparam,*rparam_len);
2116 if (!print_job_exists(snum, jobid)) {
2117 errcode = NERR_JobNotFound;
2121 errcode = NERR_notsupported;
2124 case 81: /* delete */
2125 if (print_job_delete(¤t_user, snum, jobid, &werr))
2126 errcode = NERR_Success;
2128 case 82: /* pause */
2129 if (print_job_pause(¤t_user, snum, jobid, &werr))
2130 errcode = NERR_Success;
2132 case 83: /* resume */
2133 if (print_job_resume(¤t_user, snum, jobid, &werr))
2134 errcode = NERR_Success;
2138 if (!W_ERROR_IS_OK(werr))
2139 errcode = W_ERROR_V(werr);
2142 SSVAL(*rparam,0,errcode);
2143 SSVAL(*rparam,2,0); /* converter word */
2148 /****************************************************************************
2149 Purge a print queue - or pause or resume it.
2150 ****************************************************************************/
2151 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2152 int mdrcnt,int mprcnt,
2153 char **rdata,char **rparam,
2154 int *rdata_len,int *rparam_len)
2156 int function = SVAL(param,0);
2157 char *str1 = param+2;
2158 char *str2 = skip_string(str1,1);
2159 char *QueueName = skip_string(str2,1);
2160 int errcode = NERR_notsupported;
2162 WERROR werr = WERR_OK;
2163 extern struct current_user current_user;
2165 /* check it's a supported varient */
2166 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2170 *rparam = REALLOC(*rparam,*rparam_len);
2173 snum = print_queue_snum(QueueName);
2176 errcode = NERR_JobNotFound;
2181 case 74: /* Pause queue */
2182 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2184 case 75: /* Resume queue */
2185 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2187 case 103: /* Purge */
2188 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2192 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2195 SSVAL(*rparam,0,errcode);
2196 SSVAL(*rparam,2,0); /* converter word */
2202 /****************************************************************************
2203 set the property of a print job (undocumented?)
2204 ? function = 0xb -> set name of print job
2205 ? function = 0x6 -> move print job up/down
2206 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2207 or <WWsTP> <WB21BB16B10zWWzDDz>
2208 ****************************************************************************/
2209 static int check_printjob_info(struct pack_desc* desc,
2210 int uLevel, char* id)
2212 desc->subformat = NULL;
2214 case 0: desc->format = "W"; break;
2215 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2216 case 2: desc->format = "WWzWWDDzz"; break;
2217 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2218 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2219 default: return False;
2221 if (strcmp(desc->format,id) != 0) return False;
2225 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2226 int mdrcnt,int mprcnt,
2227 char **rdata,char **rparam,
2228 int *rdata_len,int *rparam_len)
2230 struct pack_desc desc;
2231 char *str1 = param+2;
2232 char *str2 = skip_string(str1,1);
2233 char *p = skip_string(str2,1);
2236 int uLevel = SVAL(p,2);
2237 int function = SVAL(p,4);
2240 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2243 *rparam = REALLOC(*rparam,*rparam_len);
2247 /* check it's a supported varient */
2248 if ((strcmp(str1,"WWsTP")) ||
2249 (!check_printjob_info(&desc,uLevel,str2)))
2252 if (!print_job_exists(snum, jobid)) {
2253 errcode=NERR_JobNotFound;
2257 errcode = NERR_notsupported;
2261 /* change job place in the queue,
2262 data gives the new place */
2263 place = SVAL(data,0);
2264 if (print_job_set_place(snum, jobid, place)) {
2265 errcode=NERR_Success;
2270 /* change print job name, data gives the name */
2271 if (print_job_set_name(snum, jobid, data)) {
2272 errcode=NERR_Success;
2281 SSVALS(*rparam,0,errcode);
2282 SSVAL(*rparam,2,0); /* converter word */
2288 /****************************************************************************
2289 get info about the server
2290 ****************************************************************************/
2291 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2292 int mdrcnt,int mprcnt,
2293 char **rdata,char **rparam,
2294 int *rdata_len,int *rparam_len)
2296 char *str1 = param+2;
2297 char *str2 = skip_string(str1,1);
2298 char *p = skip_string(str2,1);
2299 int uLevel = SVAL(p,0);
2303 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2305 /* check it's a supported varient */
2306 if (!prefix_ok(str1,"WrLh")) return False;
2309 if (strcmp(str2,"B16") != 0) return False;
2313 if (strcmp(str2,"B16BBDz") != 0) return False;
2317 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2322 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2327 if (strcmp(str2,"DN") != 0) return False;
2331 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2334 default: return False;
2337 *rdata_len = mdrcnt;
2338 *rdata = REALLOC(*rdata,*rdata_len);
2341 p2 = p + struct_len;
2343 srvstr_push(NULL, p,local_machine,16,
2344 STR_ASCII|STR_UPPER|STR_TERMINATE);
2349 struct srv_info_struct *servers=NULL;
2352 uint32 servertype= lp_default_server_announce();
2354 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2356 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2357 for (i=0;i<count;i++) {
2358 if (strequal(servers[i].name,local_machine)) {
2359 servertype = servers[i].type;
2360 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2366 SCVAL(p,0,lp_major_announce_version());
2367 SCVAL(p,1,lp_minor_announce_version());
2368 SIVAL(p,2,servertype);
2370 if (mdrcnt == struct_len) {
2373 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2374 standard_sub_conn(conn,comment,sizeof(comment));
2375 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2376 p2 = skip_string(p2,1);
2381 return False; /* not yet implemented */
2384 *rdata_len = PTR_DIFF(p2,*rdata);
2387 *rparam = REALLOC(*rparam,*rparam_len);
2388 SSVAL(*rparam,0,NERR_Success);
2389 SSVAL(*rparam,2,0); /* converter word */
2390 SSVAL(*rparam,4,*rdata_len);
2396 /****************************************************************************
2397 get info about the server
2398 ****************************************************************************/
2399 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2400 int mdrcnt,int mprcnt,
2401 char **rdata,char **rparam,
2402 int *rdata_len,int *rparam_len)
2404 char *str1 = param+2;
2405 char *str2 = skip_string(str1,1);
2406 char *p = skip_string(str2,1);
2408 extern userdom_struct current_user_info;
2409 int level = SVAL(p,0);
2411 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2414 *rparam = REALLOC(*rparam,*rparam_len);
2416 /* check it's a supported varient */
2417 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2420 *rdata_len = mdrcnt + 1024;
2421 *rdata = REALLOC(*rdata,*rdata_len);
2423 SSVAL(*rparam,0,NERR_Success);
2424 SSVAL(*rparam,2,0); /* converter word */
2430 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2431 pstrcpy(p2,local_machine);
2433 p2 = skip_string(p2,1);
2436 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2437 pstrcpy(p2,current_user_info.smb_name);
2438 p2 = skip_string(p2,1);
2441 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2442 pstrcpy(p2,lp_workgroup());
2444 p2 = skip_string(p2,1);
2447 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2448 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2451 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2452 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2453 p2 = skip_string(p2,1);
2456 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2458 p2 = skip_string(p2,1);
2461 *rdata_len = PTR_DIFF(p2,*rdata);
2463 SSVAL(*rparam,4,*rdata_len);
2468 /****************************************************************************
2469 get info about a user
2471 struct user_info_11 {
2472 char usri11_name[21]; 0-20
2474 char *usri11_comment; 22-25
2475 char *usri11_usr_comment; 26-29
2476 unsigned short usri11_priv; 30-31
2477 unsigned long usri11_auth_flags; 32-35
2478 long usri11_password_age; 36-39
2479 char *usri11_homedir; 40-43
2480 char *usri11_parms; 44-47
2481 long usri11_last_logon; 48-51
2482 long usri11_last_logoff; 52-55
2483 unsigned short usri11_bad_pw_count; 56-57
2484 unsigned short usri11_num_logons; 58-59
2485 char *usri11_logon_server; 60-63
2486 unsigned short usri11_country_code; 64-65
2487 char *usri11_workstations; 66-69
2488 unsigned long usri11_max_storage; 70-73
2489 unsigned short usri11_units_per_week; 74-75
2490 unsigned char *usri11_logon_hours; 76-79
2491 unsigned short usri11_code_page; 80-81
2496 usri11_name specifies the user name for which information is retireved
2498 usri11_pad aligns the next data structure element to a word boundary
2500 usri11_comment is a null terminated ASCII comment
2502 usri11_user_comment is a null terminated ASCII comment about the user
2504 usri11_priv specifies the level of the privilege assigned to the user.
2505 The possible values are:
2507 Name Value Description
2508 USER_PRIV_GUEST 0 Guest privilege
2509 USER_PRIV_USER 1 User privilege
2510 USER_PRV_ADMIN 2 Administrator privilege
2512 usri11_auth_flags specifies the account operator privileges. The
2513 possible values are:
2515 Name Value Description
2516 AF_OP_PRINT 0 Print operator
2519 Leach, Naik [Page 28]
2523 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2526 AF_OP_COMM 1 Communications operator
2527 AF_OP_SERVER 2 Server operator
2528 AF_OP_ACCOUNTS 3 Accounts operator
2531 usri11_password_age specifies how many seconds have elapsed since the
2532 password was last changed.
2534 usri11_home_dir points to a null terminated ASCII string that contains
2535 the path name of the user's home directory.
2537 usri11_parms points to a null terminated ASCII string that is set
2538 aside for use by applications.
2540 usri11_last_logon specifies the time when the user last logged on.
2541 This value is stored as the number of seconds elapsed since
2542 00:00:00, January 1, 1970.
2544 usri11_last_logoff specifies the time when the user last logged off.
2545 This value is stored as the number of seconds elapsed since
2546 00:00:00, January 1, 1970. A value of 0 means the last logoff
2549 usri11_bad_pw_count specifies the number of incorrect passwords
2550 entered since the last successful logon.
2552 usri11_log1_num_logons specifies the number of times this user has
2553 logged on. A value of -1 means the number of logons is unknown.
2555 usri11_logon_server points to a null terminated ASCII string that
2556 contains the name of the server to which logon requests are sent.
2557 A null string indicates logon requests should be sent to the
2560 usri11_country_code specifies the country code for the user's language
2563 usri11_workstations points to a null terminated ASCII string that
2564 contains the names of workstations the user may log on from.
2565 There may be up to 8 workstations, with the names separated by
2566 commas. A null strings indicates there are no restrictions.
2568 usri11_max_storage specifies the maximum amount of disk space the user
2569 can occupy. A value of 0xffffffff indicates there are no
2572 usri11_units_per_week specifies the equal number of time units into
2573 which a week is divided. This value must be equal to 168.
2575 usri11_logon_hours points to a 21 byte (168 bits) string that
2576 specifies the time during which the user can log on. Each bit
2577 represents one unique hour in a week. The first bit (bit 0, word
2578 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2582 Leach, Naik [Page 29]
2586 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2589 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2590 are no restrictions.
2592 usri11_code_page specifies the code page for the user's language of
2595 All of the pointers in this data structure need to be treated
2596 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2597 to be ignored. The converter word returned in the parameters section
2598 needs to be subtracted from the lower 16 bits to calculate an offset
2599 into the return buffer where this ASCII string resides.
2601 There is no auxiliary data in the response.
2603 ****************************************************************************/
2605 #define usri11_name 0
2606 #define usri11_pad 21
2607 #define usri11_comment 22
2608 #define usri11_usr_comment 26
2609 #define usri11_full_name 30
2610 #define usri11_priv 34
2611 #define usri11_auth_flags 36
2612 #define usri11_password_age 40
2613 #define usri11_homedir 44
2614 #define usri11_parms 48
2615 #define usri11_last_logon 52
2616 #define usri11_last_logoff 56
2617 #define usri11_bad_pw_count 60
2618 #define usri11_num_logons 62
2619 #define usri11_logon_server 64
2620 #define usri11_country_code 68
2621 #define usri11_workstations 70
2622 #define usri11_max_storage 74
2623 #define usri11_units_per_week 78
2624 #define usri11_logon_hours 80
2625 #define usri11_code_page 84
2626 #define usri11_end 86
2628 #define USER_PRIV_GUEST 0
2629 #define USER_PRIV_USER 1
2630 #define USER_PRIV_ADMIN 2
2632 #define AF_OP_PRINT 0
2633 #define AF_OP_COMM 1
2634 #define AF_OP_SERVER 2
2635 #define AF_OP_ACCOUNTS 3
2638 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2639 int mdrcnt,int mprcnt,
2640 char **rdata,char **rparam,
2641 int *rdata_len,int *rparam_len)
2643 char *str1 = param+2;
2644 char *str2 = skip_string(str1,1);
2645 char *UserName = skip_string(str2,1);
2646 char *p = skip_string(UserName,1);
2647 int uLevel = SVAL(p,0);
2649 const char *level_string;
2651 /* get NIS home of a previously validated user - simeon */
2652 /* With share level security vuid will always be zero.
2653 Don't depend on vuser being non-null !!. JRA */
2654 user_struct *vuser = get_valid_user_struct(vuid);
2656 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2657 vuser->user.unix_name));
2660 *rparam = REALLOC(*rparam,*rparam_len);
2662 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2664 /* check it's a supported variant */
2665 if (strcmp(str1,"zWrLh") != 0) return False;
2668 case 0: level_string = "B21"; break;
2669 case 1: level_string = "B21BB16DWzzWz"; break;
2670 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2671 case 10: level_string = "B21Bzzz"; break;
2672 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2673 default: return False;
2676 if (strcmp(level_string,str2) != 0) return False;
2678 *rdata_len = mdrcnt + 1024;
2679 *rdata = REALLOC(*rdata,*rdata_len);
2681 SSVAL(*rparam,0,NERR_Success);
2682 SSVAL(*rparam,2,0); /* converter word */
2685 p2 = p + usri11_end;
2688 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2692 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2697 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2698 pstrcpy(p2,"Comment");
2699 p2 = skip_string(p2,1);
2701 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2702 pstrcpy(p2,"UserComment");
2703 p2 = skip_string(p2,1);
2705 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2706 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2707 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2708 p2 = skip_string(p2,1);
2711 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2713 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2714 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2715 SIVALS(p,usri11_password_age,-1); /* password age */
2716 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2717 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2718 p2 = skip_string(p2,1);
2719 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2721 p2 = skip_string(p2,1);
2722 SIVAL(p,usri11_last_logon,0); /* last logon */
2723 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2724 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2725 SSVALS(p,usri11_num_logons,-1); /* num logons */
2726 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2727 pstrcpy(p2,"\\\\*");
2728 p2 = skip_string(p2,1);
2729 SSVAL(p,usri11_country_code,0); /* country code */
2731 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2733 p2 = skip_string(p2,1);
2735 SIVALS(p,usri11_max_storage,-1); /* max storage */
2736 SSVAL(p,usri11_units_per_week,168); /* units per week */
2737 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2739 /* a simple way to get logon hours at all times. */
2741 SCVAL(p2,21,0); /* fix zero termination */
2742 p2 = skip_string(p2,1);
2744 SSVAL(p,usri11_code_page,0); /* code page */
2746 if (uLevel == 1 || uLevel == 2)
2748 memset(p+22,' ',16); /* password */
2749 SIVALS(p,38,-1); /* password age */
2751 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2752 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2753 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2754 p2 = skip_string(p2,1);
2755 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2757 SSVAL(p,52,0); /* flags */
2758 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2759 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2760 p2 = skip_string(p2,1);
2763 SIVAL(p,60,0); /* auth_flags */
2764 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2765 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2766 p2 = skip_string(p2,1);
2767 SIVAL(p,68,0); /* urs_comment */
2768 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2770 p2 = skip_string(p2,1);
2771 SIVAL(p,76,0); /* workstations */
2772 SIVAL(p,80,0); /* last_logon */
2773 SIVAL(p,84,0); /* last_logoff */
2774 SIVALS(p,88,-1); /* acct_expires */
2775 SIVALS(p,92,-1); /* max_storage */
2776 SSVAL(p,96,168); /* units_per_week */
2777 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2780 SSVALS(p,102,-1); /* bad_pw_count */
2781 SSVALS(p,104,-1); /* num_logons */
2782 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2783 pstrcpy(p2,"\\\\%L");
2784 standard_sub_conn(conn, p2,0);
2785 p2 = skip_string(p2,1);
2786 SSVAL(p,110,49); /* country_code */
2787 SSVAL(p,112,860); /* code page */
2791 *rdata_len = PTR_DIFF(p2,*rdata);
2793 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2798 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2799 int mdrcnt,int mprcnt,
2800 char **rdata,char **rparam,
2801 int *rdata_len,int *rparam_len)
2803 char *str1 = param+2;
2804 char *str2 = skip_string(str1,1);
2805 char *p = skip_string(str2,1);
2807 struct pack_desc desc;
2809 /* With share level security vuid will always be zero.
2810 Don't depend on vuser being non-null !!. JRA */
2811 user_struct *vuser = get_valid_user_struct(vuid);
2813 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2814 vuser->user.unix_name));
2819 memset((char *)&desc,'\0',sizeof(desc));
2821 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2823 /* check it's a supported varient */
2824 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2825 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2826 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2828 desc.buflen = mdrcnt;
2829 desc.subformat = NULL;
2832 if (init_package(&desc,1,0))
2834 PACKI(&desc,"W",0); /* code */
2835 PACKS(&desc,"B21",name); /* eff. name */
2836 PACKS(&desc,"B",""); /* pad */
2838 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2839 PACKI(&desc,"D",0); /* auth flags XXX */
2840 PACKI(&desc,"W",0); /* num logons */
2841 PACKI(&desc,"W",0); /* bad pw count */
2842 PACKI(&desc,"D",0); /* last logon */
2843 PACKI(&desc,"D",-1); /* last logoff */
2844 PACKI(&desc,"D",-1); /* logoff time */
2845 PACKI(&desc,"D",-1); /* kickoff time */
2846 PACKI(&desc,"D",0); /* password age */
2847 PACKI(&desc,"D",0); /* password can change */
2848 PACKI(&desc,"D",-1); /* password must change */
2851 fstrcpy(mypath,"\\\\");
2852 fstrcat(mypath,local_machine);
2854 PACKS(&desc,"z",mypath); /* computer */
2856 PACKS(&desc,"z",lp_workgroup());/* domain */
2858 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2860 PACKI(&desc,"D",0x00000000); /* reserved */
2863 *rdata_len = desc.usedlen;
2865 *rparam = REALLOC(*rparam,*rparam_len);
2866 SSVALS(*rparam,0,desc.errcode);
2868 SSVAL(*rparam,4,desc.neededlen);
2870 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2875 /****************************************************************************
2876 api_WAccessGetUserPerms
2877 ****************************************************************************/
2878 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2879 int mdrcnt,int mprcnt,
2880 char **rdata,char **rparam,
2881 int *rdata_len,int *rparam_len)
2883 char *str1 = param+2;
2884 char *str2 = skip_string(str1,1);
2885 char *user = skip_string(str2,1);
2886 char *resource = skip_string(user,1);
2888 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2890 /* check it's a supported varient */
2891 if (strcmp(str1,"zzh") != 0) return False;
2892 if (strcmp(str2,"") != 0) return False;
2895 *rparam = REALLOC(*rparam,*rparam_len);
2896 SSVALS(*rparam,0,0); /* errorcode */
2897 SSVAL(*rparam,2,0); /* converter word */
2898 SSVAL(*rparam,4,0x7f); /* permission flags */
2903 /****************************************************************************
2904 api_WPrintJobEnumerate
2905 ****************************************************************************/
2906 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2907 int mdrcnt,int mprcnt,
2908 char **rdata,char **rparam,
2909 int *rdata_len,int *rparam_len)
2911 char *str1 = param+2;
2912 char *str2 = skip_string(str1,1);
2913 char *p = skip_string(str2,1);
2919 struct pack_desc desc;
2920 print_queue_struct *queue=NULL;
2921 print_status_struct status;
2926 memset((char *)&desc,'\0',sizeof(desc));
2927 memset((char *)&status,'\0',sizeof(status));
2929 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2931 /* check it's a supported varient */
2932 if (strcmp(str1,"WWrLh") != 0) return False;
2933 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2935 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2938 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2940 count = print_queue_status(snum,&queue,&status);
2941 for (i = 0; i < count; i++) {
2942 if (queue[i].job == jobid) break;
2946 *rdata = REALLOC(*rdata,mdrcnt);
2948 desc.buflen = mdrcnt;
2951 * Don't return data but need to get correct length
2952 * init_package will return wrong size if buflen=0
2954 desc.buflen = getlen(desc.format);
2955 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2958 if (init_package(&desc,1,0)) {
2960 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2961 *rdata_len = desc.usedlen;
2964 desc.errcode = NERR_JobNotFound;
2970 *rparam = REALLOC(*rparam,*rparam_len);
2971 SSVALS(*rparam,0,desc.errcode);
2973 SSVAL(*rparam,4,desc.neededlen);
2978 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2982 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2983 int mdrcnt,int mprcnt,
2984 char **rdata,char **rparam,
2985 int *rdata_len,int *rparam_len)
2987 char *str1 = param+2;
2988 char *str2 = skip_string(str1,1);
2989 char *p = skip_string(str2,1);
2995 struct pack_desc desc;
2996 print_queue_struct *queue=NULL;
2997 print_status_struct status;
2999 memset((char *)&desc,'\0',sizeof(desc));
3000 memset((char *)&status,'\0',sizeof(status));
3002 p = skip_string(p,1);
3005 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3007 /* check it's a supported variant */
3008 if (strcmp(str1,"zWrLeh") != 0) return False;
3009 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3010 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3012 snum = lp_servicenumber(name);
3013 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3014 int pnum = lp_servicenumber(PRINTERS_NAME);
3016 lp_add_printer(name,pnum);
3017 snum = lp_servicenumber(name);
3021 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3023 count = print_queue_status(snum,&queue,&status);
3024 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3026 desc.buflen = mdrcnt;
3028 if (init_package(&desc,count,0)) {
3030 for (i = 0; i < count; i++) {
3031 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3032 if (desc.errcode == NERR_Success) succnt = i+1;
3036 *rdata_len = desc.usedlen;
3039 *rparam = REALLOC(*rparam,*rparam_len);
3040 SSVALS(*rparam,0,desc.errcode);
3042 SSVAL(*rparam,4,succnt);
3043 SSVAL(*rparam,6,count);
3047 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3051 static int check_printdest_info(struct pack_desc* desc,
3052 int uLevel, char* id)
3054 desc->subformat = NULL;
3056 case 0: desc->format = "B9"; break;
3057 case 1: desc->format = "B9B21WWzW"; break;
3058 case 2: desc->format = "z"; break;
3059 case 3: desc->format = "zzzWWzzzWW"; break;
3060 default: return False;
3062 if (strcmp(desc->format,id) != 0) return False;
3066 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3067 struct pack_desc* desc)
3070 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3071 buf[sizeof(buf)-1] = 0;
3074 PACKS(desc,"B9",buf); /* szName */
3076 PACKS(desc,"B21",""); /* szUserName */
3077 PACKI(desc,"W",0); /* uJobId */
3078 PACKI(desc,"W",0); /* fsStatus */
3079 PACKS(desc,"z",""); /* pszStatus */
3080 PACKI(desc,"W",0); /* time */
3083 if (uLevel == 2 || uLevel == 3) {
3084 PACKS(desc,"z",buf); /* pszPrinterName */
3086 PACKS(desc,"z",""); /* pszUserName */
3087 PACKS(desc,"z",""); /* pszLogAddr */
3088 PACKI(desc,"W",0); /* uJobId */
3089 PACKI(desc,"W",0); /* fsStatus */
3090 PACKS(desc,"z",""); /* pszStatus */
3091 PACKS(desc,"z",""); /* pszComment */
3092 PACKS(desc,"z","NULL"); /* pszDrivers */
3093 PACKI(desc,"W",0); /* time */
3094 PACKI(desc,"W",0); /* pad1 */
3099 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3100 int mdrcnt,int mprcnt,
3101 char **rdata,char **rparam,
3102 int *rdata_len,int *rparam_len)
3104 char *str1 = param+2;
3105 char *str2 = skip_string(str1,1);
3106 char *p = skip_string(str2,1);
3107 char* PrinterName = p;
3109 struct pack_desc desc;
3113 memset((char *)&desc,'\0',sizeof(desc));
3115 p = skip_string(p,1);
3118 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3120 /* check it's a supported varient */
3121 if (strcmp(str1,"zWrLh") != 0) return False;
3122 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3124 snum = lp_servicenumber(PrinterName);
3125 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3126 int pnum = lp_servicenumber(PRINTERS_NAME);
3128 lp_add_printer(PrinterName,pnum);
3129 snum = lp_servicenumber(PrinterName);
3135 desc.errcode = NERR_DestNotFound;
3140 *rdata = REALLOC(*rdata,mdrcnt);
3142 desc.buflen = mdrcnt;
3145 * Don't return data but need to get correct length
3146 * init_package will return wrong size if buflen=0
3148 desc.buflen = getlen(desc.format);
3149 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3151 if (init_package(&desc,1,0)) {
3152 fill_printdest_info(conn,snum,uLevel,&desc);
3154 *rdata_len = desc.usedlen;
3158 *rparam = REALLOC(*rparam,*rparam_len);
3159 SSVALS(*rparam,0,desc.errcode);
3161 SSVAL(*rparam,4,desc.neededlen);
3163 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3168 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3169 int mdrcnt,int mprcnt,
3170 char **rdata,char **rparam,
3171 int *rdata_len,int *rparam_len)
3173 char *str1 = param+2;
3174 char *str2 = skip_string(str1,1);
3175 char *p = skip_string(str2,1);
3179 struct pack_desc desc;
3180 int services = lp_numservices();
3182 memset((char *)&desc,'\0',sizeof(desc));
3186 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3188 /* check it's a supported varient */
3189 if (strcmp(str1,"WrLeh") != 0) return False;
3190 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3193 for (i = 0; i < services; i++)
3194 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3197 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3199 desc.buflen = mdrcnt;
3200 if (init_package(&desc,queuecnt,0)) {
3203 for (i = 0; i < services; i++) {
3204 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3205 fill_printdest_info(conn,i,uLevel,&desc);
3207 if (desc.errcode == NERR_Success) succnt = n;
3212 *rdata_len = desc.usedlen;
3215 *rparam = REALLOC(*rparam,*rparam_len);
3216 SSVALS(*rparam,0,desc.errcode);
3218 SSVAL(*rparam,4,succnt);
3219 SSVAL(*rparam,6,queuecnt);
3221 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3225 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3226 int mdrcnt,int mprcnt,
3227 char **rdata,char **rparam,
3228 int *rdata_len,int *rparam_len)
3230 char *str1 = param+2;
3231 char *str2 = skip_string(str1,1);
3232 char *p = skip_string(str2,1);
3235 struct pack_desc desc;
3237 memset((char *)&desc,'\0',sizeof(desc));
3241 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3243 /* check it's a supported varient */
3244 if (strcmp(str1,"WrLeh") != 0) return False;
3245 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3247 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3249 desc.buflen = mdrcnt;
3250 if (init_package(&desc,1,0)) {
3251 PACKS(&desc,"B41","NULL");
3254 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3256 *rdata_len = desc.usedlen;
3259 *rparam = REALLOC(*rparam,*rparam_len);
3260 SSVALS(*rparam,0,desc.errcode);
3262 SSVAL(*rparam,4,succnt);
3265 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3269 static BOOL api_WPrintQProcEnum(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);
3279 struct pack_desc desc;
3281 memset((char *)&desc,'\0',sizeof(desc));
3285 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3287 /* check it's a supported varient */
3288 if (strcmp(str1,"WrLeh") != 0) return False;
3289 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3291 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3293 desc.buflen = mdrcnt;
3295 if (init_package(&desc,1,0)) {
3296 PACKS(&desc,"B13","lpd");
3299 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3301 *rdata_len = desc.usedlen;
3304 *rparam = REALLOC(*rparam,*rparam_len);
3305 SSVALS(*rparam,0,desc.errcode);
3307 SSVAL(*rparam,4,succnt);
3310 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3314 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3315 int mdrcnt,int mprcnt,
3316 char **rdata,char **rparam,
3317 int *rdata_len,int *rparam_len)
3319 char *str1 = param+2;
3320 char *str2 = skip_string(str1,1);
3321 char *p = skip_string(str2,1);
3324 struct pack_desc desc;
3326 memset((char *)&desc,'\0',sizeof(desc));
3330 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3332 /* check it's a supported varient */
3333 if (strcmp(str1,"WrLeh") != 0) return False;
3334 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3336 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3337 memset((char *)&desc,'\0',sizeof(desc));
3339 desc.buflen = mdrcnt;
3341 if (init_package(&desc,1,0)) {
3342 PACKS(&desc,"B13","lp0");
3345 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3347 *rdata_len = desc.usedlen;
3350 *rparam = REALLOC(*rparam,*rparam_len);
3351 SSVALS(*rparam,0,desc.errcode);
3353 SSVAL(*rparam,4,succnt);
3356 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3361 /****************************************************************************
3363 ****************************************************************************/
3364 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3365 int mdrcnt,int mprcnt,
3366 char **rdata,char **rparam,
3367 int *rdata_len,int *rparam_len)
3370 char *str1 = param+2;
3371 char *str2 = skip_string(str1,1);
3372 char *p = skip_string(str2,1);
3374 struct pack_desc desc;
3375 struct sessionid *session_list;
3376 int i, num_sessions;
3378 memset((char *)&desc,'\0',sizeof(desc));
3382 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3383 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3384 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3386 /* check it's a supported varient */
3387 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3388 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3390 num_sessions = list_sessions(&session_list);
3392 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3393 memset((char *)&desc,'\0',sizeof(desc));
3395 desc.buflen = mdrcnt;
3397 if (!init_package(&desc,num_sessions,0)) {
3401 for(i=0; i<num_sessions; i++) {
3402 PACKS(&desc, "z", session_list[i].remote_machine);
3403 PACKS(&desc, "z", session_list[i].username);
3404 PACKI(&desc, "W", 1); /* num conns */
3405 PACKI(&desc, "W", 0); /* num opens */
3406 PACKI(&desc, "W", 1); /* num users */
3407 PACKI(&desc, "D", 0); /* session time */
3408 PACKI(&desc, "D", 0); /* idle time */
3409 PACKI(&desc, "D", 0); /* flags */
3410 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3413 *rdata_len = desc.usedlen;
3416 *rparam = REALLOC(*rparam,*rparam_len);
3417 SSVALS(*rparam,0,desc.errcode);
3418 SSVAL(*rparam,2,0); /* converter */
3419 SSVAL(*rparam,4,num_sessions); /* count */
3421 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3426 /****************************************************************************
3427 The buffer was too small
3428 ****************************************************************************/
3430 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3431 int mdrcnt,int mprcnt,
3432 char **rdata,char **rparam,
3433 int *rdata_len,int *rparam_len)
3435 *rparam_len = MIN(*rparam_len,mprcnt);
3436 *rparam = REALLOC(*rparam,*rparam_len);
3440 SSVAL(*rparam,0,NERR_BufTooSmall);
3442 DEBUG(3,("Supplied buffer too small in API command\n"));
3448 /****************************************************************************
3449 The request is not supported
3450 ****************************************************************************/
3452 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3453 int mdrcnt,int mprcnt,
3454 char **rdata,char **rparam,
3455 int *rdata_len,int *rparam_len)
3458 *rparam = REALLOC(*rparam,*rparam_len);
3462 SSVAL(*rparam,0,NERR_notsupported);
3463 SSVAL(*rparam,2,0); /* converter word */
3465 DEBUG(3,("Unsupported API command\n"));
3477 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3478 int,int,char **,char **,int *,int *);
3479 BOOL auth_user; /* Deny anonymous access? */
3480 } api_commands[] = {
3481 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3482 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3483 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3484 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3485 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3486 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3487 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3488 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3489 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3490 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3491 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3492 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3493 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3494 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3495 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3496 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3497 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3498 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3499 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3500 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3501 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3502 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3503 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3504 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3505 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3506 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3507 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3508 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3509 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3510 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3511 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3512 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3513 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3514 {NULL, -1, api_Unsupported}};
3516 /* The following RAP calls are not implemented by Samba:
3518 RAP_WFileEnum2 - anon not OK
3521 /****************************************************************************
3522 Handle remote api calls
3523 ****************************************************************************/
3525 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3526 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3530 char *rparam = NULL;
3537 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3541 api_command = SVAL(params,0);
3543 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3546 skip_string(params+2,1),
3547 tdscnt,tpscnt,mdrcnt,mprcnt));
3549 for (i=0;api_commands[i].name;i++) {
3550 if (api_commands[i].id == api_command && api_commands[i].fn) {
3551 DEBUG(3,("Doing %s\n",api_commands[i].name));
3556 /* Check whether this api call can be done anonymously */
3558 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3559 user_struct *user = get_valid_user_struct(vuid);
3561 if (!user || user->guest)
3562 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3565 rdata = (char *)malloc(1024);
3567 memset(rdata,'\0',1024);
3569 rparam = (char *)malloc(1024);
3571 memset(rparam,'\0',1024);
3573 if(!rdata || !rparam) {
3574 DEBUG(0,("api_reply: malloc fail !\n"));
3578 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3579 &rdata,&rparam,&rdata_len,&rparam_len);
3582 if (rdata_len > mdrcnt ||
3583 rparam_len > mprcnt) {
3584 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3585 &rdata,&rparam,&rdata_len,&rparam_len);
3588 /* if we get False back then it's actually unsupported */
3590 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3591 &rdata,&rparam,&rdata_len,&rparam_len);
3593 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);