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;
36 extern pstring global_myname;
37 extern fstring global_myworkgroup;
39 #define NERR_Success 0
40 #define NERR_badpass 86
41 #define NERR_notsupported 50
43 #define NERR_BASE (2100)
44 #define NERR_BufTooSmall (NERR_BASE+23)
45 #define NERR_JobNotFound (NERR_BASE+51)
46 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ACCESS_READ 0x01
49 #define ACCESS_WRITE 0x02
50 #define ACCESS_CREATE 0x04
52 #define SHPWLEN 8 /* share password length */
54 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
55 int mdrcnt,int mprcnt,
56 char **rdata,char **rparam,
57 int *rdata_len,int *rparam_len);
58 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
59 int mdrcnt,int mprcnt,
60 char **rdata,char **rparam,
61 int *rdata_len,int *rparam_len);
64 static int CopyExpanded(connection_struct *conn,
65 int snum, char** dst, char* src, int* n)
70 if (!src || !dst || !n || !(*dst)) return(0);
72 StrnCpy(buf,src,sizeof(buf)/2);
73 pstring_sub(buf,"%S",lp_servicename(snum));
74 standard_sub_conn(conn,buf,sizeof(buf));
75 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
81 static int CopyAndAdvance(char** dst, char* src, int* n)
84 if (!src || !dst || !n || !(*dst)) return(0);
85 l = push_ascii(*dst,src,*n, STR_TERMINATE);
91 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
95 StrnCpy(buf,s,sizeof(buf)/2);
96 pstring_sub(buf,"%S",lp_servicename(snum));
97 standard_sub_conn(conn,buf,sizeof(buf));
98 return strlen(buf) + 1;
101 static char* Expand(connection_struct *conn, int snum, char* s)
104 if (!s) return(NULL);
105 StrnCpy(buf,s,sizeof(buf)/2);
106 pstring_sub(buf,"%S",lp_servicename(snum));
107 standard_sub_conn(conn,buf,sizeof(buf));
111 /*******************************************************************
112 check a API string for validity when we only need to check the prefix
113 ******************************************************************/
114 static BOOL prefix_ok(char *str,char *prefix)
116 return(strncmp(str,prefix,strlen(prefix)) == 0);
120 char* format; /* formatstring for structure */
121 char* subformat; /* subformat for structure */
122 char* base; /* baseaddress of buffer */
123 int buflen; /* remaining size for fixed part; on init: length of base */
124 int subcount; /* count of substructures */
125 char* structbuf; /* pointer into buffer for remaining fixed part */
126 int stringlen; /* remaining size for variable part */
127 char* stringbuf; /* pointer into buffer for remaining variable part */
128 int neededlen; /* total needed size */
129 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
130 char* curpos; /* current position; pointer into format or subformat */
134 static int get_counter(char** p)
137 if (!p || !(*p)) return(1);
138 if (!isdigit((int)**p)) return 1;
142 n = 10 * n + (i - '0');
149 static int getlen(char* p)
155 case 'W': /* word (2 byte) */
158 case 'K': /* status word? (2 byte) */
161 case 'N': /* count of substructures (word) at end */
164 case 'D': /* double word (4 byte) */
165 case 'z': /* offset to zero terminated string (4 byte) */
166 case 'l': /* offset to user data (4 byte) */
169 case 'b': /* offset to data (with counter) (4 byte) */
173 case 'B': /* byte (with optional counter) */
174 n += get_counter(&p);
181 static BOOL init_package(struct pack_desc* p, int count, int subcount)
186 if (!p->format || !p->base) return(False);
188 i = count * getlen(p->format);
189 if (p->subformat) i += subcount * getlen(p->subformat);
190 p->structbuf = p->base;
194 p->curpos = p->format;
200 * This is the old error code we used. Aparently
201 * WinNT/2k systems return ERRbuftoosmall (2123) and
202 * OS/2 needs this. I'm leaving this here so we can revert
205 p->errcode = ERRmoredata;
207 p->errcode = ERRbuftoosmall;
211 p->errcode = NERR_Success;
214 p->stringbuf = p->base + i;
216 return(p->errcode == NERR_Success);
219 static int package(struct pack_desc* p, ...)
222 int needed=0, stringneeded;
224 int is_string=0, stringused;
231 p->curpos = p->format;
233 p->curpos = p->subformat;
238 str = va_arg(args,char*);
239 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
248 switch( *p->curpos++ ) {
249 case 'W': /* word (2 byte) */
251 temp = va_arg(args,int);
252 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
254 case 'K': /* status word? (2 byte) */
256 temp = va_arg(args,int);
257 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
259 case 'N': /* count of substructures (word) at end */
261 p->subcount = va_arg(args,int);
262 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
264 case 'D': /* double word (4 byte) */
266 temp = va_arg(args,int);
267 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
269 case 'B': /* byte (with optional counter) */
270 needed = get_counter(&p->curpos);
272 char *s = va_arg(args,char*);
273 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
276 case 'z': /* offset to zero terminated string (4 byte) */
277 str = va_arg(args,char*);
278 stringneeded = (str ? strlen(str)+1 : 0);
281 case 'l': /* offset to user data (4 byte) */
282 str = va_arg(args,char*);
283 stringneeded = va_arg(args,int);
286 case 'b': /* offset to data (with counter) (4 byte) */
287 str = va_arg(args,char*);
288 stringneeded = get_counter(&p->curpos);
293 if (stringneeded >= 0) {
295 if (p->buflen >= needed) {
296 stringused = stringneeded;
297 if (stringused > p->stringlen) {
298 stringused = (is_string ? p->stringlen : 0);
299 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
302 SIVAL(p->structbuf,0,0);
304 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
305 memcpy(p->stringbuf,str?str:"",stringused);
306 if (is_string) p->stringbuf[stringused-1] = '\0';
307 p->stringbuf += stringused;
308 p->stringlen -= stringused;
309 p->usedlen += stringused;
312 p->neededlen += stringneeded;
314 p->neededlen += needed;
315 if (p->buflen >= needed) {
316 p->structbuf += needed;
318 p->usedlen += needed;
321 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
327 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
328 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
330 #define PACK(desc,t,v) package(desc,v)
331 #define PACKl(desc,t,v,l) package(desc,v,l)
334 static void PACKI(struct pack_desc* desc,char *t,int v)
339 static void PACKS(struct pack_desc* desc,char *t,char *v)
345 /****************************************************************************
347 ****************************************************************************/
348 static void PackDriverData(struct pack_desc* desc)
350 char drivdata[4+4+32];
351 SIVAL(drivdata,0,sizeof drivdata); /* cb */
352 SIVAL(drivdata,4,1000); /* lVersion */
353 memset(drivdata+8,0,32); /* szDeviceName */
354 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
355 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
358 static int check_printq_info(struct pack_desc* desc,
359 int uLevel, char *id1, char *id2)
361 desc->subformat = NULL;
364 desc->format = "B13";
367 desc->format = "B13BWWWzzzzzWW";
370 desc->format = "B13BWWWzzzzzWN";
371 desc->subformat = "WB21BB16B10zWWzDDz";
374 desc->format = "zWWWWzzzzWWzzl";
377 desc->format = "zWWWWzzzzWNzzl";
378 desc->subformat = "WWzWWDDzz";
387 desc->format = "WzzzzzzzzN";
388 desc->subformat = "z";
390 default: return False;
392 if (strcmp(desc->format,id1) != 0) return False;
393 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
398 #define RAP_JOB_STATUS_QUEUED 0
399 #define RAP_JOB_STATUS_PAUSED 1
400 #define RAP_JOB_STATUS_SPOOLING 2
401 #define RAP_JOB_STATUS_PRINTING 3
402 #define RAP_JOB_STATUS_PRINTED 4
404 #define RAP_QUEUE_STATUS_PAUSED 1
405 #define RAP_QUEUE_STATUS_ERROR 2
407 /* turn a print job status into a on the wire status
409 static int printj_status(int v)
413 return RAP_JOB_STATUS_QUEUED;
415 return RAP_JOB_STATUS_PAUSED;
417 return RAP_JOB_STATUS_SPOOLING;
419 return RAP_JOB_STATUS_PRINTING;
424 /* turn a print queue status into a on the wire status
426 static int printq_status(int v)
432 return RAP_QUEUE_STATUS_PAUSED;
434 return RAP_QUEUE_STATUS_ERROR;
437 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
438 struct pack_desc* desc,
439 print_queue_struct* queue, int n)
441 time_t t = queue->time;
443 /* the client expects localtime */
446 PACKI(desc,"W",pjobid_to_rap(snum,queue->job)); /* uJobId */
448 PACKS(desc,"B21",queue->fs_user); /* szUserName */
449 PACKS(desc,"B",""); /* pad */
450 PACKS(desc,"B16",""); /* szNotifyName */
451 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
452 PACKS(desc,"z",""); /* pszParms */
453 PACKI(desc,"W",n+1); /* uPosition */
454 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
455 PACKS(desc,"z",""); /* pszStatus */
456 PACKI(desc,"D",t); /* ulSubmitted */
457 PACKI(desc,"D",queue->size); /* ulSize */
458 PACKS(desc,"z",queue->fs_file); /* pszComment */
460 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
461 PACKI(desc,"W",queue->priority); /* uPriority */
462 PACKS(desc,"z",queue->fs_user); /* pszUserName */
463 PACKI(desc,"W",n+1); /* uPosition */
464 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
465 PACKI(desc,"D",t); /* ulSubmitted */
466 PACKI(desc,"D",queue->size); /* ulSize */
467 PACKS(desc,"z","Samba"); /* pszComment */
468 PACKS(desc,"z",queue->fs_file); /* pszDocument */
470 PACKS(desc,"z",""); /* pszNotifyName */
471 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
472 PACKS(desc,"z",""); /* pszParms */
473 PACKS(desc,"z",""); /* pszStatus */
474 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
475 PACKS(desc,"z","lpd"); /* pszQProcName */
476 PACKS(desc,"z",""); /* pszQProcParms */
477 PACKS(desc,"z","NULL"); /* pszDriverName */
478 PackDriverData(desc); /* pDriverData */
479 PACKS(desc,"z",""); /* pszPrinterName */
480 } else if (uLevel == 4) { /* OS2 */
481 PACKS(desc,"z",""); /* pszSpoolFileName */
482 PACKS(desc,"z",""); /* pszPortName */
483 PACKS(desc,"z",""); /* pszStatus */
484 PACKI(desc,"D",0); /* ulPagesSpooled */
485 PACKI(desc,"D",0); /* ulPagesSent */
486 PACKI(desc,"D",0); /* ulPagesPrinted */
487 PACKI(desc,"D",0); /* ulTimePrinted */
488 PACKI(desc,"D",0); /* ulExtendJobStatus */
489 PACKI(desc,"D",0); /* ulStartPage */
490 PACKI(desc,"D",0); /* ulEndPage */
495 /********************************************************************
496 Return a driver name given an snum.
497 Returns True if from tdb, False otherwise.
498 ********************************************************************/
500 static BOOL get_driver_name(int snum, pstring drivername)
502 NT_PRINTER_INFO_LEVEL *info = NULL;
505 get_a_printer (&info, 2, lp_servicename(snum));
507 pstrcpy( drivername, info->info_2->drivername);
509 free_a_printer(&info, 2);
515 /********************************************************************
516 Respond to the DosPrintQInfo command with a level of 52
517 This is used to get printer driver information for Win9x clients
518 ********************************************************************/
519 static void fill_printq_info_52(connection_struct *conn, int snum,
520 struct pack_desc* desc, int count )
524 NT_PRINTER_DRIVER_INFO_LEVEL driver;
525 NT_PRINTER_INFO_LEVEL *printer = NULL;
527 if ( !W_ERROR_IS_OK(get_a_printer( &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;
684 if ( !W_ERROR_IS_OK(get_a_printer( &printer, 2, lp_servicename(snum))) ) {
685 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
686 lp_servicename(snum)));
690 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
693 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
694 printer->info_2->drivername));
698 /* count the number of files */
699 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
704 free_a_printer( &printer, 2 );
707 free_a_printer_driver( driver, 3 );
712 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
713 uint16 vuid, char *param,char *data,
714 int mdrcnt,int mprcnt,
715 char **rdata,char **rparam,
716 int *rdata_len,int *rparam_len)
718 char *str1 = param+2;
719 char *str2 = skip_string(str1,1);
720 char *p = skip_string(str2,1);
726 struct pack_desc desc;
727 print_queue_struct *queue=NULL;
728 print_status_struct status;
731 memset((char *)&status,'\0',sizeof(status));
732 memset((char *)&desc,'\0',sizeof(desc));
734 p = skip_string(p,1);
738 /* remove any trailing username */
739 if ((p = strchr_m(QueueName,'%')))
742 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
744 /* check it's a supported varient */
745 if (!prefix_ok(str1,"zWrLh"))
747 if (!check_printq_info(&desc,uLevel,str2,str3)) {
749 * Patch from Scott Moomaw <scott@bridgewater.edu>
750 * to return the 'invalid info level' error if an
751 * unknown level was requested.
755 *rparam = REALLOC(*rparam,*rparam_len);
756 SSVALS(*rparam,0,ERRunknownlevel);
762 snum = lp_servicenumber(QueueName);
763 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
764 int pnum = lp_servicenumber(PRINTERS_NAME);
766 lp_add_printer(QueueName,pnum);
767 snum = lp_servicenumber(QueueName);
771 if (snum < 0 || !VALID_SNUM(snum))
775 count = get_printerdrivernumber(snum);
776 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
778 count = print_queue_status(snum, &queue,&status);
782 *rdata = REALLOC(*rdata,mdrcnt);
784 desc.buflen = mdrcnt;
787 * Don't return data but need to get correct length
788 * init_package will return wrong size if buflen=0
790 desc.buflen = getlen(desc.format);
791 desc.base = tmpdata = (char *) malloc (desc.buflen);
794 if (init_package(&desc,1,count)) {
795 desc.subcount = count;
796 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
799 *rdata_len = desc.usedlen;
802 * We must set the return code to ERRbuftoosmall
803 * in order to support lanman style printing with Win NT/2k
806 if (!mdrcnt && lp_disable_spoolss())
807 desc.errcode = ERRbuftoosmall;
809 *rdata_len = desc.usedlen;
811 *rparam = REALLOC(*rparam,*rparam_len);
812 SSVALS(*rparam,0,desc.errcode);
814 SSVAL(*rparam,4,desc.neededlen);
816 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
824 /****************************************************************************
825 View list of all print jobs on all queues.
826 ****************************************************************************/
828 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
829 int mdrcnt, int mprcnt,
830 char **rdata, char** rparam,
831 int *rdata_len, int *rparam_len)
833 char *param_format = param+2;
834 char *output_format1 = skip_string(param_format,1);
835 char *p = skip_string(output_format1,1);
836 int uLevel = SVAL(p,0);
837 char *output_format2 = p + 4;
838 int services = lp_numservices();
840 struct pack_desc desc;
841 print_queue_struct **queue = NULL;
842 print_status_struct *status = NULL;
843 int* subcntarr = NULL;
844 int queuecnt, subcnt=0, succnt=0;
846 memset((char *)&desc,'\0',sizeof(desc));
848 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
850 if (!prefix_ok(param_format,"WrLeh")) return False;
851 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
853 * Patch from Scott Moomaw <scott@bridgewater.edu>
854 * to return the 'invalid info level' error if an
855 * unknown level was requested.
859 *rparam = REALLOC(*rparam,*rparam_len);
860 SSVALS(*rparam,0,ERRunknownlevel);
867 for (i = 0; i < services; i++)
868 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
871 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
872 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
875 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
876 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
877 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
880 memset(status,0,queuecnt*sizeof(print_status_struct));
881 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
882 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
887 for (i = 0; i < services; i++)
888 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
889 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
890 subcnt += subcntarr[n];
894 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
896 desc.buflen = mdrcnt;
898 if (init_package(&desc,queuecnt,subcnt)) {
901 for (i = 0; i < services; i++)
902 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
903 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
905 if (desc.errcode == NERR_Success) succnt = n;
909 SAFE_FREE(subcntarr);
911 *rdata_len = desc.usedlen;
913 *rparam = REALLOC(*rparam,*rparam_len);
914 SSVALS(*rparam,0,desc.errcode);
916 SSVAL(*rparam,4,succnt);
917 SSVAL(*rparam,6,queuecnt);
919 for (i = 0; i < queuecnt; i++) {
920 if (queue) SAFE_FREE(queue[i]);
929 /****************************************************************************
930 get info level for a server list query
931 ****************************************************************************/
932 static BOOL check_server_info(int uLevel, char* id)
936 if (strcmp(id,"B16") != 0) return False;
939 if (strcmp(id,"B16BBDz") != 0) return False;
947 struct srv_info_struct
957 /*******************************************************************
958 get server info lists from the files saved by nmbd. Return the
960 ******************************************************************/
961 static int get_server_info(uint32 servertype,
962 struct srv_info_struct **servers,
968 BOOL local_list_only;
971 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
973 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
977 /* request for everything is code for request all servers */
978 if (servertype == SV_TYPE_ALL)
979 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
981 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
983 DEBUG(4,("Servertype search: %8x\n",servertype));
985 for (i=0;lines[i];i++) {
987 struct srv_info_struct *s;
988 char *ptr = lines[i];
993 if (count == alloced) {
994 struct srv_info_struct *ts;
997 ts = (struct srv_info_struct *)
998 Realloc(*servers,sizeof(**servers)*alloced);
1000 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1004 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1006 s = &(*servers)[count];
1008 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1009 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1010 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1011 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1012 /* this allows us to cope with an old nmbd */
1013 pstrcpy(s->domain,global_myworkgroup);
1016 if (sscanf(stype,"%X",&s->type) != 1) {
1017 DEBUG(4,("r:host file "));
1021 /* Filter the servers/domains we return based on what was asked for. */
1023 /* Check to see if we are being asked for a local list only. */
1024 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1025 DEBUG(4,("r: local list only"));
1029 /* doesn't match up: don't want it */
1030 if (!(servertype & s->type)) {
1031 DEBUG(4,("r:serv type "));
1035 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1036 (s->type & SV_TYPE_DOMAIN_ENUM))
1038 DEBUG(4,("s: dom mismatch "));
1042 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1047 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1048 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1052 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1053 s->name, s->type, s->comment, s->domain));
1055 s->server_added = True;
1060 DEBUG(4,("%20s %8x %25s %15s\n",
1061 s->name, s->type, s->comment, s->domain));
1065 file_lines_free(lines);
1070 /*******************************************************************
1071 fill in a server info structure
1072 ******************************************************************/
1073 static int fill_srv_info(struct srv_info_struct *service,
1074 int uLevel, char **buf, int *buflen,
1075 char **stringbuf, int *stringspace, char *baseaddr)
1084 case 0: struct_len = 16; break;
1085 case 1: struct_len = 26; break;
1095 len = strlen(service->comment)+1;
1099 if (buflen) *buflen = struct_len;
1100 if (stringspace) *stringspace = len;
1101 return struct_len + len;
1106 if (*buflen < struct_len) return -1;
1114 p2 = p + struct_len;
1115 l2 = *buflen - struct_len;
1117 if (!baseaddr) baseaddr = p;
1122 push_ascii(p,service->name, 15, STR_TERMINATE);
1126 push_ascii(p,service->name,15, STR_TERMINATE);
1127 SIVAL(p,18,service->type);
1128 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1129 len += CopyAndAdvance(&p2,service->comment,&l2);
1135 *buf = p + struct_len;
1136 *buflen -= struct_len;
1149 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1151 return(strcmp(s1->name,s2->name));
1154 /****************************************************************************
1155 view list of servers available (or possibly domains). The info is
1156 extracted from lists saved by nmbd on the local host
1157 ****************************************************************************/
1158 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1159 int mdrcnt, int mprcnt, char **rdata,
1160 char **rparam, int *rdata_len, int *rparam_len)
1162 char *str1 = param+2;
1163 char *str2 = skip_string(str1,1);
1164 char *p = skip_string(str2,1);
1165 int uLevel = SVAL(p,0);
1166 int buf_len = SVAL(p,2);
1167 uint32 servertype = IVAL(p,4);
1169 int data_len, fixed_len, string_len;
1170 int f_len = 0, s_len = 0;
1171 struct srv_info_struct *servers=NULL;
1172 int counted=0,total=0;
1175 BOOL domain_request;
1178 /* If someone sets all the bits they don't really mean to set
1179 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1182 if (servertype == SV_TYPE_ALL)
1183 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1185 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1186 any other bit (they may just set this bit on it's own) they
1187 want all the locally seen servers. However this bit can be
1188 set on its own so set the requested servers to be
1189 ALL - DOMAIN_ENUM. */
1191 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1192 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1194 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1195 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1199 if (!prefix_ok(str1,"WrLehD")) return False;
1200 if (!check_server_info(uLevel,str2)) return False;
1202 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1203 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1204 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1206 if (strcmp(str1, "WrLehDz") == 0) {
1207 pull_ascii_fstring(domain, p);
1209 fstrcpy(domain, global_myworkgroup);
1212 if (lp_browse_list())
1213 total = get_server_info(servertype,&servers,domain);
1215 data_len = fixed_len = string_len = 0;
1219 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1222 char *lastname=NULL;
1224 for (i=0;i<total;i++)
1226 struct srv_info_struct *s = &servers[i];
1227 if (lastname && strequal(lastname,s->name)) continue;
1229 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1230 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1231 s->name, s->type, s->comment, s->domain));
1233 if (data_len <= buf_len) {
1236 string_len += s_len;
1243 *rdata_len = fixed_len + string_len;
1244 *rdata = REALLOC(*rdata,*rdata_len);
1245 memset(*rdata,'\0',*rdata_len);
1247 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1253 char *lastname=NULL;
1254 int count2 = counted;
1255 for (i = 0; i < total && count2;i++)
1257 struct srv_info_struct *s = &servers[i];
1258 if (lastname && strequal(lastname,s->name)) continue;
1260 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1261 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1262 s->name, s->type, s->comment, s->domain));
1268 *rparam = REALLOC(*rparam,*rparam_len);
1269 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1271 SSVAL(*rparam,4,counted);
1272 SSVAL(*rparam,6,counted+missed);
1276 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1277 domain,uLevel,counted,counted+missed));
1282 /****************************************************************************
1283 command 0x34 - suspected of being a "Lookup Names" stub api
1284 ****************************************************************************/
1285 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1286 int mdrcnt, int mprcnt, char **rdata,
1287 char **rparam, int *rdata_len, int *rparam_len)
1289 char *str1 = param+2;
1290 char *str2 = skip_string(str1,1);
1291 char *p = skip_string(str2,1);
1292 int uLevel = SVAL(p,0);
1293 int buf_len = SVAL(p,2);
1297 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1298 str1, str2, p, uLevel, buf_len));
1300 if (!prefix_ok(str1,"zWrLeh")) return False;
1305 *rparam = REALLOC(*rparam,*rparam_len);
1307 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1309 SSVAL(*rparam,4,counted);
1310 SSVAL(*rparam,6,counted+missed);
1315 /****************************************************************************
1316 get info about a share
1317 ****************************************************************************/
1318 static BOOL check_share_info(int uLevel, char* id)
1322 if (strcmp(id,"B13") != 0) return False;
1325 if (strcmp(id,"B13BWz") != 0) return False;
1328 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1331 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1333 default: return False;
1338 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1339 char** buf, int* buflen,
1340 char** stringbuf, int* stringspace, char* baseaddr)
1349 case 0: struct_len = 13; break;
1350 case 1: struct_len = 20; break;
1351 case 2: struct_len = 40; break;
1352 case 91: struct_len = 68; break;
1360 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1361 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1362 if (buflen) *buflen = struct_len;
1363 if (stringspace) *stringspace = len;
1364 return struct_len + len;
1369 if ((*buflen) < struct_len) return -1;
1377 p2 = p + struct_len;
1378 l2 = (*buflen) - struct_len;
1380 if (!baseaddr) baseaddr = p;
1382 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1388 type = STYPE_DISKTREE;
1389 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1390 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1391 SSVAL(p,14,type); /* device type */
1392 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1393 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1398 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1399 SSVALS(p,22,-1); /* max uses */
1400 SSVAL(p,24,1); /* current uses */
1401 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1402 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1403 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1408 memset(p+40,0,SHPWLEN+2);
1420 (*buf) = p + struct_len;
1421 (*buflen) -= struct_len;
1423 (*stringspace) = l2;
1433 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1434 int mdrcnt,int mprcnt,
1435 char **rdata,char **rparam,
1436 int *rdata_len,int *rparam_len)
1438 char *str1 = param+2;
1439 char *str2 = skip_string(str1,1);
1440 char *netname = skip_string(str2,1);
1441 char *p = skip_string(netname,1);
1442 int uLevel = SVAL(p,0);
1443 int snum = find_service(netname);
1445 if (snum < 0) return False;
1447 /* check it's a supported varient */
1448 if (!prefix_ok(str1,"zWrLh")) return False;
1449 if (!check_share_info(uLevel,str2)) return False;
1451 *rdata = REALLOC(*rdata,mdrcnt);
1453 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1454 if (*rdata_len < 0) return False;
1457 *rparam = REALLOC(*rparam,*rparam_len);
1458 SSVAL(*rparam,0,NERR_Success);
1459 SSVAL(*rparam,2,0); /* converter word */
1460 SSVAL(*rparam,4,*rdata_len);
1465 /****************************************************************************
1466 view list of shares available
1467 ****************************************************************************/
1468 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1469 int mdrcnt,int mprcnt,
1470 char **rdata,char **rparam,
1471 int *rdata_len,int *rparam_len)
1473 char *str1 = param+2;
1474 char *str2 = skip_string(str1,1);
1475 char *p = skip_string(str2,1);
1476 int uLevel = SVAL(p,0);
1477 int buf_len = SVAL(p,2);
1479 int count=lp_numservices();
1480 int total=0,counted=0;
1481 BOOL missed = False;
1483 int data_len, fixed_len, string_len;
1484 int f_len = 0, s_len = 0;
1486 if (!prefix_ok(str1,"WrLeh")) return False;
1487 if (!check_share_info(uLevel,str2)) return False;
1489 data_len = fixed_len = string_len = 0;
1490 for (i=0;i<count;i++)
1491 if (lp_browseable(i) && lp_snum_ok(i))
1494 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1495 if (data_len <= buf_len)
1499 string_len += s_len;
1504 *rdata_len = fixed_len + string_len;
1505 *rdata = REALLOC(*rdata,*rdata_len);
1506 memset(*rdata,0,*rdata_len);
1508 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1512 for (i = 0; i < count;i++)
1513 if (lp_browseable(i) && lp_snum_ok(i))
1514 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1518 *rparam = REALLOC(*rparam,*rparam_len);
1519 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1521 SSVAL(*rparam,4,counted);
1522 SSVAL(*rparam,6,total);
1524 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1525 counted,total,uLevel,
1526 buf_len,*rdata_len,mdrcnt));
1530 /****************************************************************************
1532 ****************************************************************************/
1533 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1534 int mdrcnt,int mprcnt,
1535 char **rdata,char **rparam,
1536 int *rdata_len,int *rparam_len)
1538 char *str1 = param+2;
1539 char *str2 = skip_string(str1,1);
1540 char *p = skip_string(str2,1);
1541 int uLevel = SVAL(p,0);
1545 char *command, *cmdname;
1546 unsigned int offset;
1550 /* check it's a supported varient */
1551 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1552 if (!check_share_info(uLevel,str2)) return False;
1553 if (uLevel != 2) return False;
1555 pull_ascii_fstring(sharename,data);
1556 snum = find_service(sharename);
1557 if (snum >= 0) { /* already exists */
1562 /* only support disk share adds */
1563 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1565 offset = IVAL(data, 16);
1566 if (offset >= mdrcnt) {
1567 res = ERRinvalidparam;
1570 pull_ascii_fstring(comment, offset? (data+offset) : "");
1572 offset = IVAL(data, 26);
1573 if (offset >= mdrcnt) {
1574 res = ERRinvalidparam;
1577 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1579 string_replace(sharename, '"', ' ');
1580 string_replace(pathname, '"', ' ');
1581 string_replace(comment, '"', ' ');
1583 cmdname = lp_add_share_cmd();
1585 if (!cmdname || *cmdname == '\0') return False;
1587 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1588 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1591 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1592 if ((res = smbrun(command, NULL)) != 0) {
1593 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1599 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1601 } else return False;
1604 *rparam = REALLOC(*rparam,*rparam_len);
1605 SSVAL(*rparam,0,NERR_Success);
1606 SSVAL(*rparam,2,0); /* converter word */
1607 SSVAL(*rparam,4,*rdata_len);
1614 *rparam = REALLOC(*rparam,*rparam_len);
1616 SSVAL(*rparam,0,res);
1622 /****************************************************************************
1623 view list of groups available
1624 ****************************************************************************/
1625 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1626 int mdrcnt,int mprcnt,
1627 char **rdata,char **rparam,
1628 int *rdata_len,int *rparam_len)
1632 int resume_context, cli_buf_size;
1633 char *str1 = param+2;
1634 char *str2 = skip_string(str1,1);
1635 char *p = skip_string(str2,1);
1637 GROUP_MAP *group_list;
1640 if (strcmp(str1,"WrLeh") != 0)
1644 * W-> resume context (number of users to skip)
1645 * r -> return parameter pointer to receive buffer
1646 * L -> length of receive buffer
1647 * e -> return parameter number of entries
1648 * h -> return parameter total number of users
1650 if (strcmp("B21",str2) != 0)
1653 /* get list of domain groups SID_DOMAIN_GRP=2 */
1654 if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) {
1655 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1659 resume_context = SVAL(p,0);
1660 cli_buf_size=SVAL(p+2,0);
1661 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1663 *rdata_len = cli_buf_size;
1664 *rdata = REALLOC(*rdata,*rdata_len);
1668 for(i=resume_context; i<num_entries; i++) {
1669 char* name=group_list[i].nt_name;
1670 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1671 /* truncate the name at 21 chars. */
1672 memcpy(p, name, 21);
1673 DEBUG(10,("adding entry %d group %s\n", i, p));
1676 /* set overflow error */
1677 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1683 *rdata_len = PTR_DIFF(p,*rdata);
1686 *rparam = REALLOC(*rparam,*rparam_len);
1688 SSVAL(*rparam, 0, errflags);
1689 SSVAL(*rparam, 2, 0); /* converter word */
1690 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1691 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1696 /*******************************************************************
1697 get groups that a user is a member of
1698 ******************************************************************/
1699 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1700 int mdrcnt,int mprcnt,
1701 char **rdata,char **rparam,
1702 int *rdata_len,int *rparam_len)
1704 char *str1 = param+2;
1705 char *str2 = skip_string(str1,1);
1706 char *UserName = skip_string(str2,1);
1707 char *p = skip_string(UserName,1);
1708 int uLevel = SVAL(p,0);
1713 *rparam = REALLOC(*rparam,*rparam_len);
1715 /* check it's a supported varient */
1716 if (!strcmp(str1,"zWrLeh"))
1726 if (strcmp(p2,str2) != 0)
1729 *rdata_len = mdrcnt + 1024;
1730 *rdata = REALLOC(*rdata,*rdata_len);
1732 SSVAL(*rparam,0,NERR_Success);
1733 SSVAL(*rparam,2,0); /* converter word */
1737 /* XXXX we need a real SAM database some day */
1738 pstrcpy(p,"Users"); p += 21; count++;
1739 pstrcpy(p,"Domain Users"); p += 21; count++;
1740 pstrcpy(p,"Guests"); p += 21; count++;
1741 pstrcpy(p,"Domain Guests"); p += 21; count++;
1743 *rdata_len = PTR_DIFF(p,*rdata);
1745 SSVAL(*rparam,4,count); /* is this right?? */
1746 SSVAL(*rparam,6,count); /* is this right?? */
1751 /*******************************************************************
1753 ******************************************************************/
1754 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1755 int mdrcnt,int mprcnt,
1756 char **rdata,char **rparam,
1757 int *rdata_len,int *rparam_len)
1759 SAM_ACCOUNT *pwd=NULL;
1763 int resume_context, cli_buf_size;
1765 char *str1 = param+2;
1766 char *str2 = skip_string(str1,1);
1767 char *p = skip_string(str2,1);
1769 if (strcmp(str1,"WrLeh") != 0)
1772 * W-> resume context (number of users to skip)
1773 * r -> return parameter pointer to receive buffer
1774 * L -> length of receive buffer
1775 * e -> return parameter number of entries
1776 * h -> return parameter total number of users
1779 resume_context = SVAL(p,0);
1780 cli_buf_size=SVAL(p+2,0);
1781 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1784 *rparam = REALLOC(*rparam,*rparam_len);
1786 /* check it's a supported varient */
1787 if (strcmp("B21",str2) != 0)
1790 *rdata_len = cli_buf_size;
1791 *rdata = REALLOC(*rdata,*rdata_len);
1795 /* to get user list enumerations for NetUserEnum in B21 format */
1798 /* Open the passgrp file - not for update. */
1800 if(!pdb_setsampwent(False)) {
1801 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1805 errflags=NERR_Success;
1807 while ( pdb_getsampwent(pwd) ) {
1808 const char *name=pdb_get_username(pwd);
1809 if ((name) && (*(name+strlen(name)-1)!='$')) {
1811 if(count_total>=resume_context) {
1812 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1814 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1818 /* set overflow error */
1819 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1832 *rdata_len = PTR_DIFF(p,*rdata);
1834 SSVAL(*rparam,0,errflags);
1835 SSVAL(*rparam,2,0); /* converter word */
1836 SSVAL(*rparam,4,count_sent); /* is this right?? */
1837 SSVAL(*rparam,6,count_total); /* is this right?? */
1844 /****************************************************************************
1845 get the time of day info
1846 ****************************************************************************/
1847 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1848 int mdrcnt,int mprcnt,
1849 char **rdata,char **rparam,
1850 int *rdata_len,int *rparam_len)
1854 *rparam = REALLOC(*rparam,*rparam_len);
1857 *rdata = REALLOC(*rdata,*rdata_len);
1859 SSVAL(*rparam,0,NERR_Success);
1860 SSVAL(*rparam,2,0); /* converter word */
1866 time_t unixdate = time(NULL);
1868 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1869 by NT in a "net time" operation,
1870 it seems to ignore the one below */
1872 /* the client expects to get localtime, not GMT, in this bit
1873 (I think, this needs testing) */
1874 t = LocalTime(&unixdate);
1876 SIVAL(p,4,0); /* msecs ? */
1877 SCVAL(p,8,t->tm_hour);
1878 SCVAL(p,9,t->tm_min);
1879 SCVAL(p,10,t->tm_sec);
1880 SCVAL(p,11,0); /* hundredths of seconds */
1881 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1882 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1883 SCVAL(p,16,t->tm_mday);
1884 SCVAL(p,17,t->tm_mon + 1);
1885 SSVAL(p,18,1900+t->tm_year);
1886 SCVAL(p,20,t->tm_wday);
1893 /****************************************************************************
1894 Set the user password.
1895 *****************************************************************************/
1897 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1898 int mdrcnt,int mprcnt,
1899 char **rdata,char **rparam,
1900 int *rdata_len,int *rparam_len)
1902 char *p = skip_string(param+2,2);
1904 fstring pass1,pass2;
1906 pull_ascii_fstring(user,p);
1908 p = skip_string(p,1);
1910 memset(pass1,'\0',sizeof(pass1));
1911 memset(pass2,'\0',sizeof(pass2));
1913 memcpy(pass2,p+16,16);
1916 *rparam = REALLOC(*rparam,*rparam_len);
1920 SSVAL(*rparam,0,NERR_badpass);
1921 SSVAL(*rparam,2,0); /* converter word */
1923 DEBUG(3,("Set password for <%s>\n",user));
1926 * Attempt to verify the old password against smbpasswd entries
1927 * Win98 clients send old and new password in plaintext for this call.
1931 auth_serversupplied_info *server_info = NULL;
1932 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
1933 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1936 * If unix password sync was requested, attempt to change
1937 * the /etc/passwd database first. Return failure if this cannot
1940 * This occurs before the oem change, becouse we don't want to
1941 * update it if chgpasswd failed.
1943 * Conditional on lp_unix_password_sync() becouse we don't want
1944 * to touch the unix db unless we have admin permission.
1947 if(lp_unix_password_sync() && IS_SAM_UNIX_USER(server_info->sam_account)
1948 && !chgpasswd(pdb_get_username(server_info->sam_account),
1949 pass1,pass2,False)) {
1950 SSVAL(*rparam,0,NERR_badpass);
1953 if (change_oem_password(server_info->sam_account,pass2))
1955 SSVAL(*rparam,0,NERR_Success);
1958 free_server_info(&server_info);
1960 data_blob_clear_free(&password);
1964 * If the plaintext change failed, attempt
1965 * the old encrypted method. NT will generate this
1966 * after trying the samr method. Note that this
1967 * method is done as a last resort as this
1968 * password change method loses the NT password hash
1969 * and cannot change the UNIX password as no plaintext
1973 if(SVAL(*rparam,0) != NERR_Success)
1975 SAM_ACCOUNT *hnd = NULL;
1977 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1978 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
1980 SSVAL(*rparam,0,NERR_Success);
1986 memset((char *)pass1,'\0',sizeof(fstring));
1987 memset((char *)pass2,'\0',sizeof(fstring));
1992 /****************************************************************************
1993 Set the user password (SamOEM version - gets plaintext).
1994 ****************************************************************************/
1996 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1997 int mdrcnt,int mprcnt,
1998 char **rdata,char **rparam,
1999 int *rdata_len,int *rparam_len)
2002 char *p = param + 2;
2004 *rparam = REALLOC(*rparam,*rparam_len);
2008 SSVAL(*rparam,0,NERR_badpass);
2011 * Check the parameter definition is correct.
2013 if(!strequal(param + 2, "zsT")) {
2014 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2017 p = skip_string(p, 1);
2019 if(!strequal(p, "B516B16")) {
2020 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2023 p = skip_string(p,1);
2025 p += pull_ascii_fstring(user,p);
2027 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2030 * Pass the user through the NT -> unix user mapping
2034 (void)map_username(user);
2036 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
2038 SSVAL(*rparam,0,NERR_Success);
2044 /****************************************************************************
2047 ****************************************************************************/
2048 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2049 int mdrcnt,int mprcnt,
2050 char **rdata,char **rparam,
2051 int *rdata_len,int *rparam_len)
2053 int function = SVAL(param,0);
2054 char *str1 = param+2;
2055 char *str2 = skip_string(str1,1);
2056 char *p = skip_string(str2,1);
2060 extern struct current_user current_user;
2061 WERROR werr = WERR_OK;
2063 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2066 /* check it's a supported varient */
2067 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2071 *rparam = REALLOC(*rparam,*rparam_len);
2074 if (!print_job_exists(snum, jobid)) {
2075 errcode = NERR_JobNotFound;
2079 errcode = NERR_notsupported;
2082 case 81: /* delete */
2083 if (print_job_delete(¤t_user, snum, jobid, &werr))
2084 errcode = NERR_Success;
2086 case 82: /* pause */
2087 if (print_job_pause(¤t_user, snum, jobid, &werr))
2088 errcode = NERR_Success;
2090 case 83: /* resume */
2091 if (print_job_resume(¤t_user, snum, jobid, &werr))
2092 errcode = NERR_Success;
2096 if (!W_ERROR_IS_OK(werr))
2097 errcode = W_ERROR_V(werr);
2100 SSVAL(*rparam,0,errcode);
2101 SSVAL(*rparam,2,0); /* converter word */
2106 /****************************************************************************
2107 Purge a print queue - or pause or resume it.
2108 ****************************************************************************/
2109 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2110 int mdrcnt,int mprcnt,
2111 char **rdata,char **rparam,
2112 int *rdata_len,int *rparam_len)
2114 int function = SVAL(param,0);
2115 char *str1 = param+2;
2116 char *str2 = skip_string(str1,1);
2117 char *QueueName = skip_string(str2,1);
2118 int errcode = NERR_notsupported;
2120 WERROR werr = WERR_OK;
2121 extern struct current_user current_user;
2123 /* check it's a supported varient */
2124 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2128 *rparam = REALLOC(*rparam,*rparam_len);
2131 snum = print_queue_snum(QueueName);
2134 errcode = NERR_JobNotFound;
2139 case 74: /* Pause queue */
2140 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2142 case 75: /* Resume queue */
2143 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2145 case 103: /* Purge */
2146 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2150 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2153 SSVAL(*rparam,0,errcode);
2154 SSVAL(*rparam,2,0); /* converter word */
2160 /****************************************************************************
2161 set the property of a print job (undocumented?)
2162 ? function = 0xb -> set name of print job
2163 ? function = 0x6 -> move print job up/down
2164 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2165 or <WWsTP> <WB21BB16B10zWWzDDz>
2166 ****************************************************************************/
2167 static int check_printjob_info(struct pack_desc* desc,
2168 int uLevel, char* id)
2170 desc->subformat = NULL;
2172 case 0: desc->format = "W"; break;
2173 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2174 case 2: desc->format = "WWzWWDDzz"; break;
2175 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2176 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2177 default: return False;
2179 if (strcmp(desc->format,id) != 0) return False;
2183 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2184 int mdrcnt,int mprcnt,
2185 char **rdata,char **rparam,
2186 int *rdata_len,int *rparam_len)
2188 struct pack_desc desc;
2189 char *str1 = param+2;
2190 char *str2 = skip_string(str1,1);
2191 char *p = skip_string(str2,1);
2194 int uLevel = SVAL(p,2);
2195 int function = SVAL(p,4);
2198 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2201 *rparam = REALLOC(*rparam,*rparam_len);
2205 /* check it's a supported varient */
2206 if ((strcmp(str1,"WWsTP")) ||
2207 (!check_printjob_info(&desc,uLevel,str2)))
2210 if (!print_job_exists(snum, jobid)) {
2211 errcode=NERR_JobNotFound;
2215 errcode = NERR_notsupported;
2219 /* change job place in the queue,
2220 data gives the new place */
2221 place = SVAL(data,0);
2222 if (print_job_set_place(snum, jobid, place)) {
2223 errcode=NERR_Success;
2228 /* change print job name, data gives the name */
2229 if (print_job_set_name(snum, jobid, data)) {
2230 errcode=NERR_Success;
2239 SSVALS(*rparam,0,errcode);
2240 SSVAL(*rparam,2,0); /* converter word */
2246 /****************************************************************************
2247 get info about the server
2248 ****************************************************************************/
2249 static BOOL api_RNetServerGetInfo(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 char *str1 = param+2;
2255 char *str2 = skip_string(str1,1);
2256 char *p = skip_string(str2,1);
2257 int uLevel = SVAL(p,0);
2261 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2263 /* check it's a supported varient */
2264 if (!prefix_ok(str1,"WrLh")) return False;
2267 if (strcmp(str2,"B16") != 0) return False;
2271 if (strcmp(str2,"B16BBDz") != 0) return False;
2275 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2280 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2285 if (strcmp(str2,"DN") != 0) return False;
2289 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2292 default: return False;
2295 *rdata_len = mdrcnt;
2296 *rdata = REALLOC(*rdata,*rdata_len);
2299 p2 = p + struct_len;
2301 srvstr_push(NULL, p,local_machine,16,
2302 STR_ASCII|STR_UPPER|STR_TERMINATE);
2307 struct srv_info_struct *servers=NULL;
2310 uint32 servertype= lp_default_server_announce();
2312 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2314 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2315 for (i=0;i<count;i++)
2316 if (strequal(servers[i].name,local_machine))
2318 servertype = servers[i].type;
2319 pstrcpy(comment,servers[i].comment);
2324 SCVAL(p,0,lp_major_announce_version());
2325 SCVAL(p,1,lp_minor_announce_version());
2326 SIVAL(p,2,servertype);
2328 if (mdrcnt == struct_len) {
2331 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2332 standard_sub_conn(conn,comment,sizeof(comment));
2333 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2334 p2 = skip_string(p2,1);
2339 return False; /* not yet implemented */
2342 *rdata_len = PTR_DIFF(p2,*rdata);
2345 *rparam = REALLOC(*rparam,*rparam_len);
2346 SSVAL(*rparam,0,NERR_Success);
2347 SSVAL(*rparam,2,0); /* converter word */
2348 SSVAL(*rparam,4,*rdata_len);
2354 /****************************************************************************
2355 get info about the server
2356 ****************************************************************************/
2357 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2358 int mdrcnt,int mprcnt,
2359 char **rdata,char **rparam,
2360 int *rdata_len,int *rparam_len)
2362 char *str1 = param+2;
2363 char *str2 = skip_string(str1,1);
2364 char *p = skip_string(str2,1);
2366 extern userdom_struct current_user_info;
2367 int level = SVAL(p,0);
2369 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2372 *rparam = REALLOC(*rparam,*rparam_len);
2374 /* check it's a supported varient */
2375 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2378 *rdata_len = mdrcnt + 1024;
2379 *rdata = REALLOC(*rdata,*rdata_len);
2381 SSVAL(*rparam,0,NERR_Success);
2382 SSVAL(*rparam,2,0); /* converter word */
2388 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2389 pstrcpy(p2,local_machine);
2391 p2 = skip_string(p2,1);
2394 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2395 pstrcpy(p2,current_user_info.smb_name);
2396 p2 = skip_string(p2,1);
2399 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2400 pstrcpy(p2,global_myworkgroup);
2402 p2 = skip_string(p2,1);
2405 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2406 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2409 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2410 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2411 p2 = skip_string(p2,1);
2414 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2416 p2 = skip_string(p2,1);
2419 *rdata_len = PTR_DIFF(p2,*rdata);
2421 SSVAL(*rparam,4,*rdata_len);
2426 /****************************************************************************
2427 get info about a user
2429 struct user_info_11 {
2430 char usri11_name[21]; 0-20
2432 char *usri11_comment; 22-25
2433 char *usri11_usr_comment; 26-29
2434 unsigned short usri11_priv; 30-31
2435 unsigned long usri11_auth_flags; 32-35
2436 long usri11_password_age; 36-39
2437 char *usri11_homedir; 40-43
2438 char *usri11_parms; 44-47
2439 long usri11_last_logon; 48-51
2440 long usri11_last_logoff; 52-55
2441 unsigned short usri11_bad_pw_count; 56-57
2442 unsigned short usri11_num_logons; 58-59
2443 char *usri11_logon_server; 60-63
2444 unsigned short usri11_country_code; 64-65
2445 char *usri11_workstations; 66-69
2446 unsigned long usri11_max_storage; 70-73
2447 unsigned short usri11_units_per_week; 74-75
2448 unsigned char *usri11_logon_hours; 76-79
2449 unsigned short usri11_code_page; 80-81
2454 usri11_name specifies the user name for which information is retireved
2456 usri11_pad aligns the next data structure element to a word boundary
2458 usri11_comment is a null terminated ASCII comment
2460 usri11_user_comment is a null terminated ASCII comment about the user
2462 usri11_priv specifies the level of the privilege assigned to the user.
2463 The possible values are:
2465 Name Value Description
2466 USER_PRIV_GUEST 0 Guest privilege
2467 USER_PRIV_USER 1 User privilege
2468 USER_PRV_ADMIN 2 Administrator privilege
2470 usri11_auth_flags specifies the account operator privileges. The
2471 possible values are:
2473 Name Value Description
2474 AF_OP_PRINT 0 Print operator
2477 Leach, Naik [Page 28]
2481 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2484 AF_OP_COMM 1 Communications operator
2485 AF_OP_SERVER 2 Server operator
2486 AF_OP_ACCOUNTS 3 Accounts operator
2489 usri11_password_age specifies how many seconds have elapsed since the
2490 password was last changed.
2492 usri11_home_dir points to a null terminated ASCII string that contains
2493 the path name of the user's home directory.
2495 usri11_parms points to a null terminated ASCII string that is set
2496 aside for use by applications.
2498 usri11_last_logon specifies the time when the user last logged on.
2499 This value is stored as the number of seconds elapsed since
2500 00:00:00, January 1, 1970.
2502 usri11_last_logoff specifies the time when the user last logged off.
2503 This value is stored as the number of seconds elapsed since
2504 00:00:00, January 1, 1970. A value of 0 means the last logoff
2507 usri11_bad_pw_count specifies the number of incorrect passwords
2508 entered since the last successful logon.
2510 usri11_log1_num_logons specifies the number of times this user has
2511 logged on. A value of -1 means the number of logons is unknown.
2513 usri11_logon_server points to a null terminated ASCII string that
2514 contains the name of the server to which logon requests are sent.
2515 A null string indicates logon requests should be sent to the
2518 usri11_country_code specifies the country code for the user's language
2521 usri11_workstations points to a null terminated ASCII string that
2522 contains the names of workstations the user may log on from.
2523 There may be up to 8 workstations, with the names separated by
2524 commas. A null strings indicates there are no restrictions.
2526 usri11_max_storage specifies the maximum amount of disk space the user
2527 can occupy. A value of 0xffffffff indicates there are no
2530 usri11_units_per_week specifies the equal number of time units into
2531 which a week is divided. This value must be equal to 168.
2533 usri11_logon_hours points to a 21 byte (168 bits) string that
2534 specifies the time during which the user can log on. Each bit
2535 represents one unique hour in a week. The first bit (bit 0, word
2536 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2540 Leach, Naik [Page 29]
2544 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2547 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2548 are no restrictions.
2550 usri11_code_page specifies the code page for the user's language of
2553 All of the pointers in this data structure need to be treated
2554 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2555 to be ignored. The converter word returned in the parameters section
2556 needs to be subtracted from the lower 16 bits to calculate an offset
2557 into the return buffer where this ASCII string resides.
2559 There is no auxiliary data in the response.
2561 ****************************************************************************/
2563 #define usri11_name 0
2564 #define usri11_pad 21
2565 #define usri11_comment 22
2566 #define usri11_usr_comment 26
2567 #define usri11_full_name 30
2568 #define usri11_priv 34
2569 #define usri11_auth_flags 36
2570 #define usri11_password_age 40
2571 #define usri11_homedir 44
2572 #define usri11_parms 48
2573 #define usri11_last_logon 52
2574 #define usri11_last_logoff 56
2575 #define usri11_bad_pw_count 60
2576 #define usri11_num_logons 62
2577 #define usri11_logon_server 64
2578 #define usri11_country_code 68
2579 #define usri11_workstations 70
2580 #define usri11_max_storage 74
2581 #define usri11_units_per_week 78
2582 #define usri11_logon_hours 80
2583 #define usri11_code_page 84
2584 #define usri11_end 86
2586 #define USER_PRIV_GUEST 0
2587 #define USER_PRIV_USER 1
2588 #define USER_PRIV_ADMIN 2
2590 #define AF_OP_PRINT 0
2591 #define AF_OP_COMM 1
2592 #define AF_OP_SERVER 2
2593 #define AF_OP_ACCOUNTS 3
2596 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2597 int mdrcnt,int mprcnt,
2598 char **rdata,char **rparam,
2599 int *rdata_len,int *rparam_len)
2601 char *str1 = param+2;
2602 char *str2 = skip_string(str1,1);
2603 char *UserName = skip_string(str2,1);
2604 char *p = skip_string(UserName,1);
2605 int uLevel = SVAL(p,0);
2608 /* get NIS home of a previously validated user - simeon */
2609 /* With share level security vuid will always be zero.
2610 Don't depend on vuser being non-null !!. JRA */
2611 user_struct *vuser = get_valid_user_struct(vuid);
2613 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2614 vuser->user.unix_name));
2617 *rparam = REALLOC(*rparam,*rparam_len);
2619 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2621 /* check it's a supported variant */
2622 if (strcmp(str1,"zWrLh") != 0) return False;
2625 case 0: p2 = "B21"; break;
2626 case 1: p2 = "B21BB16DWzzWz"; break;
2627 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2628 case 10: p2 = "B21Bzzz"; break;
2629 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2630 default: return False;
2633 if (strcmp(p2,str2) != 0) return False;
2635 *rdata_len = mdrcnt + 1024;
2636 *rdata = REALLOC(*rdata,*rdata_len);
2638 SSVAL(*rparam,0,NERR_Success);
2639 SSVAL(*rparam,2,0); /* converter word */
2642 p2 = p + usri11_end;
2645 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2649 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2654 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2655 pstrcpy(p2,"Comment");
2656 p2 = skip_string(p2,1);
2658 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2659 pstrcpy(p2,"UserComment");
2660 p2 = skip_string(p2,1);
2662 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2663 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2664 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2665 p2 = skip_string(p2,1);
2668 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2670 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2671 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2672 SIVALS(p,usri11_password_age,-1); /* password age */
2673 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2674 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2675 p2 = skip_string(p2,1);
2676 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2678 p2 = skip_string(p2,1);
2679 SIVAL(p,usri11_last_logon,0); /* last logon */
2680 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2681 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2682 SSVALS(p,usri11_num_logons,-1); /* num logons */
2683 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2684 pstrcpy(p2,"\\\\*");
2685 p2 = skip_string(p2,1);
2686 SSVAL(p,usri11_country_code,0); /* country code */
2688 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2690 p2 = skip_string(p2,1);
2692 SIVALS(p,usri11_max_storage,-1); /* max storage */
2693 SSVAL(p,usri11_units_per_week,168); /* units per week */
2694 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2696 /* a simple way to get logon hours at all times. */
2698 SCVAL(p2,21,0); /* fix zero termination */
2699 p2 = skip_string(p2,1);
2701 SSVAL(p,usri11_code_page,0); /* code page */
2703 if (uLevel == 1 || uLevel == 2)
2705 memset(p+22,' ',16); /* password */
2706 SIVALS(p,38,-1); /* password age */
2708 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2709 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2710 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2711 p2 = skip_string(p2,1);
2712 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2714 SSVAL(p,52,0); /* flags */
2715 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2716 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2717 p2 = skip_string(p2,1);
2720 SIVAL(p,60,0); /* auth_flags */
2721 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2722 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2723 p2 = skip_string(p2,1);
2724 SIVAL(p,68,0); /* urs_comment */
2725 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2727 p2 = skip_string(p2,1);
2728 SIVAL(p,76,0); /* workstations */
2729 SIVAL(p,80,0); /* last_logon */
2730 SIVAL(p,84,0); /* last_logoff */
2731 SIVALS(p,88,-1); /* acct_expires */
2732 SIVALS(p,92,-1); /* max_storage */
2733 SSVAL(p,96,168); /* units_per_week */
2734 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2737 SSVALS(p,102,-1); /* bad_pw_count */
2738 SSVALS(p,104,-1); /* num_logons */
2739 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2740 pstrcpy(p2,"\\\\%L");
2741 standard_sub_conn(conn, p2,0);
2742 p2 = skip_string(p2,1);
2743 SSVAL(p,110,49); /* country_code */
2744 SSVAL(p,112,860); /* code page */
2748 *rdata_len = PTR_DIFF(p2,*rdata);
2750 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2755 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2756 int mdrcnt,int mprcnt,
2757 char **rdata,char **rparam,
2758 int *rdata_len,int *rparam_len)
2760 char *str1 = param+2;
2761 char *str2 = skip_string(str1,1);
2762 char *p = skip_string(str2,1);
2764 struct pack_desc desc;
2766 /* With share level security vuid will always be zero.
2767 Don't depend on vuser being non-null !!. JRA */
2768 user_struct *vuser = get_valid_user_struct(vuid);
2770 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2771 vuser->user.unix_name));
2776 memset((char *)&desc,'\0',sizeof(desc));
2778 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2780 /* check it's a supported varient */
2781 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2782 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2783 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2785 desc.buflen = mdrcnt;
2786 desc.subformat = NULL;
2789 if (init_package(&desc,1,0))
2791 PACKI(&desc,"W",0); /* code */
2792 PACKS(&desc,"B21",name); /* eff. name */
2793 PACKS(&desc,"B",""); /* pad */
2795 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2796 PACKI(&desc,"D",0); /* auth flags XXX */
2797 PACKI(&desc,"W",0); /* num logons */
2798 PACKI(&desc,"W",0); /* bad pw count */
2799 PACKI(&desc,"D",0); /* last logon */
2800 PACKI(&desc,"D",-1); /* last logoff */
2801 PACKI(&desc,"D",-1); /* logoff time */
2802 PACKI(&desc,"D",-1); /* kickoff time */
2803 PACKI(&desc,"D",0); /* password age */
2804 PACKI(&desc,"D",0); /* password can change */
2805 PACKI(&desc,"D",-1); /* password must change */
2808 fstrcpy(mypath,"\\\\");
2809 fstrcat(mypath,local_machine);
2811 PACKS(&desc,"z",mypath); /* computer */
2813 PACKS(&desc,"z",global_myworkgroup);/* domain */
2815 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2817 PACKI(&desc,"D",0x00000000); /* reserved */
2820 *rdata_len = desc.usedlen;
2822 *rparam = REALLOC(*rparam,*rparam_len);
2823 SSVALS(*rparam,0,desc.errcode);
2825 SSVAL(*rparam,4,desc.neededlen);
2827 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2832 /****************************************************************************
2833 api_WAccessGetUserPerms
2834 ****************************************************************************/
2835 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2836 int mdrcnt,int mprcnt,
2837 char **rdata,char **rparam,
2838 int *rdata_len,int *rparam_len)
2840 char *str1 = param+2;
2841 char *str2 = skip_string(str1,1);
2842 char *user = skip_string(str2,1);
2843 char *resource = skip_string(user,1);
2845 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2847 /* check it's a supported varient */
2848 if (strcmp(str1,"zzh") != 0) return False;
2849 if (strcmp(str2,"") != 0) return False;
2852 *rparam = REALLOC(*rparam,*rparam_len);
2853 SSVALS(*rparam,0,0); /* errorcode */
2854 SSVAL(*rparam,2,0); /* converter word */
2855 SSVAL(*rparam,4,0x7f); /* permission flags */
2860 /****************************************************************************
2861 api_WPrintJobEnumerate
2862 ****************************************************************************/
2863 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2864 int mdrcnt,int mprcnt,
2865 char **rdata,char **rparam,
2866 int *rdata_len,int *rparam_len)
2868 char *str1 = param+2;
2869 char *str2 = skip_string(str1,1);
2870 char *p = skip_string(str2,1);
2876 struct pack_desc desc;
2877 print_queue_struct *queue=NULL;
2878 print_status_struct status;
2883 memset((char *)&desc,'\0',sizeof(desc));
2884 memset((char *)&status,'\0',sizeof(status));
2886 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2888 /* check it's a supported varient */
2889 if (strcmp(str1,"WWrLh") != 0) return False;
2890 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2892 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2895 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2897 count = print_queue_status(snum,&queue,&status);
2898 for (i = 0; i < count; i++) {
2899 if (queue[i].job == jobid) break;
2903 *rdata = REALLOC(*rdata,mdrcnt);
2905 desc.buflen = mdrcnt;
2908 * Don't return data but need to get correct length
2909 * init_package will return wrong size if buflen=0
2911 desc.buflen = getlen(desc.format);
2912 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2915 if (init_package(&desc,1,0)) {
2917 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2918 *rdata_len = desc.usedlen;
2921 desc.errcode = NERR_JobNotFound;
2927 *rparam = REALLOC(*rparam,*rparam_len);
2928 SSVALS(*rparam,0,desc.errcode);
2930 SSVAL(*rparam,4,desc.neededlen);
2935 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2939 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2940 int mdrcnt,int mprcnt,
2941 char **rdata,char **rparam,
2942 int *rdata_len,int *rparam_len)
2944 char *str1 = param+2;
2945 char *str2 = skip_string(str1,1);
2946 char *p = skip_string(str2,1);
2952 struct pack_desc desc;
2953 print_queue_struct *queue=NULL;
2954 print_status_struct status;
2956 memset((char *)&desc,'\0',sizeof(desc));
2957 memset((char *)&status,'\0',sizeof(status));
2959 p = skip_string(p,1);
2962 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2964 /* check it's a supported variant */
2965 if (strcmp(str1,"zWrLeh") != 0) return False;
2966 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2967 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2969 snum = lp_servicenumber(name);
2970 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2971 int pnum = lp_servicenumber(PRINTERS_NAME);
2973 lp_add_printer(name,pnum);
2974 snum = lp_servicenumber(name);
2978 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2980 count = print_queue_status(snum,&queue,&status);
2981 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2983 desc.buflen = mdrcnt;
2985 if (init_package(&desc,count,0)) {
2987 for (i = 0; i < count; i++) {
2988 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2989 if (desc.errcode == NERR_Success) succnt = i+1;
2993 *rdata_len = desc.usedlen;
2996 *rparam = REALLOC(*rparam,*rparam_len);
2997 SSVALS(*rparam,0,desc.errcode);
2999 SSVAL(*rparam,4,succnt);
3000 SSVAL(*rparam,6,count);
3004 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3008 static int check_printdest_info(struct pack_desc* desc,
3009 int uLevel, char* id)
3011 desc->subformat = NULL;
3013 case 0: desc->format = "B9"; break;
3014 case 1: desc->format = "B9B21WWzW"; break;
3015 case 2: desc->format = "z"; break;
3016 case 3: desc->format = "zzzWWzzzWW"; break;
3017 default: return False;
3019 if (strcmp(desc->format,id) != 0) return False;
3023 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3024 struct pack_desc* desc)
3027 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3028 buf[sizeof(buf)-1] = 0;
3031 PACKS(desc,"B9",buf); /* szName */
3033 PACKS(desc,"B21",""); /* szUserName */
3034 PACKI(desc,"W",0); /* uJobId */
3035 PACKI(desc,"W",0); /* fsStatus */
3036 PACKS(desc,"z",""); /* pszStatus */
3037 PACKI(desc,"W",0); /* time */
3040 if (uLevel == 2 || uLevel == 3) {
3041 PACKS(desc,"z",buf); /* pszPrinterName */
3043 PACKS(desc,"z",""); /* pszUserName */
3044 PACKS(desc,"z",""); /* pszLogAddr */
3045 PACKI(desc,"W",0); /* uJobId */
3046 PACKI(desc,"W",0); /* fsStatus */
3047 PACKS(desc,"z",""); /* pszStatus */
3048 PACKS(desc,"z",""); /* pszComment */
3049 PACKS(desc,"z","NULL"); /* pszDrivers */
3050 PACKI(desc,"W",0); /* time */
3051 PACKI(desc,"W",0); /* pad1 */
3056 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3057 int mdrcnt,int mprcnt,
3058 char **rdata,char **rparam,
3059 int *rdata_len,int *rparam_len)
3061 char *str1 = param+2;
3062 char *str2 = skip_string(str1,1);
3063 char *p = skip_string(str2,1);
3064 char* PrinterName = p;
3066 struct pack_desc desc;
3070 memset((char *)&desc,'\0',sizeof(desc));
3072 p = skip_string(p,1);
3075 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3077 /* check it's a supported varient */
3078 if (strcmp(str1,"zWrLh") != 0) return False;
3079 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3081 snum = lp_servicenumber(PrinterName);
3082 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3083 int pnum = lp_servicenumber(PRINTERS_NAME);
3085 lp_add_printer(PrinterName,pnum);
3086 snum = lp_servicenumber(PrinterName);
3092 desc.errcode = NERR_DestNotFound;
3097 *rdata = REALLOC(*rdata,mdrcnt);
3099 desc.buflen = mdrcnt;
3102 * Don't return data but need to get correct length
3103 * init_package will return wrong size if buflen=0
3105 desc.buflen = getlen(desc.format);
3106 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3108 if (init_package(&desc,1,0)) {
3109 fill_printdest_info(conn,snum,uLevel,&desc);
3111 *rdata_len = desc.usedlen;
3115 *rparam = REALLOC(*rparam,*rparam_len);
3116 SSVALS(*rparam,0,desc.errcode);
3118 SSVAL(*rparam,4,desc.neededlen);
3120 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3125 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3126 int mdrcnt,int mprcnt,
3127 char **rdata,char **rparam,
3128 int *rdata_len,int *rparam_len)
3130 char *str1 = param+2;
3131 char *str2 = skip_string(str1,1);
3132 char *p = skip_string(str2,1);
3136 struct pack_desc desc;
3137 int services = lp_numservices();
3139 memset((char *)&desc,'\0',sizeof(desc));
3143 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3145 /* check it's a supported varient */
3146 if (strcmp(str1,"WrLeh") != 0) return False;
3147 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3150 for (i = 0; i < services; i++)
3151 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3154 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3156 desc.buflen = mdrcnt;
3157 if (init_package(&desc,queuecnt,0)) {
3160 for (i = 0; i < services; i++) {
3161 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3162 fill_printdest_info(conn,i,uLevel,&desc);
3164 if (desc.errcode == NERR_Success) succnt = n;
3169 *rdata_len = desc.usedlen;
3172 *rparam = REALLOC(*rparam,*rparam_len);
3173 SSVALS(*rparam,0,desc.errcode);
3175 SSVAL(*rparam,4,succnt);
3176 SSVAL(*rparam,6,queuecnt);
3178 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3182 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3183 int mdrcnt,int mprcnt,
3184 char **rdata,char **rparam,
3185 int *rdata_len,int *rparam_len)
3187 char *str1 = param+2;
3188 char *str2 = skip_string(str1,1);
3189 char *p = skip_string(str2,1);
3192 struct pack_desc desc;
3194 memset((char *)&desc,'\0',sizeof(desc));
3198 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3200 /* check it's a supported varient */
3201 if (strcmp(str1,"WrLeh") != 0) return False;
3202 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3204 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3206 desc.buflen = mdrcnt;
3207 if (init_package(&desc,1,0)) {
3208 PACKS(&desc,"B41","NULL");
3211 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3213 *rdata_len = desc.usedlen;
3216 *rparam = REALLOC(*rparam,*rparam_len);
3217 SSVALS(*rparam,0,desc.errcode);
3219 SSVAL(*rparam,4,succnt);
3222 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3226 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3227 int mdrcnt,int mprcnt,
3228 char **rdata,char **rparam,
3229 int *rdata_len,int *rparam_len)
3231 char *str1 = param+2;
3232 char *str2 = skip_string(str1,1);
3233 char *p = skip_string(str2,1);
3236 struct pack_desc desc;
3238 memset((char *)&desc,'\0',sizeof(desc));
3242 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3244 /* check it's a supported varient */
3245 if (strcmp(str1,"WrLeh") != 0) return False;
3246 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3248 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3250 desc.buflen = mdrcnt;
3252 if (init_package(&desc,1,0)) {
3253 PACKS(&desc,"B13","lpd");
3256 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3258 *rdata_len = desc.usedlen;
3261 *rparam = REALLOC(*rparam,*rparam_len);
3262 SSVALS(*rparam,0,desc.errcode);
3264 SSVAL(*rparam,4,succnt);
3267 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3271 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3272 int mdrcnt,int mprcnt,
3273 char **rdata,char **rparam,
3274 int *rdata_len,int *rparam_len)
3276 char *str1 = param+2;
3277 char *str2 = skip_string(str1,1);
3278 char *p = skip_string(str2,1);
3281 struct pack_desc desc;
3283 memset((char *)&desc,'\0',sizeof(desc));
3287 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3289 /* check it's a supported varient */
3290 if (strcmp(str1,"WrLeh") != 0) return False;
3291 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3293 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3294 memset((char *)&desc,'\0',sizeof(desc));
3296 desc.buflen = mdrcnt;
3298 if (init_package(&desc,1,0)) {
3299 PACKS(&desc,"B13","lp0");
3302 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3304 *rdata_len = desc.usedlen;
3307 *rparam = REALLOC(*rparam,*rparam_len);
3308 SSVALS(*rparam,0,desc.errcode);
3310 SSVAL(*rparam,4,succnt);
3313 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3318 /****************************************************************************
3320 ****************************************************************************/
3321 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3322 int mdrcnt,int mprcnt,
3323 char **rdata,char **rparam,
3324 int *rdata_len,int *rparam_len)
3327 char *str1 = param+2;
3328 char *str2 = skip_string(str1,1);
3329 char *p = skip_string(str2,1);
3331 struct pack_desc desc;
3332 struct sessionid *session_list;
3333 int i, num_sessions;
3335 memset((char *)&desc,'\0',sizeof(desc));
3339 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3340 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3341 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3343 /* check it's a supported varient */
3344 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3345 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3347 num_sessions = list_sessions(&session_list);
3349 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3350 memset((char *)&desc,'\0',sizeof(desc));
3352 desc.buflen = mdrcnt;
3354 if (!init_package(&desc,num_sessions,0)) {
3358 for(i=0; i<num_sessions; i++) {
3359 PACKS(&desc, "z", session_list[i].remote_machine);
3360 PACKS(&desc, "z", session_list[i].username);
3361 PACKI(&desc, "W", 1); /* num conns */
3362 PACKI(&desc, "W", 0); /* num opens */
3363 PACKI(&desc, "W", 1); /* num users */
3364 PACKI(&desc, "D", 0); /* session time */
3365 PACKI(&desc, "D", 0); /* idle time */
3366 PACKI(&desc, "D", 0); /* flags */
3367 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3370 *rdata_len = desc.usedlen;
3373 *rparam = REALLOC(*rparam,*rparam_len);
3374 SSVALS(*rparam,0,desc.errcode);
3375 SSVAL(*rparam,2,0); /* converter */
3376 SSVAL(*rparam,4,num_sessions); /* count */
3378 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3383 /****************************************************************************
3384 The buffer was too small
3385 ****************************************************************************/
3387 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3388 int mdrcnt,int mprcnt,
3389 char **rdata,char **rparam,
3390 int *rdata_len,int *rparam_len)
3392 *rparam_len = MIN(*rparam_len,mprcnt);
3393 *rparam = REALLOC(*rparam,*rparam_len);
3397 SSVAL(*rparam,0,NERR_BufTooSmall);
3399 DEBUG(3,("Supplied buffer too small in API command\n"));
3405 /****************************************************************************
3406 The request is not supported
3407 ****************************************************************************/
3409 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3410 int mdrcnt,int mprcnt,
3411 char **rdata,char **rparam,
3412 int *rdata_len,int *rparam_len)
3415 *rparam = REALLOC(*rparam,*rparam_len);
3419 SSVAL(*rparam,0,NERR_notsupported);
3420 SSVAL(*rparam,2,0); /* converter word */
3422 DEBUG(3,("Unsupported API command\n"));
3434 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3435 int,int,char **,char **,int *,int *);
3436 BOOL auth_user; /* Deny anonymous access? */
3437 } api_commands[] = {
3438 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3439 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3440 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3441 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3442 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3443 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3444 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3445 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3446 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3447 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3448 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3449 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3450 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3451 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3452 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3453 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3454 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3455 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3456 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3457 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3458 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3459 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3460 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3461 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3462 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3463 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3464 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3465 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3466 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3467 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3468 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3469 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3470 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3471 {NULL, -1, api_Unsupported}};
3473 /* The following RAP calls are not implemented by Samba:
3475 RAP_WFileEnum2 - anon not OK
3478 /****************************************************************************
3479 Handle remote api calls
3480 ****************************************************************************/
3482 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3483 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3487 char *rparam = NULL;
3494 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3498 api_command = SVAL(params,0);
3500 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3503 skip_string(params+2,1),
3504 tdscnt,tpscnt,mdrcnt,mprcnt));
3506 for (i=0;api_commands[i].name;i++) {
3507 if (api_commands[i].id == api_command && api_commands[i].fn) {
3508 DEBUG(3,("Doing %s\n",api_commands[i].name));
3513 /* Check whether this api call can be done anonymously */
3515 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3516 user_struct *user = get_valid_user_struct(vuid);
3518 if (!user || user->guest)
3519 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3522 rdata = (char *)malloc(1024);
3524 memset(rdata,'\0',1024);
3526 rparam = (char *)malloc(1024);
3528 memset(rparam,'\0',1024);
3530 if(!rdata || !rparam) {
3531 DEBUG(0,("api_reply: malloc fail !\n"));
3535 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3536 &rdata,&rparam,&rdata_len,&rparam_len);
3539 if (rdata_len > mdrcnt ||
3540 rparam_len > mprcnt) {
3541 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3542 &rdata,&rparam,&rdata_len,&rparam_len);
3545 /* if we get False back then it's actually unsupported */
3547 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3548 &rdata,&rparam,&rdata_len,&rparam_len);
3550 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);