2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
35 extern fstring local_machine;
36 extern pstring global_myname;
37 extern fstring global_myworkgroup;
39 #define NERR_Success 0
40 #define NERR_badpass 86
41 #define NERR_notsupported 50
43 #define NERR_BASE (2100)
44 #define NERR_BufTooSmall (NERR_BASE+23)
45 #define NERR_JobNotFound (NERR_BASE+51)
46 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ACCESS_READ 0x01
49 #define ACCESS_WRITE 0x02
50 #define ACCESS_CREATE 0x04
52 #define SHPWLEN 8 /* share password length */
54 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
55 int mdrcnt,int mprcnt,
56 char **rdata,char **rparam,
57 int *rdata_len,int *rparam_len);
58 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
59 int mdrcnt,int mprcnt,
60 char **rdata,char **rparam,
61 int *rdata_len,int *rparam_len);
64 static int CopyExpanded(connection_struct *conn,
65 int snum, char** dst, char* src, int* n)
70 if (!src || !dst || !n || !(*dst)) return(0);
72 StrnCpy(buf,src,sizeof(buf)/2);
73 pstring_sub(buf,"%S",lp_servicename(snum));
74 standard_sub_conn(conn,buf,sizeof(buf));
75 l = push_ascii(*dst,buf,*n-1, STR_TERMINATE);
81 static int CopyAndAdvance(char** dst, char* src, int* n)
84 if (!src || !dst || !n || !(*dst)) return(0);
85 l = push_ascii(*dst,src,*n, STR_TERMINATE);
91 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
95 StrnCpy(buf,s,sizeof(buf)/2);
96 pstring_sub(buf,"%S",lp_servicename(snum));
97 standard_sub_conn(conn,buf,sizeof(buf));
98 return strlen(buf) + 1;
101 static char* Expand(connection_struct *conn, int snum, char* s)
104 if (!s) return(NULL);
105 StrnCpy(buf,s,sizeof(buf)/2);
106 pstring_sub(buf,"%S",lp_servicename(snum));
107 standard_sub_conn(conn,buf,sizeof(buf));
111 /*******************************************************************
112 check a API string for validity when we only need to check the prefix
113 ******************************************************************/
114 static BOOL prefix_ok(char *str,char *prefix)
116 return(strncmp(str,prefix,strlen(prefix)) == 0);
120 char* format; /* formatstring for structure */
121 char* subformat; /* subformat for structure */
122 char* base; /* baseaddress of buffer */
123 int buflen; /* remaining size for fixed part; on init: length of base */
124 int subcount; /* count of substructures */
125 char* structbuf; /* pointer into buffer for remaining fixed part */
126 int stringlen; /* remaining size for variable part */
127 char* stringbuf; /* pointer into buffer for remaining variable part */
128 int neededlen; /* total needed size */
129 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
130 char* curpos; /* current position; pointer into format or subformat */
134 static int get_counter(char** p)
137 if (!p || !(*p)) return(1);
138 if (!isdigit((int)**p)) return 1;
142 n = 10 * n + (i - '0');
149 static int getlen(char* p)
155 case 'W': /* word (2 byte) */
158 case 'K': /* status word? (2 byte) */
161 case 'N': /* count of substructures (word) at end */
164 case 'D': /* double word (4 byte) */
165 case 'z': /* offset to zero terminated string (4 byte) */
166 case 'l': /* offset to user data (4 byte) */
169 case 'b': /* offset to data (with counter) (4 byte) */
173 case 'B': /* byte (with optional counter) */
174 n += get_counter(&p);
181 static BOOL init_package(struct pack_desc* p, int count, int subcount)
186 if (!p->format || !p->base) return(False);
188 i = count * getlen(p->format);
189 if (p->subformat) i += subcount * getlen(p->subformat);
190 p->structbuf = p->base;
194 p->curpos = p->format;
200 * This is the old error code we used. Aparently
201 * WinNT/2k systems return ERRbuftoosmall (2123) and
202 * OS/2 needs this. I'm leaving this here so we can revert
205 p->errcode = ERRmoredata;
207 p->errcode = ERRbuftoosmall;
211 p->errcode = NERR_Success;
214 p->stringbuf = p->base + i;
216 return(p->errcode == NERR_Success);
219 static int package(struct pack_desc* p, ...)
222 int needed=0, stringneeded;
224 int is_string=0, stringused;
231 p->curpos = p->format;
233 p->curpos = p->subformat;
238 str = va_arg(args,char*);
239 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
248 switch( *p->curpos++ ) {
249 case 'W': /* word (2 byte) */
251 temp = va_arg(args,int);
252 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
254 case 'K': /* status word? (2 byte) */
256 temp = va_arg(args,int);
257 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
259 case 'N': /* count of substructures (word) at end */
261 p->subcount = va_arg(args,int);
262 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
264 case 'D': /* double word (4 byte) */
266 temp = va_arg(args,int);
267 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
269 case 'B': /* byte (with optional counter) */
270 needed = get_counter(&p->curpos);
272 char *s = va_arg(args,char*);
273 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
276 case 'z': /* offset to zero terminated string (4 byte) */
277 str = va_arg(args,char*);
278 stringneeded = (str ? strlen(str)+1 : 0);
281 case 'l': /* offset to user data (4 byte) */
282 str = va_arg(args,char*);
283 stringneeded = va_arg(args,int);
286 case 'b': /* offset to data (with counter) (4 byte) */
287 str = va_arg(args,char*);
288 stringneeded = get_counter(&p->curpos);
293 if (stringneeded >= 0) {
295 if (p->buflen >= needed) {
296 stringused = stringneeded;
297 if (stringused > p->stringlen) {
298 stringused = (is_string ? p->stringlen : 0);
299 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
302 SIVAL(p->structbuf,0,0);
304 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
305 memcpy(p->stringbuf,str?str:"",stringused);
306 if (is_string) p->stringbuf[stringused-1] = '\0';
307 p->stringbuf += stringused;
308 p->stringlen -= stringused;
309 p->usedlen += stringused;
312 p->neededlen += stringneeded;
314 p->neededlen += needed;
315 if (p->buflen >= needed) {
316 p->structbuf += needed;
318 p->usedlen += needed;
321 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
327 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
328 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
330 #define PACK(desc,t,v) package(desc,v)
331 #define PACKl(desc,t,v,l) package(desc,v,l)
334 static void PACKI(struct pack_desc* desc,char *t,int v)
339 static void PACKS(struct pack_desc* desc,char *t,char *v)
345 /****************************************************************************
347 ****************************************************************************/
348 static void PackDriverData(struct pack_desc* desc)
350 char drivdata[4+4+32];
351 SIVAL(drivdata,0,sizeof drivdata); /* cb */
352 SIVAL(drivdata,4,1000); /* lVersion */
353 memset(drivdata+8,0,32); /* szDeviceName */
354 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
355 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
358 static int check_printq_info(struct pack_desc* desc,
359 int uLevel, char *id1, char *id2)
361 desc->subformat = NULL;
364 desc->format = "B13";
367 desc->format = "B13BWWWzzzzzWW";
370 desc->format = "B13BWWWzzzzzWN";
371 desc->subformat = "WB21BB16B10zWWzDDz";
374 desc->format = "zWWWWzzzzWWzzl";
377 desc->format = "zWWWWzzzzWNzzl";
378 desc->subformat = "WWzWWDDzz";
387 desc->format = "WzzzzzzzzN";
388 desc->subformat = "z";
390 default: return False;
392 if (strcmp(desc->format,id1) != 0) return False;
393 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
398 #define RAP_JOB_STATUS_QUEUED 0
399 #define RAP_JOB_STATUS_PAUSED 1
400 #define RAP_JOB_STATUS_SPOOLING 2
401 #define RAP_JOB_STATUS_PRINTING 3
402 #define RAP_JOB_STATUS_PRINTED 4
404 #define RAP_QUEUE_STATUS_PAUSED 1
405 #define RAP_QUEUE_STATUS_ERROR 2
407 /* turn a print job status into a on the wire status
409 static int printj_status(int v)
413 return RAP_JOB_STATUS_QUEUED;
415 return RAP_JOB_STATUS_PAUSED;
417 return RAP_JOB_STATUS_SPOOLING;
419 return RAP_JOB_STATUS_PRINTING;
424 /* turn a print queue status into a on the wire status
426 static int printq_status(int v)
432 return RAP_QUEUE_STATUS_PAUSED;
434 return RAP_QUEUE_STATUS_ERROR;
437 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
438 struct pack_desc* desc,
439 print_queue_struct* queue, int n)
441 time_t t = queue->time;
443 /* the client expects localtime */
446 PACKI(desc,"W",queue->job); /* uJobId */
448 PACKS(desc,"B21",queue->fs_user); /* szUserName */
449 PACKS(desc,"B",""); /* pad */
450 PACKS(desc,"B16",""); /* szNotifyName */
451 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
452 PACKS(desc,"z",""); /* pszParms */
453 PACKI(desc,"W",n+1); /* uPosition */
454 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
455 PACKS(desc,"z",""); /* pszStatus */
456 PACKI(desc,"D",t); /* ulSubmitted */
457 PACKI(desc,"D",queue->size); /* ulSize */
458 PACKS(desc,"z",queue->fs_file); /* pszComment */
460 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
461 PACKI(desc,"W",queue->priority); /* uPriority */
462 PACKS(desc,"z",queue->fs_user); /* pszUserName */
463 PACKI(desc,"W",n+1); /* uPosition */
464 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
465 PACKI(desc,"D",t); /* ulSubmitted */
466 PACKI(desc,"D",queue->size); /* ulSize */
467 PACKS(desc,"z","Samba"); /* pszComment */
468 PACKS(desc,"z",queue->fs_file); /* pszDocument */
470 PACKS(desc,"z",""); /* pszNotifyName */
471 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
472 PACKS(desc,"z",""); /* pszParms */
473 PACKS(desc,"z",""); /* pszStatus */
474 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
475 PACKS(desc,"z","lpd"); /* pszQProcName */
476 PACKS(desc,"z",""); /* pszQProcParms */
477 PACKS(desc,"z","NULL"); /* pszDriverName */
478 PackDriverData(desc); /* pDriverData */
479 PACKS(desc,"z",""); /* pszPrinterName */
480 } else if (uLevel == 4) { /* OS2 */
481 PACKS(desc,"z",""); /* pszSpoolFileName */
482 PACKS(desc,"z",""); /* pszPortName */
483 PACKS(desc,"z",""); /* pszStatus */
484 PACKI(desc,"D",0); /* ulPagesSpooled */
485 PACKI(desc,"D",0); /* ulPagesSent */
486 PACKI(desc,"D",0); /* ulPagesPrinted */
487 PACKI(desc,"D",0); /* ulTimePrinted */
488 PACKI(desc,"D",0); /* ulExtendJobStatus */
489 PACKI(desc,"D",0); /* ulStartPage */
490 PACKI(desc,"D",0); /* ulEndPage */
495 /********************************************************************
496 Return a driver name given an snum.
497 Looks in a tdb first. Returns True if from tdb, False otherwise.
498 ********************************************************************/
500 static BOOL get_driver_name(int snum, pstring drivername)
502 NT_PRINTER_INFO_LEVEL *info = NULL;
505 get_a_printer (&info, 2, lp_servicename(snum));
507 pstrcpy( drivername, info->info_2->drivername);
509 free_a_printer(&info, 2);
511 pstrcpy( drivername, lp_printerdriver(snum));
517 /********************************************************************
518 Respond to the DosPrintQInfo command with a level of 52
519 This is used to get printer driver information for Win9x clients
520 ********************************************************************/
521 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
522 struct pack_desc* desc,
523 int count, print_queue_struct* queue,
524 print_status_struct* status)
528 pstring tok,driver,datafile,langmon,helpfile,datatype;
537 * Check in the tdb *first* before checking the legacy
538 * files. This allows an NT upload to take precedence over
539 * the existing fileset. JRA.
541 * we need to lookup the driver name prior to making the call
542 * to get_a_printer_driver_9x_compatible() and not rely on the
543 * 'print driver' parameter --jerry
547 if ((get_driver_name(snum,drivername)) &&
548 ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True))
552 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
556 /* didn't find driver in tdb */
558 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
559 snum, drivername, lp_driverfile(snum)));
561 lines = file_lines_load(lp_driverfile(snum),NULL);
564 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
566 desc->errcode=NERR_notsupported;
570 /* lookup the long printer driver name in the file description */
571 for (i=0;lines[i] && !ok;i++)
574 if (next_token(&p,tok,":",sizeof(tok)) &&
575 (strlen(drivername) == strlen(tok)) &&
576 (!strncmp(tok,drivername,strlen(drivername))))
585 /* driver file name */
586 if (!next_token(&p,driver,":",sizeof(driver)))
590 if (!next_token(&p,datafile,":",sizeof(datafile)))
594 * for the next tokens - which may be empty - I have
595 * to check for empty tokens first because the
596 * next_token function will skip all empty token
605 else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
608 /* language monitor */
614 else if (!next_token(&p,langmon,":",sizeof(langmon)))
617 /* default data type */
618 if (!next_token(&p,datatype,":",sizeof(datatype)))
621 PACKI(desc,"W",0x0400); /* don't know */
622 PACKS(desc,"z",drivername); /* long printer name */
623 PACKS(desc,"z",driver); /* Driverfile Name */
624 PACKS(desc,"z",datafile); /* Datafile name */
625 PACKS(desc,"z",langmon); /* language monitor */
628 fstrcpy(location, "\\\\");
629 fstrcat(location, global_myname);
630 fstrcat(location, "\\print$\\WIN40\\0");
631 PACKS(desc,"z",location); /* share to retrieve files */
635 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
637 PACKS(desc,"z",datatype); /* default data type */
638 PACKS(desc,"z",helpfile); /* helpfile name */
639 PACKS(desc,"z",driver); /* driver name */
641 DEBUG(3,("printerdriver:%s:\n",drivername));
642 DEBUG(3,("Driver:%s:\n",driver));
643 DEBUG(3,("Data File:%s:\n",datafile));
644 DEBUG(3,("Language Monitor:%s:\n",langmon));
646 DEBUG(3,("lp_driverlocation:%s:\n",location));
648 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
649 DEBUG(3,("Data Type:%s:\n",datatype));
650 DEBUG(3,("Help File:%s:\n",helpfile));
651 PACKI(desc,"N",count); /* number of files to copy */
653 for (i=0;i<count;i++)
655 /* no need to check return value here
656 * - it was already tested in
657 * get_printerdrivernumber */
658 next_token(&p,tok,",",sizeof(tok));
659 PACKS(desc,"z",tok); /* driver files to copy */
660 DEBUG(3,("file:%s:\n",tok));
663 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
664 SERVICE(snum),count));
666 desc->errcode=NERR_Success;
672 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
673 desc->errcode=NERR_notsupported;
676 file_lines_free(lines);
680 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
681 struct pack_desc* desc,
682 int count, print_queue_struct* queue,
683 print_status_struct* status)
688 PACKS(desc,"B13",SERVICE(snum));
693 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
696 PACKI(desc,"K",printq_status(status->status));
700 if (uLevel == 1 || uLevel == 2) {
701 PACKS(desc,"B",""); /* alignment */
702 PACKI(desc,"W",5); /* priority */
703 PACKI(desc,"W",0); /* start time */
704 PACKI(desc,"W",0); /* until time */
705 PACKS(desc,"z",""); /* pSepFile */
706 PACKS(desc,"z","lpd"); /* pPrProc */
707 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
708 PACKS(desc,"z",""); /* pParms */
710 PACKS(desc,"z","UNKNOWN PRINTER");
711 PACKI(desc,"W",LPSTAT_ERROR);
713 else if (!status || !status->message[0]) {
714 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
715 PACKI(desc,"W",LPSTAT_OK); /* status */
717 PACKS(desc,"z",status->message);
718 PACKI(desc,"W",printq_status(status->status)); /* status */
720 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
723 if (uLevel == 3 || uLevel == 4) {
726 PACKI(desc,"W",5); /* uPriority */
727 PACKI(desc,"W",0); /* uStarttime */
728 PACKI(desc,"W",0); /* uUntiltime */
729 PACKI(desc,"W",5); /* pad1 */
730 PACKS(desc,"z",""); /* pszSepFile */
731 PACKS(desc,"z","WinPrint"); /* pszPrProc */
732 PACKS(desc,"z",NULL); /* pszParms */
733 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
734 /* "don't ask" that it's done this way to fix corrupted
735 Win9X/ME printer comments. */
737 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
739 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
741 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
742 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
743 get_driver_name(snum,drivername);
744 PACKS(desc,"z",drivername); /* pszDriverName */
745 PackDriverData(desc); /* pDriverData */
748 if (uLevel == 2 || uLevel == 4) {
750 for (i=0;i<count;i++)
751 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
755 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
759 /* This function returns the number of files for a given driver */
760 static int get_printerdrivernumber(int snum)
771 * Check in the tdb *first* before checking the legacy
772 * files. This allows an NT upload to take precedence over
773 * the existing fileset. JRA.
775 * we need to lookup the driver name prior to making the call
776 * to get_a_printer_driver_9x_compatible() and not rely on the
777 * 'print driver' parameter --jerry
780 if ((get_driver_name(snum,drivername)) &&
781 (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True))
784 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
788 /* didn't find driver in tdb */
790 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
791 snum, drivername, lp_driverfile(snum)));
793 lines = file_lines_load(lp_driverfile(snum), NULL);
796 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
800 /* lookup the long printer driver name in the file description */
801 for (i=0;lines[i] && !ok;i++)
804 if (next_token(&p,tok,":",sizeof(tok)) &&
805 (strlen(drivername) == strlen(tok)) &&
806 (!strncmp(tok,drivername,strlen(drivername))))
818 if (*p++ == ':') i--;
821 DEBUG(3,("Can't determine number of printer driver files\n"));
825 /* count the number of files */
826 while (next_token(&p,tok,",",sizeof(tok)))
834 file_lines_free(lines);
839 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
840 uint16 vuid, char *param,char *data,
841 int mdrcnt,int mprcnt,
842 char **rdata,char **rparam,
843 int *rdata_len,int *rparam_len)
845 char *str1 = param+2;
846 char *str2 = skip_string(str1,1);
847 char *p = skip_string(str2,1);
853 struct pack_desc desc;
854 print_queue_struct *queue=NULL;
855 print_status_struct status;
858 memset((char *)&status,'\0',sizeof(status));
859 memset((char *)&desc,'\0',sizeof(desc));
861 p = skip_string(p,1);
865 /* remove any trailing username */
866 if ((p = strchr_m(QueueName,'%')))
869 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
871 /* check it's a supported varient */
872 if (!prefix_ok(str1,"zWrLh"))
874 if (!check_printq_info(&desc,uLevel,str2,str3)) {
876 * Patch from Scott Moomaw <scott@bridgewater.edu>
877 * to return the 'invalid info level' error if an
878 * unknown level was requested.
882 *rparam = REALLOC(*rparam,*rparam_len);
883 SSVALS(*rparam,0,ERRunknownlevel);
889 snum = lp_servicenumber(QueueName);
890 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
891 int pnum = lp_servicenumber(PRINTERS_NAME);
893 lp_add_printer(QueueName,pnum);
894 snum = lp_servicenumber(QueueName);
898 if (snum < 0 || !VALID_SNUM(snum))
902 count = get_printerdrivernumber(snum);
903 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
905 count = print_queue_status(snum, &queue,&status);
909 *rdata = REALLOC(*rdata,mdrcnt);
911 desc.buflen = mdrcnt;
914 * Don't return data but need to get correct length
915 * init_package will return wrong size if buflen=0
917 desc.buflen = getlen(desc.format);
918 desc.base = tmpdata = (char *) malloc (desc.buflen);
921 if (init_package(&desc,1,count)) {
922 desc.subcount = count;
923 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
926 *rdata_len = desc.usedlen;
929 * We must set the return code to ERRbuftoosmall
930 * in order to support lanman style printing with Win NT/2k
933 if (!mdrcnt && lp_disable_spoolss())
934 desc.errcode = ERRbuftoosmall;
936 *rdata_len = desc.usedlen;
938 *rparam = REALLOC(*rparam,*rparam_len);
939 SSVALS(*rparam,0,desc.errcode);
941 SSVAL(*rparam,4,desc.neededlen);
943 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
951 /****************************************************************************
952 View list of all print jobs on all queues.
953 ****************************************************************************/
955 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
956 int mdrcnt, int mprcnt,
957 char **rdata, char** rparam,
958 int *rdata_len, int *rparam_len)
960 char *param_format = param+2;
961 char *output_format1 = skip_string(param_format,1);
962 char *p = skip_string(output_format1,1);
963 int uLevel = SVAL(p,0);
964 char *output_format2 = p + 4;
965 int services = lp_numservices();
967 struct pack_desc desc;
968 print_queue_struct **queue = NULL;
969 print_status_struct *status = NULL;
970 int* subcntarr = NULL;
971 int queuecnt, subcnt=0, succnt=0;
973 memset((char *)&desc,'\0',sizeof(desc));
975 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
977 if (!prefix_ok(param_format,"WrLeh")) return False;
978 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
980 * Patch from Scott Moomaw <scott@bridgewater.edu>
981 * to return the 'invalid info level' error if an
982 * unknown level was requested.
986 *rparam = REALLOC(*rparam,*rparam_len);
987 SSVALS(*rparam,0,ERRunknownlevel);
994 for (i = 0; i < services; i++)
995 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
998 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
999 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1002 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1003 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
1004 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1007 memset(status,0,queuecnt*sizeof(print_status_struct));
1008 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
1009 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1014 for (i = 0; i < services; i++)
1015 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1016 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1017 subcnt += subcntarr[n];
1021 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1023 desc.buflen = mdrcnt;
1025 if (init_package(&desc,queuecnt,subcnt)) {
1028 for (i = 0; i < services; i++)
1029 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1030 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1032 if (desc.errcode == NERR_Success) succnt = n;
1036 SAFE_FREE(subcntarr);
1038 *rdata_len = desc.usedlen;
1040 *rparam = REALLOC(*rparam,*rparam_len);
1041 SSVALS(*rparam,0,desc.errcode);
1043 SSVAL(*rparam,4,succnt);
1044 SSVAL(*rparam,6,queuecnt);
1046 for (i = 0; i < queuecnt; i++) {
1047 if (queue) SAFE_FREE(queue[i]);
1056 /****************************************************************************
1057 get info level for a server list query
1058 ****************************************************************************/
1059 static BOOL check_server_info(int uLevel, char* id)
1063 if (strcmp(id,"B16") != 0) return False;
1066 if (strcmp(id,"B16BBDz") != 0) return False;
1074 struct srv_info_struct
1084 /*******************************************************************
1085 get server info lists from the files saved by nmbd. Return the
1087 ******************************************************************/
1088 static int get_server_info(uint32 servertype,
1089 struct srv_info_struct **servers,
1095 BOOL local_list_only;
1098 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1100 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1104 /* request for everything is code for request all servers */
1105 if (servertype == SV_TYPE_ALL)
1106 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1108 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1110 DEBUG(4,("Servertype search: %8x\n",servertype));
1112 for (i=0;lines[i];i++) {
1114 struct srv_info_struct *s;
1115 char *ptr = lines[i];
1118 if (!*ptr) continue;
1120 if (count == alloced) {
1121 struct srv_info_struct *ts;
1124 ts = (struct srv_info_struct *)
1125 Realloc(*servers,sizeof(**servers)*alloced);
1127 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1131 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1133 s = &(*servers)[count];
1135 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1136 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1137 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1138 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1139 /* this allows us to cope with an old nmbd */
1140 pstrcpy(s->domain,global_myworkgroup);
1143 if (sscanf(stype,"%X",&s->type) != 1) {
1144 DEBUG(4,("r:host file "));
1148 /* Filter the servers/domains we return based on what was asked for. */
1150 /* Check to see if we are being asked for a local list only. */
1151 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1152 DEBUG(4,("r: local list only"));
1156 /* doesn't match up: don't want it */
1157 if (!(servertype & s->type)) {
1158 DEBUG(4,("r:serv type "));
1162 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1163 (s->type & SV_TYPE_DOMAIN_ENUM))
1165 DEBUG(4,("s: dom mismatch "));
1169 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1174 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1175 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1179 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1180 s->name, s->type, s->comment, s->domain));
1182 s->server_added = True;
1187 DEBUG(4,("%20s %8x %25s %15s\n",
1188 s->name, s->type, s->comment, s->domain));
1192 file_lines_free(lines);
1197 /*******************************************************************
1198 fill in a server info structure
1199 ******************************************************************/
1200 static int fill_srv_info(struct srv_info_struct *service,
1201 int uLevel, char **buf, int *buflen,
1202 char **stringbuf, int *stringspace, char *baseaddr)
1211 case 0: struct_len = 16; break;
1212 case 1: struct_len = 26; break;
1222 len = strlen(service->comment)+1;
1226 if (buflen) *buflen = struct_len;
1227 if (stringspace) *stringspace = len;
1228 return struct_len + len;
1233 if (*buflen < struct_len) return -1;
1241 p2 = p + struct_len;
1242 l2 = *buflen - struct_len;
1244 if (!baseaddr) baseaddr = p;
1249 push_ascii(p,service->name, 15, STR_TERMINATE);
1253 push_ascii(p,service->name,15, STR_TERMINATE);
1254 SIVAL(p,18,service->type);
1255 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1256 len += CopyAndAdvance(&p2,service->comment,&l2);
1262 *buf = p + struct_len;
1263 *buflen -= struct_len;
1276 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1278 return(strcmp(s1->name,s2->name));
1281 /****************************************************************************
1282 view list of servers available (or possibly domains). The info is
1283 extracted from lists saved by nmbd on the local host
1284 ****************************************************************************/
1285 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1286 int mdrcnt, int mprcnt, char **rdata,
1287 char **rparam, int *rdata_len, int *rparam_len)
1289 char *str1 = param+2;
1290 char *str2 = skip_string(str1,1);
1291 char *p = skip_string(str2,1);
1292 int uLevel = SVAL(p,0);
1293 int buf_len = SVAL(p,2);
1294 uint32 servertype = IVAL(p,4);
1296 int data_len, fixed_len, string_len;
1297 int f_len = 0, s_len = 0;
1298 struct srv_info_struct *servers=NULL;
1299 int counted=0,total=0;
1302 BOOL domain_request;
1305 /* If someone sets all the bits they don't really mean to set
1306 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1309 if (servertype == SV_TYPE_ALL)
1310 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1312 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1313 any other bit (they may just set this bit on it's own) they
1314 want all the locally seen servers. However this bit can be
1315 set on its own so set the requested servers to be
1316 ALL - DOMAIN_ENUM. */
1318 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1319 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1321 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1322 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1326 if (!prefix_ok(str1,"WrLehD")) return False;
1327 if (!check_server_info(uLevel,str2)) return False;
1329 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1330 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1331 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1333 if (strcmp(str1, "WrLehDz") == 0) {
1334 pull_ascii_fstring(domain, p);
1336 fstrcpy(domain, global_myworkgroup);
1339 if (lp_browse_list())
1340 total = get_server_info(servertype,&servers,domain);
1342 data_len = fixed_len = string_len = 0;
1346 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1349 char *lastname=NULL;
1351 for (i=0;i<total;i++)
1353 struct srv_info_struct *s = &servers[i];
1354 if (lastname && strequal(lastname,s->name)) continue;
1356 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1357 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1358 s->name, s->type, s->comment, s->domain));
1360 if (data_len <= buf_len) {
1363 string_len += s_len;
1370 *rdata_len = fixed_len + string_len;
1371 *rdata = REALLOC(*rdata,*rdata_len);
1372 memset(*rdata,'\0',*rdata_len);
1374 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1380 char *lastname=NULL;
1381 int count2 = counted;
1382 for (i = 0; i < total && count2;i++)
1384 struct srv_info_struct *s = &servers[i];
1385 if (lastname && strequal(lastname,s->name)) continue;
1387 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1388 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1389 s->name, s->type, s->comment, s->domain));
1395 *rparam = REALLOC(*rparam,*rparam_len);
1396 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1398 SSVAL(*rparam,4,counted);
1399 SSVAL(*rparam,6,counted+missed);
1403 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1404 domain,uLevel,counted,counted+missed));
1409 /****************************************************************************
1410 command 0x34 - suspected of being a "Lookup Names" stub api
1411 ****************************************************************************/
1412 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1413 int mdrcnt, int mprcnt, char **rdata,
1414 char **rparam, int *rdata_len, int *rparam_len)
1416 char *str1 = param+2;
1417 char *str2 = skip_string(str1,1);
1418 char *p = skip_string(str2,1);
1419 int uLevel = SVAL(p,0);
1420 int buf_len = SVAL(p,2);
1424 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1425 str1, str2, p, uLevel, buf_len));
1427 if (!prefix_ok(str1,"zWrLeh")) return False;
1432 *rparam = REALLOC(*rparam,*rparam_len);
1434 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1436 SSVAL(*rparam,4,counted);
1437 SSVAL(*rparam,6,counted+missed);
1442 /****************************************************************************
1443 get info about a share
1444 ****************************************************************************/
1445 static BOOL check_share_info(int uLevel, char* id)
1449 if (strcmp(id,"B13") != 0) return False;
1452 if (strcmp(id,"B13BWz") != 0) return False;
1455 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1458 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1460 default: return False;
1465 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1466 char** buf, int* buflen,
1467 char** stringbuf, int* stringspace, char* baseaddr)
1476 case 0: struct_len = 13; break;
1477 case 1: struct_len = 20; break;
1478 case 2: struct_len = 40; break;
1479 case 91: struct_len = 68; break;
1487 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1488 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1489 if (buflen) *buflen = struct_len;
1490 if (stringspace) *stringspace = len;
1491 return struct_len + len;
1496 if ((*buflen) < struct_len) return -1;
1504 p2 = p + struct_len;
1505 l2 = (*buflen) - struct_len;
1507 if (!baseaddr) baseaddr = p;
1509 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1515 type = STYPE_DISKTREE;
1516 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1517 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1518 SSVAL(p,14,type); /* device type */
1519 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1520 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1525 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1526 SSVALS(p,22,-1); /* max uses */
1527 SSVAL(p,24,1); /* current uses */
1528 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1529 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1530 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1535 memset(p+40,0,SHPWLEN+2);
1547 (*buf) = p + struct_len;
1548 (*buflen) -= struct_len;
1550 (*stringspace) = l2;
1560 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1561 int mdrcnt,int mprcnt,
1562 char **rdata,char **rparam,
1563 int *rdata_len,int *rparam_len)
1565 char *str1 = param+2;
1566 char *str2 = skip_string(str1,1);
1567 char *netname = skip_string(str2,1);
1568 char *p = skip_string(netname,1);
1569 int uLevel = SVAL(p,0);
1570 int snum = find_service(netname);
1572 if (snum < 0) return False;
1574 /* check it's a supported varient */
1575 if (!prefix_ok(str1,"zWrLh")) return False;
1576 if (!check_share_info(uLevel,str2)) return False;
1578 *rdata = REALLOC(*rdata,mdrcnt);
1580 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1581 if (*rdata_len < 0) return False;
1584 *rparam = REALLOC(*rparam,*rparam_len);
1585 SSVAL(*rparam,0,NERR_Success);
1586 SSVAL(*rparam,2,0); /* converter word */
1587 SSVAL(*rparam,4,*rdata_len);
1592 /****************************************************************************
1593 view list of shares available
1594 ****************************************************************************/
1595 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1596 int mdrcnt,int mprcnt,
1597 char **rdata,char **rparam,
1598 int *rdata_len,int *rparam_len)
1600 char *str1 = param+2;
1601 char *str2 = skip_string(str1,1);
1602 char *p = skip_string(str2,1);
1603 int uLevel = SVAL(p,0);
1604 int buf_len = SVAL(p,2);
1606 int count=lp_numservices();
1607 int total=0,counted=0;
1608 BOOL missed = False;
1610 int data_len, fixed_len, string_len;
1611 int f_len = 0, s_len = 0;
1613 if (!prefix_ok(str1,"WrLeh")) return False;
1614 if (!check_share_info(uLevel,str2)) return False;
1616 data_len = fixed_len = string_len = 0;
1617 for (i=0;i<count;i++)
1618 if (lp_browseable(i) && lp_snum_ok(i))
1621 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1622 if (data_len <= buf_len)
1626 string_len += s_len;
1631 *rdata_len = fixed_len + string_len;
1632 *rdata = REALLOC(*rdata,*rdata_len);
1633 memset(*rdata,0,*rdata_len);
1635 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1639 for (i = 0; i < count;i++)
1640 if (lp_browseable(i) && lp_snum_ok(i))
1641 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1645 *rparam = REALLOC(*rparam,*rparam_len);
1646 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1648 SSVAL(*rparam,4,counted);
1649 SSVAL(*rparam,6,total);
1651 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1652 counted,total,uLevel,
1653 buf_len,*rdata_len,mdrcnt));
1657 /****************************************************************************
1659 ****************************************************************************/
1660 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1661 int mdrcnt,int mprcnt,
1662 char **rdata,char **rparam,
1663 int *rdata_len,int *rparam_len)
1665 char *str1 = param+2;
1666 char *str2 = skip_string(str1,1);
1667 char *p = skip_string(str2,1);
1668 int uLevel = SVAL(p,0);
1672 char *command, *cmdname;
1673 unsigned int offset;
1677 /* check it's a supported varient */
1678 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1679 if (!check_share_info(uLevel,str2)) return False;
1680 if (uLevel != 2) return False;
1682 pull_ascii_fstring(sharename,data);
1683 snum = find_service(sharename);
1684 if (snum >= 0) { /* already exists */
1689 /* only support disk share adds */
1690 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1692 offset = IVAL(data, 16);
1693 if (offset >= mdrcnt) {
1694 res = ERRinvalidparam;
1697 pull_ascii_fstring(comment, offset? (data+offset) : "");
1699 offset = IVAL(data, 26);
1700 if (offset >= mdrcnt) {
1701 res = ERRinvalidparam;
1704 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1706 string_replace(sharename, '"', ' ');
1707 string_replace(pathname, '"', ' ');
1708 string_replace(comment, '"', ' ');
1710 cmdname = lp_add_share_cmd();
1712 if (!cmdname || *cmdname == '\0') return False;
1714 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1715 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1718 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1719 if ((res = smbrun(command, NULL)) != 0) {
1720 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1726 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1728 } else return False;
1731 *rparam = REALLOC(*rparam,*rparam_len);
1732 SSVAL(*rparam,0,NERR_Success);
1733 SSVAL(*rparam,2,0); /* converter word */
1734 SSVAL(*rparam,4,*rdata_len);
1741 *rparam = REALLOC(*rparam,*rparam_len);
1743 SSVAL(*rparam,0,res);
1749 /****************************************************************************
1750 view list of groups available
1751 ****************************************************************************/
1752 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1753 int mdrcnt,int mprcnt,
1754 char **rdata,char **rparam,
1755 int *rdata_len,int *rparam_len)
1759 int resume_context, cli_buf_size;
1760 char *str1 = param+2;
1761 char *str2 = skip_string(str1,1);
1762 char *p = skip_string(str2,1);
1764 GROUP_MAP *group_list;
1767 if (strcmp(str1,"WrLeh") != 0)
1771 * W-> resume context (number of users to skip)
1772 * r -> return parameter pointer to receive buffer
1773 * L -> length of receive buffer
1774 * e -> return parameter number of entries
1775 * h -> return parameter total number of users
1777 if (strcmp("B21",str2) != 0)
1780 /* get list of domain groups SID_DOMAIN_GRP=2 */
1781 if(!enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) {
1782 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1786 resume_context = SVAL(p,0);
1787 cli_buf_size=SVAL(p+2,0);
1788 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1790 *rdata_len = cli_buf_size;
1791 *rdata = REALLOC(*rdata,*rdata_len);
1795 for(i=resume_context; i<num_entries; i++) {
1796 char* name=group_list[i].nt_name;
1797 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1798 /* truncate the name at 21 chars. */
1799 memcpy(p, name, 21);
1800 DEBUG(10,("adding entry %d group %s\n", i, p));
1803 /* set overflow error */
1804 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1810 *rdata_len = PTR_DIFF(p,*rdata);
1813 *rparam = REALLOC(*rparam,*rparam_len);
1815 SSVAL(*rparam, 0, errflags);
1816 SSVAL(*rparam, 2, 0); /* converter word */
1817 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1818 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1823 /*******************************************************************
1824 get groups that a user is a member of
1825 ******************************************************************/
1826 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1827 int mdrcnt,int mprcnt,
1828 char **rdata,char **rparam,
1829 int *rdata_len,int *rparam_len)
1831 char *str1 = param+2;
1832 char *str2 = skip_string(str1,1);
1833 char *UserName = skip_string(str2,1);
1834 char *p = skip_string(UserName,1);
1835 int uLevel = SVAL(p,0);
1840 *rparam = REALLOC(*rparam,*rparam_len);
1842 /* check it's a supported varient */
1843 if (!strcmp(str1,"zWrLeh"))
1853 if (strcmp(p2,str2) != 0)
1856 *rdata_len = mdrcnt + 1024;
1857 *rdata = REALLOC(*rdata,*rdata_len);
1859 SSVAL(*rparam,0,NERR_Success);
1860 SSVAL(*rparam,2,0); /* converter word */
1864 /* XXXX we need a real SAM database some day */
1865 pstrcpy(p,"Users"); p += 21; count++;
1866 pstrcpy(p,"Domain Users"); p += 21; count++;
1867 pstrcpy(p,"Guests"); p += 21; count++;
1868 pstrcpy(p,"Domain Guests"); p += 21; count++;
1870 *rdata_len = PTR_DIFF(p,*rdata);
1872 SSVAL(*rparam,4,count); /* is this right?? */
1873 SSVAL(*rparam,6,count); /* is this right?? */
1878 /*******************************************************************
1880 ******************************************************************/
1881 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1882 int mdrcnt,int mprcnt,
1883 char **rdata,char **rparam,
1884 int *rdata_len,int *rparam_len)
1886 SAM_ACCOUNT *pwd=NULL;
1890 int resume_context, cli_buf_size;
1892 char *str1 = param+2;
1893 char *str2 = skip_string(str1,1);
1894 char *p = skip_string(str2,1);
1896 if (strcmp(str1,"WrLeh") != 0)
1899 * W-> resume context (number of users to skip)
1900 * r -> return parameter pointer to receive buffer
1901 * L -> length of receive buffer
1902 * e -> return parameter number of entries
1903 * h -> return parameter total number of users
1906 resume_context = SVAL(p,0);
1907 cli_buf_size=SVAL(p+2,0);
1908 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1911 *rparam = REALLOC(*rparam,*rparam_len);
1913 /* check it's a supported varient */
1914 if (strcmp("B21",str2) != 0)
1917 *rdata_len = cli_buf_size;
1918 *rdata = REALLOC(*rdata,*rdata_len);
1922 /* to get user list enumerations for NetUserEnum in B21 format */
1925 /* Open the passgrp file - not for update. */
1927 if(!pdb_setsampwent(False)) {
1928 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1932 errflags=NERR_Success;
1934 while ( pdb_getsampwent(pwd) ) {
1935 const char *name=pdb_get_username(pwd);
1936 if ((name) && (*(name+strlen(name)-1)!='$')) {
1938 if(count_total>=resume_context) {
1939 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1941 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1945 /* set overflow error */
1946 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1959 *rdata_len = PTR_DIFF(p,*rdata);
1961 SSVAL(*rparam,0,errflags);
1962 SSVAL(*rparam,2,0); /* converter word */
1963 SSVAL(*rparam,4,count_sent); /* is this right?? */
1964 SSVAL(*rparam,6,count_total); /* is this right?? */
1971 /****************************************************************************
1972 get the time of day info
1973 ****************************************************************************/
1974 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1975 int mdrcnt,int mprcnt,
1976 char **rdata,char **rparam,
1977 int *rdata_len,int *rparam_len)
1981 *rparam = REALLOC(*rparam,*rparam_len);
1984 *rdata = REALLOC(*rdata,*rdata_len);
1986 SSVAL(*rparam,0,NERR_Success);
1987 SSVAL(*rparam,2,0); /* converter word */
1993 time_t unixdate = time(NULL);
1995 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1996 by NT in a "net time" operation,
1997 it seems to ignore the one below */
1999 /* the client expects to get localtime, not GMT, in this bit
2000 (I think, this needs testing) */
2001 t = LocalTime(&unixdate);
2003 SIVAL(p,4,0); /* msecs ? */
2004 SCVAL(p,8,t->tm_hour);
2005 SCVAL(p,9,t->tm_min);
2006 SCVAL(p,10,t->tm_sec);
2007 SCVAL(p,11,0); /* hundredths of seconds */
2008 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
2009 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2010 SCVAL(p,16,t->tm_mday);
2011 SCVAL(p,17,t->tm_mon + 1);
2012 SSVAL(p,18,1900+t->tm_year);
2013 SCVAL(p,20,t->tm_wday);
2020 /****************************************************************************
2021 Set the user password.
2022 *****************************************************************************/
2024 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2025 int mdrcnt,int mprcnt,
2026 char **rdata,char **rparam,
2027 int *rdata_len,int *rparam_len)
2029 char *p = skip_string(param+2,2);
2031 fstring pass1,pass2;
2033 pull_ascii_fstring(user,p);
2035 p = skip_string(p,1);
2037 memset(pass1,'\0',sizeof(pass1));
2038 memset(pass2,'\0',sizeof(pass2));
2040 memcpy(pass2,p+16,16);
2043 *rparam = REALLOC(*rparam,*rparam_len);
2047 SSVAL(*rparam,0,NERR_badpass);
2048 SSVAL(*rparam,2,0); /* converter word */
2050 DEBUG(3,("Set password for <%s>\n",user));
2053 * Attempt to verify the old password against smbpasswd entries
2054 * Win98 clients send old and new password in plaintext for this call.
2058 auth_serversupplied_info *server_info = NULL;
2059 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2060 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2063 * If unix password sync was requested, attempt to change
2064 * the /etc/passwd database first. Return failure if this cannot
2067 * This occurs before the oem change, becouse we don't want to
2068 * update it if chgpasswd failed.
2070 * Conditional on lp_unix_password_sync() becouse we don't want
2071 * to touch the unix db unless we have admin permission.
2074 if(lp_unix_password_sync() && IS_SAM_UNIX_USER(server_info->sam_account)
2075 && !chgpasswd(pdb_get_username(server_info->sam_account),
2076 pass1,pass2,False)) {
2077 SSVAL(*rparam,0,NERR_badpass);
2080 if (change_oem_password(server_info->sam_account,pass2))
2082 SSVAL(*rparam,0,NERR_Success);
2085 free_server_info(&server_info);
2087 data_blob_clear_free(&password);
2091 * If the plaintext change failed, attempt
2092 * the old encrypted method. NT will generate this
2093 * after trying the samr method. Note that this
2094 * method is done as a last resort as this
2095 * password change method loses the NT password hash
2096 * and cannot change the UNIX password as no plaintext
2100 if(SVAL(*rparam,0) != NERR_Success)
2102 SAM_ACCOUNT *hnd = NULL;
2104 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
2105 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
2107 SSVAL(*rparam,0,NERR_Success);
2113 memset((char *)pass1,'\0',sizeof(fstring));
2114 memset((char *)pass2,'\0',sizeof(fstring));
2119 /****************************************************************************
2120 Set the user password (SamOEM version - gets plaintext).
2121 ****************************************************************************/
2123 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2124 int mdrcnt,int mprcnt,
2125 char **rdata,char **rparam,
2126 int *rdata_len,int *rparam_len)
2129 char *p = param + 2;
2131 *rparam = REALLOC(*rparam,*rparam_len);
2135 SSVAL(*rparam,0,NERR_badpass);
2138 * Check the parameter definition is correct.
2140 if(!strequal(param + 2, "zsT")) {
2141 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2144 p = skip_string(p, 1);
2146 if(!strequal(p, "B516B16")) {
2147 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2150 p = skip_string(p,1);
2152 p += pull_ascii_fstring(user,p);
2154 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2157 * Pass the user through the NT -> unix user mapping
2161 (void)map_username(user);
2163 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
2165 SSVAL(*rparam,0,NERR_Success);
2171 /****************************************************************************
2174 ****************************************************************************/
2175 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2176 int mdrcnt,int mprcnt,
2177 char **rdata,char **rparam,
2178 int *rdata_len,int *rparam_len)
2180 int function = SVAL(param,0);
2181 char *str1 = param+2;
2182 char *str2 = skip_string(str1,1);
2183 char *p = skip_string(str2,1);
2185 extern struct current_user current_user;
2186 WERROR werr = WERR_OK;
2190 /* check it's a supported varient */
2191 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2195 *rparam = REALLOC(*rparam,*rparam_len);
2198 if (!print_job_exists(jobid)) {
2199 errcode = NERR_JobNotFound;
2203 errcode = NERR_notsupported;
2206 case 81: /* delete */
2207 if (print_job_delete(¤t_user, jobid, &werr))
2208 errcode = NERR_Success;
2210 case 82: /* pause */
2211 if (print_job_pause(¤t_user, jobid, &werr))
2212 errcode = NERR_Success;
2214 case 83: /* resume */
2215 if (print_job_resume(¤t_user, jobid, &werr))
2216 errcode = NERR_Success;
2220 if (!W_ERROR_IS_OK(werr))
2221 errcode = W_ERROR_V(werr);
2224 SSVAL(*rparam,0,errcode);
2225 SSVAL(*rparam,2,0); /* converter word */
2230 /****************************************************************************
2231 Purge a print queue - or pause or resume it.
2232 ****************************************************************************/
2233 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2234 int mdrcnt,int mprcnt,
2235 char **rdata,char **rparam,
2236 int *rdata_len,int *rparam_len)
2238 int function = SVAL(param,0);
2239 char *str1 = param+2;
2240 char *str2 = skip_string(str1,1);
2241 char *QueueName = skip_string(str2,1);
2242 int errcode = NERR_notsupported;
2244 WERROR werr = WERR_OK;
2245 extern struct current_user current_user;
2247 /* check it's a supported varient */
2248 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2252 *rparam = REALLOC(*rparam,*rparam_len);
2255 snum = print_queue_snum(QueueName);
2258 errcode = NERR_JobNotFound;
2263 case 74: /* Pause queue */
2264 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2266 case 75: /* Resume queue */
2267 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2269 case 103: /* Purge */
2270 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2274 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2277 SSVAL(*rparam,0,errcode);
2278 SSVAL(*rparam,2,0); /* converter word */
2284 /****************************************************************************
2285 set the property of a print job (undocumented?)
2286 ? function = 0xb -> set name of print job
2287 ? function = 0x6 -> move print job up/down
2288 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2289 or <WWsTP> <WB21BB16B10zWWzDDz>
2290 ****************************************************************************/
2291 static int check_printjob_info(struct pack_desc* desc,
2292 int uLevel, char* id)
2294 desc->subformat = NULL;
2296 case 0: desc->format = "W"; break;
2297 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2298 case 2: desc->format = "WWzWWDDzz"; break;
2299 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2300 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2301 default: return False;
2303 if (strcmp(desc->format,id) != 0) return False;
2307 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2308 int mdrcnt,int mprcnt,
2309 char **rdata,char **rparam,
2310 int *rdata_len,int *rparam_len)
2312 struct pack_desc desc;
2313 char *str1 = param+2;
2314 char *str2 = skip_string(str1,1);
2315 char *p = skip_string(str2,1);
2317 int uLevel = SVAL(p,2);
2318 int function = SVAL(p,4);
2323 *rparam = REALLOC(*rparam,*rparam_len);
2327 /* check it's a supported varient */
2328 if ((strcmp(str1,"WWsTP")) ||
2329 (!check_printjob_info(&desc,uLevel,str2)))
2332 if (!print_job_exists(jobid)) {
2333 errcode=NERR_JobNotFound;
2337 errcode = NERR_notsupported;
2341 /* change job place in the queue,
2342 data gives the new place */
2343 place = SVAL(data,0);
2344 if (print_job_set_place(jobid, place)) {
2345 errcode=NERR_Success;
2350 /* change print job name, data gives the name */
2351 if (print_job_set_name(jobid, data)) {
2352 errcode=NERR_Success;
2361 SSVALS(*rparam,0,errcode);
2362 SSVAL(*rparam,2,0); /* converter word */
2368 /****************************************************************************
2369 get info about the server
2370 ****************************************************************************/
2371 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2372 int mdrcnt,int mprcnt,
2373 char **rdata,char **rparam,
2374 int *rdata_len,int *rparam_len)
2376 char *str1 = param+2;
2377 char *str2 = skip_string(str1,1);
2378 char *p = skip_string(str2,1);
2379 int uLevel = SVAL(p,0);
2383 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2385 /* check it's a supported varient */
2386 if (!prefix_ok(str1,"WrLh")) return False;
2389 if (strcmp(str2,"B16") != 0) return False;
2393 if (strcmp(str2,"B16BBDz") != 0) return False;
2397 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2402 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2407 if (strcmp(str2,"DN") != 0) return False;
2411 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2414 default: return False;
2417 *rdata_len = mdrcnt;
2418 *rdata = REALLOC(*rdata,*rdata_len);
2421 p2 = p + struct_len;
2423 srvstr_push(NULL, p,local_machine,16,
2424 STR_ASCII|STR_UPPER|STR_TERMINATE);
2429 struct srv_info_struct *servers=NULL;
2432 uint32 servertype= lp_default_server_announce();
2434 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2436 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2437 for (i=0;i<count;i++)
2438 if (strequal(servers[i].name,local_machine))
2440 servertype = servers[i].type;
2441 pstrcpy(comment,servers[i].comment);
2446 SCVAL(p,0,lp_major_announce_version());
2447 SCVAL(p,1,lp_minor_announce_version());
2448 SIVAL(p,2,servertype);
2450 if (mdrcnt == struct_len) {
2453 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2454 standard_sub_conn(conn,comment,sizeof(comment));
2455 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2456 p2 = skip_string(p2,1);
2461 return False; /* not yet implemented */
2464 *rdata_len = PTR_DIFF(p2,*rdata);
2467 *rparam = REALLOC(*rparam,*rparam_len);
2468 SSVAL(*rparam,0,NERR_Success);
2469 SSVAL(*rparam,2,0); /* converter word */
2470 SSVAL(*rparam,4,*rdata_len);
2476 /****************************************************************************
2477 get info about the server
2478 ****************************************************************************/
2479 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2480 int mdrcnt,int mprcnt,
2481 char **rdata,char **rparam,
2482 int *rdata_len,int *rparam_len)
2484 char *str1 = param+2;
2485 char *str2 = skip_string(str1,1);
2486 char *p = skip_string(str2,1);
2488 extern userdom_struct current_user_info;
2489 int level = SVAL(p,0);
2491 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2494 *rparam = REALLOC(*rparam,*rparam_len);
2496 /* check it's a supported varient */
2497 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2500 *rdata_len = mdrcnt + 1024;
2501 *rdata = REALLOC(*rdata,*rdata_len);
2503 SSVAL(*rparam,0,NERR_Success);
2504 SSVAL(*rparam,2,0); /* converter word */
2510 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2511 pstrcpy(p2,local_machine);
2513 p2 = skip_string(p2,1);
2516 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2517 pstrcpy(p2,current_user_info.smb_name);
2518 p2 = skip_string(p2,1);
2521 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2522 pstrcpy(p2,global_myworkgroup);
2524 p2 = skip_string(p2,1);
2527 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2528 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2531 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2532 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2533 p2 = skip_string(p2,1);
2536 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2538 p2 = skip_string(p2,1);
2541 *rdata_len = PTR_DIFF(p2,*rdata);
2543 SSVAL(*rparam,4,*rdata_len);
2548 /****************************************************************************
2549 get info about a user
2551 struct user_info_11 {
2552 char usri11_name[21]; 0-20
2554 char *usri11_comment; 22-25
2555 char *usri11_usr_comment; 26-29
2556 unsigned short usri11_priv; 30-31
2557 unsigned long usri11_auth_flags; 32-35
2558 long usri11_password_age; 36-39
2559 char *usri11_homedir; 40-43
2560 char *usri11_parms; 44-47
2561 long usri11_last_logon; 48-51
2562 long usri11_last_logoff; 52-55
2563 unsigned short usri11_bad_pw_count; 56-57
2564 unsigned short usri11_num_logons; 58-59
2565 char *usri11_logon_server; 60-63
2566 unsigned short usri11_country_code; 64-65
2567 char *usri11_workstations; 66-69
2568 unsigned long usri11_max_storage; 70-73
2569 unsigned short usri11_units_per_week; 74-75
2570 unsigned char *usri11_logon_hours; 76-79
2571 unsigned short usri11_code_page; 80-81
2576 usri11_name specifies the user name for which information is retireved
2578 usri11_pad aligns the next data structure element to a word boundary
2580 usri11_comment is a null terminated ASCII comment
2582 usri11_user_comment is a null terminated ASCII comment about the user
2584 usri11_priv specifies the level of the privilege assigned to the user.
2585 The possible values are:
2587 Name Value Description
2588 USER_PRIV_GUEST 0 Guest privilege
2589 USER_PRIV_USER 1 User privilege
2590 USER_PRV_ADMIN 2 Administrator privilege
2592 usri11_auth_flags specifies the account operator privileges. The
2593 possible values are:
2595 Name Value Description
2596 AF_OP_PRINT 0 Print operator
2599 Leach, Naik [Page 28]
2603 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2606 AF_OP_COMM 1 Communications operator
2607 AF_OP_SERVER 2 Server operator
2608 AF_OP_ACCOUNTS 3 Accounts operator
2611 usri11_password_age specifies how many seconds have elapsed since the
2612 password was last changed.
2614 usri11_home_dir points to a null terminated ASCII string that contains
2615 the path name of the user's home directory.
2617 usri11_parms points to a null terminated ASCII string that is set
2618 aside for use by applications.
2620 usri11_last_logon specifies the time when the user last logged on.
2621 This value is stored as the number of seconds elapsed since
2622 00:00:00, January 1, 1970.
2624 usri11_last_logoff specifies the time when the user last logged off.
2625 This value is stored as the number of seconds elapsed since
2626 00:00:00, January 1, 1970. A value of 0 means the last logoff
2629 usri11_bad_pw_count specifies the number of incorrect passwords
2630 entered since the last successful logon.
2632 usri11_log1_num_logons specifies the number of times this user has
2633 logged on. A value of -1 means the number of logons is unknown.
2635 usri11_logon_server points to a null terminated ASCII string that
2636 contains the name of the server to which logon requests are sent.
2637 A null string indicates logon requests should be sent to the
2640 usri11_country_code specifies the country code for the user's language
2643 usri11_workstations points to a null terminated ASCII string that
2644 contains the names of workstations the user may log on from.
2645 There may be up to 8 workstations, with the names separated by
2646 commas. A null strings indicates there are no restrictions.
2648 usri11_max_storage specifies the maximum amount of disk space the user
2649 can occupy. A value of 0xffffffff indicates there are no
2652 usri11_units_per_week specifies the equal number of time units into
2653 which a week is divided. This value must be equal to 168.
2655 usri11_logon_hours points to a 21 byte (168 bits) string that
2656 specifies the time during which the user can log on. Each bit
2657 represents one unique hour in a week. The first bit (bit 0, word
2658 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2662 Leach, Naik [Page 29]
2666 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2669 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2670 are no restrictions.
2672 usri11_code_page specifies the code page for the user's language of
2675 All of the pointers in this data structure need to be treated
2676 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2677 to be ignored. The converter word returned in the parameters section
2678 needs to be subtracted from the lower 16 bits to calculate an offset
2679 into the return buffer where this ASCII string resides.
2681 There is no auxiliary data in the response.
2683 ****************************************************************************/
2685 #define usri11_name 0
2686 #define usri11_pad 21
2687 #define usri11_comment 22
2688 #define usri11_usr_comment 26
2689 #define usri11_full_name 30
2690 #define usri11_priv 34
2691 #define usri11_auth_flags 36
2692 #define usri11_password_age 40
2693 #define usri11_homedir 44
2694 #define usri11_parms 48
2695 #define usri11_last_logon 52
2696 #define usri11_last_logoff 56
2697 #define usri11_bad_pw_count 60
2698 #define usri11_num_logons 62
2699 #define usri11_logon_server 64
2700 #define usri11_country_code 68
2701 #define usri11_workstations 70
2702 #define usri11_max_storage 74
2703 #define usri11_units_per_week 78
2704 #define usri11_logon_hours 80
2705 #define usri11_code_page 84
2706 #define usri11_end 86
2708 #define USER_PRIV_GUEST 0
2709 #define USER_PRIV_USER 1
2710 #define USER_PRIV_ADMIN 2
2712 #define AF_OP_PRINT 0
2713 #define AF_OP_COMM 1
2714 #define AF_OP_SERVER 2
2715 #define AF_OP_ACCOUNTS 3
2718 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2719 int mdrcnt,int mprcnt,
2720 char **rdata,char **rparam,
2721 int *rdata_len,int *rparam_len)
2723 char *str1 = param+2;
2724 char *str2 = skip_string(str1,1);
2725 char *UserName = skip_string(str2,1);
2726 char *p = skip_string(UserName,1);
2727 int uLevel = SVAL(p,0);
2730 /* get NIS home of a previously validated user - simeon */
2731 /* With share level security vuid will always be zero.
2732 Don't depend on vuser being non-null !!. JRA */
2733 user_struct *vuser = get_valid_user_struct(vuid);
2735 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2736 vuser->user.unix_name));
2739 *rparam = REALLOC(*rparam,*rparam_len);
2741 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2743 /* check it's a supported variant */
2744 if (strcmp(str1,"zWrLh") != 0) return False;
2747 case 0: p2 = "B21"; break;
2748 case 1: p2 = "B21BB16DWzzWz"; break;
2749 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2750 case 10: p2 = "B21Bzzz"; break;
2751 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2752 default: return False;
2755 if (strcmp(p2,str2) != 0) return False;
2757 *rdata_len = mdrcnt + 1024;
2758 *rdata = REALLOC(*rdata,*rdata_len);
2760 SSVAL(*rparam,0,NERR_Success);
2761 SSVAL(*rparam,2,0); /* converter word */
2764 p2 = p + usri11_end;
2767 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2771 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2776 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2777 pstrcpy(p2,"Comment");
2778 p2 = skip_string(p2,1);
2780 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2781 pstrcpy(p2,"UserComment");
2782 p2 = skip_string(p2,1);
2784 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2785 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2786 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2787 p2 = skip_string(p2,1);
2790 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2792 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2793 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2794 SIVALS(p,usri11_password_age,-1); /* password age */
2795 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2796 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2797 p2 = skip_string(p2,1);
2798 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2800 p2 = skip_string(p2,1);
2801 SIVAL(p,usri11_last_logon,0); /* last logon */
2802 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2803 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2804 SSVALS(p,usri11_num_logons,-1); /* num logons */
2805 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2806 pstrcpy(p2,"\\\\*");
2807 p2 = skip_string(p2,1);
2808 SSVAL(p,usri11_country_code,0); /* country code */
2810 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2812 p2 = skip_string(p2,1);
2814 SIVALS(p,usri11_max_storage,-1); /* max storage */
2815 SSVAL(p,usri11_units_per_week,168); /* units per week */
2816 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2818 /* a simple way to get logon hours at all times. */
2820 SCVAL(p2,21,0); /* fix zero termination */
2821 p2 = skip_string(p2,1);
2823 SSVAL(p,usri11_code_page,0); /* code page */
2825 if (uLevel == 1 || uLevel == 2)
2827 memset(p+22,' ',16); /* password */
2828 SIVALS(p,38,-1); /* password age */
2830 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2831 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2832 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2833 p2 = skip_string(p2,1);
2834 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2836 SSVAL(p,52,0); /* flags */
2837 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2838 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2839 p2 = skip_string(p2,1);
2842 SIVAL(p,60,0); /* auth_flags */
2843 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2844 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2845 p2 = skip_string(p2,1);
2846 SIVAL(p,68,0); /* urs_comment */
2847 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2849 p2 = skip_string(p2,1);
2850 SIVAL(p,76,0); /* workstations */
2851 SIVAL(p,80,0); /* last_logon */
2852 SIVAL(p,84,0); /* last_logoff */
2853 SIVALS(p,88,-1); /* acct_expires */
2854 SIVALS(p,92,-1); /* max_storage */
2855 SSVAL(p,96,168); /* units_per_week */
2856 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2859 SSVALS(p,102,-1); /* bad_pw_count */
2860 SSVALS(p,104,-1); /* num_logons */
2861 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2862 pstrcpy(p2,"\\\\%L");
2863 standard_sub_conn(conn, p2,0);
2864 p2 = skip_string(p2,1);
2865 SSVAL(p,110,49); /* country_code */
2866 SSVAL(p,112,860); /* code page */
2870 *rdata_len = PTR_DIFF(p2,*rdata);
2872 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2877 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2878 int mdrcnt,int mprcnt,
2879 char **rdata,char **rparam,
2880 int *rdata_len,int *rparam_len)
2882 char *str1 = param+2;
2883 char *str2 = skip_string(str1,1);
2884 char *p = skip_string(str2,1);
2886 struct pack_desc desc;
2888 /* With share level security vuid will always be zero.
2889 Don't depend on vuser being non-null !!. JRA */
2890 user_struct *vuser = get_valid_user_struct(vuid);
2892 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2893 vuser->user.unix_name));
2898 memset((char *)&desc,'\0',sizeof(desc));
2900 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2902 /* check it's a supported varient */
2903 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2904 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2905 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2907 desc.buflen = mdrcnt;
2908 desc.subformat = NULL;
2911 if (init_package(&desc,1,0))
2913 PACKI(&desc,"W",0); /* code */
2914 PACKS(&desc,"B21",name); /* eff. name */
2915 PACKS(&desc,"B",""); /* pad */
2917 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2918 PACKI(&desc,"D",0); /* auth flags XXX */
2919 PACKI(&desc,"W",0); /* num logons */
2920 PACKI(&desc,"W",0); /* bad pw count */
2921 PACKI(&desc,"D",0); /* last logon */
2922 PACKI(&desc,"D",-1); /* last logoff */
2923 PACKI(&desc,"D",-1); /* logoff time */
2924 PACKI(&desc,"D",-1); /* kickoff time */
2925 PACKI(&desc,"D",0); /* password age */
2926 PACKI(&desc,"D",0); /* password can change */
2927 PACKI(&desc,"D",-1); /* password must change */
2930 fstrcpy(mypath,"\\\\");
2931 fstrcat(mypath,local_machine);
2933 PACKS(&desc,"z",mypath); /* computer */
2935 PACKS(&desc,"z",global_myworkgroup);/* domain */
2937 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2939 PACKI(&desc,"D",0x00000000); /* reserved */
2942 *rdata_len = desc.usedlen;
2944 *rparam = REALLOC(*rparam,*rparam_len);
2945 SSVALS(*rparam,0,desc.errcode);
2947 SSVAL(*rparam,4,desc.neededlen);
2949 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2954 /****************************************************************************
2955 api_WAccessGetUserPerms
2956 ****************************************************************************/
2957 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2958 int mdrcnt,int mprcnt,
2959 char **rdata,char **rparam,
2960 int *rdata_len,int *rparam_len)
2962 char *str1 = param+2;
2963 char *str2 = skip_string(str1,1);
2964 char *user = skip_string(str2,1);
2965 char *resource = skip_string(user,1);
2967 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2969 /* check it's a supported varient */
2970 if (strcmp(str1,"zzh") != 0) return False;
2971 if (strcmp(str2,"") != 0) return False;
2974 *rparam = REALLOC(*rparam,*rparam_len);
2975 SSVALS(*rparam,0,0); /* errorcode */
2976 SSVAL(*rparam,2,0); /* converter word */
2977 SSVAL(*rparam,4,0x7f); /* permission flags */
2982 /****************************************************************************
2983 api_WPrintJobEnumerate
2984 ****************************************************************************/
2985 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2986 int mdrcnt,int mprcnt,
2987 char **rdata,char **rparam,
2988 int *rdata_len,int *rparam_len)
2990 char *str1 = param+2;
2991 char *str2 = skip_string(str1,1);
2992 char *p = skip_string(str2,1);
2998 struct pack_desc desc;
2999 print_queue_struct *queue=NULL;
3000 print_status_struct status;
3005 memset((char *)&desc,'\0',sizeof(desc));
3006 memset((char *)&status,'\0',sizeof(status));
3008 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3010 /* check it's a supported varient */
3011 if (strcmp(str1,"WWrLh") != 0) return False;
3012 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3015 snum = print_job_snum(job);
3017 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3019 count = print_queue_status(snum,&queue,&status);
3020 for (i = 0; i < count; i++) {
3021 if (queue[i].job == job) break;
3025 *rdata = REALLOC(*rdata,mdrcnt);
3027 desc.buflen = mdrcnt;
3030 * Don't return data but need to get correct length
3031 * init_package will return wrong size if buflen=0
3033 desc.buflen = getlen(desc.format);
3034 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3037 if (init_package(&desc,1,0)) {
3039 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3040 *rdata_len = desc.usedlen;
3043 desc.errcode = NERR_JobNotFound;
3049 *rparam = REALLOC(*rparam,*rparam_len);
3050 SSVALS(*rparam,0,desc.errcode);
3052 SSVAL(*rparam,4,desc.neededlen);
3057 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3061 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3062 int mdrcnt,int mprcnt,
3063 char **rdata,char **rparam,
3064 int *rdata_len,int *rparam_len)
3066 char *str1 = param+2;
3067 char *str2 = skip_string(str1,1);
3068 char *p = skip_string(str2,1);
3074 struct pack_desc desc;
3075 print_queue_struct *queue=NULL;
3076 print_status_struct status;
3078 memset((char *)&desc,'\0',sizeof(desc));
3079 memset((char *)&status,'\0',sizeof(status));
3081 p = skip_string(p,1);
3084 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3086 /* check it's a supported variant */
3087 if (strcmp(str1,"zWrLeh") != 0) return False;
3088 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3089 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3091 snum = lp_servicenumber(name);
3092 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3093 int pnum = lp_servicenumber(PRINTERS_NAME);
3095 lp_add_printer(name,pnum);
3096 snum = lp_servicenumber(name);
3100 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3102 count = print_queue_status(snum,&queue,&status);
3103 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3105 desc.buflen = mdrcnt;
3107 if (init_package(&desc,count,0)) {
3109 for (i = 0; i < count; i++) {
3110 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3111 if (desc.errcode == NERR_Success) succnt = i+1;
3115 *rdata_len = desc.usedlen;
3118 *rparam = REALLOC(*rparam,*rparam_len);
3119 SSVALS(*rparam,0,desc.errcode);
3121 SSVAL(*rparam,4,succnt);
3122 SSVAL(*rparam,6,count);
3126 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3130 static int check_printdest_info(struct pack_desc* desc,
3131 int uLevel, char* id)
3133 desc->subformat = NULL;
3135 case 0: desc->format = "B9"; break;
3136 case 1: desc->format = "B9B21WWzW"; break;
3137 case 2: desc->format = "z"; break;
3138 case 3: desc->format = "zzzWWzzzWW"; break;
3139 default: return False;
3141 if (strcmp(desc->format,id) != 0) return False;
3145 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3146 struct pack_desc* desc)
3149 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3150 buf[sizeof(buf)-1] = 0;
3153 PACKS(desc,"B9",buf); /* szName */
3155 PACKS(desc,"B21",""); /* szUserName */
3156 PACKI(desc,"W",0); /* uJobId */
3157 PACKI(desc,"W",0); /* fsStatus */
3158 PACKS(desc,"z",""); /* pszStatus */
3159 PACKI(desc,"W",0); /* time */
3162 if (uLevel == 2 || uLevel == 3) {
3163 PACKS(desc,"z",buf); /* pszPrinterName */
3165 PACKS(desc,"z",""); /* pszUserName */
3166 PACKS(desc,"z",""); /* pszLogAddr */
3167 PACKI(desc,"W",0); /* uJobId */
3168 PACKI(desc,"W",0); /* fsStatus */
3169 PACKS(desc,"z",""); /* pszStatus */
3170 PACKS(desc,"z",""); /* pszComment */
3171 PACKS(desc,"z","NULL"); /* pszDrivers */
3172 PACKI(desc,"W",0); /* time */
3173 PACKI(desc,"W",0); /* pad1 */
3178 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3179 int mdrcnt,int mprcnt,
3180 char **rdata,char **rparam,
3181 int *rdata_len,int *rparam_len)
3183 char *str1 = param+2;
3184 char *str2 = skip_string(str1,1);
3185 char *p = skip_string(str2,1);
3186 char* PrinterName = p;
3188 struct pack_desc desc;
3192 memset((char *)&desc,'\0',sizeof(desc));
3194 p = skip_string(p,1);
3197 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3199 /* check it's a supported varient */
3200 if (strcmp(str1,"zWrLh") != 0) return False;
3201 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3203 snum = lp_servicenumber(PrinterName);
3204 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3205 int pnum = lp_servicenumber(PRINTERS_NAME);
3207 lp_add_printer(PrinterName,pnum);
3208 snum = lp_servicenumber(PrinterName);
3214 desc.errcode = NERR_DestNotFound;
3219 *rdata = REALLOC(*rdata,mdrcnt);
3221 desc.buflen = mdrcnt;
3224 * Don't return data but need to get correct length
3225 * init_package will return wrong size if buflen=0
3227 desc.buflen = getlen(desc.format);
3228 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3230 if (init_package(&desc,1,0)) {
3231 fill_printdest_info(conn,snum,uLevel,&desc);
3233 *rdata_len = desc.usedlen;
3237 *rparam = REALLOC(*rparam,*rparam_len);
3238 SSVALS(*rparam,0,desc.errcode);
3240 SSVAL(*rparam,4,desc.neededlen);
3242 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3247 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3248 int mdrcnt,int mprcnt,
3249 char **rdata,char **rparam,
3250 int *rdata_len,int *rparam_len)
3252 char *str1 = param+2;
3253 char *str2 = skip_string(str1,1);
3254 char *p = skip_string(str2,1);
3258 struct pack_desc desc;
3259 int services = lp_numservices();
3261 memset((char *)&desc,'\0',sizeof(desc));
3265 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3267 /* check it's a supported varient */
3268 if (strcmp(str1,"WrLeh") != 0) return False;
3269 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3272 for (i = 0; i < services; i++)
3273 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3276 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3278 desc.buflen = mdrcnt;
3279 if (init_package(&desc,queuecnt,0)) {
3282 for (i = 0; i < services; i++) {
3283 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3284 fill_printdest_info(conn,i,uLevel,&desc);
3286 if (desc.errcode == NERR_Success) succnt = n;
3291 *rdata_len = desc.usedlen;
3294 *rparam = REALLOC(*rparam,*rparam_len);
3295 SSVALS(*rparam,0,desc.errcode);
3297 SSVAL(*rparam,4,succnt);
3298 SSVAL(*rparam,6,queuecnt);
3300 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3304 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3305 int mdrcnt,int mprcnt,
3306 char **rdata,char **rparam,
3307 int *rdata_len,int *rparam_len)
3309 char *str1 = param+2;
3310 char *str2 = skip_string(str1,1);
3311 char *p = skip_string(str2,1);
3314 struct pack_desc desc;
3316 memset((char *)&desc,'\0',sizeof(desc));
3320 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3322 /* check it's a supported varient */
3323 if (strcmp(str1,"WrLeh") != 0) return False;
3324 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3326 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3328 desc.buflen = mdrcnt;
3329 if (init_package(&desc,1,0)) {
3330 PACKS(&desc,"B41","NULL");
3333 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3335 *rdata_len = desc.usedlen;
3338 *rparam = REALLOC(*rparam,*rparam_len);
3339 SSVALS(*rparam,0,desc.errcode);
3341 SSVAL(*rparam,4,succnt);
3344 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3348 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3349 int mdrcnt,int mprcnt,
3350 char **rdata,char **rparam,
3351 int *rdata_len,int *rparam_len)
3353 char *str1 = param+2;
3354 char *str2 = skip_string(str1,1);
3355 char *p = skip_string(str2,1);
3358 struct pack_desc desc;
3360 memset((char *)&desc,'\0',sizeof(desc));
3364 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3366 /* check it's a supported varient */
3367 if (strcmp(str1,"WrLeh") != 0) return False;
3368 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3370 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3372 desc.buflen = mdrcnt;
3374 if (init_package(&desc,1,0)) {
3375 PACKS(&desc,"B13","lpd");
3378 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3380 *rdata_len = desc.usedlen;
3383 *rparam = REALLOC(*rparam,*rparam_len);
3384 SSVALS(*rparam,0,desc.errcode);
3386 SSVAL(*rparam,4,succnt);
3389 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3393 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3394 int mdrcnt,int mprcnt,
3395 char **rdata,char **rparam,
3396 int *rdata_len,int *rparam_len)
3398 char *str1 = param+2;
3399 char *str2 = skip_string(str1,1);
3400 char *p = skip_string(str2,1);
3403 struct pack_desc desc;
3405 memset((char *)&desc,'\0',sizeof(desc));
3409 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3411 /* check it's a supported varient */
3412 if (strcmp(str1,"WrLeh") != 0) return False;
3413 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3415 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3416 memset((char *)&desc,'\0',sizeof(desc));
3418 desc.buflen = mdrcnt;
3420 if (init_package(&desc,1,0)) {
3421 PACKS(&desc,"B13","lp0");
3424 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3426 *rdata_len = desc.usedlen;
3429 *rparam = REALLOC(*rparam,*rparam_len);
3430 SSVALS(*rparam,0,desc.errcode);
3432 SSVAL(*rparam,4,succnt);
3435 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3440 /****************************************************************************
3442 ****************************************************************************/
3443 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3444 int mdrcnt,int mprcnt,
3445 char **rdata,char **rparam,
3446 int *rdata_len,int *rparam_len)
3449 char *str1 = param+2;
3450 char *str2 = skip_string(str1,1);
3451 char *p = skip_string(str2,1);
3453 struct pack_desc desc;
3454 struct sessionid *session_list;
3455 int i, num_sessions;
3457 memset((char *)&desc,'\0',sizeof(desc));
3461 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3462 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3463 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3465 /* check it's a supported varient */
3466 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3467 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3469 num_sessions = list_sessions(&session_list);
3471 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3472 memset((char *)&desc,'\0',sizeof(desc));
3474 desc.buflen = mdrcnt;
3476 if (!init_package(&desc,num_sessions,0)) {
3480 for(i=0; i<num_sessions; i++) {
3481 PACKS(&desc, "z", session_list[i].remote_machine);
3482 PACKS(&desc, "z", session_list[i].username);
3483 PACKI(&desc, "W", 1); /* num conns */
3484 PACKI(&desc, "W", 0); /* num opens */
3485 PACKI(&desc, "W", 1); /* num users */
3486 PACKI(&desc, "D", 0); /* session time */
3487 PACKI(&desc, "D", 0); /* idle time */
3488 PACKI(&desc, "D", 0); /* flags */
3489 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3492 *rdata_len = desc.usedlen;
3495 *rparam = REALLOC(*rparam,*rparam_len);
3496 SSVALS(*rparam,0,desc.errcode);
3497 SSVAL(*rparam,2,0); /* converter */
3498 SSVAL(*rparam,4,num_sessions); /* count */
3500 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3505 /****************************************************************************
3506 The buffer was too small
3507 ****************************************************************************/
3509 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3510 int mdrcnt,int mprcnt,
3511 char **rdata,char **rparam,
3512 int *rdata_len,int *rparam_len)
3514 *rparam_len = MIN(*rparam_len,mprcnt);
3515 *rparam = REALLOC(*rparam,*rparam_len);
3519 SSVAL(*rparam,0,NERR_BufTooSmall);
3521 DEBUG(3,("Supplied buffer too small in API command\n"));
3527 /****************************************************************************
3528 The request is not supported
3529 ****************************************************************************/
3531 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3532 int mdrcnt,int mprcnt,
3533 char **rdata,char **rparam,
3534 int *rdata_len,int *rparam_len)
3537 *rparam = REALLOC(*rparam,*rparam_len);
3541 SSVAL(*rparam,0,NERR_notsupported);
3542 SSVAL(*rparam,2,0); /* converter word */
3544 DEBUG(3,("Unsupported API command\n"));
3556 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3557 int,int,char **,char **,int *,int *);
3558 BOOL auth_user; /* Deny anonymous access? */
3559 } api_commands[] = {
3560 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3561 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3562 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3563 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3564 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3565 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3566 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3567 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3568 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3569 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3570 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3571 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3572 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3573 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3574 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3575 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3576 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3577 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3578 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3579 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3580 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3581 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3582 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3583 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3584 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3585 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3586 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3587 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3588 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3589 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3590 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3591 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3592 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3593 {NULL, -1, api_Unsupported}};
3595 /* The following RAP calls are not implemented by Samba:
3597 RAP_WFileEnum2 - anon not OK
3600 /****************************************************************************
3601 Handle remote api calls
3602 ****************************************************************************/
3604 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3605 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3609 char *rparam = NULL;
3616 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3620 api_command = SVAL(params,0);
3622 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3625 skip_string(params+2,1),
3626 tdscnt,tpscnt,mdrcnt,mprcnt));
3628 for (i=0;api_commands[i].name;i++) {
3629 if (api_commands[i].id == api_command && api_commands[i].fn) {
3630 DEBUG(3,("Doing %s\n",api_commands[i].name));
3635 /* Check whether this api call can be done anonymously */
3637 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3638 user_struct *user = get_valid_user_struct(vuid);
3640 if (!user || user->guest)
3641 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3644 rdata = (char *)malloc(1024);
3646 memset(rdata,'\0',1024);
3648 rparam = (char *)malloc(1024);
3650 memset(rparam,'\0',1024);
3652 if(!rdata || !rparam) {
3653 DEBUG(0,("api_reply: malloc fail !\n"));
3657 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3658 &rdata,&rparam,&rdata_len,&rparam_len);
3661 if (rdata_len > mdrcnt ||
3662 rparam_len > mprcnt) {
3663 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3664 &rdata,&rparam,&rdata_len,&rparam_len);
3667 /* if we get False back then it's actually unsupported */
3669 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3670 &rdata,&rparam,&rdata_len,&rparam_len);
3672 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);