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(char *str,char *prefix)
114 return(strncmp(str,prefix,strlen(prefix)) == 0);
118 char* format; /* formatstring for structure */
119 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 char* curpos; /* current position; pointer into format or subformat */
132 static int get_counter(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(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,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 (&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( &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( &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 pstrcpy(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, 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);
1711 *rparam = REALLOC(*rparam,*rparam_len);
1713 /* check it's a supported varient */
1714 if (!strcmp(str1,"zWrLeh"))
1724 if (strcmp(p2,str2) != 0)
1727 *rdata_len = mdrcnt + 1024;
1728 *rdata = REALLOC(*rdata,*rdata_len);
1730 SSVAL(*rparam,0,NERR_Success);
1731 SSVAL(*rparam,2,0); /* converter word */
1735 /* XXXX we need a real SAM database some day */
1736 pstrcpy(p,"Users"); p += 21; count++;
1737 pstrcpy(p,"Domain Users"); p += 21; count++;
1738 pstrcpy(p,"Guests"); p += 21; count++;
1739 pstrcpy(p,"Domain Guests"); p += 21; count++;
1741 *rdata_len = PTR_DIFF(p,*rdata);
1743 SSVAL(*rparam,4,count); /* is this right?? */
1744 SSVAL(*rparam,6,count); /* is this right?? */
1749 /*******************************************************************
1751 ******************************************************************/
1752 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1753 int mdrcnt,int mprcnt,
1754 char **rdata,char **rparam,
1755 int *rdata_len,int *rparam_len)
1757 SAM_ACCOUNT *pwd=NULL;
1761 int resume_context, cli_buf_size;
1763 char *str1 = param+2;
1764 char *str2 = skip_string(str1,1);
1765 char *p = skip_string(str2,1);
1767 if (strcmp(str1,"WrLeh") != 0)
1770 * W-> resume context (number of users to skip)
1771 * r -> return parameter pointer to receive buffer
1772 * L -> length of receive buffer
1773 * e -> return parameter number of entries
1774 * h -> return parameter total number of users
1777 resume_context = SVAL(p,0);
1778 cli_buf_size=SVAL(p+2,0);
1779 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1782 *rparam = REALLOC(*rparam,*rparam_len);
1784 /* check it's a supported varient */
1785 if (strcmp("B21",str2) != 0)
1788 *rdata_len = cli_buf_size;
1789 *rdata = REALLOC(*rdata,*rdata_len);
1793 /* to get user list enumerations for NetUserEnum in B21 format */
1796 /* Open the passgrp file - not for update. */
1798 if(!pdb_setsampwent(False)) {
1799 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1803 errflags=NERR_Success;
1805 while ( pdb_getsampwent(pwd) ) {
1806 const char *name=pdb_get_username(pwd);
1807 if ((name) && (*(name+strlen(name)-1)!='$')) {
1809 if(count_total>=resume_context) {
1810 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1812 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1816 /* set overflow error */
1817 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1830 *rdata_len = PTR_DIFF(p,*rdata);
1832 SSVAL(*rparam,0,errflags);
1833 SSVAL(*rparam,2,0); /* converter word */
1834 SSVAL(*rparam,4,count_sent); /* is this right?? */
1835 SSVAL(*rparam,6,count_total); /* is this right?? */
1842 /****************************************************************************
1843 get the time of day info
1844 ****************************************************************************/
1845 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1846 int mdrcnt,int mprcnt,
1847 char **rdata,char **rparam,
1848 int *rdata_len,int *rparam_len)
1852 *rparam = REALLOC(*rparam,*rparam_len);
1855 *rdata = REALLOC(*rdata,*rdata_len);
1857 SSVAL(*rparam,0,NERR_Success);
1858 SSVAL(*rparam,2,0); /* converter word */
1864 time_t unixdate = time(NULL);
1866 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1867 by NT in a "net time" operation,
1868 it seems to ignore the one below */
1870 /* the client expects to get localtime, not GMT, in this bit
1871 (I think, this needs testing) */
1872 t = LocalTime(&unixdate);
1874 SIVAL(p,4,0); /* msecs ? */
1875 SCVAL(p,8,t->tm_hour);
1876 SCVAL(p,9,t->tm_min);
1877 SCVAL(p,10,t->tm_sec);
1878 SCVAL(p,11,0); /* hundredths of seconds */
1879 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1880 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1881 SCVAL(p,16,t->tm_mday);
1882 SCVAL(p,17,t->tm_mon + 1);
1883 SSVAL(p,18,1900+t->tm_year);
1884 SCVAL(p,20,t->tm_wday);
1891 /****************************************************************************
1892 Set the user password.
1893 *****************************************************************************/
1895 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1896 int mdrcnt,int mprcnt,
1897 char **rdata,char **rparam,
1898 int *rdata_len,int *rparam_len)
1900 char *p = skip_string(param+2,2);
1902 fstring pass1,pass2;
1904 pull_ascii_fstring(user,p);
1906 p = skip_string(p,1);
1908 memset(pass1,'\0',sizeof(pass1));
1909 memset(pass2,'\0',sizeof(pass2));
1911 memcpy(pass2,p+16,16);
1914 *rparam = REALLOC(*rparam,*rparam_len);
1918 SSVAL(*rparam,0,NERR_badpass);
1919 SSVAL(*rparam,2,0); /* converter word */
1921 DEBUG(3,("Set password for <%s>\n",user));
1924 * Attempt to verify the old password against smbpasswd entries
1925 * Win98 clients send old and new password in plaintext for this call.
1929 auth_serversupplied_info *server_info = NULL;
1930 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
1931 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1934 * If unix password sync was requested, attempt to change
1935 * the /etc/passwd database first. Return failure if this cannot
1938 * This occurs before the oem change, becouse we don't want to
1939 * update it if chgpasswd failed.
1941 * Conditional on lp_unix_password_sync() becouse we don't want
1942 * to touch the unix db unless we have admin permission.
1945 if(lp_unix_password_sync() && IS_SAM_UNIX_USER(server_info->sam_account)
1946 && !chgpasswd(pdb_get_username(server_info->sam_account),
1947 pass1,pass2,False)) {
1948 SSVAL(*rparam,0,NERR_badpass);
1951 if (change_oem_password(server_info->sam_account,pass2))
1953 SSVAL(*rparam,0,NERR_Success);
1956 free_server_info(&server_info);
1958 data_blob_clear_free(&password);
1962 * If the plaintext change failed, attempt
1963 * the old encrypted method. NT will generate this
1964 * after trying the samr method. Note that this
1965 * method is done as a last resort as this
1966 * password change method loses the NT password hash
1967 * and cannot change the UNIX password as no plaintext
1971 if(SVAL(*rparam,0) != NERR_Success)
1973 SAM_ACCOUNT *hnd = NULL;
1975 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1976 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
1978 SSVAL(*rparam,0,NERR_Success);
1984 memset((char *)pass1,'\0',sizeof(fstring));
1985 memset((char *)pass2,'\0',sizeof(fstring));
1990 /****************************************************************************
1991 Set the user password (SamOEM version - gets plaintext).
1992 ****************************************************************************/
1994 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1995 int mdrcnt,int mprcnt,
1996 char **rdata,char **rparam,
1997 int *rdata_len,int *rparam_len)
2000 char *p = param + 2;
2002 *rparam = REALLOC(*rparam,*rparam_len);
2006 SSVAL(*rparam,0,NERR_badpass);
2009 * Check the parameter definition is correct.
2011 if(!strequal(param + 2, "zsT")) {
2012 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2015 p = skip_string(p, 1);
2017 if(!strequal(p, "B516B16")) {
2018 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2021 p = skip_string(p,1);
2023 p += pull_ascii_fstring(user,p);
2025 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2028 * Pass the user through the NT -> unix user mapping
2032 (void)map_username(user);
2034 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
2036 SSVAL(*rparam,0,NERR_Success);
2042 /****************************************************************************
2045 ****************************************************************************/
2046 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2047 int mdrcnt,int mprcnt,
2048 char **rdata,char **rparam,
2049 int *rdata_len,int *rparam_len)
2051 int function = SVAL(param,0);
2052 char *str1 = param+2;
2053 char *str2 = skip_string(str1,1);
2054 char *p = skip_string(str2,1);
2058 extern struct current_user current_user;
2059 WERROR werr = WERR_OK;
2061 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2064 /* check it's a supported varient */
2065 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2069 *rparam = REALLOC(*rparam,*rparam_len);
2072 if (!print_job_exists(snum, jobid)) {
2073 errcode = NERR_JobNotFound;
2077 errcode = NERR_notsupported;
2080 case 81: /* delete */
2081 if (print_job_delete(¤t_user, snum, jobid, &werr))
2082 errcode = NERR_Success;
2084 case 82: /* pause */
2085 if (print_job_pause(¤t_user, snum, jobid, &werr))
2086 errcode = NERR_Success;
2088 case 83: /* resume */
2089 if (print_job_resume(¤t_user, snum, jobid, &werr))
2090 errcode = NERR_Success;
2094 if (!W_ERROR_IS_OK(werr))
2095 errcode = W_ERROR_V(werr);
2098 SSVAL(*rparam,0,errcode);
2099 SSVAL(*rparam,2,0); /* converter word */
2104 /****************************************************************************
2105 Purge a print queue - or pause or resume it.
2106 ****************************************************************************/
2107 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2108 int mdrcnt,int mprcnt,
2109 char **rdata,char **rparam,
2110 int *rdata_len,int *rparam_len)
2112 int function = SVAL(param,0);
2113 char *str1 = param+2;
2114 char *str2 = skip_string(str1,1);
2115 char *QueueName = skip_string(str2,1);
2116 int errcode = NERR_notsupported;
2118 WERROR werr = WERR_OK;
2119 extern struct current_user current_user;
2121 /* check it's a supported varient */
2122 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2126 *rparam = REALLOC(*rparam,*rparam_len);
2129 snum = print_queue_snum(QueueName);
2132 errcode = NERR_JobNotFound;
2137 case 74: /* Pause queue */
2138 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2140 case 75: /* Resume queue */
2141 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2143 case 103: /* Purge */
2144 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2148 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2151 SSVAL(*rparam,0,errcode);
2152 SSVAL(*rparam,2,0); /* converter word */
2158 /****************************************************************************
2159 set the property of a print job (undocumented?)
2160 ? function = 0xb -> set name of print job
2161 ? function = 0x6 -> move print job up/down
2162 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2163 or <WWsTP> <WB21BB16B10zWWzDDz>
2164 ****************************************************************************/
2165 static int check_printjob_info(struct pack_desc* desc,
2166 int uLevel, char* id)
2168 desc->subformat = NULL;
2170 case 0: desc->format = "W"; break;
2171 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2172 case 2: desc->format = "WWzWWDDzz"; break;
2173 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2174 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2175 default: return False;
2177 if (strcmp(desc->format,id) != 0) return False;
2181 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2182 int mdrcnt,int mprcnt,
2183 char **rdata,char **rparam,
2184 int *rdata_len,int *rparam_len)
2186 struct pack_desc desc;
2187 char *str1 = param+2;
2188 char *str2 = skip_string(str1,1);
2189 char *p = skip_string(str2,1);
2192 int uLevel = SVAL(p,2);
2193 int function = SVAL(p,4);
2196 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2199 *rparam = REALLOC(*rparam,*rparam_len);
2203 /* check it's a supported varient */
2204 if ((strcmp(str1,"WWsTP")) ||
2205 (!check_printjob_info(&desc,uLevel,str2)))
2208 if (!print_job_exists(snum, jobid)) {
2209 errcode=NERR_JobNotFound;
2213 errcode = NERR_notsupported;
2217 /* change job place in the queue,
2218 data gives the new place */
2219 place = SVAL(data,0);
2220 if (print_job_set_place(snum, jobid, place)) {
2221 errcode=NERR_Success;
2226 /* change print job name, data gives the name */
2227 if (print_job_set_name(snum, jobid, data)) {
2228 errcode=NERR_Success;
2237 SSVALS(*rparam,0,errcode);
2238 SSVAL(*rparam,2,0); /* converter word */
2244 /****************************************************************************
2245 get info about the server
2246 ****************************************************************************/
2247 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2248 int mdrcnt,int mprcnt,
2249 char **rdata,char **rparam,
2250 int *rdata_len,int *rparam_len)
2252 char *str1 = param+2;
2253 char *str2 = skip_string(str1,1);
2254 char *p = skip_string(str2,1);
2255 int uLevel = SVAL(p,0);
2259 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2261 /* check it's a supported varient */
2262 if (!prefix_ok(str1,"WrLh")) return False;
2265 if (strcmp(str2,"B16") != 0) return False;
2269 if (strcmp(str2,"B16BBDz") != 0) return False;
2273 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2278 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2283 if (strcmp(str2,"DN") != 0) return False;
2287 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2290 default: return False;
2293 *rdata_len = mdrcnt;
2294 *rdata = REALLOC(*rdata,*rdata_len);
2297 p2 = p + struct_len;
2299 srvstr_push(NULL, p,local_machine,16,
2300 STR_ASCII|STR_UPPER|STR_TERMINATE);
2305 struct srv_info_struct *servers=NULL;
2308 uint32 servertype= lp_default_server_announce();
2310 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2312 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2313 for (i=0;i<count;i++)
2314 if (strequal(servers[i].name,local_machine))
2316 servertype = servers[i].type;
2317 pstrcpy(comment,servers[i].comment);
2322 SCVAL(p,0,lp_major_announce_version());
2323 SCVAL(p,1,lp_minor_announce_version());
2324 SIVAL(p,2,servertype);
2326 if (mdrcnt == struct_len) {
2329 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2330 standard_sub_conn(conn,comment,sizeof(comment));
2331 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2332 p2 = skip_string(p2,1);
2337 return False; /* not yet implemented */
2340 *rdata_len = PTR_DIFF(p2,*rdata);
2343 *rparam = REALLOC(*rparam,*rparam_len);
2344 SSVAL(*rparam,0,NERR_Success);
2345 SSVAL(*rparam,2,0); /* converter word */
2346 SSVAL(*rparam,4,*rdata_len);
2352 /****************************************************************************
2353 get info about the server
2354 ****************************************************************************/
2355 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2356 int mdrcnt,int mprcnt,
2357 char **rdata,char **rparam,
2358 int *rdata_len,int *rparam_len)
2360 char *str1 = param+2;
2361 char *str2 = skip_string(str1,1);
2362 char *p = skip_string(str2,1);
2364 extern userdom_struct current_user_info;
2365 int level = SVAL(p,0);
2367 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2370 *rparam = REALLOC(*rparam,*rparam_len);
2372 /* check it's a supported varient */
2373 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2376 *rdata_len = mdrcnt + 1024;
2377 *rdata = REALLOC(*rdata,*rdata_len);
2379 SSVAL(*rparam,0,NERR_Success);
2380 SSVAL(*rparam,2,0); /* converter word */
2386 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2387 pstrcpy(p2,local_machine);
2389 p2 = skip_string(p2,1);
2392 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2393 pstrcpy(p2,current_user_info.smb_name);
2394 p2 = skip_string(p2,1);
2397 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2398 pstrcpy(p2,lp_workgroup());
2400 p2 = skip_string(p2,1);
2403 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2404 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2407 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2408 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2409 p2 = skip_string(p2,1);
2412 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2414 p2 = skip_string(p2,1);
2417 *rdata_len = PTR_DIFF(p2,*rdata);
2419 SSVAL(*rparam,4,*rdata_len);
2424 /****************************************************************************
2425 get info about a user
2427 struct user_info_11 {
2428 char usri11_name[21]; 0-20
2430 char *usri11_comment; 22-25
2431 char *usri11_usr_comment; 26-29
2432 unsigned short usri11_priv; 30-31
2433 unsigned long usri11_auth_flags; 32-35
2434 long usri11_password_age; 36-39
2435 char *usri11_homedir; 40-43
2436 char *usri11_parms; 44-47
2437 long usri11_last_logon; 48-51
2438 long usri11_last_logoff; 52-55
2439 unsigned short usri11_bad_pw_count; 56-57
2440 unsigned short usri11_num_logons; 58-59
2441 char *usri11_logon_server; 60-63
2442 unsigned short usri11_country_code; 64-65
2443 char *usri11_workstations; 66-69
2444 unsigned long usri11_max_storage; 70-73
2445 unsigned short usri11_units_per_week; 74-75
2446 unsigned char *usri11_logon_hours; 76-79
2447 unsigned short usri11_code_page; 80-81
2452 usri11_name specifies the user name for which information is retireved
2454 usri11_pad aligns the next data structure element to a word boundary
2456 usri11_comment is a null terminated ASCII comment
2458 usri11_user_comment is a null terminated ASCII comment about the user
2460 usri11_priv specifies the level of the privilege assigned to the user.
2461 The possible values are:
2463 Name Value Description
2464 USER_PRIV_GUEST 0 Guest privilege
2465 USER_PRIV_USER 1 User privilege
2466 USER_PRV_ADMIN 2 Administrator privilege
2468 usri11_auth_flags specifies the account operator privileges. The
2469 possible values are:
2471 Name Value Description
2472 AF_OP_PRINT 0 Print operator
2475 Leach, Naik [Page 28]
2479 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2482 AF_OP_COMM 1 Communications operator
2483 AF_OP_SERVER 2 Server operator
2484 AF_OP_ACCOUNTS 3 Accounts operator
2487 usri11_password_age specifies how many seconds have elapsed since the
2488 password was last changed.
2490 usri11_home_dir points to a null terminated ASCII string that contains
2491 the path name of the user's home directory.
2493 usri11_parms points to a null terminated ASCII string that is set
2494 aside for use by applications.
2496 usri11_last_logon specifies the time when the user last logged on.
2497 This value is stored as the number of seconds elapsed since
2498 00:00:00, January 1, 1970.
2500 usri11_last_logoff specifies the time when the user last logged off.
2501 This value is stored as the number of seconds elapsed since
2502 00:00:00, January 1, 1970. A value of 0 means the last logoff
2505 usri11_bad_pw_count specifies the number of incorrect passwords
2506 entered since the last successful logon.
2508 usri11_log1_num_logons specifies the number of times this user has
2509 logged on. A value of -1 means the number of logons is unknown.
2511 usri11_logon_server points to a null terminated ASCII string that
2512 contains the name of the server to which logon requests are sent.
2513 A null string indicates logon requests should be sent to the
2516 usri11_country_code specifies the country code for the user's language
2519 usri11_workstations points to a null terminated ASCII string that
2520 contains the names of workstations the user may log on from.
2521 There may be up to 8 workstations, with the names separated by
2522 commas. A null strings indicates there are no restrictions.
2524 usri11_max_storage specifies the maximum amount of disk space the user
2525 can occupy. A value of 0xffffffff indicates there are no
2528 usri11_units_per_week specifies the equal number of time units into
2529 which a week is divided. This value must be equal to 168.
2531 usri11_logon_hours points to a 21 byte (168 bits) string that
2532 specifies the time during which the user can log on. Each bit
2533 represents one unique hour in a week. The first bit (bit 0, word
2534 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2538 Leach, Naik [Page 29]
2542 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2545 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2546 are no restrictions.
2548 usri11_code_page specifies the code page for the user's language of
2551 All of the pointers in this data structure need to be treated
2552 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2553 to be ignored. The converter word returned in the parameters section
2554 needs to be subtracted from the lower 16 bits to calculate an offset
2555 into the return buffer where this ASCII string resides.
2557 There is no auxiliary data in the response.
2559 ****************************************************************************/
2561 #define usri11_name 0
2562 #define usri11_pad 21
2563 #define usri11_comment 22
2564 #define usri11_usr_comment 26
2565 #define usri11_full_name 30
2566 #define usri11_priv 34
2567 #define usri11_auth_flags 36
2568 #define usri11_password_age 40
2569 #define usri11_homedir 44
2570 #define usri11_parms 48
2571 #define usri11_last_logon 52
2572 #define usri11_last_logoff 56
2573 #define usri11_bad_pw_count 60
2574 #define usri11_num_logons 62
2575 #define usri11_logon_server 64
2576 #define usri11_country_code 68
2577 #define usri11_workstations 70
2578 #define usri11_max_storage 74
2579 #define usri11_units_per_week 78
2580 #define usri11_logon_hours 80
2581 #define usri11_code_page 84
2582 #define usri11_end 86
2584 #define USER_PRIV_GUEST 0
2585 #define USER_PRIV_USER 1
2586 #define USER_PRIV_ADMIN 2
2588 #define AF_OP_PRINT 0
2589 #define AF_OP_COMM 1
2590 #define AF_OP_SERVER 2
2591 #define AF_OP_ACCOUNTS 3
2594 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2595 int mdrcnt,int mprcnt,
2596 char **rdata,char **rparam,
2597 int *rdata_len,int *rparam_len)
2599 char *str1 = param+2;
2600 char *str2 = skip_string(str1,1);
2601 char *UserName = skip_string(str2,1);
2602 char *p = skip_string(UserName,1);
2603 int uLevel = SVAL(p,0);
2606 /* get NIS home of a previously validated user - simeon */
2607 /* With share level security vuid will always be zero.
2608 Don't depend on vuser being non-null !!. JRA */
2609 user_struct *vuser = get_valid_user_struct(vuid);
2611 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2612 vuser->user.unix_name));
2615 *rparam = REALLOC(*rparam,*rparam_len);
2617 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2619 /* check it's a supported variant */
2620 if (strcmp(str1,"zWrLh") != 0) return False;
2623 case 0: p2 = "B21"; break;
2624 case 1: p2 = "B21BB16DWzzWz"; break;
2625 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2626 case 10: p2 = "B21Bzzz"; break;
2627 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2628 default: return False;
2631 if (strcmp(p2,str2) != 0) return False;
2633 *rdata_len = mdrcnt + 1024;
2634 *rdata = REALLOC(*rdata,*rdata_len);
2636 SSVAL(*rparam,0,NERR_Success);
2637 SSVAL(*rparam,2,0); /* converter word */
2640 p2 = p + usri11_end;
2643 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2647 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2652 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2653 pstrcpy(p2,"Comment");
2654 p2 = skip_string(p2,1);
2656 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2657 pstrcpy(p2,"UserComment");
2658 p2 = skip_string(p2,1);
2660 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2661 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2662 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2663 p2 = skip_string(p2,1);
2666 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2668 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2669 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2670 SIVALS(p,usri11_password_age,-1); /* password age */
2671 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2672 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2673 p2 = skip_string(p2,1);
2674 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2676 p2 = skip_string(p2,1);
2677 SIVAL(p,usri11_last_logon,0); /* last logon */
2678 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2679 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2680 SSVALS(p,usri11_num_logons,-1); /* num logons */
2681 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2682 pstrcpy(p2,"\\\\*");
2683 p2 = skip_string(p2,1);
2684 SSVAL(p,usri11_country_code,0); /* country code */
2686 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2688 p2 = skip_string(p2,1);
2690 SIVALS(p,usri11_max_storage,-1); /* max storage */
2691 SSVAL(p,usri11_units_per_week,168); /* units per week */
2692 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2694 /* a simple way to get logon hours at all times. */
2696 SCVAL(p2,21,0); /* fix zero termination */
2697 p2 = skip_string(p2,1);
2699 SSVAL(p,usri11_code_page,0); /* code page */
2701 if (uLevel == 1 || uLevel == 2)
2703 memset(p+22,' ',16); /* password */
2704 SIVALS(p,38,-1); /* password age */
2706 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2707 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2708 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2709 p2 = skip_string(p2,1);
2710 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2712 SSVAL(p,52,0); /* flags */
2713 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2714 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2715 p2 = skip_string(p2,1);
2718 SIVAL(p,60,0); /* auth_flags */
2719 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2720 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2721 p2 = skip_string(p2,1);
2722 SIVAL(p,68,0); /* urs_comment */
2723 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2725 p2 = skip_string(p2,1);
2726 SIVAL(p,76,0); /* workstations */
2727 SIVAL(p,80,0); /* last_logon */
2728 SIVAL(p,84,0); /* last_logoff */
2729 SIVALS(p,88,-1); /* acct_expires */
2730 SIVALS(p,92,-1); /* max_storage */
2731 SSVAL(p,96,168); /* units_per_week */
2732 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2735 SSVALS(p,102,-1); /* bad_pw_count */
2736 SSVALS(p,104,-1); /* num_logons */
2737 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2738 pstrcpy(p2,"\\\\%L");
2739 standard_sub_conn(conn, p2,0);
2740 p2 = skip_string(p2,1);
2741 SSVAL(p,110,49); /* country_code */
2742 SSVAL(p,112,860); /* code page */
2746 *rdata_len = PTR_DIFF(p2,*rdata);
2748 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2753 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2754 int mdrcnt,int mprcnt,
2755 char **rdata,char **rparam,
2756 int *rdata_len,int *rparam_len)
2758 char *str1 = param+2;
2759 char *str2 = skip_string(str1,1);
2760 char *p = skip_string(str2,1);
2762 struct pack_desc desc;
2764 /* With share level security vuid will always be zero.
2765 Don't depend on vuser being non-null !!. JRA */
2766 user_struct *vuser = get_valid_user_struct(vuid);
2768 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2769 vuser->user.unix_name));
2774 memset((char *)&desc,'\0',sizeof(desc));
2776 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2778 /* check it's a supported varient */
2779 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2780 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2781 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2783 desc.buflen = mdrcnt;
2784 desc.subformat = NULL;
2787 if (init_package(&desc,1,0))
2789 PACKI(&desc,"W",0); /* code */
2790 PACKS(&desc,"B21",name); /* eff. name */
2791 PACKS(&desc,"B",""); /* pad */
2793 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2794 PACKI(&desc,"D",0); /* auth flags XXX */
2795 PACKI(&desc,"W",0); /* num logons */
2796 PACKI(&desc,"W",0); /* bad pw count */
2797 PACKI(&desc,"D",0); /* last logon */
2798 PACKI(&desc,"D",-1); /* last logoff */
2799 PACKI(&desc,"D",-1); /* logoff time */
2800 PACKI(&desc,"D",-1); /* kickoff time */
2801 PACKI(&desc,"D",0); /* password age */
2802 PACKI(&desc,"D",0); /* password can change */
2803 PACKI(&desc,"D",-1); /* password must change */
2806 fstrcpy(mypath,"\\\\");
2807 fstrcat(mypath,local_machine);
2809 PACKS(&desc,"z",mypath); /* computer */
2811 PACKS(&desc,"z",lp_workgroup());/* domain */
2813 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2815 PACKI(&desc,"D",0x00000000); /* reserved */
2818 *rdata_len = desc.usedlen;
2820 *rparam = REALLOC(*rparam,*rparam_len);
2821 SSVALS(*rparam,0,desc.errcode);
2823 SSVAL(*rparam,4,desc.neededlen);
2825 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2830 /****************************************************************************
2831 api_WAccessGetUserPerms
2832 ****************************************************************************/
2833 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2834 int mdrcnt,int mprcnt,
2835 char **rdata,char **rparam,
2836 int *rdata_len,int *rparam_len)
2838 char *str1 = param+2;
2839 char *str2 = skip_string(str1,1);
2840 char *user = skip_string(str2,1);
2841 char *resource = skip_string(user,1);
2843 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2845 /* check it's a supported varient */
2846 if (strcmp(str1,"zzh") != 0) return False;
2847 if (strcmp(str2,"") != 0) return False;
2850 *rparam = REALLOC(*rparam,*rparam_len);
2851 SSVALS(*rparam,0,0); /* errorcode */
2852 SSVAL(*rparam,2,0); /* converter word */
2853 SSVAL(*rparam,4,0x7f); /* permission flags */
2858 /****************************************************************************
2859 api_WPrintJobEnumerate
2860 ****************************************************************************/
2861 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2862 int mdrcnt,int mprcnt,
2863 char **rdata,char **rparam,
2864 int *rdata_len,int *rparam_len)
2866 char *str1 = param+2;
2867 char *str2 = skip_string(str1,1);
2868 char *p = skip_string(str2,1);
2874 struct pack_desc desc;
2875 print_queue_struct *queue=NULL;
2876 print_status_struct status;
2881 memset((char *)&desc,'\0',sizeof(desc));
2882 memset((char *)&status,'\0',sizeof(status));
2884 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2886 /* check it's a supported varient */
2887 if (strcmp(str1,"WWrLh") != 0) return False;
2888 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2890 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2893 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2895 count = print_queue_status(snum,&queue,&status);
2896 for (i = 0; i < count; i++) {
2897 if (queue[i].job == jobid) break;
2901 *rdata = REALLOC(*rdata,mdrcnt);
2903 desc.buflen = mdrcnt;
2906 * Don't return data but need to get correct length
2907 * init_package will return wrong size if buflen=0
2909 desc.buflen = getlen(desc.format);
2910 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2913 if (init_package(&desc,1,0)) {
2915 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2916 *rdata_len = desc.usedlen;
2919 desc.errcode = NERR_JobNotFound;
2925 *rparam = REALLOC(*rparam,*rparam_len);
2926 SSVALS(*rparam,0,desc.errcode);
2928 SSVAL(*rparam,4,desc.neededlen);
2933 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2937 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2938 int mdrcnt,int mprcnt,
2939 char **rdata,char **rparam,
2940 int *rdata_len,int *rparam_len)
2942 char *str1 = param+2;
2943 char *str2 = skip_string(str1,1);
2944 char *p = skip_string(str2,1);
2950 struct pack_desc desc;
2951 print_queue_struct *queue=NULL;
2952 print_status_struct status;
2954 memset((char *)&desc,'\0',sizeof(desc));
2955 memset((char *)&status,'\0',sizeof(status));
2957 p = skip_string(p,1);
2960 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2962 /* check it's a supported variant */
2963 if (strcmp(str1,"zWrLeh") != 0) return False;
2964 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2965 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2967 snum = lp_servicenumber(name);
2968 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2969 int pnum = lp_servicenumber(PRINTERS_NAME);
2971 lp_add_printer(name,pnum);
2972 snum = lp_servicenumber(name);
2976 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2978 count = print_queue_status(snum,&queue,&status);
2979 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2981 desc.buflen = mdrcnt;
2983 if (init_package(&desc,count,0)) {
2985 for (i = 0; i < count; i++) {
2986 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2987 if (desc.errcode == NERR_Success) succnt = i+1;
2991 *rdata_len = desc.usedlen;
2994 *rparam = REALLOC(*rparam,*rparam_len);
2995 SSVALS(*rparam,0,desc.errcode);
2997 SSVAL(*rparam,4,succnt);
2998 SSVAL(*rparam,6,count);
3002 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3006 static int check_printdest_info(struct pack_desc* desc,
3007 int uLevel, char* id)
3009 desc->subformat = NULL;
3011 case 0: desc->format = "B9"; break;
3012 case 1: desc->format = "B9B21WWzW"; break;
3013 case 2: desc->format = "z"; break;
3014 case 3: desc->format = "zzzWWzzzWW"; break;
3015 default: return False;
3017 if (strcmp(desc->format,id) != 0) return False;
3021 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3022 struct pack_desc* desc)
3025 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3026 buf[sizeof(buf)-1] = 0;
3029 PACKS(desc,"B9",buf); /* szName */
3031 PACKS(desc,"B21",""); /* szUserName */
3032 PACKI(desc,"W",0); /* uJobId */
3033 PACKI(desc,"W",0); /* fsStatus */
3034 PACKS(desc,"z",""); /* pszStatus */
3035 PACKI(desc,"W",0); /* time */
3038 if (uLevel == 2 || uLevel == 3) {
3039 PACKS(desc,"z",buf); /* pszPrinterName */
3041 PACKS(desc,"z",""); /* pszUserName */
3042 PACKS(desc,"z",""); /* pszLogAddr */
3043 PACKI(desc,"W",0); /* uJobId */
3044 PACKI(desc,"W",0); /* fsStatus */
3045 PACKS(desc,"z",""); /* pszStatus */
3046 PACKS(desc,"z",""); /* pszComment */
3047 PACKS(desc,"z","NULL"); /* pszDrivers */
3048 PACKI(desc,"W",0); /* time */
3049 PACKI(desc,"W",0); /* pad1 */
3054 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3055 int mdrcnt,int mprcnt,
3056 char **rdata,char **rparam,
3057 int *rdata_len,int *rparam_len)
3059 char *str1 = param+2;
3060 char *str2 = skip_string(str1,1);
3061 char *p = skip_string(str2,1);
3062 char* PrinterName = p;
3064 struct pack_desc desc;
3068 memset((char *)&desc,'\0',sizeof(desc));
3070 p = skip_string(p,1);
3073 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3075 /* check it's a supported varient */
3076 if (strcmp(str1,"zWrLh") != 0) return False;
3077 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3079 snum = lp_servicenumber(PrinterName);
3080 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3081 int pnum = lp_servicenumber(PRINTERS_NAME);
3083 lp_add_printer(PrinterName,pnum);
3084 snum = lp_servicenumber(PrinterName);
3090 desc.errcode = NERR_DestNotFound;
3095 *rdata = REALLOC(*rdata,mdrcnt);
3097 desc.buflen = mdrcnt;
3100 * Don't return data but need to get correct length
3101 * init_package will return wrong size if buflen=0
3103 desc.buflen = getlen(desc.format);
3104 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3106 if (init_package(&desc,1,0)) {
3107 fill_printdest_info(conn,snum,uLevel,&desc);
3109 *rdata_len = desc.usedlen;
3113 *rparam = REALLOC(*rparam,*rparam_len);
3114 SSVALS(*rparam,0,desc.errcode);
3116 SSVAL(*rparam,4,desc.neededlen);
3118 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3123 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3124 int mdrcnt,int mprcnt,
3125 char **rdata,char **rparam,
3126 int *rdata_len,int *rparam_len)
3128 char *str1 = param+2;
3129 char *str2 = skip_string(str1,1);
3130 char *p = skip_string(str2,1);
3134 struct pack_desc desc;
3135 int services = lp_numservices();
3137 memset((char *)&desc,'\0',sizeof(desc));
3141 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3143 /* check it's a supported varient */
3144 if (strcmp(str1,"WrLeh") != 0) return False;
3145 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3148 for (i = 0; i < services; i++)
3149 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3152 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3154 desc.buflen = mdrcnt;
3155 if (init_package(&desc,queuecnt,0)) {
3158 for (i = 0; i < services; i++) {
3159 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3160 fill_printdest_info(conn,i,uLevel,&desc);
3162 if (desc.errcode == NERR_Success) succnt = n;
3167 *rdata_len = desc.usedlen;
3170 *rparam = REALLOC(*rparam,*rparam_len);
3171 SSVALS(*rparam,0,desc.errcode);
3173 SSVAL(*rparam,4,succnt);
3174 SSVAL(*rparam,6,queuecnt);
3176 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3180 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3181 int mdrcnt,int mprcnt,
3182 char **rdata,char **rparam,
3183 int *rdata_len,int *rparam_len)
3185 char *str1 = param+2;
3186 char *str2 = skip_string(str1,1);
3187 char *p = skip_string(str2,1);
3190 struct pack_desc desc;
3192 memset((char *)&desc,'\0',sizeof(desc));
3196 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3198 /* check it's a supported varient */
3199 if (strcmp(str1,"WrLeh") != 0) return False;
3200 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3202 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3204 desc.buflen = mdrcnt;
3205 if (init_package(&desc,1,0)) {
3206 PACKS(&desc,"B41","NULL");
3209 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3211 *rdata_len = desc.usedlen;
3214 *rparam = REALLOC(*rparam,*rparam_len);
3215 SSVALS(*rparam,0,desc.errcode);
3217 SSVAL(*rparam,4,succnt);
3220 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3224 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3225 int mdrcnt,int mprcnt,
3226 char **rdata,char **rparam,
3227 int *rdata_len,int *rparam_len)
3229 char *str1 = param+2;
3230 char *str2 = skip_string(str1,1);
3231 char *p = skip_string(str2,1);
3234 struct pack_desc desc;
3236 memset((char *)&desc,'\0',sizeof(desc));
3240 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3242 /* check it's a supported varient */
3243 if (strcmp(str1,"WrLeh") != 0) return False;
3244 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3246 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3248 desc.buflen = mdrcnt;
3250 if (init_package(&desc,1,0)) {
3251 PACKS(&desc,"B13","lpd");
3254 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3256 *rdata_len = desc.usedlen;
3259 *rparam = REALLOC(*rparam,*rparam_len);
3260 SSVALS(*rparam,0,desc.errcode);
3262 SSVAL(*rparam,4,succnt);
3265 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3269 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3270 int mdrcnt,int mprcnt,
3271 char **rdata,char **rparam,
3272 int *rdata_len,int *rparam_len)
3274 char *str1 = param+2;
3275 char *str2 = skip_string(str1,1);
3276 char *p = skip_string(str2,1);
3279 struct pack_desc desc;
3281 memset((char *)&desc,'\0',sizeof(desc));
3285 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3287 /* check it's a supported varient */
3288 if (strcmp(str1,"WrLeh") != 0) return False;
3289 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3291 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3292 memset((char *)&desc,'\0',sizeof(desc));
3294 desc.buflen = mdrcnt;
3296 if (init_package(&desc,1,0)) {
3297 PACKS(&desc,"B13","lp0");
3300 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3302 *rdata_len = desc.usedlen;
3305 *rparam = REALLOC(*rparam,*rparam_len);
3306 SSVALS(*rparam,0,desc.errcode);
3308 SSVAL(*rparam,4,succnt);
3311 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3316 /****************************************************************************
3318 ****************************************************************************/
3319 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3320 int mdrcnt,int mprcnt,
3321 char **rdata,char **rparam,
3322 int *rdata_len,int *rparam_len)
3325 char *str1 = param+2;
3326 char *str2 = skip_string(str1,1);
3327 char *p = skip_string(str2,1);
3329 struct pack_desc desc;
3330 struct sessionid *session_list;
3331 int i, num_sessions;
3333 memset((char *)&desc,'\0',sizeof(desc));
3337 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3338 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3339 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3341 /* check it's a supported varient */
3342 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3343 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3345 num_sessions = list_sessions(&session_list);
3347 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3348 memset((char *)&desc,'\0',sizeof(desc));
3350 desc.buflen = mdrcnt;
3352 if (!init_package(&desc,num_sessions,0)) {
3356 for(i=0; i<num_sessions; i++) {
3357 PACKS(&desc, "z", session_list[i].remote_machine);
3358 PACKS(&desc, "z", session_list[i].username);
3359 PACKI(&desc, "W", 1); /* num conns */
3360 PACKI(&desc, "W", 0); /* num opens */
3361 PACKI(&desc, "W", 1); /* num users */
3362 PACKI(&desc, "D", 0); /* session time */
3363 PACKI(&desc, "D", 0); /* idle time */
3364 PACKI(&desc, "D", 0); /* flags */
3365 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3368 *rdata_len = desc.usedlen;
3371 *rparam = REALLOC(*rparam,*rparam_len);
3372 SSVALS(*rparam,0,desc.errcode);
3373 SSVAL(*rparam,2,0); /* converter */
3374 SSVAL(*rparam,4,num_sessions); /* count */
3376 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3381 /****************************************************************************
3382 The buffer was too small
3383 ****************************************************************************/
3385 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3386 int mdrcnt,int mprcnt,
3387 char **rdata,char **rparam,
3388 int *rdata_len,int *rparam_len)
3390 *rparam_len = MIN(*rparam_len,mprcnt);
3391 *rparam = REALLOC(*rparam,*rparam_len);
3395 SSVAL(*rparam,0,NERR_BufTooSmall);
3397 DEBUG(3,("Supplied buffer too small in API command\n"));
3403 /****************************************************************************
3404 The request is not supported
3405 ****************************************************************************/
3407 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3408 int mdrcnt,int mprcnt,
3409 char **rdata,char **rparam,
3410 int *rdata_len,int *rparam_len)
3413 *rparam = REALLOC(*rparam,*rparam_len);
3417 SSVAL(*rparam,0,NERR_notsupported);
3418 SSVAL(*rparam,2,0); /* converter word */
3420 DEBUG(3,("Unsupported API command\n"));
3432 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3433 int,int,char **,char **,int *,int *);
3434 BOOL auth_user; /* Deny anonymous access? */
3435 } api_commands[] = {
3436 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3437 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3438 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3439 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3440 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3441 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3442 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3443 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3444 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3445 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3446 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3447 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3448 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3449 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3450 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3451 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3452 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3453 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3454 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3455 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3456 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3457 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3458 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3459 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3460 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3461 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3462 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3463 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3464 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3465 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3466 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3467 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3468 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3469 {NULL, -1, api_Unsupported}};
3471 /* The following RAP calls are not implemented by Samba:
3473 RAP_WFileEnum2 - anon not OK
3476 /****************************************************************************
3477 Handle remote api calls
3478 ****************************************************************************/
3480 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3481 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3485 char *rparam = NULL;
3492 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3496 api_command = SVAL(params,0);
3498 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3501 skip_string(params+2,1),
3502 tdscnt,tpscnt,mdrcnt,mprcnt));
3504 for (i=0;api_commands[i].name;i++) {
3505 if (api_commands[i].id == api_command && api_commands[i].fn) {
3506 DEBUG(3,("Doing %s\n",api_commands[i].name));
3511 /* Check whether this api call can be done anonymously */
3513 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3514 user_struct *user = get_valid_user_struct(vuid);
3516 if (!user || user->guest)
3517 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3520 rdata = (char *)malloc(1024);
3522 memset(rdata,'\0',1024);
3524 rparam = (char *)malloc(1024);
3526 memset(rparam,'\0',1024);
3528 if(!rdata || !rparam) {
3529 DEBUG(0,("api_reply: malloc fail !\n"));
3533 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3534 &rdata,&rparam,&rdata_len,&rparam_len);
3537 if (rdata_len > mdrcnt ||
3538 rparam_len > mprcnt) {
3539 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3540 &rdata,&rparam,&rdata_len,&rparam_len);
3543 /* if we get False back then it's actually unsupported */
3545 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3546 &rdata,&rparam,&rdata_len,&rparam_len);
3548 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);