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);
79 StrnCpy(*dst,buf,*n-1);
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;
206 * This is the old error code we used. Aparently
207 * WinNT/2k systems return ERRbuftoosmall (2123) and
208 * OS/2 needs this. I'm leaving this here so we can revert
211 p->errcode = ERRmoredata;
213 p->errcode = ERRbuftoosmall;
217 p->errcode = NERR_Success;
220 p->stringbuf = p->base + i;
222 return(p->errcode == NERR_Success);
226 static int package(struct pack_desc* p, ...)
229 static int package(va_alist)
235 int needed=0, stringneeded;
237 int is_string=0, stringused;
244 p = va_arg(args,struct pack_desc *);
249 p->curpos = p->format;
251 p->curpos = p->subformat;
256 str = va_arg(args,char*);
257 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
266 switch( *p->curpos++ ) {
267 case 'W': /* word (2 byte) */
269 temp = va_arg(args,int);
270 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
272 case 'K': /* status word? (2 byte) */
274 temp = va_arg(args,int);
275 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
277 case 'N': /* count of substructures (word) at end */
279 p->subcount = va_arg(args,int);
280 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
282 case 'D': /* double word (4 byte) */
284 temp = va_arg(args,int);
285 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
287 case 'B': /* byte (with optional counter) */
288 needed = get_counter(&p->curpos);
290 char *s = va_arg(args,char*);
291 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
294 case 'z': /* offset to zero terminated string (4 byte) */
295 str = va_arg(args,char*);
296 stringneeded = (str ? strlen(str)+1 : 0);
299 case 'l': /* offset to user data (4 byte) */
300 str = va_arg(args,char*);
301 stringneeded = va_arg(args,int);
304 case 'b': /* offset to data (with counter) (4 byte) */
305 str = va_arg(args,char*);
306 stringneeded = get_counter(&p->curpos);
311 if (stringneeded >= 0) {
313 if (p->buflen >= needed) {
314 stringused = stringneeded;
315 if (stringused > p->stringlen) {
316 stringused = (is_string ? p->stringlen : 0);
317 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
320 SIVAL(p->structbuf,0,0);
322 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
323 memcpy(p->stringbuf,str?str:"",stringused);
324 if (is_string) p->stringbuf[stringused-1] = '\0';
325 p->stringbuf += stringused;
326 p->stringlen -= stringused;
327 p->usedlen += stringused;
330 p->neededlen += stringneeded;
332 p->neededlen += needed;
333 if (p->buflen >= needed) {
334 p->structbuf += needed;
336 p->usedlen += needed;
339 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
345 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
346 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
348 #define PACK(desc,t,v) package(desc,v)
349 #define PACKl(desc,t,v,l) package(desc,v,l)
352 static void PACKI(struct pack_desc* desc,char *t,int v)
357 static void PACKS(struct pack_desc* desc,char *t,char *v)
363 /****************************************************************************
365 ****************************************************************************/
366 static void PackDriverData(struct pack_desc* desc)
368 char drivdata[4+4+32];
369 SIVAL(drivdata,0,sizeof drivdata); /* cb */
370 SIVAL(drivdata,4,1000); /* lVersion */
371 memset(drivdata+8,0,32); /* szDeviceName */
372 pstrcpy(drivdata+8,"NULL");
373 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
376 static int check_printq_info(struct pack_desc* desc,
377 int uLevel, char *id1, char *id2)
379 desc->subformat = NULL;
382 desc->format = "B13";
385 desc->format = "B13BWWWzzzzzWW";
388 desc->format = "B13BWWWzzzzzWN";
389 desc->subformat = "WB21BB16B10zWWzDDz";
392 desc->format = "zWWWWzzzzWWzzl";
395 desc->format = "zWWWWzzzzWNzzl";
396 desc->subformat = "WWzWWDDzz";
405 desc->format = "WzzzzzzzzN";
406 desc->subformat = "z";
408 default: return False;
410 if (strcmp(desc->format,id1) != 0) return False;
411 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
416 #define JOB_STATUS_QUEUED 0
417 #define JOB_STATUS_PAUSED 1
418 #define JOB_STATUS_SPOOLING 2
419 #define JOB_STATUS_PRINTING 3
420 #define JOB_STATUS_PRINTED 4
422 #define QUEUE_STATUS_PAUSED 1
423 #define QUEUE_STATUS_ERROR 2
425 /* turn a print job status into a on the wire status
427 static int printj_status(int v)
431 return JOB_STATUS_QUEUED;
433 return JOB_STATUS_PAUSED;
435 return JOB_STATUS_SPOOLING;
437 return JOB_STATUS_PRINTING;
442 /* turn a print queue status into a on the wire status
444 static int printq_status(int v)
450 return QUEUE_STATUS_PAUSED;
452 return QUEUE_STATUS_ERROR;
455 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
456 struct pack_desc* desc,
457 print_queue_struct* queue, int n)
459 time_t t = queue->time;
461 /* the client expects localtime */
464 PACKI(desc,"W",queue->job); /* uJobId */
466 PACKS(desc,"B21",queue->user); /* szUserName */
467 PACKS(desc,"B",""); /* pad */
468 PACKS(desc,"B16",""); /* szNotifyName */
469 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
470 PACKS(desc,"z",""); /* pszParms */
471 PACKI(desc,"W",n+1); /* uPosition */
472 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
473 PACKS(desc,"z",""); /* pszStatus */
474 PACKI(desc,"D",t); /* ulSubmitted */
475 PACKI(desc,"D",queue->size); /* ulSize */
476 PACKS(desc,"z",queue->file); /* pszComment */
478 if (uLevel == 2 || uLevel == 3) {
479 PACKI(desc,"W",queue->priority); /* uPriority */
480 PACKS(desc,"z",queue->user); /* pszUserName */
481 PACKI(desc,"W",n+1); /* uPosition */
482 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
483 PACKI(desc,"D",t); /* ulSubmitted */
484 PACKI(desc,"D",queue->size); /* ulSize */
485 PACKS(desc,"z","Samba"); /* pszComment */
486 PACKS(desc,"z",queue->file); /* pszDocument */
488 PACKS(desc,"z",""); /* pszNotifyName */
489 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
490 PACKS(desc,"z",""); /* pszParms */
491 PACKS(desc,"z",""); /* pszStatus */
492 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
493 PACKS(desc,"z","lpd"); /* pszQProcName */
494 PACKS(desc,"z",""); /* pszQProcParms */
495 PACKS(desc,"z","NULL"); /* pszDriverName */
496 PackDriverData(desc); /* pDriverData */
497 PACKS(desc,"z",""); /* pszPrinterName */
502 /********************************************************************
503 Respond to the DosPrintQInfo command with a level of 52
504 This is used to get printer driver information for Win9x clients
505 ********************************************************************/
506 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
507 struct pack_desc* desc,
508 int count, print_queue_struct* queue,
509 print_status_struct* status)
513 pstring tok,driver,datafile,langmon,helpfile,datatype;
517 NT_PRINTER_INFO_LEVEL *info = NULL;
522 * Check in the tdb *first* before checking the legacy
523 * files. This allows an NT upload to take precedence over
524 * the existing fileset. JRA.
526 * we need to lookup the driver name prior to making the call
527 * to get_a_printer_driver_9x_compatible() and not rely on the
528 * 'print driver' parameter --jerry
531 get_a_printer (&info, 2, lp_servicename(snum));
532 if ((info != NULL) &&
533 ((ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername)) == True))
537 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n",
538 info->info_2->drivername, gen_line));
542 /* didn't find driver in tdb */
544 DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
545 snum, lp_printerdriver(snum), lp_driverfile(snum)));
547 lines = file_lines_load(lp_driverfile(snum),NULL, False);
550 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
552 desc->errcode=NERR_notsupported;
556 /* lookup the long printer driver name in the file description */
557 for (i=0;lines[i] && !ok;i++)
560 if (next_token(&p,tok,":",sizeof(tok)) &&
561 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
562 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
571 /* driver file name */
572 if (!next_token(&p,driver,":",sizeof(driver)))
576 if (!next_token(&p,datafile,":",sizeof(datafile)))
580 * for the next tokens - which may be empty - I have
581 * to check for empty tokens first because the
582 * next_token function will skip all empty token
591 else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
594 /* language monitor */
600 else if (!next_token(&p,langmon,":",sizeof(langmon)))
603 /* default data type */
604 if (!next_token(&p,datatype,":",sizeof(datatype)))
607 PACKI(desc,"W",0x0400); /* don't know */
610 PACKS(desc,"z",info->info_2->drivername); /* long printer name */
614 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
616 PACKS(desc,"z",driver); /* Driverfile Name */
617 PACKS(desc,"z",datafile); /* Datafile name */
618 PACKS(desc,"z",langmon); /* language monitor */
621 fstrcpy(location, "\\\\");
622 fstrcat(location, global_myname);
623 fstrcat(location, "\\print$\\WIN40\\0");
624 PACKS(desc,"z",location); /* share to retrieve files */
628 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
630 PACKS(desc,"z",datatype); /* default data type */
631 PACKS(desc,"z",helpfile); /* helpfile name */
632 PACKS(desc,"z",driver); /* driver name */
635 DEBUG(3,("lp_printerdriver:%s:\n",info->info_2->drivername));
637 DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum)));
639 DEBUG(3,("Driver:%s:\n",driver));
640 DEBUG(3,("Data File:%s:\n",datafile));
641 DEBUG(3,("Language Monitor:%s:\n",langmon));
643 DEBUG(3,("lp_driverlocation:%s:\n",location));
645 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
646 DEBUG(3,("Data Type:%s:\n",datatype));
647 DEBUG(3,("Help File:%s:\n",helpfile));
648 PACKI(desc,"N",count); /* number of files to copy */
650 for (i=0;i<count;i++)
652 /* no need to check return value here
653 * - it was already tested in
654 * get_printerdrivernumber */
655 next_token(&p,tok,",",sizeof(tok));
656 PACKS(desc,"z",tok); /* driver files to copy */
657 DEBUG(3,("file:%s:\n",tok));
660 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
661 SERVICE(snum),count));
663 desc->errcode=NERR_Success;
669 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
670 desc->errcode=NERR_notsupported;
674 file_lines_free(lines);
678 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
679 struct pack_desc* desc,
680 int count, print_queue_struct* queue,
681 print_status_struct* status)
686 PACKS(desc,"B13",SERVICE(snum));
691 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
694 PACKI(desc,"K",printq_status(status->status));
698 if (uLevel == 1 || uLevel == 2) {
699 PACKS(desc,"B",""); /* alignment */
700 PACKI(desc,"W",5); /* priority */
701 PACKI(desc,"W",0); /* start time */
702 PACKI(desc,"W",0); /* until time */
703 PACKS(desc,"z",""); /* pSepFile */
704 PACKS(desc,"z","lpd"); /* pPrProc */
705 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
706 PACKS(desc,"z",""); /* pParms */
708 PACKS(desc,"z","UNKNOWN PRINTER");
709 PACKI(desc,"W",LPSTAT_ERROR);
711 else if (!status || !status->message[0]) {
712 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
713 PACKI(desc,"W",LPSTAT_OK); /* status */
715 PACKS(desc,"z",status->message);
716 PACKI(desc,"W",printq_status(status->status)); /* status */
718 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
721 if (uLevel == 3 || uLevel == 4) {
722 PACKI(desc,"W",5); /* uPriority */
723 PACKI(desc,"W",0); /* uStarttime */
724 PACKI(desc,"W",0); /* uUntiltime */
725 PACKI(desc,"W",5); /* pad1 */
726 PACKS(desc,"z",""); /* pszSepFile */
727 PACKS(desc,"z","WinPrint"); /* pszPrProc */
728 PACKS(desc,"z",""); /* pszParms */
729 if (!status || !status->message[0]) {
730 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
731 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
733 PACKS(desc,"z",status->message); /* pszComment */
734 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
736 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
737 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
738 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
739 PackDriverData(desc); /* pDriverData */
742 if (uLevel == 2 || uLevel == 4) {
744 for (i=0;i<count;i++)
745 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
749 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
753 /* This function returns the number of files for a given driver */
754 static int get_printerdrivernumber(int snum)
762 NT_PRINTER_INFO_LEVEL *info = NULL;
765 * Check in the tdb *first* before checking the legacy
766 * files. This allows an NT upload to take precedence over
767 * the existing fileset. JRA.
769 * we need to lookup the driver name prior to making the call
770 * to get_a_printer_driver_9x_compatible() and not rely on the
771 * 'print driver' parameter --jerry
774 get_a_printer (&info, 2, lp_servicename(snum));
775 if ((info != NULL) &&
776 (ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername) == True))
779 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
783 /* didn't find driver in tdb */
785 DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
786 snum, lp_printerdriver(snum), lp_driverfile(snum)));
788 lines = file_lines_load(lp_driverfile(snum), NULL, False);
791 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
795 /* lookup the long printer driver name in the file description */
796 for (i=0;lines[i] && !ok;i++)
799 if (next_token(&p,tok,":",sizeof(tok)) &&
800 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
801 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
813 if (*p++ == ':') i--;
816 DEBUG(3,("Can't determine number of printer driver files\n"));
820 /* count the number of files */
821 while (next_token(&p,tok,",",sizeof(tok)))
830 file_lines_free(lines);
835 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
836 uint16 vuid, char *param,char *data,
837 int mdrcnt,int mprcnt,
838 char **rdata,char **rparam,
839 int *rdata_len,int *rparam_len)
841 char *str1 = param+2;
842 char *str2 = skip_string(str1,1);
843 char *p = skip_string(str2,1);
849 struct pack_desc desc;
850 print_queue_struct *queue=NULL;
851 print_status_struct status;
853 memset((char *)&status,'\0',sizeof(status));
854 memset((char *)&desc,'\0',sizeof(desc));
856 p = skip_string(p,1);
860 /* remove any trailing username */
861 if ((p = strchr(QueueName,'%'))) *p = 0;
863 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
865 /* check it's a supported varient */
866 if (!prefix_ok(str1,"zWrLh")) return False;
867 if (!check_printq_info(&desc,uLevel,str2,str3)) {
869 * Patch from Scott Moomaw <scott@bridgewater.edu>
870 * to return the 'invalid info level' error if an
871 * unknown level was requested.
875 *rparam = REALLOC(*rparam,*rparam_len);
876 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
882 snum = lp_servicenumber(QueueName);
883 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
884 int pnum = lp_servicenumber(PRINTERS_NAME);
886 lp_add_printer(QueueName,pnum);
887 snum = lp_servicenumber(QueueName);
891 if (snum < 0 || !VALID_SNUM(snum)) return(False);
894 count = get_printerdrivernumber(snum);
895 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
897 count = print_queue_status(snum, &queue,&status);
900 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
902 desc.buflen = mdrcnt;
903 if (init_package(&desc,1,count)) {
904 desc.subcount = count;
905 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
906 } else if(uLevel == 0) {
909 * This is a *disgusting* hack.
910 * This is *so* bad that even I'm embarrassed (and I
911 * have no shame). Here's the deal :
912 * Until we get the correct SPOOLSS code into smbd
913 * then when we're running with NT SMB support then
914 * NT makes this call with a level of zero, and then
915 * immediately follows it with an open request to
916 * the \\SRVSVC pipe. If we allow that open to
917 * succeed then NT barfs when it cannot open the
918 * \\SPOOLSS pipe immediately after and continually
919 * whines saying "Printer name is invalid" forever
920 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
921 * to fail, then NT downgrades to using the downlevel code
922 * and everything works as well as before. I hate
923 * myself for adding this code.... JRA.
926 fail_next_srvsvc_open();
930 *rdata_len = desc.usedlen;
933 *rparam = REALLOC(*rparam,*rparam_len);
934 SSVALS(*rparam,0,desc.errcode);
936 SSVAL(*rparam,4,desc.neededlen);
938 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
940 if (queue) free(queue);
945 /****************************************************************************
946 View list of all print jobs on all queues.
947 ****************************************************************************/
949 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
950 int mdrcnt, int mprcnt,
951 char **rdata, char** rparam,
952 int *rdata_len, int *rparam_len)
954 char *param_format = param+2;
955 char *output_format1 = skip_string(param_format,1);
956 char *p = skip_string(output_format1,1);
957 int uLevel = SVAL(p,0);
958 char *output_format2 = p + 4;
959 int services = lp_numservices();
961 struct pack_desc desc;
962 print_queue_struct **queue = NULL;
963 print_status_struct *status = NULL;
964 int* subcntarr = NULL;
965 int queuecnt, subcnt=0, succnt=0;
967 memset((char *)&desc,'\0',sizeof(desc));
969 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
971 if (!prefix_ok(param_format,"WrLeh")) return False;
972 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
974 * Patch from Scott Moomaw <scott@bridgewater.edu>
975 * to return the 'invalid info level' error if an
976 * unknown level was requested.
980 *rparam = REALLOC(*rparam,*rparam_len);
981 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
988 for (i = 0; i < services; i++)
989 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
992 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
993 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
996 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
997 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
998 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1001 memset(status,0,queuecnt*sizeof(print_status_struct));
1002 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
1003 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1008 for (i = 0; i < services; i++)
1009 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1010 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1011 subcnt += subcntarr[n];
1015 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1017 desc.buflen = mdrcnt;
1019 if (init_package(&desc,queuecnt,subcnt)) {
1022 for (i = 0; i < services; i++)
1023 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1024 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1026 if (desc.errcode == NERR_Success) succnt = n;
1030 if (subcntarr) free(subcntarr);
1032 *rdata_len = desc.usedlen;
1034 *rparam = REALLOC(*rparam,*rparam_len);
1035 SSVALS(*rparam,0,desc.errcode);
1037 SSVAL(*rparam,4,succnt);
1038 SSVAL(*rparam,6,queuecnt);
1040 for (i = 0; i < queuecnt; i++) {
1041 if (queue && queue[i]) free(queue[i]);
1044 if (queue) free(queue);
1045 if (status) free(status);
1050 /****************************************************************************
1051 get info level for a server list query
1052 ****************************************************************************/
1053 static BOOL check_server_info(int uLevel, char* id)
1057 if (strcmp(id,"B16") != 0) return False;
1060 if (strcmp(id,"B16BBDz") != 0) return False;
1068 struct srv_info_struct
1078 /*******************************************************************
1079 get server info lists from the files saved by nmbd. Return the
1081 ******************************************************************/
1082 static int get_server_info(uint32 servertype,
1083 struct srv_info_struct **servers,
1089 BOOL local_list_only;
1092 lines = file_lines_load(lock_path(SERVER_LIST), NULL, False);
1094 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1098 /* request for everything is code for request all servers */
1099 if (servertype == SV_TYPE_ALL)
1100 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1102 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1104 DEBUG(4,("Servertype search: %8x\n",servertype));
1106 for (i=0;lines[i];i++) {
1108 struct srv_info_struct *s;
1109 char *ptr = lines[i];
1112 if (!*ptr) continue;
1114 if (count == alloced) {
1116 (*servers) = (struct srv_info_struct *)
1117 Realloc(*servers,sizeof(**servers)*alloced);
1118 if (!(*servers)) return(0);
1119 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1121 s = &(*servers)[count];
1123 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1124 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1125 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1126 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1127 /* this allows us to cope with an old nmbd */
1128 pstrcpy(s->domain,global_myworkgroup);
1131 if (sscanf(stype,"%X",&s->type) != 1) {
1132 DEBUG(4,("r:host file "));
1136 /* Filter the servers/domains we return based on what was asked for. */
1138 /* Check to see if we are being asked for a local list only. */
1139 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1140 DEBUG(4,("r: local list only"));
1144 /* doesn't match up: don't want it */
1145 if (!(servertype & s->type)) {
1146 DEBUG(4,("r:serv type "));
1150 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1151 (s->type & SV_TYPE_DOMAIN_ENUM))
1153 DEBUG(4,("s: dom mismatch "));
1157 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1162 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1163 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1167 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1168 s->name, s->type, s->comment, s->domain));
1170 s->server_added = True;
1175 DEBUG(4,("%20s %8x %25s %15s\n",
1176 s->name, s->type, s->comment, s->domain));
1180 file_lines_free(lines);
1185 /*******************************************************************
1186 fill in a server info structure
1187 ******************************************************************/
1188 static int fill_srv_info(struct srv_info_struct *service,
1189 int uLevel, char **buf, int *buflen,
1190 char **stringbuf, int *stringspace, char *baseaddr)
1199 case 0: struct_len = 16; break;
1200 case 1: struct_len = 26; break;
1210 len = strlen(service->comment)+1;
1214 if (buflen) *buflen = struct_len;
1215 if (stringspace) *stringspace = len;
1216 return struct_len + len;
1221 if (*buflen < struct_len) return -1;
1229 p2 = p + struct_len;
1230 l2 = *buflen - struct_len;
1232 if (!baseaddr) baseaddr = p;
1237 StrnCpy(p,service->name,15);
1241 StrnCpy(p,service->name,15);
1242 SIVAL(p,18,service->type);
1243 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1244 len += CopyAndAdvance(&p2,service->comment,&l2);
1250 *buf = p + struct_len;
1251 *buflen -= struct_len;
1264 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1266 return(strcmp(s1->name,s2->name));
1269 /****************************************************************************
1270 view list of servers available (or possibly domains). The info is
1271 extracted from lists saved by nmbd on the local host
1272 ****************************************************************************/
1273 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1274 int mdrcnt, int mprcnt, char **rdata,
1275 char **rparam, int *rdata_len, int *rparam_len)
1277 char *str1 = param+2;
1278 char *str2 = skip_string(str1,1);
1279 char *p = skip_string(str2,1);
1280 int uLevel = SVAL(p,0);
1281 int buf_len = SVAL(p,2);
1282 uint32 servertype = IVAL(p,4);
1284 int data_len, fixed_len, string_len;
1285 int f_len = 0, s_len = 0;
1286 struct srv_info_struct *servers=NULL;
1287 int counted=0,total=0;
1290 BOOL domain_request;
1293 /* If someone sets all the bits they don't really mean to set
1294 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1297 if (servertype == SV_TYPE_ALL)
1298 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1300 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1301 any other bit (they may just set this bit on it's own) they
1302 want all the locally seen servers. However this bit can be
1303 set on its own so set the requested servers to be
1304 ALL - DOMAIN_ENUM. */
1306 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1307 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1309 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1310 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1314 if (!prefix_ok(str1,"WrLehD")) return False;
1315 if (!check_server_info(uLevel,str2)) return False;
1317 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1318 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1319 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1321 if (strcmp(str1, "WrLehDz") == 0) {
1322 StrnCpy(domain, p, sizeof(fstring)-1);
1324 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1327 if (lp_browse_list())
1328 total = get_server_info(servertype,&servers,domain);
1330 data_len = fixed_len = string_len = 0;
1333 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1336 char *lastname=NULL;
1338 for (i=0;i<total;i++)
1340 struct srv_info_struct *s = &servers[i];
1341 if (lastname && strequal(lastname,s->name)) continue;
1343 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1344 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1345 s->name, s->type, s->comment, s->domain));
1347 if (data_len <= buf_len) {
1350 string_len += s_len;
1357 *rdata_len = fixed_len + string_len;
1358 *rdata = REALLOC(*rdata,*rdata_len);
1359 memset(*rdata,'\0',*rdata_len);
1361 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1367 char *lastname=NULL;
1368 int count2 = counted;
1369 for (i = 0; i < total && count2;i++)
1371 struct srv_info_struct *s = &servers[i];
1372 if (lastname && strequal(lastname,s->name)) continue;
1374 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1375 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1376 s->name, s->type, s->comment, s->domain));
1382 *rparam = REALLOC(*rparam,*rparam_len);
1383 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1385 SSVAL(*rparam,4,counted);
1386 SSVAL(*rparam,6,counted+missed);
1388 if (servers) free(servers);
1390 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1391 domain,uLevel,counted,counted+missed));
1396 /****************************************************************************
1397 command 0x34 - suspected of being a "Lookup Names" stub api
1398 ****************************************************************************/
1399 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1400 int mdrcnt, int mprcnt, char **rdata,
1401 char **rparam, int *rdata_len, int *rparam_len)
1403 char *str1 = param+2;
1404 char *str2 = skip_string(str1,1);
1405 char *p = skip_string(str2,1);
1406 int uLevel = SVAL(p,0);
1407 int buf_len = SVAL(p,2);
1411 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1412 str1, str2, p, uLevel, buf_len));
1414 if (!prefix_ok(str1,"zWrLeh")) return False;
1419 *rparam = REALLOC(*rparam,*rparam_len);
1421 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1423 SSVAL(*rparam,4,counted);
1424 SSVAL(*rparam,6,counted+missed);
1429 /****************************************************************************
1430 get info about a share
1431 ****************************************************************************/
1432 static BOOL check_share_info(int uLevel, char* id)
1436 if (strcmp(id,"B13") != 0) return False;
1439 if (strcmp(id,"B13BWz") != 0) return False;
1442 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1445 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1447 default: return False;
1452 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1453 char** buf, int* buflen,
1454 char** stringbuf, int* stringspace, char* baseaddr)
1463 case 0: struct_len = 13; break;
1464 case 1: struct_len = 20; break;
1465 case 2: struct_len = 40; break;
1466 case 91: struct_len = 68; break;
1474 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1475 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1476 if (buflen) *buflen = struct_len;
1477 if (stringspace) *stringspace = len;
1478 return struct_len + len;
1483 if ((*buflen) < struct_len) return -1;
1491 p2 = p + struct_len;
1492 l2 = (*buflen) - struct_len;
1494 if (!baseaddr) baseaddr = p;
1496 StrnCpy(p,lp_servicename(snum),13);
1502 type = STYPE_DISKTREE;
1503 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1504 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1505 SSVAL(p,14,type); /* device type */
1506 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1507 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1512 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1513 SSVALS(p,22,-1); /* max uses */
1514 SSVAL(p,24,1); /* current uses */
1515 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1516 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1517 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1522 memset(p+40,0,SHPWLEN+2);
1534 (*buf) = p + struct_len;
1535 (*buflen) -= struct_len;
1537 (*stringspace) = l2;
1547 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1548 int mdrcnt,int mprcnt,
1549 char **rdata,char **rparam,
1550 int *rdata_len,int *rparam_len)
1552 char *str1 = param+2;
1553 char *str2 = skip_string(str1,1);
1554 char *netname = skip_string(str2,1);
1555 char *p = skip_string(netname,1);
1556 int uLevel = SVAL(p,0);
1557 int snum = find_service(netname);
1559 if (snum < 0) return False;
1561 /* check it's a supported varient */
1562 if (!prefix_ok(str1,"zWrLh")) return False;
1563 if (!check_share_info(uLevel,str2)) return False;
1565 *rdata = REALLOC(*rdata,mdrcnt);
1567 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1568 if (*rdata_len < 0) return False;
1571 *rparam = REALLOC(*rparam,*rparam_len);
1572 SSVAL(*rparam,0,NERR_Success);
1573 SSVAL(*rparam,2,0); /* converter word */
1574 SSVAL(*rparam,4,*rdata_len);
1579 /****************************************************************************
1580 view list of shares available
1581 ****************************************************************************/
1582 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1583 int mdrcnt,int mprcnt,
1584 char **rdata,char **rparam,
1585 int *rdata_len,int *rparam_len)
1587 char *str1 = param+2;
1588 char *str2 = skip_string(str1,1);
1589 char *p = skip_string(str2,1);
1590 int uLevel = SVAL(p,0);
1591 int buf_len = SVAL(p,2);
1593 int count=lp_numservices();
1594 int total=0,counted=0;
1595 BOOL missed = False;
1597 int data_len, fixed_len, string_len;
1598 int f_len = 0, s_len = 0;
1600 if (!prefix_ok(str1,"WrLeh")) return False;
1601 if (!check_share_info(uLevel,str2)) return False;
1603 data_len = fixed_len = string_len = 0;
1604 for (i=0;i<count;i++)
1605 if (lp_browseable(i) && lp_snum_ok(i))
1608 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1609 if (data_len <= buf_len)
1613 string_len += s_len;
1618 *rdata_len = fixed_len + string_len;
1619 *rdata = REALLOC(*rdata,*rdata_len);
1620 memset(*rdata,0,*rdata_len);
1622 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1626 for (i = 0; i < count;i++)
1627 if (lp_browseable(i) && lp_snum_ok(i))
1628 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1632 *rparam = REALLOC(*rparam,*rparam_len);
1633 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1635 SSVAL(*rparam,4,counted);
1636 SSVAL(*rparam,6,total);
1638 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1639 counted,total,uLevel,
1640 buf_len,*rdata_len,mdrcnt));
1646 /****************************************************************************
1647 get the time of day info
1648 ****************************************************************************/
1649 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1650 int mdrcnt,int mprcnt,
1651 char **rdata,char **rparam,
1652 int *rdata_len,int *rparam_len)
1656 *rparam = REALLOC(*rparam,*rparam_len);
1659 *rdata = REALLOC(*rdata,*rdata_len);
1661 SSVAL(*rparam,0,NERR_Success);
1662 SSVAL(*rparam,2,0); /* converter word */
1668 time_t unixdate = time(NULL);
1670 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1671 by NT in a "net time" operation,
1672 it seems to ignore the one below */
1674 /* the client expects to get localtime, not GMT, in this bit
1675 (I think, this needs testing) */
1676 t = LocalTime(&unixdate);
1678 SIVAL(p,4,0); /* msecs ? */
1679 CVAL(p,8) = t->tm_hour;
1680 CVAL(p,9) = t->tm_min;
1681 CVAL(p,10) = t->tm_sec;
1682 CVAL(p,11) = 0; /* hundredths of seconds */
1683 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1684 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1685 CVAL(p,16) = t->tm_mday;
1686 CVAL(p,17) = t->tm_mon + 1;
1687 SSVAL(p,18,1900+t->tm_year);
1688 CVAL(p,20) = t->tm_wday;
1695 /****************************************************************************
1696 Set the user password.
1697 *****************************************************************************/
1699 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1700 int mdrcnt,int mprcnt,
1701 char **rdata,char **rparam,
1702 int *rdata_len,int *rparam_len)
1704 char *p = skip_string(param+2,2);
1706 fstring pass1,pass2;
1710 p = skip_string(p,1);
1712 memset(pass1,'\0',sizeof(pass1));
1713 memset(pass2,'\0',sizeof(pass2));
1715 memcpy(pass2,p+16,16);
1718 *rparam = REALLOC(*rparam,*rparam_len);
1722 SSVAL(*rparam,0,NERR_badpass);
1723 SSVAL(*rparam,2,0); /* converter word */
1725 DEBUG(3,("Set password for <%s>\n",user));
1728 * Pass the user through the NT -> unix user mapping
1732 (void)map_username(user);
1735 * Do any UNIX username case mangling.
1737 (void)Get_Pwnam( user, True);
1740 * Attempt to verify the old password against smbpasswd entries
1741 * Win98 clients send old and new password in plaintext for this call.
1745 fstring saved_pass2;
1746 SAM_ACCOUNT *sampass;
1749 * Save the new password as change_oem_password overwrites it
1753 fstrcpy(saved_pass2, pass2);
1755 if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) &&
1756 change_oem_password(sampass,pass2,False))
1758 SSVAL(*rparam,0,NERR_Success);
1761 * If unix password sync was requested, attempt to change
1762 * the /etc/passwd database also. Return failure if this cannot
1766 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1767 SSVAL(*rparam,0,NERR_badpass);
1772 * If the above failed, attempt the plaintext password change.
1773 * This tests against the /etc/passwd database only.
1776 if(SVAL(*rparam,0) != NERR_Success)
1778 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1779 chgpasswd(user,pass1,pass2,False))
1781 SSVAL(*rparam,0,NERR_Success);
1786 * If the plaintext change failed, attempt
1787 * the old encrypted method. NT will generate this
1788 * after trying the samr method. Note that this
1789 * method is done as a last resort as this
1790 * password change method loses the NT password hash
1791 * and cannot change the UNIX password as no plaintext
1795 if(SVAL(*rparam,0) != NERR_Success)
1797 SAM_ACCOUNT *hnd = NULL;
1799 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1800 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
1802 SSVAL(*rparam,0,NERR_Success);
1806 memset((char *)pass1,'\0',sizeof(fstring));
1807 memset((char *)pass2,'\0',sizeof(fstring));
1812 /****************************************************************************
1813 Set the user password (SamOEM version - gets plaintext).
1814 ****************************************************************************/
1816 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1817 int mdrcnt,int mprcnt,
1818 char **rdata,char **rparam,
1819 int *rdata_len,int *rparam_len)
1822 char *p = param + 2;
1824 *rparam = REALLOC(*rparam,*rparam_len);
1828 SSVAL(*rparam,0,NERR_badpass);
1831 * Check the parameter definition is correct.
1833 if(!strequal(param + 2, "zsT")) {
1834 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1837 p = skip_string(p, 1);
1839 if(!strequal(p, "B516B16")) {
1840 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1843 p = skip_string(p,1);
1846 p = skip_string(p,1);
1848 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1851 * Pass the user through the NT -> unix user mapping
1855 (void)map_username(user);
1858 * Do any UNIX username case mangling.
1860 (void)Get_Pwnam( user, True);
1862 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1864 SSVAL(*rparam,0,NERR_Success);
1870 /****************************************************************************
1873 ****************************************************************************/
1874 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1875 int mdrcnt,int mprcnt,
1876 char **rdata,char **rparam,
1877 int *rdata_len,int *rparam_len)
1879 int function = SVAL(param,0);
1880 char *str1 = param+2;
1881 char *str2 = skip_string(str1,1);
1882 char *p = skip_string(str2,1);
1884 extern struct current_user current_user;
1888 /* check it's a supported varient */
1889 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1893 *rparam = REALLOC(*rparam,*rparam_len);
1896 if (!print_job_exists(jobid)) {
1897 errcode = NERR_JobNotFound;
1901 errcode = NERR_notsupported;
1904 case 81: /* delete */
1905 if (print_job_delete(¤t_user, jobid, &errcode))
1906 errcode = NERR_Success;
1908 case 82: /* pause */
1909 if (print_job_pause(¤t_user, jobid, &errcode))
1910 errcode = NERR_Success;
1912 case 83: /* resume */
1913 if (print_job_resume(¤t_user, jobid, &errcode))
1914 errcode = NERR_Success;
1919 SSVAL(*rparam,0,errcode);
1920 SSVAL(*rparam,2,0); /* converter word */
1925 /****************************************************************************
1926 Purge a print queue - or pause or resume it.
1927 ****************************************************************************/
1928 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
1929 int mdrcnt,int mprcnt,
1930 char **rdata,char **rparam,
1931 int *rdata_len,int *rparam_len)
1933 int function = SVAL(param,0);
1934 char *str1 = param+2;
1935 char *str2 = skip_string(str1,1);
1936 char *QueueName = skip_string(str2,1);
1937 int errcode = NERR_notsupported;
1940 /* check it's a supported varient */
1941 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1945 *rparam = REALLOC(*rparam,*rparam_len);
1948 snum = print_queue_snum(QueueName);
1951 errcode = NERR_JobNotFound;
1956 case 74: /* Pause queue */
1957 if (print_queue_pause(NULL, snum, &errcode)) errcode = NERR_Success;
1959 case 75: /* Resume queue */
1960 if (print_queue_resume(NULL, snum, &errcode)) errcode = NERR_Success;
1962 case 103: /* Purge */
1963 if (print_queue_purge(NULL, snum, &errcode)) errcode = NERR_Success;
1968 SSVAL(*rparam,0,errcode);
1969 SSVAL(*rparam,2,0); /* converter word */
1975 /****************************************************************************
1976 set the property of a print job (undocumented?)
1977 ? function = 0xb -> set name of print job
1978 ? function = 0x6 -> move print job up/down
1979 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1980 or <WWsTP> <WB21BB16B10zWWzDDz>
1981 ****************************************************************************/
1982 static int check_printjob_info(struct pack_desc* desc,
1983 int uLevel, char* id)
1985 desc->subformat = NULL;
1987 case 0: desc->format = "W"; break;
1988 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1989 case 2: desc->format = "WWzWWDDzz"; break;
1990 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1991 default: return False;
1993 if (strcmp(desc->format,id) != 0) return False;
1997 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1998 int mdrcnt,int mprcnt,
1999 char **rdata,char **rparam,
2000 int *rdata_len,int *rparam_len)
2002 struct pack_desc desc;
2003 char *str1 = param+2;
2004 char *str2 = skip_string(str1,1);
2005 char *p = skip_string(str2,1);
2007 int uLevel = SVAL(p,2);
2008 int function = SVAL(p,4);
2013 *rparam = REALLOC(*rparam,*rparam_len);
2017 /* check it's a supported varient */
2018 if ((strcmp(str1,"WWsTP")) ||
2019 (!check_printjob_info(&desc,uLevel,str2)))
2022 if (!print_job_exists(jobid)) {
2023 errcode=NERR_JobNotFound;
2027 errcode = NERR_notsupported;
2031 /* change job place in the queue,
2032 data gives the new place */
2033 place = SVAL(data,0);
2034 if (print_job_set_place(jobid, place)) {
2035 errcode=NERR_Success;
2040 /* change print job name, data gives the name */
2041 if (print_job_set_name(jobid, data)) {
2042 errcode=NERR_Success;
2051 SSVALS(*rparam,0,errcode);
2052 SSVAL(*rparam,2,0); /* converter word */
2058 /****************************************************************************
2059 get info about the server
2060 ****************************************************************************/
2061 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2062 int mdrcnt,int mprcnt,
2063 char **rdata,char **rparam,
2064 int *rdata_len,int *rparam_len)
2066 char *str1 = param+2;
2067 char *str2 = skip_string(str1,1);
2068 char *p = skip_string(str2,1);
2069 int uLevel = SVAL(p,0);
2073 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2075 /* check it's a supported varient */
2076 if (!prefix_ok(str1,"WrLh")) return False;
2079 if (strcmp(str2,"B16") != 0) return False;
2083 if (strcmp(str2,"B16BBDz") != 0) return False;
2087 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2092 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2097 if (strcmp(str2,"DN") != 0) return False;
2101 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2104 default: return False;
2107 *rdata_len = mdrcnt;
2108 *rdata = REALLOC(*rdata,*rdata_len);
2111 p2 = p + struct_len;
2113 StrnCpy(p,local_machine,16);
2119 struct srv_info_struct *servers=NULL;
2122 uint32 servertype= lp_default_server_announce();
2124 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2126 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2127 for (i=0;i<count;i++)
2128 if (strequal(servers[i].name,local_machine))
2130 servertype = servers[i].type;
2131 pstrcpy(comment,servers[i].comment);
2134 if (servers) free(servers);
2136 SCVAL(p,0,lp_major_announce_version());
2137 SCVAL(p,1,lp_minor_announce_version());
2138 SIVAL(p,2,servertype);
2140 if (mdrcnt == struct_len) {
2143 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2144 standard_sub_conn(conn,comment);
2145 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2146 p2 = skip_string(p2,1);
2151 return False; /* not yet implemented */
2154 *rdata_len = PTR_DIFF(p2,*rdata);
2157 *rparam = REALLOC(*rparam,*rparam_len);
2158 SSVAL(*rparam,0,NERR_Success);
2159 SSVAL(*rparam,2,0); /* converter word */
2160 SSVAL(*rparam,4,*rdata_len);
2166 /****************************************************************************
2167 get info about the server
2168 ****************************************************************************/
2169 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2170 int mdrcnt,int mprcnt,
2171 char **rdata,char **rparam,
2172 int *rdata_len,int *rparam_len)
2174 char *str1 = param+2;
2175 char *str2 = skip_string(str1,1);
2176 char *p = skip_string(str2,1);
2178 extern pstring sesssetup_user;
2179 int level = SVAL(p,0);
2181 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2184 *rparam = REALLOC(*rparam,*rparam_len);
2186 /* check it's a supported varient */
2187 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2190 *rdata_len = mdrcnt + 1024;
2191 *rdata = REALLOC(*rdata,*rdata_len);
2193 SSVAL(*rparam,0,NERR_Success);
2194 SSVAL(*rparam,2,0); /* converter word */
2200 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2201 pstrcpy(p2,local_machine);
2203 p2 = skip_string(p2,1);
2206 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2207 pstrcpy(p2,sesssetup_user);
2208 p2 = skip_string(p2,1);
2211 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2212 pstrcpy(p2,global_myworkgroup);
2214 p2 = skip_string(p2,1);
2217 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2218 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2221 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2222 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2223 p2 = skip_string(p2,1);
2226 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2228 p2 = skip_string(p2,1);
2231 *rdata_len = PTR_DIFF(p2,*rdata);
2233 SSVAL(*rparam,4,*rdata_len);
2238 /****************************************************************************
2239 get info about a user
2241 struct user_info_11 {
2242 char usri11_name[21]; 0-20
2244 char *usri11_comment; 22-25
2245 char *usri11_usr_comment; 26-29
2246 unsigned short usri11_priv; 30-31
2247 unsigned long usri11_auth_flags; 32-35
2248 long usri11_password_age; 36-39
2249 char *usri11_homedir; 40-43
2250 char *usri11_parms; 44-47
2251 long usri11_last_logon; 48-51
2252 long usri11_last_logoff; 52-55
2253 unsigned short usri11_bad_pw_count; 56-57
2254 unsigned short usri11_num_logons; 58-59
2255 char *usri11_logon_server; 60-63
2256 unsigned short usri11_country_code; 64-65
2257 char *usri11_workstations; 66-69
2258 unsigned long usri11_max_storage; 70-73
2259 unsigned short usri11_units_per_week; 74-75
2260 unsigned char *usri11_logon_hours; 76-79
2261 unsigned short usri11_code_page; 80-81
2266 usri11_name specifies the user name for which information is retireved
2268 usri11_pad aligns the next data structure element to a word boundary
2270 usri11_comment is a null terminated ASCII comment
2272 usri11_user_comment is a null terminated ASCII comment about the user
2274 usri11_priv specifies the level of the privilege assigned to the user.
2275 The possible values are:
2277 Name Value Description
2278 USER_PRIV_GUEST 0 Guest privilege
2279 USER_PRIV_USER 1 User privilege
2280 USER_PRV_ADMIN 2 Administrator privilege
2282 usri11_auth_flags specifies the account operator privileges. The
2283 possible values are:
2285 Name Value Description
2286 AF_OP_PRINT 0 Print operator
2289 Leach, Naik [Page 28]
2293 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2296 AF_OP_COMM 1 Communications operator
2297 AF_OP_SERVER 2 Server operator
2298 AF_OP_ACCOUNTS 3 Accounts operator
2301 usri11_password_age specifies how many seconds have elapsed since the
2302 password was last changed.
2304 usri11_home_dir points to a null terminated ASCII string that contains
2305 the path name of the user's home directory.
2307 usri11_parms points to a null terminated ASCII string that is set
2308 aside for use by applications.
2310 usri11_last_logon specifies the time when the user last logged on.
2311 This value is stored as the number of seconds elapsed since
2312 00:00:00, January 1, 1970.
2314 usri11_last_logoff specifies the time when the user last logged off.
2315 This value is stored as the number of seconds elapsed since
2316 00:00:00, January 1, 1970. A value of 0 means the last logoff
2319 usri11_bad_pw_count specifies the number of incorrect passwords
2320 entered since the last successful logon.
2322 usri11_log1_num_logons specifies the number of times this user has
2323 logged on. A value of -1 means the number of logons is unknown.
2325 usri11_logon_server points to a null terminated ASCII string that
2326 contains the name of the server to which logon requests are sent.
2327 A null string indicates logon requests should be sent to the
2330 usri11_country_code specifies the country code for the user's language
2333 usri11_workstations points to a null terminated ASCII string that
2334 contains the names of workstations the user may log on from.
2335 There may be up to 8 workstations, with the names separated by
2336 commas. A null strings indicates there are no restrictions.
2338 usri11_max_storage specifies the maximum amount of disk space the user
2339 can occupy. A value of 0xffffffff indicates there are no
2342 usri11_units_per_week specifies the equal number of time units into
2343 which a week is divided. This value must be equal to 168.
2345 usri11_logon_hours points to a 21 byte (168 bits) string that
2346 specifies the time during which the user can log on. Each bit
2347 represents one unique hour in a week. The first bit (bit 0, word
2348 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2352 Leach, Naik [Page 29]
2356 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2359 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2360 are no restrictions.
2362 usri11_code_page specifies the code page for the user's language of
2365 All of the pointers in this data structure need to be treated
2366 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2367 to be ignored. The converter word returned in the parameters section
2368 needs to be subtracted from the lower 16 bits to calculate an offset
2369 into the return buffer where this ASCII string resides.
2371 There is no auxiliary data in the response.
2373 ****************************************************************************/
2375 #define usri11_name 0
2376 #define usri11_pad 21
2377 #define usri11_comment 22
2378 #define usri11_usr_comment 26
2379 #define usri11_full_name 30
2380 #define usri11_priv 34
2381 #define usri11_auth_flags 36
2382 #define usri11_password_age 40
2383 #define usri11_homedir 44
2384 #define usri11_parms 48
2385 #define usri11_last_logon 52
2386 #define usri11_last_logoff 56
2387 #define usri11_bad_pw_count 60
2388 #define usri11_num_logons 62
2389 #define usri11_logon_server 64
2390 #define usri11_country_code 68
2391 #define usri11_workstations 70
2392 #define usri11_max_storage 74
2393 #define usri11_units_per_week 78
2394 #define usri11_logon_hours 80
2395 #define usri11_code_page 84
2396 #define usri11_end 86
2398 #define USER_PRIV_GUEST 0
2399 #define USER_PRIV_USER 1
2400 #define USER_PRIV_ADMIN 2
2402 #define AF_OP_PRINT 0
2403 #define AF_OP_COMM 1
2404 #define AF_OP_SERVER 2
2405 #define AF_OP_ACCOUNTS 3
2408 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2409 int mdrcnt,int mprcnt,
2410 char **rdata,char **rparam,
2411 int *rdata_len,int *rparam_len)
2413 char *str1 = param+2;
2414 char *str2 = skip_string(str1,1);
2415 char *UserName = skip_string(str2,1);
2416 char *p = skip_string(UserName,1);
2417 int uLevel = SVAL(p,0);
2420 /* get NIS home of a previously validated user - simeon */
2421 /* With share level security vuid will always be zero.
2422 Don't depend on vuser being non-null !!. JRA */
2423 user_struct *vuser = get_valid_user_struct(vuid);
2425 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2426 vuser->user.unix_name));
2429 *rparam = REALLOC(*rparam,*rparam_len);
2431 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2433 /* check it's a supported variant */
2434 if (strcmp(str1,"zWrLh") != 0) return False;
2437 case 0: p2 = "B21"; break;
2438 case 1: p2 = "B21BB16DWzzWz"; break;
2439 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2440 case 10: p2 = "B21Bzzz"; break;
2441 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2442 default: return False;
2445 if (strcmp(p2,str2) != 0) return False;
2447 *rdata_len = mdrcnt + 1024;
2448 *rdata = REALLOC(*rdata,*rdata_len);
2450 SSVAL(*rparam,0,NERR_Success);
2451 SSVAL(*rparam,2,0); /* converter word */
2454 p2 = p + usri11_end;
2457 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2461 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2466 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2467 pstrcpy(p2,"Comment");
2468 p2 = skip_string(p2,1);
2470 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2471 pstrcpy(p2,"UserComment");
2472 p2 = skip_string(p2,1);
2474 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2475 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2476 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2477 p2 = skip_string(p2,1);
2480 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2482 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2483 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2484 SIVALS(p,usri11_password_age,-1); /* password age */
2485 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2486 pstrcpy(p2, lp_logon_home());
2487 standard_sub_conn(conn, p2);
2488 p2 = skip_string(p2,1);
2489 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2491 p2 = skip_string(p2,1);
2492 SIVAL(p,usri11_last_logon,0); /* last logon */
2493 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2494 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2495 SSVALS(p,usri11_num_logons,-1); /* num logons */
2496 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2497 pstrcpy(p2,"\\\\*");
2498 p2 = skip_string(p2,1);
2499 SSVAL(p,usri11_country_code,0); /* country code */
2501 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2503 p2 = skip_string(p2,1);
2505 SIVALS(p,usri11_max_storage,-1); /* max storage */
2506 SSVAL(p,usri11_units_per_week,168); /* units per week */
2507 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2509 /* a simple way to get logon hours at all times. */
2511 SCVAL(p2,21,0); /* fix zero termination */
2512 p2 = skip_string(p2,1);
2514 SSVAL(p,usri11_code_page,0); /* code page */
2516 if (uLevel == 1 || uLevel == 2)
2518 memset(p+22,' ',16); /* password */
2519 SIVALS(p,38,-1); /* password age */
2521 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2522 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2523 pstrcpy(p2,lp_logon_home());
2524 standard_sub_conn(conn, p2);
2525 p2 = skip_string(p2,1);
2526 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2528 SSVAL(p,52,0); /* flags */
2529 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2530 pstrcpy(p2,lp_logon_script());
2531 standard_sub_conn( conn, p2 );
2532 p2 = skip_string(p2,1);
2535 SIVAL(p,60,0); /* auth_flags */
2536 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2537 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2538 p2 = skip_string(p2,1);
2539 SIVAL(p,68,0); /* urs_comment */
2540 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2542 p2 = skip_string(p2,1);
2543 SIVAL(p,76,0); /* workstations */
2544 SIVAL(p,80,0); /* last_logon */
2545 SIVAL(p,84,0); /* last_logoff */
2546 SIVALS(p,88,-1); /* acct_expires */
2547 SIVALS(p,92,-1); /* max_storage */
2548 SSVAL(p,96,168); /* units_per_week */
2549 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2552 SSVALS(p,102,-1); /* bad_pw_count */
2553 SSVALS(p,104,-1); /* num_logons */
2554 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2555 pstrcpy(p2,"\\\\%L");
2556 standard_sub_conn(conn, p2);
2557 p2 = skip_string(p2,1);
2558 SSVAL(p,110,49); /* country_code */
2559 SSVAL(p,112,860); /* code page */
2563 *rdata_len = PTR_DIFF(p2,*rdata);
2565 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2570 /*******************************************************************
2571 get groups that a user is a member of
2572 ******************************************************************/
2573 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2574 int mdrcnt,int mprcnt,
2575 char **rdata,char **rparam,
2576 int *rdata_len,int *rparam_len)
2578 char *str1 = param+2;
2579 char *str2 = skip_string(str1,1);
2580 char *UserName = skip_string(str2,1);
2581 char *p = skip_string(UserName,1);
2582 int uLevel = SVAL(p,0);
2587 *rparam = REALLOC(*rparam,*rparam_len);
2589 /* check it's a supported varient */
2590 if (strcmp(str1,"zWrLeh") != 0) return False;
2592 case 0: p2 = "B21"; break;
2593 default: return False;
2595 if (strcmp(p2,str2) != 0) return False;
2597 *rdata_len = mdrcnt + 1024;
2598 *rdata = REALLOC(*rdata,*rdata_len);
2600 SSVAL(*rparam,0,NERR_Success);
2601 SSVAL(*rparam,2,0); /* converter word */
2605 /* XXXX we need a real SAM database some day */
2606 pstrcpy(p,"Users"); p += 21; count++;
2607 pstrcpy(p,"Domain Users"); p += 21; count++;
2608 pstrcpy(p,"Guests"); p += 21; count++;
2609 pstrcpy(p,"Domain Guests"); p += 21; count++;
2611 *rdata_len = PTR_DIFF(p,*rdata);
2613 SSVAL(*rparam,4,count); /* is this right?? */
2614 SSVAL(*rparam,6,count); /* is this right?? */
2620 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2621 int mdrcnt,int mprcnt,
2622 char **rdata,char **rparam,
2623 int *rdata_len,int *rparam_len)
2625 char *str1 = param+2;
2626 char *str2 = skip_string(str1,1);
2627 char *p = skip_string(str2,1);
2629 struct pack_desc desc;
2635 memset((char *)&desc,'\0',sizeof(desc));
2637 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2639 /* check it's a supported varient */
2640 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2641 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2642 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2644 desc.buflen = mdrcnt;
2645 desc.subformat = NULL;
2648 if (init_package(&desc,1,0))
2650 PACKI(&desc,"W",0); /* code */
2651 PACKS(&desc,"B21",name); /* eff. name */
2652 PACKS(&desc,"B",""); /* pad */
2654 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2655 PACKI(&desc,"D",0); /* auth flags XXX */
2656 PACKI(&desc,"W",0); /* num logons */
2657 PACKI(&desc,"W",0); /* bad pw count */
2658 PACKI(&desc,"D",0); /* last logon */
2659 PACKI(&desc,"D",-1); /* last logoff */
2660 PACKI(&desc,"D",-1); /* logoff time */
2661 PACKI(&desc,"D",-1); /* kickoff time */
2662 PACKI(&desc,"D",0); /* password age */
2663 PACKI(&desc,"D",0); /* password can change */
2664 PACKI(&desc,"D",-1); /* password must change */
2667 fstrcpy(mypath,"\\\\");
2668 fstrcat(mypath,local_machine);
2670 PACKS(&desc,"z",mypath); /* computer */
2672 PACKS(&desc,"z",global_myworkgroup);/* domain */
2674 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2675 /* made sure all macros are fully substituted and available */
2677 pstring logon_script;
2678 pstrcpy(logon_script,lp_logon_script());
2679 standard_sub_conn( conn, logon_script );
2680 PACKS(&desc,"z", logon_script); /* script path */
2682 /* End of JHT mods */
2684 PACKI(&desc,"D",0x00000000); /* reserved */
2687 *rdata_len = desc.usedlen;
2689 *rparam = REALLOC(*rparam,*rparam_len);
2690 SSVALS(*rparam,0,desc.errcode);
2692 SSVAL(*rparam,4,desc.neededlen);
2694 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2699 /****************************************************************************
2700 api_WAccessGetUserPerms
2701 ****************************************************************************/
2702 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2703 int mdrcnt,int mprcnt,
2704 char **rdata,char **rparam,
2705 int *rdata_len,int *rparam_len)
2707 char *str1 = param+2;
2708 char *str2 = skip_string(str1,1);
2709 char *user = skip_string(str2,1);
2710 char *resource = skip_string(user,1);
2712 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2714 /* check it's a supported varient */
2715 if (strcmp(str1,"zzh") != 0) return False;
2716 if (strcmp(str2,"") != 0) return False;
2719 *rparam = REALLOC(*rparam,*rparam_len);
2720 SSVALS(*rparam,0,0); /* errorcode */
2721 SSVAL(*rparam,2,0); /* converter word */
2722 SSVAL(*rparam,4,0x7f); /* permission flags */
2727 /****************************************************************************
2728 api_WPrintJobEnumerate
2729 ****************************************************************************/
2730 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2731 int mdrcnt,int mprcnt,
2732 char **rdata,char **rparam,
2733 int *rdata_len,int *rparam_len)
2735 char *str1 = param+2;
2736 char *str2 = skip_string(str1,1);
2737 char *p = skip_string(str2,1);
2743 struct pack_desc desc;
2744 print_queue_struct *queue=NULL;
2745 print_status_struct status;
2749 memset((char *)&desc,'\0',sizeof(desc));
2750 memset((char *)&status,'\0',sizeof(status));
2752 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2754 /* check it's a supported varient */
2755 if (strcmp(str1,"WWrLh") != 0) return False;
2756 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2759 snum = print_job_snum(job);
2761 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2763 count = print_queue_status(snum,&queue,&status);
2764 for (i = 0; i < count; i++) {
2765 if (queue[i].job == job) break;
2767 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2769 desc.buflen = mdrcnt;
2771 if (init_package(&desc,1,0)) {
2773 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2774 *rdata_len = desc.usedlen;
2777 desc.errcode = NERR_JobNotFound;
2783 *rparam = REALLOC(*rparam,*rparam_len);
2784 SSVALS(*rparam,0,desc.errcode);
2786 SSVAL(*rparam,4,desc.neededlen);
2788 if (queue) free(queue);
2790 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2794 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2795 int mdrcnt,int mprcnt,
2796 char **rdata,char **rparam,
2797 int *rdata_len,int *rparam_len)
2799 char *str1 = param+2;
2800 char *str2 = skip_string(str1,1);
2801 char *p = skip_string(str2,1);
2807 struct pack_desc desc;
2808 print_queue_struct *queue=NULL;
2809 print_status_struct status;
2811 memset((char *)&desc,'\0',sizeof(desc));
2812 memset((char *)&status,'\0',sizeof(status));
2814 p = skip_string(p,1);
2817 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2819 /* check it's a supported varient */
2820 if (strcmp(str1,"zWrLeh") != 0) return False;
2821 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2822 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2824 snum = lp_servicenumber(name);
2825 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2826 int pnum = lp_servicenumber(PRINTERS_NAME);
2828 lp_add_printer(name,pnum);
2829 snum = lp_servicenumber(name);
2833 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2835 count = print_queue_status(snum,&queue,&status);
2836 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2838 desc.buflen = mdrcnt;
2840 if (init_package(&desc,count,0)) {
2842 for (i = 0; i < count; i++) {
2843 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2844 if (desc.errcode == NERR_Success) succnt = i+1;
2848 *rdata_len = desc.usedlen;
2851 *rparam = REALLOC(*rparam,*rparam_len);
2852 SSVALS(*rparam,0,desc.errcode);
2854 SSVAL(*rparam,4,succnt);
2855 SSVAL(*rparam,6,count);
2857 if (queue) free(queue);
2859 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2863 static int check_printdest_info(struct pack_desc* desc,
2864 int uLevel, char* id)
2866 desc->subformat = NULL;
2868 case 0: desc->format = "B9"; break;
2869 case 1: desc->format = "B9B21WWzW"; break;
2870 case 2: desc->format = "z"; break;
2871 case 3: desc->format = "zzzWWzzzWW"; break;
2872 default: return False;
2874 if (strcmp(desc->format,id) != 0) return False;
2878 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2879 struct pack_desc* desc)
2882 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2883 buf[sizeof(buf)-1] = 0;
2886 PACKS(desc,"B9",buf); /* szName */
2888 PACKS(desc,"B21",""); /* szUserName */
2889 PACKI(desc,"W",0); /* uJobId */
2890 PACKI(desc,"W",0); /* fsStatus */
2891 PACKS(desc,"z",""); /* pszStatus */
2892 PACKI(desc,"W",0); /* time */
2895 if (uLevel == 2 || uLevel == 3) {
2896 PACKS(desc,"z",buf); /* pszPrinterName */
2898 PACKS(desc,"z",""); /* pszUserName */
2899 PACKS(desc,"z",""); /* pszLogAddr */
2900 PACKI(desc,"W",0); /* uJobId */
2901 PACKI(desc,"W",0); /* fsStatus */
2902 PACKS(desc,"z",""); /* pszStatus */
2903 PACKS(desc,"z",""); /* pszComment */
2904 PACKS(desc,"z","NULL"); /* pszDrivers */
2905 PACKI(desc,"W",0); /* time */
2906 PACKI(desc,"W",0); /* pad1 */
2911 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2912 int mdrcnt,int mprcnt,
2913 char **rdata,char **rparam,
2914 int *rdata_len,int *rparam_len)
2916 char *str1 = param+2;
2917 char *str2 = skip_string(str1,1);
2918 char *p = skip_string(str2,1);
2919 char* PrinterName = p;
2921 struct pack_desc desc;
2924 memset((char *)&desc,'\0',sizeof(desc));
2926 p = skip_string(p,1);
2929 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2931 /* check it's a supported varient */
2932 if (strcmp(str1,"zWrLh") != 0) return False;
2933 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2935 snum = lp_servicenumber(PrinterName);
2936 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2937 int pnum = lp_servicenumber(PRINTERS_NAME);
2939 lp_add_printer(PrinterName,pnum);
2940 snum = lp_servicenumber(PrinterName);
2946 desc.errcode = NERR_DestNotFound;
2950 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2952 desc.buflen = mdrcnt;
2953 if (init_package(&desc,1,0)) {
2954 fill_printdest_info(conn,snum,uLevel,&desc);
2956 *rdata_len = desc.usedlen;
2960 *rparam = REALLOC(*rparam,*rparam_len);
2961 SSVALS(*rparam,0,desc.errcode);
2963 SSVAL(*rparam,4,desc.neededlen);
2965 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2969 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2970 int mdrcnt,int mprcnt,
2971 char **rdata,char **rparam,
2972 int *rdata_len,int *rparam_len)
2974 char *str1 = param+2;
2975 char *str2 = skip_string(str1,1);
2976 char *p = skip_string(str2,1);
2980 struct pack_desc desc;
2981 int services = lp_numservices();
2983 memset((char *)&desc,'\0',sizeof(desc));
2987 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2989 /* check it's a supported varient */
2990 if (strcmp(str1,"WrLeh") != 0) return False;
2991 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2994 for (i = 0; i < services; i++)
2995 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2998 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3000 desc.buflen = mdrcnt;
3001 if (init_package(&desc,queuecnt,0)) {
3004 for (i = 0; i < services; i++) {
3005 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3006 fill_printdest_info(conn,i,uLevel,&desc);
3008 if (desc.errcode == NERR_Success) succnt = n;
3013 *rdata_len = desc.usedlen;
3016 *rparam = REALLOC(*rparam,*rparam_len);
3017 SSVALS(*rparam,0,desc.errcode);
3019 SSVAL(*rparam,4,succnt);
3020 SSVAL(*rparam,6,queuecnt);
3022 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3026 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3027 int mdrcnt,int mprcnt,
3028 char **rdata,char **rparam,
3029 int *rdata_len,int *rparam_len)
3031 char *str1 = param+2;
3032 char *str2 = skip_string(str1,1);
3033 char *p = skip_string(str2,1);
3036 struct pack_desc desc;
3038 memset((char *)&desc,'\0',sizeof(desc));
3042 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3044 /* check it's a supported varient */
3045 if (strcmp(str1,"WrLeh") != 0) return False;
3046 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3048 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3050 desc.buflen = mdrcnt;
3051 if (init_package(&desc,1,0)) {
3052 PACKS(&desc,"B41","NULL");
3055 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3057 *rdata_len = desc.usedlen;
3060 *rparam = REALLOC(*rparam,*rparam_len);
3061 SSVALS(*rparam,0,desc.errcode);
3063 SSVAL(*rparam,4,succnt);
3066 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3070 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3071 int mdrcnt,int mprcnt,
3072 char **rdata,char **rparam,
3073 int *rdata_len,int *rparam_len)
3075 char *str1 = param+2;
3076 char *str2 = skip_string(str1,1);
3077 char *p = skip_string(str2,1);
3080 struct pack_desc desc;
3082 memset((char *)&desc,'\0',sizeof(desc));
3086 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3088 /* check it's a supported varient */
3089 if (strcmp(str1,"WrLeh") != 0) return False;
3090 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3092 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3094 desc.buflen = mdrcnt;
3096 if (init_package(&desc,1,0)) {
3097 PACKS(&desc,"B13","lpd");
3100 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3102 *rdata_len = desc.usedlen;
3105 *rparam = REALLOC(*rparam,*rparam_len);
3106 SSVALS(*rparam,0,desc.errcode);
3108 SSVAL(*rparam,4,succnt);
3111 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3115 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3116 int mdrcnt,int mprcnt,
3117 char **rdata,char **rparam,
3118 int *rdata_len,int *rparam_len)
3120 char *str1 = param+2;
3121 char *str2 = skip_string(str1,1);
3122 char *p = skip_string(str2,1);
3125 struct pack_desc desc;
3127 memset((char *)&desc,'\0',sizeof(desc));
3131 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3133 /* check it's a supported varient */
3134 if (strcmp(str1,"WrLeh") != 0) return False;
3135 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3137 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3138 memset((char *)&desc,'\0',sizeof(desc));
3140 desc.buflen = mdrcnt;
3142 if (init_package(&desc,1,0)) {
3143 PACKS(&desc,"B13","lp0");
3146 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3148 *rdata_len = desc.usedlen;
3151 *rparam = REALLOC(*rparam,*rparam_len);
3152 SSVALS(*rparam,0,desc.errcode);
3154 SSVAL(*rparam,4,succnt);
3157 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3161 /****************************************************************************
3162 The buffer was too small
3163 ****************************************************************************/
3165 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3166 int mdrcnt,int mprcnt,
3167 char **rdata,char **rparam,
3168 int *rdata_len,int *rparam_len)
3170 *rparam_len = MIN(*rparam_len,mprcnt);
3171 *rparam = REALLOC(*rparam,*rparam_len);
3175 SSVAL(*rparam,0,NERR_BufTooSmall);
3177 DEBUG(3,("Supplied buffer too small in API command\n"));
3183 /****************************************************************************
3184 The request is not supported
3185 ****************************************************************************/
3187 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3188 int mdrcnt,int mprcnt,
3189 char **rdata,char **rparam,
3190 int *rdata_len,int *rparam_len)
3193 *rparam = REALLOC(*rparam,*rparam_len);
3197 SSVAL(*rparam,0,NERR_notsupported);
3198 SSVAL(*rparam,2,0); /* converter word */
3200 DEBUG(3,("Unsupported API command\n"));
3212 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3213 int,int,char **,char **,int *,int *);
3215 } api_commands[] = {
3216 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3217 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3218 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3219 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3220 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3221 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3222 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3223 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3224 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3225 {"WPrintQueuePause", 74, api_WPrintQueueCtrl,0},
3226 {"WPrintQueueResume", 75, api_WPrintQueueCtrl,0},
3227 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3228 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3229 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3230 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3231 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3232 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3233 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3234 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3235 {"WPrintQueuePurge", 103, api_WPrintQueueCtrl,0},
3236 {"NetServerEnum", 104, api_RNetServerEnum,0},
3237 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3238 {"SetUserPassword", 115, api_SetUserPassword,0},
3239 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3240 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3241 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3242 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3243 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3244 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3245 {NULL, -1, api_Unsupported,0}};
3248 /****************************************************************************
3249 Handle remote api calls
3250 ****************************************************************************/
3252 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3253 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3257 char *rparam = NULL;
3264 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3268 api_command = SVAL(params,0);
3270 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3273 skip_string(params+2,1),
3274 tdscnt,tpscnt,mdrcnt,mprcnt));
3276 for (i=0;api_commands[i].name;i++) {
3277 if (api_commands[i].id == api_command && api_commands[i].fn) {
3278 DEBUG(3,("Doing %s\n",api_commands[i].name));
3283 rdata = (char *)malloc(1024);
3285 memset(rdata,'\0',1024);
3287 rparam = (char *)malloc(1024);
3289 memset(rparam,'\0',1024);
3291 if(!rdata || !rparam) {
3292 DEBUG(0,("api_reply: malloc fail !\n"));
3296 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3297 &rdata,&rparam,&rdata_len,&rparam_len);
3300 if (rdata_len > mdrcnt ||
3301 rparam_len > mprcnt) {
3302 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3303 &rdata,&rparam,&rdata_len,&rparam_len);
3306 /* if we get False back then it's actually unsupported */
3308 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3309 &rdata,&rparam,&rdata_len,&rparam_len);
3311 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);