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;
1198 *buflen = struct_len;
1200 return struct_len + len;
1205 if (*buflen < struct_len) {
1212 p2 = p + struct_len;
1213 l2 = *buflen - struct_len;
1221 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1225 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1226 SIVAL(p,18,service->type);
1227 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1228 len += CopyAndAdvance(&p2,service->comment,&l2);
1233 *buf = p + struct_len;
1234 *buflen -= struct_len;
1245 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1247 return(strcmp(s1->name,s2->name));
1250 /****************************************************************************
1251 View list of servers available (or possibly domains). The info is
1252 extracted from lists saved by nmbd on the local host.
1253 ****************************************************************************/
1255 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1256 int mdrcnt, int mprcnt, char **rdata,
1257 char **rparam, int *rdata_len, int *rparam_len)
1259 char *str1 = param+2;
1260 char *str2 = skip_string(str1,1);
1261 char *p = skip_string(str2,1);
1262 int uLevel = SVAL(p,0);
1263 int buf_len = SVAL(p,2);
1264 uint32 servertype = IVAL(p,4);
1266 int data_len, fixed_len, string_len;
1267 int f_len = 0, s_len = 0;
1268 struct srv_info_struct *servers=NULL;
1269 int counted=0,total=0;
1272 BOOL domain_request;
1275 /* If someone sets all the bits they don't really mean to set
1276 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1279 if (servertype == SV_TYPE_ALL) {
1280 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1283 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1284 any other bit (they may just set this bit on it's own) they
1285 want all the locally seen servers. However this bit can be
1286 set on its own so set the requested servers to be
1287 ALL - DOMAIN_ENUM. */
1289 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1290 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1293 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1294 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1298 if (!prefix_ok(str1,"WrLehD")) {
1301 if (!check_server_info(uLevel,str2)) {
1305 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1306 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1307 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1309 if (strcmp(str1, "WrLehDz") == 0) {
1310 pull_ascii_fstring(domain, p);
1312 fstrcpy(domain, lp_workgroup());
1315 if (lp_browse_list()) {
1316 total = get_server_info(servertype,&servers,domain);
1319 data_len = fixed_len = string_len = 0;
1323 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1327 char *lastname=NULL;
1329 for (i=0;i<total;i++) {
1330 struct srv_info_struct *s = &servers[i];
1332 if (lastname && strequal(lastname,s->name)) {
1336 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1337 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1338 s->name, s->type, s->comment, s->domain));
1340 if (data_len <= buf_len) {
1343 string_len += s_len;
1350 *rdata_len = fixed_len + string_len;
1351 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1355 memset(*rdata,'\0',*rdata_len);
1357 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1363 char *lastname=NULL;
1364 int count2 = counted;
1366 for (i = 0; i < total && count2;i++) {
1367 struct srv_info_struct *s = &servers[i];
1369 if (lastname && strequal(lastname,s->name)) {
1373 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1374 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1375 s->name, s->type, s->comment, s->domain));
1381 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1385 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1387 SSVAL(*rparam,4,counted);
1388 SSVAL(*rparam,6,counted+missed);
1392 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1393 domain,uLevel,counted,counted+missed));
1398 /****************************************************************************
1399 command 0x34 - suspected of being a "Lookup Names" stub api
1400 ****************************************************************************/
1402 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1403 int mdrcnt, int mprcnt, char **rdata,
1404 char **rparam, int *rdata_len, int *rparam_len)
1406 char *str1 = param+2;
1407 char *str2 = skip_string(str1,1);
1408 char *p = skip_string(str2,1);
1409 int uLevel = SVAL(p,0);
1410 int buf_len = SVAL(p,2);
1414 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1415 str1, str2, p, uLevel, buf_len));
1417 if (!prefix_ok(str1,"zWrLeh")) {
1424 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1429 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1431 SSVAL(*rparam,4,counted);
1432 SSVAL(*rparam,6,counted+missed);
1437 /****************************************************************************
1438 get info about a share
1439 ****************************************************************************/
1441 static BOOL check_share_info(int uLevel, char* id)
1445 if (strcmp(id,"B13") != 0) {
1450 if (strcmp(id,"B13BWz") != 0) {
1455 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1460 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1470 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1471 char** buf, int* buflen,
1472 char** stringbuf, int* stringspace, char* baseaddr)
1502 len += StrlenExpanded(conn,snum,lp_comment(snum));
1505 len += strlen(lp_pathname(snum)) + 1;
1508 *buflen = struct_len;
1513 return struct_len + len;
1518 if ((*buflen) < struct_len) {
1526 p2 = p + struct_len;
1527 l2 = (*buflen) - struct_len;
1534 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1540 type = STYPE_DISKTREE;
1541 if (lp_print_ok(snum)) {
1542 type = STYPE_PRINTQ;
1544 if (strequal("IPC",lp_fstype(snum))) {
1547 SSVAL(p,14,type); /* device type */
1548 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1549 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1553 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1554 SSVALS(p,22,-1); /* max uses */
1555 SSVAL(p,24,1); /* current uses */
1556 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1557 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1558 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1562 memset(p+40,0,SHPWLEN+2);
1573 (*buf) = p + struct_len;
1574 (*buflen) -= struct_len;
1576 (*stringspace) = l2;
1585 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1586 int mdrcnt,int mprcnt,
1587 char **rdata,char **rparam,
1588 int *rdata_len,int *rparam_len)
1590 char *str1 = param+2;
1591 char *str2 = skip_string(str1,1);
1592 char *netname = skip_string(str2,1);
1593 char *p = skip_string(netname,1);
1594 int uLevel = SVAL(p,0);
1595 int snum = find_service(netname);
1601 /* check it's a supported varient */
1602 if (!prefix_ok(str1,"zWrLh")) {
1605 if (!check_share_info(uLevel,str2)) {
1609 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1614 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1615 if (*rdata_len < 0) {
1620 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1624 SSVAL(*rparam,0,NERR_Success);
1625 SSVAL(*rparam,2,0); /* converter word */
1626 SSVAL(*rparam,4,*rdata_len);
1631 /****************************************************************************
1632 View the list of available shares.
1634 This function is the server side of the NetShareEnum() RAP call.
1635 It fills the return buffer with share names and share comments.
1636 Note that the return buffer normally (in all known cases) allows only
1637 twelve byte strings for share names (plus one for a nul terminator).
1638 Share names longer than 12 bytes must be skipped.
1639 ****************************************************************************/
1641 static BOOL api_RNetShareEnum( connection_struct *conn,
1652 char *str1 = param+2;
1653 char *str2 = skip_string(str1,1);
1654 char *p = skip_string(str2,1);
1655 int uLevel = SVAL(p,0);
1656 int buf_len = SVAL(p,2);
1659 int total=0,counted=0;
1660 BOOL missed = False;
1662 int data_len, fixed_len, string_len;
1663 int f_len = 0, s_len = 0;
1665 if (!prefix_ok(str1,"WrLeh")) {
1668 if (!check_share_info(uLevel,str2)) {
1672 /* Ensure all the usershares are loaded. */
1674 count = load_usershare_shares();
1677 data_len = fixed_len = string_len = 0;
1678 for (i=0;i<count;i++) {
1679 fstring servicename_dos;
1680 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1683 push_ascii_fstring(servicename_dos, lp_servicename(i));
1684 /* Maximum name length = 13. */
1685 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1687 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1688 if (data_len <= buf_len) {
1691 string_len += s_len;
1698 *rdata_len = fixed_len + string_len;
1699 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1703 memset(*rdata,0,*rdata_len);
1705 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1710 for( i = 0; i < count; i++ ) {
1711 fstring servicename_dos;
1712 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1716 push_ascii_fstring(servicename_dos, lp_servicename(i));
1717 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1718 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1725 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1729 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1731 SSVAL(*rparam,4,counted);
1732 SSVAL(*rparam,6,total);
1734 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1735 counted,total,uLevel,
1736 buf_len,*rdata_len,mdrcnt));
1741 /****************************************************************************
1743 ****************************************************************************/
1745 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1746 int mdrcnt,int mprcnt,
1747 char **rdata,char **rparam,
1748 int *rdata_len,int *rparam_len)
1750 char *str1 = param+2;
1751 char *str2 = skip_string(str1,1);
1752 char *p = skip_string(str2,1);
1753 int uLevel = SVAL(p,0);
1757 char *command, *cmdname;
1758 unsigned int offset;
1762 /* check it's a supported varient */
1763 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1766 if (!check_share_info(uLevel,str2)) {
1773 pull_ascii_fstring(sharename,data);
1774 snum = find_service(sharename);
1775 if (snum >= 0) { /* already exists */
1780 /* only support disk share adds */
1781 if (SVAL(data,14)!=STYPE_DISKTREE) {
1785 offset = IVAL(data, 16);
1786 if (offset >= mdrcnt) {
1787 res = ERRinvalidparam;
1791 pull_ascii_fstring(comment, offset? (data+offset) : "");
1793 offset = IVAL(data, 26);
1795 if (offset >= mdrcnt) {
1796 res = ERRinvalidparam;
1800 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1802 string_replace(sharename, '"', ' ');
1803 string_replace(pathname, '"', ' ');
1804 string_replace(comment, '"', ' ');
1806 cmdname = lp_add_share_cmd();
1808 if (!cmdname || *cmdname == '\0') {
1812 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1813 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1816 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1818 if ((res = smbrun(command, NULL)) != 0) {
1819 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1825 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1832 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1836 SSVAL(*rparam,0,NERR_Success);
1837 SSVAL(*rparam,2,0); /* converter word */
1838 SSVAL(*rparam,4,*rdata_len);
1846 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1851 SSVAL(*rparam,0,res);
1856 /****************************************************************************
1857 view list of groups available
1858 ****************************************************************************/
1860 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1861 int mdrcnt,int mprcnt,
1862 char **rdata,char **rparam,
1863 int *rdata_len,int *rparam_len)
1867 int resume_context, cli_buf_size;
1868 char *str1 = param+2;
1869 char *str2 = skip_string(str1,1);
1870 char *p = skip_string(str2,1);
1872 struct pdb_search *search;
1873 struct samr_displayentry *entries;
1877 if (strcmp(str1,"WrLeh") != 0) {
1882 * W-> resume context (number of users to skip)
1883 * r -> return parameter pointer to receive buffer
1884 * L -> length of receive buffer
1885 * e -> return parameter number of entries
1886 * h -> return parameter total number of users
1889 if (strcmp("B21",str2) != 0) {
1893 /* get list of domain groups SID_DOMAIN_GRP=2 */
1895 search = pdb_search_groups();
1898 if (search == NULL) {
1899 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1903 resume_context = SVAL(p,0);
1904 cli_buf_size=SVAL(p+2,0);
1905 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1906 "%d\n", resume_context, cli_buf_size));
1909 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1913 *rdata_len = cli_buf_size;
1914 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1921 for(i=0; i<num_entries; i++) {
1923 fstrcpy(name, entries[i].account_name);
1924 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1925 /* truncate the name at 21 chars. */
1926 memcpy(p, name, 21);
1927 DEBUG(10,("adding entry %d group %s\n", i, p));
1929 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1932 /* set overflow error */
1933 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1939 pdb_search_destroy(search);
1941 *rdata_len = PTR_DIFF(p,*rdata);
1944 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1948 SSVAL(*rparam, 0, errflags);
1949 SSVAL(*rparam, 2, 0); /* converter word */
1950 SSVAL(*rparam, 4, i); /* is this right?? */
1951 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1956 /*******************************************************************
1957 Get groups that a user is a member of.
1958 ******************************************************************/
1960 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1961 int mdrcnt,int mprcnt,
1962 char **rdata,char **rparam,
1963 int *rdata_len,int *rparam_len)
1965 char *str1 = param+2;
1966 char *str2 = skip_string(str1,1);
1967 char *UserName = skip_string(str2,1);
1968 char *p = skip_string(UserName,1);
1969 int uLevel = SVAL(p,0);
1970 const char *level_string;
1972 struct samu *sampw = NULL;
1980 enum lsa_SidType type;
1981 TALLOC_CTX *mem_ctx;
1984 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1989 /* check it's a supported varient */
1991 if ( strcmp(str1,"zWrLeh") != 0 )
1996 level_string = "B21";
2002 if (strcmp(level_string,str2) != 0)
2005 *rdata_len = mdrcnt + 1024;
2006 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2010 SSVAL(*rparam,0,NERR_Success);
2011 SSVAL(*rparam,2,0); /* converter word */
2015 mem_ctx = talloc_new(NULL);
2016 if (mem_ctx == NULL) {
2017 DEBUG(0, ("talloc_new failed\n"));
2021 if ( !(sampw = samu_new(mem_ctx)) ) {
2022 DEBUG(0, ("samu_new() failed!\n"));
2023 TALLOC_FREE(mem_ctx);
2027 /* Lookup the user information; This should only be one of
2028 our accounts (not remote domains) */
2030 become_root(); /* ROOT BLOCK */
2032 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2033 NULL, NULL, &user_sid, &type)) {
2034 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2038 if (type != SID_NAME_USER) {
2039 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2040 sid_type_lookup(type)));
2044 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2045 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2046 sid_string_static(&user_sid), UserName));
2054 result = pdb_enum_group_memberships(mem_ctx, sampw,
2055 &sids, &gids, &num_groups);
2057 if (!NT_STATUS_IS_OK(result)) {
2058 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2063 for (i=0; i<num_groups; i++) {
2065 const char *grp_name;
2067 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2068 pstrcpy(p, grp_name);
2074 *rdata_len = PTR_DIFF(p,*rdata);
2076 SSVAL(*rparam,4,count); /* is this right?? */
2077 SSVAL(*rparam,6,count); /* is this right?? */
2082 unbecome_root(); /* END ROOT BLOCK */
2084 TALLOC_FREE(mem_ctx);
2089 /*******************************************************************
2091 ******************************************************************/
2093 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2094 int mdrcnt,int mprcnt,
2095 char **rdata,char **rparam,
2096 int *rdata_len,int *rparam_len)
2101 int i, resume_context, cli_buf_size;
2102 struct pdb_search *search;
2103 struct samr_displayentry *users;
2105 char *str1 = param+2;
2106 char *str2 = skip_string(str1,1);
2107 char *p = skip_string(str2,1);
2109 if (strcmp(str1,"WrLeh") != 0)
2112 * W-> resume context (number of users to skip)
2113 * r -> return parameter pointer to receive buffer
2114 * L -> length of receive buffer
2115 * e -> return parameter number of entries
2116 * h -> return parameter total number of users
2119 resume_context = SVAL(p,0);
2120 cli_buf_size=SVAL(p+2,0);
2121 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2122 resume_context, cli_buf_size));
2125 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2130 /* check it's a supported varient */
2131 if (strcmp("B21",str2) != 0)
2134 *rdata_len = cli_buf_size;
2135 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2143 search = pdb_search_users(ACB_NORMAL);
2145 if (search == NULL) {
2146 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2151 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2155 errflags=NERR_Success;
2157 for (i=0; i<num_users; i++) {
2158 const char *name = users[i].account_name;
2160 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2162 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2163 "%s\n",count_sent,p));
2167 /* set overflow error */
2168 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2169 "username %s\n",count_sent,name));
2175 pdb_search_destroy(search);
2177 *rdata_len = PTR_DIFF(p,*rdata);
2179 SSVAL(*rparam,0,errflags);
2180 SSVAL(*rparam,2,0); /* converter word */
2181 SSVAL(*rparam,4,count_sent); /* is this right?? */
2182 SSVAL(*rparam,6,num_users); /* is this right?? */
2187 /****************************************************************************
2188 Get the time of day info.
2189 ****************************************************************************/
2191 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
2192 int mdrcnt,int mprcnt,
2193 char **rdata,char **rparam,
2194 int *rdata_len,int *rparam_len)
2197 time_t unixdate = time(NULL);
2201 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2207 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2212 SSVAL(*rparam,0,NERR_Success);
2213 SSVAL(*rparam,2,0); /* converter word */
2217 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2218 by NT in a "net time" operation,
2219 it seems to ignore the one below */
2221 /* the client expects to get localtime, not GMT, in this bit
2222 (I think, this needs testing) */
2223 t = localtime(&unixdate);
2228 SIVAL(p,4,0); /* msecs ? */
2229 SCVAL(p,8,t->tm_hour);
2230 SCVAL(p,9,t->tm_min);
2231 SCVAL(p,10,t->tm_sec);
2232 SCVAL(p,11,0); /* hundredths of seconds */
2233 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2234 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2235 SCVAL(p,16,t->tm_mday);
2236 SCVAL(p,17,t->tm_mon + 1);
2237 SSVAL(p,18,1900+t->tm_year);
2238 SCVAL(p,20,t->tm_wday);
2243 /****************************************************************************
2244 Set the user password.
2245 *****************************************************************************/
2247 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2248 int mdrcnt,int mprcnt,
2249 char **rdata,char **rparam,
2250 int *rdata_len,int *rparam_len)
2252 char *p = skip_string(param+2,2);
2254 fstring pass1,pass2;
2256 pull_ascii_fstring(user,p);
2258 p = skip_string(p,1);
2260 memset(pass1,'\0',sizeof(pass1));
2261 memset(pass2,'\0',sizeof(pass2));
2263 memcpy(pass2,p+16,16);
2266 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2273 SSVAL(*rparam,0,NERR_badpass);
2274 SSVAL(*rparam,2,0); /* converter word */
2276 DEBUG(3,("Set password for <%s>\n",user));
2279 * Attempt to verify the old password against smbpasswd entries
2280 * Win98 clients send old and new password in plaintext for this call.
2284 auth_serversupplied_info *server_info = NULL;
2285 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2287 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2290 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2291 SSVAL(*rparam,0,NERR_Success);
2295 TALLOC_FREE(server_info);
2297 data_blob_clear_free(&password);
2301 * If the plaintext change failed, attempt
2302 * the old encrypted method. NT will generate this
2303 * after trying the samr method. Note that this
2304 * method is done as a last resort as this
2305 * password change method loses the NT password hash
2306 * and cannot change the UNIX password as no plaintext
2310 if(SVAL(*rparam,0) != NERR_Success) {
2311 struct samu *hnd = NULL;
2313 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2315 if (change_lanman_password(hnd,(uchar *)pass2)) {
2316 SSVAL(*rparam,0,NERR_Success);
2323 memset((char *)pass1,'\0',sizeof(fstring));
2324 memset((char *)pass2,'\0',sizeof(fstring));
2329 /****************************************************************************
2330 Set the user password (SamOEM version - gets plaintext).
2331 ****************************************************************************/
2333 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2334 int mdrcnt,int mprcnt,
2335 char **rdata,char **rparam,
2336 int *rdata_len,int *rparam_len)
2339 char *p = param + 2;
2341 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2348 SSVAL(*rparam,0,NERR_badpass);
2351 * Check the parameter definition is correct.
2354 if(!strequal(param + 2, "zsT")) {
2355 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2358 p = skip_string(p, 1);
2360 if(!strequal(p, "B516B16")) {
2361 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2364 p = skip_string(p,1);
2365 p += pull_ascii_fstring(user,p);
2367 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2370 * Pass the user through the NT -> unix user mapping
2374 (void)map_username(user);
2376 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2377 SSVAL(*rparam,0,NERR_Success);
2383 /****************************************************************************
2386 ****************************************************************************/
2388 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2389 int mdrcnt,int mprcnt,
2390 char **rdata,char **rparam,
2391 int *rdata_len,int *rparam_len)
2393 int function = SVAL(param,0);
2394 char *str1 = param+2;
2395 char *str2 = skip_string(str1,1);
2396 char *p = skip_string(str2,1);
2401 WERROR werr = WERR_OK;
2403 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2406 /* check it's a supported varient */
2407 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2411 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2417 if (!print_job_exists(sharename, jobid)) {
2418 errcode = NERR_JobNotFound;
2422 snum = lp_servicenumber( sharename);
2424 errcode = NERR_DestNotFound;
2428 errcode = NERR_notsupported;
2431 case 81: /* delete */
2432 if (print_job_delete(¤t_user, snum, jobid, &werr))
2433 errcode = NERR_Success;
2435 case 82: /* pause */
2436 if (print_job_pause(¤t_user, snum, jobid, &werr))
2437 errcode = NERR_Success;
2439 case 83: /* resume */
2440 if (print_job_resume(¤t_user, snum, jobid, &werr))
2441 errcode = NERR_Success;
2445 if (!W_ERROR_IS_OK(werr))
2446 errcode = W_ERROR_V(werr);
2449 SSVAL(*rparam,0,errcode);
2450 SSVAL(*rparam,2,0); /* converter word */
2455 /****************************************************************************
2456 Purge a print queue - or pause or resume it.
2457 ****************************************************************************/
2459 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2460 int mdrcnt,int mprcnt,
2461 char **rdata,char **rparam,
2462 int *rdata_len,int *rparam_len)
2464 int function = SVAL(param,0);
2465 char *str1 = param+2;
2466 char *str2 = skip_string(str1,1);
2467 char *QueueName = skip_string(str2,1);
2468 int errcode = NERR_notsupported;
2470 WERROR werr = WERR_OK;
2472 /* check it's a supported varient */
2473 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2477 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2483 snum = print_queue_snum(QueueName);
2486 errcode = NERR_JobNotFound;
2491 case 74: /* Pause queue */
2492 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2494 case 75: /* Resume queue */
2495 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2497 case 103: /* Purge */
2498 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2502 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2505 SSVAL(*rparam,0,errcode);
2506 SSVAL(*rparam,2,0); /* converter word */
2511 /****************************************************************************
2512 set the property of a print job (undocumented?)
2513 ? function = 0xb -> set name of print job
2514 ? function = 0x6 -> move print job up/down
2515 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2516 or <WWsTP> <WB21BB16B10zWWzDDz>
2517 ****************************************************************************/
2519 static int check_printjob_info(struct pack_desc* desc,
2520 int uLevel, char* id)
2522 desc->subformat = NULL;
2524 case 0: desc->format = "W"; break;
2525 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2526 case 2: desc->format = "WWzWWDDzz"; break;
2527 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2528 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2529 default: return False;
2531 if (strcmp(desc->format,id) != 0) return False;
2535 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2536 int mdrcnt,int mprcnt,
2537 char **rdata,char **rparam,
2538 int *rdata_len,int *rparam_len)
2540 struct pack_desc desc;
2541 char *str1 = param+2;
2542 char *str2 = skip_string(str1,1);
2543 char *p = skip_string(str2,1);
2546 int uLevel = SVAL(p,2);
2547 int function = SVAL(p,4);
2550 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2553 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2558 if (!share_defined(sharename)) {
2559 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2566 /* check it's a supported varient */
2567 if ((strcmp(str1,"WWsTP")) ||
2568 (!check_printjob_info(&desc,uLevel,str2)))
2571 if (!print_job_exists(sharename, jobid)) {
2572 errcode=NERR_JobNotFound;
2576 errcode = NERR_notsupported;
2580 /* change job place in the queue,
2581 data gives the new place */
2582 place = SVAL(data,0);
2583 if (print_job_set_place(sharename, jobid, place)) {
2584 errcode=NERR_Success;
2589 /* change print job name, data gives the name */
2590 if (print_job_set_name(sharename, jobid, data)) {
2591 errcode=NERR_Success;
2600 SSVALS(*rparam,0,errcode);
2601 SSVAL(*rparam,2,0); /* converter word */
2607 /****************************************************************************
2608 Get info about the server.
2609 ****************************************************************************/
2611 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2612 int mdrcnt,int mprcnt,
2613 char **rdata,char **rparam,
2614 int *rdata_len,int *rparam_len)
2616 char *str1 = param+2;
2617 char *str2 = skip_string(str1,1);
2618 char *p = skip_string(str2,1);
2619 int uLevel = SVAL(p,0);
2623 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2625 /* check it's a supported varient */
2626 if (!prefix_ok(str1,"WrLh")) {
2632 if (strcmp(str2,"B16") != 0) {
2638 if (strcmp(str2,"B16BBDz") != 0) {
2644 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2650 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2656 if (strcmp(str2,"DN") != 0) {
2662 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2671 *rdata_len = mdrcnt;
2672 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2678 p2 = p + struct_len;
2680 srvstr_push(NULL, p,get_local_machine_name(),16,
2681 STR_ASCII|STR_UPPER|STR_TERMINATE);
2685 struct srv_info_struct *servers=NULL;
2688 uint32 servertype= lp_default_server_announce();
2690 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2692 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2693 for (i=0;i<count;i++) {
2694 if (strequal(servers[i].name,get_local_machine_name())) {
2695 servertype = servers[i].type;
2696 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2703 SCVAL(p,0,lp_major_announce_version());
2704 SCVAL(p,1,lp_minor_announce_version());
2705 SIVAL(p,2,servertype);
2707 if (mdrcnt == struct_len) {
2710 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2711 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
2712 conn->connectpath, conn->gid,
2713 get_current_username(),
2714 current_user_info.domain,
2715 comment, sizeof(comment));
2716 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2717 p2 = skip_string(p2,1);
2722 return False; /* not yet implemented */
2725 *rdata_len = PTR_DIFF(p2,*rdata);
2728 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2732 SSVAL(*rparam,0,NERR_Success);
2733 SSVAL(*rparam,2,0); /* converter word */
2734 SSVAL(*rparam,4,*rdata_len);
2739 /****************************************************************************
2740 Get info about the server.
2741 ****************************************************************************/
2743 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2744 int mdrcnt,int mprcnt,
2745 char **rdata,char **rparam,
2746 int *rdata_len,int *rparam_len)
2748 char *str1 = param+2;
2749 char *str2 = skip_string(str1,1);
2750 char *p = skip_string(str2,1);
2752 int level = SVAL(p,0);
2754 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2757 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2762 /* check it's a supported varient */
2763 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2767 *rdata_len = mdrcnt + 1024;
2768 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2773 SSVAL(*rparam,0,NERR_Success);
2774 SSVAL(*rparam,2,0); /* converter word */
2779 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2780 pstrcpy(p2,get_local_machine_name());
2782 p2 = skip_string(p2,1);
2785 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2786 pstrcpy(p2,current_user_info.smb_name);
2787 p2 = skip_string(p2,1);
2790 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2791 pstrcpy(p2,lp_workgroup());
2793 p2 = skip_string(p2,1);
2796 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2797 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2800 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2801 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2802 p2 = skip_string(p2,1);
2805 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2807 p2 = skip_string(p2,1);
2810 *rdata_len = PTR_DIFF(p2,*rdata);
2812 SSVAL(*rparam,4,*rdata_len);
2817 /****************************************************************************
2818 get info about a user
2820 struct user_info_11 {
2821 char usri11_name[21]; 0-20
2823 char *usri11_comment; 22-25
2824 char *usri11_usr_comment; 26-29
2825 unsigned short usri11_priv; 30-31
2826 unsigned long usri11_auth_flags; 32-35
2827 long usri11_password_age; 36-39
2828 char *usri11_homedir; 40-43
2829 char *usri11_parms; 44-47
2830 long usri11_last_logon; 48-51
2831 long usri11_last_logoff; 52-55
2832 unsigned short usri11_bad_pw_count; 56-57
2833 unsigned short usri11_num_logons; 58-59
2834 char *usri11_logon_server; 60-63
2835 unsigned short usri11_country_code; 64-65
2836 char *usri11_workstations; 66-69
2837 unsigned long usri11_max_storage; 70-73
2838 unsigned short usri11_units_per_week; 74-75
2839 unsigned char *usri11_logon_hours; 76-79
2840 unsigned short usri11_code_page; 80-81
2845 usri11_name specifies the user name for which information is retireved
2847 usri11_pad aligns the next data structure element to a word boundary
2849 usri11_comment is a null terminated ASCII comment
2851 usri11_user_comment is a null terminated ASCII comment about the user
2853 usri11_priv specifies the level of the privilege assigned to the user.
2854 The possible values are:
2856 Name Value Description
2857 USER_PRIV_GUEST 0 Guest privilege
2858 USER_PRIV_USER 1 User privilege
2859 USER_PRV_ADMIN 2 Administrator privilege
2861 usri11_auth_flags specifies the account operator privileges. The
2862 possible values are:
2864 Name Value Description
2865 AF_OP_PRINT 0 Print operator
2868 Leach, Naik [Page 28]
2872 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2875 AF_OP_COMM 1 Communications operator
2876 AF_OP_SERVER 2 Server operator
2877 AF_OP_ACCOUNTS 3 Accounts operator
2880 usri11_password_age specifies how many seconds have elapsed since the
2881 password was last changed.
2883 usri11_home_dir points to a null terminated ASCII string that contains
2884 the path name of the user's home directory.
2886 usri11_parms points to a null terminated ASCII string that is set
2887 aside for use by applications.
2889 usri11_last_logon specifies the time when the user last logged on.
2890 This value is stored as the number of seconds elapsed since
2891 00:00:00, January 1, 1970.
2893 usri11_last_logoff specifies the time when the user last logged off.
2894 This value is stored as the number of seconds elapsed since
2895 00:00:00, January 1, 1970. A value of 0 means the last logoff
2898 usri11_bad_pw_count specifies the number of incorrect passwords
2899 entered since the last successful logon.
2901 usri11_log1_num_logons specifies the number of times this user has
2902 logged on. A value of -1 means the number of logons is unknown.
2904 usri11_logon_server points to a null terminated ASCII string that
2905 contains the name of the server to which logon requests are sent.
2906 A null string indicates logon requests should be sent to the
2909 usri11_country_code specifies the country code for the user's language
2912 usri11_workstations points to a null terminated ASCII string that
2913 contains the names of workstations the user may log on from.
2914 There may be up to 8 workstations, with the names separated by
2915 commas. A null strings indicates there are no restrictions.
2917 usri11_max_storage specifies the maximum amount of disk space the user
2918 can occupy. A value of 0xffffffff indicates there are no
2921 usri11_units_per_week specifies the equal number of time units into
2922 which a week is divided. This value must be equal to 168.
2924 usri11_logon_hours points to a 21 byte (168 bits) string that
2925 specifies the time during which the user can log on. Each bit
2926 represents one unique hour in a week. The first bit (bit 0, word
2927 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2931 Leach, Naik [Page 29]
2935 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2938 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2939 are no restrictions.
2941 usri11_code_page specifies the code page for the user's language of
2944 All of the pointers in this data structure need to be treated
2945 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2946 to be ignored. The converter word returned in the parameters section
2947 needs to be subtracted from the lower 16 bits to calculate an offset
2948 into the return buffer where this ASCII string resides.
2950 There is no auxiliary data in the response.
2952 ****************************************************************************/
2954 #define usri11_name 0
2955 #define usri11_pad 21
2956 #define usri11_comment 22
2957 #define usri11_usr_comment 26
2958 #define usri11_full_name 30
2959 #define usri11_priv 34
2960 #define usri11_auth_flags 36
2961 #define usri11_password_age 40
2962 #define usri11_homedir 44
2963 #define usri11_parms 48
2964 #define usri11_last_logon 52
2965 #define usri11_last_logoff 56
2966 #define usri11_bad_pw_count 60
2967 #define usri11_num_logons 62
2968 #define usri11_logon_server 64
2969 #define usri11_country_code 68
2970 #define usri11_workstations 70
2971 #define usri11_max_storage 74
2972 #define usri11_units_per_week 78
2973 #define usri11_logon_hours 80
2974 #define usri11_code_page 84
2975 #define usri11_end 86
2977 #define USER_PRIV_GUEST 0
2978 #define USER_PRIV_USER 1
2979 #define USER_PRIV_ADMIN 2
2981 #define AF_OP_PRINT 0
2982 #define AF_OP_COMM 1
2983 #define AF_OP_SERVER 2
2984 #define AF_OP_ACCOUNTS 3
2987 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2988 int mdrcnt,int mprcnt,
2989 char **rdata,char **rparam,
2990 int *rdata_len,int *rparam_len)
2992 char *str1 = param+2;
2993 char *str2 = skip_string(str1,1);
2994 char *UserName = skip_string(str2,1);
2995 char *p = skip_string(UserName,1);
2996 int uLevel = SVAL(p,0);
2998 const char *level_string;
3000 /* get NIS home of a previously validated user - simeon */
3001 /* With share level security vuid will always be zero.
3002 Don't depend on vuser being non-null !!. JRA */
3003 user_struct *vuser = get_valid_user_struct(vuid);
3005 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3006 vuser->user.unix_name));
3010 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3015 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3017 /* check it's a supported variant */
3018 if (strcmp(str1,"zWrLh") != 0) {
3022 case 0: level_string = "B21"; break;
3023 case 1: level_string = "B21BB16DWzzWz"; break;
3024 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3025 case 10: level_string = "B21Bzzz"; break;
3026 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3027 default: return False;
3030 if (strcmp(level_string,str2) != 0) {
3034 *rdata_len = mdrcnt + 1024;
3035 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3040 SSVAL(*rparam,0,NERR_Success);
3041 SSVAL(*rparam,2,0); /* converter word */
3044 p2 = p + usri11_end;
3047 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3050 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3055 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3056 pstrcpy(p2,"Comment");
3057 p2 = skip_string(p2,1);
3059 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3060 pstrcpy(p2,"UserComment");
3061 p2 = skip_string(p2,1);
3063 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3064 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3065 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3066 p2 = skip_string(p2,1);
3070 /* modelled after NTAS 3.51 reply */
3071 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3072 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3073 SIVALS(p,usri11_password_age,-1); /* password age */
3074 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3075 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3076 p2 = skip_string(p2,1);
3077 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3079 p2 = skip_string(p2,1);
3080 SIVAL(p,usri11_last_logon,0); /* last logon */
3081 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3082 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3083 SSVALS(p,usri11_num_logons,-1); /* num logons */
3084 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3085 pstrcpy(p2,"\\\\*");
3086 p2 = skip_string(p2,1);
3087 SSVAL(p,usri11_country_code,0); /* country code */
3089 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3091 p2 = skip_string(p2,1);
3093 SIVALS(p,usri11_max_storage,-1); /* max storage */
3094 SSVAL(p,usri11_units_per_week,168); /* units per week */
3095 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3097 /* a simple way to get logon hours at all times. */
3099 SCVAL(p2,21,0); /* fix zero termination */
3100 p2 = skip_string(p2,1);
3102 SSVAL(p,usri11_code_page,0); /* code page */
3105 if (uLevel == 1 || uLevel == 2) {
3106 memset(p+22,' ',16); /* password */
3107 SIVALS(p,38,-1); /* password age */
3109 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3110 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3111 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3112 p2 = skip_string(p2,1);
3113 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3115 SSVAL(p,52,0); /* flags */
3116 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3117 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3118 p2 = skip_string(p2,1);
3120 SIVAL(p,60,0); /* auth_flags */
3121 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3122 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3123 p2 = skip_string(p2,1);
3124 SIVAL(p,68,0); /* urs_comment */
3125 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3127 p2 = skip_string(p2,1);
3128 SIVAL(p,76,0); /* workstations */
3129 SIVAL(p,80,0); /* last_logon */
3130 SIVAL(p,84,0); /* last_logoff */
3131 SIVALS(p,88,-1); /* acct_expires */
3132 SIVALS(p,92,-1); /* max_storage */
3133 SSVAL(p,96,168); /* units_per_week */
3134 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3137 SSVALS(p,102,-1); /* bad_pw_count */
3138 SSVALS(p,104,-1); /* num_logons */
3139 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3142 pstrcpy(tmp, "\\\\%L");
3143 standard_sub_basic("", "", tmp, sizeof(tmp));
3146 p2 = skip_string(p2,1);
3147 SSVAL(p,110,49); /* country_code */
3148 SSVAL(p,112,860); /* code page */
3152 *rdata_len = PTR_DIFF(p2,*rdata);
3154 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3159 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
3160 int mdrcnt,int mprcnt,
3161 char **rdata,char **rparam,
3162 int *rdata_len,int *rparam_len)
3164 char *str1 = param+2;
3165 char *str2 = skip_string(str1,1);
3166 char *p = skip_string(str2,1);
3168 struct pack_desc desc;
3170 /* With share level security vuid will always be zero.
3171 Don't depend on vuser being non-null !!. JRA */
3172 user_struct *vuser = get_valid_user_struct(vuid);
3175 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3176 vuser->user.unix_name));
3182 memset((char *)&desc,'\0',sizeof(desc));
3184 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3186 /* check it's a supported varient */
3187 if (strcmp(str1,"OOWb54WrLh") != 0) {
3190 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3194 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3201 desc.buflen = mdrcnt;
3202 desc.subformat = NULL;
3205 if (init_package(&desc,1,0)) {
3206 PACKI(&desc,"W",0); /* code */
3207 PACKS(&desc,"B21",name); /* eff. name */
3208 PACKS(&desc,"B",""); /* pad */
3209 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3210 PACKI(&desc,"D",0); /* auth flags XXX */
3211 PACKI(&desc,"W",0); /* num logons */
3212 PACKI(&desc,"W",0); /* bad pw count */
3213 PACKI(&desc,"D",0); /* last logon */
3214 PACKI(&desc,"D",-1); /* last logoff */
3215 PACKI(&desc,"D",-1); /* logoff time */
3216 PACKI(&desc,"D",-1); /* kickoff time */
3217 PACKI(&desc,"D",0); /* password age */
3218 PACKI(&desc,"D",0); /* password can change */
3219 PACKI(&desc,"D",-1); /* password must change */
3223 fstrcpy(mypath,"\\\\");
3224 fstrcat(mypath,get_local_machine_name());
3226 PACKS(&desc,"z",mypath); /* computer */
3229 PACKS(&desc,"z",lp_workgroup());/* domain */
3230 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3231 PACKI(&desc,"D",0x00000000); /* reserved */
3234 *rdata_len = desc.usedlen;
3236 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3240 SSVALS(*rparam,0,desc.errcode);
3242 SSVAL(*rparam,4,desc.neededlen);
3244 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3249 /****************************************************************************
3250 api_WAccessGetUserPerms
3251 ****************************************************************************/
3253 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
3254 int mdrcnt,int mprcnt,
3255 char **rdata,char **rparam,
3256 int *rdata_len,int *rparam_len)
3258 char *str1 = param+2;
3259 char *str2 = skip_string(str1,1);
3260 char *user = skip_string(str2,1);
3261 char *resource = skip_string(user,1);
3263 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3265 /* check it's a supported varient */
3266 if (strcmp(str1,"zzh") != 0) {
3269 if (strcmp(str2,"") != 0) {
3274 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3278 SSVALS(*rparam,0,0); /* errorcode */
3279 SSVAL(*rparam,2,0); /* converter word */
3280 SSVAL(*rparam,4,0x7f); /* permission flags */
3285 /****************************************************************************
3286 api_WPrintJobEnumerate
3287 ****************************************************************************/
3289 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3290 int mdrcnt,int mprcnt,
3291 char **rdata,char **rparam,
3292 int *rdata_len,int *rparam_len)
3294 char *str1 = param+2;
3295 char *str2 = skip_string(str1,1);
3296 char *p = skip_string(str2,1);
3303 struct pack_desc desc;
3304 print_queue_struct *queue=NULL;
3305 print_status_struct status;
3310 memset((char *)&desc,'\0',sizeof(desc));
3311 memset((char *)&status,'\0',sizeof(status));
3313 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3315 /* check it's a supported varient */
3316 if (strcmp(str1,"WWrLh") != 0) {
3319 if (!check_printjob_info(&desc,uLevel,str2)) {
3323 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3327 snum = lp_servicenumber( sharename);
3328 if (snum < 0 || !VALID_SNUM(snum)) {
3332 count = print_queue_status(snum,&queue,&status);
3333 for (i = 0; i < count; i++) {
3334 if (queue[i].job == jobid) {
3340 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3345 desc.buflen = mdrcnt;
3348 * Don't return data but need to get correct length
3349 * init_package will return wrong size if buflen=0
3351 desc.buflen = getlen(desc.format);
3352 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3355 if (init_package(&desc,1,0)) {
3357 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3358 *rdata_len = desc.usedlen;
3360 desc.errcode = NERR_JobNotFound;
3366 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3370 SSVALS(*rparam,0,desc.errcode);
3372 SSVAL(*rparam,4,desc.neededlen);
3377 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3382 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3383 int mdrcnt,int mprcnt,
3384 char **rdata,char **rparam,
3385 int *rdata_len,int *rparam_len)
3387 char *str1 = param+2;
3388 char *str2 = skip_string(str1,1);
3389 char *p = skip_string(str2,1);
3395 struct pack_desc desc;
3396 print_queue_struct *queue=NULL;
3397 print_status_struct status;
3399 memset((char *)&desc,'\0',sizeof(desc));
3400 memset((char *)&status,'\0',sizeof(status));
3402 p = skip_string(p,1);
3405 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3407 /* check it's a supported variant */
3408 if (strcmp(str1,"zWrLeh") != 0) {
3413 return False; /* defined only for uLevel 0,1,2 */
3416 if (!check_printjob_info(&desc,uLevel,str2)) {
3420 snum = find_service(name);
3421 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3425 count = print_queue_status(snum,&queue,&status);
3427 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3433 desc.buflen = mdrcnt;
3435 if (init_package(&desc,count,0)) {
3437 for (i = 0; i < count; i++) {
3438 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3439 if (desc.errcode == NERR_Success) {
3445 *rdata_len = desc.usedlen;
3448 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3452 SSVALS(*rparam,0,desc.errcode);
3454 SSVAL(*rparam,4,succnt);
3455 SSVAL(*rparam,6,count);
3459 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3464 static int check_printdest_info(struct pack_desc* desc,
3465 int uLevel, char* id)
3467 desc->subformat = NULL;
3470 desc->format = "B9";
3473 desc->format = "B9B21WWzW";
3479 desc->format = "zzzWWzzzWW";
3484 if (strcmp(desc->format,id) != 0) {
3490 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3491 struct pack_desc* desc)
3495 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3496 buf[sizeof(buf)-1] = 0;
3500 PACKS(desc,"B9",buf); /* szName */
3502 PACKS(desc,"B21",""); /* szUserName */
3503 PACKI(desc,"W",0); /* uJobId */
3504 PACKI(desc,"W",0); /* fsStatus */
3505 PACKS(desc,"z",""); /* pszStatus */
3506 PACKI(desc,"W",0); /* time */
3510 if (uLevel == 2 || uLevel == 3) {
3511 PACKS(desc,"z",buf); /* pszPrinterName */
3513 PACKS(desc,"z",""); /* pszUserName */
3514 PACKS(desc,"z",""); /* pszLogAddr */
3515 PACKI(desc,"W",0); /* uJobId */
3516 PACKI(desc,"W",0); /* fsStatus */
3517 PACKS(desc,"z",""); /* pszStatus */
3518 PACKS(desc,"z",""); /* pszComment */
3519 PACKS(desc,"z","NULL"); /* pszDrivers */
3520 PACKI(desc,"W",0); /* time */
3521 PACKI(desc,"W",0); /* pad1 */
3526 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3527 int mdrcnt,int mprcnt,
3528 char **rdata,char **rparam,
3529 int *rdata_len,int *rparam_len)
3531 char *str1 = param+2;
3532 char *str2 = skip_string(str1,1);
3533 char *p = skip_string(str2,1);
3534 char* PrinterName = p;
3536 struct pack_desc desc;
3540 memset((char *)&desc,'\0',sizeof(desc));
3542 p = skip_string(p,1);
3545 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3547 /* check it's a supported varient */
3548 if (strcmp(str1,"zWrLh") != 0) {
3551 if (!check_printdest_info(&desc,uLevel,str2)) {
3555 snum = find_service(PrinterName);
3556 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3558 desc.errcode = NERR_DestNotFound;
3562 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3567 desc.buflen = mdrcnt;
3570 * Don't return data but need to get correct length
3571 * init_package will return wrong size if buflen=0
3573 desc.buflen = getlen(desc.format);
3574 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3576 if (init_package(&desc,1,0)) {
3577 fill_printdest_info(conn,snum,uLevel,&desc);
3579 *rdata_len = desc.usedlen;
3583 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3587 SSVALS(*rparam,0,desc.errcode);
3589 SSVAL(*rparam,4,desc.neededlen);
3591 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3597 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3598 int mdrcnt,int mprcnt,
3599 char **rdata,char **rparam,
3600 int *rdata_len,int *rparam_len)
3602 char *str1 = param+2;
3603 char *str2 = skip_string(str1,1);
3604 char *p = skip_string(str2,1);
3608 struct pack_desc desc;
3609 int services = lp_numservices();
3611 memset((char *)&desc,'\0',sizeof(desc));
3615 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3617 /* check it's a supported varient */
3618 if (strcmp(str1,"WrLeh") != 0) {
3621 if (!check_printdest_info(&desc,uLevel,str2)) {
3626 for (i = 0; i < services; i++) {
3627 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3633 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3640 desc.buflen = mdrcnt;
3641 if (init_package(&desc,queuecnt,0)) {
3644 for (i = 0; i < services; i++) {
3645 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3646 fill_printdest_info(conn,i,uLevel,&desc);
3648 if (desc.errcode == NERR_Success) {
3655 *rdata_len = desc.usedlen;
3658 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3662 SSVALS(*rparam,0,desc.errcode);
3664 SSVAL(*rparam,4,succnt);
3665 SSVAL(*rparam,6,queuecnt);
3667 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3672 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3673 int mdrcnt,int mprcnt,
3674 char **rdata,char **rparam,
3675 int *rdata_len,int *rparam_len)
3677 char *str1 = param+2;
3678 char *str2 = skip_string(str1,1);
3679 char *p = skip_string(str2,1);
3682 struct pack_desc desc;
3684 memset((char *)&desc,'\0',sizeof(desc));
3688 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3690 /* check it's a supported varient */
3691 if (strcmp(str1,"WrLeh") != 0) {
3694 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
3699 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3705 desc.buflen = mdrcnt;
3706 if (init_package(&desc,1,0)) {
3707 PACKS(&desc,"B41","NULL");
3710 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3712 *rdata_len = desc.usedlen;
3715 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3719 SSVALS(*rparam,0,desc.errcode);
3721 SSVAL(*rparam,4,succnt);
3724 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3729 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3730 int mdrcnt,int mprcnt,
3731 char **rdata,char **rparam,
3732 int *rdata_len,int *rparam_len)
3734 char *str1 = param+2;
3735 char *str2 = skip_string(str1,1);
3736 char *p = skip_string(str2,1);
3739 struct pack_desc desc;
3741 memset((char *)&desc,'\0',sizeof(desc));
3745 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3747 /* check it's a supported varient */
3748 if (strcmp(str1,"WrLeh") != 0) {
3751 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
3756 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3762 desc.buflen = mdrcnt;
3764 if (init_package(&desc,1,0)) {
3765 PACKS(&desc,"B13","lpd");
3768 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3770 *rdata_len = desc.usedlen;
3773 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3777 SSVALS(*rparam,0,desc.errcode);
3779 SSVAL(*rparam,4,succnt);
3782 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3787 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3788 int mdrcnt,int mprcnt,
3789 char **rdata,char **rparam,
3790 int *rdata_len,int *rparam_len)
3792 char *str1 = param+2;
3793 char *str2 = skip_string(str1,1);
3794 char *p = skip_string(str2,1);
3797 struct pack_desc desc;
3799 memset((char *)&desc,'\0',sizeof(desc));
3803 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3805 /* check it's a supported varient */
3806 if (strcmp(str1,"WrLeh") != 0) {
3809 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
3814 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3819 memset((char *)&desc,'\0',sizeof(desc));
3821 desc.buflen = mdrcnt;
3823 if (init_package(&desc,1,0)) {
3824 PACKS(&desc,"B13","lp0");
3827 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3829 *rdata_len = desc.usedlen;
3832 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3836 SSVALS(*rparam,0,desc.errcode);
3838 SSVAL(*rparam,4,succnt);
3841 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3847 /****************************************************************************
3849 ****************************************************************************/
3850 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3851 int mdrcnt,int mprcnt,
3852 char **rdata,char **rparam,
3853 int *rdata_len,int *rparam_len)
3856 char *str1 = param+2;
3857 char *str2 = skip_string(str1,1);
3858 char *p = skip_string(str2,1);
3860 struct pack_desc desc;
3861 struct sessionid *session_list;
3862 int i, num_sessions;
3864 memset((char *)&desc,'\0',sizeof(desc));
3868 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3869 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3870 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3872 /* check it's a supported varient */
3873 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
3876 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
3880 num_sessions = list_sessions(&session_list);
3883 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3888 memset((char *)&desc,'\0',sizeof(desc));
3890 desc.buflen = mdrcnt;
3892 if (!init_package(&desc,num_sessions,0)) {
3896 for(i=0; i<num_sessions; i++) {
3897 PACKS(&desc, "z", session_list[i].remote_machine);
3898 PACKS(&desc, "z", session_list[i].username);
3899 PACKI(&desc, "W", 1); /* num conns */
3900 PACKI(&desc, "W", 0); /* num opens */
3901 PACKI(&desc, "W", 1); /* num users */
3902 PACKI(&desc, "D", 0); /* session time */
3903 PACKI(&desc, "D", 0); /* idle time */
3904 PACKI(&desc, "D", 0); /* flags */
3905 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3908 *rdata_len = desc.usedlen;
3911 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3915 SSVALS(*rparam,0,desc.errcode);
3916 SSVAL(*rparam,2,0); /* converter */
3917 SSVAL(*rparam,4,num_sessions); /* count */
3919 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3925 /****************************************************************************
3926 The buffer was too small.
3927 ****************************************************************************/
3929 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
3930 int mdrcnt, int mprcnt,
3931 char **rdata, char **rparam,
3932 int *rdata_len, int *rparam_len)
3934 *rparam_len = MIN(*rparam_len,mprcnt);
3935 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3942 SSVAL(*rparam,0,NERR_BufTooSmall);
3944 DEBUG(3,("Supplied buffer too small in API command\n"));
3949 /****************************************************************************
3950 The request is not supported.
3951 ****************************************************************************/
3953 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
3954 int mdrcnt, int mprcnt,
3955 char **rdata, char **rparam,
3956 int *rdata_len, int *rparam_len)
3959 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3966 SSVAL(*rparam,0,NERR_notsupported);
3967 SSVAL(*rparam,2,0); /* converter word */
3969 DEBUG(3,("Unsupported API command\n"));
3974 static const struct {
3977 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3978 int,int,char **,char **,int *,int *);
3979 BOOL auth_user; /* Deny anonymous access? */
3980 } api_commands[] = {
3981 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3982 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3983 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3984 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3985 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3986 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3987 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3988 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3989 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3990 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3991 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3992 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3993 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3994 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3995 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3996 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3997 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3998 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3999 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4000 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4001 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4002 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4003 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4004 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4005 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4006 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4007 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4008 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4009 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4010 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4011 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4012 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4013 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4014 {NULL, -1, api_Unsupported}
4015 /* The following RAP calls are not implemented by Samba:
4017 RAP_WFileEnum2 - anon not OK
4022 /****************************************************************************
4023 Handle remote api calls
4024 ****************************************************************************/
4026 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4027 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4031 char *rparam = NULL;
4038 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4042 api_command = SVAL(params,0);
4044 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4047 skip_string(params+2,1),
4048 tdscnt,tpscnt,mdrcnt,mprcnt));
4050 for (i=0;api_commands[i].name;i++) {
4051 if (api_commands[i].id == api_command && api_commands[i].fn) {
4052 DEBUG(3,("Doing %s\n",api_commands[i].name));
4057 /* Check whether this api call can be done anonymously */
4059 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4060 user_struct *user = get_valid_user_struct(vuid);
4062 if (!user || user->guest) {
4063 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4067 rdata = (char *)SMB_MALLOC(1024);
4069 memset(rdata,'\0',1024);
4072 rparam = (char *)SMB_MALLOC(1024);
4074 memset(rparam,'\0',1024);
4077 if(!rdata || !rparam) {
4078 DEBUG(0,("api_reply: malloc fail !\n"));
4084 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
4085 &rdata,&rparam,&rdata_len,&rparam_len);
4088 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4089 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4090 &rdata,&rparam,&rdata_len,&rparam_len);
4093 /* if we get False back then it's actually unsupported */
4095 reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
4096 &rdata,&rparam,&rdata_len,&rparam_len);
4099 /* If api_Unsupported returns false we can't return anything. */
4101 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);