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;
525 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
526 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
527 lp_servicename(snum)));
531 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
534 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
535 printer->info_2->drivername));
539 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
540 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
541 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
543 PACKI(desc, "W", 0x0400); /* don't know */
544 PACKS(desc, "z", driver.info_3->name); /* long printer name */
545 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
546 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
547 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
549 fstrcpy(location, "\\\\");
550 fstrcat(location, get_called_name());
551 fstrcat(location, "\\print$\\WIN40\\0");
552 PACKS(desc,"z", location); /* share to retrieve files */
554 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
555 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
556 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
558 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
559 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
560 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
561 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
562 DEBUG(3,("Driver Location: %s:\n",location));
563 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
564 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
565 PACKI(desc,"N",count); /* number of files to copy */
567 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
569 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
570 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
571 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
576 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
579 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
581 desc->errcode=NERR_Success;
585 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
586 desc->errcode=NERR_notsupported;
590 free_a_printer( &printer, 2 );
593 free_a_printer_driver( driver, 3 );
597 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
598 struct pack_desc* desc,
599 int count, print_queue_struct* queue,
600 print_status_struct* status)
605 PACKS(desc,"B13",SERVICE(snum));
610 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
613 PACKI(desc,"K",printq_status(status->status));
617 if (uLevel == 1 || uLevel == 2) {
618 PACKS(desc,"B",""); /* alignment */
619 PACKI(desc,"W",5); /* priority */
620 PACKI(desc,"W",0); /* start time */
621 PACKI(desc,"W",0); /* until time */
622 PACKS(desc,"z",""); /* pSepFile */
623 PACKS(desc,"z","lpd"); /* pPrProc */
624 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
625 PACKS(desc,"z",""); /* pParms */
627 PACKS(desc,"z","UNKNOWN PRINTER");
628 PACKI(desc,"W",LPSTAT_ERROR);
630 else if (!status || !status->message[0]) {
631 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
632 PACKI(desc,"W",LPSTAT_OK); /* status */
634 PACKS(desc,"z",status->message);
635 PACKI(desc,"W",printq_status(status->status)); /* status */
637 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
640 if (uLevel == 3 || uLevel == 4) {
643 PACKI(desc,"W",5); /* uPriority */
644 PACKI(desc,"W",0); /* uStarttime */
645 PACKI(desc,"W",0); /* uUntiltime */
646 PACKI(desc,"W",5); /* pad1 */
647 PACKS(desc,"z",""); /* pszSepFile */
648 PACKS(desc,"z","WinPrint"); /* pszPrProc */
649 PACKS(desc,"z",NULL); /* pszParms */
650 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
651 /* "don't ask" that it's done this way to fix corrupted
652 Win9X/ME printer comments. */
654 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
656 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
658 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
659 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
660 get_driver_name(snum,drivername);
661 PACKS(desc,"z",drivername); /* pszDriverName */
662 PackDriverData(desc); /* pDriverData */
665 if (uLevel == 2 || uLevel == 4) {
667 for (i=0;i<count;i++)
668 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
672 fill_printq_info_52( conn, snum, desc, count );
675 /* This function returns the number of files for a given driver */
676 static int get_printerdrivernumber(int snum)
679 NT_PRINTER_DRIVER_INFO_LEVEL driver;
680 NT_PRINTER_INFO_LEVEL *printer = NULL;
682 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
683 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
684 lp_servicename(snum)));
688 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
691 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
692 printer->info_2->drivername));
696 /* count the number of files */
697 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
702 free_a_printer( &printer, 2 );
705 free_a_printer_driver( driver, 3 );
710 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
711 uint16 vuid, char *param,char *data,
712 int mdrcnt,int mprcnt,
713 char **rdata,char **rparam,
714 int *rdata_len,int *rparam_len)
716 char *str1 = param+2;
717 char *str2 = skip_string(str1,1);
718 char *p = skip_string(str2,1);
724 struct pack_desc desc;
725 print_queue_struct *queue=NULL;
726 print_status_struct status;
729 memset((char *)&status,'\0',sizeof(status));
730 memset((char *)&desc,'\0',sizeof(desc));
732 p = skip_string(p,1);
736 /* remove any trailing username */
737 if ((p = strchr_m(QueueName,'%')))
740 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
742 /* check it's a supported varient */
743 if (!prefix_ok(str1,"zWrLh"))
745 if (!check_printq_info(&desc,uLevel,str2,str3)) {
747 * Patch from Scott Moomaw <scott@bridgewater.edu>
748 * to return the 'invalid info level' error if an
749 * unknown level was requested.
753 *rparam = REALLOC(*rparam,*rparam_len);
754 SSVALS(*rparam,0,ERRunknownlevel);
760 snum = lp_servicenumber(QueueName);
761 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
762 int pnum = lp_servicenumber(PRINTERS_NAME);
764 lp_add_printer(QueueName,pnum);
765 snum = lp_servicenumber(QueueName);
769 if (snum < 0 || !VALID_SNUM(snum))
773 count = get_printerdrivernumber(snum);
774 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
776 count = print_queue_status(snum, &queue,&status);
780 *rdata = REALLOC(*rdata,mdrcnt);
782 desc.buflen = mdrcnt;
785 * Don't return data but need to get correct length
786 * init_package will return wrong size if buflen=0
788 desc.buflen = getlen(desc.format);
789 desc.base = tmpdata = (char *) malloc (desc.buflen);
792 if (init_package(&desc,1,count)) {
793 desc.subcount = count;
794 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
797 *rdata_len = desc.usedlen;
800 * We must set the return code to ERRbuftoosmall
801 * in order to support lanman style printing with Win NT/2k
804 if (!mdrcnt && lp_disable_spoolss())
805 desc.errcode = ERRbuftoosmall;
807 *rdata_len = desc.usedlen;
809 *rparam = REALLOC(*rparam,*rparam_len);
810 SSVALS(*rparam,0,desc.errcode);
812 SSVAL(*rparam,4,desc.neededlen);
814 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
822 /****************************************************************************
823 View list of all print jobs on all queues.
824 ****************************************************************************/
826 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
827 int mdrcnt, int mprcnt,
828 char **rdata, char** rparam,
829 int *rdata_len, int *rparam_len)
831 char *param_format = param+2;
832 char *output_format1 = skip_string(param_format,1);
833 char *p = skip_string(output_format1,1);
834 int uLevel = SVAL(p,0);
835 char *output_format2 = p + 4;
836 int services = lp_numservices();
838 struct pack_desc desc;
839 print_queue_struct **queue = NULL;
840 print_status_struct *status = NULL;
841 int* subcntarr = NULL;
842 int queuecnt, subcnt=0, succnt=0;
844 memset((char *)&desc,'\0',sizeof(desc));
846 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
848 if (!prefix_ok(param_format,"WrLeh")) return False;
849 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
851 * Patch from Scott Moomaw <scott@bridgewater.edu>
852 * to return the 'invalid info level' error if an
853 * unknown level was requested.
857 *rparam = REALLOC(*rparam,*rparam_len);
858 SSVALS(*rparam,0,ERRunknownlevel);
865 for (i = 0; i < services; i++)
866 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
869 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
870 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
873 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
874 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
875 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
878 memset(status,0,queuecnt*sizeof(print_status_struct));
879 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
880 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
885 for (i = 0; i < services; i++)
886 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
887 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
888 subcnt += subcntarr[n];
892 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
894 desc.buflen = mdrcnt;
896 if (init_package(&desc,queuecnt,subcnt)) {
899 for (i = 0; i < services; i++)
900 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
901 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
903 if (desc.errcode == NERR_Success) succnt = n;
907 SAFE_FREE(subcntarr);
909 *rdata_len = desc.usedlen;
911 *rparam = REALLOC(*rparam,*rparam_len);
912 SSVALS(*rparam,0,desc.errcode);
914 SSVAL(*rparam,4,succnt);
915 SSVAL(*rparam,6,queuecnt);
917 for (i = 0; i < queuecnt; i++) {
918 if (queue) SAFE_FREE(queue[i]);
927 /****************************************************************************
928 get info level for a server list query
929 ****************************************************************************/
930 static BOOL check_server_info(int uLevel, char* id)
934 if (strcmp(id,"B16") != 0) return False;
937 if (strcmp(id,"B16BBDz") != 0) return False;
945 struct srv_info_struct
955 /*******************************************************************
956 get server info lists from the files saved by nmbd. Return the
958 ******************************************************************/
959 static int get_server_info(uint32 servertype,
960 struct srv_info_struct **servers,
966 BOOL local_list_only;
969 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
971 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
975 /* request for everything is code for request all servers */
976 if (servertype == SV_TYPE_ALL)
977 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
979 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
981 DEBUG(4,("Servertype search: %8x\n",servertype));
983 for (i=0;lines[i];i++) {
985 struct srv_info_struct *s;
986 const char *ptr = lines[i];
991 if (count == alloced) {
992 struct srv_info_struct *ts;
995 ts = (struct srv_info_struct *)
996 Realloc(*servers,sizeof(**servers)*alloced);
998 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1002 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1004 s = &(*servers)[count];
1006 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1007 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1008 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1009 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1010 /* this allows us to cope with an old nmbd */
1011 fstrcpy(s->domain,lp_workgroup());
1014 if (sscanf(stype,"%X",&s->type) != 1) {
1015 DEBUG(4,("r:host file "));
1019 /* Filter the servers/domains we return based on what was asked for. */
1021 /* Check to see if we are being asked for a local list only. */
1022 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1023 DEBUG(4,("r: local list only"));
1027 /* doesn't match up: don't want it */
1028 if (!(servertype & s->type)) {
1029 DEBUG(4,("r:serv type "));
1033 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1034 (s->type & SV_TYPE_DOMAIN_ENUM))
1036 DEBUG(4,("s: dom mismatch "));
1040 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1045 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1046 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1050 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1051 s->name, s->type, s->comment, s->domain));
1053 s->server_added = True;
1058 DEBUG(4,("%20s %8x %25s %15s\n",
1059 s->name, s->type, s->comment, s->domain));
1063 file_lines_free(lines);
1068 /*******************************************************************
1069 fill in a server info structure
1070 ******************************************************************/
1071 static int fill_srv_info(struct srv_info_struct *service,
1072 int uLevel, char **buf, int *buflen,
1073 char **stringbuf, int *stringspace, char *baseaddr)
1082 case 0: struct_len = 16; break;
1083 case 1: struct_len = 26; break;
1093 len = strlen(service->comment)+1;
1097 if (buflen) *buflen = struct_len;
1098 if (stringspace) *stringspace = len;
1099 return struct_len + len;
1104 if (*buflen < struct_len) return -1;
1112 p2 = p + struct_len;
1113 l2 = *buflen - struct_len;
1115 if (!baseaddr) baseaddr = p;
1120 push_ascii(p,service->name, 15, STR_TERMINATE);
1124 push_ascii(p,service->name,15, STR_TERMINATE);
1125 SIVAL(p,18,service->type);
1126 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1127 len += CopyAndAdvance(&p2,service->comment,&l2);
1133 *buf = p + struct_len;
1134 *buflen -= struct_len;
1147 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1149 return(strcmp(s1->name,s2->name));
1152 /****************************************************************************
1153 view list of servers available (or possibly domains). The info is
1154 extracted from lists saved by nmbd on the local host
1155 ****************************************************************************/
1156 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1157 int mdrcnt, int mprcnt, char **rdata,
1158 char **rparam, int *rdata_len, int *rparam_len)
1160 char *str1 = param+2;
1161 char *str2 = skip_string(str1,1);
1162 char *p = skip_string(str2,1);
1163 int uLevel = SVAL(p,0);
1164 int buf_len = SVAL(p,2);
1165 uint32 servertype = IVAL(p,4);
1167 int data_len, fixed_len, string_len;
1168 int f_len = 0, s_len = 0;
1169 struct srv_info_struct *servers=NULL;
1170 int counted=0,total=0;
1173 BOOL domain_request;
1176 /* If someone sets all the bits they don't really mean to set
1177 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1180 if (servertype == SV_TYPE_ALL)
1181 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1183 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1184 any other bit (they may just set this bit on it's own) they
1185 want all the locally seen servers. However this bit can be
1186 set on its own so set the requested servers to be
1187 ALL - DOMAIN_ENUM. */
1189 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1190 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1192 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1193 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1197 if (!prefix_ok(str1,"WrLehD")) return False;
1198 if (!check_server_info(uLevel,str2)) return False;
1200 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1201 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1202 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1204 if (strcmp(str1, "WrLehDz") == 0) {
1205 pull_ascii_fstring(domain, p);
1207 fstrcpy(domain, lp_workgroup());
1210 if (lp_browse_list())
1211 total = get_server_info(servertype,&servers,domain);
1213 data_len = fixed_len = string_len = 0;
1217 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1220 char *lastname=NULL;
1222 for (i=0;i<total;i++)
1224 struct srv_info_struct *s = &servers[i];
1225 if (lastname && strequal(lastname,s->name)) continue;
1227 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1228 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1229 s->name, s->type, s->comment, s->domain));
1231 if (data_len <= buf_len) {
1234 string_len += s_len;
1241 *rdata_len = fixed_len + string_len;
1242 *rdata = REALLOC(*rdata,*rdata_len);
1243 memset(*rdata,'\0',*rdata_len);
1245 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1251 char *lastname=NULL;
1252 int count2 = counted;
1253 for (i = 0; i < total && count2;i++)
1255 struct srv_info_struct *s = &servers[i];
1256 if (lastname && strequal(lastname,s->name)) continue;
1258 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1259 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1260 s->name, s->type, s->comment, s->domain));
1266 *rparam = REALLOC(*rparam,*rparam_len);
1267 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1269 SSVAL(*rparam,4,counted);
1270 SSVAL(*rparam,6,counted+missed);
1274 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1275 domain,uLevel,counted,counted+missed));
1280 /****************************************************************************
1281 command 0x34 - suspected of being a "Lookup Names" stub api
1282 ****************************************************************************/
1283 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1284 int mdrcnt, int mprcnt, char **rdata,
1285 char **rparam, int *rdata_len, int *rparam_len)
1287 char *str1 = param+2;
1288 char *str2 = skip_string(str1,1);
1289 char *p = skip_string(str2,1);
1290 int uLevel = SVAL(p,0);
1291 int buf_len = SVAL(p,2);
1295 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1296 str1, str2, p, uLevel, buf_len));
1298 if (!prefix_ok(str1,"zWrLeh")) return False;
1303 *rparam = REALLOC(*rparam,*rparam_len);
1305 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1307 SSVAL(*rparam,4,counted);
1308 SSVAL(*rparam,6,counted+missed);
1313 /****************************************************************************
1314 get info about a share
1315 ****************************************************************************/
1316 static BOOL check_share_info(int uLevel, char* id)
1320 if (strcmp(id,"B13") != 0) return False;
1323 if (strcmp(id,"B13BWz") != 0) return False;
1326 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1329 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1331 default: return False;
1336 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1337 char** buf, int* buflen,
1338 char** stringbuf, int* stringspace, char* baseaddr)
1347 case 0: struct_len = 13; break;
1348 case 1: struct_len = 20; break;
1349 case 2: struct_len = 40; break;
1350 case 91: struct_len = 68; break;
1358 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1359 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1360 if (buflen) *buflen = struct_len;
1361 if (stringspace) *stringspace = len;
1362 return struct_len + len;
1367 if ((*buflen) < struct_len) return -1;
1375 p2 = p + struct_len;
1376 l2 = (*buflen) - struct_len;
1378 if (!baseaddr) baseaddr = p;
1380 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1386 type = STYPE_DISKTREE;
1387 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1388 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1389 SSVAL(p,14,type); /* device type */
1390 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1391 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1396 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1397 SSVALS(p,22,-1); /* max uses */
1398 SSVAL(p,24,1); /* current uses */
1399 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1400 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1401 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1406 memset(p+40,0,SHPWLEN+2);
1418 (*buf) = p + struct_len;
1419 (*buflen) -= struct_len;
1421 (*stringspace) = l2;
1431 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1432 int mdrcnt,int mprcnt,
1433 char **rdata,char **rparam,
1434 int *rdata_len,int *rparam_len)
1436 char *str1 = param+2;
1437 char *str2 = skip_string(str1,1);
1438 char *netname = skip_string(str2,1);
1439 char *p = skip_string(netname,1);
1440 int uLevel = SVAL(p,0);
1441 int snum = find_service(netname);
1443 if (snum < 0) return False;
1445 /* check it's a supported varient */
1446 if (!prefix_ok(str1,"zWrLh")) return False;
1447 if (!check_share_info(uLevel,str2)) return False;
1449 *rdata = REALLOC(*rdata,mdrcnt);
1451 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1452 if (*rdata_len < 0) return False;
1455 *rparam = REALLOC(*rparam,*rparam_len);
1456 SSVAL(*rparam,0,NERR_Success);
1457 SSVAL(*rparam,2,0); /* converter word */
1458 SSVAL(*rparam,4,*rdata_len);
1463 /****************************************************************************
1464 view list of shares available
1465 ****************************************************************************/
1466 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1467 int mdrcnt,int mprcnt,
1468 char **rdata,char **rparam,
1469 int *rdata_len,int *rparam_len)
1471 char *str1 = param+2;
1472 char *str2 = skip_string(str1,1);
1473 char *p = skip_string(str2,1);
1474 int uLevel = SVAL(p,0);
1475 int buf_len = SVAL(p,2);
1477 int count=lp_numservices();
1478 int total=0,counted=0;
1479 BOOL missed = False;
1481 int data_len, fixed_len, string_len;
1482 int f_len = 0, s_len = 0;
1484 if (!prefix_ok(str1,"WrLeh")) return False;
1485 if (!check_share_info(uLevel,str2)) return False;
1487 data_len = fixed_len = string_len = 0;
1488 for (i=0;i<count;i++)
1489 if (lp_browseable(i) && lp_snum_ok(i))
1492 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1493 if (data_len <= buf_len)
1497 string_len += s_len;
1502 *rdata_len = fixed_len + string_len;
1503 *rdata = REALLOC(*rdata,*rdata_len);
1504 memset(*rdata,0,*rdata_len);
1506 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1510 for (i = 0; i < count;i++)
1511 if (lp_browseable(i) && lp_snum_ok(i))
1512 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1516 *rparam = REALLOC(*rparam,*rparam_len);
1517 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1519 SSVAL(*rparam,4,counted);
1520 SSVAL(*rparam,6,total);
1522 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1523 counted,total,uLevel,
1524 buf_len,*rdata_len,mdrcnt));
1528 /****************************************************************************
1530 ****************************************************************************/
1531 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1532 int mdrcnt,int mprcnt,
1533 char **rdata,char **rparam,
1534 int *rdata_len,int *rparam_len)
1536 char *str1 = param+2;
1537 char *str2 = skip_string(str1,1);
1538 char *p = skip_string(str2,1);
1539 int uLevel = SVAL(p,0);
1543 char *command, *cmdname;
1544 unsigned int offset;
1548 /* check it's a supported varient */
1549 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1550 if (!check_share_info(uLevel,str2)) return False;
1551 if (uLevel != 2) return False;
1553 pull_ascii_fstring(sharename,data);
1554 snum = find_service(sharename);
1555 if (snum >= 0) { /* already exists */
1560 /* only support disk share adds */
1561 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1563 offset = IVAL(data, 16);
1564 if (offset >= mdrcnt) {
1565 res = ERRinvalidparam;
1568 pull_ascii_fstring(comment, offset? (data+offset) : "");
1570 offset = IVAL(data, 26);
1571 if (offset >= mdrcnt) {
1572 res = ERRinvalidparam;
1575 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1577 string_replace(sharename, '"', ' ');
1578 string_replace(pathname, '"', ' ');
1579 string_replace(comment, '"', ' ');
1581 cmdname = lp_add_share_cmd();
1583 if (!cmdname || *cmdname == '\0') return False;
1585 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1586 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1589 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1590 if ((res = smbrun(command, NULL)) != 0) {
1591 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1597 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1599 } else return False;
1602 *rparam = REALLOC(*rparam,*rparam_len);
1603 SSVAL(*rparam,0,NERR_Success);
1604 SSVAL(*rparam,2,0); /* converter word */
1605 SSVAL(*rparam,4,*rdata_len);
1612 *rparam = REALLOC(*rparam,*rparam_len);
1614 SSVAL(*rparam,0,res);
1620 /****************************************************************************
1621 view list of groups available
1622 ****************************************************************************/
1623 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1624 int mdrcnt,int mprcnt,
1625 char **rdata,char **rparam,
1626 int *rdata_len,int *rparam_len)
1630 int resume_context, cli_buf_size;
1631 char *str1 = param+2;
1632 char *str2 = skip_string(str1,1);
1633 char *p = skip_string(str2,1);
1635 GROUP_MAP *group_list;
1638 if (strcmp(str1,"WrLeh") != 0)
1642 * W-> resume context (number of users to skip)
1643 * r -> return parameter pointer to receive buffer
1644 * L -> length of receive buffer
1645 * e -> return parameter number of entries
1646 * h -> return parameter total number of users
1648 if (strcmp("B21",str2) != 0)
1651 /* get list of domain groups SID_DOMAIN_GRP=2 */
1652 if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False)) {
1653 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1657 resume_context = SVAL(p,0);
1658 cli_buf_size=SVAL(p+2,0);
1659 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1661 *rdata_len = cli_buf_size;
1662 *rdata = REALLOC(*rdata,*rdata_len);
1666 for(i=resume_context; i<num_entries; i++) {
1667 char* name=group_list[i].nt_name;
1668 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1669 /* truncate the name at 21 chars. */
1670 memcpy(p, name, 21);
1671 DEBUG(10,("adding entry %d group %s\n", i, p));
1674 /* set overflow error */
1675 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1681 *rdata_len = PTR_DIFF(p,*rdata);
1684 *rparam = REALLOC(*rparam,*rparam_len);
1686 SSVAL(*rparam, 0, errflags);
1687 SSVAL(*rparam, 2, 0); /* converter word */
1688 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1689 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1694 /*******************************************************************
1695 get groups that a user is a member of
1696 ******************************************************************/
1697 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1698 int mdrcnt,int mprcnt,
1699 char **rdata,char **rparam,
1700 int *rdata_len,int *rparam_len)
1702 char *str1 = param+2;
1703 char *str2 = skip_string(str1,1);
1704 char *UserName = skip_string(str2,1);
1705 char *p = skip_string(UserName,1);
1706 int uLevel = SVAL(p,0);
1707 const char *level_string;
1709 SAM_ACCOUNT *sampw = NULL;
1711 DOM_GID *gids = NULL;
1716 enum SID_NAME_USE grp_type;
1717 DOM_SID sid, dom_sid;
1720 *rparam = REALLOC(*rparam,*rparam_len);
1722 /* check it's a supported varient */
1724 if ( strcmp(str1,"zWrLeh") != 0 )
1729 level_string = "B21";
1735 if (strcmp(level_string,str2) != 0)
1738 *rdata_len = mdrcnt + 1024;
1739 *rdata = REALLOC(*rdata,*rdata_len);
1741 SSVAL(*rparam,0,NERR_Success);
1742 SSVAL(*rparam,2,0); /* converter word */
1746 /* Lookup the user information; This should only be one of
1747 our accounts (not remote domains) */
1749 pdb_init_sam( &sampw );
1751 become_root(); /* ROOT BLOCK */
1753 if ( !pdb_getsampwnam(sampw, UserName) )
1756 /* this next set of code is horribly inefficient, but since
1757 it is rarely called, I'm going to leave it like this since
1758 it easier to follow --jerry */
1760 /* get the list of group SIDs */
1762 if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
1763 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1767 /* convert to names (we don't support universal groups so the domain
1768 can only be ours) */
1770 sid_copy( &dom_sid, get_global_sam_sid() );
1771 for (i=0; i<num_groups; i++) {
1773 /* make the DOM_GID into a DOM_SID and then lookup
1776 sid_copy( &sid, &dom_sid );
1777 sid_append_rid( &sid, gids[i].g_rid );
1779 if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
1780 pstrcpy(p, grp_name);
1786 *rdata_len = PTR_DIFF(p,*rdata);
1788 SSVAL(*rparam,4,count); /* is this right?? */
1789 SSVAL(*rparam,6,count); /* is this right?? */
1794 unbecome_root(); /* END ROOT BLOCK */
1796 pdb_free_sam( &sampw );
1801 /*******************************************************************
1803 ******************************************************************/
1804 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1805 int mdrcnt,int mprcnt,
1806 char **rdata,char **rparam,
1807 int *rdata_len,int *rparam_len)
1809 SAM_ACCOUNT *pwd=NULL;
1813 int resume_context, cli_buf_size;
1815 char *str1 = param+2;
1816 char *str2 = skip_string(str1,1);
1817 char *p = skip_string(str2,1);
1819 if (strcmp(str1,"WrLeh") != 0)
1822 * W-> resume context (number of users to skip)
1823 * r -> return parameter pointer to receive buffer
1824 * L -> length of receive buffer
1825 * e -> return parameter number of entries
1826 * h -> return parameter total number of users
1829 resume_context = SVAL(p,0);
1830 cli_buf_size=SVAL(p+2,0);
1831 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1834 *rparam = REALLOC(*rparam,*rparam_len);
1836 /* check it's a supported varient */
1837 if (strcmp("B21",str2) != 0)
1840 *rdata_len = cli_buf_size;
1841 *rdata = REALLOC(*rdata,*rdata_len);
1845 /* to get user list enumerations for NetUserEnum in B21 format */
1848 /* Open the passgrp file - not for update. */
1850 if(!pdb_setsampwent(False)) {
1851 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1855 errflags=NERR_Success;
1857 while ( pdb_getsampwent(pwd) ) {
1858 const char *name=pdb_get_username(pwd);
1859 if ((name) && (*(name+strlen(name)-1)!='$')) {
1861 if(count_total>=resume_context) {
1862 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1864 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1868 /* set overflow error */
1869 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1882 *rdata_len = PTR_DIFF(p,*rdata);
1884 SSVAL(*rparam,0,errflags);
1885 SSVAL(*rparam,2,0); /* converter word */
1886 SSVAL(*rparam,4,count_sent); /* is this right?? */
1887 SSVAL(*rparam,6,count_total); /* is this right?? */
1894 /****************************************************************************
1895 get the time of day info
1896 ****************************************************************************/
1897 static BOOL api_NetRemoteTOD(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)
1904 *rparam = REALLOC(*rparam,*rparam_len);
1907 *rdata = REALLOC(*rdata,*rdata_len);
1909 SSVAL(*rparam,0,NERR_Success);
1910 SSVAL(*rparam,2,0); /* converter word */
1916 time_t unixdate = time(NULL);
1918 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1919 by NT in a "net time" operation,
1920 it seems to ignore the one below */
1922 /* the client expects to get localtime, not GMT, in this bit
1923 (I think, this needs testing) */
1924 t = LocalTime(&unixdate);
1926 SIVAL(p,4,0); /* msecs ? */
1927 SCVAL(p,8,t->tm_hour);
1928 SCVAL(p,9,t->tm_min);
1929 SCVAL(p,10,t->tm_sec);
1930 SCVAL(p,11,0); /* hundredths of seconds */
1931 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1932 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1933 SCVAL(p,16,t->tm_mday);
1934 SCVAL(p,17,t->tm_mon + 1);
1935 SSVAL(p,18,1900+t->tm_year);
1936 SCVAL(p,20,t->tm_wday);
1943 /****************************************************************************
1944 Set the user password.
1945 *****************************************************************************/
1947 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1948 int mdrcnt,int mprcnt,
1949 char **rdata,char **rparam,
1950 int *rdata_len,int *rparam_len)
1952 char *p = skip_string(param+2,2);
1954 fstring pass1,pass2;
1956 pull_ascii_fstring(user,p);
1958 p = skip_string(p,1);
1960 memset(pass1,'\0',sizeof(pass1));
1961 memset(pass2,'\0',sizeof(pass2));
1963 memcpy(pass2,p+16,16);
1966 *rparam = REALLOC(*rparam,*rparam_len);
1970 SSVAL(*rparam,0,NERR_badpass);
1971 SSVAL(*rparam,2,0); /* converter word */
1973 DEBUG(3,("Set password for <%s>\n",user));
1976 * Attempt to verify the old password against smbpasswd entries
1977 * Win98 clients send old and new password in plaintext for this call.
1981 auth_serversupplied_info *server_info = NULL;
1982 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
1984 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1987 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) {
1988 SSVAL(*rparam,0,NERR_Success);
1992 free_server_info(&server_info);
1994 data_blob_clear_free(&password);
1998 * If the plaintext change failed, attempt
1999 * the old encrypted method. NT will generate this
2000 * after trying the samr method. Note that this
2001 * method is done as a last resort as this
2002 * password change method loses the NT password hash
2003 * and cannot change the UNIX password as no plaintext
2007 if(SVAL(*rparam,0) != NERR_Success) {
2008 SAM_ACCOUNT *hnd = NULL;
2010 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2012 if (change_lanman_password(hnd,(uchar *)pass2)) {
2013 SSVAL(*rparam,0,NERR_Success);
2020 memset((char *)pass1,'\0',sizeof(fstring));
2021 memset((char *)pass2,'\0',sizeof(fstring));
2026 /****************************************************************************
2027 Set the user password (SamOEM version - gets plaintext).
2028 ****************************************************************************/
2030 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2031 int mdrcnt,int mprcnt,
2032 char **rdata,char **rparam,
2033 int *rdata_len,int *rparam_len)
2036 char *p = param + 2;
2038 *rparam = REALLOC(*rparam,*rparam_len);
2042 SSVAL(*rparam,0,NERR_badpass);
2045 * Check the parameter definition is correct.
2047 if(!strequal(param + 2, "zsT")) {
2048 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2051 p = skip_string(p, 1);
2053 if(!strequal(p, "B516B16")) {
2054 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2057 p = skip_string(p,1);
2059 p += pull_ascii_fstring(user,p);
2061 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2064 * Pass the user through the NT -> unix user mapping
2068 (void)map_username(user);
2070 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)))
2072 SSVAL(*rparam,0,NERR_Success);
2078 /****************************************************************************
2081 ****************************************************************************/
2082 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2083 int mdrcnt,int mprcnt,
2084 char **rdata,char **rparam,
2085 int *rdata_len,int *rparam_len)
2087 int function = SVAL(param,0);
2088 char *str1 = param+2;
2089 char *str2 = skip_string(str1,1);
2090 char *p = skip_string(str2,1);
2094 extern struct current_user current_user;
2095 WERROR werr = WERR_OK;
2097 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2100 /* check it's a supported varient */
2101 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2105 *rparam = REALLOC(*rparam,*rparam_len);
2108 if (!print_job_exists(snum, jobid)) {
2109 errcode = NERR_JobNotFound;
2113 errcode = NERR_notsupported;
2116 case 81: /* delete */
2117 if (print_job_delete(¤t_user, snum, jobid, &werr))
2118 errcode = NERR_Success;
2120 case 82: /* pause */
2121 if (print_job_pause(¤t_user, snum, jobid, &werr))
2122 errcode = NERR_Success;
2124 case 83: /* resume */
2125 if (print_job_resume(¤t_user, snum, jobid, &werr))
2126 errcode = NERR_Success;
2130 if (!W_ERROR_IS_OK(werr))
2131 errcode = W_ERROR_V(werr);
2134 SSVAL(*rparam,0,errcode);
2135 SSVAL(*rparam,2,0); /* converter word */
2140 /****************************************************************************
2141 Purge a print queue - or pause or resume it.
2142 ****************************************************************************/
2143 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2144 int mdrcnt,int mprcnt,
2145 char **rdata,char **rparam,
2146 int *rdata_len,int *rparam_len)
2148 int function = SVAL(param,0);
2149 char *str1 = param+2;
2150 char *str2 = skip_string(str1,1);
2151 char *QueueName = skip_string(str2,1);
2152 int errcode = NERR_notsupported;
2154 WERROR werr = WERR_OK;
2155 extern struct current_user current_user;
2157 /* check it's a supported varient */
2158 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2162 *rparam = REALLOC(*rparam,*rparam_len);
2165 snum = print_queue_snum(QueueName);
2168 errcode = NERR_JobNotFound;
2173 case 74: /* Pause queue */
2174 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2176 case 75: /* Resume queue */
2177 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2179 case 103: /* Purge */
2180 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2184 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2187 SSVAL(*rparam,0,errcode);
2188 SSVAL(*rparam,2,0); /* converter word */
2194 /****************************************************************************
2195 set the property of a print job (undocumented?)
2196 ? function = 0xb -> set name of print job
2197 ? function = 0x6 -> move print job up/down
2198 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2199 or <WWsTP> <WB21BB16B10zWWzDDz>
2200 ****************************************************************************/
2201 static int check_printjob_info(struct pack_desc* desc,
2202 int uLevel, char* id)
2204 desc->subformat = NULL;
2206 case 0: desc->format = "W"; break;
2207 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2208 case 2: desc->format = "WWzWWDDzz"; break;
2209 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2210 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2211 default: return False;
2213 if (strcmp(desc->format,id) != 0) return False;
2217 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2218 int mdrcnt,int mprcnt,
2219 char **rdata,char **rparam,
2220 int *rdata_len,int *rparam_len)
2222 struct pack_desc desc;
2223 char *str1 = param+2;
2224 char *str2 = skip_string(str1,1);
2225 char *p = skip_string(str2,1);
2228 int uLevel = SVAL(p,2);
2229 int function = SVAL(p,4);
2232 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2235 *rparam = REALLOC(*rparam,*rparam_len);
2239 /* check it's a supported varient */
2240 if ((strcmp(str1,"WWsTP")) ||
2241 (!check_printjob_info(&desc,uLevel,str2)))
2244 if (!print_job_exists(snum, jobid)) {
2245 errcode=NERR_JobNotFound;
2249 errcode = NERR_notsupported;
2253 /* change job place in the queue,
2254 data gives the new place */
2255 place = SVAL(data,0);
2256 if (print_job_set_place(snum, jobid, place)) {
2257 errcode=NERR_Success;
2262 /* change print job name, data gives the name */
2263 if (print_job_set_name(snum, jobid, data)) {
2264 errcode=NERR_Success;
2273 SSVALS(*rparam,0,errcode);
2274 SSVAL(*rparam,2,0); /* converter word */
2280 /****************************************************************************
2281 get info about the server
2282 ****************************************************************************/
2283 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2284 int mdrcnt,int mprcnt,
2285 char **rdata,char **rparam,
2286 int *rdata_len,int *rparam_len)
2288 char *str1 = param+2;
2289 char *str2 = skip_string(str1,1);
2290 char *p = skip_string(str2,1);
2291 int uLevel = SVAL(p,0);
2295 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2297 /* check it's a supported varient */
2298 if (!prefix_ok(str1,"WrLh")) return False;
2301 if (strcmp(str2,"B16") != 0) return False;
2305 if (strcmp(str2,"B16BBDz") != 0) return False;
2309 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2314 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2319 if (strcmp(str2,"DN") != 0) return False;
2323 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2326 default: return False;
2329 *rdata_len = mdrcnt;
2330 *rdata = REALLOC(*rdata,*rdata_len);
2333 p2 = p + struct_len;
2335 srvstr_push(NULL, p,local_machine,16,
2336 STR_ASCII|STR_UPPER|STR_TERMINATE);
2341 struct srv_info_struct *servers=NULL;
2344 uint32 servertype= lp_default_server_announce();
2346 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2348 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2349 for (i=0;i<count;i++)
2350 if (strequal(servers[i].name,local_machine))
2352 servertype = servers[i].type;
2353 pstrcpy(comment,servers[i].comment);
2358 SCVAL(p,0,lp_major_announce_version());
2359 SCVAL(p,1,lp_minor_announce_version());
2360 SIVAL(p,2,servertype);
2362 if (mdrcnt == struct_len) {
2365 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2366 standard_sub_conn(conn,comment,sizeof(comment));
2367 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2368 p2 = skip_string(p2,1);
2373 return False; /* not yet implemented */
2376 *rdata_len = PTR_DIFF(p2,*rdata);
2379 *rparam = REALLOC(*rparam,*rparam_len);
2380 SSVAL(*rparam,0,NERR_Success);
2381 SSVAL(*rparam,2,0); /* converter word */
2382 SSVAL(*rparam,4,*rdata_len);
2388 /****************************************************************************
2389 get info about the server
2390 ****************************************************************************/
2391 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2392 int mdrcnt,int mprcnt,
2393 char **rdata,char **rparam,
2394 int *rdata_len,int *rparam_len)
2396 char *str1 = param+2;
2397 char *str2 = skip_string(str1,1);
2398 char *p = skip_string(str2,1);
2400 extern userdom_struct current_user_info;
2401 int level = SVAL(p,0);
2403 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2406 *rparam = REALLOC(*rparam,*rparam_len);
2408 /* check it's a supported varient */
2409 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2412 *rdata_len = mdrcnt + 1024;
2413 *rdata = REALLOC(*rdata,*rdata_len);
2415 SSVAL(*rparam,0,NERR_Success);
2416 SSVAL(*rparam,2,0); /* converter word */
2422 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2423 pstrcpy(p2,local_machine);
2425 p2 = skip_string(p2,1);
2428 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2429 pstrcpy(p2,current_user_info.smb_name);
2430 p2 = skip_string(p2,1);
2433 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2434 pstrcpy(p2,lp_workgroup());
2436 p2 = skip_string(p2,1);
2439 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2440 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2443 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2444 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2445 p2 = skip_string(p2,1);
2448 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2450 p2 = skip_string(p2,1);
2453 *rdata_len = PTR_DIFF(p2,*rdata);
2455 SSVAL(*rparam,4,*rdata_len);
2460 /****************************************************************************
2461 get info about a user
2463 struct user_info_11 {
2464 char usri11_name[21]; 0-20
2466 char *usri11_comment; 22-25
2467 char *usri11_usr_comment; 26-29
2468 unsigned short usri11_priv; 30-31
2469 unsigned long usri11_auth_flags; 32-35
2470 long usri11_password_age; 36-39
2471 char *usri11_homedir; 40-43
2472 char *usri11_parms; 44-47
2473 long usri11_last_logon; 48-51
2474 long usri11_last_logoff; 52-55
2475 unsigned short usri11_bad_pw_count; 56-57
2476 unsigned short usri11_num_logons; 58-59
2477 char *usri11_logon_server; 60-63
2478 unsigned short usri11_country_code; 64-65
2479 char *usri11_workstations; 66-69
2480 unsigned long usri11_max_storage; 70-73
2481 unsigned short usri11_units_per_week; 74-75
2482 unsigned char *usri11_logon_hours; 76-79
2483 unsigned short usri11_code_page; 80-81
2488 usri11_name specifies the user name for which information is retireved
2490 usri11_pad aligns the next data structure element to a word boundary
2492 usri11_comment is a null terminated ASCII comment
2494 usri11_user_comment is a null terminated ASCII comment about the user
2496 usri11_priv specifies the level of the privilege assigned to the user.
2497 The possible values are:
2499 Name Value Description
2500 USER_PRIV_GUEST 0 Guest privilege
2501 USER_PRIV_USER 1 User privilege
2502 USER_PRV_ADMIN 2 Administrator privilege
2504 usri11_auth_flags specifies the account operator privileges. The
2505 possible values are:
2507 Name Value Description
2508 AF_OP_PRINT 0 Print operator
2511 Leach, Naik [Page 28]
2515 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2518 AF_OP_COMM 1 Communications operator
2519 AF_OP_SERVER 2 Server operator
2520 AF_OP_ACCOUNTS 3 Accounts operator
2523 usri11_password_age specifies how many seconds have elapsed since the
2524 password was last changed.
2526 usri11_home_dir points to a null terminated ASCII string that contains
2527 the path name of the user's home directory.
2529 usri11_parms points to a null terminated ASCII string that is set
2530 aside for use by applications.
2532 usri11_last_logon specifies the time when the user last logged on.
2533 This value is stored as the number of seconds elapsed since
2534 00:00:00, January 1, 1970.
2536 usri11_last_logoff specifies the time when the user last logged off.
2537 This value is stored as the number of seconds elapsed since
2538 00:00:00, January 1, 1970. A value of 0 means the last logoff
2541 usri11_bad_pw_count specifies the number of incorrect passwords
2542 entered since the last successful logon.
2544 usri11_log1_num_logons specifies the number of times this user has
2545 logged on. A value of -1 means the number of logons is unknown.
2547 usri11_logon_server points to a null terminated ASCII string that
2548 contains the name of the server to which logon requests are sent.
2549 A null string indicates logon requests should be sent to the
2552 usri11_country_code specifies the country code for the user's language
2555 usri11_workstations points to a null terminated ASCII string that
2556 contains the names of workstations the user may log on from.
2557 There may be up to 8 workstations, with the names separated by
2558 commas. A null strings indicates there are no restrictions.
2560 usri11_max_storage specifies the maximum amount of disk space the user
2561 can occupy. A value of 0xffffffff indicates there are no
2564 usri11_units_per_week specifies the equal number of time units into
2565 which a week is divided. This value must be equal to 168.
2567 usri11_logon_hours points to a 21 byte (168 bits) string that
2568 specifies the time during which the user can log on. Each bit
2569 represents one unique hour in a week. The first bit (bit 0, word
2570 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2574 Leach, Naik [Page 29]
2578 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2581 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2582 are no restrictions.
2584 usri11_code_page specifies the code page for the user's language of
2587 All of the pointers in this data structure need to be treated
2588 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2589 to be ignored. The converter word returned in the parameters section
2590 needs to be subtracted from the lower 16 bits to calculate an offset
2591 into the return buffer where this ASCII string resides.
2593 There is no auxiliary data in the response.
2595 ****************************************************************************/
2597 #define usri11_name 0
2598 #define usri11_pad 21
2599 #define usri11_comment 22
2600 #define usri11_usr_comment 26
2601 #define usri11_full_name 30
2602 #define usri11_priv 34
2603 #define usri11_auth_flags 36
2604 #define usri11_password_age 40
2605 #define usri11_homedir 44
2606 #define usri11_parms 48
2607 #define usri11_last_logon 52
2608 #define usri11_last_logoff 56
2609 #define usri11_bad_pw_count 60
2610 #define usri11_num_logons 62
2611 #define usri11_logon_server 64
2612 #define usri11_country_code 68
2613 #define usri11_workstations 70
2614 #define usri11_max_storage 74
2615 #define usri11_units_per_week 78
2616 #define usri11_logon_hours 80
2617 #define usri11_code_page 84
2618 #define usri11_end 86
2620 #define USER_PRIV_GUEST 0
2621 #define USER_PRIV_USER 1
2622 #define USER_PRIV_ADMIN 2
2624 #define AF_OP_PRINT 0
2625 #define AF_OP_COMM 1
2626 #define AF_OP_SERVER 2
2627 #define AF_OP_ACCOUNTS 3
2630 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2631 int mdrcnt,int mprcnt,
2632 char **rdata,char **rparam,
2633 int *rdata_len,int *rparam_len)
2635 char *str1 = param+2;
2636 char *str2 = skip_string(str1,1);
2637 char *UserName = skip_string(str2,1);
2638 char *p = skip_string(UserName,1);
2639 int uLevel = SVAL(p,0);
2641 const char *level_string;
2643 /* get NIS home of a previously validated user - simeon */
2644 /* With share level security vuid will always be zero.
2645 Don't depend on vuser being non-null !!. JRA */
2646 user_struct *vuser = get_valid_user_struct(vuid);
2648 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2649 vuser->user.unix_name));
2652 *rparam = REALLOC(*rparam,*rparam_len);
2654 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2656 /* check it's a supported variant */
2657 if (strcmp(str1,"zWrLh") != 0) return False;
2660 case 0: level_string = "B21"; break;
2661 case 1: level_string = "B21BB16DWzzWz"; break;
2662 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2663 case 10: level_string = "B21Bzzz"; break;
2664 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2665 default: return False;
2668 if (strcmp(level_string,str2) != 0) return False;
2670 *rdata_len = mdrcnt + 1024;
2671 *rdata = REALLOC(*rdata,*rdata_len);
2673 SSVAL(*rparam,0,NERR_Success);
2674 SSVAL(*rparam,2,0); /* converter word */
2677 p2 = p + usri11_end;
2680 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2684 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2689 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2690 pstrcpy(p2,"Comment");
2691 p2 = skip_string(p2,1);
2693 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2694 pstrcpy(p2,"UserComment");
2695 p2 = skip_string(p2,1);
2697 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2698 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2699 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2700 p2 = skip_string(p2,1);
2703 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2705 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2706 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2707 SIVALS(p,usri11_password_age,-1); /* password age */
2708 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2709 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2710 p2 = skip_string(p2,1);
2711 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2713 p2 = skip_string(p2,1);
2714 SIVAL(p,usri11_last_logon,0); /* last logon */
2715 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2716 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2717 SSVALS(p,usri11_num_logons,-1); /* num logons */
2718 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2719 pstrcpy(p2,"\\\\*");
2720 p2 = skip_string(p2,1);
2721 SSVAL(p,usri11_country_code,0); /* country code */
2723 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2725 p2 = skip_string(p2,1);
2727 SIVALS(p,usri11_max_storage,-1); /* max storage */
2728 SSVAL(p,usri11_units_per_week,168); /* units per week */
2729 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2731 /* a simple way to get logon hours at all times. */
2733 SCVAL(p2,21,0); /* fix zero termination */
2734 p2 = skip_string(p2,1);
2736 SSVAL(p,usri11_code_page,0); /* code page */
2738 if (uLevel == 1 || uLevel == 2)
2740 memset(p+22,' ',16); /* password */
2741 SIVALS(p,38,-1); /* password age */
2743 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2744 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2745 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2746 p2 = skip_string(p2,1);
2747 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2749 SSVAL(p,52,0); /* flags */
2750 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2751 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2752 p2 = skip_string(p2,1);
2755 SIVAL(p,60,0); /* auth_flags */
2756 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2757 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2758 p2 = skip_string(p2,1);
2759 SIVAL(p,68,0); /* urs_comment */
2760 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2762 p2 = skip_string(p2,1);
2763 SIVAL(p,76,0); /* workstations */
2764 SIVAL(p,80,0); /* last_logon */
2765 SIVAL(p,84,0); /* last_logoff */
2766 SIVALS(p,88,-1); /* acct_expires */
2767 SIVALS(p,92,-1); /* max_storage */
2768 SSVAL(p,96,168); /* units_per_week */
2769 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2772 SSVALS(p,102,-1); /* bad_pw_count */
2773 SSVALS(p,104,-1); /* num_logons */
2774 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2775 pstrcpy(p2,"\\\\%L");
2776 standard_sub_conn(conn, p2,0);
2777 p2 = skip_string(p2,1);
2778 SSVAL(p,110,49); /* country_code */
2779 SSVAL(p,112,860); /* code page */
2783 *rdata_len = PTR_DIFF(p2,*rdata);
2785 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2790 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2791 int mdrcnt,int mprcnt,
2792 char **rdata,char **rparam,
2793 int *rdata_len,int *rparam_len)
2795 char *str1 = param+2;
2796 char *str2 = skip_string(str1,1);
2797 char *p = skip_string(str2,1);
2799 struct pack_desc desc;
2801 /* With share level security vuid will always be zero.
2802 Don't depend on vuser being non-null !!. JRA */
2803 user_struct *vuser = get_valid_user_struct(vuid);
2805 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2806 vuser->user.unix_name));
2811 memset((char *)&desc,'\0',sizeof(desc));
2813 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2815 /* check it's a supported varient */
2816 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2817 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2818 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2820 desc.buflen = mdrcnt;
2821 desc.subformat = NULL;
2824 if (init_package(&desc,1,0))
2826 PACKI(&desc,"W",0); /* code */
2827 PACKS(&desc,"B21",name); /* eff. name */
2828 PACKS(&desc,"B",""); /* pad */
2830 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2831 PACKI(&desc,"D",0); /* auth flags XXX */
2832 PACKI(&desc,"W",0); /* num logons */
2833 PACKI(&desc,"W",0); /* bad pw count */
2834 PACKI(&desc,"D",0); /* last logon */
2835 PACKI(&desc,"D",-1); /* last logoff */
2836 PACKI(&desc,"D",-1); /* logoff time */
2837 PACKI(&desc,"D",-1); /* kickoff time */
2838 PACKI(&desc,"D",0); /* password age */
2839 PACKI(&desc,"D",0); /* password can change */
2840 PACKI(&desc,"D",-1); /* password must change */
2843 fstrcpy(mypath,"\\\\");
2844 fstrcat(mypath,local_machine);
2846 PACKS(&desc,"z",mypath); /* computer */
2848 PACKS(&desc,"z",lp_workgroup());/* domain */
2850 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2852 PACKI(&desc,"D",0x00000000); /* reserved */
2855 *rdata_len = desc.usedlen;
2857 *rparam = REALLOC(*rparam,*rparam_len);
2858 SSVALS(*rparam,0,desc.errcode);
2860 SSVAL(*rparam,4,desc.neededlen);
2862 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2867 /****************************************************************************
2868 api_WAccessGetUserPerms
2869 ****************************************************************************/
2870 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2871 int mdrcnt,int mprcnt,
2872 char **rdata,char **rparam,
2873 int *rdata_len,int *rparam_len)
2875 char *str1 = param+2;
2876 char *str2 = skip_string(str1,1);
2877 char *user = skip_string(str2,1);
2878 char *resource = skip_string(user,1);
2880 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2882 /* check it's a supported varient */
2883 if (strcmp(str1,"zzh") != 0) return False;
2884 if (strcmp(str2,"") != 0) return False;
2887 *rparam = REALLOC(*rparam,*rparam_len);
2888 SSVALS(*rparam,0,0); /* errorcode */
2889 SSVAL(*rparam,2,0); /* converter word */
2890 SSVAL(*rparam,4,0x7f); /* permission flags */
2895 /****************************************************************************
2896 api_WPrintJobEnumerate
2897 ****************************************************************************/
2898 static BOOL api_WPrintJobGetInfo(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 *p = skip_string(str2,1);
2911 struct pack_desc desc;
2912 print_queue_struct *queue=NULL;
2913 print_status_struct status;
2918 memset((char *)&desc,'\0',sizeof(desc));
2919 memset((char *)&status,'\0',sizeof(status));
2921 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2923 /* check it's a supported varient */
2924 if (strcmp(str1,"WWrLh") != 0) return False;
2925 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2927 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2930 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2932 count = print_queue_status(snum,&queue,&status);
2933 for (i = 0; i < count; i++) {
2934 if (queue[i].job == jobid) break;
2938 *rdata = REALLOC(*rdata,mdrcnt);
2940 desc.buflen = mdrcnt;
2943 * Don't return data but need to get correct length
2944 * init_package will return wrong size if buflen=0
2946 desc.buflen = getlen(desc.format);
2947 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2950 if (init_package(&desc,1,0)) {
2952 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2953 *rdata_len = desc.usedlen;
2956 desc.errcode = NERR_JobNotFound;
2962 *rparam = REALLOC(*rparam,*rparam_len);
2963 SSVALS(*rparam,0,desc.errcode);
2965 SSVAL(*rparam,4,desc.neededlen);
2970 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2974 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2975 int mdrcnt,int mprcnt,
2976 char **rdata,char **rparam,
2977 int *rdata_len,int *rparam_len)
2979 char *str1 = param+2;
2980 char *str2 = skip_string(str1,1);
2981 char *p = skip_string(str2,1);
2987 struct pack_desc desc;
2988 print_queue_struct *queue=NULL;
2989 print_status_struct status;
2991 memset((char *)&desc,'\0',sizeof(desc));
2992 memset((char *)&status,'\0',sizeof(status));
2994 p = skip_string(p,1);
2997 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2999 /* check it's a supported variant */
3000 if (strcmp(str1,"zWrLeh") != 0) return False;
3001 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3002 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3004 snum = lp_servicenumber(name);
3005 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3006 int pnum = lp_servicenumber(PRINTERS_NAME);
3008 lp_add_printer(name,pnum);
3009 snum = lp_servicenumber(name);
3013 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3015 count = print_queue_status(snum,&queue,&status);
3016 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3018 desc.buflen = mdrcnt;
3020 if (init_package(&desc,count,0)) {
3022 for (i = 0; i < count; i++) {
3023 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3024 if (desc.errcode == NERR_Success) succnt = i+1;
3028 *rdata_len = desc.usedlen;
3031 *rparam = REALLOC(*rparam,*rparam_len);
3032 SSVALS(*rparam,0,desc.errcode);
3034 SSVAL(*rparam,4,succnt);
3035 SSVAL(*rparam,6,count);
3039 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3043 static int check_printdest_info(struct pack_desc* desc,
3044 int uLevel, char* id)
3046 desc->subformat = NULL;
3048 case 0: desc->format = "B9"; break;
3049 case 1: desc->format = "B9B21WWzW"; break;
3050 case 2: desc->format = "z"; break;
3051 case 3: desc->format = "zzzWWzzzWW"; break;
3052 default: return False;
3054 if (strcmp(desc->format,id) != 0) return False;
3058 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3059 struct pack_desc* desc)
3062 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3063 buf[sizeof(buf)-1] = 0;
3066 PACKS(desc,"B9",buf); /* szName */
3068 PACKS(desc,"B21",""); /* szUserName */
3069 PACKI(desc,"W",0); /* uJobId */
3070 PACKI(desc,"W",0); /* fsStatus */
3071 PACKS(desc,"z",""); /* pszStatus */
3072 PACKI(desc,"W",0); /* time */
3075 if (uLevel == 2 || uLevel == 3) {
3076 PACKS(desc,"z",buf); /* pszPrinterName */
3078 PACKS(desc,"z",""); /* pszUserName */
3079 PACKS(desc,"z",""); /* pszLogAddr */
3080 PACKI(desc,"W",0); /* uJobId */
3081 PACKI(desc,"W",0); /* fsStatus */
3082 PACKS(desc,"z",""); /* pszStatus */
3083 PACKS(desc,"z",""); /* pszComment */
3084 PACKS(desc,"z","NULL"); /* pszDrivers */
3085 PACKI(desc,"W",0); /* time */
3086 PACKI(desc,"W",0); /* pad1 */
3091 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3092 int mdrcnt,int mprcnt,
3093 char **rdata,char **rparam,
3094 int *rdata_len,int *rparam_len)
3096 char *str1 = param+2;
3097 char *str2 = skip_string(str1,1);
3098 char *p = skip_string(str2,1);
3099 char* PrinterName = p;
3101 struct pack_desc desc;
3105 memset((char *)&desc,'\0',sizeof(desc));
3107 p = skip_string(p,1);
3110 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3112 /* check it's a supported varient */
3113 if (strcmp(str1,"zWrLh") != 0) return False;
3114 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3116 snum = lp_servicenumber(PrinterName);
3117 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3118 int pnum = lp_servicenumber(PRINTERS_NAME);
3120 lp_add_printer(PrinterName,pnum);
3121 snum = lp_servicenumber(PrinterName);
3127 desc.errcode = NERR_DestNotFound;
3132 *rdata = REALLOC(*rdata,mdrcnt);
3134 desc.buflen = mdrcnt;
3137 * Don't return data but need to get correct length
3138 * init_package will return wrong size if buflen=0
3140 desc.buflen = getlen(desc.format);
3141 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3143 if (init_package(&desc,1,0)) {
3144 fill_printdest_info(conn,snum,uLevel,&desc);
3146 *rdata_len = desc.usedlen;
3150 *rparam = REALLOC(*rparam,*rparam_len);
3151 SSVALS(*rparam,0,desc.errcode);
3153 SSVAL(*rparam,4,desc.neededlen);
3155 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3160 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3161 int mdrcnt,int mprcnt,
3162 char **rdata,char **rparam,
3163 int *rdata_len,int *rparam_len)
3165 char *str1 = param+2;
3166 char *str2 = skip_string(str1,1);
3167 char *p = skip_string(str2,1);
3171 struct pack_desc desc;
3172 int services = lp_numservices();
3174 memset((char *)&desc,'\0',sizeof(desc));
3178 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3180 /* check it's a supported varient */
3181 if (strcmp(str1,"WrLeh") != 0) return False;
3182 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3185 for (i = 0; i < services; i++)
3186 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3189 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3191 desc.buflen = mdrcnt;
3192 if (init_package(&desc,queuecnt,0)) {
3195 for (i = 0; i < services; i++) {
3196 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3197 fill_printdest_info(conn,i,uLevel,&desc);
3199 if (desc.errcode == NERR_Success) succnt = n;
3204 *rdata_len = desc.usedlen;
3207 *rparam = REALLOC(*rparam,*rparam_len);
3208 SSVALS(*rparam,0,desc.errcode);
3210 SSVAL(*rparam,4,succnt);
3211 SSVAL(*rparam,6,queuecnt);
3213 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3217 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3218 int mdrcnt,int mprcnt,
3219 char **rdata,char **rparam,
3220 int *rdata_len,int *rparam_len)
3222 char *str1 = param+2;
3223 char *str2 = skip_string(str1,1);
3224 char *p = skip_string(str2,1);
3227 struct pack_desc desc;
3229 memset((char *)&desc,'\0',sizeof(desc));
3233 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3235 /* check it's a supported varient */
3236 if (strcmp(str1,"WrLeh") != 0) return False;
3237 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3239 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3241 desc.buflen = mdrcnt;
3242 if (init_package(&desc,1,0)) {
3243 PACKS(&desc,"B41","NULL");
3246 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3248 *rdata_len = desc.usedlen;
3251 *rparam = REALLOC(*rparam,*rparam_len);
3252 SSVALS(*rparam,0,desc.errcode);
3254 SSVAL(*rparam,4,succnt);
3257 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3261 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3262 int mdrcnt,int mprcnt,
3263 char **rdata,char **rparam,
3264 int *rdata_len,int *rparam_len)
3266 char *str1 = param+2;
3267 char *str2 = skip_string(str1,1);
3268 char *p = skip_string(str2,1);
3271 struct pack_desc desc;
3273 memset((char *)&desc,'\0',sizeof(desc));
3277 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3279 /* check it's a supported varient */
3280 if (strcmp(str1,"WrLeh") != 0) return False;
3281 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3283 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3285 desc.buflen = mdrcnt;
3287 if (init_package(&desc,1,0)) {
3288 PACKS(&desc,"B13","lpd");
3291 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3293 *rdata_len = desc.usedlen;
3296 *rparam = REALLOC(*rparam,*rparam_len);
3297 SSVALS(*rparam,0,desc.errcode);
3299 SSVAL(*rparam,4,succnt);
3302 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3306 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3307 int mdrcnt,int mprcnt,
3308 char **rdata,char **rparam,
3309 int *rdata_len,int *rparam_len)
3311 char *str1 = param+2;
3312 char *str2 = skip_string(str1,1);
3313 char *p = skip_string(str2,1);
3316 struct pack_desc desc;
3318 memset((char *)&desc,'\0',sizeof(desc));
3322 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3324 /* check it's a supported varient */
3325 if (strcmp(str1,"WrLeh") != 0) return False;
3326 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3328 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3329 memset((char *)&desc,'\0',sizeof(desc));
3331 desc.buflen = mdrcnt;
3333 if (init_package(&desc,1,0)) {
3334 PACKS(&desc,"B13","lp0");
3337 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3339 *rdata_len = desc.usedlen;
3342 *rparam = REALLOC(*rparam,*rparam_len);
3343 SSVALS(*rparam,0,desc.errcode);
3345 SSVAL(*rparam,4,succnt);
3348 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3353 /****************************************************************************
3355 ****************************************************************************/
3356 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3357 int mdrcnt,int mprcnt,
3358 char **rdata,char **rparam,
3359 int *rdata_len,int *rparam_len)
3362 char *str1 = param+2;
3363 char *str2 = skip_string(str1,1);
3364 char *p = skip_string(str2,1);
3366 struct pack_desc desc;
3367 struct sessionid *session_list;
3368 int i, num_sessions;
3370 memset((char *)&desc,'\0',sizeof(desc));
3374 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3375 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3376 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3378 /* check it's a supported varient */
3379 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3380 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3382 num_sessions = list_sessions(&session_list);
3384 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3385 memset((char *)&desc,'\0',sizeof(desc));
3387 desc.buflen = mdrcnt;
3389 if (!init_package(&desc,num_sessions,0)) {
3393 for(i=0; i<num_sessions; i++) {
3394 PACKS(&desc, "z", session_list[i].remote_machine);
3395 PACKS(&desc, "z", session_list[i].username);
3396 PACKI(&desc, "W", 1); /* num conns */
3397 PACKI(&desc, "W", 0); /* num opens */
3398 PACKI(&desc, "W", 1); /* num users */
3399 PACKI(&desc, "D", 0); /* session time */
3400 PACKI(&desc, "D", 0); /* idle time */
3401 PACKI(&desc, "D", 0); /* flags */
3402 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3405 *rdata_len = desc.usedlen;
3408 *rparam = REALLOC(*rparam,*rparam_len);
3409 SSVALS(*rparam,0,desc.errcode);
3410 SSVAL(*rparam,2,0); /* converter */
3411 SSVAL(*rparam,4,num_sessions); /* count */
3413 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3418 /****************************************************************************
3419 The buffer was too small
3420 ****************************************************************************/
3422 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3423 int mdrcnt,int mprcnt,
3424 char **rdata,char **rparam,
3425 int *rdata_len,int *rparam_len)
3427 *rparam_len = MIN(*rparam_len,mprcnt);
3428 *rparam = REALLOC(*rparam,*rparam_len);
3432 SSVAL(*rparam,0,NERR_BufTooSmall);
3434 DEBUG(3,("Supplied buffer too small in API command\n"));
3440 /****************************************************************************
3441 The request is not supported
3442 ****************************************************************************/
3444 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3445 int mdrcnt,int mprcnt,
3446 char **rdata,char **rparam,
3447 int *rdata_len,int *rparam_len)
3450 *rparam = REALLOC(*rparam,*rparam_len);
3454 SSVAL(*rparam,0,NERR_notsupported);
3455 SSVAL(*rparam,2,0); /* converter word */
3457 DEBUG(3,("Unsupported API command\n"));
3469 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3470 int,int,char **,char **,int *,int *);
3471 BOOL auth_user; /* Deny anonymous access? */
3472 } api_commands[] = {
3473 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3474 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3475 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3476 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3477 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3478 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3479 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3480 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3481 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3482 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3483 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3484 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3485 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3486 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3487 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3488 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3489 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3490 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3491 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3492 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3493 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3494 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3495 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3496 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3497 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3498 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3499 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3500 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3501 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3502 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3503 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3504 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3505 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3506 {NULL, -1, api_Unsupported}};
3508 /* The following RAP calls are not implemented by Samba:
3510 RAP_WFileEnum2 - anon not OK
3513 /****************************************************************************
3514 Handle remote api calls
3515 ****************************************************************************/
3517 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3518 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3522 char *rparam = NULL;
3529 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3533 api_command = SVAL(params,0);
3535 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3538 skip_string(params+2,1),
3539 tdscnt,tpscnt,mdrcnt,mprcnt));
3541 for (i=0;api_commands[i].name;i++) {
3542 if (api_commands[i].id == api_command && api_commands[i].fn) {
3543 DEBUG(3,("Doing %s\n",api_commands[i].name));
3548 /* Check whether this api call can be done anonymously */
3550 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3551 user_struct *user = get_valid_user_struct(vuid);
3553 if (!user || user->guest)
3554 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3557 rdata = (char *)malloc(1024);
3559 memset(rdata,'\0',1024);
3561 rparam = (char *)malloc(1024);
3563 memset(rparam,'\0',1024);
3565 if(!rdata || !rparam) {
3566 DEBUG(0,("api_reply: malloc fail !\n"));
3570 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3571 &rdata,&rparam,&rdata_len,&rparam_len);
3574 if (rdata_len > mdrcnt ||
3575 rparam_len > mprcnt) {
3576 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3577 &rdata,&rparam,&rdata_len,&rparam_len);
3580 /* if we get False back then it's actually unsupported */
3582 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3583 &rdata,&rparam,&rdata_len,&rparam_len);
3585 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);