2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
36 extern fstring local_machine;
37 extern pstring global_myname;
38 extern fstring global_myworkgroup;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
49 #define ACCESS_READ 0x01
50 #define ACCESS_WRITE 0x02
51 #define ACCESS_CREATE 0x04
53 #define SHPWLEN 8 /* share password length */
55 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
56 int mdrcnt,int mprcnt,
57 char **rdata,char **rparam,
58 int *rdata_len,int *rparam_len);
59 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
60 int mdrcnt,int mprcnt,
61 char **rdata,char **rparam,
62 int *rdata_len,int *rparam_len);
65 static int CopyExpanded(connection_struct *conn,
66 int snum, char** dst, char* src, int* n)
71 if (!src || !dst || !n || !(*dst)) return(0);
73 StrnCpy(buf,src,sizeof(buf)/2);
74 pstring_sub(buf,"%S",lp_servicename(snum));
75 standard_sub_conn(conn,buf);
76 l = push_ascii(*dst,buf,*n-1, STR_TERMINATE);
82 static int CopyAndAdvance(char** dst, char* src, int* n)
85 if (!src || !dst || !n || !(*dst)) return(0);
86 l = push_ascii(*dst,src,*n-1, STR_TERMINATE);
92 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
96 StrnCpy(buf,s,sizeof(buf)/2);
97 pstring_sub(buf,"%S",lp_servicename(snum));
98 standard_sub_conn(conn,buf);
99 return strlen(buf) + 1;
102 static char* Expand(connection_struct *conn, int snum, char* s)
105 if (!s) return(NULL);
106 StrnCpy(buf,s,sizeof(buf)/2);
107 pstring_sub(buf,"%S",lp_servicename(snum));
108 standard_sub_conn(conn,buf);
112 /*******************************************************************
113 check a API string for validity when we only need to check the prefix
114 ******************************************************************/
115 static BOOL prefix_ok(char *str,char *prefix)
117 return(strncmp(str,prefix,strlen(prefix)) == 0);
121 char* format; /* formatstring for structure */
122 char* subformat; /* subformat for structure */
123 char* base; /* baseaddress of buffer */
124 int buflen; /* remaining size for fixed part; on init: length of base */
125 int subcount; /* count of substructures */
126 char* structbuf; /* pointer into buffer for remaining fixed part */
127 int stringlen; /* remaining size for variable part */
128 char* stringbuf; /* pointer into buffer for remaining variable part */
129 int neededlen; /* total needed size */
130 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
131 char* curpos; /* current position; pointer into format or subformat */
135 static int get_counter(char** p)
138 if (!p || !(*p)) return(1);
139 if (!isdigit((int)**p)) return 1;
143 n = 10 * n + (i - '0');
150 static int getlen(char* p)
156 case 'W': /* word (2 byte) */
159 case 'K': /* status word? (2 byte) */
162 case 'N': /* count of substructures (word) at end */
165 case 'D': /* double word (4 byte) */
166 case 'z': /* offset to zero terminated string (4 byte) */
167 case 'l': /* offset to user data (4 byte) */
170 case 'b': /* offset to data (with counter) (4 byte) */
174 case 'B': /* byte (with optional counter) */
175 n += get_counter(&p);
182 static BOOL init_package(struct pack_desc* p, int count, int subcount)
187 if (!p->format || !p->base) return(False);
189 i = count * getlen(p->format);
190 if (p->subformat) i += subcount * getlen(p->subformat);
191 p->structbuf = p->base;
195 p->curpos = p->format;
201 * This is the old error code we used. Aparently
202 * WinNT/2k systems return ERRbuftoosmall (2123) and
203 * OS/2 needs this. I'm leaving this here so we can revert
206 p->errcode = ERRmoredata;
208 p->errcode = ERRbuftoosmall;
212 p->errcode = NERR_Success;
215 p->stringbuf = p->base + i;
217 return(p->errcode == NERR_Success);
220 static int package(struct pack_desc* p, ...)
223 int needed=0, stringneeded;
225 int is_string=0, stringused;
232 p->curpos = p->format;
234 p->curpos = p->subformat;
239 str = va_arg(args,char*);
240 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
249 switch( *p->curpos++ ) {
250 case 'W': /* word (2 byte) */
252 temp = va_arg(args,int);
253 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
255 case 'K': /* status word? (2 byte) */
257 temp = va_arg(args,int);
258 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
260 case 'N': /* count of substructures (word) at end */
262 p->subcount = va_arg(args,int);
263 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
265 case 'D': /* double word (4 byte) */
267 temp = va_arg(args,int);
268 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
270 case 'B': /* byte (with optional counter) */
271 needed = get_counter(&p->curpos);
273 char *s = va_arg(args,char*);
274 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
277 case 'z': /* offset to zero terminated string (4 byte) */
278 str = va_arg(args,char*);
279 stringneeded = (str ? strlen(str)+1 : 0);
282 case 'l': /* offset to user data (4 byte) */
283 str = va_arg(args,char*);
284 stringneeded = va_arg(args,int);
287 case 'b': /* offset to data (with counter) (4 byte) */
288 str = va_arg(args,char*);
289 stringneeded = get_counter(&p->curpos);
294 if (stringneeded >= 0) {
296 if (p->buflen >= needed) {
297 stringused = stringneeded;
298 if (stringused > p->stringlen) {
299 stringused = (is_string ? p->stringlen : 0);
300 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
303 SIVAL(p->structbuf,0,0);
305 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
306 memcpy(p->stringbuf,str?str:"",stringused);
307 if (is_string) p->stringbuf[stringused-1] = '\0';
308 p->stringbuf += stringused;
309 p->stringlen -= stringused;
310 p->usedlen += stringused;
313 p->neededlen += stringneeded;
315 p->neededlen += needed;
316 if (p->buflen >= needed) {
317 p->structbuf += needed;
319 p->usedlen += needed;
322 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
328 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
329 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
331 #define PACK(desc,t,v) package(desc,v)
332 #define PACKl(desc,t,v,l) package(desc,v,l)
335 static void PACKI(struct pack_desc* desc,char *t,int v)
340 static void PACKS(struct pack_desc* desc,char *t,char *v)
346 /****************************************************************************
348 ****************************************************************************/
349 static void PackDriverData(struct pack_desc* desc)
351 char drivdata[4+4+32];
352 SIVAL(drivdata,0,sizeof drivdata); /* cb */
353 SIVAL(drivdata,4,1000); /* lVersion */
354 memset(drivdata+8,0,32); /* szDeviceName */
355 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
356 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
359 static int check_printq_info(struct pack_desc* desc,
360 int uLevel, char *id1, char *id2)
362 desc->subformat = NULL;
365 desc->format = "B13";
368 desc->format = "B13BWWWzzzzzWW";
371 desc->format = "B13BWWWzzzzzWN";
372 desc->subformat = "WB21BB16B10zWWzDDz";
375 desc->format = "zWWWWzzzzWWzzl";
378 desc->format = "zWWWWzzzzWNzzl";
379 desc->subformat = "WWzWWDDzz";
388 desc->format = "WzzzzzzzzN";
389 desc->subformat = "z";
391 default: return False;
393 if (strcmp(desc->format,id1) != 0) return False;
394 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
399 #define RAP_JOB_STATUS_QUEUED 0
400 #define RAP_JOB_STATUS_PAUSED 1
401 #define RAP_JOB_STATUS_SPOOLING 2
402 #define RAP_JOB_STATUS_PRINTING 3
403 #define RAP_JOB_STATUS_PRINTED 4
405 #define RAP_QUEUE_STATUS_PAUSED 1
406 #define RAP_QUEUE_STATUS_ERROR 2
408 /* turn a print job status into a on the wire status
410 static int printj_status(int v)
414 return RAP_JOB_STATUS_QUEUED;
416 return RAP_JOB_STATUS_PAUSED;
418 return RAP_JOB_STATUS_SPOOLING;
420 return RAP_JOB_STATUS_PRINTING;
425 /* turn a print queue status into a on the wire status
427 static int printq_status(int v)
433 return RAP_QUEUE_STATUS_PAUSED;
435 return RAP_QUEUE_STATUS_ERROR;
438 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
439 struct pack_desc* desc,
440 print_queue_struct* queue, int n)
442 time_t t = queue->time;
444 /* the client expects localtime */
447 PACKI(desc,"W",queue->job); /* uJobId */
449 PACKS(desc,"B21",queue->user); /* szUserName */
450 PACKS(desc,"B",""); /* pad */
451 PACKS(desc,"B16",""); /* szNotifyName */
452 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
453 PACKS(desc,"z",""); /* pszParms */
454 PACKI(desc,"W",n+1); /* uPosition */
455 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
456 PACKS(desc,"z",""); /* pszStatus */
457 PACKI(desc,"D",t); /* ulSubmitted */
458 PACKI(desc,"D",queue->size); /* ulSize */
459 PACKS(desc,"z",queue->file); /* pszComment */
461 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
462 PACKI(desc,"W",queue->priority); /* uPriority */
463 PACKS(desc,"z",queue->user); /* pszUserName */
464 PACKI(desc,"W",n+1); /* uPosition */
465 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
466 PACKI(desc,"D",t); /* ulSubmitted */
467 PACKI(desc,"D",queue->size); /* ulSize */
468 PACKS(desc,"z","Samba"); /* pszComment */
469 PACKS(desc,"z",queue->file); /* pszDocument */
471 PACKS(desc,"z",""); /* pszNotifyName */
472 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
473 PACKS(desc,"z",""); /* pszParms */
474 PACKS(desc,"z",""); /* pszStatus */
475 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
476 PACKS(desc,"z","lpd"); /* pszQProcName */
477 PACKS(desc,"z",""); /* pszQProcParms */
478 PACKS(desc,"z","NULL"); /* pszDriverName */
479 PackDriverData(desc); /* pDriverData */
480 PACKS(desc,"z",""); /* pszPrinterName */
481 } else if (uLevel == 4) { /* OS2 */
482 PACKS(desc,"z",""); /* pszSpoolFileName */
483 PACKS(desc,"z",""); /* pszPortName */
484 PACKS(desc,"z",""); /* pszStatus */
485 PACKI(desc,"D",0); /* ulPagesSpooled */
486 PACKI(desc,"D",0); /* ulPagesSent */
487 PACKI(desc,"D",0); /* ulPagesPrinted */
488 PACKI(desc,"D",0); /* ulTimePrinted */
489 PACKI(desc,"D",0); /* ulExtendJobStatus */
490 PACKI(desc,"D",0); /* ulStartPage */
491 PACKI(desc,"D",0); /* ulEndPage */
496 /********************************************************************
497 Return a driver name given an snum.
498 Looks in a tdb first. Returns True if from tdb, False otherwise.
499 ********************************************************************/
501 static BOOL get_driver_name(int snum, pstring drivername)
503 NT_PRINTER_INFO_LEVEL *info = NULL;
506 get_a_printer (&info, 2, lp_servicename(snum));
508 pstrcpy( drivername, info->info_2->drivername);
510 free_a_printer(&info, 2);
512 pstrcpy( drivername, lp_printerdriver(snum));
518 /********************************************************************
519 Respond to the DosPrintQInfo command with a level of 52
520 This is used to get printer driver information for Win9x clients
521 ********************************************************************/
522 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
523 struct pack_desc* desc,
524 int count, print_queue_struct* queue,
525 print_status_struct* status)
529 pstring tok,driver,datafile,langmon,helpfile,datatype;
538 * Check in the tdb *first* before checking the legacy
539 * files. This allows an NT upload to take precedence over
540 * the existing fileset. JRA.
542 * we need to lookup the driver name prior to making the call
543 * to get_a_printer_driver_9x_compatible() and not rely on the
544 * 'print driver' parameter --jerry
548 if ((get_driver_name(snum,drivername)) &&
549 ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True))
553 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
557 /* didn't find driver in tdb */
559 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
560 snum, drivername, lp_driverfile(snum)));
562 lines = file_lines_load(lp_driverfile(snum),NULL);
565 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
567 desc->errcode=NERR_notsupported;
571 /* lookup the long printer driver name in the file description */
572 for (i=0;lines[i] && !ok;i++)
575 if (next_token(&p,tok,":",sizeof(tok)) &&
576 (strlen(drivername) == strlen(tok)) &&
577 (!strncmp(tok,drivername,strlen(drivername))))
586 /* driver file name */
587 if (!next_token(&p,driver,":",sizeof(driver)))
591 if (!next_token(&p,datafile,":",sizeof(datafile)))
595 * for the next tokens - which may be empty - I have
596 * to check for empty tokens first because the
597 * next_token function will skip all empty token
606 else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
609 /* language monitor */
615 else if (!next_token(&p,langmon,":",sizeof(langmon)))
618 /* default data type */
619 if (!next_token(&p,datatype,":",sizeof(datatype)))
622 PACKI(desc,"W",0x0400); /* don't know */
623 PACKS(desc,"z",drivername); /* long printer name */
624 PACKS(desc,"z",driver); /* Driverfile Name */
625 PACKS(desc,"z",datafile); /* Datafile name */
626 PACKS(desc,"z",langmon); /* language monitor */
629 fstrcpy(location, "\\\\");
630 fstrcat(location, global_myname);
631 fstrcat(location, "\\print$\\WIN40\\0");
632 PACKS(desc,"z",location); /* share to retrieve files */
636 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
638 PACKS(desc,"z",datatype); /* default data type */
639 PACKS(desc,"z",helpfile); /* helpfile name */
640 PACKS(desc,"z",driver); /* driver name */
642 DEBUG(3,("printerdriver:%s:\n",drivername));
643 DEBUG(3,("Driver:%s:\n",driver));
644 DEBUG(3,("Data File:%s:\n",datafile));
645 DEBUG(3,("Language Monitor:%s:\n",langmon));
647 DEBUG(3,("lp_driverlocation:%s:\n",location));
649 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
650 DEBUG(3,("Data Type:%s:\n",datatype));
651 DEBUG(3,("Help File:%s:\n",helpfile));
652 PACKI(desc,"N",count); /* number of files to copy */
654 for (i=0;i<count;i++)
656 /* no need to check return value here
657 * - it was already tested in
658 * get_printerdrivernumber */
659 next_token(&p,tok,",",sizeof(tok));
660 PACKS(desc,"z",tok); /* driver files to copy */
661 DEBUG(3,("file:%s:\n",tok));
664 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
665 SERVICE(snum),count));
667 desc->errcode=NERR_Success;
673 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
674 desc->errcode=NERR_notsupported;
677 file_lines_free(lines);
681 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
682 struct pack_desc* desc,
683 int count, print_queue_struct* queue,
684 print_status_struct* status)
689 PACKS(desc,"B13",SERVICE(snum));
694 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
697 PACKI(desc,"K",printq_status(status->status));
701 if (uLevel == 1 || uLevel == 2) {
702 PACKS(desc,"B",""); /* alignment */
703 PACKI(desc,"W",5); /* priority */
704 PACKI(desc,"W",0); /* start time */
705 PACKI(desc,"W",0); /* until time */
706 PACKS(desc,"z",""); /* pSepFile */
707 PACKS(desc,"z","lpd"); /* pPrProc */
708 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
709 PACKS(desc,"z",""); /* pParms */
711 PACKS(desc,"z","UNKNOWN PRINTER");
712 PACKI(desc,"W",LPSTAT_ERROR);
714 else if (!status || !status->message[0]) {
715 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
716 PACKI(desc,"W",LPSTAT_OK); /* status */
718 PACKS(desc,"z",status->message);
719 PACKI(desc,"W",printq_status(status->status)); /* status */
721 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
724 if (uLevel == 3 || uLevel == 4) {
727 PACKI(desc,"W",5); /* uPriority */
728 PACKI(desc,"W",0); /* uStarttime */
729 PACKI(desc,"W",0); /* uUntiltime */
730 PACKI(desc,"W",5); /* pad1 */
731 PACKS(desc,"z",""); /* pszSepFile */
732 PACKS(desc,"z","WinPrint"); /* pszPrProc */
733 PACKS(desc,"z",NULL); /* pszParms */
734 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
735 /* "don't ask" that it's done this way to fix corrupted
736 Win9X/ME printer comments. */
738 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
740 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
742 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
743 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
744 get_driver_name(snum,drivername);
745 PACKS(desc,"z",drivername); /* pszDriverName */
746 PackDriverData(desc); /* pDriverData */
749 if (uLevel == 2 || uLevel == 4) {
751 for (i=0;i<count;i++)
752 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
756 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
760 /* This function returns the number of files for a given driver */
761 static int get_printerdrivernumber(int snum)
772 * Check in the tdb *first* before checking the legacy
773 * files. This allows an NT upload to take precedence over
774 * the existing fileset. JRA.
776 * we need to lookup the driver name prior to making the call
777 * to get_a_printer_driver_9x_compatible() and not rely on the
778 * 'print driver' parameter --jerry
781 if ((get_driver_name(snum,drivername)) &&
782 (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True))
785 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
789 /* didn't find driver in tdb */
791 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
792 snum, drivername, lp_driverfile(snum)));
794 lines = file_lines_load(lp_driverfile(snum), NULL);
797 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
801 /* lookup the long printer driver name in the file description */
802 for (i=0;lines[i] && !ok;i++)
805 if (next_token(&p,tok,":",sizeof(tok)) &&
806 (strlen(drivername) == strlen(tok)) &&
807 (!strncmp(tok,drivername,strlen(drivername))))
819 if (*p++ == ':') i--;
822 DEBUG(3,("Can't determine number of printer driver files\n"));
826 /* count the number of files */
827 while (next_token(&p,tok,",",sizeof(tok)))
835 file_lines_free(lines);
840 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
841 uint16 vuid, char *param,char *data,
842 int mdrcnt,int mprcnt,
843 char **rdata,char **rparam,
844 int *rdata_len,int *rparam_len)
846 char *str1 = param+2;
847 char *str2 = skip_string(str1,1);
848 char *p = skip_string(str2,1);
854 struct pack_desc desc;
855 print_queue_struct *queue=NULL;
856 print_status_struct status;
859 memset((char *)&status,'\0',sizeof(status));
860 memset((char *)&desc,'\0',sizeof(desc));
862 p = skip_string(p,1);
866 /* remove any trailing username */
867 if ((p = strchr_m(QueueName,'%')))
870 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
872 /* check it's a supported varient */
873 if (!prefix_ok(str1,"zWrLh"))
875 if (!check_printq_info(&desc,uLevel,str2,str3)) {
877 * Patch from Scott Moomaw <scott@bridgewater.edu>
878 * to return the 'invalid info level' error if an
879 * unknown level was requested.
883 *rparam = REALLOC(*rparam,*rparam_len);
884 SSVALS(*rparam,0,ERRunknownlevel);
890 snum = lp_servicenumber(QueueName);
891 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
892 int pnum = lp_servicenumber(PRINTERS_NAME);
894 lp_add_printer(QueueName,pnum);
895 snum = lp_servicenumber(QueueName);
899 if (snum < 0 || !VALID_SNUM(snum))
903 count = get_printerdrivernumber(snum);
904 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
906 count = print_queue_status(snum, &queue,&status);
910 *rdata = REALLOC(*rdata,mdrcnt);
912 desc.buflen = mdrcnt;
915 * Don't return data but need to get correct length
916 * init_package will return wrong size if buflen=0
918 desc.buflen = getlen(desc.format);
919 desc.base = tmpdata = (char *) malloc (desc.buflen);
922 if (init_package(&desc,1,count)) {
923 desc.subcount = count;
924 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
927 *rdata_len = desc.usedlen;
930 * We must set the return code to ERRbuftoosmall
931 * in order to support lanman style printing with Win NT/2k
934 if (!mdrcnt && lp_disable_spoolss())
935 desc.errcode = ERRbuftoosmall;
937 *rdata_len = desc.usedlen;
939 *rparam = REALLOC(*rparam,*rparam_len);
940 SSVALS(*rparam,0,desc.errcode);
942 SSVAL(*rparam,4,desc.neededlen);
944 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
952 /****************************************************************************
953 View list of all print jobs on all queues.
954 ****************************************************************************/
956 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
957 int mdrcnt, int mprcnt,
958 char **rdata, char** rparam,
959 int *rdata_len, int *rparam_len)
961 char *param_format = param+2;
962 char *output_format1 = skip_string(param_format,1);
963 char *p = skip_string(output_format1,1);
964 int uLevel = SVAL(p,0);
965 char *output_format2 = p + 4;
966 int services = lp_numservices();
968 struct pack_desc desc;
969 print_queue_struct **queue = NULL;
970 print_status_struct *status = NULL;
971 int* subcntarr = NULL;
972 int queuecnt, subcnt=0, succnt=0;
974 memset((char *)&desc,'\0',sizeof(desc));
976 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
978 if (!prefix_ok(param_format,"WrLeh")) return False;
979 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
981 * Patch from Scott Moomaw <scott@bridgewater.edu>
982 * to return the 'invalid info level' error if an
983 * unknown level was requested.
987 *rparam = REALLOC(*rparam,*rparam_len);
988 SSVALS(*rparam,0,ERRunknownlevel);
995 for (i = 0; i < services; i++)
996 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
999 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
1000 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1003 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1004 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
1005 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1008 memset(status,0,queuecnt*sizeof(print_status_struct));
1009 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
1010 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1015 for (i = 0; i < services; i++)
1016 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1017 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1018 subcnt += subcntarr[n];
1022 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1024 desc.buflen = mdrcnt;
1026 if (init_package(&desc,queuecnt,subcnt)) {
1029 for (i = 0; i < services; i++)
1030 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1031 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1033 if (desc.errcode == NERR_Success) succnt = n;
1037 SAFE_FREE(subcntarr);
1039 *rdata_len = desc.usedlen;
1041 *rparam = REALLOC(*rparam,*rparam_len);
1042 SSVALS(*rparam,0,desc.errcode);
1044 SSVAL(*rparam,4,succnt);
1045 SSVAL(*rparam,6,queuecnt);
1047 for (i = 0; i < queuecnt; i++) {
1048 if (queue) SAFE_FREE(queue[i]);
1057 /****************************************************************************
1058 get info level for a server list query
1059 ****************************************************************************/
1060 static BOOL check_server_info(int uLevel, char* id)
1064 if (strcmp(id,"B16") != 0) return False;
1067 if (strcmp(id,"B16BBDz") != 0) return False;
1075 struct srv_info_struct
1085 /*******************************************************************
1086 get server info lists from the files saved by nmbd. Return the
1088 ******************************************************************/
1089 static int get_server_info(uint32 servertype,
1090 struct srv_info_struct **servers,
1096 BOOL local_list_only;
1099 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1101 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1105 /* request for everything is code for request all servers */
1106 if (servertype == SV_TYPE_ALL)
1107 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1109 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1111 DEBUG(4,("Servertype search: %8x\n",servertype));
1113 for (i=0;lines[i];i++) {
1115 struct srv_info_struct *s;
1116 char *ptr = lines[i];
1119 if (!*ptr) continue;
1121 if (count == alloced) {
1122 struct srv_info_struct *ts;
1125 ts = (struct srv_info_struct *)
1126 Realloc(*servers,sizeof(**servers)*alloced);
1128 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1132 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1134 s = &(*servers)[count];
1136 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1137 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1138 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1139 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1140 /* this allows us to cope with an old nmbd */
1141 pstrcpy(s->domain,global_myworkgroup);
1144 if (sscanf(stype,"%X",&s->type) != 1) {
1145 DEBUG(4,("r:host file "));
1149 /* Filter the servers/domains we return based on what was asked for. */
1151 /* Check to see if we are being asked for a local list only. */
1152 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1153 DEBUG(4,("r: local list only"));
1157 /* doesn't match up: don't want it */
1158 if (!(servertype & s->type)) {
1159 DEBUG(4,("r:serv type "));
1163 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1164 (s->type & SV_TYPE_DOMAIN_ENUM))
1166 DEBUG(4,("s: dom mismatch "));
1170 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1175 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1176 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1180 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1181 s->name, s->type, s->comment, s->domain));
1183 s->server_added = True;
1188 DEBUG(4,("%20s %8x %25s %15s\n",
1189 s->name, s->type, s->comment, s->domain));
1193 file_lines_free(lines);
1198 /*******************************************************************
1199 fill in a server info structure
1200 ******************************************************************/
1201 static int fill_srv_info(struct srv_info_struct *service,
1202 int uLevel, char **buf, int *buflen,
1203 char **stringbuf, int *stringspace, char *baseaddr)
1212 case 0: struct_len = 16; break;
1213 case 1: struct_len = 26; break;
1223 len = strlen(service->comment)+1;
1227 if (buflen) *buflen = struct_len;
1228 if (stringspace) *stringspace = len;
1229 return struct_len + len;
1234 if (*buflen < struct_len) return -1;
1242 p2 = p + struct_len;
1243 l2 = *buflen - struct_len;
1245 if (!baseaddr) baseaddr = p;
1250 push_ascii(p,service->name, 15, STR_TERMINATE);
1254 push_ascii(p,service->name,15, STR_TERMINATE);
1255 SIVAL(p,18,service->type);
1256 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1257 len += CopyAndAdvance(&p2,service->comment,&l2);
1263 *buf = p + struct_len;
1264 *buflen -= struct_len;
1277 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1279 return(strcmp(s1->name,s2->name));
1282 /****************************************************************************
1283 view list of servers available (or possibly domains). The info is
1284 extracted from lists saved by nmbd on the local host
1285 ****************************************************************************/
1286 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1287 int mdrcnt, int mprcnt, char **rdata,
1288 char **rparam, int *rdata_len, int *rparam_len)
1290 char *str1 = param+2;
1291 char *str2 = skip_string(str1,1);
1292 char *p = skip_string(str2,1);
1293 int uLevel = SVAL(p,0);
1294 int buf_len = SVAL(p,2);
1295 uint32 servertype = IVAL(p,4);
1297 int data_len, fixed_len, string_len;
1298 int f_len = 0, s_len = 0;
1299 struct srv_info_struct *servers=NULL;
1300 int counted=0,total=0;
1303 BOOL domain_request;
1306 /* If someone sets all the bits they don't really mean to set
1307 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1310 if (servertype == SV_TYPE_ALL)
1311 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1313 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1314 any other bit (they may just set this bit on it's own) they
1315 want all the locally seen servers. However this bit can be
1316 set on its own so set the requested servers to be
1317 ALL - DOMAIN_ENUM. */
1319 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1320 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1322 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1323 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1327 if (!prefix_ok(str1,"WrLehD")) return False;
1328 if (!check_server_info(uLevel,str2)) return False;
1330 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1331 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1332 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1334 if (strcmp(str1, "WrLehDz") == 0) {
1335 pull_ascii_fstring(domain, p);
1337 fstrcpy(domain, global_myworkgroup);
1340 if (lp_browse_list())
1341 total = get_server_info(servertype,&servers,domain);
1343 data_len = fixed_len = string_len = 0;
1347 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1350 char *lastname=NULL;
1352 for (i=0;i<total;i++)
1354 struct srv_info_struct *s = &servers[i];
1355 if (lastname && strequal(lastname,s->name)) continue;
1357 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1358 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1359 s->name, s->type, s->comment, s->domain));
1361 if (data_len <= buf_len) {
1364 string_len += s_len;
1371 *rdata_len = fixed_len + string_len;
1372 *rdata = REALLOC(*rdata,*rdata_len);
1373 memset(*rdata,'\0',*rdata_len);
1375 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1381 char *lastname=NULL;
1382 int count2 = counted;
1383 for (i = 0; i < total && count2;i++)
1385 struct srv_info_struct *s = &servers[i];
1386 if (lastname && strequal(lastname,s->name)) continue;
1388 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1389 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1390 s->name, s->type, s->comment, s->domain));
1396 *rparam = REALLOC(*rparam,*rparam_len);
1397 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1399 SSVAL(*rparam,4,counted);
1400 SSVAL(*rparam,6,counted+missed);
1404 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1405 domain,uLevel,counted,counted+missed));
1410 /****************************************************************************
1411 command 0x34 - suspected of being a "Lookup Names" stub api
1412 ****************************************************************************/
1413 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1414 int mdrcnt, int mprcnt, char **rdata,
1415 char **rparam, int *rdata_len, int *rparam_len)
1417 char *str1 = param+2;
1418 char *str2 = skip_string(str1,1);
1419 char *p = skip_string(str2,1);
1420 int uLevel = SVAL(p,0);
1421 int buf_len = SVAL(p,2);
1425 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1426 str1, str2, p, uLevel, buf_len));
1428 if (!prefix_ok(str1,"zWrLeh")) return False;
1433 *rparam = REALLOC(*rparam,*rparam_len);
1435 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1437 SSVAL(*rparam,4,counted);
1438 SSVAL(*rparam,6,counted+missed);
1443 /****************************************************************************
1444 get info about a share
1445 ****************************************************************************/
1446 static BOOL check_share_info(int uLevel, char* id)
1450 if (strcmp(id,"B13") != 0) return False;
1453 if (strcmp(id,"B13BWz") != 0) return False;
1456 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1459 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1461 default: return False;
1466 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1467 char** buf, int* buflen,
1468 char** stringbuf, int* stringspace, char* baseaddr)
1477 case 0: struct_len = 13; break;
1478 case 1: struct_len = 20; break;
1479 case 2: struct_len = 40; break;
1480 case 91: struct_len = 68; break;
1488 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1489 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1490 if (buflen) *buflen = struct_len;
1491 if (stringspace) *stringspace = len;
1492 return struct_len + len;
1497 if ((*buflen) < struct_len) return -1;
1505 p2 = p + struct_len;
1506 l2 = (*buflen) - struct_len;
1508 if (!baseaddr) baseaddr = p;
1510 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1516 type = STYPE_DISKTREE;
1517 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1518 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1519 SSVAL(p,14,type); /* device type */
1520 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1521 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1526 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1527 SSVALS(p,22,-1); /* max uses */
1528 SSVAL(p,24,1); /* current uses */
1529 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1530 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1531 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1536 memset(p+40,0,SHPWLEN+2);
1548 (*buf) = p + struct_len;
1549 (*buflen) -= struct_len;
1551 (*stringspace) = l2;
1561 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1562 int mdrcnt,int mprcnt,
1563 char **rdata,char **rparam,
1564 int *rdata_len,int *rparam_len)
1566 char *str1 = param+2;
1567 char *str2 = skip_string(str1,1);
1568 char *netname = skip_string(str2,1);
1569 char *p = skip_string(netname,1);
1570 int uLevel = SVAL(p,0);
1571 int snum = find_service(netname);
1573 if (snum < 0) return False;
1575 /* check it's a supported varient */
1576 if (!prefix_ok(str1,"zWrLh")) return False;
1577 if (!check_share_info(uLevel,str2)) return False;
1579 *rdata = REALLOC(*rdata,mdrcnt);
1581 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1582 if (*rdata_len < 0) return False;
1585 *rparam = REALLOC(*rparam,*rparam_len);
1586 SSVAL(*rparam,0,NERR_Success);
1587 SSVAL(*rparam,2,0); /* converter word */
1588 SSVAL(*rparam,4,*rdata_len);
1593 /****************************************************************************
1594 view list of shares available
1595 ****************************************************************************/
1596 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1597 int mdrcnt,int mprcnt,
1598 char **rdata,char **rparam,
1599 int *rdata_len,int *rparam_len)
1601 char *str1 = param+2;
1602 char *str2 = skip_string(str1,1);
1603 char *p = skip_string(str2,1);
1604 int uLevel = SVAL(p,0);
1605 int buf_len = SVAL(p,2);
1607 int count=lp_numservices();
1608 int total=0,counted=0;
1609 BOOL missed = False;
1611 int data_len, fixed_len, string_len;
1612 int f_len = 0, s_len = 0;
1614 if (!prefix_ok(str1,"WrLeh")) return False;
1615 if (!check_share_info(uLevel,str2)) return False;
1617 data_len = fixed_len = string_len = 0;
1618 for (i=0;i<count;i++)
1619 if (lp_browseable(i) && lp_snum_ok(i))
1622 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1623 if (data_len <= buf_len)
1627 string_len += s_len;
1632 *rdata_len = fixed_len + string_len;
1633 *rdata = REALLOC(*rdata,*rdata_len);
1634 memset(*rdata,0,*rdata_len);
1636 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1640 for (i = 0; i < count;i++)
1641 if (lp_browseable(i) && lp_snum_ok(i))
1642 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1646 *rparam = REALLOC(*rparam,*rparam_len);
1647 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1649 SSVAL(*rparam,4,counted);
1650 SSVAL(*rparam,6,total);
1652 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1653 counted,total,uLevel,
1654 buf_len,*rdata_len,mdrcnt));
1658 /****************************************************************************
1660 ****************************************************************************/
1661 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1662 int mdrcnt,int mprcnt,
1663 char **rdata,char **rparam,
1664 int *rdata_len,int *rparam_len)
1666 char *str1 = param+2;
1667 char *str2 = skip_string(str1,1);
1668 char *p = skip_string(str2,1);
1669 int uLevel = SVAL(p,0);
1673 char *command, *cmdname;
1678 /* check it's a supported varient */
1679 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1680 if (!check_share_info(uLevel,str2)) return False;
1681 if (uLevel != 2) return False;
1683 pull_ascii_fstring(sharename,data);
1684 snum = find_service(sharename);
1685 if (snum >= 0) { /* already exists */
1690 /* only support disk share adds */
1691 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1693 offset = IVAL(data, 16);
1694 if (offset >= mdrcnt) {
1695 res = ERRinvalidparam;
1698 pull_ascii_fstring(comment, offset? (data+offset) : "");
1700 offset = IVAL(data, 26);
1701 if (offset >= mdrcnt) {
1702 res = ERRinvalidparam;
1705 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1707 string_replace(sharename, '"', ' ');
1708 string_replace(pathname, '"', ' ');
1709 string_replace(comment, '"', ' ');
1711 cmdname = lp_add_share_cmd();
1713 if (!cmdname || *cmdname == '\0') return False;
1715 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1716 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1719 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1720 if ((res = smbrun(command, NULL)) != 0) {
1721 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1727 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1729 } else return False;
1732 *rparam = REALLOC(*rparam,*rparam_len);
1733 SSVAL(*rparam,0,NERR_Success);
1734 SSVAL(*rparam,2,0); /* converter word */
1735 SSVAL(*rparam,4,*rdata_len);
1742 *rparam = REALLOC(*rparam,*rparam_len);
1744 SSVAL(*rparam,0,res);
1750 /****************************************************************************
1751 view list of groups available
1752 ****************************************************************************/
1753 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1754 int mdrcnt,int mprcnt,
1755 char **rdata,char **rparam,
1756 int *rdata_len,int *rparam_len)
1758 char *str1 = param+2;
1759 char *str2 = skip_string(str1,1);
1760 char *p = skip_string(str2,1);
1761 int uLevel = SVAL(p,0);
1765 if (!prefix_ok(str1,"WrLeh")) return False;
1767 /* check it's a supported variant */
1777 if (strcmp(p2,str2) != 0) return False;
1779 *rdata_len = mdrcnt + 1024;
1780 *rdata = REALLOC(*rdata,*rdata_len);
1782 SSVAL(*rparam,0,NERR_Success);
1783 SSVAL(*rparam,2,0); /* converter word */
1787 /* XXXX we need a real SAM database some day */
1788 pstrcpy(p,"Users"); p += 21; count++;
1789 pstrcpy(p,"Domain Users"); p += 21; count++;
1790 pstrcpy(p,"Guests"); p += 21; count++;
1791 pstrcpy(p,"Domain Guests"); p += 21; count++;
1793 *rdata_len = PTR_DIFF(p,*rdata);
1796 *rparam = REALLOC(*rparam,*rparam_len);
1798 SSVAL(*rparam,4,count); /* is this right?? */
1799 SSVAL(*rparam,6,count); /* is this right?? */
1801 DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count));
1806 /****************************************************************************
1807 view list of groups available
1808 ****************************************************************************/
1809 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1810 int mdrcnt,int mprcnt,
1811 char **rdata,char **rparam,
1812 int *rdata_len,int *rparam_len)
1814 char *str1 = param+2;
1815 char *str2 = skip_string(str1,1);
1816 char *p = skip_string(str2,1);
1817 int uLevel = SVAL(p,0);
1821 if (!prefix_ok(str1,"WrLeh")) return False;
1823 /* check it's a supported variant */
1833 if (strcmp(p2,str2) != 0) return False;
1835 *rdata_len = mdrcnt + 1024;
1836 *rdata = REALLOC(*rdata,*rdata_len);
1838 SSVAL(*rparam,0,NERR_Success);
1839 SSVAL(*rparam,2,0); /* converter word */
1843 /* XXXX we need a real SAM database some day */
1844 pstrcpy(p,"Users"); p += 21; count++;
1845 pstrcpy(p,"Domain Users"); p += 21; count++;
1846 pstrcpy(p,"Guests"); p += 21; count++;
1847 pstrcpy(p,"Domain Guests"); p += 21; count++;
1849 *rdata_len = PTR_DIFF(p,*rdata);
1852 *rparam = REALLOC(*rparam,*rparam_len);
1854 SSVAL(*rparam,4,count); /* is this right?? */
1855 SSVAL(*rparam,6,count); /* is this right?? */
1857 DEBUG(3,("api_RNetUserEnum gave %d entries\n", count));
1864 /****************************************************************************
1865 get the time of day info
1866 ****************************************************************************/
1867 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1868 int mdrcnt,int mprcnt,
1869 char **rdata,char **rparam,
1870 int *rdata_len,int *rparam_len)
1874 *rparam = REALLOC(*rparam,*rparam_len);
1877 *rdata = REALLOC(*rdata,*rdata_len);
1879 SSVAL(*rparam,0,NERR_Success);
1880 SSVAL(*rparam,2,0); /* converter word */
1886 time_t unixdate = time(NULL);
1888 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1889 by NT in a "net time" operation,
1890 it seems to ignore the one below */
1892 /* the client expects to get localtime, not GMT, in this bit
1893 (I think, this needs testing) */
1894 t = LocalTime(&unixdate);
1896 SIVAL(p,4,0); /* msecs ? */
1897 SCVAL(p,8,t->tm_hour);
1898 SCVAL(p,9,t->tm_min);
1899 SCVAL(p,10,t->tm_sec);
1900 SCVAL(p,11,0); /* hundredths of seconds */
1901 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1902 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1903 SCVAL(p,16,t->tm_mday);
1904 SCVAL(p,17,t->tm_mon + 1);
1905 SSVAL(p,18,1900+t->tm_year);
1906 SCVAL(p,20,t->tm_wday);
1913 /****************************************************************************
1914 Set the user password.
1915 *****************************************************************************/
1917 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1918 int mdrcnt,int mprcnt,
1919 char **rdata,char **rparam,
1920 int *rdata_len,int *rparam_len)
1922 char *p = skip_string(param+2,2);
1924 fstring pass1,pass2;
1926 pull_ascii_fstring(user,p);
1928 p = skip_string(p,1);
1930 memset(pass1,'\0',sizeof(pass1));
1931 memset(pass2,'\0',sizeof(pass2));
1933 memcpy(pass2,p+16,16);
1936 *rparam = REALLOC(*rparam,*rparam_len);
1940 SSVAL(*rparam,0,NERR_badpass);
1941 SSVAL(*rparam,2,0); /* converter word */
1943 DEBUG(3,("Set password for <%s>\n",user));
1946 * Attempt to verify the old password against smbpasswd entries
1947 * Win98 clients send old and new password in plaintext for this call.
1951 auth_serversupplied_info *server_info = NULL;
1952 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
1953 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1954 if (change_oem_password(server_info->sam_account,pass2))
1956 SSVAL(*rparam,0,NERR_Success);
1960 * If unix password sync was requested, attempt to change
1961 * the /etc/passwd database also. Return failure if this cannot
1964 * This occours regardless of the previous result, becouse
1965 * It might not have been testing the password against the SAM backend.
1966 * (and therefore the change_oem_password would fail).
1968 * Conditional on lp_unix_password_sync() becouse we don't want
1969 * to touch the unix db unless we have admin permission.
1972 if(lp_unix_password_sync() && !chgpasswd(pdb_get_username(server_info->sam_account),
1973 pass1,pass2,False)) {
1974 SSVAL(*rparam,0,NERR_badpass);
1977 free_server_info(&server_info);
1979 data_blob_clear_free(&password);
1983 * If the plaintext change failed, attempt
1984 * the old encrypted method. NT will generate this
1985 * after trying the samr method. Note that this
1986 * method is done as a last resort as this
1987 * password change method loses the NT password hash
1988 * and cannot change the UNIX password as no plaintext
1992 if(SVAL(*rparam,0) != NERR_Success)
1994 SAM_ACCOUNT *hnd = NULL;
1996 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1997 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
1999 SSVAL(*rparam,0,NERR_Success);
2005 memset((char *)pass1,'\0',sizeof(fstring));
2006 memset((char *)pass2,'\0',sizeof(fstring));
2011 /****************************************************************************
2012 Set the user password (SamOEM version - gets plaintext).
2013 ****************************************************************************/
2015 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2016 int mdrcnt,int mprcnt,
2017 char **rdata,char **rparam,
2018 int *rdata_len,int *rparam_len)
2021 char *p = param + 2;
2023 *rparam = REALLOC(*rparam,*rparam_len);
2027 SSVAL(*rparam,0,NERR_badpass);
2030 * Check the parameter definition is correct.
2032 if(!strequal(param + 2, "zsT")) {
2033 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2036 p = skip_string(p, 1);
2038 if(!strequal(p, "B516B16")) {
2039 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2042 p = skip_string(p,1);
2044 p += pull_ascii_fstring(user,p);
2046 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2049 * Pass the user through the NT -> unix user mapping
2053 (void)map_username(user);
2056 * Do any UNIX username case mangling.
2058 (void)Get_Pwnam_Modify( user );
2060 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
2062 SSVAL(*rparam,0,NERR_Success);
2068 /****************************************************************************
2071 ****************************************************************************/
2072 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2073 int mdrcnt,int mprcnt,
2074 char **rdata,char **rparam,
2075 int *rdata_len,int *rparam_len)
2077 int function = SVAL(param,0);
2078 char *str1 = param+2;
2079 char *str2 = skip_string(str1,1);
2080 char *p = skip_string(str2,1);
2082 extern struct current_user current_user;
2083 WERROR werr = WERR_OK;
2087 /* check it's a supported varient */
2088 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2092 *rparam = REALLOC(*rparam,*rparam_len);
2095 if (!print_job_exists(jobid)) {
2096 errcode = NERR_JobNotFound;
2100 errcode = NERR_notsupported;
2103 case 81: /* delete */
2104 if (print_job_delete(¤t_user, jobid, &werr))
2105 errcode = NERR_Success;
2107 case 82: /* pause */
2108 if (print_job_pause(¤t_user, jobid, &werr))
2109 errcode = NERR_Success;
2111 case 83: /* resume */
2112 if (print_job_resume(¤t_user, jobid, &werr))
2113 errcode = NERR_Success;
2117 if (!W_ERROR_IS_OK(werr))
2118 errcode = W_ERROR_V(werr);
2121 SSVAL(*rparam,0,errcode);
2122 SSVAL(*rparam,2,0); /* converter word */
2127 /****************************************************************************
2128 Purge a print queue - or pause or resume it.
2129 ****************************************************************************/
2130 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2131 int mdrcnt,int mprcnt,
2132 char **rdata,char **rparam,
2133 int *rdata_len,int *rparam_len)
2135 int function = SVAL(param,0);
2136 char *str1 = param+2;
2137 char *str2 = skip_string(str1,1);
2138 char *QueueName = skip_string(str2,1);
2139 int errcode = NERR_notsupported;
2141 WERROR werr = WERR_OK;
2142 extern struct current_user current_user;
2144 /* check it's a supported varient */
2145 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2149 *rparam = REALLOC(*rparam,*rparam_len);
2152 snum = print_queue_snum(QueueName);
2155 errcode = NERR_JobNotFound;
2160 case 74: /* Pause queue */
2161 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2163 case 75: /* Resume queue */
2164 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2166 case 103: /* Purge */
2167 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2171 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2174 SSVAL(*rparam,0,errcode);
2175 SSVAL(*rparam,2,0); /* converter word */
2181 /****************************************************************************
2182 set the property of a print job (undocumented?)
2183 ? function = 0xb -> set name of print job
2184 ? function = 0x6 -> move print job up/down
2185 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2186 or <WWsTP> <WB21BB16B10zWWzDDz>
2187 ****************************************************************************/
2188 static int check_printjob_info(struct pack_desc* desc,
2189 int uLevel, char* id)
2191 desc->subformat = NULL;
2193 case 0: desc->format = "W"; break;
2194 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2195 case 2: desc->format = "WWzWWDDzz"; break;
2196 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2197 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2198 default: return False;
2200 if (strcmp(desc->format,id) != 0) return False;
2204 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2205 int mdrcnt,int mprcnt,
2206 char **rdata,char **rparam,
2207 int *rdata_len,int *rparam_len)
2209 struct pack_desc desc;
2210 char *str1 = param+2;
2211 char *str2 = skip_string(str1,1);
2212 char *p = skip_string(str2,1);
2214 int uLevel = SVAL(p,2);
2215 int function = SVAL(p,4);
2220 *rparam = REALLOC(*rparam,*rparam_len);
2224 /* check it's a supported varient */
2225 if ((strcmp(str1,"WWsTP")) ||
2226 (!check_printjob_info(&desc,uLevel,str2)))
2229 if (!print_job_exists(jobid)) {
2230 errcode=NERR_JobNotFound;
2234 errcode = NERR_notsupported;
2238 /* change job place in the queue,
2239 data gives the new place */
2240 place = SVAL(data,0);
2241 if (print_job_set_place(jobid, place)) {
2242 errcode=NERR_Success;
2247 /* change print job name, data gives the name */
2248 if (print_job_set_name(jobid, data)) {
2249 errcode=NERR_Success;
2258 SSVALS(*rparam,0,errcode);
2259 SSVAL(*rparam,2,0); /* converter word */
2265 /****************************************************************************
2266 get info about the server
2267 ****************************************************************************/
2268 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2269 int mdrcnt,int mprcnt,
2270 char **rdata,char **rparam,
2271 int *rdata_len,int *rparam_len)
2273 char *str1 = param+2;
2274 char *str2 = skip_string(str1,1);
2275 char *p = skip_string(str2,1);
2276 int uLevel = SVAL(p,0);
2280 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2282 /* check it's a supported varient */
2283 if (!prefix_ok(str1,"WrLh")) return False;
2286 if (strcmp(str2,"B16") != 0) return False;
2290 if (strcmp(str2,"B16BBDz") != 0) return False;
2294 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2299 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2304 if (strcmp(str2,"DN") != 0) return False;
2308 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2311 default: return False;
2314 *rdata_len = mdrcnt;
2315 *rdata = REALLOC(*rdata,*rdata_len);
2318 p2 = p + struct_len;
2320 srvstr_push(NULL, p,local_machine,16,
2321 STR_ASCII|STR_UPPER|STR_TERMINATE);
2326 struct srv_info_struct *servers=NULL;
2329 uint32 servertype= lp_default_server_announce();
2331 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2333 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2334 for (i=0;i<count;i++)
2335 if (strequal(servers[i].name,local_machine))
2337 servertype = servers[i].type;
2338 pstrcpy(comment,servers[i].comment);
2343 SCVAL(p,0,lp_major_announce_version());
2344 SCVAL(p,1,lp_minor_announce_version());
2345 SIVAL(p,2,servertype);
2347 if (mdrcnt == struct_len) {
2350 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2351 standard_sub_conn(conn,comment);
2352 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2353 p2 = skip_string(p2,1);
2358 return False; /* not yet implemented */
2361 *rdata_len = PTR_DIFF(p2,*rdata);
2364 *rparam = REALLOC(*rparam,*rparam_len);
2365 SSVAL(*rparam,0,NERR_Success);
2366 SSVAL(*rparam,2,0); /* converter word */
2367 SSVAL(*rparam,4,*rdata_len);
2373 /****************************************************************************
2374 get info about the server
2375 ****************************************************************************/
2376 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2377 int mdrcnt,int mprcnt,
2378 char **rdata,char **rparam,
2379 int *rdata_len,int *rparam_len)
2381 char *str1 = param+2;
2382 char *str2 = skip_string(str1,1);
2383 char *p = skip_string(str2,1);
2385 extern userdom_struct current_user_info;
2386 int level = SVAL(p,0);
2388 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2391 *rparam = REALLOC(*rparam,*rparam_len);
2393 /* check it's a supported varient */
2394 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2397 *rdata_len = mdrcnt + 1024;
2398 *rdata = REALLOC(*rdata,*rdata_len);
2400 SSVAL(*rparam,0,NERR_Success);
2401 SSVAL(*rparam,2,0); /* converter word */
2407 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2408 pstrcpy(p2,local_machine);
2410 p2 = skip_string(p2,1);
2413 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2414 pstrcpy(p2,current_user_info.smb_name);
2415 p2 = skip_string(p2,1);
2418 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2419 pstrcpy(p2,global_myworkgroup);
2421 p2 = skip_string(p2,1);
2424 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2425 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2428 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2429 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2430 p2 = skip_string(p2,1);
2433 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2435 p2 = skip_string(p2,1);
2438 *rdata_len = PTR_DIFF(p2,*rdata);
2440 SSVAL(*rparam,4,*rdata_len);
2445 /****************************************************************************
2446 get info about a user
2448 struct user_info_11 {
2449 char usri11_name[21]; 0-20
2451 char *usri11_comment; 22-25
2452 char *usri11_usr_comment; 26-29
2453 unsigned short usri11_priv; 30-31
2454 unsigned long usri11_auth_flags; 32-35
2455 long usri11_password_age; 36-39
2456 char *usri11_homedir; 40-43
2457 char *usri11_parms; 44-47
2458 long usri11_last_logon; 48-51
2459 long usri11_last_logoff; 52-55
2460 unsigned short usri11_bad_pw_count; 56-57
2461 unsigned short usri11_num_logons; 58-59
2462 char *usri11_logon_server; 60-63
2463 unsigned short usri11_country_code; 64-65
2464 char *usri11_workstations; 66-69
2465 unsigned long usri11_max_storage; 70-73
2466 unsigned short usri11_units_per_week; 74-75
2467 unsigned char *usri11_logon_hours; 76-79
2468 unsigned short usri11_code_page; 80-81
2473 usri11_name specifies the user name for which information is retireved
2475 usri11_pad aligns the next data structure element to a word boundary
2477 usri11_comment is a null terminated ASCII comment
2479 usri11_user_comment is a null terminated ASCII comment about the user
2481 usri11_priv specifies the level of the privilege assigned to the user.
2482 The possible values are:
2484 Name Value Description
2485 USER_PRIV_GUEST 0 Guest privilege
2486 USER_PRIV_USER 1 User privilege
2487 USER_PRV_ADMIN 2 Administrator privilege
2489 usri11_auth_flags specifies the account operator privileges. The
2490 possible values are:
2492 Name Value Description
2493 AF_OP_PRINT 0 Print operator
2496 Leach, Naik [Page 28]
2500 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2503 AF_OP_COMM 1 Communications operator
2504 AF_OP_SERVER 2 Server operator
2505 AF_OP_ACCOUNTS 3 Accounts operator
2508 usri11_password_age specifies how many seconds have elapsed since the
2509 password was last changed.
2511 usri11_home_dir points to a null terminated ASCII string that contains
2512 the path name of the user's home directory.
2514 usri11_parms points to a null terminated ASCII string that is set
2515 aside for use by applications.
2517 usri11_last_logon specifies the time when the user last logged on.
2518 This value is stored as the number of seconds elapsed since
2519 00:00:00, January 1, 1970.
2521 usri11_last_logoff specifies the time when the user last logged off.
2522 This value is stored as the number of seconds elapsed since
2523 00:00:00, January 1, 1970. A value of 0 means the last logoff
2526 usri11_bad_pw_count specifies the number of incorrect passwords
2527 entered since the last successful logon.
2529 usri11_log1_num_logons specifies the number of times this user has
2530 logged on. A value of -1 means the number of logons is unknown.
2532 usri11_logon_server points to a null terminated ASCII string that
2533 contains the name of the server to which logon requests are sent.
2534 A null string indicates logon requests should be sent to the
2537 usri11_country_code specifies the country code for the user's language
2540 usri11_workstations points to a null terminated ASCII string that
2541 contains the names of workstations the user may log on from.
2542 There may be up to 8 workstations, with the names separated by
2543 commas. A null strings indicates there are no restrictions.
2545 usri11_max_storage specifies the maximum amount of disk space the user
2546 can occupy. A value of 0xffffffff indicates there are no
2549 usri11_units_per_week specifies the equal number of time units into
2550 which a week is divided. This value must be equal to 168.
2552 usri11_logon_hours points to a 21 byte (168 bits) string that
2553 specifies the time during which the user can log on. Each bit
2554 represents one unique hour in a week. The first bit (bit 0, word
2555 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2559 Leach, Naik [Page 29]
2563 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2566 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2567 are no restrictions.
2569 usri11_code_page specifies the code page for the user's language of
2572 All of the pointers in this data structure need to be treated
2573 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2574 to be ignored. The converter word returned in the parameters section
2575 needs to be subtracted from the lower 16 bits to calculate an offset
2576 into the return buffer where this ASCII string resides.
2578 There is no auxiliary data in the response.
2580 ****************************************************************************/
2582 #define usri11_name 0
2583 #define usri11_pad 21
2584 #define usri11_comment 22
2585 #define usri11_usr_comment 26
2586 #define usri11_full_name 30
2587 #define usri11_priv 34
2588 #define usri11_auth_flags 36
2589 #define usri11_password_age 40
2590 #define usri11_homedir 44
2591 #define usri11_parms 48
2592 #define usri11_last_logon 52
2593 #define usri11_last_logoff 56
2594 #define usri11_bad_pw_count 60
2595 #define usri11_num_logons 62
2596 #define usri11_logon_server 64
2597 #define usri11_country_code 68
2598 #define usri11_workstations 70
2599 #define usri11_max_storage 74
2600 #define usri11_units_per_week 78
2601 #define usri11_logon_hours 80
2602 #define usri11_code_page 84
2603 #define usri11_end 86
2605 #define USER_PRIV_GUEST 0
2606 #define USER_PRIV_USER 1
2607 #define USER_PRIV_ADMIN 2
2609 #define AF_OP_PRINT 0
2610 #define AF_OP_COMM 1
2611 #define AF_OP_SERVER 2
2612 #define AF_OP_ACCOUNTS 3
2615 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2616 int mdrcnt,int mprcnt,
2617 char **rdata,char **rparam,
2618 int *rdata_len,int *rparam_len)
2620 char *str1 = param+2;
2621 char *str2 = skip_string(str1,1);
2622 char *UserName = skip_string(str2,1);
2623 char *p = skip_string(UserName,1);
2624 int uLevel = SVAL(p,0);
2627 /* get NIS home of a previously validated user - simeon */
2628 /* With share level security vuid will always be zero.
2629 Don't depend on vuser being non-null !!. JRA */
2630 user_struct *vuser = get_valid_user_struct(vuid);
2632 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2633 vuser->user.unix_name));
2636 *rparam = REALLOC(*rparam,*rparam_len);
2638 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2640 /* check it's a supported variant */
2641 if (strcmp(str1,"zWrLh") != 0) return False;
2644 case 0: p2 = "B21"; break;
2645 case 1: p2 = "B21BB16DWzzWz"; break;
2646 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2647 case 10: p2 = "B21Bzzz"; break;
2648 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2649 default: return False;
2652 if (strcmp(p2,str2) != 0) return False;
2654 *rdata_len = mdrcnt + 1024;
2655 *rdata = REALLOC(*rdata,*rdata_len);
2657 SSVAL(*rparam,0,NERR_Success);
2658 SSVAL(*rparam,2,0); /* converter word */
2661 p2 = p + usri11_end;
2664 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2668 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2673 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2674 pstrcpy(p2,"Comment");
2675 p2 = skip_string(p2,1);
2677 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2678 pstrcpy(p2,"UserComment");
2679 p2 = skip_string(p2,1);
2681 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2682 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2683 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2684 p2 = skip_string(p2,1);
2687 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2689 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2690 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2691 SIVALS(p,usri11_password_age,-1); /* password age */
2692 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2693 pstrcpy(p2, lp_logon_home());
2694 standard_sub_conn(conn, p2);
2695 p2 = skip_string(p2,1);
2696 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2698 p2 = skip_string(p2,1);
2699 SIVAL(p,usri11_last_logon,0); /* last logon */
2700 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2701 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2702 SSVALS(p,usri11_num_logons,-1); /* num logons */
2703 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2704 pstrcpy(p2,"\\\\*");
2705 p2 = skip_string(p2,1);
2706 SSVAL(p,usri11_country_code,0); /* country code */
2708 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2710 p2 = skip_string(p2,1);
2712 SIVALS(p,usri11_max_storage,-1); /* max storage */
2713 SSVAL(p,usri11_units_per_week,168); /* units per week */
2714 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2716 /* a simple way to get logon hours at all times. */
2718 SCVAL(p2,21,0); /* fix zero termination */
2719 p2 = skip_string(p2,1);
2721 SSVAL(p,usri11_code_page,0); /* code page */
2723 if (uLevel == 1 || uLevel == 2)
2725 memset(p+22,' ',16); /* password */
2726 SIVALS(p,38,-1); /* password age */
2728 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2729 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2730 pstrcpy(p2,lp_logon_home());
2731 standard_sub_conn(conn, p2);
2732 p2 = skip_string(p2,1);
2733 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2735 SSVAL(p,52,0); /* flags */
2736 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2737 pstrcpy(p2,lp_logon_script());
2738 standard_sub_conn( conn, p2 );
2739 p2 = skip_string(p2,1);
2742 SIVAL(p,60,0); /* auth_flags */
2743 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2744 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2745 p2 = skip_string(p2,1);
2746 SIVAL(p,68,0); /* urs_comment */
2747 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2749 p2 = skip_string(p2,1);
2750 SIVAL(p,76,0); /* workstations */
2751 SIVAL(p,80,0); /* last_logon */
2752 SIVAL(p,84,0); /* last_logoff */
2753 SIVALS(p,88,-1); /* acct_expires */
2754 SIVALS(p,92,-1); /* max_storage */
2755 SSVAL(p,96,168); /* units_per_week */
2756 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2759 SSVALS(p,102,-1); /* bad_pw_count */
2760 SSVALS(p,104,-1); /* num_logons */
2761 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2762 pstrcpy(p2,"\\\\%L");
2763 standard_sub_conn(conn, p2);
2764 p2 = skip_string(p2,1);
2765 SSVAL(p,110,49); /* country_code */
2766 SSVAL(p,112,860); /* code page */
2770 *rdata_len = PTR_DIFF(p2,*rdata);
2772 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2777 /*******************************************************************
2778 get groups that a user is a member of
2779 ******************************************************************/
2780 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2781 int mdrcnt,int mprcnt,
2782 char **rdata,char **rparam,
2783 int *rdata_len,int *rparam_len)
2785 char *str1 = param+2;
2786 char *str2 = skip_string(str1,1);
2787 char *UserName = skip_string(str2,1);
2788 char *p = skip_string(UserName,1);
2789 int uLevel = SVAL(p,0);
2794 *rparam = REALLOC(*rparam,*rparam_len);
2796 /* check it's a supported varient */
2797 if (strcmp(str1,"zWrLeh") != 0) return False;
2799 case 0: p2 = "B21"; break;
2800 default: return False;
2802 if (strcmp(p2,str2) != 0) return False;
2804 *rdata_len = mdrcnt + 1024;
2805 *rdata = REALLOC(*rdata,*rdata_len);
2807 SSVAL(*rparam,0,NERR_Success);
2808 SSVAL(*rparam,2,0); /* converter word */
2812 /* XXXX we need a real SAM database some day */
2813 pstrcpy(p,"Users"); p += 21; count++;
2814 pstrcpy(p,"Domain Users"); p += 21; count++;
2815 pstrcpy(p,"Guests"); p += 21; count++;
2816 pstrcpy(p,"Domain Guests"); p += 21; count++;
2818 *rdata_len = PTR_DIFF(p,*rdata);
2820 SSVAL(*rparam,4,count); /* is this right?? */
2821 SSVAL(*rparam,6,count); /* is this right?? */
2827 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2828 int mdrcnt,int mprcnt,
2829 char **rdata,char **rparam,
2830 int *rdata_len,int *rparam_len)
2832 char *str1 = param+2;
2833 char *str2 = skip_string(str1,1);
2834 char *p = skip_string(str2,1);
2836 struct pack_desc desc;
2842 memset((char *)&desc,'\0',sizeof(desc));
2844 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2846 /* check it's a supported varient */
2847 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2848 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2849 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2851 desc.buflen = mdrcnt;
2852 desc.subformat = NULL;
2855 if (init_package(&desc,1,0))
2857 PACKI(&desc,"W",0); /* code */
2858 PACKS(&desc,"B21",name); /* eff. name */
2859 PACKS(&desc,"B",""); /* pad */
2861 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2862 PACKI(&desc,"D",0); /* auth flags XXX */
2863 PACKI(&desc,"W",0); /* num logons */
2864 PACKI(&desc,"W",0); /* bad pw count */
2865 PACKI(&desc,"D",0); /* last logon */
2866 PACKI(&desc,"D",-1); /* last logoff */
2867 PACKI(&desc,"D",-1); /* logoff time */
2868 PACKI(&desc,"D",-1); /* kickoff time */
2869 PACKI(&desc,"D",0); /* password age */
2870 PACKI(&desc,"D",0); /* password can change */
2871 PACKI(&desc,"D",-1); /* password must change */
2874 fstrcpy(mypath,"\\\\");
2875 fstrcat(mypath,local_machine);
2877 PACKS(&desc,"z",mypath); /* computer */
2879 PACKS(&desc,"z",global_myworkgroup);/* domain */
2881 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2882 /* made sure all macros are fully substituted and available */
2884 pstring logon_script;
2885 pstrcpy(logon_script,lp_logon_script());
2886 standard_sub_conn( conn, logon_script );
2887 PACKS(&desc,"z", logon_script); /* script path */
2889 /* End of JHT mods */
2891 PACKI(&desc,"D",0x00000000); /* reserved */
2894 *rdata_len = desc.usedlen;
2896 *rparam = REALLOC(*rparam,*rparam_len);
2897 SSVALS(*rparam,0,desc.errcode);
2899 SSVAL(*rparam,4,desc.neededlen);
2901 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2906 /****************************************************************************
2907 api_WAccessGetUserPerms
2908 ****************************************************************************/
2909 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2910 int mdrcnt,int mprcnt,
2911 char **rdata,char **rparam,
2912 int *rdata_len,int *rparam_len)
2914 char *str1 = param+2;
2915 char *str2 = skip_string(str1,1);
2916 char *user = skip_string(str2,1);
2917 char *resource = skip_string(user,1);
2919 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2921 /* check it's a supported varient */
2922 if (strcmp(str1,"zzh") != 0) return False;
2923 if (strcmp(str2,"") != 0) return False;
2926 *rparam = REALLOC(*rparam,*rparam_len);
2927 SSVALS(*rparam,0,0); /* errorcode */
2928 SSVAL(*rparam,2,0); /* converter word */
2929 SSVAL(*rparam,4,0x7f); /* permission flags */
2934 /****************************************************************************
2935 api_WPrintJobEnumerate
2936 ****************************************************************************/
2937 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2938 int mdrcnt,int mprcnt,
2939 char **rdata,char **rparam,
2940 int *rdata_len,int *rparam_len)
2942 char *str1 = param+2;
2943 char *str2 = skip_string(str1,1);
2944 char *p = skip_string(str2,1);
2950 struct pack_desc desc;
2951 print_queue_struct *queue=NULL;
2952 print_status_struct status;
2957 memset((char *)&desc,'\0',sizeof(desc));
2958 memset((char *)&status,'\0',sizeof(status));
2960 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2962 /* check it's a supported varient */
2963 if (strcmp(str1,"WWrLh") != 0) return False;
2964 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2967 snum = print_job_snum(job);
2969 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2971 count = print_queue_status(snum,&queue,&status);
2972 for (i = 0; i < count; i++) {
2973 if (queue[i].job == job) break;
2977 *rdata = REALLOC(*rdata,mdrcnt);
2979 desc.buflen = mdrcnt;
2982 * Don't return data but need to get correct length
2983 * init_package will return wrong size if buflen=0
2985 desc.buflen = getlen(desc.format);
2986 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2989 if (init_package(&desc,1,0)) {
2991 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2992 *rdata_len = desc.usedlen;
2995 desc.errcode = NERR_JobNotFound;
3001 *rparam = REALLOC(*rparam,*rparam_len);
3002 SSVALS(*rparam,0,desc.errcode);
3004 SSVAL(*rparam,4,desc.neededlen);
3009 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3013 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3014 int mdrcnt,int mprcnt,
3015 char **rdata,char **rparam,
3016 int *rdata_len,int *rparam_len)
3018 char *str1 = param+2;
3019 char *str2 = skip_string(str1,1);
3020 char *p = skip_string(str2,1);
3026 struct pack_desc desc;
3027 print_queue_struct *queue=NULL;
3028 print_status_struct status;
3030 memset((char *)&desc,'\0',sizeof(desc));
3031 memset((char *)&status,'\0',sizeof(status));
3033 p = skip_string(p,1);
3036 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3038 /* check it's a supported varient */
3039 if (strcmp(str1,"zWrLeh") != 0) return False;
3040 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3041 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3043 snum = lp_servicenumber(name);
3044 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3045 int pnum = lp_servicenumber(PRINTERS_NAME);
3047 lp_add_printer(name,pnum);
3048 snum = lp_servicenumber(name);
3052 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3054 count = print_queue_status(snum,&queue,&status);
3055 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3057 desc.buflen = mdrcnt;
3059 if (init_package(&desc,count,0)) {
3061 for (i = 0; i < count; i++) {
3062 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3063 if (desc.errcode == NERR_Success) succnt = i+1;
3067 *rdata_len = desc.usedlen;
3070 *rparam = REALLOC(*rparam,*rparam_len);
3071 SSVALS(*rparam,0,desc.errcode);
3073 SSVAL(*rparam,4,succnt);
3074 SSVAL(*rparam,6,count);
3078 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3082 static int check_printdest_info(struct pack_desc* desc,
3083 int uLevel, char* id)
3085 desc->subformat = NULL;
3087 case 0: desc->format = "B9"; break;
3088 case 1: desc->format = "B9B21WWzW"; break;
3089 case 2: desc->format = "z"; break;
3090 case 3: desc->format = "zzzWWzzzWW"; break;
3091 default: return False;
3093 if (strcmp(desc->format,id) != 0) return False;
3097 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3098 struct pack_desc* desc)
3101 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3102 buf[sizeof(buf)-1] = 0;
3105 PACKS(desc,"B9",buf); /* szName */
3107 PACKS(desc,"B21",""); /* szUserName */
3108 PACKI(desc,"W",0); /* uJobId */
3109 PACKI(desc,"W",0); /* fsStatus */
3110 PACKS(desc,"z",""); /* pszStatus */
3111 PACKI(desc,"W",0); /* time */
3114 if (uLevel == 2 || uLevel == 3) {
3115 PACKS(desc,"z",buf); /* pszPrinterName */
3117 PACKS(desc,"z",""); /* pszUserName */
3118 PACKS(desc,"z",""); /* pszLogAddr */
3119 PACKI(desc,"W",0); /* uJobId */
3120 PACKI(desc,"W",0); /* fsStatus */
3121 PACKS(desc,"z",""); /* pszStatus */
3122 PACKS(desc,"z",""); /* pszComment */
3123 PACKS(desc,"z","NULL"); /* pszDrivers */
3124 PACKI(desc,"W",0); /* time */
3125 PACKI(desc,"W",0); /* pad1 */
3130 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3131 int mdrcnt,int mprcnt,
3132 char **rdata,char **rparam,
3133 int *rdata_len,int *rparam_len)
3135 char *str1 = param+2;
3136 char *str2 = skip_string(str1,1);
3137 char *p = skip_string(str2,1);
3138 char* PrinterName = p;
3140 struct pack_desc desc;
3144 memset((char *)&desc,'\0',sizeof(desc));
3146 p = skip_string(p,1);
3149 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3151 /* check it's a supported varient */
3152 if (strcmp(str1,"zWrLh") != 0) return False;
3153 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3155 snum = lp_servicenumber(PrinterName);
3156 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3157 int pnum = lp_servicenumber(PRINTERS_NAME);
3159 lp_add_printer(PrinterName,pnum);
3160 snum = lp_servicenumber(PrinterName);
3166 desc.errcode = NERR_DestNotFound;
3171 *rdata = REALLOC(*rdata,mdrcnt);
3173 desc.buflen = mdrcnt;
3176 * Don't return data but need to get correct length
3177 * init_package will return wrong size if buflen=0
3179 desc.buflen = getlen(desc.format);
3180 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3182 if (init_package(&desc,1,0)) {
3183 fill_printdest_info(conn,snum,uLevel,&desc);
3185 *rdata_len = desc.usedlen;
3189 *rparam = REALLOC(*rparam,*rparam_len);
3190 SSVALS(*rparam,0,desc.errcode);
3192 SSVAL(*rparam,4,desc.neededlen);
3194 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3199 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3200 int mdrcnt,int mprcnt,
3201 char **rdata,char **rparam,
3202 int *rdata_len,int *rparam_len)
3204 char *str1 = param+2;
3205 char *str2 = skip_string(str1,1);
3206 char *p = skip_string(str2,1);
3210 struct pack_desc desc;
3211 int services = lp_numservices();
3213 memset((char *)&desc,'\0',sizeof(desc));
3217 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3219 /* check it's a supported varient */
3220 if (strcmp(str1,"WrLeh") != 0) return False;
3221 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3224 for (i = 0; i < services; i++)
3225 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3228 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3230 desc.buflen = mdrcnt;
3231 if (init_package(&desc,queuecnt,0)) {
3234 for (i = 0; i < services; i++) {
3235 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3236 fill_printdest_info(conn,i,uLevel,&desc);
3238 if (desc.errcode == NERR_Success) succnt = n;
3243 *rdata_len = desc.usedlen;
3246 *rparam = REALLOC(*rparam,*rparam_len);
3247 SSVALS(*rparam,0,desc.errcode);
3249 SSVAL(*rparam,4,succnt);
3250 SSVAL(*rparam,6,queuecnt);
3252 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3256 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3257 int mdrcnt,int mprcnt,
3258 char **rdata,char **rparam,
3259 int *rdata_len,int *rparam_len)
3261 char *str1 = param+2;
3262 char *str2 = skip_string(str1,1);
3263 char *p = skip_string(str2,1);
3266 struct pack_desc desc;
3268 memset((char *)&desc,'\0',sizeof(desc));
3272 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3274 /* check it's a supported varient */
3275 if (strcmp(str1,"WrLeh") != 0) return False;
3276 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3278 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3280 desc.buflen = mdrcnt;
3281 if (init_package(&desc,1,0)) {
3282 PACKS(&desc,"B41","NULL");
3285 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3287 *rdata_len = desc.usedlen;
3290 *rparam = REALLOC(*rparam,*rparam_len);
3291 SSVALS(*rparam,0,desc.errcode);
3293 SSVAL(*rparam,4,succnt);
3296 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3300 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3301 int mdrcnt,int mprcnt,
3302 char **rdata,char **rparam,
3303 int *rdata_len,int *rparam_len)
3305 char *str1 = param+2;
3306 char *str2 = skip_string(str1,1);
3307 char *p = skip_string(str2,1);
3310 struct pack_desc desc;
3312 memset((char *)&desc,'\0',sizeof(desc));
3316 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3318 /* check it's a supported varient */
3319 if (strcmp(str1,"WrLeh") != 0) return False;
3320 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3322 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3324 desc.buflen = mdrcnt;
3326 if (init_package(&desc,1,0)) {
3327 PACKS(&desc,"B13","lpd");
3330 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3332 *rdata_len = desc.usedlen;
3335 *rparam = REALLOC(*rparam,*rparam_len);
3336 SSVALS(*rparam,0,desc.errcode);
3338 SSVAL(*rparam,4,succnt);
3341 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3345 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3346 int mdrcnt,int mprcnt,
3347 char **rdata,char **rparam,
3348 int *rdata_len,int *rparam_len)
3350 char *str1 = param+2;
3351 char *str2 = skip_string(str1,1);
3352 char *p = skip_string(str2,1);
3355 struct pack_desc desc;
3357 memset((char *)&desc,'\0',sizeof(desc));
3361 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3363 /* check it's a supported varient */
3364 if (strcmp(str1,"WrLeh") != 0) return False;
3365 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3367 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3368 memset((char *)&desc,'\0',sizeof(desc));
3370 desc.buflen = mdrcnt;
3372 if (init_package(&desc,1,0)) {
3373 PACKS(&desc,"B13","lp0");
3376 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3378 *rdata_len = desc.usedlen;
3381 *rparam = REALLOC(*rparam,*rparam_len);
3382 SSVALS(*rparam,0,desc.errcode);
3384 SSVAL(*rparam,4,succnt);
3387 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3391 struct session_info {
3399 struct sessions_info {
3401 struct session_info *session_list;
3404 static int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
3406 struct sessions_info *sinfo = state;
3407 struct session_info *curinfo = NULL;
3408 struct sessionid *sessid = (struct sessionid *) dbuf.dptr;
3411 sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info));
3413 curinfo = &(sinfo->session_list[sinfo->count - 1]);
3415 safe_strcpy(curinfo->machine, sessid->remote_machine,
3416 sizeof(curinfo->machine));
3417 safe_strcpy(curinfo->username, uidtoname(sessid->uid),
3418 sizeof(curinfo->username));
3419 DEBUG(7,("gather_sessioninfo session from %s@%s\n",
3420 curinfo->username, curinfo->machine));
3424 /****************************************************************************
3426 ****************************************************************************/
3427 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3428 int mdrcnt,int mprcnt,
3429 char **rdata,char **rparam,
3430 int *rdata_len,int *rparam_len)
3433 char *str1 = param+2;
3434 char *str2 = skip_string(str1,1);
3435 char *p = skip_string(str2,1);
3437 struct pack_desc desc;
3438 struct sessions_info sinfo;
3441 memset((char *)&desc,'\0',sizeof(desc));
3445 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3446 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3447 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3449 /* check it's a supported varient */
3450 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3451 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3454 sinfo.session_list = NULL;
3456 if (!session_traverse(gather_sessioninfo, &sinfo)) {
3457 DEBUG(4,("RNetSessionEnum session_traverse failed\n"));
3461 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3462 memset((char *)&desc,'\0',sizeof(desc));
3464 desc.buflen = mdrcnt;
3466 if (!init_package(&desc,sinfo.count,0)) {
3470 for(i=0; i<sinfo.count; i++) {
3471 PACKS(&desc, "z", sinfo.session_list[i].machine);
3472 PACKS(&desc, "z", sinfo.session_list[i].username);
3473 PACKI(&desc, "W", 1); /* num conns */
3474 PACKI(&desc, "W", 0); /* num opens */
3475 PACKI(&desc, "W", 1); /* num users */
3476 PACKI(&desc, "D", 0); /* session time */
3477 PACKI(&desc, "D", 0); /* idle time */
3478 PACKI(&desc, "D", 0); /* flags */
3479 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3482 *rdata_len = desc.usedlen;
3485 *rparam = REALLOC(*rparam,*rparam_len);
3486 SSVALS(*rparam,0,desc.errcode);
3487 SSVAL(*rparam,2,0); /* converter */
3488 SSVAL(*rparam,4,sinfo.count); /* count */
3490 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3495 /****************************************************************************
3496 The buffer was too small
3497 ****************************************************************************/
3499 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3500 int mdrcnt,int mprcnt,
3501 char **rdata,char **rparam,
3502 int *rdata_len,int *rparam_len)
3504 *rparam_len = MIN(*rparam_len,mprcnt);
3505 *rparam = REALLOC(*rparam,*rparam_len);
3509 SSVAL(*rparam,0,NERR_BufTooSmall);
3511 DEBUG(3,("Supplied buffer too small in API command\n"));
3517 /****************************************************************************
3518 The request is not supported
3519 ****************************************************************************/
3521 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3522 int mdrcnt,int mprcnt,
3523 char **rdata,char **rparam,
3524 int *rdata_len,int *rparam_len)
3527 *rparam = REALLOC(*rparam,*rparam_len);
3531 SSVAL(*rparam,0,NERR_notsupported);
3532 SSVAL(*rparam,2,0); /* converter word */
3534 DEBUG(3,("Unsupported API command\n"));
3546 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3547 int,int,char **,char **,int *,int *);
3549 } api_commands[] = {
3550 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum,0},
3551 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo,0},
3552 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd,0},
3553 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum,0},
3554 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo,0},
3555 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum,0},
3556 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers,0},
3557 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum,0},
3558 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo,0},
3559 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups,0},
3560 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo,0},
3561 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum,0},
3562 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo,0},
3563 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl,0},
3564 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl,0},
3565 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate,0},
3566 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo,0},
3567 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel,0},
3568 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel,0},
3569 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel,0},
3570 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum,0},
3571 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo,0},
3572 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD,0},
3573 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl,0},
3574 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum,0},
3575 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms,0},
3576 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword,0},
3577 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon,0},
3578 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo,0},
3579 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum,0},
3580 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum,0},
3581 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum,0},
3582 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword,0},
3583 {NULL, -1, api_Unsupported,0}};
3586 /****************************************************************************
3587 Handle remote api calls
3588 ****************************************************************************/
3590 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3591 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3595 char *rparam = NULL;
3602 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3606 api_command = SVAL(params,0);
3608 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3611 skip_string(params+2,1),
3612 tdscnt,tpscnt,mdrcnt,mprcnt));
3614 for (i=0;api_commands[i].name;i++) {
3615 if (api_commands[i].id == api_command && api_commands[i].fn) {
3616 DEBUG(3,("Doing %s\n",api_commands[i].name));
3621 rdata = (char *)malloc(1024);
3623 memset(rdata,'\0',1024);
3625 rparam = (char *)malloc(1024);
3627 memset(rparam,'\0',1024);
3629 if(!rdata || !rparam) {
3630 DEBUG(0,("api_reply: malloc fail !\n"));
3634 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3635 &rdata,&rparam,&rdata_len,&rparam_len);
3638 if (rdata_len > mdrcnt ||
3639 rparam_len > mprcnt) {
3640 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3641 &rdata,&rparam,&rdata_len,&rparam_len);
3644 /* if we get False back then it's actually unsupported */
3646 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3647 &rdata,&rparam,&rdata_len,&rparam_len);
3649 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);