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
30 extern struct current_user current_user;
31 extern userdom_struct current_user_info;
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param, char *data,
54 int mdrcnt, int mprcnt,
55 char **rdata, char **rparam,
56 int *rdata_len, int *rparam_len);
57 static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
58 int mdrcnt, int mprcnt,
59 char **rdata, char **rparam,
60 int *rdata_len, int *rparam_len);
63 static int CopyExpanded(connection_struct *conn,
64 int snum, char **dst, char *src, int *n)
69 if (!src || !dst || !n || !(*dst)) {
73 StrnCpy(buf,src,sizeof(buf)/2);
74 pstring_sub(buf,"%S",lp_servicename(snum));
75 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
76 conn->connectpath, conn->gid,
77 get_current_username(),
78 current_user_info.domain,
80 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
86 static int CopyAndAdvance(char **dst, char *src, int *n)
89 if (!src || !dst || !n || !(*dst)) {
92 l = push_ascii(*dst,src,*n, STR_TERMINATE);
98 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
104 StrnCpy(buf,s,sizeof(buf)/2);
105 pstring_sub(buf,"%S",lp_servicename(snum));
106 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
107 conn->connectpath, conn->gid,
108 get_current_username(),
109 current_user_info.domain,
111 return strlen(buf) + 1;
114 static char *Expand(connection_struct *conn, int snum, char *s)
120 StrnCpy(buf,s,sizeof(buf)/2);
121 pstring_sub(buf,"%S",lp_servicename(snum));
122 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
123 conn->connectpath, conn->gid,
124 get_current_username(),
125 current_user_info.domain,
130 /*******************************************************************
131 Check a API string for validity when we only need to check the prefix.
132 ******************************************************************/
134 static BOOL prefix_ok(const char *str, const char *prefix)
136 return(strncmp(str,prefix,strlen(prefix)) == 0);
140 const char *format; /* formatstring for structure */
141 const char *subformat; /* subformat for structure */
142 char *base; /* baseaddress of buffer */
143 int buflen; /* remaining size for fixed part; on init: length of base */
144 int subcount; /* count of substructures */
145 char *structbuf; /* pointer into buffer for remaining fixed part */
146 int stringlen; /* remaining size for variable part */
147 char *stringbuf; /* pointer into buffer for remaining variable part */
148 int neededlen; /* total needed size */
149 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
150 const char *curpos; /* current position; pointer into format or subformat */
154 static int get_counter(const char **p)
160 if (!isdigit((int)**p)) {
166 n = 10 * n + (i - '0');
174 static int getlen(const char *p)
183 case 'W': /* word (2 byte) */
186 case 'K': /* status word? (2 byte) */
189 case 'N': /* count of substructures (word) at end */
192 case 'D': /* double word (4 byte) */
193 case 'z': /* offset to zero terminated string (4 byte) */
194 case 'l': /* offset to user data (4 byte) */
197 case 'b': /* offset to data (with counter) (4 byte) */
201 case 'B': /* byte (with optional counter) */
202 n += get_counter(&p);
209 static BOOL init_package(struct pack_desc *p, int count, int subcount)
214 if (!p->format || !p->base) {
218 i = count * getlen(p->format);
220 i += subcount * getlen(p->subformat);
222 p->structbuf = p->base;
226 p->curpos = p->format;
232 * This is the old error code we used. Aparently
233 * WinNT/2k systems return ERRbuftoosmall (2123) and
234 * OS/2 needs this. I'm leaving this here so we can revert
237 p->errcode = ERRmoredata;
239 p->errcode = ERRbuftoosmall;
242 p->errcode = NERR_Success;
246 p->stringbuf = p->base + i;
248 return (p->errcode == NERR_Success);
251 static int package(struct pack_desc *p, ...)
254 int needed=0, stringneeded;
255 const char *str=NULL;
256 int is_string=0, stringused;
263 p->curpos = p->format;
265 p->curpos = p->subformat;
270 str = va_arg(args,char*);
271 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
280 switch( *p->curpos++ ) {
281 case 'W': /* word (2 byte) */
283 temp = va_arg(args,int);
284 if (p->buflen >= needed) {
285 SSVAL(p->structbuf,0,temp);
288 case 'K': /* status word? (2 byte) */
290 temp = va_arg(args,int);
291 if (p->buflen >= needed) {
292 SSVAL(p->structbuf,0,temp);
295 case 'N': /* count of substructures (word) at end */
297 p->subcount = va_arg(args,int);
298 if (p->buflen >= needed) {
299 SSVAL(p->structbuf,0,p->subcount);
302 case 'D': /* double word (4 byte) */
304 temp = va_arg(args,int);
305 if (p->buflen >= needed) {
306 SIVAL(p->structbuf,0,temp);
309 case 'B': /* byte (with optional counter) */
310 needed = get_counter(&p->curpos);
312 char *s = va_arg(args,char*);
313 if (p->buflen >= needed) {
314 StrnCpy(p->structbuf,s?s:"",needed-1);
318 case 'z': /* offset to zero terminated string (4 byte) */
319 str = va_arg(args,char*);
320 stringneeded = (str ? strlen(str)+1 : 0);
323 case 'l': /* offset to user data (4 byte) */
324 str = va_arg(args,char*);
325 stringneeded = va_arg(args,int);
328 case 'b': /* offset to data (with counter) (4 byte) */
329 str = va_arg(args,char*);
330 stringneeded = get_counter(&p->curpos);
336 if (stringneeded >= 0) {
338 if (p->buflen >= needed) {
339 stringused = stringneeded;
340 if (stringused > p->stringlen) {
341 stringused = (is_string ? p->stringlen : 0);
342 if (p->errcode == NERR_Success) {
343 p->errcode = ERRmoredata;
347 SIVAL(p->structbuf,0,0);
349 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
350 memcpy(p->stringbuf,str?str:"",stringused);
352 p->stringbuf[stringused-1] = '\0';
354 p->stringbuf += stringused;
355 p->stringlen -= stringused;
356 p->usedlen += stringused;
359 p->neededlen += stringneeded;
362 p->neededlen += needed;
363 if (p->buflen >= needed) {
364 p->structbuf += needed;
366 p->usedlen += needed;
368 if (p->errcode == NERR_Success) {
369 p->errcode = ERRmoredata;
376 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
377 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
379 #define PACK(desc,t,v) package(desc,v)
380 #define PACKl(desc,t,v,l) package(desc,v,l)
383 static void PACKI(struct pack_desc* desc, const char *t,int v)
388 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
393 /****************************************************************************
395 ****************************************************************************/
397 static void PackDriverData(struct pack_desc* desc)
399 char drivdata[4+4+32];
400 SIVAL(drivdata,0,sizeof drivdata); /* cb */
401 SIVAL(drivdata,4,1000); /* lVersion */
402 memset(drivdata+8,0,32); /* szDeviceName */
403 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
404 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
407 static int check_printq_info(struct pack_desc* desc,
408 unsigned int uLevel, char *id1, char *id2)
410 desc->subformat = NULL;
413 desc->format = "B13";
416 desc->format = "B13BWWWzzzzzWW";
419 desc->format = "B13BWWWzzzzzWN";
420 desc->subformat = "WB21BB16B10zWWzDDz";
423 desc->format = "zWWWWzzzzWWzzl";
426 desc->format = "zWWWWzzzzWNzzl";
427 desc->subformat = "WWzWWDDzz";
436 desc->format = "WzzzzzzzzN";
437 desc->subformat = "z";
442 if (strcmp(desc->format,id1) != 0) {
445 if (desc->subformat && strcmp(desc->subformat,id2) != 0) {
452 #define RAP_JOB_STATUS_QUEUED 0
453 #define RAP_JOB_STATUS_PAUSED 1
454 #define RAP_JOB_STATUS_SPOOLING 2
455 #define RAP_JOB_STATUS_PRINTING 3
456 #define RAP_JOB_STATUS_PRINTED 4
458 #define RAP_QUEUE_STATUS_PAUSED 1
459 #define RAP_QUEUE_STATUS_ERROR 2
461 /* turn a print job status into a on the wire status
463 static int printj_status(int v)
467 return RAP_JOB_STATUS_QUEUED;
469 return RAP_JOB_STATUS_PAUSED;
471 return RAP_JOB_STATUS_SPOOLING;
473 return RAP_JOB_STATUS_PRINTING;
478 /* turn a print queue status into a on the wire status
480 static int printq_status(int v)
486 return RAP_QUEUE_STATUS_PAUSED;
488 return RAP_QUEUE_STATUS_ERROR;
491 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
492 struct pack_desc *desc,
493 print_queue_struct *queue, int n)
495 time_t t = queue->time;
497 /* the client expects localtime */
498 t -= get_time_zone(t);
500 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
502 PACKS(desc,"B21",queue->fs_user); /* szUserName */
503 PACKS(desc,"B",""); /* pad */
504 PACKS(desc,"B16",""); /* szNotifyName */
505 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
506 PACKS(desc,"z",""); /* pszParms */
507 PACKI(desc,"W",n+1); /* uPosition */
508 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
509 PACKS(desc,"z",""); /* pszStatus */
510 PACKI(desc,"D",t); /* ulSubmitted */
511 PACKI(desc,"D",queue->size); /* ulSize */
512 PACKS(desc,"z",queue->fs_file); /* pszComment */
514 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
515 PACKI(desc,"W",queue->priority); /* uPriority */
516 PACKS(desc,"z",queue->fs_user); /* pszUserName */
517 PACKI(desc,"W",n+1); /* uPosition */
518 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
519 PACKI(desc,"D",t); /* ulSubmitted */
520 PACKI(desc,"D",queue->size); /* ulSize */
521 PACKS(desc,"z","Samba"); /* pszComment */
522 PACKS(desc,"z",queue->fs_file); /* pszDocument */
524 PACKS(desc,"z",""); /* pszNotifyName */
525 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
526 PACKS(desc,"z",""); /* pszParms */
527 PACKS(desc,"z",""); /* pszStatus */
528 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
529 PACKS(desc,"z","lpd"); /* pszQProcName */
530 PACKS(desc,"z",""); /* pszQProcParms */
531 PACKS(desc,"z","NULL"); /* pszDriverName */
532 PackDriverData(desc); /* pDriverData */
533 PACKS(desc,"z",""); /* pszPrinterName */
534 } else if (uLevel == 4) { /* OS2 */
535 PACKS(desc,"z",""); /* pszSpoolFileName */
536 PACKS(desc,"z",""); /* pszPortName */
537 PACKS(desc,"z",""); /* pszStatus */
538 PACKI(desc,"D",0); /* ulPagesSpooled */
539 PACKI(desc,"D",0); /* ulPagesSent */
540 PACKI(desc,"D",0); /* ulPagesPrinted */
541 PACKI(desc,"D",0); /* ulTimePrinted */
542 PACKI(desc,"D",0); /* ulExtendJobStatus */
543 PACKI(desc,"D",0); /* ulStartPage */
544 PACKI(desc,"D",0); /* ulEndPage */
549 /********************************************************************
550 Return a driver name given an snum.
551 Returns True if from tdb, False otherwise.
552 ********************************************************************/
554 static BOOL get_driver_name(int snum, pstring drivername)
556 NT_PRINTER_INFO_LEVEL *info = NULL;
559 get_a_printer (NULL, &info, 2, lp_servicename(snum));
561 pstrcpy( drivername, info->info_2->drivername);
563 free_a_printer(&info, 2);
569 /********************************************************************
570 Respond to the DosPrintQInfo command with a level of 52
571 This is used to get printer driver information for Win9x clients
572 ********************************************************************/
573 static void fill_printq_info_52(connection_struct *conn, int snum,
574 struct pack_desc* desc, int count )
578 NT_PRINTER_DRIVER_INFO_LEVEL driver;
579 NT_PRINTER_INFO_LEVEL *printer = NULL;
583 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
584 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
585 lp_servicename(snum)));
589 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
592 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
593 printer->info_2->drivername));
597 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
598 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
599 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
601 PACKI(desc, "W", 0x0400); /* don't know */
602 PACKS(desc, "z", driver.info_3->name); /* long printer name */
603 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
604 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
605 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
607 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
608 standard_sub_basic( "", "", location, sizeof(location)-1 );
609 PACKS(desc,"z", location); /* share to retrieve files */
611 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
612 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
613 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
615 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
616 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
617 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
618 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
619 DEBUG(3,("Driver Location: %s:\n",location));
620 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
621 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
622 PACKI(desc,"N",count); /* number of files to copy */
624 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
626 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
627 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
628 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
633 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
636 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
638 desc->errcode=NERR_Success;
642 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
643 desc->errcode=NERR_notsupported;
647 free_a_printer( &printer, 2 );
650 free_a_printer_driver( driver, 3 );
654 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
655 struct pack_desc* desc,
656 int count, print_queue_struct* queue,
657 print_status_struct* status)
662 PACKS(desc,"B13",SERVICE(snum));
667 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
670 PACKI(desc,"K",printq_status(status->status));
674 if (uLevel == 1 || uLevel == 2) {
675 PACKS(desc,"B",""); /* alignment */
676 PACKI(desc,"W",5); /* priority */
677 PACKI(desc,"W",0); /* start time */
678 PACKI(desc,"W",0); /* until time */
679 PACKS(desc,"z",""); /* pSepFile */
680 PACKS(desc,"z","lpd"); /* pPrProc */
681 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
682 PACKS(desc,"z",""); /* pParms */
684 PACKS(desc,"z","UNKNOWN PRINTER");
685 PACKI(desc,"W",LPSTAT_ERROR);
687 else if (!status || !status->message[0]) {
688 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
689 PACKI(desc,"W",LPSTAT_OK); /* status */
691 PACKS(desc,"z",status->message);
692 PACKI(desc,"W",printq_status(status->status)); /* status */
694 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
697 if (uLevel == 3 || uLevel == 4) {
700 PACKI(desc,"W",5); /* uPriority */
701 PACKI(desc,"W",0); /* uStarttime */
702 PACKI(desc,"W",0); /* uUntiltime */
703 PACKI(desc,"W",5); /* pad1 */
704 PACKS(desc,"z",""); /* pszSepFile */
705 PACKS(desc,"z","WinPrint"); /* pszPrProc */
706 PACKS(desc,"z",NULL); /* pszParms */
707 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
708 /* "don't ask" that it's done this way to fix corrupted
709 Win9X/ME printer comments. */
711 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
713 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
715 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
716 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
717 get_driver_name(snum,drivername);
718 PACKS(desc,"z",drivername); /* pszDriverName */
719 PackDriverData(desc); /* pDriverData */
722 if (uLevel == 2 || uLevel == 4) {
724 for (i=0;i<count;i++)
725 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
729 fill_printq_info_52( conn, snum, desc, count );
732 /* This function returns the number of files for a given driver */
733 static int get_printerdrivernumber(int snum)
736 NT_PRINTER_DRIVER_INFO_LEVEL driver;
737 NT_PRINTER_INFO_LEVEL *printer = NULL;
741 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
742 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
743 lp_servicename(snum)));
747 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
750 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
751 printer->info_2->drivername));
755 /* count the number of files */
756 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
761 free_a_printer( &printer, 2 );
764 free_a_printer_driver( driver, 3 );
769 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
770 uint16 vuid, char *param,char *data,
771 int mdrcnt,int mprcnt,
772 char **rdata,char **rparam,
773 int *rdata_len,int *rparam_len)
775 char *str1 = param+2;
776 char *str2 = skip_string(str1,1);
777 char *p = skip_string(str2,1);
783 struct pack_desc desc;
784 print_queue_struct *queue=NULL;
785 print_status_struct status;
788 memset((char *)&status,'\0',sizeof(status));
789 memset((char *)&desc,'\0',sizeof(desc));
791 p = skip_string(p,1);
795 /* remove any trailing username */
796 if ((p = strchr_m(QueueName,'%')))
799 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
801 /* check it's a supported varient */
802 if (!prefix_ok(str1,"zWrLh"))
804 if (!check_printq_info(&desc,uLevel,str2,str3)) {
806 * Patch from Scott Moomaw <scott@bridgewater.edu>
807 * to return the 'invalid info level' error if an
808 * unknown level was requested.
812 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
816 SSVALS(*rparam,0,ERRunknownlevel);
822 snum = find_service(QueueName);
823 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
827 count = get_printerdrivernumber(snum);
828 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
830 count = print_queue_status(snum, &queue,&status);
834 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
839 desc.buflen = mdrcnt;
842 * Don't return data but need to get correct length
843 * init_package will return wrong size if buflen=0
845 desc.buflen = getlen(desc.format);
846 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
849 if (init_package(&desc,1,count)) {
850 desc.subcount = count;
851 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
854 *rdata_len = desc.usedlen;
857 * We must set the return code to ERRbuftoosmall
858 * in order to support lanman style printing with Win NT/2k
861 if (!mdrcnt && lp_disable_spoolss())
862 desc.errcode = ERRbuftoosmall;
864 *rdata_len = desc.usedlen;
866 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
870 SSVALS(*rparam,0,desc.errcode);
872 SSVAL(*rparam,4,desc.neededlen);
874 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
882 /****************************************************************************
883 View list of all print jobs on all queues.
884 ****************************************************************************/
886 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
887 int mdrcnt, int mprcnt,
888 char **rdata, char** rparam,
889 int *rdata_len, int *rparam_len)
891 char *param_format = param+2;
892 char *output_format1 = skip_string(param_format,1);
893 char *p = skip_string(output_format1,1);
894 unsigned int uLevel = SVAL(p,0);
895 char *output_format2 = p + 4;
896 int services = lp_numservices();
898 struct pack_desc desc;
899 print_queue_struct **queue = NULL;
900 print_status_struct *status = NULL;
901 int *subcntarr = NULL;
902 int queuecnt = 0, subcnt = 0, succnt = 0;
904 memset((char *)&desc,'\0',sizeof(desc));
906 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
908 if (!prefix_ok(param_format,"WrLeh")) {
911 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
913 * Patch from Scott Moomaw <scott@bridgewater.edu>
914 * to return the 'invalid info level' error if an
915 * unknown level was requested.
919 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
923 SSVALS(*rparam,0,ERRunknownlevel);
929 for (i = 0; i < services; i++) {
930 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
935 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
936 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
939 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
940 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
941 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
944 memset(status,0,queuecnt*sizeof(print_status_struct));
945 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
946 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
952 for (i = 0; i < services; i++) {
953 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
954 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
955 subcnt += subcntarr[n];
961 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
967 desc.buflen = mdrcnt;
969 if (init_package(&desc,queuecnt,subcnt)) {
972 for (i = 0; i < services; i++) {
973 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
974 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
976 if (desc.errcode == NERR_Success) {
983 SAFE_FREE(subcntarr);
985 *rdata_len = desc.usedlen;
987 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
991 SSVALS(*rparam,0,desc.errcode);
993 SSVAL(*rparam,4,succnt);
994 SSVAL(*rparam,6,queuecnt);
996 for (i = 0; i < queuecnt; i++) {
1009 SAFE_FREE(subcntarr);
1010 for (i = 0; i < queuecnt; i++) {
1012 SAFE_FREE(queue[i]);
1021 /****************************************************************************
1022 Get info level for a server list query.
1023 ****************************************************************************/
1025 static BOOL check_server_info(int uLevel, char* id)
1029 if (strcmp(id,"B16") != 0) {
1034 if (strcmp(id,"B16BBDz") != 0) {
1044 struct srv_info_struct {
1052 /*******************************************************************
1053 Get server info lists from the files saved by nmbd. Return the
1055 ******************************************************************/
1057 static int get_server_info(uint32 servertype,
1058 struct srv_info_struct **servers,
1064 BOOL local_list_only;
1067 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1069 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1073 /* request for everything is code for request all servers */
1074 if (servertype == SV_TYPE_ALL) {
1075 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1078 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1080 DEBUG(4,("Servertype search: %8x\n",servertype));
1082 for (i=0;lines[i];i++) {
1084 struct srv_info_struct *s;
1085 const char *ptr = lines[i];
1092 if (count == alloced) {
1094 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1096 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1097 file_lines_free(lines);
1100 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1102 s = &(*servers)[count];
1104 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1107 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1110 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1113 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1114 /* this allows us to cope with an old nmbd */
1115 fstrcpy(s->domain,lp_workgroup());
1118 if (sscanf(stype,"%X",&s->type) != 1) {
1119 DEBUG(4,("r:host file "));
1123 /* Filter the servers/domains we return based on what was asked for. */
1125 /* Check to see if we are being asked for a local list only. */
1126 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1127 DEBUG(4,("r: local list only"));
1131 /* doesn't match up: don't want it */
1132 if (!(servertype & s->type)) {
1133 DEBUG(4,("r:serv type "));
1137 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1138 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1139 DEBUG(4,("s: dom mismatch "));
1143 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1147 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1148 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1151 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1152 s->name, s->type, s->comment, s->domain));
1153 s->server_added = True;
1156 DEBUG(4,("%20s %8x %25s %15s\n",
1157 s->name, s->type, s->comment, s->domain));
1161 file_lines_free(lines);
1165 /*******************************************************************
1166 Fill in a server info structure.
1167 ******************************************************************/
1169 static int fill_srv_info(struct srv_info_struct *service,
1170 int uLevel, char **buf, int *buflen,
1171 char **stringbuf, int *stringspace, char *baseaddr)
1194 len = strlen(service->comment)+1;
1199 *buflen = struct_len;
1204 return struct_len + len;
1209 if (*buflen < struct_len) {
1216 p2 = p + struct_len;
1217 l2 = *buflen - struct_len;
1225 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1229 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1230 SIVAL(p,18,service->type);
1231 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1232 len += CopyAndAdvance(&p2,service->comment,&l2);
1237 *buf = p + struct_len;
1238 *buflen -= struct_len;
1249 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1251 return(strcmp(s1->name,s2->name));
1254 /****************************************************************************
1255 View list of servers available (or possibly domains). The info is
1256 extracted from lists saved by nmbd on the local host.
1257 ****************************************************************************/
1259 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1260 int mdrcnt, int mprcnt, char **rdata,
1261 char **rparam, int *rdata_len, int *rparam_len)
1263 char *str1 = param+2;
1264 char *str2 = skip_string(str1,1);
1265 char *p = skip_string(str2,1);
1266 int uLevel = SVAL(p,0);
1267 int buf_len = SVAL(p,2);
1268 uint32 servertype = IVAL(p,4);
1270 int data_len, fixed_len, string_len;
1271 int f_len = 0, s_len = 0;
1272 struct srv_info_struct *servers=NULL;
1273 int counted=0,total=0;
1276 BOOL domain_request;
1279 /* If someone sets all the bits they don't really mean to set
1280 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1283 if (servertype == SV_TYPE_ALL) {
1284 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1287 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1288 any other bit (they may just set this bit on it's own) they
1289 want all the locally seen servers. However this bit can be
1290 set on its own so set the requested servers to be
1291 ALL - DOMAIN_ENUM. */
1293 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1294 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1297 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1298 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1302 if (!prefix_ok(str1,"WrLehD")) {
1305 if (!check_server_info(uLevel,str2)) {
1309 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1310 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1311 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1313 if (strcmp(str1, "WrLehDz") == 0) {
1314 pull_ascii_fstring(domain, p);
1316 fstrcpy(domain, lp_workgroup());
1319 if (lp_browse_list()) {
1320 total = get_server_info(servertype,&servers,domain);
1323 data_len = fixed_len = string_len = 0;
1327 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1331 char *lastname=NULL;
1333 for (i=0;i<total;i++) {
1334 struct srv_info_struct *s = &servers[i];
1336 if (lastname && strequal(lastname,s->name)) {
1340 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1341 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1342 s->name, s->type, s->comment, s->domain));
1344 if (data_len <= buf_len) {
1347 string_len += s_len;
1354 *rdata_len = fixed_len + string_len;
1355 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1359 memset(*rdata,'\0',*rdata_len);
1361 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1367 char *lastname=NULL;
1368 int count2 = counted;
1370 for (i = 0; i < total && count2;i++) {
1371 struct srv_info_struct *s = &servers[i];
1373 if (lastname && strequal(lastname,s->name)) {
1377 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1378 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1379 s->name, s->type, s->comment, s->domain));
1385 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1389 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1391 SSVAL(*rparam,4,counted);
1392 SSVAL(*rparam,6,counted+missed);
1396 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1397 domain,uLevel,counted,counted+missed));
1402 /****************************************************************************
1403 command 0x34 - suspected of being a "Lookup Names" stub api
1404 ****************************************************************************/
1406 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1407 int mdrcnt, int mprcnt, char **rdata,
1408 char **rparam, int *rdata_len, int *rparam_len)
1410 char *str1 = param+2;
1411 char *str2 = skip_string(str1,1);
1412 char *p = skip_string(str2,1);
1413 int uLevel = SVAL(p,0);
1414 int buf_len = SVAL(p,2);
1418 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1419 str1, str2, p, uLevel, buf_len));
1421 if (!prefix_ok(str1,"zWrLeh")) {
1428 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1433 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1435 SSVAL(*rparam,4,counted);
1436 SSVAL(*rparam,6,counted+missed);
1441 /****************************************************************************
1442 get info about a share
1443 ****************************************************************************/
1445 static BOOL check_share_info(int uLevel, char* id)
1449 if (strcmp(id,"B13") != 0) {
1454 if (strcmp(id,"B13BWz") != 0) {
1459 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1464 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1474 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1475 char** buf, int* buflen,
1476 char** stringbuf, int* stringspace, char* baseaddr)
1506 len += StrlenExpanded(conn,snum,lp_comment(snum));
1509 len += strlen(lp_pathname(snum)) + 1;
1512 *buflen = struct_len;
1517 return struct_len + len;
1522 if ((*buflen) < struct_len) {
1530 p2 = p + struct_len;
1531 l2 = (*buflen) - struct_len;
1538 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1544 type = STYPE_DISKTREE;
1545 if (lp_print_ok(snum)) {
1546 type = STYPE_PRINTQ;
1548 if (strequal("IPC",lp_fstype(snum))) {
1551 SSVAL(p,14,type); /* device type */
1552 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1553 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1557 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1558 SSVALS(p,22,-1); /* max uses */
1559 SSVAL(p,24,1); /* current uses */
1560 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1561 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1562 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1566 memset(p+40,0,SHPWLEN+2);
1577 (*buf) = p + struct_len;
1578 (*buflen) -= struct_len;
1580 (*stringspace) = l2;
1589 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1590 int mdrcnt,int mprcnt,
1591 char **rdata,char **rparam,
1592 int *rdata_len,int *rparam_len)
1594 char *str1 = param+2;
1595 char *str2 = skip_string(str1,1);
1596 char *netname = skip_string(str2,1);
1597 char *p = skip_string(netname,1);
1598 int uLevel = SVAL(p,0);
1599 int snum = find_service(netname);
1605 /* check it's a supported varient */
1606 if (!prefix_ok(str1,"zWrLh")) {
1609 if (!check_share_info(uLevel,str2)) {
1613 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1618 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1619 if (*rdata_len < 0) {
1624 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1628 SSVAL(*rparam,0,NERR_Success);
1629 SSVAL(*rparam,2,0); /* converter word */
1630 SSVAL(*rparam,4,*rdata_len);
1635 /****************************************************************************
1636 View the list of available shares.
1638 This function is the server side of the NetShareEnum() RAP call.
1639 It fills the return buffer with share names and share comments.
1640 Note that the return buffer normally (in all known cases) allows only
1641 twelve byte strings for share names (plus one for a nul terminator).
1642 Share names longer than 12 bytes must be skipped.
1643 ****************************************************************************/
1645 static BOOL api_RNetShareEnum( connection_struct *conn,
1656 char *str1 = param+2;
1657 char *str2 = skip_string(str1,1);
1658 char *p = skip_string(str2,1);
1659 int uLevel = SVAL(p,0);
1660 int buf_len = SVAL(p,2);
1663 int total=0,counted=0;
1664 BOOL missed = False;
1666 int data_len, fixed_len, string_len;
1667 int f_len = 0, s_len = 0;
1669 if (!prefix_ok(str1,"WrLeh")) {
1672 if (!check_share_info(uLevel,str2)) {
1676 /* Ensure all the usershares are loaded. */
1678 count = load_usershare_shares();
1681 data_len = fixed_len = string_len = 0;
1682 for (i=0;i<count;i++) {
1683 fstring servicename_dos;
1684 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1687 push_ascii_fstring(servicename_dos, lp_servicename(i));
1688 /* Maximum name length = 13. */
1689 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1691 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1692 if (data_len <= buf_len) {
1695 string_len += s_len;
1702 *rdata_len = fixed_len + string_len;
1703 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1707 memset(*rdata,0,*rdata_len);
1709 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1714 for( i = 0; i < count; i++ ) {
1715 fstring servicename_dos;
1716 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1720 push_ascii_fstring(servicename_dos, lp_servicename(i));
1721 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1722 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1729 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1733 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1735 SSVAL(*rparam,4,counted);
1736 SSVAL(*rparam,6,total);
1738 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1739 counted,total,uLevel,
1740 buf_len,*rdata_len,mdrcnt));
1745 /****************************************************************************
1747 ****************************************************************************/
1749 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1750 int mdrcnt,int mprcnt,
1751 char **rdata,char **rparam,
1752 int *rdata_len,int *rparam_len)
1754 char *str1 = param+2;
1755 char *str2 = skip_string(str1,1);
1756 char *p = skip_string(str2,1);
1757 int uLevel = SVAL(p,0);
1761 char *command, *cmdname;
1762 unsigned int offset;
1766 /* check it's a supported varient */
1767 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1770 if (!check_share_info(uLevel,str2)) {
1777 pull_ascii_fstring(sharename,data);
1778 snum = find_service(sharename);
1779 if (snum >= 0) { /* already exists */
1784 /* only support disk share adds */
1785 if (SVAL(data,14)!=STYPE_DISKTREE) {
1789 offset = IVAL(data, 16);
1790 if (offset >= mdrcnt) {
1791 res = ERRinvalidparam;
1795 pull_ascii_fstring(comment, offset? (data+offset) : "");
1797 offset = IVAL(data, 26);
1799 if (offset >= mdrcnt) {
1800 res = ERRinvalidparam;
1804 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1806 string_replace(sharename, '"', ' ');
1807 string_replace(pathname, '"', ' ');
1808 string_replace(comment, '"', ' ');
1810 cmdname = lp_add_share_cmd();
1812 if (!cmdname || *cmdname == '\0') {
1816 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1817 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1820 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1822 if ((res = smbrun(command, NULL)) != 0) {
1823 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1829 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1836 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1840 SSVAL(*rparam,0,NERR_Success);
1841 SSVAL(*rparam,2,0); /* converter word */
1842 SSVAL(*rparam,4,*rdata_len);
1850 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1855 SSVAL(*rparam,0,res);
1860 /****************************************************************************
1861 view list of groups available
1862 ****************************************************************************/
1864 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1865 int mdrcnt,int mprcnt,
1866 char **rdata,char **rparam,
1867 int *rdata_len,int *rparam_len)
1871 int resume_context, cli_buf_size;
1872 char *str1 = param+2;
1873 char *str2 = skip_string(str1,1);
1874 char *p = skip_string(str2,1);
1876 struct pdb_search *search;
1877 struct samr_displayentry *entries;
1881 if (strcmp(str1,"WrLeh") != 0) {
1886 * W-> resume context (number of users to skip)
1887 * r -> return parameter pointer to receive buffer
1888 * L -> length of receive buffer
1889 * e -> return parameter number of entries
1890 * h -> return parameter total number of users
1893 if (strcmp("B21",str2) != 0) {
1897 /* get list of domain groups SID_DOMAIN_GRP=2 */
1899 search = pdb_search_groups();
1902 if (search == NULL) {
1903 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1907 resume_context = SVAL(p,0);
1908 cli_buf_size=SVAL(p+2,0);
1909 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1910 "%d\n", resume_context, cli_buf_size));
1913 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1917 *rdata_len = cli_buf_size;
1918 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1925 for(i=0; i<num_entries; i++) {
1927 fstrcpy(name, entries[i].account_name);
1928 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1929 /* truncate the name at 21 chars. */
1930 memcpy(p, name, 21);
1931 DEBUG(10,("adding entry %d group %s\n", i, p));
1933 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1936 /* set overflow error */
1937 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1943 pdb_search_destroy(search);
1945 *rdata_len = PTR_DIFF(p,*rdata);
1948 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1952 SSVAL(*rparam, 0, errflags);
1953 SSVAL(*rparam, 2, 0); /* converter word */
1954 SSVAL(*rparam, 4, i); /* is this right?? */
1955 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1960 /*******************************************************************
1961 Get groups that a user is a member of.
1962 ******************************************************************/
1964 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1965 int mdrcnt,int mprcnt,
1966 char **rdata,char **rparam,
1967 int *rdata_len,int *rparam_len)
1969 char *str1 = param+2;
1970 char *str2 = skip_string(str1,1);
1971 char *UserName = skip_string(str2,1);
1972 char *p = skip_string(UserName,1);
1973 int uLevel = SVAL(p,0);
1974 const char *level_string;
1976 struct samu *sampw = NULL;
1984 enum SID_NAME_USE type;
1985 TALLOC_CTX *mem_ctx;
1988 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1993 /* check it's a supported varient */
1995 if ( strcmp(str1,"zWrLeh") != 0 )
2000 level_string = "B21";
2006 if (strcmp(level_string,str2) != 0)
2009 *rdata_len = mdrcnt + 1024;
2010 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2014 SSVAL(*rparam,0,NERR_Success);
2015 SSVAL(*rparam,2,0); /* converter word */
2019 mem_ctx = talloc_new(NULL);
2020 if (mem_ctx == NULL) {
2021 DEBUG(0, ("talloc_new failed\n"));
2025 if ( !(sampw = samu_new(mem_ctx)) ) {
2026 DEBUG(0, ("samu_new() failed!\n"));
2027 TALLOC_FREE(mem_ctx);
2031 /* Lookup the user information; This should only be one of
2032 our accounts (not remote domains) */
2034 become_root(); /* ROOT BLOCK */
2036 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2037 NULL, NULL, &user_sid, &type)) {
2038 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2042 if (type != SID_NAME_USER) {
2043 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2044 sid_type_lookup(type)));
2048 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2049 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2050 sid_string_static(&user_sid), UserName));
2058 result = pdb_enum_group_memberships(mem_ctx, sampw,
2059 &sids, &gids, &num_groups);
2061 if (!NT_STATUS_IS_OK(result)) {
2062 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2067 for (i=0; i<num_groups; i++) {
2069 const char *grp_name;
2071 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2072 pstrcpy(p, grp_name);
2078 *rdata_len = PTR_DIFF(p,*rdata);
2080 SSVAL(*rparam,4,count); /* is this right?? */
2081 SSVAL(*rparam,6,count); /* is this right?? */
2086 unbecome_root(); /* END ROOT BLOCK */
2088 TALLOC_FREE(mem_ctx);
2093 /*******************************************************************
2095 ******************************************************************/
2097 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2098 int mdrcnt,int mprcnt,
2099 char **rdata,char **rparam,
2100 int *rdata_len,int *rparam_len)
2105 int i, resume_context, cli_buf_size;
2106 struct pdb_search *search;
2107 struct samr_displayentry *users;
2109 char *str1 = param+2;
2110 char *str2 = skip_string(str1,1);
2111 char *p = skip_string(str2,1);
2113 if (strcmp(str1,"WrLeh") != 0)
2116 * W-> resume context (number of users to skip)
2117 * r -> return parameter pointer to receive buffer
2118 * L -> length of receive buffer
2119 * e -> return parameter number of entries
2120 * h -> return parameter total number of users
2123 resume_context = SVAL(p,0);
2124 cli_buf_size=SVAL(p+2,0);
2125 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2126 resume_context, cli_buf_size));
2129 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2134 /* check it's a supported varient */
2135 if (strcmp("B21",str2) != 0)
2138 *rdata_len = cli_buf_size;
2139 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2147 search = pdb_search_users(ACB_NORMAL);
2149 if (search == NULL) {
2150 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2155 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2159 errflags=NERR_Success;
2161 for (i=0; i<num_users; i++) {
2162 const char *name = users[i].account_name;
2164 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2166 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2167 "%s\n",count_sent,p));
2171 /* set overflow error */
2172 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2173 "username %s\n",count_sent,name));
2179 pdb_search_destroy(search);
2181 *rdata_len = PTR_DIFF(p,*rdata);
2183 SSVAL(*rparam,0,errflags);
2184 SSVAL(*rparam,2,0); /* converter word */
2185 SSVAL(*rparam,4,count_sent); /* is this right?? */
2186 SSVAL(*rparam,6,num_users); /* is this right?? */
2191 /****************************************************************************
2192 Get the time of day info.
2193 ****************************************************************************/
2195 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
2196 int mdrcnt,int mprcnt,
2197 char **rdata,char **rparam,
2198 int *rdata_len,int *rparam_len)
2201 time_t unixdate = time(NULL);
2205 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2211 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2216 SSVAL(*rparam,0,NERR_Success);
2217 SSVAL(*rparam,2,0); /* converter word */
2221 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2222 by NT in a "net time" operation,
2223 it seems to ignore the one below */
2225 /* the client expects to get localtime, not GMT, in this bit
2226 (I think, this needs testing) */
2227 t = localtime(&unixdate);
2232 SIVAL(p,4,0); /* msecs ? */
2233 SCVAL(p,8,t->tm_hour);
2234 SCVAL(p,9,t->tm_min);
2235 SCVAL(p,10,t->tm_sec);
2236 SCVAL(p,11,0); /* hundredths of seconds */
2237 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2238 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2239 SCVAL(p,16,t->tm_mday);
2240 SCVAL(p,17,t->tm_mon + 1);
2241 SSVAL(p,18,1900+t->tm_year);
2242 SCVAL(p,20,t->tm_wday);
2247 /****************************************************************************
2248 Set the user password.
2249 *****************************************************************************/
2251 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2252 int mdrcnt,int mprcnt,
2253 char **rdata,char **rparam,
2254 int *rdata_len,int *rparam_len)
2256 char *p = skip_string(param+2,2);
2258 fstring pass1,pass2;
2260 pull_ascii_fstring(user,p);
2262 p = skip_string(p,1);
2264 memset(pass1,'\0',sizeof(pass1));
2265 memset(pass2,'\0',sizeof(pass2));
2267 memcpy(pass2,p+16,16);
2270 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2277 SSVAL(*rparam,0,NERR_badpass);
2278 SSVAL(*rparam,2,0); /* converter word */
2280 DEBUG(3,("Set password for <%s>\n",user));
2283 * Attempt to verify the old password against smbpasswd entries
2284 * Win98 clients send old and new password in plaintext for this call.
2288 auth_serversupplied_info *server_info = NULL;
2289 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2291 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2294 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2295 SSVAL(*rparam,0,NERR_Success);
2299 TALLOC_FREE(server_info);
2301 data_blob_clear_free(&password);
2305 * If the plaintext change failed, attempt
2306 * the old encrypted method. NT will generate this
2307 * after trying the samr method. Note that this
2308 * method is done as a last resort as this
2309 * password change method loses the NT password hash
2310 * and cannot change the UNIX password as no plaintext
2314 if(SVAL(*rparam,0) != NERR_Success) {
2315 struct samu *hnd = NULL;
2317 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2319 if (change_lanman_password(hnd,(uchar *)pass2)) {
2320 SSVAL(*rparam,0,NERR_Success);
2327 memset((char *)pass1,'\0',sizeof(fstring));
2328 memset((char *)pass2,'\0',sizeof(fstring));
2333 /****************************************************************************
2334 Set the user password (SamOEM version - gets plaintext).
2335 ****************************************************************************/
2337 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2338 int mdrcnt,int mprcnt,
2339 char **rdata,char **rparam,
2340 int *rdata_len,int *rparam_len)
2343 char *p = param + 2;
2345 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2352 SSVAL(*rparam,0,NERR_badpass);
2355 * Check the parameter definition is correct.
2358 if(!strequal(param + 2, "zsT")) {
2359 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2362 p = skip_string(p, 1);
2364 if(!strequal(p, "B516B16")) {
2365 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2368 p = skip_string(p,1);
2369 p += pull_ascii_fstring(user,p);
2371 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2374 * Pass the user through the NT -> unix user mapping
2378 (void)map_username(user);
2380 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2381 SSVAL(*rparam,0,NERR_Success);
2387 /****************************************************************************
2390 ****************************************************************************/
2392 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2393 int mdrcnt,int mprcnt,
2394 char **rdata,char **rparam,
2395 int *rdata_len,int *rparam_len)
2397 int function = SVAL(param,0);
2398 char *str1 = param+2;
2399 char *str2 = skip_string(str1,1);
2400 char *p = skip_string(str2,1);
2405 WERROR werr = WERR_OK;
2407 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2410 /* check it's a supported varient */
2411 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2415 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2421 if (!print_job_exists(sharename, jobid)) {
2422 errcode = NERR_JobNotFound;
2426 snum = lp_servicenumber( sharename);
2428 errcode = NERR_DestNotFound;
2432 errcode = NERR_notsupported;
2435 case 81: /* delete */
2436 if (print_job_delete(¤t_user, snum, jobid, &werr))
2437 errcode = NERR_Success;
2439 case 82: /* pause */
2440 if (print_job_pause(¤t_user, snum, jobid, &werr))
2441 errcode = NERR_Success;
2443 case 83: /* resume */
2444 if (print_job_resume(¤t_user, snum, jobid, &werr))
2445 errcode = NERR_Success;
2449 if (!W_ERROR_IS_OK(werr))
2450 errcode = W_ERROR_V(werr);
2453 SSVAL(*rparam,0,errcode);
2454 SSVAL(*rparam,2,0); /* converter word */
2459 /****************************************************************************
2460 Purge a print queue - or pause or resume it.
2461 ****************************************************************************/
2463 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2464 int mdrcnt,int mprcnt,
2465 char **rdata,char **rparam,
2466 int *rdata_len,int *rparam_len)
2468 int function = SVAL(param,0);
2469 char *str1 = param+2;
2470 char *str2 = skip_string(str1,1);
2471 char *QueueName = skip_string(str2,1);
2472 int errcode = NERR_notsupported;
2474 WERROR werr = WERR_OK;
2476 /* check it's a supported varient */
2477 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2481 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2487 snum = print_queue_snum(QueueName);
2490 errcode = NERR_JobNotFound;
2495 case 74: /* Pause queue */
2496 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2498 case 75: /* Resume queue */
2499 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2501 case 103: /* Purge */
2502 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2506 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2509 SSVAL(*rparam,0,errcode);
2510 SSVAL(*rparam,2,0); /* converter word */
2515 /****************************************************************************
2516 set the property of a print job (undocumented?)
2517 ? function = 0xb -> set name of print job
2518 ? function = 0x6 -> move print job up/down
2519 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2520 or <WWsTP> <WB21BB16B10zWWzDDz>
2521 ****************************************************************************/
2523 static int check_printjob_info(struct pack_desc* desc,
2524 int uLevel, char* id)
2526 desc->subformat = NULL;
2528 case 0: desc->format = "W"; break;
2529 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2530 case 2: desc->format = "WWzWWDDzz"; break;
2531 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2532 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2533 default: return False;
2535 if (strcmp(desc->format,id) != 0) return False;
2539 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2540 int mdrcnt,int mprcnt,
2541 char **rdata,char **rparam,
2542 int *rdata_len,int *rparam_len)
2544 struct pack_desc desc;
2545 char *str1 = param+2;
2546 char *str2 = skip_string(str1,1);
2547 char *p = skip_string(str2,1);
2550 int uLevel = SVAL(p,2);
2551 int function = SVAL(p,4);
2554 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2557 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2562 if (!share_defined(sharename)) {
2563 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2570 /* check it's a supported varient */
2571 if ((strcmp(str1,"WWsTP")) ||
2572 (!check_printjob_info(&desc,uLevel,str2)))
2575 if (!print_job_exists(sharename, jobid)) {
2576 errcode=NERR_JobNotFound;
2580 errcode = NERR_notsupported;
2584 /* change job place in the queue,
2585 data gives the new place */
2586 place = SVAL(data,0);
2587 if (print_job_set_place(sharename, jobid, place)) {
2588 errcode=NERR_Success;
2593 /* change print job name, data gives the name */
2594 if (print_job_set_name(sharename, jobid, data)) {
2595 errcode=NERR_Success;
2604 SSVALS(*rparam,0,errcode);
2605 SSVAL(*rparam,2,0); /* converter word */
2611 /****************************************************************************
2612 Get info about the server.
2613 ****************************************************************************/
2615 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2616 int mdrcnt,int mprcnt,
2617 char **rdata,char **rparam,
2618 int *rdata_len,int *rparam_len)
2620 char *str1 = param+2;
2621 char *str2 = skip_string(str1,1);
2622 char *p = skip_string(str2,1);
2623 int uLevel = SVAL(p,0);
2627 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2629 /* check it's a supported varient */
2630 if (!prefix_ok(str1,"WrLh")) {
2636 if (strcmp(str2,"B16") != 0) {
2642 if (strcmp(str2,"B16BBDz") != 0) {
2648 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2654 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2660 if (strcmp(str2,"DN") != 0) {
2666 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2675 *rdata_len = mdrcnt;
2676 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2682 p2 = p + struct_len;
2684 srvstr_push(NULL, p,get_local_machine_name(),16,
2685 STR_ASCII|STR_UPPER|STR_TERMINATE);
2689 struct srv_info_struct *servers=NULL;
2692 uint32 servertype= lp_default_server_announce();
2694 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2696 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2697 for (i=0;i<count;i++) {
2698 if (strequal(servers[i].name,get_local_machine_name())) {
2699 servertype = servers[i].type;
2700 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2707 SCVAL(p,0,lp_major_announce_version());
2708 SCVAL(p,1,lp_minor_announce_version());
2709 SIVAL(p,2,servertype);
2711 if (mdrcnt == struct_len) {
2714 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2715 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2716 conn->connectpath, conn->gid,
2717 get_current_username(),
2718 current_user_info.domain,
2719 comment, sizeof(comment));
2720 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2721 p2 = skip_string(p2,1);
2726 return False; /* not yet implemented */
2729 *rdata_len = PTR_DIFF(p2,*rdata);
2732 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2736 SSVAL(*rparam,0,NERR_Success);
2737 SSVAL(*rparam,2,0); /* converter word */
2738 SSVAL(*rparam,4,*rdata_len);
2743 /****************************************************************************
2744 Get info about the server.
2745 ****************************************************************************/
2747 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2748 int mdrcnt,int mprcnt,
2749 char **rdata,char **rparam,
2750 int *rdata_len,int *rparam_len)
2752 char *str1 = param+2;
2753 char *str2 = skip_string(str1,1);
2754 char *p = skip_string(str2,1);
2756 int level = SVAL(p,0);
2758 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2761 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2766 /* check it's a supported varient */
2767 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2771 *rdata_len = mdrcnt + 1024;
2772 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2777 SSVAL(*rparam,0,NERR_Success);
2778 SSVAL(*rparam,2,0); /* converter word */
2783 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2784 pstrcpy(p2,get_local_machine_name());
2786 p2 = skip_string(p2,1);
2789 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2790 pstrcpy(p2,current_user_info.smb_name);
2791 p2 = skip_string(p2,1);
2794 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2795 pstrcpy(p2,lp_workgroup());
2797 p2 = skip_string(p2,1);
2800 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2801 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2804 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2805 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2806 p2 = skip_string(p2,1);
2809 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2811 p2 = skip_string(p2,1);
2814 *rdata_len = PTR_DIFF(p2,*rdata);
2816 SSVAL(*rparam,4,*rdata_len);
2821 /****************************************************************************
2822 get info about a user
2824 struct user_info_11 {
2825 char usri11_name[21]; 0-20
2827 char *usri11_comment; 22-25
2828 char *usri11_usr_comment; 26-29
2829 unsigned short usri11_priv; 30-31
2830 unsigned long usri11_auth_flags; 32-35
2831 long usri11_password_age; 36-39
2832 char *usri11_homedir; 40-43
2833 char *usri11_parms; 44-47
2834 long usri11_last_logon; 48-51
2835 long usri11_last_logoff; 52-55
2836 unsigned short usri11_bad_pw_count; 56-57
2837 unsigned short usri11_num_logons; 58-59
2838 char *usri11_logon_server; 60-63
2839 unsigned short usri11_country_code; 64-65
2840 char *usri11_workstations; 66-69
2841 unsigned long usri11_max_storage; 70-73
2842 unsigned short usri11_units_per_week; 74-75
2843 unsigned char *usri11_logon_hours; 76-79
2844 unsigned short usri11_code_page; 80-81
2849 usri11_name specifies the user name for which information is retireved
2851 usri11_pad aligns the next data structure element to a word boundary
2853 usri11_comment is a null terminated ASCII comment
2855 usri11_user_comment is a null terminated ASCII comment about the user
2857 usri11_priv specifies the level of the privilege assigned to the user.
2858 The possible values are:
2860 Name Value Description
2861 USER_PRIV_GUEST 0 Guest privilege
2862 USER_PRIV_USER 1 User privilege
2863 USER_PRV_ADMIN 2 Administrator privilege
2865 usri11_auth_flags specifies the account operator privileges. The
2866 possible values are:
2868 Name Value Description
2869 AF_OP_PRINT 0 Print operator
2872 Leach, Naik [Page 28]
2876 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2879 AF_OP_COMM 1 Communications operator
2880 AF_OP_SERVER 2 Server operator
2881 AF_OP_ACCOUNTS 3 Accounts operator
2884 usri11_password_age specifies how many seconds have elapsed since the
2885 password was last changed.
2887 usri11_home_dir points to a null terminated ASCII string that contains
2888 the path name of the user's home directory.
2890 usri11_parms points to a null terminated ASCII string that is set
2891 aside for use by applications.
2893 usri11_last_logon specifies the time when the user last logged on.
2894 This value is stored as the number of seconds elapsed since
2895 00:00:00, January 1, 1970.
2897 usri11_last_logoff specifies the time when the user last logged off.
2898 This value is stored as the number of seconds elapsed since
2899 00:00:00, January 1, 1970. A value of 0 means the last logoff
2902 usri11_bad_pw_count specifies the number of incorrect passwords
2903 entered since the last successful logon.
2905 usri11_log1_num_logons specifies the number of times this user has
2906 logged on. A value of -1 means the number of logons is unknown.
2908 usri11_logon_server points to a null terminated ASCII string that
2909 contains the name of the server to which logon requests are sent.
2910 A null string indicates logon requests should be sent to the
2913 usri11_country_code specifies the country code for the user's language
2916 usri11_workstations points to a null terminated ASCII string that
2917 contains the names of workstations the user may log on from.
2918 There may be up to 8 workstations, with the names separated by
2919 commas. A null strings indicates there are no restrictions.
2921 usri11_max_storage specifies the maximum amount of disk space the user
2922 can occupy. A value of 0xffffffff indicates there are no
2925 usri11_units_per_week specifies the equal number of time units into
2926 which a week is divided. This value must be equal to 168.
2928 usri11_logon_hours points to a 21 byte (168 bits) string that
2929 specifies the time during which the user can log on. Each bit
2930 represents one unique hour in a week. The first bit (bit 0, word
2931 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2935 Leach, Naik [Page 29]
2939 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2942 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2943 are no restrictions.
2945 usri11_code_page specifies the code page for the user's language of
2948 All of the pointers in this data structure need to be treated
2949 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2950 to be ignored. The converter word returned in the parameters section
2951 needs to be subtracted from the lower 16 bits to calculate an offset
2952 into the return buffer where this ASCII string resides.
2954 There is no auxiliary data in the response.
2956 ****************************************************************************/
2958 #define usri11_name 0
2959 #define usri11_pad 21
2960 #define usri11_comment 22
2961 #define usri11_usr_comment 26
2962 #define usri11_full_name 30
2963 #define usri11_priv 34
2964 #define usri11_auth_flags 36
2965 #define usri11_password_age 40
2966 #define usri11_homedir 44
2967 #define usri11_parms 48
2968 #define usri11_last_logon 52
2969 #define usri11_last_logoff 56
2970 #define usri11_bad_pw_count 60
2971 #define usri11_num_logons 62
2972 #define usri11_logon_server 64
2973 #define usri11_country_code 68
2974 #define usri11_workstations 70
2975 #define usri11_max_storage 74
2976 #define usri11_units_per_week 78
2977 #define usri11_logon_hours 80
2978 #define usri11_code_page 84
2979 #define usri11_end 86
2981 #define USER_PRIV_GUEST 0
2982 #define USER_PRIV_USER 1
2983 #define USER_PRIV_ADMIN 2
2985 #define AF_OP_PRINT 0
2986 #define AF_OP_COMM 1
2987 #define AF_OP_SERVER 2
2988 #define AF_OP_ACCOUNTS 3
2991 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2992 int mdrcnt,int mprcnt,
2993 char **rdata,char **rparam,
2994 int *rdata_len,int *rparam_len)
2996 char *str1 = param+2;
2997 char *str2 = skip_string(str1,1);
2998 char *UserName = skip_string(str2,1);
2999 char *p = skip_string(UserName,1);
3000 int uLevel = SVAL(p,0);
3002 const char *level_string;
3004 /* get NIS home of a previously validated user - simeon */
3005 /* With share level security vuid will always be zero.
3006 Don't depend on vuser being non-null !!. JRA */
3007 user_struct *vuser = get_valid_user_struct(vuid);
3009 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3010 vuser->user.unix_name));
3014 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3019 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3021 /* check it's a supported variant */
3022 if (strcmp(str1,"zWrLh") != 0) {
3026 case 0: level_string = "B21"; break;
3027 case 1: level_string = "B21BB16DWzzWz"; break;
3028 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3029 case 10: level_string = "B21Bzzz"; break;
3030 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3031 default: return False;
3034 if (strcmp(level_string,str2) != 0) {
3038 *rdata_len = mdrcnt + 1024;
3039 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3044 SSVAL(*rparam,0,NERR_Success);
3045 SSVAL(*rparam,2,0); /* converter word */
3048 p2 = p + usri11_end;
3051 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3054 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3059 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3060 pstrcpy(p2,"Comment");
3061 p2 = skip_string(p2,1);
3063 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3064 pstrcpy(p2,"UserComment");
3065 p2 = skip_string(p2,1);
3067 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3068 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3069 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3070 p2 = skip_string(p2,1);
3074 /* modelled after NTAS 3.51 reply */
3075 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3076 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3077 SIVALS(p,usri11_password_age,-1); /* password age */
3078 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3079 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3080 p2 = skip_string(p2,1);
3081 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3083 p2 = skip_string(p2,1);
3084 SIVAL(p,usri11_last_logon,0); /* last logon */
3085 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3086 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3087 SSVALS(p,usri11_num_logons,-1); /* num logons */
3088 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3089 pstrcpy(p2,"\\\\*");
3090 p2 = skip_string(p2,1);
3091 SSVAL(p,usri11_country_code,0); /* country code */
3093 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3095 p2 = skip_string(p2,1);
3097 SIVALS(p,usri11_max_storage,-1); /* max storage */
3098 SSVAL(p,usri11_units_per_week,168); /* units per week */
3099 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3101 /* a simple way to get logon hours at all times. */
3103 SCVAL(p2,21,0); /* fix zero termination */
3104 p2 = skip_string(p2,1);
3106 SSVAL(p,usri11_code_page,0); /* code page */
3109 if (uLevel == 1 || uLevel == 2) {
3110 memset(p+22,' ',16); /* password */
3111 SIVALS(p,38,-1); /* password age */
3113 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3114 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3115 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3116 p2 = skip_string(p2,1);
3117 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3119 SSVAL(p,52,0); /* flags */
3120 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3121 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3122 p2 = skip_string(p2,1);
3124 SIVAL(p,60,0); /* auth_flags */
3125 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3126 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3127 p2 = skip_string(p2,1);
3128 SIVAL(p,68,0); /* urs_comment */
3129 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3131 p2 = skip_string(p2,1);
3132 SIVAL(p,76,0); /* workstations */
3133 SIVAL(p,80,0); /* last_logon */
3134 SIVAL(p,84,0); /* last_logoff */
3135 SIVALS(p,88,-1); /* acct_expires */
3136 SIVALS(p,92,-1); /* max_storage */
3137 SSVAL(p,96,168); /* units_per_week */
3138 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3141 SSVALS(p,102,-1); /* bad_pw_count */
3142 SSVALS(p,104,-1); /* num_logons */
3143 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3146 pstrcpy(tmp, "\\\\%L");
3147 standard_sub_basic("", "", tmp, sizeof(tmp));
3150 p2 = skip_string(p2,1);
3151 SSVAL(p,110,49); /* country_code */
3152 SSVAL(p,112,860); /* code page */
3156 *rdata_len = PTR_DIFF(p2,*rdata);
3158 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3163 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
3164 int mdrcnt,int mprcnt,
3165 char **rdata,char **rparam,
3166 int *rdata_len,int *rparam_len)
3168 char *str1 = param+2;
3169 char *str2 = skip_string(str1,1);
3170 char *p = skip_string(str2,1);
3172 struct pack_desc desc;
3174 /* With share level security vuid will always be zero.
3175 Don't depend on vuser being non-null !!. JRA */
3176 user_struct *vuser = get_valid_user_struct(vuid);
3179 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3180 vuser->user.unix_name));
3186 memset((char *)&desc,'\0',sizeof(desc));
3188 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3190 /* check it's a supported varient */
3191 if (strcmp(str1,"OOWb54WrLh") != 0) {
3194 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3198 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3205 desc.buflen = mdrcnt;
3206 desc.subformat = NULL;
3209 if (init_package(&desc,1,0)) {
3210 PACKI(&desc,"W",0); /* code */
3211 PACKS(&desc,"B21",name); /* eff. name */
3212 PACKS(&desc,"B",""); /* pad */
3213 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3214 PACKI(&desc,"D",0); /* auth flags XXX */
3215 PACKI(&desc,"W",0); /* num logons */
3216 PACKI(&desc,"W",0); /* bad pw count */
3217 PACKI(&desc,"D",0); /* last logon */
3218 PACKI(&desc,"D",-1); /* last logoff */
3219 PACKI(&desc,"D",-1); /* logoff time */
3220 PACKI(&desc,"D",-1); /* kickoff time */
3221 PACKI(&desc,"D",0); /* password age */
3222 PACKI(&desc,"D",0); /* password can change */
3223 PACKI(&desc,"D",-1); /* password must change */
3227 fstrcpy(mypath,"\\\\");
3228 fstrcat(mypath,get_local_machine_name());
3230 PACKS(&desc,"z",mypath); /* computer */
3233 PACKS(&desc,"z",lp_workgroup());/* domain */
3234 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3235 PACKI(&desc,"D",0x00000000); /* reserved */
3238 *rdata_len = desc.usedlen;
3240 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3244 SSVALS(*rparam,0,desc.errcode);
3246 SSVAL(*rparam,4,desc.neededlen);
3248 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3253 /****************************************************************************
3254 api_WAccessGetUserPerms
3255 ****************************************************************************/
3257 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
3258 int mdrcnt,int mprcnt,
3259 char **rdata,char **rparam,
3260 int *rdata_len,int *rparam_len)
3262 char *str1 = param+2;
3263 char *str2 = skip_string(str1,1);
3264 char *user = skip_string(str2,1);
3265 char *resource = skip_string(user,1);
3267 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3269 /* check it's a supported varient */
3270 if (strcmp(str1,"zzh") != 0) {
3273 if (strcmp(str2,"") != 0) {
3278 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3282 SSVALS(*rparam,0,0); /* errorcode */
3283 SSVAL(*rparam,2,0); /* converter word */
3284 SSVAL(*rparam,4,0x7f); /* permission flags */
3289 /****************************************************************************
3290 api_WPrintJobEnumerate
3291 ****************************************************************************/
3293 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3294 int mdrcnt,int mprcnt,
3295 char **rdata,char **rparam,
3296 int *rdata_len,int *rparam_len)
3298 char *str1 = param+2;
3299 char *str2 = skip_string(str1,1);
3300 char *p = skip_string(str2,1);
3307 struct pack_desc desc;
3308 print_queue_struct *queue=NULL;
3309 print_status_struct status;
3314 memset((char *)&desc,'\0',sizeof(desc));
3315 memset((char *)&status,'\0',sizeof(status));
3317 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3319 /* check it's a supported varient */
3320 if (strcmp(str1,"WWrLh") != 0) {
3323 if (!check_printjob_info(&desc,uLevel,str2)) {
3327 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3331 snum = lp_servicenumber( sharename);
3332 if (snum < 0 || !VALID_SNUM(snum)) {
3336 count = print_queue_status(snum,&queue,&status);
3337 for (i = 0; i < count; i++) {
3338 if (queue[i].job == jobid) {
3344 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3349 desc.buflen = mdrcnt;
3352 * Don't return data but need to get correct length
3353 * init_package will return wrong size if buflen=0
3355 desc.buflen = getlen(desc.format);
3356 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3359 if (init_package(&desc,1,0)) {
3361 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3362 *rdata_len = desc.usedlen;
3364 desc.errcode = NERR_JobNotFound;
3370 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3374 SSVALS(*rparam,0,desc.errcode);
3376 SSVAL(*rparam,4,desc.neededlen);
3381 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3386 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3387 int mdrcnt,int mprcnt,
3388 char **rdata,char **rparam,
3389 int *rdata_len,int *rparam_len)
3391 char *str1 = param+2;
3392 char *str2 = skip_string(str1,1);
3393 char *p = skip_string(str2,1);
3399 struct pack_desc desc;
3400 print_queue_struct *queue=NULL;
3401 print_status_struct status;
3403 memset((char *)&desc,'\0',sizeof(desc));
3404 memset((char *)&status,'\0',sizeof(status));
3406 p = skip_string(p,1);
3409 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3411 /* check it's a supported variant */
3412 if (strcmp(str1,"zWrLeh") != 0) {
3417 return False; /* defined only for uLevel 0,1,2 */
3420 if (!check_printjob_info(&desc,uLevel,str2)) {
3424 snum = find_service(name);
3425 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3429 count = print_queue_status(snum,&queue,&status);
3431 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3437 desc.buflen = mdrcnt;
3439 if (init_package(&desc,count,0)) {
3441 for (i = 0; i < count; i++) {
3442 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3443 if (desc.errcode == NERR_Success) {
3449 *rdata_len = desc.usedlen;
3452 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3456 SSVALS(*rparam,0,desc.errcode);
3458 SSVAL(*rparam,4,succnt);
3459 SSVAL(*rparam,6,count);
3463 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3468 static int check_printdest_info(struct pack_desc* desc,
3469 int uLevel, char* id)
3471 desc->subformat = NULL;
3474 desc->format = "B9";
3477 desc->format = "B9B21WWzW";
3483 desc->format = "zzzWWzzzWW";
3488 if (strcmp(desc->format,id) != 0) {
3494 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3495 struct pack_desc* desc)
3499 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3500 buf[sizeof(buf)-1] = 0;
3504 PACKS(desc,"B9",buf); /* szName */
3506 PACKS(desc,"B21",""); /* szUserName */
3507 PACKI(desc,"W",0); /* uJobId */
3508 PACKI(desc,"W",0); /* fsStatus */
3509 PACKS(desc,"z",""); /* pszStatus */
3510 PACKI(desc,"W",0); /* time */
3514 if (uLevel == 2 || uLevel == 3) {
3515 PACKS(desc,"z",buf); /* pszPrinterName */
3517 PACKS(desc,"z",""); /* pszUserName */
3518 PACKS(desc,"z",""); /* pszLogAddr */
3519 PACKI(desc,"W",0); /* uJobId */
3520 PACKI(desc,"W",0); /* fsStatus */
3521 PACKS(desc,"z",""); /* pszStatus */
3522 PACKS(desc,"z",""); /* pszComment */
3523 PACKS(desc,"z","NULL"); /* pszDrivers */
3524 PACKI(desc,"W",0); /* time */
3525 PACKI(desc,"W",0); /* pad1 */
3530 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3531 int mdrcnt,int mprcnt,
3532 char **rdata,char **rparam,
3533 int *rdata_len,int *rparam_len)
3535 char *str1 = param+2;
3536 char *str2 = skip_string(str1,1);
3537 char *p = skip_string(str2,1);
3538 char* PrinterName = p;
3540 struct pack_desc desc;
3544 memset((char *)&desc,'\0',sizeof(desc));
3546 p = skip_string(p,1);
3549 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3551 /* check it's a supported varient */
3552 if (strcmp(str1,"zWrLh") != 0) {
3555 if (!check_printdest_info(&desc,uLevel,str2)) {
3559 snum = find_service(PrinterName);
3560 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3562 desc.errcode = NERR_DestNotFound;
3566 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3571 desc.buflen = mdrcnt;
3574 * Don't return data but need to get correct length
3575 * init_package will return wrong size if buflen=0
3577 desc.buflen = getlen(desc.format);
3578 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3580 if (init_package(&desc,1,0)) {
3581 fill_printdest_info(conn,snum,uLevel,&desc);
3583 *rdata_len = desc.usedlen;
3587 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3591 SSVALS(*rparam,0,desc.errcode);
3593 SSVAL(*rparam,4,desc.neededlen);
3595 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3601 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3602 int mdrcnt,int mprcnt,
3603 char **rdata,char **rparam,
3604 int *rdata_len,int *rparam_len)
3606 char *str1 = param+2;
3607 char *str2 = skip_string(str1,1);
3608 char *p = skip_string(str2,1);
3612 struct pack_desc desc;
3613 int services = lp_numservices();
3615 memset((char *)&desc,'\0',sizeof(desc));
3619 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3621 /* check it's a supported varient */
3622 if (strcmp(str1,"WrLeh") != 0) {
3625 if (!check_printdest_info(&desc,uLevel,str2)) {
3630 for (i = 0; i < services; i++) {
3631 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3637 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3644 desc.buflen = mdrcnt;
3645 if (init_package(&desc,queuecnt,0)) {
3648 for (i = 0; i < services; i++) {
3649 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3650 fill_printdest_info(conn,i,uLevel,&desc);
3652 if (desc.errcode == NERR_Success) {
3659 *rdata_len = desc.usedlen;
3662 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3666 SSVALS(*rparam,0,desc.errcode);
3668 SSVAL(*rparam,4,succnt);
3669 SSVAL(*rparam,6,queuecnt);
3671 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3676 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3677 int mdrcnt,int mprcnt,
3678 char **rdata,char **rparam,
3679 int *rdata_len,int *rparam_len)
3681 char *str1 = param+2;
3682 char *str2 = skip_string(str1,1);
3683 char *p = skip_string(str2,1);
3686 struct pack_desc desc;
3688 memset((char *)&desc,'\0',sizeof(desc));
3692 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3694 /* check it's a supported varient */
3695 if (strcmp(str1,"WrLeh") != 0) {
3698 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
3703 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3709 desc.buflen = mdrcnt;
3710 if (init_package(&desc,1,0)) {
3711 PACKS(&desc,"B41","NULL");
3714 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3716 *rdata_len = desc.usedlen;
3719 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3723 SSVALS(*rparam,0,desc.errcode);
3725 SSVAL(*rparam,4,succnt);
3728 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3733 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3734 int mdrcnt,int mprcnt,
3735 char **rdata,char **rparam,
3736 int *rdata_len,int *rparam_len)
3738 char *str1 = param+2;
3739 char *str2 = skip_string(str1,1);
3740 char *p = skip_string(str2,1);
3743 struct pack_desc desc;
3745 memset((char *)&desc,'\0',sizeof(desc));
3749 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3751 /* check it's a supported varient */
3752 if (strcmp(str1,"WrLeh") != 0) {
3755 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
3760 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3766 desc.buflen = mdrcnt;
3768 if (init_package(&desc,1,0)) {
3769 PACKS(&desc,"B13","lpd");
3772 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3774 *rdata_len = desc.usedlen;
3777 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3781 SSVALS(*rparam,0,desc.errcode);
3783 SSVAL(*rparam,4,succnt);
3786 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3791 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3792 int mdrcnt,int mprcnt,
3793 char **rdata,char **rparam,
3794 int *rdata_len,int *rparam_len)
3796 char *str1 = param+2;
3797 char *str2 = skip_string(str1,1);
3798 char *p = skip_string(str2,1);
3801 struct pack_desc desc;
3803 memset((char *)&desc,'\0',sizeof(desc));
3807 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3809 /* check it's a supported varient */
3810 if (strcmp(str1,"WrLeh") != 0) {
3813 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
3818 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3823 memset((char *)&desc,'\0',sizeof(desc));
3825 desc.buflen = mdrcnt;
3827 if (init_package(&desc,1,0)) {
3828 PACKS(&desc,"B13","lp0");
3831 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3833 *rdata_len = desc.usedlen;
3836 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3840 SSVALS(*rparam,0,desc.errcode);
3842 SSVAL(*rparam,4,succnt);
3845 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3851 /****************************************************************************
3853 ****************************************************************************/
3854 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3855 int mdrcnt,int mprcnt,
3856 char **rdata,char **rparam,
3857 int *rdata_len,int *rparam_len)
3860 char *str1 = param+2;
3861 char *str2 = skip_string(str1,1);
3862 char *p = skip_string(str2,1);
3864 struct pack_desc desc;
3865 struct sessionid *session_list;
3866 int i, num_sessions;
3868 memset((char *)&desc,'\0',sizeof(desc));
3872 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3873 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3874 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3876 /* check it's a supported varient */
3877 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
3880 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
3884 num_sessions = list_sessions(&session_list);
3887 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3892 memset((char *)&desc,'\0',sizeof(desc));
3894 desc.buflen = mdrcnt;
3896 if (!init_package(&desc,num_sessions,0)) {
3900 for(i=0; i<num_sessions; i++) {
3901 PACKS(&desc, "z", session_list[i].remote_machine);
3902 PACKS(&desc, "z", session_list[i].username);
3903 PACKI(&desc, "W", 1); /* num conns */
3904 PACKI(&desc, "W", 0); /* num opens */
3905 PACKI(&desc, "W", 1); /* num users */
3906 PACKI(&desc, "D", 0); /* session time */
3907 PACKI(&desc, "D", 0); /* idle time */
3908 PACKI(&desc, "D", 0); /* flags */
3909 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3912 *rdata_len = desc.usedlen;
3915 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3919 SSVALS(*rparam,0,desc.errcode);
3920 SSVAL(*rparam,2,0); /* converter */
3921 SSVAL(*rparam,4,num_sessions); /* count */
3923 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3929 /****************************************************************************
3930 The buffer was too small.
3931 ****************************************************************************/
3933 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
3934 int mdrcnt, int mprcnt,
3935 char **rdata, char **rparam,
3936 int *rdata_len, int *rparam_len)
3938 *rparam_len = MIN(*rparam_len,mprcnt);
3939 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3946 SSVAL(*rparam,0,NERR_BufTooSmall);
3948 DEBUG(3,("Supplied buffer too small in API command\n"));
3953 /****************************************************************************
3954 The request is not supported.
3955 ****************************************************************************/
3957 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
3958 int mdrcnt, int mprcnt,
3959 char **rdata, char **rparam,
3960 int *rdata_len, int *rparam_len)
3963 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3970 SSVAL(*rparam,0,NERR_notsupported);
3971 SSVAL(*rparam,2,0); /* converter word */
3973 DEBUG(3,("Unsupported API command\n"));
3978 static const struct {
3981 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3982 int,int,char **,char **,int *,int *);
3983 BOOL auth_user; /* Deny anonymous access? */
3984 } api_commands[] = {
3985 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3986 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3987 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3988 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3989 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3990 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3991 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3992 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3993 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3994 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3995 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3996 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3997 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3998 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3999 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4000 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4001 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4002 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4003 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4004 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4005 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4006 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4007 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4008 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4009 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4010 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4011 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4012 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4013 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4014 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4015 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4016 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4017 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4018 {NULL, -1, api_Unsupported}
4019 /* The following RAP calls are not implemented by Samba:
4021 RAP_WFileEnum2 - anon not OK
4026 /****************************************************************************
4027 Handle remote api calls
4028 ****************************************************************************/
4030 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4031 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4035 char *rparam = NULL;
4042 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4046 api_command = SVAL(params,0);
4048 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4051 skip_string(params+2,1),
4052 tdscnt,tpscnt,mdrcnt,mprcnt));
4054 for (i=0;api_commands[i].name;i++) {
4055 if (api_commands[i].id == api_command && api_commands[i].fn) {
4056 DEBUG(3,("Doing %s\n",api_commands[i].name));
4061 /* Check whether this api call can be done anonymously */
4063 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4064 user_struct *user = get_valid_user_struct(vuid);
4066 if (!user || user->guest) {
4067 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4071 rdata = (char *)SMB_MALLOC(1024);
4073 memset(rdata,'\0',1024);
4076 rparam = (char *)SMB_MALLOC(1024);
4078 memset(rparam,'\0',1024);
4081 if(!rdata || !rparam) {
4082 DEBUG(0,("api_reply: malloc fail !\n"));
4088 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
4089 &rdata,&rparam,&rdata_len,&rparam_len);
4092 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4093 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4094 &rdata,&rparam,&rdata_len,&rparam_len);
4097 /* if we get False back then it's actually unsupported */
4099 reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
4100 &rdata,&rparam,&rdata_len,&rparam_len);
4103 /* If api_Unsupported returns false we can't return anything. */
4105 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);