2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
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 /* Limit size of ipc replies */
55 static char *smb_realloc_limit(void *ptr, size_t size)
59 size = MAX((size),4*1024);
60 val = (char *)SMB_REALLOC(ptr,size);
62 memset(val,'\0',size);
67 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
68 char *param, int tpscnt,
69 char *data, int tdscnt,
70 int mdrcnt, int mprcnt,
71 char **rdata, char **rparam,
72 int *rdata_len, int *rparam_len);
74 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
75 int mdrcnt, int mprcnt,
76 char **rdata, char **rparam,
77 int *rdata_len, int *rparam_len);
80 static int CopyExpanded(connection_struct *conn,
81 int snum, char **dst, char *src, int *p_space_remaining)
83 TALLOC_CTX *ctx = talloc_tos();
87 if (!src || !dst || !p_space_remaining || !(*dst) ||
88 *p_space_remaining <= 0) {
92 buf = talloc_strdup(ctx, src);
94 *p_space_remaining = 0;
97 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
99 *p_space_remaining = 0;
102 buf = talloc_sub_advanced(ctx,
103 lp_servicename(SNUM(conn)),
104 conn->server_info->unix_name,
106 conn->server_info->gid,
107 get_current_username(),
108 current_user_info.domain,
111 *p_space_remaining = 0;
114 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
119 (*p_space_remaining) -= l;
123 static int CopyAndAdvance(char **dst, char *src, int *n)
126 if (!src || !dst || !n || !(*dst)) {
129 l = push_ascii(*dst,src,*n, STR_TERMINATE);
138 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
140 TALLOC_CTX *ctx = talloc_tos();
145 buf = talloc_strdup(ctx,s);
149 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
153 buf = talloc_sub_advanced(ctx,
154 lp_servicename(SNUM(conn)),
155 conn->server_info->unix_name,
157 conn->server_info->gid,
158 get_current_username(),
159 current_user_info.domain,
164 return strlen(buf) + 1;
167 static char *Expand(connection_struct *conn, int snum, char *s)
169 TALLOC_CTX *ctx = talloc_tos();
175 buf = talloc_strdup(ctx,s);
179 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
183 return talloc_sub_advanced(ctx,
184 lp_servicename(SNUM(conn)),
185 conn->server_info->unix_name,
187 conn->server_info->gid,
188 get_current_username(),
189 current_user_info.domain,
193 /*******************************************************************
194 Check a API string for validity when we only need to check the prefix.
195 ******************************************************************/
197 static bool prefix_ok(const char *str, const char *prefix)
199 return(strncmp(str,prefix,strlen(prefix)) == 0);
203 const char *format; /* formatstring for structure */
204 const char *subformat; /* subformat for structure */
205 char *base; /* baseaddress of buffer */
206 int buflen; /* remaining size for fixed part; on init: length of base */
207 int subcount; /* count of substructures */
208 char *structbuf; /* pointer into buffer for remaining fixed part */
209 int stringlen; /* remaining size for variable part */
210 char *stringbuf; /* pointer into buffer for remaining variable part */
211 int neededlen; /* total needed size */
212 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
213 const char *curpos; /* current position; pointer into format or subformat */
217 static int get_counter(const char **p)
223 if (!isdigit((int)**p)) {
229 n = 10 * n + (i - '0');
237 static int getlen(const char *p)
246 case 'W': /* word (2 byte) */
249 case 'K': /* status word? (2 byte) */
252 case 'N': /* count of substructures (word) at end */
255 case 'D': /* double word (4 byte) */
256 case 'z': /* offset to zero terminated string (4 byte) */
257 case 'l': /* offset to user data (4 byte) */
260 case 'b': /* offset to data (with counter) (4 byte) */
264 case 'B': /* byte (with optional counter) */
265 n += get_counter(&p);
272 static bool init_package(struct pack_desc *p, int count, int subcount)
277 if (!p->format || !p->base) {
281 i = count * getlen(p->format);
283 i += subcount * getlen(p->subformat);
285 p->structbuf = p->base;
289 p->curpos = p->format;
295 * This is the old error code we used. Aparently
296 * WinNT/2k systems return ERRbuftoosmall (2123) and
297 * OS/2 needs this. I'm leaving this here so we can revert
300 p->errcode = ERRmoredata;
302 p->errcode = ERRbuftoosmall;
305 p->errcode = NERR_Success;
309 p->stringbuf = p->base + i;
311 return (p->errcode == NERR_Success);
314 static int package(struct pack_desc *p, ...)
317 int needed=0, stringneeded;
318 const char *str=NULL;
319 int is_string=0, stringused;
326 p->curpos = p->format;
328 p->curpos = p->subformat;
333 str = va_arg(args,char*);
334 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
343 switch( *p->curpos++ ) {
344 case 'W': /* word (2 byte) */
346 temp = va_arg(args,int);
347 if (p->buflen >= needed) {
348 SSVAL(p->structbuf,0,temp);
351 case 'K': /* status word? (2 byte) */
353 temp = va_arg(args,int);
354 if (p->buflen >= needed) {
355 SSVAL(p->structbuf,0,temp);
358 case 'N': /* count of substructures (word) at end */
360 p->subcount = va_arg(args,int);
361 if (p->buflen >= needed) {
362 SSVAL(p->structbuf,0,p->subcount);
365 case 'D': /* double word (4 byte) */
367 temp = va_arg(args,int);
368 if (p->buflen >= needed) {
369 SIVAL(p->structbuf,0,temp);
372 case 'B': /* byte (with optional counter) */
373 needed = get_counter(&p->curpos);
375 char *s = va_arg(args,char*);
376 if (p->buflen >= needed) {
377 StrnCpy(p->structbuf,s?s:"",needed-1);
381 case 'z': /* offset to zero terminated string (4 byte) */
382 str = va_arg(args,char*);
383 stringneeded = (str ? strlen(str)+1 : 0);
386 case 'l': /* offset to user data (4 byte) */
387 str = va_arg(args,char*);
388 stringneeded = va_arg(args,int);
391 case 'b': /* offset to data (with counter) (4 byte) */
392 str = va_arg(args,char*);
393 stringneeded = get_counter(&p->curpos);
399 if (stringneeded >= 0) {
401 if (p->buflen >= needed) {
402 stringused = stringneeded;
403 if (stringused > p->stringlen) {
404 stringused = (is_string ? p->stringlen : 0);
405 if (p->errcode == NERR_Success) {
406 p->errcode = ERRmoredata;
410 SIVAL(p->structbuf,0,0);
412 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
413 memcpy(p->stringbuf,str?str:"",stringused);
415 p->stringbuf[stringused-1] = '\0';
417 p->stringbuf += stringused;
418 p->stringlen -= stringused;
419 p->usedlen += stringused;
422 p->neededlen += stringneeded;
425 p->neededlen += needed;
426 if (p->buflen >= needed) {
427 p->structbuf += needed;
429 p->usedlen += needed;
431 if (p->errcode == NERR_Success) {
432 p->errcode = ERRmoredata;
439 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
440 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
442 #define PACK(desc,t,v) package(desc,v)
443 #define PACKl(desc,t,v,l) package(desc,v,l)
446 static void PACKI(struct pack_desc* desc, const char *t,int v)
451 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
456 /****************************************************************************
458 ****************************************************************************/
460 static void PackDriverData(struct pack_desc* desc)
462 char drivdata[4+4+32];
463 SIVAL(drivdata,0,sizeof drivdata); /* cb */
464 SIVAL(drivdata,4,1000); /* lVersion */
465 memset(drivdata+8,0,32); /* szDeviceName */
466 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
467 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
470 static int check_printq_info(struct pack_desc* desc,
471 unsigned int uLevel, char *id1, char *id2)
473 desc->subformat = NULL;
476 desc->format = "B13";
479 desc->format = "B13BWWWzzzzzWW";
482 desc->format = "B13BWWWzzzzzWN";
483 desc->subformat = "WB21BB16B10zWWzDDz";
486 desc->format = "zWWWWzzzzWWzzl";
489 desc->format = "zWWWWzzzzWNzzl";
490 desc->subformat = "WWzWWDDzz";
499 desc->format = "WzzzzzzzzN";
500 desc->subformat = "z";
503 DEBUG(0,("check_printq_info: invalid level %d\n",
507 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
508 DEBUG(0,("check_printq_info: invalid format %s\n",
509 id1 ? id1 : "<NULL>" ));
512 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
513 DEBUG(0,("check_printq_info: invalid subformat %s\n",
514 id2 ? id2 : "<NULL>" ));
521 #define RAP_JOB_STATUS_QUEUED 0
522 #define RAP_JOB_STATUS_PAUSED 1
523 #define RAP_JOB_STATUS_SPOOLING 2
524 #define RAP_JOB_STATUS_PRINTING 3
525 #define RAP_JOB_STATUS_PRINTED 4
527 #define RAP_QUEUE_STATUS_PAUSED 1
528 #define RAP_QUEUE_STATUS_ERROR 2
530 /* turn a print job status into a on the wire status
532 static int printj_status(int v)
536 return RAP_JOB_STATUS_QUEUED;
538 return RAP_JOB_STATUS_PAUSED;
540 return RAP_JOB_STATUS_SPOOLING;
542 return RAP_JOB_STATUS_PRINTING;
547 /* turn a print queue status into a on the wire status
549 static int printq_status(int v)
555 return RAP_QUEUE_STATUS_PAUSED;
557 return RAP_QUEUE_STATUS_ERROR;
560 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
561 struct pack_desc *desc,
562 print_queue_struct *queue, int n)
564 time_t t = queue->time;
566 /* the client expects localtime */
567 t -= get_time_zone(t);
569 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
571 PACKS(desc,"B21",queue->fs_user); /* szUserName */
572 PACKS(desc,"B",""); /* pad */
573 PACKS(desc,"B16",""); /* szNotifyName */
574 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
575 PACKS(desc,"z",""); /* pszParms */
576 PACKI(desc,"W",n+1); /* uPosition */
577 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
578 PACKS(desc,"z",""); /* pszStatus */
579 PACKI(desc,"D",t); /* ulSubmitted */
580 PACKI(desc,"D",queue->size); /* ulSize */
581 PACKS(desc,"z",queue->fs_file); /* pszComment */
583 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
584 PACKI(desc,"W",queue->priority); /* uPriority */
585 PACKS(desc,"z",queue->fs_user); /* pszUserName */
586 PACKI(desc,"W",n+1); /* uPosition */
587 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
588 PACKI(desc,"D",t); /* ulSubmitted */
589 PACKI(desc,"D",queue->size); /* ulSize */
590 PACKS(desc,"z","Samba"); /* pszComment */
591 PACKS(desc,"z",queue->fs_file); /* pszDocument */
593 PACKS(desc,"z",""); /* pszNotifyName */
594 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
595 PACKS(desc,"z",""); /* pszParms */
596 PACKS(desc,"z",""); /* pszStatus */
597 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
598 PACKS(desc,"z","lpd"); /* pszQProcName */
599 PACKS(desc,"z",""); /* pszQProcParms */
600 PACKS(desc,"z","NULL"); /* pszDriverName */
601 PackDriverData(desc); /* pDriverData */
602 PACKS(desc,"z",""); /* pszPrinterName */
603 } else if (uLevel == 4) { /* OS2 */
604 PACKS(desc,"z",""); /* pszSpoolFileName */
605 PACKS(desc,"z",""); /* pszPortName */
606 PACKS(desc,"z",""); /* pszStatus */
607 PACKI(desc,"D",0); /* ulPagesSpooled */
608 PACKI(desc,"D",0); /* ulPagesSent */
609 PACKI(desc,"D",0); /* ulPagesPrinted */
610 PACKI(desc,"D",0); /* ulTimePrinted */
611 PACKI(desc,"D",0); /* ulExtendJobStatus */
612 PACKI(desc,"D",0); /* ulStartPage */
613 PACKI(desc,"D",0); /* ulEndPage */
618 /********************************************************************
619 Return a driver name given an snum.
620 Returns True if from tdb, False otherwise.
621 ********************************************************************/
623 static bool get_driver_name(int snum, char **pp_drivername)
625 NT_PRINTER_INFO_LEVEL *info = NULL;
628 get_a_printer (NULL, &info, 2, lp_servicename(snum));
630 *pp_drivername = talloc_strdup(talloc_tos(),
631 info->info_2->drivername);
633 free_a_printer(&info, 2);
634 if (!*pp_drivername) {
642 /********************************************************************
643 Respond to the DosPrintQInfo command with a level of 52
644 This is used to get printer driver information for Win9x clients
645 ********************************************************************/
646 static void fill_printq_info_52(connection_struct *conn, int snum,
647 struct pack_desc* desc, int count )
651 NT_PRINTER_DRIVER_INFO_LEVEL driver;
652 NT_PRINTER_INFO_LEVEL *printer = NULL;
656 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
657 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
658 lp_servicename(snum)));
662 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
665 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
666 printer->info_2->drivername));
670 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
671 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
672 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
674 PACKI(desc, "W", 0x0400); /* don't know */
675 PACKS(desc, "z", driver.info_3->name); /* long printer name */
676 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
677 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
678 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
680 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
681 standard_sub_basic( "", "", location, sizeof(location)-1 );
682 PACKS(desc,"z", location); /* share to retrieve files */
684 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
685 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
686 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
688 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
689 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
690 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
691 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
692 DEBUG(3,("Driver Location: %s:\n",location));
693 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
694 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
695 PACKI(desc,"N",count); /* number of files to copy */
697 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
699 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
700 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
701 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
706 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
709 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
711 desc->errcode=NERR_Success;
715 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
716 desc->errcode=NERR_notsupported;
720 free_a_printer( &printer, 2 );
723 free_a_printer_driver( driver, 3 );
727 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
728 struct pack_desc* desc,
729 int count, print_queue_struct* queue,
730 print_status_struct* status)
735 PACKS(desc,"B13",SERVICE(snum));
740 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
743 PACKI(desc,"K",printq_status(status->status));
747 if (uLevel == 1 || uLevel == 2) {
748 PACKS(desc,"B",""); /* alignment */
749 PACKI(desc,"W",5); /* priority */
750 PACKI(desc,"W",0); /* start time */
751 PACKI(desc,"W",0); /* until time */
752 PACKS(desc,"z",""); /* pSepFile */
753 PACKS(desc,"z","lpd"); /* pPrProc */
754 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
755 PACKS(desc,"z",""); /* pParms */
757 PACKS(desc,"z","UNKNOWN PRINTER");
758 PACKI(desc,"W",LPSTAT_ERROR);
760 else if (!status || !status->message[0]) {
761 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
762 PACKI(desc,"W",LPSTAT_OK); /* status */
764 PACKS(desc,"z",status->message);
765 PACKI(desc,"W",printq_status(status->status)); /* status */
767 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
770 if (uLevel == 3 || uLevel == 4) {
771 char *drivername = NULL;
773 PACKI(desc,"W",5); /* uPriority */
774 PACKI(desc,"W",0); /* uStarttime */
775 PACKI(desc,"W",0); /* uUntiltime */
776 PACKI(desc,"W",5); /* pad1 */
777 PACKS(desc,"z",""); /* pszSepFile */
778 PACKS(desc,"z","WinPrint"); /* pszPrProc */
779 PACKS(desc,"z",NULL); /* pszParms */
780 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
781 /* "don't ask" that it's done this way to fix corrupted
782 Win9X/ME printer comments. */
784 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
786 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
788 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
789 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
790 get_driver_name(snum,&drivername);
794 PACKS(desc,"z",drivername); /* pszDriverName */
795 PackDriverData(desc); /* pDriverData */
798 if (uLevel == 2 || uLevel == 4) {
800 for (i=0;i<count;i++)
801 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
805 fill_printq_info_52( conn, snum, desc, count );
808 /* This function returns the number of files for a given driver */
809 static int get_printerdrivernumber(int snum)
812 NT_PRINTER_DRIVER_INFO_LEVEL driver;
813 NT_PRINTER_INFO_LEVEL *printer = NULL;
817 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
818 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
819 lp_servicename(snum)));
823 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
826 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
827 printer->info_2->drivername));
831 /* count the number of files */
832 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
837 free_a_printer( &printer, 2 );
840 free_a_printer_driver( driver, 3 );
845 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
846 char *param, int tpscnt,
847 char *data, int tdscnt,
848 int mdrcnt,int mprcnt,
849 char **rdata,char **rparam,
850 int *rdata_len,int *rparam_len)
852 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
853 char *str2 = skip_string(param,tpscnt,str1);
854 char *p = skip_string(param,tpscnt,str2);
860 struct pack_desc desc;
861 print_queue_struct *queue=NULL;
862 print_status_struct status;
865 if (!str1 || !str2 || !p) {
868 memset((char *)&status,'\0',sizeof(status));
869 memset((char *)&desc,'\0',sizeof(desc));
871 p = skip_string(param,tpscnt,p);
875 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
876 str3 = get_safe_str_ptr(param,tpscnt,p,4);
877 /* str3 may be null here and is checked in check_printq_info(). */
879 /* remove any trailing username */
880 if ((p = strchr_m(QueueName,'%')))
883 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
885 /* check it's a supported varient */
886 if (!prefix_ok(str1,"zWrLh"))
888 if (!check_printq_info(&desc,uLevel,str2,str3)) {
890 * Patch from Scott Moomaw <scott@bridgewater.edu>
891 * to return the 'invalid info level' error if an
892 * unknown level was requested.
896 *rparam = smb_realloc_limit(*rparam,*rparam_len);
900 SSVALS(*rparam,0,ERRunknownlevel);
906 snum = find_service(QueueName);
907 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
911 count = get_printerdrivernumber(snum);
912 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
914 count = print_queue_status(snum, &queue,&status);
918 *rdata = smb_realloc_limit(*rdata,mdrcnt);
924 desc.buflen = mdrcnt;
927 * Don't return data but need to get correct length
928 * init_package will return wrong size if buflen=0
930 desc.buflen = getlen(desc.format);
931 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
934 if (init_package(&desc,1,count)) {
935 desc.subcount = count;
936 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
939 *rdata_len = desc.usedlen;
942 * We must set the return code to ERRbuftoosmall
943 * in order to support lanman style printing with Win NT/2k
946 if (!mdrcnt && lp_disable_spoolss())
947 desc.errcode = ERRbuftoosmall;
949 *rdata_len = desc.usedlen;
951 *rparam = smb_realloc_limit(*rparam,*rparam_len);
957 SSVALS(*rparam,0,desc.errcode);
959 SSVAL(*rparam,4,desc.neededlen);
961 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
969 /****************************************************************************
970 View list of all print jobs on all queues.
971 ****************************************************************************/
973 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
974 char *param, int tpscnt,
975 char *data, int tdscnt,
976 int mdrcnt, int mprcnt,
977 char **rdata, char** rparam,
978 int *rdata_len, int *rparam_len)
980 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
981 char *output_format1 = skip_string(param,tpscnt,param_format);
982 char *p = skip_string(param,tpscnt,output_format1);
983 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
984 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
985 int services = lp_numservices();
987 struct pack_desc desc;
988 print_queue_struct **queue = NULL;
989 print_status_struct *status = NULL;
990 int *subcntarr = NULL;
991 int queuecnt = 0, subcnt = 0, succnt = 0;
993 if (!param_format || !output_format1 || !p) {
997 memset((char *)&desc,'\0',sizeof(desc));
999 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
1001 if (!prefix_ok(param_format,"WrLeh")) {
1004 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1006 * Patch from Scott Moomaw <scott@bridgewater.edu>
1007 * to return the 'invalid info level' error if an
1008 * unknown level was requested.
1012 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1016 SSVALS(*rparam,0,ERRunknownlevel);
1022 for (i = 0; i < services; i++) {
1023 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1028 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1029 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1032 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1033 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1034 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1037 memset(status,0,queuecnt*sizeof(print_status_struct));
1038 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1039 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1045 for (i = 0; i < services; i++) {
1046 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1047 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1048 subcnt += subcntarr[n];
1054 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1060 desc.buflen = mdrcnt;
1062 if (init_package(&desc,queuecnt,subcnt)) {
1065 for (i = 0; i < services; i++) {
1066 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1067 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1069 if (desc.errcode == NERR_Success) {
1076 SAFE_FREE(subcntarr);
1078 *rdata_len = desc.usedlen;
1080 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1084 SSVALS(*rparam,0,desc.errcode);
1086 SSVAL(*rparam,4,succnt);
1087 SSVAL(*rparam,6,queuecnt);
1089 for (i = 0; i < queuecnt; i++) {
1091 SAFE_FREE(queue[i]);
1102 SAFE_FREE(subcntarr);
1103 for (i = 0; i < queuecnt; i++) {
1105 SAFE_FREE(queue[i]);
1114 /****************************************************************************
1115 Get info level for a server list query.
1116 ****************************************************************************/
1118 static bool check_server_info(int uLevel, char* id)
1122 if (strcmp(id,"B16") != 0) {
1127 if (strcmp(id,"B16BBDz") != 0) {
1137 struct srv_info_struct {
1145 /*******************************************************************
1146 Get server info lists from the files saved by nmbd. Return the
1148 ******************************************************************/
1150 static int get_server_info(uint32 servertype,
1151 struct srv_info_struct **servers,
1157 bool local_list_only;
1160 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1162 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1166 /* request for everything is code for request all servers */
1167 if (servertype == SV_TYPE_ALL) {
1168 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1171 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1173 DEBUG(4,("Servertype search: %8x\n",servertype));
1175 for (i=0;lines[i];i++) {
1177 struct srv_info_struct *s;
1178 const char *ptr = lines[i];
1180 TALLOC_CTX *frame = NULL;
1187 if (count == alloced) {
1189 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1191 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1192 file_lines_free(lines);
1195 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1197 s = &(*servers)[count];
1199 frame = talloc_stackframe();
1201 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1205 fstrcpy(s->name, p);
1208 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1214 s->comment[0] = '\0';
1215 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1219 fstrcpy(s->comment, p);
1221 s->domain[0] = '\0';
1222 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1223 /* this allows us to cope with an old nmbd */
1224 fstrcpy(s->domain,lp_workgroup());
1226 fstrcpy(s->domain, p);
1230 if (sscanf(stype,"%X",&s->type) != 1) {
1231 DEBUG(4,("r:host file "));
1235 /* Filter the servers/domains we return based on what was asked for. */
1237 /* Check to see if we are being asked for a local list only. */
1238 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1239 DEBUG(4,("r: local list only"));
1243 /* doesn't match up: don't want it */
1244 if (!(servertype & s->type)) {
1245 DEBUG(4,("r:serv type "));
1249 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1250 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1251 DEBUG(4,("s: dom mismatch "));
1255 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1259 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1260 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1263 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1264 s->name, s->type, s->comment, s->domain));
1265 s->server_added = True;
1268 DEBUG(4,("%20s %8x %25s %15s\n",
1269 s->name, s->type, s->comment, s->domain));
1273 file_lines_free(lines);
1277 /*******************************************************************
1278 Fill in a server info structure.
1279 ******************************************************************/
1281 static int fill_srv_info(struct srv_info_struct *service,
1282 int uLevel, char **buf, int *buflen,
1283 char **stringbuf, int *stringspace, char *baseaddr)
1306 len = strlen(service->comment)+1;
1310 *buflen = struct_len;
1312 return struct_len + len;
1317 if (*buflen < struct_len) {
1324 p2 = p + struct_len;
1325 l2 = *buflen - struct_len;
1333 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1337 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1338 SIVAL(p,18,service->type);
1339 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1340 len += CopyAndAdvance(&p2,service->comment,&l2);
1345 *buf = p + struct_len;
1346 *buflen -= struct_len;
1357 static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1359 return(strcmp(s1->name,s2->name));
1362 /****************************************************************************
1363 View list of servers available (or possibly domains). The info is
1364 extracted from lists saved by nmbd on the local host.
1365 ****************************************************************************/
1367 static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1368 char *param, int tpscnt,
1369 char *data, int tdscnt,
1370 int mdrcnt, int mprcnt, char **rdata,
1371 char **rparam, int *rdata_len, int *rparam_len)
1373 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1374 char *str2 = skip_string(param,tpscnt,str1);
1375 char *p = skip_string(param,tpscnt,str2);
1376 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1377 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1378 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1380 int data_len, fixed_len, string_len;
1381 int f_len = 0, s_len = 0;
1382 struct srv_info_struct *servers=NULL;
1383 int counted=0,total=0;
1386 bool domain_request;
1389 if (!str1 || !str2 || !p) {
1393 /* If someone sets all the bits they don't really mean to set
1394 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1397 if (servertype == SV_TYPE_ALL) {
1398 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1401 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1402 any other bit (they may just set this bit on its own) they
1403 want all the locally seen servers. However this bit can be
1404 set on its own so set the requested servers to be
1405 ALL - DOMAIN_ENUM. */
1407 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1408 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1411 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1412 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1416 if (!prefix_ok(str1,"WrLehD")) {
1419 if (!check_server_info(uLevel,str2)) {
1423 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1424 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1425 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1427 if (strcmp(str1, "WrLehDz") == 0) {
1428 if (skip_string(param,tpscnt,p) == NULL) {
1431 pull_ascii_fstring(domain, p);
1433 fstrcpy(domain, lp_workgroup());
1436 if (lp_browse_list()) {
1437 total = get_server_info(servertype,&servers,domain);
1440 data_len = fixed_len = string_len = 0;
1444 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1448 char *lastname=NULL;
1450 for (i=0;i<total;i++) {
1451 struct srv_info_struct *s = &servers[i];
1453 if (lastname && strequal(lastname,s->name)) {
1457 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1458 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1459 s->name, s->type, s->comment, s->domain));
1461 if (data_len <= buf_len) {
1464 string_len += s_len;
1471 *rdata_len = fixed_len + string_len;
1472 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1477 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1483 char *lastname=NULL;
1484 int count2 = counted;
1486 for (i = 0; i < total && count2;i++) {
1487 struct srv_info_struct *s = &servers[i];
1489 if (lastname && strequal(lastname,s->name)) {
1493 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1494 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1495 s->name, s->type, s->comment, s->domain));
1501 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1505 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1507 SSVAL(*rparam,4,counted);
1508 SSVAL(*rparam,6,counted+missed);
1512 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1513 domain,uLevel,counted,counted+missed));
1518 /****************************************************************************
1519 command 0x34 - suspected of being a "Lookup Names" stub api
1520 ****************************************************************************/
1522 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1523 char *param, int tpscnt,
1524 char *data, int tdscnt,
1525 int mdrcnt, int mprcnt, char **rdata,
1526 char **rparam, int *rdata_len, int *rparam_len)
1528 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1529 char *str2 = skip_string(param,tpscnt,str1);
1530 char *p = skip_string(param,tpscnt,str2);
1531 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1532 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1536 if (!str1 || !str2 || !p) {
1540 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1541 str1, str2, p, uLevel, buf_len));
1543 if (!prefix_ok(str1,"zWrLeh")) {
1550 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1555 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1557 SSVAL(*rparam,4,counted);
1558 SSVAL(*rparam,6,counted+missed);
1563 /****************************************************************************
1564 get info about a share
1565 ****************************************************************************/
1567 static bool check_share_info(int uLevel, char* id)
1571 if (strcmp(id,"B13") != 0) {
1576 if (strcmp(id,"B13BWz") != 0) {
1581 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1586 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1596 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1597 char** buf, int* buflen,
1598 char** stringbuf, int* stringspace, char* baseaddr)
1628 len += StrlenExpanded(conn,snum,lp_comment(snum));
1631 len += strlen(lp_pathname(snum)) + 1;
1634 *buflen = struct_len;
1639 return struct_len + len;
1644 if ((*buflen) < struct_len) {
1652 p2 = p + struct_len;
1653 l2 = (*buflen) - struct_len;
1660 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1666 type = STYPE_DISKTREE;
1667 if (lp_print_ok(snum)) {
1668 type = STYPE_PRINTQ;
1670 if (strequal("IPC",lp_fstype(snum))) {
1673 SSVAL(p,14,type); /* device type */
1674 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1675 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1679 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1680 SSVALS(p,22,-1); /* max uses */
1681 SSVAL(p,24,1); /* current uses */
1682 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1683 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1684 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1688 memset(p+40,0,SHPWLEN+2);
1699 (*buf) = p + struct_len;
1700 (*buflen) -= struct_len;
1702 (*stringspace) = l2;
1711 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1712 char *param, int tpscnt,
1713 char *data, int tdscnt,
1714 int mdrcnt,int mprcnt,
1715 char **rdata,char **rparam,
1716 int *rdata_len,int *rparam_len)
1718 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1719 char *str2 = skip_string(param,tpscnt,str1);
1720 char *netname = skip_string(param,tpscnt,str2);
1721 char *p = skip_string(param,tpscnt,netname);
1722 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1725 if (!str1 || !str2 || !netname || !p) {
1729 snum = find_service(netname);
1734 /* check it's a supported varient */
1735 if (!prefix_ok(str1,"zWrLh")) {
1738 if (!check_share_info(uLevel,str2)) {
1742 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1747 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1748 if (*rdata_len < 0) {
1753 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1757 SSVAL(*rparam,0,NERR_Success);
1758 SSVAL(*rparam,2,0); /* converter word */
1759 SSVAL(*rparam,4,*rdata_len);
1764 /****************************************************************************
1765 View the list of available shares.
1767 This function is the server side of the NetShareEnum() RAP call.
1768 It fills the return buffer with share names and share comments.
1769 Note that the return buffer normally (in all known cases) allows only
1770 twelve byte strings for share names (plus one for a nul terminator).
1771 Share names longer than 12 bytes must be skipped.
1772 ****************************************************************************/
1774 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1775 char *param, int tpscnt,
1776 char *data, int tdscnt,
1784 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1785 char *str2 = skip_string(param,tpscnt,str1);
1786 char *p = skip_string(param,tpscnt,str2);
1787 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1788 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1791 int total=0,counted=0;
1792 bool missed = False;
1794 int data_len, fixed_len, string_len;
1795 int f_len = 0, s_len = 0;
1797 if (!str1 || !str2 || !p) {
1801 if (!prefix_ok(str1,"WrLeh")) {
1804 if (!check_share_info(uLevel,str2)) {
1808 /* Ensure all the usershares are loaded. */
1810 load_registry_shares();
1811 count = load_usershare_shares();
1814 data_len = fixed_len = string_len = 0;
1815 for (i=0;i<count;i++) {
1816 fstring servicename_dos;
1817 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1820 push_ascii_fstring(servicename_dos, lp_servicename(i));
1821 /* Maximum name length = 13. */
1822 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1824 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1825 if (data_len <= buf_len) {
1828 string_len += s_len;
1835 *rdata_len = fixed_len + string_len;
1836 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1841 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1846 for( i = 0; i < count; i++ ) {
1847 fstring servicename_dos;
1848 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1852 push_ascii_fstring(servicename_dos, lp_servicename(i));
1853 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1854 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1861 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1865 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1867 SSVAL(*rparam,4,counted);
1868 SSVAL(*rparam,6,total);
1870 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1871 counted,total,uLevel,
1872 buf_len,*rdata_len,mdrcnt));
1877 /****************************************************************************
1879 ****************************************************************************/
1881 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1882 char *param, int tpscnt,
1883 char *data, int tdscnt,
1884 int mdrcnt,int mprcnt,
1885 char **rdata,char **rparam,
1886 int *rdata_len,int *rparam_len)
1888 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1889 char *str2 = skip_string(param,tpscnt,str1);
1890 char *p = skip_string(param,tpscnt,str2);
1891 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1894 char *pathname = NULL;
1895 char *command, *cmdname;
1896 unsigned int offset;
1899 size_t converted_size;
1901 if (!str1 || !str2 || !p) {
1905 /* check it's a supported varient */
1906 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1909 if (!check_share_info(uLevel,str2)) {
1916 /* Do we have a string ? */
1917 if (skip_string(data,mdrcnt,data) == NULL) {
1920 pull_ascii_fstring(sharename,data);
1921 snum = find_service(sharename);
1922 if (snum >= 0) { /* already exists */
1931 /* only support disk share adds */
1932 if (SVAL(data,14)!=STYPE_DISKTREE) {
1936 offset = IVAL(data, 16);
1937 if (offset >= mdrcnt) {
1938 res = ERRinvalidparam;
1942 /* Do we have a string ? */
1943 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1946 pull_ascii_fstring(comment, offset? (data+offset) : "");
1948 offset = IVAL(data, 26);
1950 if (offset >= mdrcnt) {
1951 res = ERRinvalidparam;
1955 /* Do we have a string ? */
1956 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1960 if (!pull_ascii_talloc(talloc_tos(), &pathname,
1961 offset ? (data+offset) : "", &converted_size))
1963 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1971 string_replace(sharename, '"', ' ');
1972 string_replace(pathname, '"', ' ');
1973 string_replace(comment, '"', ' ');
1975 cmdname = lp_add_share_cmd();
1977 if (!cmdname || *cmdname == '\0') {
1981 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1982 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
1983 pathname, comment) == -1) {
1987 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1989 if ((res = smbrun(command, NULL)) != 0) {
1990 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1997 message_send_all(smbd_messaging_context(),
1998 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
2002 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2006 SSVAL(*rparam,0,NERR_Success);
2007 SSVAL(*rparam,2,0); /* converter word */
2008 SSVAL(*rparam,4,*rdata_len);
2016 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2021 SSVAL(*rparam,0,res);
2026 /****************************************************************************
2027 view list of groups available
2028 ****************************************************************************/
2030 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2031 char *param, int tpscnt,
2032 char *data, int tdscnt,
2033 int mdrcnt,int mprcnt,
2034 char **rdata,char **rparam,
2035 int *rdata_len,int *rparam_len)
2039 int resume_context, cli_buf_size;
2040 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2041 char *str2 = skip_string(param,tpscnt,str1);
2042 char *p = skip_string(param,tpscnt,str2);
2044 struct pdb_search *search;
2045 struct samr_displayentry *entries;
2049 if (!str1 || !str2 || !p) {
2053 if (strcmp(str1,"WrLeh") != 0) {
2058 * W-> resume context (number of users to skip)
2059 * r -> return parameter pointer to receive buffer
2060 * L -> length of receive buffer
2061 * e -> return parameter number of entries
2062 * h -> return parameter total number of users
2065 if (strcmp("B21",str2) != 0) {
2069 /* get list of domain groups SID_DOMAIN_GRP=2 */
2071 search = pdb_search_groups();
2074 if (search == NULL) {
2075 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
2079 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2080 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2081 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2082 "%d\n", resume_context, cli_buf_size));
2085 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
2089 *rdata_len = cli_buf_size;
2090 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2097 for(i=0; i<num_entries; i++) {
2099 fstrcpy(name, entries[i].account_name);
2100 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2101 /* truncate the name at 21 chars. */
2102 memcpy(p, name, 21);
2103 DEBUG(10,("adding entry %d group %s\n", i, p));
2105 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2108 /* set overflow error */
2109 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2115 pdb_search_destroy(search);
2117 *rdata_len = PTR_DIFF(p,*rdata);
2120 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2124 SSVAL(*rparam, 0, errflags);
2125 SSVAL(*rparam, 2, 0); /* converter word */
2126 SSVAL(*rparam, 4, i); /* is this right?? */
2127 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2132 /*******************************************************************
2133 Get groups that a user is a member of.
2134 ******************************************************************/
2136 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2137 char *param, int tpscnt,
2138 char *data, int tdscnt,
2139 int mdrcnt,int mprcnt,
2140 char **rdata,char **rparam,
2141 int *rdata_len,int *rparam_len)
2143 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2144 char *str2 = skip_string(param,tpscnt,str1);
2145 char *UserName = skip_string(param,tpscnt,str2);
2146 char *p = skip_string(param,tpscnt,UserName);
2147 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2148 const char *level_string;
2150 struct samu *sampw = NULL;
2158 enum lsa_SidType type;
2160 TALLOC_CTX *mem_ctx;
2162 if (!str1 || !str2 || !UserName || !p) {
2167 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2172 /* check it's a supported varient */
2174 if ( strcmp(str1,"zWrLeh") != 0 )
2179 level_string = "B21";
2185 if (strcmp(level_string,str2) != 0)
2188 *rdata_len = mdrcnt + 1024;
2189 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2194 SSVAL(*rparam,0,NERR_Success);
2195 SSVAL(*rparam,2,0); /* converter word */
2198 endp = *rdata + *rdata_len;
2200 mem_ctx = talloc_new(NULL);
2201 if (mem_ctx == NULL) {
2202 DEBUG(0, ("talloc_new failed\n"));
2206 if ( !(sampw = samu_new(mem_ctx)) ) {
2207 DEBUG(0, ("samu_new() failed!\n"));
2208 TALLOC_FREE(mem_ctx);
2212 /* Lookup the user information; This should only be one of
2213 our accounts (not remote domains) */
2215 become_root(); /* ROOT BLOCK */
2217 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2218 NULL, NULL, &user_sid, &type)) {
2219 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2223 if (type != SID_NAME_USER) {
2224 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2225 sid_type_lookup(type)));
2229 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2230 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2231 sid_string_dbg(&user_sid), UserName));
2239 result = pdb_enum_group_memberships(mem_ctx, sampw,
2240 &sids, &gids, &num_groups);
2242 if (!NT_STATUS_IS_OK(result)) {
2243 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2248 for (i=0; i<num_groups; i++) {
2249 const char *grp_name;
2251 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2252 strlcpy(p, grp_name, PTR_DIFF(endp,p));
2258 *rdata_len = PTR_DIFF(p,*rdata);
2260 SSVAL(*rparam,4,count); /* is this right?? */
2261 SSVAL(*rparam,6,count); /* is this right?? */
2266 unbecome_root(); /* END ROOT BLOCK */
2268 TALLOC_FREE(mem_ctx);
2273 /*******************************************************************
2275 ******************************************************************/
2277 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2278 char *param, int tpscnt,
2279 char *data, int tdscnt,
2280 int mdrcnt,int mprcnt,
2281 char **rdata,char **rparam,
2282 int *rdata_len,int *rparam_len)
2287 int i, resume_context, cli_buf_size;
2288 struct pdb_search *search;
2289 struct samr_displayentry *users;
2291 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2292 char *str2 = skip_string(param,tpscnt,str1);
2293 char *p = skip_string(param,tpscnt,str2);
2296 if (!str1 || !str2 || !p) {
2300 if (strcmp(str1,"WrLeh") != 0)
2303 * W-> resume context (number of users to skip)
2304 * r -> return parameter pointer to receive buffer
2305 * L -> length of receive buffer
2306 * e -> return parameter number of entries
2307 * h -> return parameter total number of users
2310 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2311 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2312 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2313 resume_context, cli_buf_size));
2316 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2321 /* check it's a supported varient */
2322 if (strcmp("B21",str2) != 0)
2325 *rdata_len = cli_buf_size;
2326 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2332 endp = *rdata + *rdata_len;
2335 search = pdb_search_users(ACB_NORMAL);
2337 if (search == NULL) {
2338 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2343 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2347 errflags=NERR_Success;
2349 for (i=0; i<num_users; i++) {
2350 const char *name = users[i].account_name;
2352 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2353 strlcpy(p,name,PTR_DIFF(endp,p));
2354 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2355 "%s\n",count_sent,p));
2359 /* set overflow error */
2360 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2361 "username %s\n",count_sent,name));
2367 pdb_search_destroy(search);
2369 *rdata_len = PTR_DIFF(p,*rdata);
2371 SSVAL(*rparam,0,errflags);
2372 SSVAL(*rparam,2,0); /* converter word */
2373 SSVAL(*rparam,4,count_sent); /* is this right?? */
2374 SSVAL(*rparam,6,num_users); /* is this right?? */
2379 /****************************************************************************
2380 Get the time of day info.
2381 ****************************************************************************/
2383 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2384 char *param, int tpscnt,
2385 char *data, int tdscnt,
2386 int mdrcnt,int mprcnt,
2387 char **rdata,char **rparam,
2388 int *rdata_len,int *rparam_len)
2391 time_t unixdate = time(NULL);
2395 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2401 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2406 SSVAL(*rparam,0,NERR_Success);
2407 SSVAL(*rparam,2,0); /* converter word */
2411 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2412 by NT in a "net time" operation,
2413 it seems to ignore the one below */
2415 /* the client expects to get localtime, not GMT, in this bit
2416 (I think, this needs testing) */
2417 t = localtime(&unixdate);
2422 SIVAL(p,4,0); /* msecs ? */
2423 SCVAL(p,8,t->tm_hour);
2424 SCVAL(p,9,t->tm_min);
2425 SCVAL(p,10,t->tm_sec);
2426 SCVAL(p,11,0); /* hundredths of seconds */
2427 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2428 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2429 SCVAL(p,16,t->tm_mday);
2430 SCVAL(p,17,t->tm_mon + 1);
2431 SSVAL(p,18,1900+t->tm_year);
2432 SCVAL(p,20,t->tm_wday);
2437 /****************************************************************************
2438 Set the user password.
2439 *****************************************************************************/
2441 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2442 char *param, int tpscnt,
2443 char *data, int tdscnt,
2444 int mdrcnt,int mprcnt,
2445 char **rdata,char **rparam,
2446 int *rdata_len,int *rparam_len)
2448 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2451 fstring pass1,pass2;
2453 /* Skip 2 strings. */
2454 p = skip_string(param,tpscnt,np);
2455 p = skip_string(param,tpscnt,p);
2461 /* Do we have a string ? */
2462 if (skip_string(param,tpscnt,p) == NULL) {
2465 pull_ascii_fstring(user,p);
2467 p = skip_string(param,tpscnt,p);
2472 memset(pass1,'\0',sizeof(pass1));
2473 memset(pass2,'\0',sizeof(pass2));
2475 * We use 31 here not 32 as we're checking
2476 * the last byte we want to access is safe.
2478 if (!is_offset_safe(param,tpscnt,p,31)) {
2482 memcpy(pass2,p+16,16);
2485 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2492 SSVAL(*rparam,0,NERR_badpass);
2493 SSVAL(*rparam,2,0); /* converter word */
2495 DEBUG(3,("Set password for <%s>\n",user));
2498 * Attempt to verify the old password against smbpasswd entries
2499 * Win98 clients send old and new password in plaintext for this call.
2503 auth_serversupplied_info *server_info = NULL;
2504 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2506 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2509 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2510 SSVAL(*rparam,0,NERR_Success);
2514 TALLOC_FREE(server_info);
2516 data_blob_clear_free(&password);
2520 * If the plaintext change failed, attempt
2521 * the old encrypted method. NT will generate this
2522 * after trying the samr method. Note that this
2523 * method is done as a last resort as this
2524 * password change method loses the NT password hash
2525 * and cannot change the UNIX password as no plaintext
2529 if(SVAL(*rparam,0) != NERR_Success) {
2530 struct samu *hnd = NULL;
2532 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2534 if (change_lanman_password(hnd,(uchar *)pass2)) {
2535 SSVAL(*rparam,0,NERR_Success);
2542 memset((char *)pass1,'\0',sizeof(fstring));
2543 memset((char *)pass2,'\0',sizeof(fstring));
2548 /****************************************************************************
2549 Set the user password (SamOEM version - gets plaintext).
2550 ****************************************************************************/
2552 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2553 char *param, int tpscnt,
2554 char *data, int tdscnt,
2555 int mdrcnt,int mprcnt,
2556 char **rdata,char **rparam,
2557 int *rdata_len,int *rparam_len)
2560 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2562 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2572 SSVAL(*rparam,0,NERR_badpass);
2575 * Check the parameter definition is correct.
2578 /* Do we have a string ? */
2579 if (skip_string(param,tpscnt,p) == 0) {
2582 if(!strequal(p, "zsT")) {
2583 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2586 p = skip_string(param, tpscnt, p);
2591 /* Do we have a string ? */
2592 if (skip_string(param,tpscnt,p) == 0) {
2595 if(!strequal(p, "B516B16")) {
2596 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2599 p = skip_string(param,tpscnt,p);
2603 /* Do we have a string ? */
2604 if (skip_string(param,tpscnt,p) == 0) {
2607 p += pull_ascii_fstring(user,p);
2609 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2612 * Pass the user through the NT -> unix user mapping
2616 (void)map_username(user);
2618 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2619 SSVAL(*rparam,0,NERR_Success);
2625 /****************************************************************************
2628 ****************************************************************************/
2630 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2631 char *param, int tpscnt,
2632 char *data, int tdscnt,
2633 int mdrcnt,int mprcnt,
2634 char **rdata,char **rparam,
2635 int *rdata_len,int *rparam_len)
2637 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2638 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2639 char *str2 = skip_string(param,tpscnt,str1);
2640 char *p = skip_string(param,tpscnt,str2);
2645 WERROR werr = WERR_OK;
2647 if (!str1 || !str2 || !p) {
2651 * We use 1 here not 2 as we're checking
2652 * the last byte we want to access is safe.
2654 if (!is_offset_safe(param,tpscnt,p,1)) {
2657 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2660 /* check it's a supported varient */
2661 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2665 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2671 if (!print_job_exists(sharename, jobid)) {
2672 errcode = NERR_JobNotFound;
2676 snum = lp_servicenumber( sharename);
2678 errcode = NERR_DestNotFound;
2682 errcode = NERR_notsupported;
2685 case 81: /* delete */
2686 if (print_job_delete(¤t_user, snum, jobid, &werr))
2687 errcode = NERR_Success;
2689 case 82: /* pause */
2690 if (print_job_pause(¤t_user, snum, jobid, &werr))
2691 errcode = NERR_Success;
2693 case 83: /* resume */
2694 if (print_job_resume(¤t_user, snum, jobid, &werr))
2695 errcode = NERR_Success;
2699 if (!W_ERROR_IS_OK(werr))
2700 errcode = W_ERROR_V(werr);
2703 SSVAL(*rparam,0,errcode);
2704 SSVAL(*rparam,2,0); /* converter word */
2709 /****************************************************************************
2710 Purge a print queue - or pause or resume it.
2711 ****************************************************************************/
2713 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2714 char *param, int tpscnt,
2715 char *data, int tdscnt,
2716 int mdrcnt,int mprcnt,
2717 char **rdata,char **rparam,
2718 int *rdata_len,int *rparam_len)
2720 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2721 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2722 char *str2 = skip_string(param,tpscnt,str1);
2723 char *QueueName = skip_string(param,tpscnt,str2);
2724 int errcode = NERR_notsupported;
2726 WERROR werr = WERR_OK;
2728 if (!str1 || !str2 || !QueueName) {
2732 /* check it's a supported varient */
2733 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2737 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2743 if (skip_string(param,tpscnt,QueueName) == NULL) {
2746 snum = print_queue_snum(QueueName);
2749 errcode = NERR_JobNotFound;
2754 case 74: /* Pause queue */
2755 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2757 case 75: /* Resume queue */
2758 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2760 case 103: /* Purge */
2761 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2765 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2768 SSVAL(*rparam,0,errcode);
2769 SSVAL(*rparam,2,0); /* converter word */
2774 /****************************************************************************
2775 set the property of a print job (undocumented?)
2776 ? function = 0xb -> set name of print job
2777 ? function = 0x6 -> move print job up/down
2778 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2779 or <WWsTP> <WB21BB16B10zWWzDDz>
2780 ****************************************************************************/
2782 static int check_printjob_info(struct pack_desc* desc,
2783 int uLevel, char* id)
2785 desc->subformat = NULL;
2787 case 0: desc->format = "W"; break;
2788 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2789 case 2: desc->format = "WWzWWDDzz"; break;
2790 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2791 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2793 DEBUG(0,("check_printjob_info: invalid level %d\n",
2797 if (id == NULL || strcmp(desc->format,id) != 0) {
2798 DEBUG(0,("check_printjob_info: invalid format %s\n",
2799 id ? id : "<NULL>" ));
2805 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2806 char *param, int tpscnt,
2807 char *data, int tdscnt,
2808 int mdrcnt,int mprcnt,
2809 char **rdata,char **rparam,
2810 int *rdata_len,int *rparam_len)
2812 struct pack_desc desc;
2813 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2814 char *str2 = skip_string(param,tpscnt,str1);
2815 char *p = skip_string(param,tpscnt,str2);
2818 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2819 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2822 if (!str1 || !str2 || !p) {
2826 * We use 1 here not 2 as we're checking
2827 * the last byte we want to access is safe.
2829 if (!is_offset_safe(param,tpscnt,p,1)) {
2832 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2835 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2840 if (!share_defined(sharename)) {
2841 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2848 /* check it's a supported varient */
2849 if ((strcmp(str1,"WWsTP")) ||
2850 (!check_printjob_info(&desc,uLevel,str2)))
2853 if (!print_job_exists(sharename, jobid)) {
2854 errcode=NERR_JobNotFound;
2858 errcode = NERR_notsupported;
2862 /* change job place in the queue,
2863 data gives the new place */
2864 place = SVAL(data,0);
2865 if (print_job_set_place(sharename, jobid, place)) {
2866 errcode=NERR_Success;
2871 /* change print job name, data gives the name */
2872 if (print_job_set_name(sharename, jobid, data)) {
2873 errcode=NERR_Success;
2882 SSVALS(*rparam,0,errcode);
2883 SSVAL(*rparam,2,0); /* converter word */
2889 /****************************************************************************
2890 Get info about the server.
2891 ****************************************************************************/
2893 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2894 char *param, int tpscnt,
2895 char *data, int tdscnt,
2896 int mdrcnt,int mprcnt,
2897 char **rdata,char **rparam,
2898 int *rdata_len,int *rparam_len)
2900 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2901 char *str2 = skip_string(param,tpscnt,str1);
2902 char *p = skip_string(param,tpscnt,str2);
2903 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2907 if (!str1 || !str2 || !p) {
2911 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2913 /* check it's a supported varient */
2914 if (!prefix_ok(str1,"WrLh")) {
2920 if (strcmp(str2,"B16") != 0) {
2926 if (strcmp(str2,"B16BBDz") != 0) {
2932 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2938 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2944 if (strcmp(str2,"DN") != 0) {
2950 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2959 *rdata_len = mdrcnt;
2960 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2966 p2 = p + struct_len;
2968 srvstr_push(NULL, 0, p,global_myname(),16,
2969 STR_ASCII|STR_UPPER|STR_TERMINATE);
2973 struct srv_info_struct *servers=NULL;
2975 char *comment = NULL;
2976 TALLOC_CTX *ctx = talloc_tos();
2977 uint32 servertype= lp_default_server_announce();
2979 comment = talloc_strdup(ctx,lp_serverstring());
2984 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2985 for (i=0;i<count;i++) {
2986 if (strequal(servers[i].name,global_myname())) {
2987 servertype = servers[i].type;
2988 TALLOC_FREE(comment);
2989 comment = talloc_strdup(ctx,
2990 servers[i].comment);
3000 SCVAL(p,0,lp_major_announce_version());
3001 SCVAL(p,1,lp_minor_announce_version());
3002 SIVAL(p,2,servertype);
3004 if (mdrcnt == struct_len) {
3007 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3008 comment = talloc_sub_advanced(ctx,
3009 lp_servicename(SNUM(conn)),
3010 conn->server_info->unix_name,
3012 conn->server_info->gid,
3013 get_current_username(),
3014 current_user_info.domain,
3019 if (mdrcnt - struct_len <= 0) {
3024 MIN(mdrcnt - struct_len,
3025 MAX_SERVER_STRING_LENGTH),
3027 p2 = skip_string(*rdata,*rdata_len,p2);
3035 return False; /* not yet implemented */
3038 *rdata_len = PTR_DIFF(p2,*rdata);
3041 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3045 SSVAL(*rparam,0,NERR_Success);
3046 SSVAL(*rparam,2,0); /* converter word */
3047 SSVAL(*rparam,4,*rdata_len);
3052 /****************************************************************************
3053 Get info about the server.
3054 ****************************************************************************/
3056 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3057 char *param, int tpscnt,
3058 char *data, int tdscnt,
3059 int mdrcnt,int mprcnt,
3060 char **rdata,char **rparam,
3061 int *rdata_len,int *rparam_len)
3063 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3064 char *str2 = skip_string(param,tpscnt,str1);
3065 char *p = skip_string(param,tpscnt,str2);
3068 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3070 if (!str1 || !str2 || !p) {
3074 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3077 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3082 /* check it's a supported varient */
3083 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3087 *rdata_len = mdrcnt + 1024;
3088 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3093 SSVAL(*rparam,0,NERR_Success);
3094 SSVAL(*rparam,2,0); /* converter word */
3097 endp = *rdata + *rdata_len;
3099 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3104 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3105 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3107 p2 = skip_string(*rdata,*rdata_len,p2);
3113 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3114 strlcpy(p2,current_user_info.smb_name,PTR_DIFF(endp,p2));
3115 p2 = skip_string(*rdata,*rdata_len,p2);
3121 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3122 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3124 p2 = skip_string(*rdata,*rdata_len,p2);
3130 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3131 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3134 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3135 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3136 p2 = skip_string(*rdata,*rdata_len,p2);
3142 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3143 strlcpy(p2,"",PTR_DIFF(endp,p2));
3144 p2 = skip_string(*rdata,*rdata_len,p2);
3150 *rdata_len = PTR_DIFF(p2,*rdata);
3152 SSVAL(*rparam,4,*rdata_len);
3157 /****************************************************************************
3158 get info about a user
3160 struct user_info_11 {
3161 char usri11_name[21]; 0-20
3163 char *usri11_comment; 22-25
3164 char *usri11_usr_comment; 26-29
3165 unsigned short usri11_priv; 30-31
3166 unsigned long usri11_auth_flags; 32-35
3167 long usri11_password_age; 36-39
3168 char *usri11_homedir; 40-43
3169 char *usri11_parms; 44-47
3170 long usri11_last_logon; 48-51
3171 long usri11_last_logoff; 52-55
3172 unsigned short usri11_bad_pw_count; 56-57
3173 unsigned short usri11_num_logons; 58-59
3174 char *usri11_logon_server; 60-63
3175 unsigned short usri11_country_code; 64-65
3176 char *usri11_workstations; 66-69
3177 unsigned long usri11_max_storage; 70-73
3178 unsigned short usri11_units_per_week; 74-75
3179 unsigned char *usri11_logon_hours; 76-79
3180 unsigned short usri11_code_page; 80-81
3185 usri11_name specifies the user name for which information is retrieved
3187 usri11_pad aligns the next data structure element to a word boundary
3189 usri11_comment is a null terminated ASCII comment
3191 usri11_user_comment is a null terminated ASCII comment about the user
3193 usri11_priv specifies the level of the privilege assigned to the user.
3194 The possible values are:
3196 Name Value Description
3197 USER_PRIV_GUEST 0 Guest privilege
3198 USER_PRIV_USER 1 User privilege
3199 USER_PRV_ADMIN 2 Administrator privilege
3201 usri11_auth_flags specifies the account operator privileges. The
3202 possible values are:
3204 Name Value Description
3205 AF_OP_PRINT 0 Print operator
3208 Leach, Naik [Page 28]
3212 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3215 AF_OP_COMM 1 Communications operator
3216 AF_OP_SERVER 2 Server operator
3217 AF_OP_ACCOUNTS 3 Accounts operator
3220 usri11_password_age specifies how many seconds have elapsed since the
3221 password was last changed.
3223 usri11_home_dir points to a null terminated ASCII string that contains
3224 the path name of the user's home directory.
3226 usri11_parms points to a null terminated ASCII string that is set
3227 aside for use by applications.
3229 usri11_last_logon specifies the time when the user last logged on.
3230 This value is stored as the number of seconds elapsed since
3231 00:00:00, January 1, 1970.
3233 usri11_last_logoff specifies the time when the user last logged off.
3234 This value is stored as the number of seconds elapsed since
3235 00:00:00, January 1, 1970. A value of 0 means the last logoff
3238 usri11_bad_pw_count specifies the number of incorrect passwords
3239 entered since the last successful logon.
3241 usri11_log1_num_logons specifies the number of times this user has
3242 logged on. A value of -1 means the number of logons is unknown.
3244 usri11_logon_server points to a null terminated ASCII string that
3245 contains the name of the server to which logon requests are sent.
3246 A null string indicates logon requests should be sent to the
3249 usri11_country_code specifies the country code for the user's language
3252 usri11_workstations points to a null terminated ASCII string that
3253 contains the names of workstations the user may log on from.
3254 There may be up to 8 workstations, with the names separated by
3255 commas. A null strings indicates there are no restrictions.
3257 usri11_max_storage specifies the maximum amount of disk space the user
3258 can occupy. A value of 0xffffffff indicates there are no
3261 usri11_units_per_week specifies the equal number of time units into
3262 which a week is divided. This value must be equal to 168.
3264 usri11_logon_hours points to a 21 byte (168 bits) string that
3265 specifies the time during which the user can log on. Each bit
3266 represents one unique hour in a week. The first bit (bit 0, word
3267 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3271 Leach, Naik [Page 29]
3275 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3278 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3279 are no restrictions.
3281 usri11_code_page specifies the code page for the user's language of
3284 All of the pointers in this data structure need to be treated
3285 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3286 to be ignored. The converter word returned in the parameters section
3287 needs to be subtracted from the lower 16 bits to calculate an offset
3288 into the return buffer where this ASCII string resides.
3290 There is no auxiliary data in the response.
3292 ****************************************************************************/
3294 #define usri11_name 0
3295 #define usri11_pad 21
3296 #define usri11_comment 22
3297 #define usri11_usr_comment 26
3298 #define usri11_full_name 30
3299 #define usri11_priv 34
3300 #define usri11_auth_flags 36
3301 #define usri11_password_age 40
3302 #define usri11_homedir 44
3303 #define usri11_parms 48
3304 #define usri11_last_logon 52
3305 #define usri11_last_logoff 56
3306 #define usri11_bad_pw_count 60
3307 #define usri11_num_logons 62
3308 #define usri11_logon_server 64
3309 #define usri11_country_code 68
3310 #define usri11_workstations 70
3311 #define usri11_max_storage 74
3312 #define usri11_units_per_week 78
3313 #define usri11_logon_hours 80
3314 #define usri11_code_page 84
3315 #define usri11_end 86
3317 #define USER_PRIV_GUEST 0
3318 #define USER_PRIV_USER 1
3319 #define USER_PRIV_ADMIN 2
3321 #define AF_OP_PRINT 0
3322 #define AF_OP_COMM 1
3323 #define AF_OP_SERVER 2
3324 #define AF_OP_ACCOUNTS 3
3327 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3328 char *param, int tpscnt,
3329 char *data, int tdscnt,
3330 int mdrcnt,int mprcnt,
3331 char **rdata,char **rparam,
3332 int *rdata_len,int *rparam_len)
3334 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3335 char *str2 = skip_string(param,tpscnt,str1);
3336 char *UserName = skip_string(param,tpscnt,str2);
3337 char *p = skip_string(param,tpscnt,UserName);
3338 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3341 const char *level_string;
3343 /* get NIS home of a previously validated user - simeon */
3344 /* With share level security vuid will always be zero.
3345 Don't depend on vuser being non-null !!. JRA */
3346 user_struct *vuser = get_valid_user_struct(vuid);
3348 DEBUG(3,(" Username of UID %d is %s\n",
3349 (int)vuser->server_info->uid,
3350 vuser->server_info->unix_name));
3353 if (!str1 || !str2 || !UserName || !p) {
3358 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3363 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3365 /* check it's a supported variant */
3366 if (strcmp(str1,"zWrLh") != 0) {
3370 case 0: level_string = "B21"; break;
3371 case 1: level_string = "B21BB16DWzzWz"; break;
3372 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3373 case 10: level_string = "B21Bzzz"; break;
3374 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3375 default: return False;
3378 if (strcmp(level_string,str2) != 0) {
3382 *rdata_len = mdrcnt + 1024;
3383 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3388 SSVAL(*rparam,0,NERR_Success);
3389 SSVAL(*rparam,2,0); /* converter word */
3392 endp = *rdata + *rdata_len;
3393 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3399 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3402 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3407 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3408 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3409 p2 = skip_string(*rdata,*rdata_len,p2);
3414 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3415 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3416 p2 = skip_string(*rdata,*rdata_len,p2);
3421 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3422 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3423 strlcpy(p2,((vuser != NULL)
3424 ? pdb_get_fullname(vuser->server_info->sam_account)
3425 : UserName),PTR_DIFF(endp,p2));
3426 p2 = skip_string(*rdata,*rdata_len,p2);
3433 const char *homedir = "";
3434 if (vuser != NULL) {
3435 homedir = pdb_get_homedir(
3436 vuser->server_info->sam_account);
3438 /* modelled after NTAS 3.51 reply */
3439 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3440 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3441 SIVALS(p,usri11_password_age,-1); /* password age */
3442 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3443 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3444 p2 = skip_string(*rdata,*rdata_len,p2);
3448 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3449 strlcpy(p2,"",PTR_DIFF(endp,p2));
3450 p2 = skip_string(*rdata,*rdata_len,p2);
3454 SIVAL(p,usri11_last_logon,0); /* last logon */
3455 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3456 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3457 SSVALS(p,usri11_num_logons,-1); /* num logons */
3458 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3459 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3460 p2 = skip_string(*rdata,*rdata_len,p2);
3464 SSVAL(p,usri11_country_code,0); /* country code */
3466 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3467 strlcpy(p2,"",PTR_DIFF(endp,p2));
3468 p2 = skip_string(*rdata,*rdata_len,p2);
3473 SIVALS(p,usri11_max_storage,-1); /* max storage */
3474 SSVAL(p,usri11_units_per_week,168); /* units per week */
3475 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3477 /* a simple way to get logon hours at all times. */
3479 SCVAL(p2,21,0); /* fix zero termination */
3480 p2 = skip_string(*rdata,*rdata_len,p2);
3485 SSVAL(p,usri11_code_page,0); /* code page */
3488 if (uLevel == 1 || uLevel == 2) {
3489 memset(p+22,' ',16); /* password */
3490 SIVALS(p,38,-1); /* password age */
3492 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3493 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3494 strlcpy(p2, vuser ? pdb_get_homedir(
3495 vuser->server_info->sam_account) : "",
3497 p2 = skip_string(*rdata,*rdata_len,p2);
3501 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3503 SSVAL(p,52,0); /* flags */
3504 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3505 strlcpy(p2, vuser ? pdb_get_logon_script(
3506 vuser->server_info->sam_account) : "",
3508 p2 = skip_string(*rdata,*rdata_len,p2);
3513 SIVAL(p,60,0); /* auth_flags */
3514 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3515 strlcpy(p2,((vuser != NULL)
3516 ? pdb_get_fullname(vuser->server_info->sam_account)
3517 : UserName),PTR_DIFF(endp,p2));
3518 p2 = skip_string(*rdata,*rdata_len,p2);
3522 SIVAL(p,68,0); /* urs_comment */
3523 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3524 strlcpy(p2,"",PTR_DIFF(endp,p2));
3525 p2 = skip_string(*rdata,*rdata_len,p2);
3529 SIVAL(p,76,0); /* workstations */
3530 SIVAL(p,80,0); /* last_logon */
3531 SIVAL(p,84,0); /* last_logoff */
3532 SIVALS(p,88,-1); /* acct_expires */
3533 SIVALS(p,92,-1); /* max_storage */
3534 SSVAL(p,96,168); /* units_per_week */
3535 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3538 SSVALS(p,102,-1); /* bad_pw_count */
3539 SSVALS(p,104,-1); /* num_logons */
3540 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3542 TALLOC_CTX *ctx = talloc_tos();
3543 int space_rem = *rdata_len - (p2 - *rdata);
3546 if (space_rem <= 0) {
3549 tmp = talloc_strdup(ctx, "\\\\%L");
3553 tmp = talloc_sub_basic(ctx,
3566 p2 = skip_string(*rdata,*rdata_len,p2);
3570 SSVAL(p,110,49); /* country_code */
3571 SSVAL(p,112,860); /* code page */
3575 *rdata_len = PTR_DIFF(p2,*rdata);
3577 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3582 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3583 char *param, int tpscnt,
3584 char *data, int tdscnt,
3585 int mdrcnt,int mprcnt,
3586 char **rdata,char **rparam,
3587 int *rdata_len,int *rparam_len)
3589 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3590 char *str2 = skip_string(param,tpscnt,str1);
3591 char *p = skip_string(param,tpscnt,str2);
3593 struct pack_desc desc;
3595 /* With share level security vuid will always be zero.
3596 Don't depend on vuser being non-null !!. JRA */
3597 user_struct *vuser = get_valid_user_struct(vuid);
3599 if (!str1 || !str2 || !p) {
3604 DEBUG(3,(" Username of UID %d is %s\n",
3605 (int)vuser->server_info->uid,
3606 vuser->server_info->unix_name));
3609 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3610 name = get_safe_str_ptr(param,tpscnt,p,2);
3615 memset((char *)&desc,'\0',sizeof(desc));
3617 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3619 /* check it's a supported varient */
3620 if (strcmp(str1,"OOWb54WrLh") != 0) {
3623 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3627 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3634 desc.buflen = mdrcnt;
3635 desc.subformat = NULL;
3638 if (init_package(&desc,1,0)) {
3639 PACKI(&desc,"W",0); /* code */
3640 PACKS(&desc,"B21",name); /* eff. name */
3641 PACKS(&desc,"B",""); /* pad */
3642 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3643 PACKI(&desc,"D",0); /* auth flags XXX */
3644 PACKI(&desc,"W",0); /* num logons */
3645 PACKI(&desc,"W",0); /* bad pw count */
3646 PACKI(&desc,"D",0); /* last logon */
3647 PACKI(&desc,"D",-1); /* last logoff */
3648 PACKI(&desc,"D",-1); /* logoff time */
3649 PACKI(&desc,"D",-1); /* kickoff time */
3650 PACKI(&desc,"D",0); /* password age */
3651 PACKI(&desc,"D",0); /* password can change */
3652 PACKI(&desc,"D",-1); /* password must change */
3656 fstrcpy(mypath,"\\\\");
3657 fstrcat(mypath,get_local_machine_name());
3659 PACKS(&desc,"z",mypath); /* computer */
3662 PACKS(&desc,"z",lp_workgroup());/* domain */
3663 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
3664 vuser->server_info->sam_account) : ""); /* script path */
3665 PACKI(&desc,"D",0x00000000); /* reserved */
3668 *rdata_len = desc.usedlen;
3670 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3674 SSVALS(*rparam,0,desc.errcode);
3676 SSVAL(*rparam,4,desc.neededlen);
3678 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3683 /****************************************************************************
3684 api_WAccessGetUserPerms
3685 ****************************************************************************/
3687 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3688 char *param, int tpscnt,
3689 char *data, int tdscnt,
3690 int mdrcnt,int mprcnt,
3691 char **rdata,char **rparam,
3692 int *rdata_len,int *rparam_len)
3694 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3695 char *str2 = skip_string(param,tpscnt,str1);
3696 char *user = skip_string(param,tpscnt,str2);
3697 char *resource = skip_string(param,tpscnt,user);
3699 if (!str1 || !str2 || !user || !resource) {
3703 if (skip_string(param,tpscnt,resource) == NULL) {
3706 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3708 /* check it's a supported varient */
3709 if (strcmp(str1,"zzh") != 0) {
3712 if (strcmp(str2,"") != 0) {
3717 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3721 SSVALS(*rparam,0,0); /* errorcode */
3722 SSVAL(*rparam,2,0); /* converter word */
3723 SSVAL(*rparam,4,0x7f); /* permission flags */
3728 /****************************************************************************
3729 api_WPrintJobEnumerate
3730 ****************************************************************************/
3732 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3733 char *param, int tpscnt,
3734 char *data, int tdscnt,
3735 int mdrcnt,int mprcnt,
3736 char **rdata,char **rparam,
3737 int *rdata_len,int *rparam_len)
3739 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3740 char *str2 = skip_string(param,tpscnt,str1);
3741 char *p = skip_string(param,tpscnt,str2);
3748 struct pack_desc desc;
3749 print_queue_struct *queue=NULL;
3750 print_status_struct status;
3753 if (!str1 || !str2 || !p) {
3757 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3759 memset((char *)&desc,'\0',sizeof(desc));
3760 memset((char *)&status,'\0',sizeof(status));
3762 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3764 /* check it's a supported varient */
3765 if (strcmp(str1,"WWrLh") != 0) {
3768 if (!check_printjob_info(&desc,uLevel,str2)) {
3772 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3776 snum = lp_servicenumber( sharename);
3777 if (snum < 0 || !VALID_SNUM(snum)) {
3781 count = print_queue_status(snum,&queue,&status);
3782 for (i = 0; i < count; i++) {
3783 if (queue[i].job == jobid) {
3789 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3794 desc.buflen = mdrcnt;
3797 * Don't return data but need to get correct length
3798 * init_package will return wrong size if buflen=0
3800 desc.buflen = getlen(desc.format);
3801 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3804 if (init_package(&desc,1,0)) {
3806 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3807 *rdata_len = desc.usedlen;
3809 desc.errcode = NERR_JobNotFound;
3815 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3819 SSVALS(*rparam,0,desc.errcode);
3821 SSVAL(*rparam,4,desc.neededlen);
3826 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3831 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3832 char *param, int tpscnt,
3833 char *data, int tdscnt,
3834 int mdrcnt,int mprcnt,
3835 char **rdata,char **rparam,
3836 int *rdata_len,int *rparam_len)
3838 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3839 char *str2 = skip_string(param,tpscnt,str1);
3840 char *p = skip_string(param,tpscnt,str2);
3846 struct pack_desc desc;
3847 print_queue_struct *queue=NULL;
3848 print_status_struct status;
3850 if (!str1 || !str2 || !p) {
3854 memset((char *)&desc,'\0',sizeof(desc));
3855 memset((char *)&status,'\0',sizeof(status));
3857 p = skip_string(param,tpscnt,p);
3861 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3863 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3865 /* check it's a supported variant */
3866 if (strcmp(str1,"zWrLeh") != 0) {
3871 return False; /* defined only for uLevel 0,1,2 */
3874 if (!check_printjob_info(&desc,uLevel,str2)) {
3878 snum = find_service(name);
3879 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3883 count = print_queue_status(snum,&queue,&status);
3885 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3891 desc.buflen = mdrcnt;
3893 if (init_package(&desc,count,0)) {
3895 for (i = 0; i < count; i++) {
3896 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3897 if (desc.errcode == NERR_Success) {
3903 *rdata_len = desc.usedlen;
3906 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3910 SSVALS(*rparam,0,desc.errcode);
3912 SSVAL(*rparam,4,succnt);
3913 SSVAL(*rparam,6,count);
3917 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3922 static int check_printdest_info(struct pack_desc* desc,
3923 int uLevel, char* id)
3925 desc->subformat = NULL;
3928 desc->format = "B9";
3931 desc->format = "B9B21WWzW";
3937 desc->format = "zzzWWzzzWW";
3940 DEBUG(0,("check_printdest_info: invalid level %d\n",
3944 if (id == NULL || strcmp(desc->format,id) != 0) {
3945 DEBUG(0,("check_printdest_info: invalid string %s\n",
3946 id ? id : "<NULL>" ));
3952 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3953 struct pack_desc* desc)
3957 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3958 buf[sizeof(buf)-1] = 0;
3962 PACKS(desc,"B9",buf); /* szName */
3964 PACKS(desc,"B21",""); /* szUserName */
3965 PACKI(desc,"W",0); /* uJobId */
3966 PACKI(desc,"W",0); /* fsStatus */
3967 PACKS(desc,"z",""); /* pszStatus */
3968 PACKI(desc,"W",0); /* time */
3972 if (uLevel == 2 || uLevel == 3) {
3973 PACKS(desc,"z",buf); /* pszPrinterName */
3975 PACKS(desc,"z",""); /* pszUserName */
3976 PACKS(desc,"z",""); /* pszLogAddr */
3977 PACKI(desc,"W",0); /* uJobId */
3978 PACKI(desc,"W",0); /* fsStatus */
3979 PACKS(desc,"z",""); /* pszStatus */
3980 PACKS(desc,"z",""); /* pszComment */
3981 PACKS(desc,"z","NULL"); /* pszDrivers */
3982 PACKI(desc,"W",0); /* time */
3983 PACKI(desc,"W",0); /* pad1 */
3988 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3989 char *param, int tpscnt,
3990 char *data, int tdscnt,
3991 int mdrcnt,int mprcnt,
3992 char **rdata,char **rparam,
3993 int *rdata_len,int *rparam_len)
3995 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3996 char *str2 = skip_string(param,tpscnt,str1);
3997 char *p = skip_string(param,tpscnt,str2);
3998 char* PrinterName = p;
4000 struct pack_desc desc;
4004 if (!str1 || !str2 || !p) {
4008 memset((char *)&desc,'\0',sizeof(desc));
4010 p = skip_string(param,tpscnt,p);
4014 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4016 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4018 /* check it's a supported varient */
4019 if (strcmp(str1,"zWrLh") != 0) {
4022 if (!check_printdest_info(&desc,uLevel,str2)) {
4026 snum = find_service(PrinterName);
4027 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4029 desc.errcode = NERR_DestNotFound;
4033 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4038 desc.buflen = mdrcnt;
4041 * Don't return data but need to get correct length
4042 * init_package will return wrong size if buflen=0
4044 desc.buflen = getlen(desc.format);
4045 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4047 if (init_package(&desc,1,0)) {
4048 fill_printdest_info(conn,snum,uLevel,&desc);
4050 *rdata_len = desc.usedlen;
4054 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4058 SSVALS(*rparam,0,desc.errcode);
4060 SSVAL(*rparam,4,desc.neededlen);
4062 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4068 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4069 char *param, int tpscnt,
4070 char *data, int tdscnt,
4071 int mdrcnt,int mprcnt,
4072 char **rdata,char **rparam,
4073 int *rdata_len,int *rparam_len)
4075 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4076 char *str2 = skip_string(param,tpscnt,str1);
4077 char *p = skip_string(param,tpscnt,str2);
4081 struct pack_desc desc;
4082 int services = lp_numservices();
4084 if (!str1 || !str2 || !p) {
4088 memset((char *)&desc,'\0',sizeof(desc));
4090 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4092 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4094 /* check it's a supported varient */
4095 if (strcmp(str1,"WrLeh") != 0) {
4098 if (!check_printdest_info(&desc,uLevel,str2)) {
4103 for (i = 0; i < services; i++) {
4104 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4110 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4117 desc.buflen = mdrcnt;
4118 if (init_package(&desc,queuecnt,0)) {
4121 for (i = 0; i < services; i++) {
4122 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4123 fill_printdest_info(conn,i,uLevel,&desc);
4125 if (desc.errcode == NERR_Success) {
4132 *rdata_len = desc.usedlen;
4135 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4139 SSVALS(*rparam,0,desc.errcode);
4141 SSVAL(*rparam,4,succnt);
4142 SSVAL(*rparam,6,queuecnt);
4144 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4149 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4150 char *param, int tpscnt,
4151 char *data, int tdscnt,
4152 int mdrcnt,int mprcnt,
4153 char **rdata,char **rparam,
4154 int *rdata_len,int *rparam_len)
4156 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4157 char *str2 = skip_string(param,tpscnt,str1);
4158 char *p = skip_string(param,tpscnt,str2);
4161 struct pack_desc desc;
4163 if (!str1 || !str2 || !p) {
4167 memset((char *)&desc,'\0',sizeof(desc));
4169 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4171 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4173 /* check it's a supported varient */
4174 if (strcmp(str1,"WrLeh") != 0) {
4177 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4182 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4188 desc.buflen = mdrcnt;
4189 if (init_package(&desc,1,0)) {
4190 PACKS(&desc,"B41","NULL");
4193 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4195 *rdata_len = desc.usedlen;
4198 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4202 SSVALS(*rparam,0,desc.errcode);
4204 SSVAL(*rparam,4,succnt);
4207 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4212 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4213 char *param, int tpscnt,
4214 char *data, int tdscnt,
4215 int mdrcnt,int mprcnt,
4216 char **rdata,char **rparam,
4217 int *rdata_len,int *rparam_len)
4219 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4220 char *str2 = skip_string(param,tpscnt,str1);
4221 char *p = skip_string(param,tpscnt,str2);
4224 struct pack_desc desc;
4226 if (!str1 || !str2 || !p) {
4229 memset((char *)&desc,'\0',sizeof(desc));
4231 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4233 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4235 /* check it's a supported varient */
4236 if (strcmp(str1,"WrLeh") != 0) {
4239 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4244 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4250 desc.buflen = mdrcnt;
4252 if (init_package(&desc,1,0)) {
4253 PACKS(&desc,"B13","lpd");
4256 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4258 *rdata_len = desc.usedlen;
4261 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4265 SSVALS(*rparam,0,desc.errcode);
4267 SSVAL(*rparam,4,succnt);
4270 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4275 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4276 char *param, int tpscnt,
4277 char *data, int tdscnt,
4278 int mdrcnt,int mprcnt,
4279 char **rdata,char **rparam,
4280 int *rdata_len,int *rparam_len)
4282 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4283 char *str2 = skip_string(param,tpscnt,str1);
4284 char *p = skip_string(param,tpscnt,str2);
4287 struct pack_desc desc;
4289 if (!str1 || !str2 || !p) {
4293 memset((char *)&desc,'\0',sizeof(desc));
4295 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4297 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4299 /* check it's a supported varient */
4300 if (strcmp(str1,"WrLeh") != 0) {
4303 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4308 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4313 memset((char *)&desc,'\0',sizeof(desc));
4315 desc.buflen = mdrcnt;
4317 if (init_package(&desc,1,0)) {
4318 PACKS(&desc,"B13","lp0");
4321 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4323 *rdata_len = desc.usedlen;
4326 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4330 SSVALS(*rparam,0,desc.errcode);
4332 SSVAL(*rparam,4,succnt);
4335 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4340 /****************************************************************************
4342 ****************************************************************************/
4344 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4345 char *param, int tpscnt,
4346 char *data, int tdscnt,
4347 int mdrcnt,int mprcnt,
4348 char **rdata,char **rparam,
4349 int *rdata_len,int *rparam_len)
4352 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4353 char *str2 = skip_string(param,tpscnt,str1);
4354 char *p = skip_string(param,tpscnt,str2);
4356 struct pack_desc desc;
4357 struct sessionid *session_list;
4358 int i, num_sessions;
4360 if (!str1 || !str2 || !p) {
4364 memset((char *)&desc,'\0',sizeof(desc));
4366 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4368 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4369 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4370 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4372 /* check it's a supported varient */
4373 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4376 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4380 num_sessions = list_sessions(talloc_tos(), &session_list);
4383 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4388 memset((char *)&desc,'\0',sizeof(desc));
4390 desc.buflen = mdrcnt;
4392 if (!init_package(&desc,num_sessions,0)) {
4396 for(i=0; i<num_sessions; i++) {
4397 PACKS(&desc, "z", session_list[i].remote_machine);
4398 PACKS(&desc, "z", session_list[i].username);
4399 PACKI(&desc, "W", 1); /* num conns */
4400 PACKI(&desc, "W", 0); /* num opens */
4401 PACKI(&desc, "W", 1); /* num users */
4402 PACKI(&desc, "D", 0); /* session time */
4403 PACKI(&desc, "D", 0); /* idle time */
4404 PACKI(&desc, "D", 0); /* flags */
4405 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4408 *rdata_len = desc.usedlen;
4411 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4415 SSVALS(*rparam,0,desc.errcode);
4416 SSVAL(*rparam,2,0); /* converter */
4417 SSVAL(*rparam,4,num_sessions); /* count */
4419 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4425 /****************************************************************************
4426 The buffer was too small.
4427 ****************************************************************************/
4429 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4430 int mdrcnt, int mprcnt,
4431 char **rdata, char **rparam,
4432 int *rdata_len, int *rparam_len)
4434 *rparam_len = MIN(*rparam_len,mprcnt);
4435 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4442 SSVAL(*rparam,0,NERR_BufTooSmall);
4444 DEBUG(3,("Supplied buffer too small in API command\n"));
4449 /****************************************************************************
4450 The request is not supported.
4451 ****************************************************************************/
4453 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4454 char *param, int tpscnt,
4455 char *data, int tdscnt,
4456 int mdrcnt, int mprcnt,
4457 char **rdata, char **rparam,
4458 int *rdata_len, int *rparam_len)
4461 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4468 SSVAL(*rparam,0,NERR_notsupported);
4469 SSVAL(*rparam,2,0); /* converter word */
4471 DEBUG(3,("Unsupported API command\n"));
4476 static const struct {
4479 bool (*fn)(connection_struct *, uint16,
4482 int,int,char **,char **,int *,int *);
4483 bool auth_user; /* Deny anonymous access? */
4484 } api_commands[] = {
4485 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4486 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4487 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4488 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4489 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4490 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4491 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4492 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4493 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4494 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4495 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4496 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4497 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4498 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4499 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4500 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4501 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4502 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4503 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4504 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4505 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4506 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4507 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4508 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4509 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4510 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4511 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4512 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4513 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4514 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4515 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4516 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4517 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4518 {NULL, -1, api_Unsupported}
4519 /* The following RAP calls are not implemented by Samba:
4521 RAP_WFileEnum2 - anon not OK
4526 /****************************************************************************
4527 Handle remote api calls.
4528 ****************************************************************************/
4530 void api_reply(connection_struct *conn, uint16 vuid,
4531 struct smb_request *req,
4532 char *data, char *params,
4533 int tdscnt, int tpscnt,
4534 int mdrcnt, int mprcnt)
4538 char *rparam = NULL;
4539 const char *name1 = NULL;
4540 const char *name2 = NULL;
4547 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4556 api_command = SVAL(params,0);
4557 /* Is there a string at position params+2 ? */
4558 if (skip_string(params,tpscnt,params+2)) {
4563 name2 = skip_string(params,tpscnt,params+2);
4568 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4572 tdscnt,tpscnt,mdrcnt,mprcnt));
4574 for (i=0;api_commands[i].name;i++) {
4575 if (api_commands[i].id == api_command && api_commands[i].fn) {
4576 DEBUG(3,("Doing %s\n",api_commands[i].name));
4581 /* Check whether this api call can be done anonymously */
4583 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4584 user_struct *user = get_valid_user_struct(vuid);
4586 if (!user || user->server_info->guest) {
4587 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4592 rdata = (char *)SMB_MALLOC(1024);
4594 memset(rdata,'\0',1024);
4597 rparam = (char *)SMB_MALLOC(1024);
4599 memset(rparam,'\0',1024);
4602 if(!rdata || !rparam) {
4603 DEBUG(0,("api_reply: malloc fail !\n"));
4606 reply_nterror(req, NT_STATUS_NO_MEMORY);
4610 reply = api_commands[i].fn(conn,
4612 params,tpscnt, /* params + length */
4613 data,tdscnt, /* data + length */
4615 &rdata,&rparam,&rdata_len,&rparam_len);
4618 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4619 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4620 &rdata,&rparam,&rdata_len,&rparam_len);
4623 /* if we get False back then it's actually unsupported */
4625 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4626 &rdata,&rparam,&rdata_len,&rparam_len);
4629 /* If api_Unsupported returns false we can't return anything. */
4631 send_trans_reply(conn, req, rparam, rparam_len,
4632 rdata, rdata_len, False);