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, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1128 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, 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 the list of available shares.
1470 This function is the server side of the NetShareEnum() RAP call.
1471 It fills the return buffer with share names and share comments.
1472 Note that the return buffer normally (in all known cases) allows only
1473 twelve byte strings for share names (plus one for a nul terminator).
1474 Share names longer than 12 bytes must be skipped.
1475 ****************************************************************************/
1476 static BOOL api_RNetShareEnum( connection_struct *conn,
1487 char *str1 = param+2;
1488 char *str2 = skip_string(str1,1);
1489 char *p = skip_string(str2,1);
1490 int uLevel = SVAL(p,0);
1491 int buf_len = SVAL(p,2);
1493 int count=lp_numservices();
1494 int total=0,counted=0;
1495 BOOL missed = False;
1497 int data_len, fixed_len, string_len;
1498 int f_len = 0, s_len = 0;
1500 if (!prefix_ok(str1,"WrLeh")) return False;
1501 if (!check_share_info(uLevel,str2)) return False;
1503 data_len = fixed_len = string_len = 0;
1504 for (i=0;i<count;i++)
1505 if( lp_browseable( i )
1507 && (strlen( lp_servicename( i ) ) < 13) ) /* Maximum name length. */
1510 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1511 if (data_len <= buf_len)
1515 string_len += s_len;
1520 *rdata_len = fixed_len + string_len;
1521 *rdata = REALLOC(*rdata,*rdata_len);
1522 memset(*rdata,0,*rdata_len);
1524 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1528 for( i = 0; i < count; i++ )
1530 if( lp_browseable( i )
1532 && (strlen( lp_servicename( i ) ) < 13) )
1534 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1540 *rparam = REALLOC(*rparam,*rparam_len);
1541 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1543 SSVAL(*rparam,4,counted);
1544 SSVAL(*rparam,6,total);
1546 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1547 counted,total,uLevel,
1548 buf_len,*rdata_len,mdrcnt));
1550 } /* api_RNetShareEnum */
1552 /****************************************************************************
1554 ****************************************************************************/
1555 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1556 int mdrcnt,int mprcnt,
1557 char **rdata,char **rparam,
1558 int *rdata_len,int *rparam_len)
1560 char *str1 = param+2;
1561 char *str2 = skip_string(str1,1);
1562 char *p = skip_string(str2,1);
1563 int uLevel = SVAL(p,0);
1567 char *command, *cmdname;
1568 unsigned int offset;
1572 /* check it's a supported varient */
1573 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1574 if (!check_share_info(uLevel,str2)) return False;
1575 if (uLevel != 2) return False;
1577 pull_ascii_fstring(sharename,data);
1578 snum = find_service(sharename);
1579 if (snum >= 0) { /* already exists */
1584 /* only support disk share adds */
1585 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1587 offset = IVAL(data, 16);
1588 if (offset >= mdrcnt) {
1589 res = ERRinvalidparam;
1592 pull_ascii_fstring(comment, offset? (data+offset) : "");
1594 offset = IVAL(data, 26);
1595 if (offset >= mdrcnt) {
1596 res = ERRinvalidparam;
1599 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1601 string_replace(sharename, '"', ' ');
1602 string_replace(pathname, '"', ' ');
1603 string_replace(comment, '"', ' ');
1605 cmdname = lp_add_share_cmd();
1607 if (!cmdname || *cmdname == '\0') return False;
1609 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1610 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1613 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1614 if ((res = smbrun(command, NULL)) != 0) {
1615 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1621 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1623 } else return False;
1626 *rparam = REALLOC(*rparam,*rparam_len);
1627 SSVAL(*rparam,0,NERR_Success);
1628 SSVAL(*rparam,2,0); /* converter word */
1629 SSVAL(*rparam,4,*rdata_len);
1636 *rparam = REALLOC(*rparam,*rparam_len);
1638 SSVAL(*rparam,0,res);
1644 /****************************************************************************
1645 view list of groups available
1646 ****************************************************************************/
1647 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1648 int mdrcnt,int mprcnt,
1649 char **rdata,char **rparam,
1650 int *rdata_len,int *rparam_len)
1654 int resume_context, cli_buf_size;
1655 char *str1 = param+2;
1656 char *str2 = skip_string(str1,1);
1657 char *p = skip_string(str2,1);
1660 GROUP_MAP *group_list;
1663 if (strcmp(str1,"WrLeh") != 0)
1667 * W-> resume context (number of users to skip)
1668 * r -> return parameter pointer to receive buffer
1669 * L -> length of receive buffer
1670 * e -> return parameter number of entries
1671 * h -> return parameter total number of users
1673 if (strcmp("B21",str2) != 0)
1676 /* get list of domain groups SID_DOMAIN_GRP=2 */
1678 ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
1682 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1686 resume_context = SVAL(p,0);
1687 cli_buf_size=SVAL(p+2,0);
1688 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1690 *rdata_len = cli_buf_size;
1691 *rdata = REALLOC(*rdata,*rdata_len);
1695 for(i=resume_context; i<num_entries; i++) {
1696 char* name=group_list[i].nt_name;
1697 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1698 /* truncate the name at 21 chars. */
1699 memcpy(p, name, 21);
1700 DEBUG(10,("adding entry %d group %s\n", i, p));
1703 /* set overflow error */
1704 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1710 *rdata_len = PTR_DIFF(p,*rdata);
1713 *rparam = REALLOC(*rparam,*rparam_len);
1715 SSVAL(*rparam, 0, errflags);
1716 SSVAL(*rparam, 2, 0); /* converter word */
1717 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1718 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1723 /*******************************************************************
1724 get groups that a user is a member of
1725 ******************************************************************/
1726 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1727 int mdrcnt,int mprcnt,
1728 char **rdata,char **rparam,
1729 int *rdata_len,int *rparam_len)
1731 char *str1 = param+2;
1732 char *str2 = skip_string(str1,1);
1733 char *UserName = skip_string(str2,1);
1734 char *p = skip_string(UserName,1);
1735 int uLevel = SVAL(p,0);
1736 const char *level_string;
1738 SAM_ACCOUNT *sampw = NULL;
1740 DOM_GID *gids = NULL;
1745 enum SID_NAME_USE grp_type;
1746 DOM_SID sid, dom_sid;
1749 *rparam = REALLOC(*rparam,*rparam_len);
1751 /* check it's a supported varient */
1753 if ( strcmp(str1,"zWrLeh") != 0 )
1758 level_string = "B21";
1764 if (strcmp(level_string,str2) != 0)
1767 *rdata_len = mdrcnt + 1024;
1768 *rdata = REALLOC(*rdata,*rdata_len);
1770 SSVAL(*rparam,0,NERR_Success);
1771 SSVAL(*rparam,2,0); /* converter word */
1775 /* Lookup the user information; This should only be one of
1776 our accounts (not remote domains) */
1778 pdb_init_sam( &sampw );
1780 become_root(); /* ROOT BLOCK */
1782 if ( !pdb_getsampwnam(sampw, UserName) )
1785 /* this next set of code is horribly inefficient, but since
1786 it is rarely called, I'm going to leave it like this since
1787 it easier to follow --jerry */
1789 /* get the list of group SIDs */
1791 if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
1792 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1796 /* convert to names (we don't support universal groups so the domain
1797 can only be ours) */
1799 sid_copy( &dom_sid, get_global_sam_sid() );
1800 for (i=0; i<num_groups; i++) {
1802 /* make the DOM_GID into a DOM_SID and then lookup
1805 sid_copy( &sid, &dom_sid );
1806 sid_append_rid( &sid, gids[i].g_rid );
1808 if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
1809 pstrcpy(p, grp_name);
1815 *rdata_len = PTR_DIFF(p,*rdata);
1817 SSVAL(*rparam,4,count); /* is this right?? */
1818 SSVAL(*rparam,6,count); /* is this right?? */
1823 unbecome_root(); /* END ROOT BLOCK */
1825 pdb_free_sam( &sampw );
1830 /*******************************************************************
1832 ******************************************************************/
1833 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1834 int mdrcnt,int mprcnt,
1835 char **rdata,char **rparam,
1836 int *rdata_len,int *rparam_len)
1838 SAM_ACCOUNT *pwd=NULL;
1842 int resume_context, cli_buf_size;
1844 char *str1 = param+2;
1845 char *str2 = skip_string(str1,1);
1846 char *p = skip_string(str2,1);
1848 if (strcmp(str1,"WrLeh") != 0)
1851 * W-> resume context (number of users to skip)
1852 * r -> return parameter pointer to receive buffer
1853 * L -> length of receive buffer
1854 * e -> return parameter number of entries
1855 * h -> return parameter total number of users
1858 resume_context = SVAL(p,0);
1859 cli_buf_size=SVAL(p+2,0);
1860 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1863 *rparam = REALLOC(*rparam,*rparam_len);
1865 /* check it's a supported varient */
1866 if (strcmp("B21",str2) != 0)
1869 *rdata_len = cli_buf_size;
1870 *rdata = REALLOC(*rdata,*rdata_len);
1874 /* to get user list enumerations for NetUserEnum in B21 format */
1877 /* Open the passgrp file - not for update. */
1879 if(!pdb_setsampwent(False)) {
1880 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1884 errflags=NERR_Success;
1886 while ( pdb_getsampwent(pwd) ) {
1887 const char *name=pdb_get_username(pwd);
1888 if ((name) && (*(name+strlen(name)-1)!='$')) {
1890 if(count_total>=resume_context) {
1891 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1893 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1897 /* set overflow error */
1898 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1911 *rdata_len = PTR_DIFF(p,*rdata);
1913 SSVAL(*rparam,0,errflags);
1914 SSVAL(*rparam,2,0); /* converter word */
1915 SSVAL(*rparam,4,count_sent); /* is this right?? */
1916 SSVAL(*rparam,6,count_total); /* is this right?? */
1923 /****************************************************************************
1924 get the time of day info
1925 ****************************************************************************/
1926 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1927 int mdrcnt,int mprcnt,
1928 char **rdata,char **rparam,
1929 int *rdata_len,int *rparam_len)
1933 *rparam = REALLOC(*rparam,*rparam_len);
1936 *rdata = REALLOC(*rdata,*rdata_len);
1938 SSVAL(*rparam,0,NERR_Success);
1939 SSVAL(*rparam,2,0); /* converter word */
1945 time_t unixdate = time(NULL);
1947 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1948 by NT in a "net time" operation,
1949 it seems to ignore the one below */
1951 /* the client expects to get localtime, not GMT, in this bit
1952 (I think, this needs testing) */
1953 t = LocalTime(&unixdate);
1955 SIVAL(p,4,0); /* msecs ? */
1956 SCVAL(p,8,t->tm_hour);
1957 SCVAL(p,9,t->tm_min);
1958 SCVAL(p,10,t->tm_sec);
1959 SCVAL(p,11,0); /* hundredths of seconds */
1960 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1961 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1962 SCVAL(p,16,t->tm_mday);
1963 SCVAL(p,17,t->tm_mon + 1);
1964 SSVAL(p,18,1900+t->tm_year);
1965 SCVAL(p,20,t->tm_wday);
1972 /****************************************************************************
1973 Set the user password.
1974 *****************************************************************************/
1976 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1977 int mdrcnt,int mprcnt,
1978 char **rdata,char **rparam,
1979 int *rdata_len,int *rparam_len)
1981 char *p = skip_string(param+2,2);
1983 fstring pass1,pass2;
1985 pull_ascii_fstring(user,p);
1987 p = skip_string(p,1);
1989 memset(pass1,'\0',sizeof(pass1));
1990 memset(pass2,'\0',sizeof(pass2));
1992 memcpy(pass2,p+16,16);
1995 *rparam = REALLOC(*rparam,*rparam_len);
1999 SSVAL(*rparam,0,NERR_badpass);
2000 SSVAL(*rparam,2,0); /* converter word */
2002 DEBUG(3,("Set password for <%s>\n",user));
2005 * Attempt to verify the old password against smbpasswd entries
2006 * Win98 clients send old and new password in plaintext for this call.
2010 auth_serversupplied_info *server_info = NULL;
2011 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2013 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2016 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2017 SSVAL(*rparam,0,NERR_Success);
2021 free_server_info(&server_info);
2023 data_blob_clear_free(&password);
2027 * If the plaintext change failed, attempt
2028 * the old encrypted method. NT will generate this
2029 * after trying the samr method. Note that this
2030 * method is done as a last resort as this
2031 * password change method loses the NT password hash
2032 * and cannot change the UNIX password as no plaintext
2036 if(SVAL(*rparam,0) != NERR_Success) {
2037 SAM_ACCOUNT *hnd = NULL;
2039 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2041 if (change_lanman_password(hnd,(uchar *)pass2)) {
2042 SSVAL(*rparam,0,NERR_Success);
2049 memset((char *)pass1,'\0',sizeof(fstring));
2050 memset((char *)pass2,'\0',sizeof(fstring));
2055 /****************************************************************************
2056 Set the user password (SamOEM version - gets plaintext).
2057 ****************************************************************************/
2059 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2060 int mdrcnt,int mprcnt,
2061 char **rdata,char **rparam,
2062 int *rdata_len,int *rparam_len)
2065 char *p = param + 2;
2067 *rparam = REALLOC(*rparam,*rparam_len);
2071 SSVAL(*rparam,0,NERR_badpass);
2074 * Check the parameter definition is correct.
2077 if(!strequal(param + 2, "zsT")) {
2078 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2081 p = skip_string(p, 1);
2083 if(!strequal(p, "B516B16")) {
2084 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2087 p = skip_string(p,1);
2088 p += pull_ascii_fstring(user,p);
2090 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2093 * Pass the user through the NT -> unix user mapping
2097 (void)map_username(user);
2099 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2100 SSVAL(*rparam,0,NERR_Success);
2106 /****************************************************************************
2109 ****************************************************************************/
2110 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2111 int mdrcnt,int mprcnt,
2112 char **rdata,char **rparam,
2113 int *rdata_len,int *rparam_len)
2115 int function = SVAL(param,0);
2116 char *str1 = param+2;
2117 char *str2 = skip_string(str1,1);
2118 char *p = skip_string(str2,1);
2122 extern struct current_user current_user;
2123 WERROR werr = WERR_OK;
2125 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2128 /* check it's a supported varient */
2129 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2133 *rparam = REALLOC(*rparam,*rparam_len);
2136 if (!print_job_exists(snum, jobid)) {
2137 errcode = NERR_JobNotFound;
2141 errcode = NERR_notsupported;
2144 case 81: /* delete */
2145 if (print_job_delete(¤t_user, snum, jobid, &werr))
2146 errcode = NERR_Success;
2148 case 82: /* pause */
2149 if (print_job_pause(¤t_user, snum, jobid, &werr))
2150 errcode = NERR_Success;
2152 case 83: /* resume */
2153 if (print_job_resume(¤t_user, snum, jobid, &werr))
2154 errcode = NERR_Success;
2158 if (!W_ERROR_IS_OK(werr))
2159 errcode = W_ERROR_V(werr);
2162 SSVAL(*rparam,0,errcode);
2163 SSVAL(*rparam,2,0); /* converter word */
2168 /****************************************************************************
2169 Purge a print queue - or pause or resume it.
2170 ****************************************************************************/
2171 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2172 int mdrcnt,int mprcnt,
2173 char **rdata,char **rparam,
2174 int *rdata_len,int *rparam_len)
2176 int function = SVAL(param,0);
2177 char *str1 = param+2;
2178 char *str2 = skip_string(str1,1);
2179 char *QueueName = skip_string(str2,1);
2180 int errcode = NERR_notsupported;
2182 WERROR werr = WERR_OK;
2183 extern struct current_user current_user;
2185 /* check it's a supported varient */
2186 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2190 *rparam = REALLOC(*rparam,*rparam_len);
2193 snum = print_queue_snum(QueueName);
2196 errcode = NERR_JobNotFound;
2201 case 74: /* Pause queue */
2202 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2204 case 75: /* Resume queue */
2205 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2207 case 103: /* Purge */
2208 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2212 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2215 SSVAL(*rparam,0,errcode);
2216 SSVAL(*rparam,2,0); /* converter word */
2222 /****************************************************************************
2223 set the property of a print job (undocumented?)
2224 ? function = 0xb -> set name of print job
2225 ? function = 0x6 -> move print job up/down
2226 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2227 or <WWsTP> <WB21BB16B10zWWzDDz>
2228 ****************************************************************************/
2229 static int check_printjob_info(struct pack_desc* desc,
2230 int uLevel, char* id)
2232 desc->subformat = NULL;
2234 case 0: desc->format = "W"; break;
2235 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2236 case 2: desc->format = "WWzWWDDzz"; break;
2237 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2238 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2239 default: return False;
2241 if (strcmp(desc->format,id) != 0) return False;
2245 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2246 int mdrcnt,int mprcnt,
2247 char **rdata,char **rparam,
2248 int *rdata_len,int *rparam_len)
2250 struct pack_desc desc;
2251 char *str1 = param+2;
2252 char *str2 = skip_string(str1,1);
2253 char *p = skip_string(str2,1);
2256 int uLevel = SVAL(p,2);
2257 int function = SVAL(p,4);
2260 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2263 *rparam = REALLOC(*rparam,*rparam_len);
2267 /* check it's a supported varient */
2268 if ((strcmp(str1,"WWsTP")) ||
2269 (!check_printjob_info(&desc,uLevel,str2)))
2272 if (!print_job_exists(snum, jobid)) {
2273 errcode=NERR_JobNotFound;
2277 errcode = NERR_notsupported;
2281 /* change job place in the queue,
2282 data gives the new place */
2283 place = SVAL(data,0);
2284 if (print_job_set_place(snum, jobid, place)) {
2285 errcode=NERR_Success;
2290 /* change print job name, data gives the name */
2291 if (print_job_set_name(snum, jobid, data)) {
2292 errcode=NERR_Success;
2301 SSVALS(*rparam,0,errcode);
2302 SSVAL(*rparam,2,0); /* converter word */
2308 /****************************************************************************
2309 get info about the server
2310 ****************************************************************************/
2311 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2312 int mdrcnt,int mprcnt,
2313 char **rdata,char **rparam,
2314 int *rdata_len,int *rparam_len)
2316 char *str1 = param+2;
2317 char *str2 = skip_string(str1,1);
2318 char *p = skip_string(str2,1);
2319 int uLevel = SVAL(p,0);
2323 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2325 /* check it's a supported varient */
2326 if (!prefix_ok(str1,"WrLh")) return False;
2329 if (strcmp(str2,"B16") != 0) return False;
2333 if (strcmp(str2,"B16BBDz") != 0) return False;
2337 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2342 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2347 if (strcmp(str2,"DN") != 0) return False;
2351 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2354 default: return False;
2357 *rdata_len = mdrcnt;
2358 *rdata = REALLOC(*rdata,*rdata_len);
2361 p2 = p + struct_len;
2363 srvstr_push(NULL, p,local_machine,16,
2364 STR_ASCII|STR_UPPER|STR_TERMINATE);
2369 struct srv_info_struct *servers=NULL;
2372 uint32 servertype= lp_default_server_announce();
2374 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2376 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2377 for (i=0;i<count;i++) {
2378 if (strequal(servers[i].name,local_machine)) {
2379 servertype = servers[i].type;
2380 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2386 SCVAL(p,0,lp_major_announce_version());
2387 SCVAL(p,1,lp_minor_announce_version());
2388 SIVAL(p,2,servertype);
2390 if (mdrcnt == struct_len) {
2393 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2394 standard_sub_conn(conn,comment,sizeof(comment));
2395 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2396 p2 = skip_string(p2,1);
2401 return False; /* not yet implemented */
2404 *rdata_len = PTR_DIFF(p2,*rdata);
2407 *rparam = REALLOC(*rparam,*rparam_len);
2408 SSVAL(*rparam,0,NERR_Success);
2409 SSVAL(*rparam,2,0); /* converter word */
2410 SSVAL(*rparam,4,*rdata_len);
2416 /****************************************************************************
2417 get info about the server
2418 ****************************************************************************/
2419 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2420 int mdrcnt,int mprcnt,
2421 char **rdata,char **rparam,
2422 int *rdata_len,int *rparam_len)
2424 char *str1 = param+2;
2425 char *str2 = skip_string(str1,1);
2426 char *p = skip_string(str2,1);
2428 extern userdom_struct current_user_info;
2429 int level = SVAL(p,0);
2431 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2434 *rparam = REALLOC(*rparam,*rparam_len);
2436 /* check it's a supported varient */
2437 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2440 *rdata_len = mdrcnt + 1024;
2441 *rdata = REALLOC(*rdata,*rdata_len);
2443 SSVAL(*rparam,0,NERR_Success);
2444 SSVAL(*rparam,2,0); /* converter word */
2450 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2451 pstrcpy(p2,local_machine);
2453 p2 = skip_string(p2,1);
2456 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2457 pstrcpy(p2,current_user_info.smb_name);
2458 p2 = skip_string(p2,1);
2461 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2462 pstrcpy(p2,lp_workgroup());
2464 p2 = skip_string(p2,1);
2467 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2468 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2471 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2472 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2473 p2 = skip_string(p2,1);
2476 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2478 p2 = skip_string(p2,1);
2481 *rdata_len = PTR_DIFF(p2,*rdata);
2483 SSVAL(*rparam,4,*rdata_len);
2488 /****************************************************************************
2489 get info about a user
2491 struct user_info_11 {
2492 char usri11_name[21]; 0-20
2494 char *usri11_comment; 22-25
2495 char *usri11_usr_comment; 26-29
2496 unsigned short usri11_priv; 30-31
2497 unsigned long usri11_auth_flags; 32-35
2498 long usri11_password_age; 36-39
2499 char *usri11_homedir; 40-43
2500 char *usri11_parms; 44-47
2501 long usri11_last_logon; 48-51
2502 long usri11_last_logoff; 52-55
2503 unsigned short usri11_bad_pw_count; 56-57
2504 unsigned short usri11_num_logons; 58-59
2505 char *usri11_logon_server; 60-63
2506 unsigned short usri11_country_code; 64-65
2507 char *usri11_workstations; 66-69
2508 unsigned long usri11_max_storage; 70-73
2509 unsigned short usri11_units_per_week; 74-75
2510 unsigned char *usri11_logon_hours; 76-79
2511 unsigned short usri11_code_page; 80-81
2516 usri11_name specifies the user name for which information is retireved
2518 usri11_pad aligns the next data structure element to a word boundary
2520 usri11_comment is a null terminated ASCII comment
2522 usri11_user_comment is a null terminated ASCII comment about the user
2524 usri11_priv specifies the level of the privilege assigned to the user.
2525 The possible values are:
2527 Name Value Description
2528 USER_PRIV_GUEST 0 Guest privilege
2529 USER_PRIV_USER 1 User privilege
2530 USER_PRV_ADMIN 2 Administrator privilege
2532 usri11_auth_flags specifies the account operator privileges. The
2533 possible values are:
2535 Name Value Description
2536 AF_OP_PRINT 0 Print operator
2539 Leach, Naik [Page 28]
2543 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2546 AF_OP_COMM 1 Communications operator
2547 AF_OP_SERVER 2 Server operator
2548 AF_OP_ACCOUNTS 3 Accounts operator
2551 usri11_password_age specifies how many seconds have elapsed since the
2552 password was last changed.
2554 usri11_home_dir points to a null terminated ASCII string that contains
2555 the path name of the user's home directory.
2557 usri11_parms points to a null terminated ASCII string that is set
2558 aside for use by applications.
2560 usri11_last_logon specifies the time when the user last logged on.
2561 This value is stored as the number of seconds elapsed since
2562 00:00:00, January 1, 1970.
2564 usri11_last_logoff specifies the time when the user last logged off.
2565 This value is stored as the number of seconds elapsed since
2566 00:00:00, January 1, 1970. A value of 0 means the last logoff
2569 usri11_bad_pw_count specifies the number of incorrect passwords
2570 entered since the last successful logon.
2572 usri11_log1_num_logons specifies the number of times this user has
2573 logged on. A value of -1 means the number of logons is unknown.
2575 usri11_logon_server points to a null terminated ASCII string that
2576 contains the name of the server to which logon requests are sent.
2577 A null string indicates logon requests should be sent to the
2580 usri11_country_code specifies the country code for the user's language
2583 usri11_workstations points to a null terminated ASCII string that
2584 contains the names of workstations the user may log on from.
2585 There may be up to 8 workstations, with the names separated by
2586 commas. A null strings indicates there are no restrictions.
2588 usri11_max_storage specifies the maximum amount of disk space the user
2589 can occupy. A value of 0xffffffff indicates there are no
2592 usri11_units_per_week specifies the equal number of time units into
2593 which a week is divided. This value must be equal to 168.
2595 usri11_logon_hours points to a 21 byte (168 bits) string that
2596 specifies the time during which the user can log on. Each bit
2597 represents one unique hour in a week. The first bit (bit 0, word
2598 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2602 Leach, Naik [Page 29]
2606 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2609 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2610 are no restrictions.
2612 usri11_code_page specifies the code page for the user's language of
2615 All of the pointers in this data structure need to be treated
2616 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2617 to be ignored. The converter word returned in the parameters section
2618 needs to be subtracted from the lower 16 bits to calculate an offset
2619 into the return buffer where this ASCII string resides.
2621 There is no auxiliary data in the response.
2623 ****************************************************************************/
2625 #define usri11_name 0
2626 #define usri11_pad 21
2627 #define usri11_comment 22
2628 #define usri11_usr_comment 26
2629 #define usri11_full_name 30
2630 #define usri11_priv 34
2631 #define usri11_auth_flags 36
2632 #define usri11_password_age 40
2633 #define usri11_homedir 44
2634 #define usri11_parms 48
2635 #define usri11_last_logon 52
2636 #define usri11_last_logoff 56
2637 #define usri11_bad_pw_count 60
2638 #define usri11_num_logons 62
2639 #define usri11_logon_server 64
2640 #define usri11_country_code 68
2641 #define usri11_workstations 70
2642 #define usri11_max_storage 74
2643 #define usri11_units_per_week 78
2644 #define usri11_logon_hours 80
2645 #define usri11_code_page 84
2646 #define usri11_end 86
2648 #define USER_PRIV_GUEST 0
2649 #define USER_PRIV_USER 1
2650 #define USER_PRIV_ADMIN 2
2652 #define AF_OP_PRINT 0
2653 #define AF_OP_COMM 1
2654 #define AF_OP_SERVER 2
2655 #define AF_OP_ACCOUNTS 3
2658 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2659 int mdrcnt,int mprcnt,
2660 char **rdata,char **rparam,
2661 int *rdata_len,int *rparam_len)
2663 char *str1 = param+2;
2664 char *str2 = skip_string(str1,1);
2665 char *UserName = skip_string(str2,1);
2666 char *p = skip_string(UserName,1);
2667 int uLevel = SVAL(p,0);
2669 const char *level_string;
2671 /* get NIS home of a previously validated user - simeon */
2672 /* With share level security vuid will always be zero.
2673 Don't depend on vuser being non-null !!. JRA */
2674 user_struct *vuser = get_valid_user_struct(vuid);
2676 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2677 vuser->user.unix_name));
2680 *rparam = REALLOC(*rparam,*rparam_len);
2682 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2684 /* check it's a supported variant */
2685 if (strcmp(str1,"zWrLh") != 0) return False;
2688 case 0: level_string = "B21"; break;
2689 case 1: level_string = "B21BB16DWzzWz"; break;
2690 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2691 case 10: level_string = "B21Bzzz"; break;
2692 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2693 default: return False;
2696 if (strcmp(level_string,str2) != 0) return False;
2698 *rdata_len = mdrcnt + 1024;
2699 *rdata = REALLOC(*rdata,*rdata_len);
2701 SSVAL(*rparam,0,NERR_Success);
2702 SSVAL(*rparam,2,0); /* converter word */
2705 p2 = p + usri11_end;
2708 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2712 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2717 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2718 pstrcpy(p2,"Comment");
2719 p2 = skip_string(p2,1);
2721 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2722 pstrcpy(p2,"UserComment");
2723 p2 = skip_string(p2,1);
2725 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2726 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2727 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2728 p2 = skip_string(p2,1);
2731 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2733 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2734 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2735 SIVALS(p,usri11_password_age,-1); /* password age */
2736 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2737 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2738 p2 = skip_string(p2,1);
2739 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2741 p2 = skip_string(p2,1);
2742 SIVAL(p,usri11_last_logon,0); /* last logon */
2743 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2744 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2745 SSVALS(p,usri11_num_logons,-1); /* num logons */
2746 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2747 pstrcpy(p2,"\\\\*");
2748 p2 = skip_string(p2,1);
2749 SSVAL(p,usri11_country_code,0); /* country code */
2751 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2753 p2 = skip_string(p2,1);
2755 SIVALS(p,usri11_max_storage,-1); /* max storage */
2756 SSVAL(p,usri11_units_per_week,168); /* units per week */
2757 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2759 /* a simple way to get logon hours at all times. */
2761 SCVAL(p2,21,0); /* fix zero termination */
2762 p2 = skip_string(p2,1);
2764 SSVAL(p,usri11_code_page,0); /* code page */
2766 if (uLevel == 1 || uLevel == 2)
2768 memset(p+22,' ',16); /* password */
2769 SIVALS(p,38,-1); /* password age */
2771 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2772 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2773 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2774 p2 = skip_string(p2,1);
2775 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2777 SSVAL(p,52,0); /* flags */
2778 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2779 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2780 p2 = skip_string(p2,1);
2783 SIVAL(p,60,0); /* auth_flags */
2784 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2785 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2786 p2 = skip_string(p2,1);
2787 SIVAL(p,68,0); /* urs_comment */
2788 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2790 p2 = skip_string(p2,1);
2791 SIVAL(p,76,0); /* workstations */
2792 SIVAL(p,80,0); /* last_logon */
2793 SIVAL(p,84,0); /* last_logoff */
2794 SIVALS(p,88,-1); /* acct_expires */
2795 SIVALS(p,92,-1); /* max_storage */
2796 SSVAL(p,96,168); /* units_per_week */
2797 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2800 SSVALS(p,102,-1); /* bad_pw_count */
2801 SSVALS(p,104,-1); /* num_logons */
2802 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2803 pstrcpy(p2,"\\\\%L");
2804 standard_sub_conn(conn, p2,0);
2805 p2 = skip_string(p2,1);
2806 SSVAL(p,110,49); /* country_code */
2807 SSVAL(p,112,860); /* code page */
2811 *rdata_len = PTR_DIFF(p2,*rdata);
2813 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2818 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2819 int mdrcnt,int mprcnt,
2820 char **rdata,char **rparam,
2821 int *rdata_len,int *rparam_len)
2823 char *str1 = param+2;
2824 char *str2 = skip_string(str1,1);
2825 char *p = skip_string(str2,1);
2827 struct pack_desc desc;
2829 /* With share level security vuid will always be zero.
2830 Don't depend on vuser being non-null !!. JRA */
2831 user_struct *vuser = get_valid_user_struct(vuid);
2833 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2834 vuser->user.unix_name));
2839 memset((char *)&desc,'\0',sizeof(desc));
2841 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2843 /* check it's a supported varient */
2844 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2845 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2846 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2848 desc.buflen = mdrcnt;
2849 desc.subformat = NULL;
2852 if (init_package(&desc,1,0))
2854 PACKI(&desc,"W",0); /* code */
2855 PACKS(&desc,"B21",name); /* eff. name */
2856 PACKS(&desc,"B",""); /* pad */
2858 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2859 PACKI(&desc,"D",0); /* auth flags XXX */
2860 PACKI(&desc,"W",0); /* num logons */
2861 PACKI(&desc,"W",0); /* bad pw count */
2862 PACKI(&desc,"D",0); /* last logon */
2863 PACKI(&desc,"D",-1); /* last logoff */
2864 PACKI(&desc,"D",-1); /* logoff time */
2865 PACKI(&desc,"D",-1); /* kickoff time */
2866 PACKI(&desc,"D",0); /* password age */
2867 PACKI(&desc,"D",0); /* password can change */
2868 PACKI(&desc,"D",-1); /* password must change */
2871 fstrcpy(mypath,"\\\\");
2872 fstrcat(mypath,local_machine);
2874 PACKS(&desc,"z",mypath); /* computer */
2876 PACKS(&desc,"z",lp_workgroup());/* domain */
2878 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2880 PACKI(&desc,"D",0x00000000); /* reserved */
2883 *rdata_len = desc.usedlen;
2885 *rparam = REALLOC(*rparam,*rparam_len);
2886 SSVALS(*rparam,0,desc.errcode);
2888 SSVAL(*rparam,4,desc.neededlen);
2890 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2895 /****************************************************************************
2896 api_WAccessGetUserPerms
2897 ****************************************************************************/
2898 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2899 int mdrcnt,int mprcnt,
2900 char **rdata,char **rparam,
2901 int *rdata_len,int *rparam_len)
2903 char *str1 = param+2;
2904 char *str2 = skip_string(str1,1);
2905 char *user = skip_string(str2,1);
2906 char *resource = skip_string(user,1);
2908 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2910 /* check it's a supported varient */
2911 if (strcmp(str1,"zzh") != 0) return False;
2912 if (strcmp(str2,"") != 0) return False;
2915 *rparam = REALLOC(*rparam,*rparam_len);
2916 SSVALS(*rparam,0,0); /* errorcode */
2917 SSVAL(*rparam,2,0); /* converter word */
2918 SSVAL(*rparam,4,0x7f); /* permission flags */
2923 /****************************************************************************
2924 api_WPrintJobEnumerate
2925 ****************************************************************************/
2926 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2927 int mdrcnt,int mprcnt,
2928 char **rdata,char **rparam,
2929 int *rdata_len,int *rparam_len)
2931 char *str1 = param+2;
2932 char *str2 = skip_string(str1,1);
2933 char *p = skip_string(str2,1);
2939 struct pack_desc desc;
2940 print_queue_struct *queue=NULL;
2941 print_status_struct status;
2946 memset((char *)&desc,'\0',sizeof(desc));
2947 memset((char *)&status,'\0',sizeof(status));
2949 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2951 /* check it's a supported varient */
2952 if (strcmp(str1,"WWrLh") != 0) return False;
2953 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2955 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2958 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2960 count = print_queue_status(snum,&queue,&status);
2961 for (i = 0; i < count; i++) {
2962 if (queue[i].job == jobid) break;
2966 *rdata = REALLOC(*rdata,mdrcnt);
2968 desc.buflen = mdrcnt;
2971 * Don't return data but need to get correct length
2972 * init_package will return wrong size if buflen=0
2974 desc.buflen = getlen(desc.format);
2975 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2978 if (init_package(&desc,1,0)) {
2980 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2981 *rdata_len = desc.usedlen;
2984 desc.errcode = NERR_JobNotFound;
2990 *rparam = REALLOC(*rparam,*rparam_len);
2991 SSVALS(*rparam,0,desc.errcode);
2993 SSVAL(*rparam,4,desc.neededlen);
2998 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3002 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3003 int mdrcnt,int mprcnt,
3004 char **rdata,char **rparam,
3005 int *rdata_len,int *rparam_len)
3007 char *str1 = param+2;
3008 char *str2 = skip_string(str1,1);
3009 char *p = skip_string(str2,1);
3015 struct pack_desc desc;
3016 print_queue_struct *queue=NULL;
3017 print_status_struct status;
3019 memset((char *)&desc,'\0',sizeof(desc));
3020 memset((char *)&status,'\0',sizeof(status));
3022 p = skip_string(p,1);
3025 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3027 /* check it's a supported variant */
3028 if (strcmp(str1,"zWrLeh") != 0) return False;
3029 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3030 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3032 snum = lp_servicenumber(name);
3033 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3034 int pnum = lp_servicenumber(PRINTERS_NAME);
3036 lp_add_printer(name,pnum);
3037 snum = lp_servicenumber(name);
3041 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3043 count = print_queue_status(snum,&queue,&status);
3044 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3046 desc.buflen = mdrcnt;
3048 if (init_package(&desc,count,0)) {
3050 for (i = 0; i < count; i++) {
3051 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3052 if (desc.errcode == NERR_Success) succnt = i+1;
3056 *rdata_len = desc.usedlen;
3059 *rparam = REALLOC(*rparam,*rparam_len);
3060 SSVALS(*rparam,0,desc.errcode);
3062 SSVAL(*rparam,4,succnt);
3063 SSVAL(*rparam,6,count);
3067 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3071 static int check_printdest_info(struct pack_desc* desc,
3072 int uLevel, char* id)
3074 desc->subformat = NULL;
3076 case 0: desc->format = "B9"; break;
3077 case 1: desc->format = "B9B21WWzW"; break;
3078 case 2: desc->format = "z"; break;
3079 case 3: desc->format = "zzzWWzzzWW"; break;
3080 default: return False;
3082 if (strcmp(desc->format,id) != 0) return False;
3086 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3087 struct pack_desc* desc)
3090 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3091 buf[sizeof(buf)-1] = 0;
3094 PACKS(desc,"B9",buf); /* szName */
3096 PACKS(desc,"B21",""); /* szUserName */
3097 PACKI(desc,"W",0); /* uJobId */
3098 PACKI(desc,"W",0); /* fsStatus */
3099 PACKS(desc,"z",""); /* pszStatus */
3100 PACKI(desc,"W",0); /* time */
3103 if (uLevel == 2 || uLevel == 3) {
3104 PACKS(desc,"z",buf); /* pszPrinterName */
3106 PACKS(desc,"z",""); /* pszUserName */
3107 PACKS(desc,"z",""); /* pszLogAddr */
3108 PACKI(desc,"W",0); /* uJobId */
3109 PACKI(desc,"W",0); /* fsStatus */
3110 PACKS(desc,"z",""); /* pszStatus */
3111 PACKS(desc,"z",""); /* pszComment */
3112 PACKS(desc,"z","NULL"); /* pszDrivers */
3113 PACKI(desc,"W",0); /* time */
3114 PACKI(desc,"W",0); /* pad1 */
3119 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3120 int mdrcnt,int mprcnt,
3121 char **rdata,char **rparam,
3122 int *rdata_len,int *rparam_len)
3124 char *str1 = param+2;
3125 char *str2 = skip_string(str1,1);
3126 char *p = skip_string(str2,1);
3127 char* PrinterName = p;
3129 struct pack_desc desc;
3133 memset((char *)&desc,'\0',sizeof(desc));
3135 p = skip_string(p,1);
3138 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3140 /* check it's a supported varient */
3141 if (strcmp(str1,"zWrLh") != 0) return False;
3142 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3144 snum = lp_servicenumber(PrinterName);
3145 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3146 int pnum = lp_servicenumber(PRINTERS_NAME);
3148 lp_add_printer(PrinterName,pnum);
3149 snum = lp_servicenumber(PrinterName);
3155 desc.errcode = NERR_DestNotFound;
3160 *rdata = REALLOC(*rdata,mdrcnt);
3162 desc.buflen = mdrcnt;
3165 * Don't return data but need to get correct length
3166 * init_package will return wrong size if buflen=0
3168 desc.buflen = getlen(desc.format);
3169 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3171 if (init_package(&desc,1,0)) {
3172 fill_printdest_info(conn,snum,uLevel,&desc);
3174 *rdata_len = desc.usedlen;
3178 *rparam = REALLOC(*rparam,*rparam_len);
3179 SSVALS(*rparam,0,desc.errcode);
3181 SSVAL(*rparam,4,desc.neededlen);
3183 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3188 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3189 int mdrcnt,int mprcnt,
3190 char **rdata,char **rparam,
3191 int *rdata_len,int *rparam_len)
3193 char *str1 = param+2;
3194 char *str2 = skip_string(str1,1);
3195 char *p = skip_string(str2,1);
3199 struct pack_desc desc;
3200 int services = lp_numservices();
3202 memset((char *)&desc,'\0',sizeof(desc));
3206 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3208 /* check it's a supported varient */
3209 if (strcmp(str1,"WrLeh") != 0) return False;
3210 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3213 for (i = 0; i < services; i++)
3214 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3217 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3219 desc.buflen = mdrcnt;
3220 if (init_package(&desc,queuecnt,0)) {
3223 for (i = 0; i < services; i++) {
3224 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3225 fill_printdest_info(conn,i,uLevel,&desc);
3227 if (desc.errcode == NERR_Success) succnt = n;
3232 *rdata_len = desc.usedlen;
3235 *rparam = REALLOC(*rparam,*rparam_len);
3236 SSVALS(*rparam,0,desc.errcode);
3238 SSVAL(*rparam,4,succnt);
3239 SSVAL(*rparam,6,queuecnt);
3241 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3245 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3246 int mdrcnt,int mprcnt,
3247 char **rdata,char **rparam,
3248 int *rdata_len,int *rparam_len)
3250 char *str1 = param+2;
3251 char *str2 = skip_string(str1,1);
3252 char *p = skip_string(str2,1);
3255 struct pack_desc desc;
3257 memset((char *)&desc,'\0',sizeof(desc));
3261 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3263 /* check it's a supported varient */
3264 if (strcmp(str1,"WrLeh") != 0) return False;
3265 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3267 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3269 desc.buflen = mdrcnt;
3270 if (init_package(&desc,1,0)) {
3271 PACKS(&desc,"B41","NULL");
3274 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3276 *rdata_len = desc.usedlen;
3279 *rparam = REALLOC(*rparam,*rparam_len);
3280 SSVALS(*rparam,0,desc.errcode);
3282 SSVAL(*rparam,4,succnt);
3285 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3289 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3290 int mdrcnt,int mprcnt,
3291 char **rdata,char **rparam,
3292 int *rdata_len,int *rparam_len)
3294 char *str1 = param+2;
3295 char *str2 = skip_string(str1,1);
3296 char *p = skip_string(str2,1);
3299 struct pack_desc desc;
3301 memset((char *)&desc,'\0',sizeof(desc));
3305 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3307 /* check it's a supported varient */
3308 if (strcmp(str1,"WrLeh") != 0) return False;
3309 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3311 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3313 desc.buflen = mdrcnt;
3315 if (init_package(&desc,1,0)) {
3316 PACKS(&desc,"B13","lpd");
3319 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3321 *rdata_len = desc.usedlen;
3324 *rparam = REALLOC(*rparam,*rparam_len);
3325 SSVALS(*rparam,0,desc.errcode);
3327 SSVAL(*rparam,4,succnt);
3330 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3334 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3335 int mdrcnt,int mprcnt,
3336 char **rdata,char **rparam,
3337 int *rdata_len,int *rparam_len)
3339 char *str1 = param+2;
3340 char *str2 = skip_string(str1,1);
3341 char *p = skip_string(str2,1);
3344 struct pack_desc desc;
3346 memset((char *)&desc,'\0',sizeof(desc));
3350 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3352 /* check it's a supported varient */
3353 if (strcmp(str1,"WrLeh") != 0) return False;
3354 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3356 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3357 memset((char *)&desc,'\0',sizeof(desc));
3359 desc.buflen = mdrcnt;
3361 if (init_package(&desc,1,0)) {
3362 PACKS(&desc,"B13","lp0");
3365 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3367 *rdata_len = desc.usedlen;
3370 *rparam = REALLOC(*rparam,*rparam_len);
3371 SSVALS(*rparam,0,desc.errcode);
3373 SSVAL(*rparam,4,succnt);
3376 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3381 /****************************************************************************
3383 ****************************************************************************/
3384 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3385 int mdrcnt,int mprcnt,
3386 char **rdata,char **rparam,
3387 int *rdata_len,int *rparam_len)
3390 char *str1 = param+2;
3391 char *str2 = skip_string(str1,1);
3392 char *p = skip_string(str2,1);
3394 struct pack_desc desc;
3395 struct sessionid *session_list;
3396 int i, num_sessions;
3398 memset((char *)&desc,'\0',sizeof(desc));
3402 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3403 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3404 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3406 /* check it's a supported varient */
3407 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3408 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3410 num_sessions = list_sessions(&session_list);
3412 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3413 memset((char *)&desc,'\0',sizeof(desc));
3415 desc.buflen = mdrcnt;
3417 if (!init_package(&desc,num_sessions,0)) {
3421 for(i=0; i<num_sessions; i++) {
3422 PACKS(&desc, "z", session_list[i].remote_machine);
3423 PACKS(&desc, "z", session_list[i].username);
3424 PACKI(&desc, "W", 1); /* num conns */
3425 PACKI(&desc, "W", 0); /* num opens */
3426 PACKI(&desc, "W", 1); /* num users */
3427 PACKI(&desc, "D", 0); /* session time */
3428 PACKI(&desc, "D", 0); /* idle time */
3429 PACKI(&desc, "D", 0); /* flags */
3430 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3433 *rdata_len = desc.usedlen;
3436 *rparam = REALLOC(*rparam,*rparam_len);
3437 SSVALS(*rparam,0,desc.errcode);
3438 SSVAL(*rparam,2,0); /* converter */
3439 SSVAL(*rparam,4,num_sessions); /* count */
3441 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3446 /****************************************************************************
3447 The buffer was too small
3448 ****************************************************************************/
3450 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3451 int mdrcnt,int mprcnt,
3452 char **rdata,char **rparam,
3453 int *rdata_len,int *rparam_len)
3455 *rparam_len = MIN(*rparam_len,mprcnt);
3456 *rparam = REALLOC(*rparam,*rparam_len);
3460 SSVAL(*rparam,0,NERR_BufTooSmall);
3462 DEBUG(3,("Supplied buffer too small in API command\n"));
3468 /****************************************************************************
3469 The request is not supported
3470 ****************************************************************************/
3472 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3473 int mdrcnt,int mprcnt,
3474 char **rdata,char **rparam,
3475 int *rdata_len,int *rparam_len)
3478 *rparam = REALLOC(*rparam,*rparam_len);
3482 SSVAL(*rparam,0,NERR_notsupported);
3483 SSVAL(*rparam,2,0); /* converter word */
3485 DEBUG(3,("Unsupported API command\n"));
3497 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3498 int,int,char **,char **,int *,int *);
3499 BOOL auth_user; /* Deny anonymous access? */
3500 } api_commands[] = {
3501 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3502 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3503 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3504 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3505 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3506 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3507 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3508 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3509 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3510 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3511 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3512 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3513 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3514 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3515 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3516 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3517 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3518 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3519 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3520 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3521 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3522 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3523 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3524 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3525 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3526 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3527 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3528 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3529 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3530 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3531 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3532 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3533 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3534 {NULL, -1, api_Unsupported}};
3536 /* The following RAP calls are not implemented by Samba:
3538 RAP_WFileEnum2 - anon not OK
3541 /****************************************************************************
3542 Handle remote api calls
3543 ****************************************************************************/
3545 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3546 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3550 char *rparam = NULL;
3557 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3561 api_command = SVAL(params,0);
3563 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3566 skip_string(params+2,1),
3567 tdscnt,tpscnt,mdrcnt,mprcnt));
3569 for (i=0;api_commands[i].name;i++) {
3570 if (api_commands[i].id == api_command && api_commands[i].fn) {
3571 DEBUG(3,("Doing %s\n",api_commands[i].name));
3576 /* Check whether this api call can be done anonymously */
3578 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3579 user_struct *user = get_valid_user_struct(vuid);
3581 if (!user || user->guest)
3582 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3585 rdata = (char *)malloc(1024);
3587 memset(rdata,'\0',1024);
3589 rparam = (char *)malloc(1024);
3591 memset(rparam,'\0',1024);
3593 if(!rdata || !rparam) {
3594 DEBUG(0,("api_reply: malloc fail !\n"));
3598 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3599 &rdata,&rparam,&rdata_len,&rparam_len);
3602 if (rdata_len > mdrcnt ||
3603 rparam_len > mprcnt) {
3604 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3605 &rdata,&rparam,&rdata_len,&rparam_len);
3608 /* if we get False back then it's actually unsupported */
3610 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3611 &rdata,&rparam,&rdata_len,&rparam_len);
3613 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);