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;
1711 *rparam = REALLOC(*rparam,*rparam_len);
1713 /* check it's a supported varient */
1714 if (!strcmp(str1,"zWrLeh"))
1718 level_string = "B21";
1724 if (strcmp(level_string,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);
1932 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1935 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) {
1936 SSVAL(*rparam,0,NERR_Success);
1940 free_server_info(&server_info);
1942 data_blob_clear_free(&password);
1946 * If the plaintext change failed, attempt
1947 * the old encrypted method. NT will generate this
1948 * after trying the samr method. Note that this
1949 * method is done as a last resort as this
1950 * password change method loses the NT password hash
1951 * and cannot change the UNIX password as no plaintext
1955 if(SVAL(*rparam,0) != NERR_Success) {
1956 SAM_ACCOUNT *hnd = NULL;
1958 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
1960 if (change_lanman_password(hnd,(uchar *)pass2)) {
1961 SSVAL(*rparam,0,NERR_Success);
1968 memset((char *)pass1,'\0',sizeof(fstring));
1969 memset((char *)pass2,'\0',sizeof(fstring));
1974 /****************************************************************************
1975 Set the user password (SamOEM version - gets plaintext).
1976 ****************************************************************************/
1978 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1979 int mdrcnt,int mprcnt,
1980 char **rdata,char **rparam,
1981 int *rdata_len,int *rparam_len)
1984 char *p = param + 2;
1986 *rparam = REALLOC(*rparam,*rparam_len);
1990 SSVAL(*rparam,0,NERR_badpass);
1993 * Check the parameter definition is correct.
1995 if(!strequal(param + 2, "zsT")) {
1996 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1999 p = skip_string(p, 1);
2001 if(!strequal(p, "B516B16")) {
2002 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2005 p = skip_string(p,1);
2007 p += pull_ascii_fstring(user,p);
2009 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2012 * Pass the user through the NT -> unix user mapping
2016 (void)map_username(user);
2018 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)))
2020 SSVAL(*rparam,0,NERR_Success);
2026 /****************************************************************************
2029 ****************************************************************************/
2030 static BOOL api_RDosPrintJobDel(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)
2035 int function = SVAL(param,0);
2036 char *str1 = param+2;
2037 char *str2 = skip_string(str1,1);
2038 char *p = skip_string(str2,1);
2042 extern struct current_user current_user;
2043 WERROR werr = WERR_OK;
2045 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2048 /* check it's a supported varient */
2049 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2053 *rparam = REALLOC(*rparam,*rparam_len);
2056 if (!print_job_exists(snum, jobid)) {
2057 errcode = NERR_JobNotFound;
2061 errcode = NERR_notsupported;
2064 case 81: /* delete */
2065 if (print_job_delete(¤t_user, snum, jobid, &werr))
2066 errcode = NERR_Success;
2068 case 82: /* pause */
2069 if (print_job_pause(¤t_user, snum, jobid, &werr))
2070 errcode = NERR_Success;
2072 case 83: /* resume */
2073 if (print_job_resume(¤t_user, snum, jobid, &werr))
2074 errcode = NERR_Success;
2078 if (!W_ERROR_IS_OK(werr))
2079 errcode = W_ERROR_V(werr);
2082 SSVAL(*rparam,0,errcode);
2083 SSVAL(*rparam,2,0); /* converter word */
2088 /****************************************************************************
2089 Purge a print queue - or pause or resume it.
2090 ****************************************************************************/
2091 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2092 int mdrcnt,int mprcnt,
2093 char **rdata,char **rparam,
2094 int *rdata_len,int *rparam_len)
2096 int function = SVAL(param,0);
2097 char *str1 = param+2;
2098 char *str2 = skip_string(str1,1);
2099 char *QueueName = skip_string(str2,1);
2100 int errcode = NERR_notsupported;
2102 WERROR werr = WERR_OK;
2103 extern struct current_user current_user;
2105 /* check it's a supported varient */
2106 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2110 *rparam = REALLOC(*rparam,*rparam_len);
2113 snum = print_queue_snum(QueueName);
2116 errcode = NERR_JobNotFound;
2121 case 74: /* Pause queue */
2122 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2124 case 75: /* Resume queue */
2125 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2127 case 103: /* Purge */
2128 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2132 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2135 SSVAL(*rparam,0,errcode);
2136 SSVAL(*rparam,2,0); /* converter word */
2142 /****************************************************************************
2143 set the property of a print job (undocumented?)
2144 ? function = 0xb -> set name of print job
2145 ? function = 0x6 -> move print job up/down
2146 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2147 or <WWsTP> <WB21BB16B10zWWzDDz>
2148 ****************************************************************************/
2149 static int check_printjob_info(struct pack_desc* desc,
2150 int uLevel, char* id)
2152 desc->subformat = NULL;
2154 case 0: desc->format = "W"; break;
2155 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2156 case 2: desc->format = "WWzWWDDzz"; break;
2157 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2158 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2159 default: return False;
2161 if (strcmp(desc->format,id) != 0) return False;
2165 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2166 int mdrcnt,int mprcnt,
2167 char **rdata,char **rparam,
2168 int *rdata_len,int *rparam_len)
2170 struct pack_desc desc;
2171 char *str1 = param+2;
2172 char *str2 = skip_string(str1,1);
2173 char *p = skip_string(str2,1);
2176 int uLevel = SVAL(p,2);
2177 int function = SVAL(p,4);
2180 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2183 *rparam = REALLOC(*rparam,*rparam_len);
2187 /* check it's a supported varient */
2188 if ((strcmp(str1,"WWsTP")) ||
2189 (!check_printjob_info(&desc,uLevel,str2)))
2192 if (!print_job_exists(snum, jobid)) {
2193 errcode=NERR_JobNotFound;
2197 errcode = NERR_notsupported;
2201 /* change job place in the queue,
2202 data gives the new place */
2203 place = SVAL(data,0);
2204 if (print_job_set_place(snum, jobid, place)) {
2205 errcode=NERR_Success;
2210 /* change print job name, data gives the name */
2211 if (print_job_set_name(snum, jobid, data)) {
2212 errcode=NERR_Success;
2221 SSVALS(*rparam,0,errcode);
2222 SSVAL(*rparam,2,0); /* converter word */
2228 /****************************************************************************
2229 get info about the server
2230 ****************************************************************************/
2231 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2232 int mdrcnt,int mprcnt,
2233 char **rdata,char **rparam,
2234 int *rdata_len,int *rparam_len)
2236 char *str1 = param+2;
2237 char *str2 = skip_string(str1,1);
2238 char *p = skip_string(str2,1);
2239 int uLevel = SVAL(p,0);
2243 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2245 /* check it's a supported varient */
2246 if (!prefix_ok(str1,"WrLh")) return False;
2249 if (strcmp(str2,"B16") != 0) return False;
2253 if (strcmp(str2,"B16BBDz") != 0) return False;
2257 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2262 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2267 if (strcmp(str2,"DN") != 0) return False;
2271 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2274 default: return False;
2277 *rdata_len = mdrcnt;
2278 *rdata = REALLOC(*rdata,*rdata_len);
2281 p2 = p + struct_len;
2283 srvstr_push(NULL, p,local_machine,16,
2284 STR_ASCII|STR_UPPER|STR_TERMINATE);
2289 struct srv_info_struct *servers=NULL;
2292 uint32 servertype= lp_default_server_announce();
2294 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2296 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2297 for (i=0;i<count;i++)
2298 if (strequal(servers[i].name,local_machine))
2300 servertype = servers[i].type;
2301 pstrcpy(comment,servers[i].comment);
2306 SCVAL(p,0,lp_major_announce_version());
2307 SCVAL(p,1,lp_minor_announce_version());
2308 SIVAL(p,2,servertype);
2310 if (mdrcnt == struct_len) {
2313 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2314 standard_sub_conn(conn,comment,sizeof(comment));
2315 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2316 p2 = skip_string(p2,1);
2321 return False; /* not yet implemented */
2324 *rdata_len = PTR_DIFF(p2,*rdata);
2327 *rparam = REALLOC(*rparam,*rparam_len);
2328 SSVAL(*rparam,0,NERR_Success);
2329 SSVAL(*rparam,2,0); /* converter word */
2330 SSVAL(*rparam,4,*rdata_len);
2336 /****************************************************************************
2337 get info about the server
2338 ****************************************************************************/
2339 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2340 int mdrcnt,int mprcnt,
2341 char **rdata,char **rparam,
2342 int *rdata_len,int *rparam_len)
2344 char *str1 = param+2;
2345 char *str2 = skip_string(str1,1);
2346 char *p = skip_string(str2,1);
2348 extern userdom_struct current_user_info;
2349 int level = SVAL(p,0);
2351 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2354 *rparam = REALLOC(*rparam,*rparam_len);
2356 /* check it's a supported varient */
2357 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2360 *rdata_len = mdrcnt + 1024;
2361 *rdata = REALLOC(*rdata,*rdata_len);
2363 SSVAL(*rparam,0,NERR_Success);
2364 SSVAL(*rparam,2,0); /* converter word */
2370 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2371 pstrcpy(p2,local_machine);
2373 p2 = skip_string(p2,1);
2376 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2377 pstrcpy(p2,current_user_info.smb_name);
2378 p2 = skip_string(p2,1);
2381 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2382 pstrcpy(p2,lp_workgroup());
2384 p2 = skip_string(p2,1);
2387 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2388 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2391 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2392 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2393 p2 = skip_string(p2,1);
2396 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2398 p2 = skip_string(p2,1);
2401 *rdata_len = PTR_DIFF(p2,*rdata);
2403 SSVAL(*rparam,4,*rdata_len);
2408 /****************************************************************************
2409 get info about a user
2411 struct user_info_11 {
2412 char usri11_name[21]; 0-20
2414 char *usri11_comment; 22-25
2415 char *usri11_usr_comment; 26-29
2416 unsigned short usri11_priv; 30-31
2417 unsigned long usri11_auth_flags; 32-35
2418 long usri11_password_age; 36-39
2419 char *usri11_homedir; 40-43
2420 char *usri11_parms; 44-47
2421 long usri11_last_logon; 48-51
2422 long usri11_last_logoff; 52-55
2423 unsigned short usri11_bad_pw_count; 56-57
2424 unsigned short usri11_num_logons; 58-59
2425 char *usri11_logon_server; 60-63
2426 unsigned short usri11_country_code; 64-65
2427 char *usri11_workstations; 66-69
2428 unsigned long usri11_max_storage; 70-73
2429 unsigned short usri11_units_per_week; 74-75
2430 unsigned char *usri11_logon_hours; 76-79
2431 unsigned short usri11_code_page; 80-81
2436 usri11_name specifies the user name for which information is retireved
2438 usri11_pad aligns the next data structure element to a word boundary
2440 usri11_comment is a null terminated ASCII comment
2442 usri11_user_comment is a null terminated ASCII comment about the user
2444 usri11_priv specifies the level of the privilege assigned to the user.
2445 The possible values are:
2447 Name Value Description
2448 USER_PRIV_GUEST 0 Guest privilege
2449 USER_PRIV_USER 1 User privilege
2450 USER_PRV_ADMIN 2 Administrator privilege
2452 usri11_auth_flags specifies the account operator privileges. The
2453 possible values are:
2455 Name Value Description
2456 AF_OP_PRINT 0 Print operator
2459 Leach, Naik [Page 28]
2463 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2466 AF_OP_COMM 1 Communications operator
2467 AF_OP_SERVER 2 Server operator
2468 AF_OP_ACCOUNTS 3 Accounts operator
2471 usri11_password_age specifies how many seconds have elapsed since the
2472 password was last changed.
2474 usri11_home_dir points to a null terminated ASCII string that contains
2475 the path name of the user's home directory.
2477 usri11_parms points to a null terminated ASCII string that is set
2478 aside for use by applications.
2480 usri11_last_logon specifies the time when the user last logged on.
2481 This value is stored as the number of seconds elapsed since
2482 00:00:00, January 1, 1970.
2484 usri11_last_logoff specifies the time when the user last logged off.
2485 This value is stored as the number of seconds elapsed since
2486 00:00:00, January 1, 1970. A value of 0 means the last logoff
2489 usri11_bad_pw_count specifies the number of incorrect passwords
2490 entered since the last successful logon.
2492 usri11_log1_num_logons specifies the number of times this user has
2493 logged on. A value of -1 means the number of logons is unknown.
2495 usri11_logon_server points to a null terminated ASCII string that
2496 contains the name of the server to which logon requests are sent.
2497 A null string indicates logon requests should be sent to the
2500 usri11_country_code specifies the country code for the user's language
2503 usri11_workstations points to a null terminated ASCII string that
2504 contains the names of workstations the user may log on from.
2505 There may be up to 8 workstations, with the names separated by
2506 commas. A null strings indicates there are no restrictions.
2508 usri11_max_storage specifies the maximum amount of disk space the user
2509 can occupy. A value of 0xffffffff indicates there are no
2512 usri11_units_per_week specifies the equal number of time units into
2513 which a week is divided. This value must be equal to 168.
2515 usri11_logon_hours points to a 21 byte (168 bits) string that
2516 specifies the time during which the user can log on. Each bit
2517 represents one unique hour in a week. The first bit (bit 0, word
2518 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2522 Leach, Naik [Page 29]
2526 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2529 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2530 are no restrictions.
2532 usri11_code_page specifies the code page for the user's language of
2535 All of the pointers in this data structure need to be treated
2536 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2537 to be ignored. The converter word returned in the parameters section
2538 needs to be subtracted from the lower 16 bits to calculate an offset
2539 into the return buffer where this ASCII string resides.
2541 There is no auxiliary data in the response.
2543 ****************************************************************************/
2545 #define usri11_name 0
2546 #define usri11_pad 21
2547 #define usri11_comment 22
2548 #define usri11_usr_comment 26
2549 #define usri11_full_name 30
2550 #define usri11_priv 34
2551 #define usri11_auth_flags 36
2552 #define usri11_password_age 40
2553 #define usri11_homedir 44
2554 #define usri11_parms 48
2555 #define usri11_last_logon 52
2556 #define usri11_last_logoff 56
2557 #define usri11_bad_pw_count 60
2558 #define usri11_num_logons 62
2559 #define usri11_logon_server 64
2560 #define usri11_country_code 68
2561 #define usri11_workstations 70
2562 #define usri11_max_storage 74
2563 #define usri11_units_per_week 78
2564 #define usri11_logon_hours 80
2565 #define usri11_code_page 84
2566 #define usri11_end 86
2568 #define USER_PRIV_GUEST 0
2569 #define USER_PRIV_USER 1
2570 #define USER_PRIV_ADMIN 2
2572 #define AF_OP_PRINT 0
2573 #define AF_OP_COMM 1
2574 #define AF_OP_SERVER 2
2575 #define AF_OP_ACCOUNTS 3
2578 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2579 int mdrcnt,int mprcnt,
2580 char **rdata,char **rparam,
2581 int *rdata_len,int *rparam_len)
2583 char *str1 = param+2;
2584 char *str2 = skip_string(str1,1);
2585 char *UserName = skip_string(str2,1);
2586 char *p = skip_string(UserName,1);
2587 int uLevel = SVAL(p,0);
2589 const char *level_string;
2591 /* get NIS home of a previously validated user - simeon */
2592 /* With share level security vuid will always be zero.
2593 Don't depend on vuser being non-null !!. JRA */
2594 user_struct *vuser = get_valid_user_struct(vuid);
2596 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2597 vuser->user.unix_name));
2600 *rparam = REALLOC(*rparam,*rparam_len);
2602 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2604 /* check it's a supported variant */
2605 if (strcmp(str1,"zWrLh") != 0) return False;
2608 case 0: level_string = "B21"; break;
2609 case 1: level_string = "B21BB16DWzzWz"; break;
2610 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2611 case 10: level_string = "B21Bzzz"; break;
2612 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2613 default: return False;
2616 if (strcmp(level_string,str2) != 0) return False;
2618 *rdata_len = mdrcnt + 1024;
2619 *rdata = REALLOC(*rdata,*rdata_len);
2621 SSVAL(*rparam,0,NERR_Success);
2622 SSVAL(*rparam,2,0); /* converter word */
2625 p2 = p + usri11_end;
2628 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2632 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2637 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2638 pstrcpy(p2,"Comment");
2639 p2 = skip_string(p2,1);
2641 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2642 pstrcpy(p2,"UserComment");
2643 p2 = skip_string(p2,1);
2645 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2646 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2647 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2648 p2 = skip_string(p2,1);
2651 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2653 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2654 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2655 SIVALS(p,usri11_password_age,-1); /* password age */
2656 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2657 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2658 p2 = skip_string(p2,1);
2659 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2661 p2 = skip_string(p2,1);
2662 SIVAL(p,usri11_last_logon,0); /* last logon */
2663 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2664 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2665 SSVALS(p,usri11_num_logons,-1); /* num logons */
2666 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2667 pstrcpy(p2,"\\\\*");
2668 p2 = skip_string(p2,1);
2669 SSVAL(p,usri11_country_code,0); /* country code */
2671 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2673 p2 = skip_string(p2,1);
2675 SIVALS(p,usri11_max_storage,-1); /* max storage */
2676 SSVAL(p,usri11_units_per_week,168); /* units per week */
2677 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2679 /* a simple way to get logon hours at all times. */
2681 SCVAL(p2,21,0); /* fix zero termination */
2682 p2 = skip_string(p2,1);
2684 SSVAL(p,usri11_code_page,0); /* code page */
2686 if (uLevel == 1 || uLevel == 2)
2688 memset(p+22,' ',16); /* password */
2689 SIVALS(p,38,-1); /* password age */
2691 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2692 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2693 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2694 p2 = skip_string(p2,1);
2695 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2697 SSVAL(p,52,0); /* flags */
2698 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2699 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2700 p2 = skip_string(p2,1);
2703 SIVAL(p,60,0); /* auth_flags */
2704 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2705 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2706 p2 = skip_string(p2,1);
2707 SIVAL(p,68,0); /* urs_comment */
2708 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2710 p2 = skip_string(p2,1);
2711 SIVAL(p,76,0); /* workstations */
2712 SIVAL(p,80,0); /* last_logon */
2713 SIVAL(p,84,0); /* last_logoff */
2714 SIVALS(p,88,-1); /* acct_expires */
2715 SIVALS(p,92,-1); /* max_storage */
2716 SSVAL(p,96,168); /* units_per_week */
2717 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2720 SSVALS(p,102,-1); /* bad_pw_count */
2721 SSVALS(p,104,-1); /* num_logons */
2722 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2723 pstrcpy(p2,"\\\\%L");
2724 standard_sub_conn(conn, p2,0);
2725 p2 = skip_string(p2,1);
2726 SSVAL(p,110,49); /* country_code */
2727 SSVAL(p,112,860); /* code page */
2731 *rdata_len = PTR_DIFF(p2,*rdata);
2733 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2738 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2739 int mdrcnt,int mprcnt,
2740 char **rdata,char **rparam,
2741 int *rdata_len,int *rparam_len)
2743 char *str1 = param+2;
2744 char *str2 = skip_string(str1,1);
2745 char *p = skip_string(str2,1);
2747 struct pack_desc desc;
2749 /* With share level security vuid will always be zero.
2750 Don't depend on vuser being non-null !!. JRA */
2751 user_struct *vuser = get_valid_user_struct(vuid);
2753 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2754 vuser->user.unix_name));
2759 memset((char *)&desc,'\0',sizeof(desc));
2761 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2763 /* check it's a supported varient */
2764 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2765 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2766 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2768 desc.buflen = mdrcnt;
2769 desc.subformat = NULL;
2772 if (init_package(&desc,1,0))
2774 PACKI(&desc,"W",0); /* code */
2775 PACKS(&desc,"B21",name); /* eff. name */
2776 PACKS(&desc,"B",""); /* pad */
2778 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2779 PACKI(&desc,"D",0); /* auth flags XXX */
2780 PACKI(&desc,"W",0); /* num logons */
2781 PACKI(&desc,"W",0); /* bad pw count */
2782 PACKI(&desc,"D",0); /* last logon */
2783 PACKI(&desc,"D",-1); /* last logoff */
2784 PACKI(&desc,"D",-1); /* logoff time */
2785 PACKI(&desc,"D",-1); /* kickoff time */
2786 PACKI(&desc,"D",0); /* password age */
2787 PACKI(&desc,"D",0); /* password can change */
2788 PACKI(&desc,"D",-1); /* password must change */
2791 fstrcpy(mypath,"\\\\");
2792 fstrcat(mypath,local_machine);
2794 PACKS(&desc,"z",mypath); /* computer */
2796 PACKS(&desc,"z",lp_workgroup());/* domain */
2798 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2800 PACKI(&desc,"D",0x00000000); /* reserved */
2803 *rdata_len = desc.usedlen;
2805 *rparam = REALLOC(*rparam,*rparam_len);
2806 SSVALS(*rparam,0,desc.errcode);
2808 SSVAL(*rparam,4,desc.neededlen);
2810 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2815 /****************************************************************************
2816 api_WAccessGetUserPerms
2817 ****************************************************************************/
2818 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2819 int mdrcnt,int mprcnt,
2820 char **rdata,char **rparam,
2821 int *rdata_len,int *rparam_len)
2823 char *str1 = param+2;
2824 char *str2 = skip_string(str1,1);
2825 char *user = skip_string(str2,1);
2826 char *resource = skip_string(user,1);
2828 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2830 /* check it's a supported varient */
2831 if (strcmp(str1,"zzh") != 0) return False;
2832 if (strcmp(str2,"") != 0) return False;
2835 *rparam = REALLOC(*rparam,*rparam_len);
2836 SSVALS(*rparam,0,0); /* errorcode */
2837 SSVAL(*rparam,2,0); /* converter word */
2838 SSVAL(*rparam,4,0x7f); /* permission flags */
2843 /****************************************************************************
2844 api_WPrintJobEnumerate
2845 ****************************************************************************/
2846 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2847 int mdrcnt,int mprcnt,
2848 char **rdata,char **rparam,
2849 int *rdata_len,int *rparam_len)
2851 char *str1 = param+2;
2852 char *str2 = skip_string(str1,1);
2853 char *p = skip_string(str2,1);
2859 struct pack_desc desc;
2860 print_queue_struct *queue=NULL;
2861 print_status_struct status;
2866 memset((char *)&desc,'\0',sizeof(desc));
2867 memset((char *)&status,'\0',sizeof(status));
2869 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2871 /* check it's a supported varient */
2872 if (strcmp(str1,"WWrLh") != 0) return False;
2873 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2875 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2878 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2880 count = print_queue_status(snum,&queue,&status);
2881 for (i = 0; i < count; i++) {
2882 if (queue[i].job == jobid) break;
2886 *rdata = REALLOC(*rdata,mdrcnt);
2888 desc.buflen = mdrcnt;
2891 * Don't return data but need to get correct length
2892 * init_package will return wrong size if buflen=0
2894 desc.buflen = getlen(desc.format);
2895 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2898 if (init_package(&desc,1,0)) {
2900 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2901 *rdata_len = desc.usedlen;
2904 desc.errcode = NERR_JobNotFound;
2910 *rparam = REALLOC(*rparam,*rparam_len);
2911 SSVALS(*rparam,0,desc.errcode);
2913 SSVAL(*rparam,4,desc.neededlen);
2918 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2922 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2923 int mdrcnt,int mprcnt,
2924 char **rdata,char **rparam,
2925 int *rdata_len,int *rparam_len)
2927 char *str1 = param+2;
2928 char *str2 = skip_string(str1,1);
2929 char *p = skip_string(str2,1);
2935 struct pack_desc desc;
2936 print_queue_struct *queue=NULL;
2937 print_status_struct status;
2939 memset((char *)&desc,'\0',sizeof(desc));
2940 memset((char *)&status,'\0',sizeof(status));
2942 p = skip_string(p,1);
2945 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2947 /* check it's a supported variant */
2948 if (strcmp(str1,"zWrLeh") != 0) return False;
2949 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2950 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2952 snum = lp_servicenumber(name);
2953 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2954 int pnum = lp_servicenumber(PRINTERS_NAME);
2956 lp_add_printer(name,pnum);
2957 snum = lp_servicenumber(name);
2961 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2963 count = print_queue_status(snum,&queue,&status);
2964 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2966 desc.buflen = mdrcnt;
2968 if (init_package(&desc,count,0)) {
2970 for (i = 0; i < count; i++) {
2971 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2972 if (desc.errcode == NERR_Success) succnt = i+1;
2976 *rdata_len = desc.usedlen;
2979 *rparam = REALLOC(*rparam,*rparam_len);
2980 SSVALS(*rparam,0,desc.errcode);
2982 SSVAL(*rparam,4,succnt);
2983 SSVAL(*rparam,6,count);
2987 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2991 static int check_printdest_info(struct pack_desc* desc,
2992 int uLevel, char* id)
2994 desc->subformat = NULL;
2996 case 0: desc->format = "B9"; break;
2997 case 1: desc->format = "B9B21WWzW"; break;
2998 case 2: desc->format = "z"; break;
2999 case 3: desc->format = "zzzWWzzzWW"; break;
3000 default: return False;
3002 if (strcmp(desc->format,id) != 0) return False;
3006 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3007 struct pack_desc* desc)
3010 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3011 buf[sizeof(buf)-1] = 0;
3014 PACKS(desc,"B9",buf); /* szName */
3016 PACKS(desc,"B21",""); /* szUserName */
3017 PACKI(desc,"W",0); /* uJobId */
3018 PACKI(desc,"W",0); /* fsStatus */
3019 PACKS(desc,"z",""); /* pszStatus */
3020 PACKI(desc,"W",0); /* time */
3023 if (uLevel == 2 || uLevel == 3) {
3024 PACKS(desc,"z",buf); /* pszPrinterName */
3026 PACKS(desc,"z",""); /* pszUserName */
3027 PACKS(desc,"z",""); /* pszLogAddr */
3028 PACKI(desc,"W",0); /* uJobId */
3029 PACKI(desc,"W",0); /* fsStatus */
3030 PACKS(desc,"z",""); /* pszStatus */
3031 PACKS(desc,"z",""); /* pszComment */
3032 PACKS(desc,"z","NULL"); /* pszDrivers */
3033 PACKI(desc,"W",0); /* time */
3034 PACKI(desc,"W",0); /* pad1 */
3039 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3040 int mdrcnt,int mprcnt,
3041 char **rdata,char **rparam,
3042 int *rdata_len,int *rparam_len)
3044 char *str1 = param+2;
3045 char *str2 = skip_string(str1,1);
3046 char *p = skip_string(str2,1);
3047 char* PrinterName = p;
3049 struct pack_desc desc;
3053 memset((char *)&desc,'\0',sizeof(desc));
3055 p = skip_string(p,1);
3058 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3060 /* check it's a supported varient */
3061 if (strcmp(str1,"zWrLh") != 0) return False;
3062 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3064 snum = lp_servicenumber(PrinterName);
3065 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3066 int pnum = lp_servicenumber(PRINTERS_NAME);
3068 lp_add_printer(PrinterName,pnum);
3069 snum = lp_servicenumber(PrinterName);
3075 desc.errcode = NERR_DestNotFound;
3080 *rdata = REALLOC(*rdata,mdrcnt);
3082 desc.buflen = mdrcnt;
3085 * Don't return data but need to get correct length
3086 * init_package will return wrong size if buflen=0
3088 desc.buflen = getlen(desc.format);
3089 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3091 if (init_package(&desc,1,0)) {
3092 fill_printdest_info(conn,snum,uLevel,&desc);
3094 *rdata_len = desc.usedlen;
3098 *rparam = REALLOC(*rparam,*rparam_len);
3099 SSVALS(*rparam,0,desc.errcode);
3101 SSVAL(*rparam,4,desc.neededlen);
3103 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3108 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3109 int mdrcnt,int mprcnt,
3110 char **rdata,char **rparam,
3111 int *rdata_len,int *rparam_len)
3113 char *str1 = param+2;
3114 char *str2 = skip_string(str1,1);
3115 char *p = skip_string(str2,1);
3119 struct pack_desc desc;
3120 int services = lp_numservices();
3122 memset((char *)&desc,'\0',sizeof(desc));
3126 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3128 /* check it's a supported varient */
3129 if (strcmp(str1,"WrLeh") != 0) return False;
3130 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3133 for (i = 0; i < services; i++)
3134 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3137 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3139 desc.buflen = mdrcnt;
3140 if (init_package(&desc,queuecnt,0)) {
3143 for (i = 0; i < services; i++) {
3144 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3145 fill_printdest_info(conn,i,uLevel,&desc);
3147 if (desc.errcode == NERR_Success) succnt = n;
3152 *rdata_len = desc.usedlen;
3155 *rparam = REALLOC(*rparam,*rparam_len);
3156 SSVALS(*rparam,0,desc.errcode);
3158 SSVAL(*rparam,4,succnt);
3159 SSVAL(*rparam,6,queuecnt);
3161 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3165 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3166 int mdrcnt,int mprcnt,
3167 char **rdata,char **rparam,
3168 int *rdata_len,int *rparam_len)
3170 char *str1 = param+2;
3171 char *str2 = skip_string(str1,1);
3172 char *p = skip_string(str2,1);
3175 struct pack_desc desc;
3177 memset((char *)&desc,'\0',sizeof(desc));
3181 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3183 /* check it's a supported varient */
3184 if (strcmp(str1,"WrLeh") != 0) return False;
3185 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3187 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3189 desc.buflen = mdrcnt;
3190 if (init_package(&desc,1,0)) {
3191 PACKS(&desc,"B41","NULL");
3194 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3196 *rdata_len = desc.usedlen;
3199 *rparam = REALLOC(*rparam,*rparam_len);
3200 SSVALS(*rparam,0,desc.errcode);
3202 SSVAL(*rparam,4,succnt);
3205 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3209 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3210 int mdrcnt,int mprcnt,
3211 char **rdata,char **rparam,
3212 int *rdata_len,int *rparam_len)
3214 char *str1 = param+2;
3215 char *str2 = skip_string(str1,1);
3216 char *p = skip_string(str2,1);
3219 struct pack_desc desc;
3221 memset((char *)&desc,'\0',sizeof(desc));
3225 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3227 /* check it's a supported varient */
3228 if (strcmp(str1,"WrLeh") != 0) return False;
3229 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3231 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3233 desc.buflen = mdrcnt;
3235 if (init_package(&desc,1,0)) {
3236 PACKS(&desc,"B13","lpd");
3239 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3241 *rdata_len = desc.usedlen;
3244 *rparam = REALLOC(*rparam,*rparam_len);
3245 SSVALS(*rparam,0,desc.errcode);
3247 SSVAL(*rparam,4,succnt);
3250 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3254 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3255 int mdrcnt,int mprcnt,
3256 char **rdata,char **rparam,
3257 int *rdata_len,int *rparam_len)
3259 char *str1 = param+2;
3260 char *str2 = skip_string(str1,1);
3261 char *p = skip_string(str2,1);
3264 struct pack_desc desc;
3266 memset((char *)&desc,'\0',sizeof(desc));
3270 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3272 /* check it's a supported varient */
3273 if (strcmp(str1,"WrLeh") != 0) return False;
3274 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3276 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3277 memset((char *)&desc,'\0',sizeof(desc));
3279 desc.buflen = mdrcnt;
3281 if (init_package(&desc,1,0)) {
3282 PACKS(&desc,"B13","lp0");
3285 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3287 *rdata_len = desc.usedlen;
3290 *rparam = REALLOC(*rparam,*rparam_len);
3291 SSVALS(*rparam,0,desc.errcode);
3293 SSVAL(*rparam,4,succnt);
3296 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3301 /****************************************************************************
3303 ****************************************************************************/
3304 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3305 int mdrcnt,int mprcnt,
3306 char **rdata,char **rparam,
3307 int *rdata_len,int *rparam_len)
3310 char *str1 = param+2;
3311 char *str2 = skip_string(str1,1);
3312 char *p = skip_string(str2,1);
3314 struct pack_desc desc;
3315 struct sessionid *session_list;
3316 int i, num_sessions;
3318 memset((char *)&desc,'\0',sizeof(desc));
3322 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3323 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3324 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3326 /* check it's a supported varient */
3327 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3328 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3330 num_sessions = list_sessions(&session_list);
3332 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3333 memset((char *)&desc,'\0',sizeof(desc));
3335 desc.buflen = mdrcnt;
3337 if (!init_package(&desc,num_sessions,0)) {
3341 for(i=0; i<num_sessions; i++) {
3342 PACKS(&desc, "z", session_list[i].remote_machine);
3343 PACKS(&desc, "z", session_list[i].username);
3344 PACKI(&desc, "W", 1); /* num conns */
3345 PACKI(&desc, "W", 0); /* num opens */
3346 PACKI(&desc, "W", 1); /* num users */
3347 PACKI(&desc, "D", 0); /* session time */
3348 PACKI(&desc, "D", 0); /* idle time */
3349 PACKI(&desc, "D", 0); /* flags */
3350 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3353 *rdata_len = desc.usedlen;
3356 *rparam = REALLOC(*rparam,*rparam_len);
3357 SSVALS(*rparam,0,desc.errcode);
3358 SSVAL(*rparam,2,0); /* converter */
3359 SSVAL(*rparam,4,num_sessions); /* count */
3361 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3366 /****************************************************************************
3367 The buffer was too small
3368 ****************************************************************************/
3370 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3371 int mdrcnt,int mprcnt,
3372 char **rdata,char **rparam,
3373 int *rdata_len,int *rparam_len)
3375 *rparam_len = MIN(*rparam_len,mprcnt);
3376 *rparam = REALLOC(*rparam,*rparam_len);
3380 SSVAL(*rparam,0,NERR_BufTooSmall);
3382 DEBUG(3,("Supplied buffer too small in API command\n"));
3388 /****************************************************************************
3389 The request is not supported
3390 ****************************************************************************/
3392 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3393 int mdrcnt,int mprcnt,
3394 char **rdata,char **rparam,
3395 int *rdata_len,int *rparam_len)
3398 *rparam = REALLOC(*rparam,*rparam_len);
3402 SSVAL(*rparam,0,NERR_notsupported);
3403 SSVAL(*rparam,2,0); /* converter word */
3405 DEBUG(3,("Unsupported API command\n"));
3417 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3418 int,int,char **,char **,int *,int *);
3419 BOOL auth_user; /* Deny anonymous access? */
3420 } api_commands[] = {
3421 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3422 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3423 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3424 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3425 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3426 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3427 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3428 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3429 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3430 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3431 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3432 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3433 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3434 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3435 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3436 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3437 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3438 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3439 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3440 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3441 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3442 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3443 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3444 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3445 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3446 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3447 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3448 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3449 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3450 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3451 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3452 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3453 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3454 {NULL, -1, api_Unsupported}};
3456 /* The following RAP calls are not implemented by Samba:
3458 RAP_WFileEnum2 - anon not OK
3461 /****************************************************************************
3462 Handle remote api calls
3463 ****************************************************************************/
3465 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3466 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3470 char *rparam = NULL;
3477 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3481 api_command = SVAL(params,0);
3483 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3486 skip_string(params+2,1),
3487 tdscnt,tpscnt,mdrcnt,mprcnt));
3489 for (i=0;api_commands[i].name;i++) {
3490 if (api_commands[i].id == api_command && api_commands[i].fn) {
3491 DEBUG(3,("Doing %s\n",api_commands[i].name));
3496 /* Check whether this api call can be done anonymously */
3498 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3499 user_struct *user = get_valid_user_struct(vuid);
3501 if (!user || user->guest)
3502 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3505 rdata = (char *)malloc(1024);
3507 memset(rdata,'\0',1024);
3509 rparam = (char *)malloc(1024);
3511 memset(rparam,'\0',1024);
3513 if(!rdata || !rparam) {
3514 DEBUG(0,("api_reply: malloc fail !\n"));
3518 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3519 &rdata,&rparam,&rdata_len,&rparam_len);
3522 if (rdata_len > mdrcnt ||
3523 rparam_len > mprcnt) {
3524 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3525 &rdata,&rparam,&rdata_len,&rparam_len);
3528 /* if we get False back then it's actually unsupported */
3530 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3531 &rdata,&rparam,&rdata_len,&rparam_len);
3533 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);