3 Unix SMB/Netbios implementation.
5 Inter-process communication and named pipe handling
6 Copyright (C) Andrew Tridgell 1992-1998
9 Copyright (C) John H Terpstra 1995-1998
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 This file handles the named pipe and mailslot calls
27 in the SMBtrans protocol
37 extern int DEBUGLEVEL;
39 extern fstring local_machine;
40 extern pstring global_myname;
41 extern fstring global_myworkgroup;
43 #define NERR_Success 0
44 #define NERR_badpass 86
45 #define NERR_notsupported 50
47 #define NERR_BASE (2100)
48 #define NERR_BufTooSmall (NERR_BASE+23)
49 #define NERR_JobNotFound (NERR_BASE+51)
50 #define NERR_DestNotFound (NERR_BASE+52)
52 #define ACCESS_READ 0x01
53 #define ACCESS_WRITE 0x02
54 #define ACCESS_CREATE 0x04
56 #define SHPWLEN 8 /* share password length */
58 static BOOL api_Unsupported(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);
62 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
63 int mdrcnt,int mprcnt,
64 char **rdata,char **rparam,
65 int *rdata_len,int *rparam_len);
68 static int CopyExpanded(connection_struct *conn,
69 int snum, char** dst, char* src, int* n)
74 if (!src || !dst || !n || !(*dst)) return(0);
76 StrnCpy(buf,src,sizeof(buf)/2);
77 pstring_sub(buf,"%S",lp_servicename(snum));
78 standard_sub_conn(conn,buf);
86 static int CopyAndAdvance(char** dst, char* src, int* n)
89 if (!src || !dst || !n || !(*dst)) return(0);
90 StrnCpy(*dst,src,*n-1);
97 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
101 StrnCpy(buf,s,sizeof(buf)/2);
102 pstring_sub(buf,"%S",lp_servicename(snum));
103 standard_sub_conn(conn,buf);
104 return strlen(buf) + 1;
107 static char* Expand(connection_struct *conn, int snum, char* s)
110 if (!s) return(NULL);
111 StrnCpy(buf,s,sizeof(buf)/2);
112 pstring_sub(buf,"%S",lp_servicename(snum));
113 standard_sub_conn(conn,buf);
117 /*******************************************************************
118 check a API string for validity when we only need to check the prefix
119 ******************************************************************/
120 static BOOL prefix_ok(char *str,char *prefix)
122 return(strncmp(str,prefix,strlen(prefix)) == 0);
126 char* format; /* formatstring for structure */
127 char* subformat; /* subformat for structure */
128 char* base; /* baseaddress of buffer */
129 int buflen; /* remaining size for fixed part; on init: length of base */
130 int subcount; /* count of substructures */
131 char* structbuf; /* pointer into buffer for remaining fixed part */
132 int stringlen; /* remaining size for variable part */
133 char* stringbuf; /* pointer into buffer for remaining variable part */
134 int neededlen; /* total needed size */
135 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
136 char* curpos; /* current position; pointer into format or subformat */
140 static int get_counter(char** p)
143 if (!p || !(*p)) return(1);
144 if (!isdigit((int)**p)) return 1;
148 n = 10 * n + (i - '0');
155 static int getlen(char* p)
161 case 'W': /* word (2 byte) */
164 case 'K': /* status word? (2 byte) */
167 case 'N': /* count of substructures (word) at end */
170 case 'D': /* double word (4 byte) */
171 case 'z': /* offset to zero terminated string (4 byte) */
172 case 'l': /* offset to user data (4 byte) */
175 case 'b': /* offset to data (with counter) (4 byte) */
179 case 'B': /* byte (with optional counter) */
180 n += get_counter(&p);
187 static BOOL init_package(struct pack_desc* p, int count, int subcount)
192 if (!p->format || !p->base) return(False);
194 i = count * getlen(p->format);
195 if (p->subformat) i += subcount * getlen(p->subformat);
196 p->structbuf = p->base;
200 p->curpos = p->format;
204 p->errcode = ERRmoredata;
207 p->errcode = NERR_Success;
210 p->stringbuf = p->base + i;
212 return(p->errcode == NERR_Success);
216 static int package(struct pack_desc* p, ...)
219 static int package(va_alist)
225 int needed=0, stringneeded;
227 int is_string=0, stringused;
234 p = va_arg(args,struct pack_desc *);
239 p->curpos = p->format;
241 p->curpos = p->subformat;
246 str = va_arg(args,char*);
247 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
256 switch( *p->curpos++ ) {
257 case 'W': /* word (2 byte) */
259 temp = va_arg(args,int);
260 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
262 case 'K': /* status word? (2 byte) */
264 temp = va_arg(args,int);
265 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
267 case 'N': /* count of substructures (word) at end */
269 p->subcount = va_arg(args,int);
270 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
272 case 'D': /* double word (4 byte) */
274 temp = va_arg(args,int);
275 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
277 case 'B': /* byte (with optional counter) */
278 needed = get_counter(&p->curpos);
280 char *s = va_arg(args,char*);
281 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
284 case 'z': /* offset to zero terminated string (4 byte) */
285 str = va_arg(args,char*);
286 stringneeded = (str ? strlen(str)+1 : 0);
289 case 'l': /* offset to user data (4 byte) */
290 str = va_arg(args,char*);
291 stringneeded = va_arg(args,int);
294 case 'b': /* offset to data (with counter) (4 byte) */
295 str = va_arg(args,char*);
296 stringneeded = get_counter(&p->curpos);
301 if (stringneeded >= 0) {
303 if (p->buflen >= needed) {
304 stringused = stringneeded;
305 if (stringused > p->stringlen) {
306 stringused = (is_string ? p->stringlen : 0);
307 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
310 SIVAL(p->structbuf,0,0);
312 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
313 memcpy(p->stringbuf,str?str:"",stringused);
314 if (is_string) p->stringbuf[stringused-1] = '\0';
315 p->stringbuf += stringused;
316 p->stringlen -= stringused;
317 p->usedlen += stringused;
320 p->neededlen += stringneeded;
322 p->neededlen += needed;
323 if (p->buflen >= needed) {
324 p->structbuf += needed;
326 p->usedlen += needed;
329 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
335 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
336 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
338 #define PACK(desc,t,v) package(desc,v)
339 #define PACKl(desc,t,v,l) package(desc,v,l)
342 static void PACKI(struct pack_desc* desc,char *t,int v)
347 static void PACKS(struct pack_desc* desc,char *t,char *v)
353 /****************************************************************************
355 ****************************************************************************/
356 static void PackDriverData(struct pack_desc* desc)
358 char drivdata[4+4+32];
359 SIVAL(drivdata,0,sizeof drivdata); /* cb */
360 SIVAL(drivdata,4,1000); /* lVersion */
361 memset(drivdata+8,0,32); /* szDeviceName */
362 pstrcpy(drivdata+8,"NULL");
363 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
366 static int check_printq_info(struct pack_desc* desc,
367 int uLevel, char *id1, char *id2)
369 desc->subformat = NULL;
372 desc->format = "B13";
375 desc->format = "B13BWWWzzzzzWW";
378 desc->format = "B13BWWWzzzzzWN";
379 desc->subformat = "WB21BB16B10zWWzDDz";
382 desc->format = "zWWWWzzzzWWzzl";
385 desc->format = "zWWWWzzzzWNzzl";
386 desc->subformat = "WWzWWDDzz";
395 desc->format = "WzzzzzzzzN";
396 desc->subformat = "z";
398 default: return False;
400 if (strcmp(desc->format,id1) != 0) return False;
401 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
406 #define JOB_STATUS_QUEUED 0
407 #define JOB_STATUS_PAUSED 1
408 #define JOB_STATUS_SPOOLING 2
409 #define JOB_STATUS_PRINTING 3
410 #define JOB_STATUS_PRINTED 4
412 #define QUEUE_STATUS_PAUSED 1
413 #define QUEUE_STATUS_ERROR 2
415 /* turn a print job status into a on the wire status
417 static int printj_status(int v)
421 return JOB_STATUS_QUEUED;
423 return JOB_STATUS_PAUSED;
425 return JOB_STATUS_SPOOLING;
427 return JOB_STATUS_PRINTING;
432 /* turn a print queue status into a on the wire status
434 static int printq_status(int v)
440 return QUEUE_STATUS_PAUSED;
442 return QUEUE_STATUS_ERROR;
445 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
446 struct pack_desc* desc,
447 print_queue_struct* queue, int n)
449 time_t t = queue->time;
451 /* the client expects localtime */
454 PACKI(desc,"W",queue->job); /* uJobId */
456 PACKS(desc,"B21",queue->user); /* szUserName */
457 PACKS(desc,"B",""); /* pad */
458 PACKS(desc,"B16",""); /* szNotifyName */
459 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
460 PACKS(desc,"z",""); /* pszParms */
461 PACKI(desc,"W",n+1); /* uPosition */
462 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
463 PACKS(desc,"z",""); /* pszStatus */
464 PACKI(desc,"D",t); /* ulSubmitted */
465 PACKI(desc,"D",queue->size); /* ulSize */
466 PACKS(desc,"z",queue->file); /* pszComment */
468 if (uLevel == 2 || uLevel == 3) {
469 PACKI(desc,"W",queue->priority); /* uPriority */
470 PACKS(desc,"z",queue->user); /* pszUserName */
471 PACKI(desc,"W",n+1); /* uPosition */
472 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
473 PACKI(desc,"D",t); /* ulSubmitted */
474 PACKI(desc,"D",queue->size); /* ulSize */
475 PACKS(desc,"z","Samba"); /* pszComment */
476 PACKS(desc,"z",queue->file); /* pszDocument */
478 PACKS(desc,"z",""); /* pszNotifyName */
479 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
480 PACKS(desc,"z",""); /* pszParms */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
483 PACKS(desc,"z","lpd"); /* pszQProcName */
484 PACKS(desc,"z",""); /* pszQProcParms */
485 PACKS(desc,"z","NULL"); /* pszDriverName */
486 PackDriverData(desc); /* pDriverData */
487 PACKS(desc,"z",""); /* pszPrinterName */
492 /********************************************************************
493 Respond to the DosPrintQInfo command with a level of 52
494 This is used to get printer driver information for Win9x clients
495 ********************************************************************/
496 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
497 struct pack_desc* desc,
498 int count, print_queue_struct* queue,
499 print_status_struct* status)
503 pstring tok,driver,datafile,langmon,helpfile,datatype;
507 NT_PRINTER_INFO_LEVEL *info = NULL;
512 * Check in the tdb *first* before checking the legacy
513 * files. This allows an NT upload to take precedence over
514 * the existing fileset. JRA.
516 * we need to lookup the driver name prior to making the call
517 * to get_a_printer_driver_9x_compatible() and not rely on the
518 * 'print driver' parameter --jerry
521 get_a_printer (&info, 2, lp_servicename(snum));
522 if ((info != NULL) &&
523 ((ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername)) == True))
527 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n",
528 info->info_2->drivername, gen_line));
532 /* didn't find driver in tdb */
534 DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
535 snum, lp_printerdriver(snum), lp_driverfile(snum)));
537 lines = file_lines_load(lp_driverfile(snum),NULL);
540 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
542 desc->errcode=NERR_notsupported;
546 /* lookup the long printer driver name in the file description */
547 for (i=0;lines[i] && !ok;i++)
550 if (next_token(&p,tok,":",sizeof(tok)) &&
551 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
552 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
561 /* driver file name */
562 if (!next_token(&p,driver,":",sizeof(driver)))
566 if (!next_token(&p,datafile,":",sizeof(datafile)))
570 * for the next tokens - which may be empty - I have
571 * to check for empty tokens first because the
572 * next_token function will skip all empty token
581 else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
584 /* language monitor */
590 else if (!next_token(&p,langmon,":",sizeof(langmon)))
593 /* default data type */
594 if (!next_token(&p,datatype,":",sizeof(datatype)))
597 PACKI(desc,"W",0x0400); /* don't know */
600 PACKS(desc,"z",info->info_2->drivername); /* long printer name */
604 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
606 PACKS(desc,"z",driver); /* Driverfile Name */
607 PACKS(desc,"z",datafile); /* Datafile name */
608 PACKS(desc,"z",langmon); /* language monitor */
611 fstrcpy(location, "\\\\");
612 fstrcat(location, global_myname);
613 fstrcat(location, "\\print$\\WIN40\\0");
614 PACKS(desc,"z",location); /* share to retrieve files */
618 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
620 PACKS(desc,"z",datatype); /* default data type */
621 PACKS(desc,"z",helpfile); /* helpfile name */
622 PACKS(desc,"z",driver); /* driver name */
625 DEBUG(3,("lp_printerdriver:%s:\n",info->info_2->drivername));
627 DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum)));
629 DEBUG(3,("Driver:%s:\n",driver));
630 DEBUG(3,("Data File:%s:\n",datafile));
631 DEBUG(3,("Language Monitor:%s:\n",langmon));
633 DEBUG(3,("lp_driverlocation:%s:\n",location));
635 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
636 DEBUG(3,("Data Type:%s:\n",datatype));
637 DEBUG(3,("Help File:%s:\n",helpfile));
638 PACKI(desc,"N",count); /* number of files to copy */
640 for (i=0;i<count;i++)
642 /* no need to check return value here
643 * - it was already tested in
644 * get_printerdrivernumber */
645 next_token(&p,tok,",",sizeof(tok));
646 PACKS(desc,"z",tok); /* driver files to copy */
647 DEBUG(3,("file:%s:\n",tok));
650 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
651 SERVICE(snum),count));
653 desc->errcode=NERR_Success;
659 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
660 desc->errcode=NERR_notsupported;
664 file_lines_free(lines);
668 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
669 struct pack_desc* desc,
670 int count, print_queue_struct* queue,
671 print_status_struct* status)
676 PACKS(desc,"B13",SERVICE(snum));
681 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
684 PACKI(desc,"K",printq_status(status->status));
688 if (uLevel == 1 || uLevel == 2) {
689 PACKS(desc,"B",""); /* alignment */
690 PACKI(desc,"W",5); /* priority */
691 PACKI(desc,"W",0); /* start time */
692 PACKI(desc,"W",0); /* until time */
693 PACKS(desc,"z",""); /* pSepFile */
694 PACKS(desc,"z","lpd"); /* pPrProc */
695 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
696 PACKS(desc,"z",""); /* pParms */
698 PACKS(desc,"z","UNKNOWN PRINTER");
699 PACKI(desc,"W",LPSTAT_ERROR);
701 else if (!status || !status->message[0]) {
702 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
703 PACKI(desc,"W",LPSTAT_OK); /* status */
705 PACKS(desc,"z",status->message);
706 PACKI(desc,"W",printq_status(status->status)); /* status */
708 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
711 if (uLevel == 3 || uLevel == 4) {
712 PACKI(desc,"W",5); /* uPriority */
713 PACKI(desc,"W",0); /* uStarttime */
714 PACKI(desc,"W",0); /* uUntiltime */
715 PACKI(desc,"W",5); /* pad1 */
716 PACKS(desc,"z",""); /* pszSepFile */
717 PACKS(desc,"z","WinPrint"); /* pszPrProc */
718 PACKS(desc,"z",""); /* pszParms */
719 if (!status || !status->message[0]) {
720 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
721 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
723 PACKS(desc,"z",status->message); /* pszComment */
724 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
726 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
727 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
728 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
729 PackDriverData(desc); /* pDriverData */
732 if (uLevel == 2 || uLevel == 4) {
734 for (i=0;i<count;i++)
735 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
739 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
743 /* This function returns the number of files for a given driver */
744 static int get_printerdrivernumber(int snum)
752 NT_PRINTER_INFO_LEVEL *info = NULL;
755 * Check in the tdb *first* before checking the legacy
756 * files. This allows an NT upload to take precedence over
757 * the existing fileset. JRA.
759 * we need to lookup the driver name prior to making the call
760 * to get_a_printer_driver_9x_compatible() and not rely on the
761 * 'print driver' parameter --jerry
764 get_a_printer (&info, 2, lp_servicename(snum));
765 if ((info != NULL) &&
766 (ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername) == True))
769 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
773 /* didn't find driver in tdb */
775 DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
776 snum, lp_printerdriver(snum), lp_driverfile(snum)));
778 lines = file_lines_load(lp_driverfile(snum), NULL);
781 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
785 /* lookup the long printer driver name in the file description */
786 for (i=0;lines[i] && !ok;i++)
789 if (next_token(&p,tok,":",sizeof(tok)) &&
790 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
791 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
803 if (*p++ == ':') i--;
806 DEBUG(3,("Can't determine number of printer driver files\n"));
810 /* count the number of files */
811 while (next_token(&p,tok,",",sizeof(tok)))
820 file_lines_free(lines);
825 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
826 uint16 vuid, char *param,char *data,
827 int mdrcnt,int mprcnt,
828 char **rdata,char **rparam,
829 int *rdata_len,int *rparam_len)
831 char *str1 = param+2;
832 char *str2 = skip_string(str1,1);
833 char *p = skip_string(str2,1);
839 struct pack_desc desc;
840 print_queue_struct *queue=NULL;
841 print_status_struct status;
843 memset((char *)&status,'\0',sizeof(status));
844 memset((char *)&desc,'\0',sizeof(desc));
846 p = skip_string(p,1);
850 /* remove any trailing username */
851 if ((p = strchr(QueueName,'%'))) *p = 0;
853 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
855 /* check it's a supported varient */
856 if (!prefix_ok(str1,"zWrLh")) return False;
857 if (!check_printq_info(&desc,uLevel,str2,str3)) {
859 * Patch from Scott Moomaw <scott@bridgewater.edu>
860 * to return the 'invalid info level' error if an
861 * unknown level was requested.
865 *rparam = REALLOC(*rparam,*rparam_len);
866 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
872 snum = lp_servicenumber(QueueName);
873 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
874 int pnum = lp_servicenumber(PRINTERS_NAME);
876 lp_add_printer(QueueName,pnum);
877 snum = lp_servicenumber(QueueName);
881 if (snum < 0 || !VALID_SNUM(snum)) return(False);
884 count = get_printerdrivernumber(snum);
885 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
887 count = print_queue_status(snum, &queue,&status);
890 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
892 desc.buflen = mdrcnt;
893 if (init_package(&desc,1,count)) {
894 desc.subcount = count;
895 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
896 } else if(uLevel == 0) {
899 * This is a *disgusting* hack.
900 * This is *so* bad that even I'm embarrassed (and I
901 * have no shame). Here's the deal :
902 * Until we get the correct SPOOLSS code into smbd
903 * then when we're running with NT SMB support then
904 * NT makes this call with a level of zero, and then
905 * immediately follows it with an open request to
906 * the \\SRVSVC pipe. If we allow that open to
907 * succeed then NT barfs when it cannot open the
908 * \\SPOOLSS pipe immediately after and continually
909 * whines saying "Printer name is invalid" forever
910 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
911 * to fail, then NT downgrades to using the downlevel code
912 * and everything works as well as before. I hate
913 * myself for adding this code.... JRA.
916 fail_next_srvsvc_open();
920 *rdata_len = desc.usedlen;
923 *rparam = REALLOC(*rparam,*rparam_len);
924 SSVALS(*rparam,0,desc.errcode);
926 SSVAL(*rparam,4,desc.neededlen);
928 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
930 if (queue) free(queue);
935 /****************************************************************************
936 View list of all print jobs on all queues.
937 ****************************************************************************/
939 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
940 int mdrcnt, int mprcnt,
941 char **rdata, char** rparam,
942 int *rdata_len, int *rparam_len)
944 char *param_format = param+2;
945 char *output_format1 = skip_string(param_format,1);
946 char *p = skip_string(output_format1,1);
947 int uLevel = SVAL(p,0);
948 char *output_format2 = p + 4;
949 int services = lp_numservices();
951 struct pack_desc desc;
952 print_queue_struct **queue = NULL;
953 print_status_struct *status = NULL;
954 int* subcntarr = NULL;
955 int queuecnt, subcnt=0, succnt=0;
957 memset((char *)&desc,'\0',sizeof(desc));
959 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
961 if (!prefix_ok(param_format,"WrLeh")) return False;
962 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
964 * Patch from Scott Moomaw <scott@bridgewater.edu>
965 * to return the 'invalid info level' error if an
966 * unknown level was requested.
970 *rparam = REALLOC(*rparam,*rparam_len);
971 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
978 for (i = 0; i < services; i++)
979 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
982 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
983 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
986 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
987 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
988 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
991 memset(status,0,queuecnt*sizeof(print_status_struct));
992 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
993 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
998 for (i = 0; i < services; i++)
999 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1000 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1001 subcnt += subcntarr[n];
1005 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1007 desc.buflen = mdrcnt;
1009 if (init_package(&desc,queuecnt,subcnt)) {
1012 for (i = 0; i < services; i++)
1013 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1014 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1016 if (desc.errcode == NERR_Success) succnt = n;
1020 if (subcntarr) free(subcntarr);
1022 *rdata_len = desc.usedlen;
1024 *rparam = REALLOC(*rparam,*rparam_len);
1025 SSVALS(*rparam,0,desc.errcode);
1027 SSVAL(*rparam,4,succnt);
1028 SSVAL(*rparam,6,queuecnt);
1030 for (i = 0; i < queuecnt; i++) {
1031 if (queue && queue[i]) free(queue[i]);
1034 if (queue) free(queue);
1035 if (status) free(status);
1040 /****************************************************************************
1041 get info level for a server list query
1042 ****************************************************************************/
1043 static BOOL check_server_info(int uLevel, char* id)
1047 if (strcmp(id,"B16") != 0) return False;
1050 if (strcmp(id,"B16BBDz") != 0) return False;
1058 struct srv_info_struct
1068 /*******************************************************************
1069 get server info lists from the files saved by nmbd. Return the
1071 ******************************************************************/
1072 static int get_server_info(uint32 servertype,
1073 struct srv_info_struct **servers,
1079 BOOL local_list_only;
1082 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1084 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1088 /* request for everything is code for request all servers */
1089 if (servertype == SV_TYPE_ALL)
1090 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1092 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1094 DEBUG(4,("Servertype search: %8x\n",servertype));
1096 for (i=0;lines[i];i++) {
1098 struct srv_info_struct *s;
1099 char *ptr = lines[i];
1102 if (!*ptr) continue;
1104 if (count == alloced) {
1106 (*servers) = (struct srv_info_struct *)
1107 Realloc(*servers,sizeof(**servers)*alloced);
1108 if (!(*servers)) return(0);
1109 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1111 s = &(*servers)[count];
1113 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1114 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1115 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1116 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1117 /* this allows us to cope with an old nmbd */
1118 pstrcpy(s->domain,global_myworkgroup);
1121 if (sscanf(stype,"%X",&s->type) != 1) {
1122 DEBUG(4,("r:host file "));
1126 /* Filter the servers/domains we return based on what was asked for. */
1128 /* Check to see if we are being asked for a local list only. */
1129 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1130 DEBUG(4,("r: local list only"));
1134 /* doesn't match up: don't want it */
1135 if (!(servertype & s->type)) {
1136 DEBUG(4,("r:serv type "));
1140 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1141 (s->type & SV_TYPE_DOMAIN_ENUM))
1143 DEBUG(4,("s: dom mismatch "));
1147 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1152 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1153 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1157 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1158 s->name, s->type, s->comment, s->domain));
1160 s->server_added = True;
1165 DEBUG(4,("%20s %8x %25s %15s\n",
1166 s->name, s->type, s->comment, s->domain));
1170 file_lines_free(lines);
1175 /*******************************************************************
1176 fill in a server info structure
1177 ******************************************************************/
1178 static int fill_srv_info(struct srv_info_struct *service,
1179 int uLevel, char **buf, int *buflen,
1180 char **stringbuf, int *stringspace, char *baseaddr)
1189 case 0: struct_len = 16; break;
1190 case 1: struct_len = 26; break;
1200 len = strlen(service->comment)+1;
1204 if (buflen) *buflen = struct_len;
1205 if (stringspace) *stringspace = len;
1206 return struct_len + len;
1211 if (*buflen < struct_len) return -1;
1219 p2 = p + struct_len;
1220 l2 = *buflen - struct_len;
1222 if (!baseaddr) baseaddr = p;
1227 StrnCpy(p,service->name,15);
1231 StrnCpy(p,service->name,15);
1232 SIVAL(p,18,service->type);
1233 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1234 len += CopyAndAdvance(&p2,service->comment,&l2);
1240 *buf = p + struct_len;
1241 *buflen -= struct_len;
1254 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1256 return(strcmp(s1->name,s2->name));
1259 /****************************************************************************
1260 view list of servers available (or possibly domains). The info is
1261 extracted from lists saved by nmbd on the local host
1262 ****************************************************************************/
1263 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1264 int mdrcnt, int mprcnt, char **rdata,
1265 char **rparam, int *rdata_len, int *rparam_len)
1267 char *str1 = param+2;
1268 char *str2 = skip_string(str1,1);
1269 char *p = skip_string(str2,1);
1270 int uLevel = SVAL(p,0);
1271 int buf_len = SVAL(p,2);
1272 uint32 servertype = IVAL(p,4);
1274 int data_len, fixed_len, string_len;
1275 int f_len = 0, s_len = 0;
1276 struct srv_info_struct *servers=NULL;
1277 int counted=0,total=0;
1280 BOOL domain_request;
1283 /* If someone sets all the bits they don't really mean to set
1284 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1287 if (servertype == SV_TYPE_ALL)
1288 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1290 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1291 any other bit (they may just set this bit on it's own) they
1292 want all the locally seen servers. However this bit can be
1293 set on its own so set the requested servers to be
1294 ALL - DOMAIN_ENUM. */
1296 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1297 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1299 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1300 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1304 if (!prefix_ok(str1,"WrLehD")) return False;
1305 if (!check_server_info(uLevel,str2)) return False;
1307 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1308 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1309 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1311 if (strcmp(str1, "WrLehDz") == 0) {
1312 StrnCpy(domain, p, sizeof(fstring)-1);
1314 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1317 if (lp_browse_list())
1318 total = get_server_info(servertype,&servers,domain);
1320 data_len = fixed_len = string_len = 0;
1323 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1326 char *lastname=NULL;
1328 for (i=0;i<total;i++)
1330 struct srv_info_struct *s = &servers[i];
1331 if (lastname && strequal(lastname,s->name)) continue;
1333 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1334 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1335 s->name, s->type, s->comment, s->domain));
1337 if (data_len <= buf_len) {
1340 string_len += s_len;
1347 *rdata_len = fixed_len + string_len;
1348 *rdata = REALLOC(*rdata,*rdata_len);
1349 memset(*rdata,'\0',*rdata_len);
1351 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1357 char *lastname=NULL;
1358 int count2 = counted;
1359 for (i = 0; i < total && count2;i++)
1361 struct srv_info_struct *s = &servers[i];
1362 if (lastname && strequal(lastname,s->name)) continue;
1364 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1365 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1366 s->name, s->type, s->comment, s->domain));
1372 *rparam = REALLOC(*rparam,*rparam_len);
1373 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1375 SSVAL(*rparam,4,counted);
1376 SSVAL(*rparam,6,counted+missed);
1378 if (servers) free(servers);
1380 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1381 domain,uLevel,counted,counted+missed));
1386 /****************************************************************************
1387 command 0x34 - suspected of being a "Lookup Names" stub api
1388 ****************************************************************************/
1389 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1390 int mdrcnt, int mprcnt, char **rdata,
1391 char **rparam, int *rdata_len, int *rparam_len)
1393 char *str1 = param+2;
1394 char *str2 = skip_string(str1,1);
1395 char *p = skip_string(str2,1);
1396 int uLevel = SVAL(p,0);
1397 int buf_len = SVAL(p,2);
1401 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1402 str1, str2, p, uLevel, buf_len));
1404 if (!prefix_ok(str1,"zWrLeh")) return False;
1409 *rparam = REALLOC(*rparam,*rparam_len);
1411 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1413 SSVAL(*rparam,4,counted);
1414 SSVAL(*rparam,6,counted+missed);
1419 /****************************************************************************
1420 get info about a share
1421 ****************************************************************************/
1422 static BOOL check_share_info(int uLevel, char* id)
1426 if (strcmp(id,"B13") != 0) return False;
1429 if (strcmp(id,"B13BWz") != 0) return False;
1432 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1435 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1437 default: return False;
1442 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1443 char** buf, int* buflen,
1444 char** stringbuf, int* stringspace, char* baseaddr)
1453 case 0: struct_len = 13; break;
1454 case 1: struct_len = 20; break;
1455 case 2: struct_len = 40; break;
1456 case 91: struct_len = 68; break;
1464 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1465 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1466 if (buflen) *buflen = struct_len;
1467 if (stringspace) *stringspace = len;
1468 return struct_len + len;
1473 if ((*buflen) < struct_len) return -1;
1481 p2 = p + struct_len;
1482 l2 = (*buflen) - struct_len;
1484 if (!baseaddr) baseaddr = p;
1486 StrnCpy(p,lp_servicename(snum),13);
1492 type = STYPE_DISKTREE;
1493 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1494 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1495 SSVAL(p,14,type); /* device type */
1496 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1497 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1502 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1503 SSVALS(p,22,-1); /* max uses */
1504 SSVAL(p,24,1); /* current uses */
1505 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1506 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1507 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1512 memset(p+40,0,SHPWLEN+2);
1524 (*buf) = p + struct_len;
1525 (*buflen) -= struct_len;
1527 (*stringspace) = l2;
1537 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1538 int mdrcnt,int mprcnt,
1539 char **rdata,char **rparam,
1540 int *rdata_len,int *rparam_len)
1542 char *str1 = param+2;
1543 char *str2 = skip_string(str1,1);
1544 char *netname = skip_string(str2,1);
1545 char *p = skip_string(netname,1);
1546 int uLevel = SVAL(p,0);
1547 int snum = find_service(netname);
1549 if (snum < 0) return False;
1551 /* check it's a supported varient */
1552 if (!prefix_ok(str1,"zWrLh")) return False;
1553 if (!check_share_info(uLevel,str2)) return False;
1555 *rdata = REALLOC(*rdata,mdrcnt);
1557 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1558 if (*rdata_len < 0) return False;
1561 *rparam = REALLOC(*rparam,*rparam_len);
1562 SSVAL(*rparam,0,NERR_Success);
1563 SSVAL(*rparam,2,0); /* converter word */
1564 SSVAL(*rparam,4,*rdata_len);
1569 /****************************************************************************
1570 view list of shares available
1571 ****************************************************************************/
1572 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1573 int mdrcnt,int mprcnt,
1574 char **rdata,char **rparam,
1575 int *rdata_len,int *rparam_len)
1577 char *str1 = param+2;
1578 char *str2 = skip_string(str1,1);
1579 char *p = skip_string(str2,1);
1580 int uLevel = SVAL(p,0);
1581 int buf_len = SVAL(p,2);
1583 int count=lp_numservices();
1584 int total=0,counted=0;
1585 BOOL missed = False;
1587 int data_len, fixed_len, string_len;
1588 int f_len = 0, s_len = 0;
1590 if (!prefix_ok(str1,"WrLeh")) return False;
1591 if (!check_share_info(uLevel,str2)) return False;
1593 data_len = fixed_len = string_len = 0;
1594 for (i=0;i<count;i++)
1595 if (lp_browseable(i) && lp_snum_ok(i))
1598 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1599 if (data_len <= buf_len)
1603 string_len += s_len;
1608 *rdata_len = fixed_len + string_len;
1609 *rdata = REALLOC(*rdata,*rdata_len);
1610 memset(*rdata,0,*rdata_len);
1612 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1616 for (i = 0; i < count;i++)
1617 if (lp_browseable(i) && lp_snum_ok(i))
1618 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1622 *rparam = REALLOC(*rparam,*rparam_len);
1623 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1625 SSVAL(*rparam,4,counted);
1626 SSVAL(*rparam,6,total);
1628 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1629 counted,total,uLevel,
1630 buf_len,*rdata_len,mdrcnt));
1636 /****************************************************************************
1637 get the time of day info
1638 ****************************************************************************/
1639 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1640 int mdrcnt,int mprcnt,
1641 char **rdata,char **rparam,
1642 int *rdata_len,int *rparam_len)
1646 *rparam = REALLOC(*rparam,*rparam_len);
1649 *rdata = REALLOC(*rdata,*rdata_len);
1651 SSVAL(*rparam,0,NERR_Success);
1652 SSVAL(*rparam,2,0); /* converter word */
1658 time_t unixdate = time(NULL);
1660 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1661 by NT in a "net time" operation,
1662 it seems to ignore the one below */
1664 /* the client expects to get localtime, not GMT, in this bit
1665 (I think, this needs testing) */
1666 t = LocalTime(&unixdate);
1668 SIVAL(p,4,0); /* msecs ? */
1669 CVAL(p,8) = t->tm_hour;
1670 CVAL(p,9) = t->tm_min;
1671 CVAL(p,10) = t->tm_sec;
1672 CVAL(p,11) = 0; /* hundredths of seconds */
1673 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1674 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1675 CVAL(p,16) = t->tm_mday;
1676 CVAL(p,17) = t->tm_mon + 1;
1677 SSVAL(p,18,1900+t->tm_year);
1678 CVAL(p,20) = t->tm_wday;
1685 /****************************************************************************
1686 Set the user password.
1687 *****************************************************************************/
1689 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1690 int mdrcnt,int mprcnt,
1691 char **rdata,char **rparam,
1692 int *rdata_len,int *rparam_len)
1694 char *p = skip_string(param+2,2);
1696 fstring pass1,pass2;
1700 p = skip_string(p,1);
1702 memset(pass1,'\0',sizeof(pass1));
1703 memset(pass2,'\0',sizeof(pass2));
1705 memcpy(pass2,p+16,16);
1708 *rparam = REALLOC(*rparam,*rparam_len);
1712 SSVAL(*rparam,0,NERR_badpass);
1713 SSVAL(*rparam,2,0); /* converter word */
1715 DEBUG(3,("Set password for <%s>\n",user));
1718 * Pass the user through the NT -> unix user mapping
1722 (void)map_username(user);
1725 * Do any UNIX username case mangling.
1727 (void)Get_Pwnam( user, True);
1730 * Attempt to verify the old password against smbpasswd entries
1731 * Win98 clients send old and new password in plaintext for this call.
1735 fstring saved_pass2;
1736 SAM_ACCOUNT *sampass;
1739 * Save the new password as change_oem_password overwrites it
1743 fstrcpy(saved_pass2, pass2);
1745 if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) &&
1746 change_oem_password(sampass,pass2,False))
1748 SSVAL(*rparam,0,NERR_Success);
1751 * If unix password sync was requested, attempt to change
1752 * the /etc/passwd database also. Return failure if this cannot
1756 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1757 SSVAL(*rparam,0,NERR_badpass);
1762 * If the above failed, attempt the plaintext password change.
1763 * This tests against the /etc/passwd database only.
1766 if(SVAL(*rparam,0) != NERR_Success)
1768 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1769 chgpasswd(user,pass1,pass2,False))
1771 SSVAL(*rparam,0,NERR_Success);
1776 * If the plaintext change failed, attempt
1777 * the old encrypted method. NT will generate this
1778 * after trying the samr method. Note that this
1779 * method is done as a last resort as this
1780 * password change method loses the NT password hash
1781 * and cannot change the UNIX password as no plaintext
1785 if(SVAL(*rparam,0) != NERR_Success)
1787 SAM_ACCOUNT *hnd = NULL;
1789 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1790 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
1792 SSVAL(*rparam,0,NERR_Success);
1796 memset((char *)pass1,'\0',sizeof(fstring));
1797 memset((char *)pass2,'\0',sizeof(fstring));
1802 /****************************************************************************
1803 Set the user password (SamOEM version - gets plaintext).
1804 ****************************************************************************/
1806 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1807 int mdrcnt,int mprcnt,
1808 char **rdata,char **rparam,
1809 int *rdata_len,int *rparam_len)
1812 char *p = param + 2;
1814 *rparam = REALLOC(*rparam,*rparam_len);
1818 SSVAL(*rparam,0,NERR_badpass);
1821 * Check the parameter definition is correct.
1823 if(!strequal(param + 2, "zsT")) {
1824 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1827 p = skip_string(p, 1);
1829 if(!strequal(p, "B516B16")) {
1830 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1833 p = skip_string(p,1);
1836 p = skip_string(p,1);
1838 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1841 * Pass the user through the NT -> unix user mapping
1845 (void)map_username(user);
1848 * Do any UNIX username case mangling.
1850 (void)Get_Pwnam( user, True);
1852 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1854 SSVAL(*rparam,0,NERR_Success);
1860 /****************************************************************************
1863 ****************************************************************************/
1864 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1865 int mdrcnt,int mprcnt,
1866 char **rdata,char **rparam,
1867 int *rdata_len,int *rparam_len)
1869 int function = SVAL(param,0);
1870 char *str1 = param+2;
1871 char *str2 = skip_string(str1,1);
1872 char *p = skip_string(str2,1);
1874 extern struct current_user current_user;
1878 /* check it's a supported varient */
1879 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1883 *rparam = REALLOC(*rparam,*rparam_len);
1886 if (!print_job_exists(jobid)) {
1887 errcode = NERR_JobNotFound;
1891 errcode = NERR_notsupported;
1894 case 81: /* delete */
1895 if (print_job_delete(¤t_user, jobid, &errcode))
1896 errcode = NERR_Success;
1898 case 82: /* pause */
1899 if (print_job_pause(¤t_user, jobid, &errcode))
1900 errcode = NERR_Success;
1902 case 83: /* resume */
1903 if (print_job_resume(¤t_user, jobid, &errcode))
1904 errcode = NERR_Success;
1909 SSVAL(*rparam,0,errcode);
1910 SSVAL(*rparam,2,0); /* converter word */
1915 /****************************************************************************
1916 Purge a print queue - or pause or resume it.
1917 ****************************************************************************/
1918 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
1919 int mdrcnt,int mprcnt,
1920 char **rdata,char **rparam,
1921 int *rdata_len,int *rparam_len)
1923 int function = SVAL(param,0);
1924 char *str1 = param+2;
1925 char *str2 = skip_string(str1,1);
1926 char *QueueName = skip_string(str2,1);
1927 int errcode = NERR_notsupported;
1930 /* check it's a supported varient */
1931 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1935 *rparam = REALLOC(*rparam,*rparam_len);
1938 snum = print_queue_snum(QueueName);
1941 errcode = NERR_JobNotFound;
1946 case 74: /* Pause queue */
1947 if (print_queue_pause(NULL, snum, &errcode)) errcode = NERR_Success;
1949 case 75: /* Resume queue */
1950 if (print_queue_resume(NULL, snum, &errcode)) errcode = NERR_Success;
1952 case 103: /* Purge */
1953 if (print_queue_purge(NULL, snum, &errcode)) errcode = NERR_Success;
1958 SSVAL(*rparam,0,errcode);
1959 SSVAL(*rparam,2,0); /* converter word */
1965 /****************************************************************************
1966 set the property of a print job (undocumented?)
1967 ? function = 0xb -> set name of print job
1968 ? function = 0x6 -> move print job up/down
1969 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1970 or <WWsTP> <WB21BB16B10zWWzDDz>
1971 ****************************************************************************/
1972 static int check_printjob_info(struct pack_desc* desc,
1973 int uLevel, char* id)
1975 desc->subformat = NULL;
1977 case 0: desc->format = "W"; break;
1978 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1979 case 2: desc->format = "WWzWWDDzz"; break;
1980 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1981 default: return False;
1983 if (strcmp(desc->format,id) != 0) return False;
1987 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1988 int mdrcnt,int mprcnt,
1989 char **rdata,char **rparam,
1990 int *rdata_len,int *rparam_len)
1992 struct pack_desc desc;
1993 char *str1 = param+2;
1994 char *str2 = skip_string(str1,1);
1995 char *p = skip_string(str2,1);
1997 int uLevel = SVAL(p,2);
1998 int function = SVAL(p,4);
2003 *rparam = REALLOC(*rparam,*rparam_len);
2007 /* check it's a supported varient */
2008 if ((strcmp(str1,"WWsTP")) ||
2009 (!check_printjob_info(&desc,uLevel,str2)))
2012 if (!print_job_exists(jobid)) {
2013 errcode=NERR_JobNotFound;
2017 errcode = NERR_notsupported;
2021 /* change job place in the queue,
2022 data gives the new place */
2023 place = SVAL(data,0);
2024 if (print_job_set_place(jobid, place)) {
2025 errcode=NERR_Success;
2030 /* change print job name, data gives the name */
2031 if (print_job_set_name(jobid, data)) {
2032 errcode=NERR_Success;
2041 SSVALS(*rparam,0,errcode);
2042 SSVAL(*rparam,2,0); /* converter word */
2048 /****************************************************************************
2049 get info about the server
2050 ****************************************************************************/
2051 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2052 int mdrcnt,int mprcnt,
2053 char **rdata,char **rparam,
2054 int *rdata_len,int *rparam_len)
2056 char *str1 = param+2;
2057 char *str2 = skip_string(str1,1);
2058 char *p = skip_string(str2,1);
2059 int uLevel = SVAL(p,0);
2063 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2065 /* check it's a supported varient */
2066 if (!prefix_ok(str1,"WrLh")) return False;
2069 if (strcmp(str2,"B16") != 0) return False;
2073 if (strcmp(str2,"B16BBDz") != 0) return False;
2077 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2082 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2087 if (strcmp(str2,"DN") != 0) return False;
2091 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2094 default: return False;
2097 *rdata_len = mdrcnt;
2098 *rdata = REALLOC(*rdata,*rdata_len);
2101 p2 = p + struct_len;
2103 StrnCpy(p,local_machine,16);
2109 struct srv_info_struct *servers=NULL;
2112 uint32 servertype= lp_default_server_announce();
2114 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2116 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2117 for (i=0;i<count;i++)
2118 if (strequal(servers[i].name,local_machine))
2120 servertype = servers[i].type;
2121 pstrcpy(comment,servers[i].comment);
2124 if (servers) free(servers);
2126 SCVAL(p,0,lp_major_announce_version());
2127 SCVAL(p,1,lp_minor_announce_version());
2128 SIVAL(p,2,servertype);
2130 if (mdrcnt == struct_len) {
2133 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2134 standard_sub_conn(conn,comment);
2135 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2136 p2 = skip_string(p2,1);
2141 return False; /* not yet implemented */
2144 *rdata_len = PTR_DIFF(p2,*rdata);
2147 *rparam = REALLOC(*rparam,*rparam_len);
2148 SSVAL(*rparam,0,NERR_Success);
2149 SSVAL(*rparam,2,0); /* converter word */
2150 SSVAL(*rparam,4,*rdata_len);
2156 /****************************************************************************
2157 get info about the server
2158 ****************************************************************************/
2159 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2160 int mdrcnt,int mprcnt,
2161 char **rdata,char **rparam,
2162 int *rdata_len,int *rparam_len)
2164 char *str1 = param+2;
2165 char *str2 = skip_string(str1,1);
2166 char *p = skip_string(str2,1);
2168 extern pstring sesssetup_user;
2169 int level = SVAL(p,0);
2171 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2174 *rparam = REALLOC(*rparam,*rparam_len);
2176 /* check it's a supported varient */
2177 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2180 *rdata_len = mdrcnt + 1024;
2181 *rdata = REALLOC(*rdata,*rdata_len);
2183 SSVAL(*rparam,0,NERR_Success);
2184 SSVAL(*rparam,2,0); /* converter word */
2190 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2191 pstrcpy(p2,local_machine);
2193 p2 = skip_string(p2,1);
2196 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2197 pstrcpy(p2,sesssetup_user);
2198 p2 = skip_string(p2,1);
2201 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2202 pstrcpy(p2,global_myworkgroup);
2204 p2 = skip_string(p2,1);
2207 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2208 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2211 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2212 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2213 p2 = skip_string(p2,1);
2216 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2218 p2 = skip_string(p2,1);
2221 *rdata_len = PTR_DIFF(p2,*rdata);
2223 SSVAL(*rparam,4,*rdata_len);
2228 /****************************************************************************
2229 get info about a user
2231 struct user_info_11 {
2232 char usri11_name[21]; 0-20
2234 char *usri11_comment; 22-25
2235 char *usri11_usr_comment; 26-29
2236 unsigned short usri11_priv; 30-31
2237 unsigned long usri11_auth_flags; 32-35
2238 long usri11_password_age; 36-39
2239 char *usri11_homedir; 40-43
2240 char *usri11_parms; 44-47
2241 long usri11_last_logon; 48-51
2242 long usri11_last_logoff; 52-55
2243 unsigned short usri11_bad_pw_count; 56-57
2244 unsigned short usri11_num_logons; 58-59
2245 char *usri11_logon_server; 60-63
2246 unsigned short usri11_country_code; 64-65
2247 char *usri11_workstations; 66-69
2248 unsigned long usri11_max_storage; 70-73
2249 unsigned short usri11_units_per_week; 74-75
2250 unsigned char *usri11_logon_hours; 76-79
2251 unsigned short usri11_code_page; 80-81
2256 usri11_name specifies the user name for which information is retireved
2258 usri11_pad aligns the next data structure element to a word boundary
2260 usri11_comment is a null terminated ASCII comment
2262 usri11_user_comment is a null terminated ASCII comment about the user
2264 usri11_priv specifies the level of the privilege assigned to the user.
2265 The possible values are:
2267 Name Value Description
2268 USER_PRIV_GUEST 0 Guest privilege
2269 USER_PRIV_USER 1 User privilege
2270 USER_PRV_ADMIN 2 Administrator privilege
2272 usri11_auth_flags specifies the account operator privileges. The
2273 possible values are:
2275 Name Value Description
2276 AF_OP_PRINT 0 Print operator
2279 Leach, Naik [Page 28]
2283 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2286 AF_OP_COMM 1 Communications operator
2287 AF_OP_SERVER 2 Server operator
2288 AF_OP_ACCOUNTS 3 Accounts operator
2291 usri11_password_age specifies how many seconds have elapsed since the
2292 password was last changed.
2294 usri11_home_dir points to a null terminated ASCII string that contains
2295 the path name of the user's home directory.
2297 usri11_parms points to a null terminated ASCII string that is set
2298 aside for use by applications.
2300 usri11_last_logon specifies the time when the user last logged on.
2301 This value is stored as the number of seconds elapsed since
2302 00:00:00, January 1, 1970.
2304 usri11_last_logoff specifies the time when the user last logged off.
2305 This value is stored as the number of seconds elapsed since
2306 00:00:00, January 1, 1970. A value of 0 means the last logoff
2309 usri11_bad_pw_count specifies the number of incorrect passwords
2310 entered since the last successful logon.
2312 usri11_log1_num_logons specifies the number of times this user has
2313 logged on. A value of -1 means the number of logons is unknown.
2315 usri11_logon_server points to a null terminated ASCII string that
2316 contains the name of the server to which logon requests are sent.
2317 A null string indicates logon requests should be sent to the
2320 usri11_country_code specifies the country code for the user's language
2323 usri11_workstations points to a null terminated ASCII string that
2324 contains the names of workstations the user may log on from.
2325 There may be up to 8 workstations, with the names separated by
2326 commas. A null strings indicates there are no restrictions.
2328 usri11_max_storage specifies the maximum amount of disk space the user
2329 can occupy. A value of 0xffffffff indicates there are no
2332 usri11_units_per_week specifies the equal number of time units into
2333 which a week is divided. This value must be equal to 168.
2335 usri11_logon_hours points to a 21 byte (168 bits) string that
2336 specifies the time during which the user can log on. Each bit
2337 represents one unique hour in a week. The first bit (bit 0, word
2338 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2342 Leach, Naik [Page 29]
2346 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2349 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2350 are no restrictions.
2352 usri11_code_page specifies the code page for the user's language of
2355 All of the pointers in this data structure need to be treated
2356 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2357 to be ignored. The converter word returned in the parameters section
2358 needs to be subtracted from the lower 16 bits to calculate an offset
2359 into the return buffer where this ASCII string resides.
2361 There is no auxiliary data in the response.
2363 ****************************************************************************/
2365 #define usri11_name 0
2366 #define usri11_pad 21
2367 #define usri11_comment 22
2368 #define usri11_usr_comment 26
2369 #define usri11_full_name 30
2370 #define usri11_priv 34
2371 #define usri11_auth_flags 36
2372 #define usri11_password_age 40
2373 #define usri11_homedir 44
2374 #define usri11_parms 48
2375 #define usri11_last_logon 52
2376 #define usri11_last_logoff 56
2377 #define usri11_bad_pw_count 60
2378 #define usri11_num_logons 62
2379 #define usri11_logon_server 64
2380 #define usri11_country_code 68
2381 #define usri11_workstations 70
2382 #define usri11_max_storage 74
2383 #define usri11_units_per_week 78
2384 #define usri11_logon_hours 80
2385 #define usri11_code_page 84
2386 #define usri11_end 86
2388 #define USER_PRIV_GUEST 0
2389 #define USER_PRIV_USER 1
2390 #define USER_PRIV_ADMIN 2
2392 #define AF_OP_PRINT 0
2393 #define AF_OP_COMM 1
2394 #define AF_OP_SERVER 2
2395 #define AF_OP_ACCOUNTS 3
2398 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2399 int mdrcnt,int mprcnt,
2400 char **rdata,char **rparam,
2401 int *rdata_len,int *rparam_len)
2403 char *str1 = param+2;
2404 char *str2 = skip_string(str1,1);
2405 char *UserName = skip_string(str2,1);
2406 char *p = skip_string(UserName,1);
2407 int uLevel = SVAL(p,0);
2410 /* get NIS home of a previously validated user - simeon */
2411 /* With share level security vuid will always be zero.
2412 Don't depend on vuser being non-null !!. JRA */
2413 user_struct *vuser = get_valid_user_struct(vuid);
2415 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2416 vuser->user.unix_name));
2419 *rparam = REALLOC(*rparam,*rparam_len);
2421 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2423 /* check it's a supported variant */
2424 if (strcmp(str1,"zWrLh") != 0) return False;
2427 case 0: p2 = "B21"; break;
2428 case 1: p2 = "B21BB16DWzzWz"; break;
2429 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2430 case 10: p2 = "B21Bzzz"; break;
2431 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2432 default: return False;
2435 if (strcmp(p2,str2) != 0) return False;
2437 *rdata_len = mdrcnt + 1024;
2438 *rdata = REALLOC(*rdata,*rdata_len);
2440 SSVAL(*rparam,0,NERR_Success);
2441 SSVAL(*rparam,2,0); /* converter word */
2444 p2 = p + usri11_end;
2447 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2451 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2456 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2457 pstrcpy(p2,"Comment");
2458 p2 = skip_string(p2,1);
2460 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2461 pstrcpy(p2,"UserComment");
2462 p2 = skip_string(p2,1);
2464 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2465 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2466 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2467 p2 = skip_string(p2,1);
2470 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2472 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2473 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2474 SIVALS(p,usri11_password_age,-1); /* password age */
2475 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2476 pstrcpy(p2, lp_logon_home());
2477 standard_sub_conn(conn, p2);
2478 p2 = skip_string(p2,1);
2479 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2481 p2 = skip_string(p2,1);
2482 SIVAL(p,usri11_last_logon,0); /* last logon */
2483 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2484 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2485 SSVALS(p,usri11_num_logons,-1); /* num logons */
2486 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2487 pstrcpy(p2,"\\\\*");
2488 p2 = skip_string(p2,1);
2489 SSVAL(p,usri11_country_code,0); /* country code */
2491 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2493 p2 = skip_string(p2,1);
2495 SIVALS(p,usri11_max_storage,-1); /* max storage */
2496 SSVAL(p,usri11_units_per_week,168); /* units per week */
2497 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2499 /* a simple way to get logon hours at all times. */
2501 SCVAL(p2,21,0); /* fix zero termination */
2502 p2 = skip_string(p2,1);
2504 SSVAL(p,usri11_code_page,0); /* code page */
2506 if (uLevel == 1 || uLevel == 2)
2508 memset(p+22,' ',16); /* password */
2509 SIVALS(p,38,-1); /* password age */
2511 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2512 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2513 pstrcpy(p2,lp_logon_home());
2514 standard_sub_conn(conn, p2);
2515 p2 = skip_string(p2,1);
2516 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2518 SSVAL(p,52,0); /* flags */
2519 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2520 pstrcpy(p2,lp_logon_script());
2521 standard_sub_conn( conn, p2 );
2522 p2 = skip_string(p2,1);
2525 SIVAL(p,60,0); /* auth_flags */
2526 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2527 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2528 p2 = skip_string(p2,1);
2529 SIVAL(p,68,0); /* urs_comment */
2530 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2532 p2 = skip_string(p2,1);
2533 SIVAL(p,76,0); /* workstations */
2534 SIVAL(p,80,0); /* last_logon */
2535 SIVAL(p,84,0); /* last_logoff */
2536 SIVALS(p,88,-1); /* acct_expires */
2537 SIVALS(p,92,-1); /* max_storage */
2538 SSVAL(p,96,168); /* units_per_week */
2539 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2542 SSVALS(p,102,-1); /* bad_pw_count */
2543 SSVALS(p,104,-1); /* num_logons */
2544 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2545 pstrcpy(p2,"\\\\%L");
2546 standard_sub_conn(conn, p2);
2547 p2 = skip_string(p2,1);
2548 SSVAL(p,110,49); /* country_code */
2549 SSVAL(p,112,860); /* code page */
2553 *rdata_len = PTR_DIFF(p2,*rdata);
2555 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2560 /*******************************************************************
2561 get groups that a user is a member of
2562 ******************************************************************/
2563 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2564 int mdrcnt,int mprcnt,
2565 char **rdata,char **rparam,
2566 int *rdata_len,int *rparam_len)
2568 char *str1 = param+2;
2569 char *str2 = skip_string(str1,1);
2570 char *UserName = skip_string(str2,1);
2571 char *p = skip_string(UserName,1);
2572 int uLevel = SVAL(p,0);
2577 *rparam = REALLOC(*rparam,*rparam_len);
2579 /* check it's a supported varient */
2580 if (strcmp(str1,"zWrLeh") != 0) return False;
2582 case 0: p2 = "B21"; break;
2583 default: return False;
2585 if (strcmp(p2,str2) != 0) return False;
2587 *rdata_len = mdrcnt + 1024;
2588 *rdata = REALLOC(*rdata,*rdata_len);
2590 SSVAL(*rparam,0,NERR_Success);
2591 SSVAL(*rparam,2,0); /* converter word */
2595 /* XXXX we need a real SAM database some day */
2596 pstrcpy(p,"Users"); p += 21; count++;
2597 pstrcpy(p,"Domain Users"); p += 21; count++;
2598 pstrcpy(p,"Guests"); p += 21; count++;
2599 pstrcpy(p,"Domain Guests"); p += 21; count++;
2601 *rdata_len = PTR_DIFF(p,*rdata);
2603 SSVAL(*rparam,4,count); /* is this right?? */
2604 SSVAL(*rparam,6,count); /* is this right?? */
2610 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2611 int mdrcnt,int mprcnt,
2612 char **rdata,char **rparam,
2613 int *rdata_len,int *rparam_len)
2615 char *str1 = param+2;
2616 char *str2 = skip_string(str1,1);
2617 char *p = skip_string(str2,1);
2619 struct pack_desc desc;
2625 memset((char *)&desc,'\0',sizeof(desc));
2627 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2629 /* check it's a supported varient */
2630 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2631 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2632 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2634 desc.buflen = mdrcnt;
2635 desc.subformat = NULL;
2638 if (init_package(&desc,1,0))
2640 PACKI(&desc,"W",0); /* code */
2641 PACKS(&desc,"B21",name); /* eff. name */
2642 PACKS(&desc,"B",""); /* pad */
2644 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2645 PACKI(&desc,"D",0); /* auth flags XXX */
2646 PACKI(&desc,"W",0); /* num logons */
2647 PACKI(&desc,"W",0); /* bad pw count */
2648 PACKI(&desc,"D",0); /* last logon */
2649 PACKI(&desc,"D",-1); /* last logoff */
2650 PACKI(&desc,"D",-1); /* logoff time */
2651 PACKI(&desc,"D",-1); /* kickoff time */
2652 PACKI(&desc,"D",0); /* password age */
2653 PACKI(&desc,"D",0); /* password can change */
2654 PACKI(&desc,"D",-1); /* password must change */
2657 fstrcpy(mypath,"\\\\");
2658 fstrcat(mypath,local_machine);
2660 PACKS(&desc,"z",mypath); /* computer */
2662 PACKS(&desc,"z",global_myworkgroup);/* domain */
2664 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2665 /* made sure all macros are fully substituted and available */
2667 pstring logon_script;
2668 pstrcpy(logon_script,lp_logon_script());
2669 standard_sub_conn( conn, logon_script );
2670 PACKS(&desc,"z", logon_script); /* script path */
2672 /* End of JHT mods */
2674 PACKI(&desc,"D",0x00000000); /* reserved */
2677 *rdata_len = desc.usedlen;
2679 *rparam = REALLOC(*rparam,*rparam_len);
2680 SSVALS(*rparam,0,desc.errcode);
2682 SSVAL(*rparam,4,desc.neededlen);
2684 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2689 /****************************************************************************
2690 api_WAccessGetUserPerms
2691 ****************************************************************************/
2692 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2693 int mdrcnt,int mprcnt,
2694 char **rdata,char **rparam,
2695 int *rdata_len,int *rparam_len)
2697 char *str1 = param+2;
2698 char *str2 = skip_string(str1,1);
2699 char *user = skip_string(str2,1);
2700 char *resource = skip_string(user,1);
2702 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2704 /* check it's a supported varient */
2705 if (strcmp(str1,"zzh") != 0) return False;
2706 if (strcmp(str2,"") != 0) return False;
2709 *rparam = REALLOC(*rparam,*rparam_len);
2710 SSVALS(*rparam,0,0); /* errorcode */
2711 SSVAL(*rparam,2,0); /* converter word */
2712 SSVAL(*rparam,4,0x7f); /* permission flags */
2717 /****************************************************************************
2718 api_WPrintJobEnumerate
2719 ****************************************************************************/
2720 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2721 int mdrcnt,int mprcnt,
2722 char **rdata,char **rparam,
2723 int *rdata_len,int *rparam_len)
2725 char *str1 = param+2;
2726 char *str2 = skip_string(str1,1);
2727 char *p = skip_string(str2,1);
2733 struct pack_desc desc;
2734 print_queue_struct *queue=NULL;
2735 print_status_struct status;
2739 memset((char *)&desc,'\0',sizeof(desc));
2740 memset((char *)&status,'\0',sizeof(status));
2742 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2744 /* check it's a supported varient */
2745 if (strcmp(str1,"WWrLh") != 0) return False;
2746 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2749 snum = print_job_snum(job);
2751 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2753 count = print_queue_status(snum,&queue,&status);
2754 for (i = 0; i < count; i++) {
2755 if (queue[i].job == job) break;
2757 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2759 desc.buflen = mdrcnt;
2761 if (init_package(&desc,1,0)) {
2763 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2764 *rdata_len = desc.usedlen;
2767 desc.errcode = NERR_JobNotFound;
2773 *rparam = REALLOC(*rparam,*rparam_len);
2774 SSVALS(*rparam,0,desc.errcode);
2776 SSVAL(*rparam,4,desc.neededlen);
2778 if (queue) free(queue);
2780 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2784 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2785 int mdrcnt,int mprcnt,
2786 char **rdata,char **rparam,
2787 int *rdata_len,int *rparam_len)
2789 char *str1 = param+2;
2790 char *str2 = skip_string(str1,1);
2791 char *p = skip_string(str2,1);
2797 struct pack_desc desc;
2798 print_queue_struct *queue=NULL;
2799 print_status_struct status;
2801 memset((char *)&desc,'\0',sizeof(desc));
2802 memset((char *)&status,'\0',sizeof(status));
2804 p = skip_string(p,1);
2807 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2809 /* check it's a supported varient */
2810 if (strcmp(str1,"zWrLeh") != 0) return False;
2811 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2812 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2814 snum = lp_servicenumber(name);
2815 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2816 int pnum = lp_servicenumber(PRINTERS_NAME);
2818 lp_add_printer(name,pnum);
2819 snum = lp_servicenumber(name);
2823 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2825 count = print_queue_status(snum,&queue,&status);
2826 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2828 desc.buflen = mdrcnt;
2830 if (init_package(&desc,count,0)) {
2832 for (i = 0; i < count; i++) {
2833 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2834 if (desc.errcode == NERR_Success) succnt = i+1;
2838 *rdata_len = desc.usedlen;
2841 *rparam = REALLOC(*rparam,*rparam_len);
2842 SSVALS(*rparam,0,desc.errcode);
2844 SSVAL(*rparam,4,succnt);
2845 SSVAL(*rparam,6,count);
2847 if (queue) free(queue);
2849 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2853 static int check_printdest_info(struct pack_desc* desc,
2854 int uLevel, char* id)
2856 desc->subformat = NULL;
2858 case 0: desc->format = "B9"; break;
2859 case 1: desc->format = "B9B21WWzW"; break;
2860 case 2: desc->format = "z"; break;
2861 case 3: desc->format = "zzzWWzzzWW"; break;
2862 default: return False;
2864 if (strcmp(desc->format,id) != 0) return False;
2868 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2869 struct pack_desc* desc)
2872 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2873 buf[sizeof(buf)-1] = 0;
2876 PACKS(desc,"B9",buf); /* szName */
2878 PACKS(desc,"B21",""); /* szUserName */
2879 PACKI(desc,"W",0); /* uJobId */
2880 PACKI(desc,"W",0); /* fsStatus */
2881 PACKS(desc,"z",""); /* pszStatus */
2882 PACKI(desc,"W",0); /* time */
2885 if (uLevel == 2 || uLevel == 3) {
2886 PACKS(desc,"z",buf); /* pszPrinterName */
2888 PACKS(desc,"z",""); /* pszUserName */
2889 PACKS(desc,"z",""); /* pszLogAddr */
2890 PACKI(desc,"W",0); /* uJobId */
2891 PACKI(desc,"W",0); /* fsStatus */
2892 PACKS(desc,"z",""); /* pszStatus */
2893 PACKS(desc,"z",""); /* pszComment */
2894 PACKS(desc,"z","NULL"); /* pszDrivers */
2895 PACKI(desc,"W",0); /* time */
2896 PACKI(desc,"W",0); /* pad1 */
2901 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2902 int mdrcnt,int mprcnt,
2903 char **rdata,char **rparam,
2904 int *rdata_len,int *rparam_len)
2906 char *str1 = param+2;
2907 char *str2 = skip_string(str1,1);
2908 char *p = skip_string(str2,1);
2909 char* PrinterName = p;
2911 struct pack_desc desc;
2914 memset((char *)&desc,'\0',sizeof(desc));
2916 p = skip_string(p,1);
2919 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2921 /* check it's a supported varient */
2922 if (strcmp(str1,"zWrLh") != 0) return False;
2923 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2925 snum = lp_servicenumber(PrinterName);
2926 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2927 int pnum = lp_servicenumber(PRINTERS_NAME);
2929 lp_add_printer(PrinterName,pnum);
2930 snum = lp_servicenumber(PrinterName);
2936 desc.errcode = NERR_DestNotFound;
2940 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2942 desc.buflen = mdrcnt;
2943 if (init_package(&desc,1,0)) {
2944 fill_printdest_info(conn,snum,uLevel,&desc);
2946 *rdata_len = desc.usedlen;
2950 *rparam = REALLOC(*rparam,*rparam_len);
2951 SSVALS(*rparam,0,desc.errcode);
2953 SSVAL(*rparam,4,desc.neededlen);
2955 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2959 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2960 int mdrcnt,int mprcnt,
2961 char **rdata,char **rparam,
2962 int *rdata_len,int *rparam_len)
2964 char *str1 = param+2;
2965 char *str2 = skip_string(str1,1);
2966 char *p = skip_string(str2,1);
2970 struct pack_desc desc;
2971 int services = lp_numservices();
2973 memset((char *)&desc,'\0',sizeof(desc));
2977 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2979 /* check it's a supported varient */
2980 if (strcmp(str1,"WrLeh") != 0) return False;
2981 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2984 for (i = 0; i < services; i++)
2985 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2988 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2990 desc.buflen = mdrcnt;
2991 if (init_package(&desc,queuecnt,0)) {
2994 for (i = 0; i < services; i++) {
2995 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2996 fill_printdest_info(conn,i,uLevel,&desc);
2998 if (desc.errcode == NERR_Success) succnt = n;
3003 *rdata_len = desc.usedlen;
3006 *rparam = REALLOC(*rparam,*rparam_len);
3007 SSVALS(*rparam,0,desc.errcode);
3009 SSVAL(*rparam,4,succnt);
3010 SSVAL(*rparam,6,queuecnt);
3012 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3016 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3017 int mdrcnt,int mprcnt,
3018 char **rdata,char **rparam,
3019 int *rdata_len,int *rparam_len)
3021 char *str1 = param+2;
3022 char *str2 = skip_string(str1,1);
3023 char *p = skip_string(str2,1);
3026 struct pack_desc desc;
3028 memset((char *)&desc,'\0',sizeof(desc));
3032 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3034 /* check it's a supported varient */
3035 if (strcmp(str1,"WrLeh") != 0) return False;
3036 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3038 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3040 desc.buflen = mdrcnt;
3041 if (init_package(&desc,1,0)) {
3042 PACKS(&desc,"B41","NULL");
3045 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3047 *rdata_len = desc.usedlen;
3050 *rparam = REALLOC(*rparam,*rparam_len);
3051 SSVALS(*rparam,0,desc.errcode);
3053 SSVAL(*rparam,4,succnt);
3056 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3060 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3061 int mdrcnt,int mprcnt,
3062 char **rdata,char **rparam,
3063 int *rdata_len,int *rparam_len)
3065 char *str1 = param+2;
3066 char *str2 = skip_string(str1,1);
3067 char *p = skip_string(str2,1);
3070 struct pack_desc desc;
3072 memset((char *)&desc,'\0',sizeof(desc));
3076 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3078 /* check it's a supported varient */
3079 if (strcmp(str1,"WrLeh") != 0) return False;
3080 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3082 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3084 desc.buflen = mdrcnt;
3086 if (init_package(&desc,1,0)) {
3087 PACKS(&desc,"B13","lpd");
3090 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3092 *rdata_len = desc.usedlen;
3095 *rparam = REALLOC(*rparam,*rparam_len);
3096 SSVALS(*rparam,0,desc.errcode);
3098 SSVAL(*rparam,4,succnt);
3101 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3105 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3106 int mdrcnt,int mprcnt,
3107 char **rdata,char **rparam,
3108 int *rdata_len,int *rparam_len)
3110 char *str1 = param+2;
3111 char *str2 = skip_string(str1,1);
3112 char *p = skip_string(str2,1);
3115 struct pack_desc desc;
3117 memset((char *)&desc,'\0',sizeof(desc));
3121 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3123 /* check it's a supported varient */
3124 if (strcmp(str1,"WrLeh") != 0) return False;
3125 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3127 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3128 memset((char *)&desc,'\0',sizeof(desc));
3130 desc.buflen = mdrcnt;
3132 if (init_package(&desc,1,0)) {
3133 PACKS(&desc,"B13","lp0");
3136 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3138 *rdata_len = desc.usedlen;
3141 *rparam = REALLOC(*rparam,*rparam_len);
3142 SSVALS(*rparam,0,desc.errcode);
3144 SSVAL(*rparam,4,succnt);
3147 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3151 /****************************************************************************
3152 The buffer was too small
3153 ****************************************************************************/
3155 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3156 int mdrcnt,int mprcnt,
3157 char **rdata,char **rparam,
3158 int *rdata_len,int *rparam_len)
3160 *rparam_len = MIN(*rparam_len,mprcnt);
3161 *rparam = REALLOC(*rparam,*rparam_len);
3165 SSVAL(*rparam,0,NERR_BufTooSmall);
3167 DEBUG(3,("Supplied buffer too small in API command\n"));
3173 /****************************************************************************
3174 The request is not supported
3175 ****************************************************************************/
3177 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3178 int mdrcnt,int mprcnt,
3179 char **rdata,char **rparam,
3180 int *rdata_len,int *rparam_len)
3183 *rparam = REALLOC(*rparam,*rparam_len);
3187 SSVAL(*rparam,0,NERR_notsupported);
3188 SSVAL(*rparam,2,0); /* converter word */
3190 DEBUG(3,("Unsupported API command\n"));
3202 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3203 int,int,char **,char **,int *,int *);
3205 } api_commands[] = {
3206 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3207 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3208 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3209 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3210 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3211 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3212 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3213 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3214 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3215 {"WPrintQueuePause", 74, api_WPrintQueueCtrl,0},
3216 {"WPrintQueueResume", 75, api_WPrintQueueCtrl,0},
3217 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3218 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3219 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3220 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3221 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3222 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3223 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3224 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3225 {"WPrintQueuePurge", 103, api_WPrintQueueCtrl,0},
3226 {"NetServerEnum", 104, api_RNetServerEnum,0},
3227 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3228 {"SetUserPassword", 115, api_SetUserPassword,0},
3229 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3230 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3231 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3232 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3233 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3234 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3235 {NULL, -1, api_Unsupported,0}};
3238 /****************************************************************************
3239 Handle remote api calls
3240 ****************************************************************************/
3242 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3243 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3247 char *rparam = NULL;
3254 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3258 api_command = SVAL(params,0);
3260 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3263 skip_string(params+2,1),
3264 tdscnt,tpscnt,mdrcnt,mprcnt));
3266 for (i=0;api_commands[i].name;i++) {
3267 if (api_commands[i].id == api_command && api_commands[i].fn) {
3268 DEBUG(3,("Doing %s\n",api_commands[i].name));
3273 rdata = (char *)malloc(1024);
3275 memset(rdata,'\0',1024);
3277 rparam = (char *)malloc(1024);
3279 memset(rparam,'\0',1024);
3281 if(!rdata || !rparam) {
3282 DEBUG(0,("api_reply: malloc fail !\n"));
3286 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3287 &rdata,&rparam,&rdata_len,&rparam_len);
3290 if (rdata_len > mdrcnt ||
3291 rparam_len > mprcnt) {
3292 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3293 &rdata,&rparam,&rdata_len,&rparam_len);
3296 /* if we get False back then it's actually unsupported */
3298 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3299 &rdata,&rparam,&rdata_len,&rparam_len);
3301 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);