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 fstring 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;
654 file_lines_free(lines);
660 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
661 desc->errcode=NERR_notsupported;
662 file_lines_free(lines);
666 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
667 struct pack_desc* desc,
668 int count, print_queue_struct* queue,
669 print_status_struct* status)
674 PACKS(desc,"B13",SERVICE(snum));
679 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
682 PACKI(desc,"K",printq_status(status->status));
686 if (uLevel == 1 || uLevel == 2) {
687 PACKS(desc,"B",""); /* alignment */
688 PACKI(desc,"W",5); /* priority */
689 PACKI(desc,"W",0); /* start time */
690 PACKI(desc,"W",0); /* until time */
691 PACKS(desc,"z",""); /* pSepFile */
692 PACKS(desc,"z","lpd"); /* pPrProc */
693 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
694 PACKS(desc,"z",""); /* pParms */
696 PACKS(desc,"z","UNKNOWN PRINTER");
697 PACKI(desc,"W",LPSTAT_ERROR);
699 else if (!status || !status->message[0]) {
700 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
701 PACKI(desc,"W",LPSTAT_OK); /* status */
703 PACKS(desc,"z",status->message);
704 PACKI(desc,"W",printq_status(status->status)); /* status */
706 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
709 if (uLevel == 3 || uLevel == 4) {
710 PACKI(desc,"W",5); /* uPriority */
711 PACKI(desc,"W",0); /* uStarttime */
712 PACKI(desc,"W",0); /* uUntiltime */
713 PACKI(desc,"W",5); /* pad1 */
714 PACKS(desc,"z",""); /* pszSepFile */
715 PACKS(desc,"z","WinPrint"); /* pszPrProc */
716 PACKS(desc,"z",""); /* pszParms */
717 if (!status || !status->message[0]) {
718 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
719 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
721 PACKS(desc,"z",status->message); /* pszComment */
722 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
724 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
725 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
726 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
727 PackDriverData(desc); /* pDriverData */
730 if (uLevel == 2 || uLevel == 4) {
732 for (i=0;i<count;i++)
733 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
737 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
741 /* This function returns the number of files for a given driver */
742 static int get_printerdrivernumber(int snum)
750 NT_PRINTER_INFO_LEVEL *info = NULL;
753 * Check in the tdb *first* before checking the legacy
754 * files. This allows an NT upload to take precedence over
755 * the existing fileset. JRA.
757 * we need to lookup the driver name prior to making the call
758 * to get_a_printer_driver_9x_compatible() and not rely on the
759 * 'print driver' parameter --jerry
762 get_a_printer (&info, 2, lp_servicename(snum));
763 if ((info != NULL) &&
764 (ok = get_a_printer_driver_9x_compatible(gen_line, info->info_2->drivername) == True))
767 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
771 /* didn't find driver in tdb */
773 DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
774 snum, lp_printerdriver(snum), lp_driverfile(snum)));
776 lines = file_lines_load(lp_driverfile(snum), NULL);
779 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
783 /* lookup the long printer driver name in the file description */
784 for (i=0;lines[i] && !ok;i++)
787 if (next_token(&p,tok,":",sizeof(tok)) &&
788 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
789 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
801 if (*p++ == ':') i--;
806 /* count the number of files */
807 while (next_token(&p,tok,",",sizeof(tok)))
810 file_lines_free(lines);
816 DEBUG(3,("Can't determine number of printer driver files\n"));
817 file_lines_free(lines);
821 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
822 uint16 vuid, char *param,char *data,
823 int mdrcnt,int mprcnt,
824 char **rdata,char **rparam,
825 int *rdata_len,int *rparam_len)
827 char *str1 = param+2;
828 char *str2 = skip_string(str1,1);
829 char *p = skip_string(str2,1);
835 struct pack_desc desc;
836 print_queue_struct *queue=NULL;
837 print_status_struct status;
839 memset((char *)&status,'\0',sizeof(status));
840 memset((char *)&desc,'\0',sizeof(desc));
842 p = skip_string(p,1);
846 /* remove any trailing username */
847 if ((p = strchr(QueueName,'%'))) *p = 0;
849 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
851 /* check it's a supported varient */
852 if (!prefix_ok(str1,"zWrLh")) return False;
853 if (!check_printq_info(&desc,uLevel,str2,str3)) {
855 * Patch from Scott Moomaw <scott@bridgewater.edu>
856 * to return the 'invalid info level' error if an
857 * unknown level was requested.
861 *rparam = REALLOC(*rparam,*rparam_len);
862 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
868 snum = lp_servicenumber(QueueName);
869 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
870 int pnum = lp_servicenumber(PRINTERS_NAME);
872 lp_add_printer(QueueName,pnum);
873 snum = lp_servicenumber(QueueName);
877 if (snum < 0 || !VALID_SNUM(snum)) return(False);
880 count = get_printerdrivernumber(snum);
881 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
883 count = print_queue_status(snum, &queue,&status);
886 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
888 desc.buflen = mdrcnt;
889 if (init_package(&desc,1,count)) {
890 desc.subcount = count;
891 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
892 } else if(uLevel == 0) {
895 * This is a *disgusting* hack.
896 * This is *so* bad that even I'm embarrassed (and I
897 * have no shame). Here's the deal :
898 * Until we get the correct SPOOLSS code into smbd
899 * then when we're running with NT SMB support then
900 * NT makes this call with a level of zero, and then
901 * immediately follows it with an open request to
902 * the \\SRVSVC pipe. If we allow that open to
903 * succeed then NT barfs when it cannot open the
904 * \\SPOOLSS pipe immediately after and continually
905 * whines saying "Printer name is invalid" forever
906 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
907 * to fail, then NT downgrades to using the downlevel code
908 * and everything works as well as before. I hate
909 * myself for adding this code.... JRA.
912 fail_next_srvsvc_open();
916 *rdata_len = desc.usedlen;
919 *rparam = REALLOC(*rparam,*rparam_len);
920 SSVALS(*rparam,0,desc.errcode);
922 SSVAL(*rparam,4,desc.neededlen);
924 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
926 if (queue) free(queue);
931 /****************************************************************************
932 View list of all print jobs on all queues.
933 ****************************************************************************/
935 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
936 int mdrcnt, int mprcnt,
937 char **rdata, char** rparam,
938 int *rdata_len, int *rparam_len)
940 char *param_format = param+2;
941 char *output_format1 = skip_string(param_format,1);
942 char *p = skip_string(output_format1,1);
943 int uLevel = SVAL(p,0);
944 char *output_format2 = p + 4;
945 int services = lp_numservices();
947 struct pack_desc desc;
948 print_queue_struct **queue = NULL;
949 print_status_struct *status = NULL;
950 int* subcntarr = NULL;
951 int queuecnt, subcnt=0, succnt=0;
953 memset((char *)&desc,'\0',sizeof(desc));
955 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
957 if (!prefix_ok(param_format,"WrLeh")) return False;
958 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
960 * Patch from Scott Moomaw <scott@bridgewater.edu>
961 * to return the 'invalid info level' error if an
962 * unknown level was requested.
966 *rparam = REALLOC(*rparam,*rparam_len);
967 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
974 for (i = 0; i < services; i++)
975 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
978 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
979 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
982 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
983 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
984 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
987 memset(status,0,queuecnt*sizeof(print_status_struct));
988 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
989 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
994 for (i = 0; i < services; i++)
995 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
996 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
997 subcnt += subcntarr[n];
1001 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1003 desc.buflen = mdrcnt;
1005 if (init_package(&desc,queuecnt,subcnt)) {
1008 for (i = 0; i < services; i++)
1009 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1010 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1012 if (desc.errcode == NERR_Success) succnt = n;
1016 if (subcntarr) free(subcntarr);
1018 *rdata_len = desc.usedlen;
1020 *rparam = REALLOC(*rparam,*rparam_len);
1021 SSVALS(*rparam,0,desc.errcode);
1023 SSVAL(*rparam,4,succnt);
1024 SSVAL(*rparam,6,queuecnt);
1026 for (i = 0; i < queuecnt; i++) {
1027 if (queue && queue[i]) free(queue[i]);
1030 if (queue) free(queue);
1031 if (status) free(status);
1036 /****************************************************************************
1037 get info level for a server list query
1038 ****************************************************************************/
1039 static BOOL check_server_info(int uLevel, char* id)
1043 if (strcmp(id,"B16") != 0) return False;
1046 if (strcmp(id,"B16BBDz") != 0) return False;
1054 struct srv_info_struct
1064 /*******************************************************************
1065 get server info lists from the files saved by nmbd. Return the
1067 ******************************************************************/
1068 static int get_server_info(uint32 servertype,
1069 struct srv_info_struct **servers,
1075 BOOL local_list_only;
1078 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1080 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1084 /* request for everything is code for request all servers */
1085 if (servertype == SV_TYPE_ALL)
1086 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1088 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1090 DEBUG(4,("Servertype search: %8x\n",servertype));
1092 for (i=0;lines[i];i++) {
1094 struct srv_info_struct *s;
1095 char *ptr = lines[i];
1098 if (!*ptr) continue;
1100 if (count == alloced) {
1102 (*servers) = (struct srv_info_struct *)
1103 Realloc(*servers,sizeof(**servers)*alloced);
1104 if (!(*servers)) return(0);
1105 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1107 s = &(*servers)[count];
1109 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1110 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1111 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1112 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1113 /* this allows us to cope with an old nmbd */
1114 pstrcpy(s->domain,global_myworkgroup);
1117 if (sscanf(stype,"%X",&s->type) != 1) {
1118 DEBUG(4,("r:host file "));
1122 /* Filter the servers/domains we return based on what was asked for. */
1124 /* Check to see if we are being asked for a local list only. */
1125 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1126 DEBUG(4,("r: local list only"));
1130 /* doesn't match up: don't want it */
1131 if (!(servertype & s->type)) {
1132 DEBUG(4,("r:serv type "));
1136 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1137 (s->type & SV_TYPE_DOMAIN_ENUM))
1139 DEBUG(4,("s: dom mismatch "));
1143 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1148 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1149 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1153 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1154 s->name, s->type, s->comment, s->domain));
1156 s->server_added = True;
1161 DEBUG(4,("%20s %8x %25s %15s\n",
1162 s->name, s->type, s->comment, s->domain));
1166 file_lines_free(lines);
1171 /*******************************************************************
1172 fill in a server info structure
1173 ******************************************************************/
1174 static int fill_srv_info(struct srv_info_struct *service,
1175 int uLevel, char **buf, int *buflen,
1176 char **stringbuf, int *stringspace, char *baseaddr)
1185 case 0: struct_len = 16; break;
1186 case 1: struct_len = 26; break;
1196 len = strlen(service->comment)+1;
1200 if (buflen) *buflen = struct_len;
1201 if (stringspace) *stringspace = len;
1202 return struct_len + len;
1207 if (*buflen < struct_len) return -1;
1215 p2 = p + struct_len;
1216 l2 = *buflen - struct_len;
1218 if (!baseaddr) baseaddr = p;
1223 StrnCpy(p,service->name,15);
1227 StrnCpy(p,service->name,15);
1228 SIVAL(p,18,service->type);
1229 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1230 len += CopyAndAdvance(&p2,service->comment,&l2);
1236 *buf = p + struct_len;
1237 *buflen -= struct_len;
1250 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1252 return(strcmp(s1->name,s2->name));
1255 /****************************************************************************
1256 view list of servers available (or possibly domains). The info is
1257 extracted from lists saved by nmbd on the local host
1258 ****************************************************************************/
1259 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1260 int mdrcnt, int mprcnt, char **rdata,
1261 char **rparam, int *rdata_len, int *rparam_len)
1263 char *str1 = param+2;
1264 char *str2 = skip_string(str1,1);
1265 char *p = skip_string(str2,1);
1266 int uLevel = SVAL(p,0);
1267 int buf_len = SVAL(p,2);
1268 uint32 servertype = IVAL(p,4);
1270 int data_len, fixed_len, string_len;
1271 int f_len = 0, s_len = 0;
1272 struct srv_info_struct *servers=NULL;
1273 int counted=0,total=0;
1276 BOOL domain_request;
1279 /* If someone sets all the bits they don't really mean to set
1280 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1283 if (servertype == SV_TYPE_ALL)
1284 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1286 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1287 any other bit (they may just set this bit on it's own) they
1288 want all the locally seen servers. However this bit can be
1289 set on its own so set the requested servers to be
1290 ALL - DOMAIN_ENUM. */
1292 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1293 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1295 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1296 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1300 if (!prefix_ok(str1,"WrLehD")) return False;
1301 if (!check_server_info(uLevel,str2)) return False;
1303 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1304 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1305 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1307 if (strcmp(str1, "WrLehDz") == 0) {
1308 StrnCpy(domain, p, sizeof(fstring)-1);
1310 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1313 if (lp_browse_list())
1314 total = get_server_info(servertype,&servers,domain);
1316 data_len = fixed_len = string_len = 0;
1319 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1322 char *lastname=NULL;
1324 for (i=0;i<total;i++)
1326 struct srv_info_struct *s = &servers[i];
1327 if (lastname && strequal(lastname,s->name)) continue;
1329 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1330 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1331 s->name, s->type, s->comment, s->domain));
1333 if (data_len <= buf_len) {
1336 string_len += s_len;
1343 *rdata_len = fixed_len + string_len;
1344 *rdata = REALLOC(*rdata,*rdata_len);
1345 memset(*rdata,'\0',*rdata_len);
1347 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1353 char *lastname=NULL;
1354 int count2 = counted;
1355 for (i = 0; i < total && count2;i++)
1357 struct srv_info_struct *s = &servers[i];
1358 if (lastname && strequal(lastname,s->name)) continue;
1360 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1361 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1362 s->name, s->type, s->comment, s->domain));
1368 *rparam = REALLOC(*rparam,*rparam_len);
1369 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1371 SSVAL(*rparam,4,counted);
1372 SSVAL(*rparam,6,counted+missed);
1374 if (servers) free(servers);
1376 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1377 domain,uLevel,counted,counted+missed));
1382 /****************************************************************************
1383 command 0x34 - suspected of being a "Lookup Names" stub api
1384 ****************************************************************************/
1385 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1386 int mdrcnt, int mprcnt, char **rdata,
1387 char **rparam, int *rdata_len, int *rparam_len)
1389 char *str1 = param+2;
1390 char *str2 = skip_string(str1,1);
1391 char *p = skip_string(str2,1);
1392 int uLevel = SVAL(p,0);
1393 int buf_len = SVAL(p,2);
1397 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1398 str1, str2, p, uLevel, buf_len));
1400 if (!prefix_ok(str1,"zWrLeh")) return False;
1405 *rparam = REALLOC(*rparam,*rparam_len);
1407 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1409 SSVAL(*rparam,4,counted);
1410 SSVAL(*rparam,6,counted+missed);
1415 /****************************************************************************
1416 get info about a share
1417 ****************************************************************************/
1418 static BOOL check_share_info(int uLevel, char* id)
1422 if (strcmp(id,"B13") != 0) return False;
1425 if (strcmp(id,"B13BWz") != 0) return False;
1428 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1431 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1433 default: return False;
1438 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1439 char** buf, int* buflen,
1440 char** stringbuf, int* stringspace, char* baseaddr)
1449 case 0: struct_len = 13; break;
1450 case 1: struct_len = 20; break;
1451 case 2: struct_len = 40; break;
1452 case 91: struct_len = 68; break;
1460 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1461 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1462 if (buflen) *buflen = struct_len;
1463 if (stringspace) *stringspace = len;
1464 return struct_len + len;
1469 if ((*buflen) < struct_len) return -1;
1477 p2 = p + struct_len;
1478 l2 = (*buflen) - struct_len;
1480 if (!baseaddr) baseaddr = p;
1482 StrnCpy(p,lp_servicename(snum),13);
1488 type = STYPE_DISKTREE;
1489 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1490 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1491 SSVAL(p,14,type); /* device type */
1492 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1493 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1498 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1499 SSVALS(p,22,-1); /* max uses */
1500 SSVAL(p,24,1); /* current uses */
1501 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1502 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1503 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1508 memset(p+40,0,SHPWLEN+2);
1520 (*buf) = p + struct_len;
1521 (*buflen) -= struct_len;
1523 (*stringspace) = l2;
1533 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1534 int mdrcnt,int mprcnt,
1535 char **rdata,char **rparam,
1536 int *rdata_len,int *rparam_len)
1538 char *str1 = param+2;
1539 char *str2 = skip_string(str1,1);
1540 char *netname = skip_string(str2,1);
1541 char *p = skip_string(netname,1);
1542 int uLevel = SVAL(p,0);
1543 int snum = find_service(netname);
1545 if (snum < 0) return False;
1547 /* check it's a supported varient */
1548 if (!prefix_ok(str1,"zWrLh")) return False;
1549 if (!check_share_info(uLevel,str2)) return False;
1551 *rdata = REALLOC(*rdata,mdrcnt);
1553 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1554 if (*rdata_len < 0) return False;
1557 *rparam = REALLOC(*rparam,*rparam_len);
1558 SSVAL(*rparam,0,NERR_Success);
1559 SSVAL(*rparam,2,0); /* converter word */
1560 SSVAL(*rparam,4,*rdata_len);
1565 /****************************************************************************
1566 view list of shares available
1567 ****************************************************************************/
1568 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1569 int mdrcnt,int mprcnt,
1570 char **rdata,char **rparam,
1571 int *rdata_len,int *rparam_len)
1573 char *str1 = param+2;
1574 char *str2 = skip_string(str1,1);
1575 char *p = skip_string(str2,1);
1576 int uLevel = SVAL(p,0);
1577 int buf_len = SVAL(p,2);
1579 int count=lp_numservices();
1580 int total=0,counted=0;
1581 BOOL missed = False;
1583 int data_len, fixed_len, string_len;
1584 int f_len = 0, s_len = 0;
1586 if (!prefix_ok(str1,"WrLeh")) return False;
1587 if (!check_share_info(uLevel,str2)) return False;
1589 data_len = fixed_len = string_len = 0;
1590 for (i=0;i<count;i++)
1591 if (lp_browseable(i) && lp_snum_ok(i))
1594 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1595 if (data_len <= buf_len)
1599 string_len += s_len;
1604 *rdata_len = fixed_len + string_len;
1605 *rdata = REALLOC(*rdata,*rdata_len);
1606 memset(*rdata,0,*rdata_len);
1608 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1612 for (i = 0; i < count;i++)
1613 if (lp_browseable(i) && lp_snum_ok(i))
1614 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1618 *rparam = REALLOC(*rparam,*rparam_len);
1619 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1621 SSVAL(*rparam,4,counted);
1622 SSVAL(*rparam,6,total);
1624 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1625 counted,total,uLevel,
1626 buf_len,*rdata_len,mdrcnt));
1632 /****************************************************************************
1633 get the time of day info
1634 ****************************************************************************/
1635 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1636 int mdrcnt,int mprcnt,
1637 char **rdata,char **rparam,
1638 int *rdata_len,int *rparam_len)
1642 *rparam = REALLOC(*rparam,*rparam_len);
1645 *rdata = REALLOC(*rdata,*rdata_len);
1647 SSVAL(*rparam,0,NERR_Success);
1648 SSVAL(*rparam,2,0); /* converter word */
1654 time_t unixdate = time(NULL);
1656 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1657 by NT in a "net time" operation,
1658 it seems to ignore the one below */
1660 /* the client expects to get localtime, not GMT, in this bit
1661 (I think, this needs testing) */
1662 t = LocalTime(&unixdate);
1664 SIVAL(p,4,0); /* msecs ? */
1665 CVAL(p,8) = t->tm_hour;
1666 CVAL(p,9) = t->tm_min;
1667 CVAL(p,10) = t->tm_sec;
1668 CVAL(p,11) = 0; /* hundredths of seconds */
1669 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1670 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1671 CVAL(p,16) = t->tm_mday;
1672 CVAL(p,17) = t->tm_mon + 1;
1673 SSVAL(p,18,1900+t->tm_year);
1674 CVAL(p,20) = t->tm_wday;
1681 /****************************************************************************
1682 Set the user password.
1683 *****************************************************************************/
1685 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1686 int mdrcnt,int mprcnt,
1687 char **rdata,char **rparam,
1688 int *rdata_len,int *rparam_len)
1690 char *p = skip_string(param+2,2);
1692 fstring pass1,pass2;
1696 p = skip_string(p,1);
1698 memset(pass1,'\0',sizeof(pass1));
1699 memset(pass2,'\0',sizeof(pass2));
1701 memcpy(pass2,p+16,16);
1704 *rparam = REALLOC(*rparam,*rparam_len);
1708 SSVAL(*rparam,0,NERR_badpass);
1709 SSVAL(*rparam,2,0); /* converter word */
1711 DEBUG(3,("Set password for <%s>\n",user));
1714 * Pass the user through the NT -> unix user mapping
1718 (void)map_username(user);
1721 * Do any UNIX username case mangling.
1723 (void)Get_Pwnam( user, True);
1726 * Attempt to verify the old password against smbpasswd entries
1727 * Win98 clients send old and new password in plaintext for this call.
1731 fstring saved_pass2;
1732 struct smb_passwd *smbpw = NULL;
1735 * Save the new password as change_oem_password overwrites it
1739 fstrcpy(saved_pass2, pass2);
1741 if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
1742 change_oem_password(smbpw,pass2,False))
1744 SSVAL(*rparam,0,NERR_Success);
1747 * If unix password sync was requested, attempt to change
1748 * the /etc/passwd database also. Return failure if this cannot
1752 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1753 SSVAL(*rparam,0,NERR_badpass);
1758 * If the above failed, attempt the plaintext password change.
1759 * This tests against the /etc/passwd database only.
1762 if(SVAL(*rparam,0) != NERR_Success)
1764 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1765 chgpasswd(user,pass1,pass2,False))
1767 SSVAL(*rparam,0,NERR_Success);
1772 * If the plaintext change failed, attempt
1773 * the old encrypted method. NT will generate this
1774 * after trying the samr method. Note that this
1775 * method is done as a last resort as this
1776 * password change method loses the NT password hash
1777 * and cannot change the UNIX password as no plaintext
1781 if(SVAL(*rparam,0) != NERR_Success)
1783 struct smb_passwd *sampw = NULL;
1785 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1786 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1788 SSVAL(*rparam,0,NERR_Success);
1792 memset((char *)pass1,'\0',sizeof(fstring));
1793 memset((char *)pass2,'\0',sizeof(fstring));
1798 /****************************************************************************
1799 Set the user password (SamOEM version - gets plaintext).
1800 ****************************************************************************/
1802 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1803 int mdrcnt,int mprcnt,
1804 char **rdata,char **rparam,
1805 int *rdata_len,int *rparam_len)
1808 char *p = param + 2;
1810 *rparam = REALLOC(*rparam,*rparam_len);
1814 SSVAL(*rparam,0,NERR_badpass);
1817 * Check the parameter definition is correct.
1819 if(!strequal(param + 2, "zsT")) {
1820 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1823 p = skip_string(p, 1);
1825 if(!strequal(p, "B516B16")) {
1826 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1829 p = skip_string(p,1);
1832 p = skip_string(p,1);
1834 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1837 * Pass the user through the NT -> unix user mapping
1841 (void)map_username(user);
1844 * Do any UNIX username case mangling.
1846 (void)Get_Pwnam( user, True);
1848 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1850 SSVAL(*rparam,0,NERR_Success);
1856 /****************************************************************************
1859 ****************************************************************************/
1860 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1861 int mdrcnt,int mprcnt,
1862 char **rdata,char **rparam,
1863 int *rdata_len,int *rparam_len)
1865 int function = SVAL(param,0);
1866 char *str1 = param+2;
1867 char *str2 = skip_string(str1,1);
1868 char *p = skip_string(str2,1);
1870 extern struct current_user current_user;
1874 /* check it's a supported varient */
1875 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1879 *rparam = REALLOC(*rparam,*rparam_len);
1882 if (!print_job_exists(jobid)) {
1883 errcode = NERR_JobNotFound;
1887 errcode = NERR_notsupported;
1890 case 81: /* delete */
1891 if (print_job_delete(¤t_user, jobid))
1892 errcode = NERR_Success;
1894 case 82: /* pause */
1895 if (print_job_pause(¤t_user, jobid))
1896 errcode = NERR_Success;
1898 case 83: /* resume */
1899 if (print_job_resume(¤t_user, jobid))
1900 errcode = NERR_Success;
1905 SSVAL(*rparam,0,errcode);
1906 SSVAL(*rparam,2,0); /* converter word */
1911 /****************************************************************************
1912 Purge a print queue - or pause or resume it.
1913 ****************************************************************************/
1914 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1915 int mdrcnt,int mprcnt,
1916 char **rdata,char **rparam,
1917 int *rdata_len,int *rparam_len)
1919 int function = SVAL(param,0);
1920 char *str1 = param+2;
1921 char *str2 = skip_string(str1,1);
1922 char *QueueName = skip_string(str2,1);
1923 int errcode = NERR_notsupported;
1926 /* check it's a supported varient */
1927 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1931 *rparam = REALLOC(*rparam,*rparam_len);
1934 snum = print_queue_snum(QueueName);
1937 errcode = NERR_JobNotFound;
1942 case 74: /* Pause queue */
1943 if (print_queue_pause(NULL, snum, &errcode)) errcode = NERR_Success;
1945 case 75: /* Resume queue */
1946 if (print_queue_resume(NULL, snum, &errcode)) errcode = NERR_Success;
1948 case 103: /* Purge */
1949 if (print_queue_purge(NULL, snum, &errcode)) errcode = NERR_Success;
1954 SSVAL(*rparam,0,errcode);
1955 SSVAL(*rparam,2,0); /* converter word */
1961 /****************************************************************************
1962 set the property of a print job (undocumented?)
1963 ? function = 0xb -> set name of print job
1964 ? function = 0x6 -> move print job up/down
1965 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1966 or <WWsTP> <WB21BB16B10zWWzDDz>
1967 ****************************************************************************/
1968 static int check_printjob_info(struct pack_desc* desc,
1969 int uLevel, char* id)
1971 desc->subformat = NULL;
1973 case 0: desc->format = "W"; break;
1974 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1975 case 2: desc->format = "WWzWWDDzz"; break;
1976 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1977 default: return False;
1979 if (strcmp(desc->format,id) != 0) return False;
1983 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1984 int mdrcnt,int mprcnt,
1985 char **rdata,char **rparam,
1986 int *rdata_len,int *rparam_len)
1988 struct pack_desc desc;
1989 char *str1 = param+2;
1990 char *str2 = skip_string(str1,1);
1991 char *p = skip_string(str2,1);
1993 int uLevel = SVAL(p,2);
1994 int function = SVAL(p,4);
1999 *rparam = REALLOC(*rparam,*rparam_len);
2003 /* check it's a supported varient */
2004 if ((strcmp(str1,"WWsTP")) ||
2005 (!check_printjob_info(&desc,uLevel,str2)))
2008 if (!print_job_exists(jobid)) {
2009 errcode=NERR_JobNotFound;
2013 errcode = NERR_notsupported;
2017 /* change job place in the queue,
2018 data gives the new place */
2019 place = SVAL(data,0);
2020 if (print_job_set_place(jobid, place)) {
2021 errcode=NERR_Success;
2026 /* change print job name, data gives the name */
2027 if (print_job_set_name(jobid, data)) {
2028 errcode=NERR_Success;
2037 SSVALS(*rparam,0,errcode);
2038 SSVAL(*rparam,2,0); /* converter word */
2044 /****************************************************************************
2045 get info about the server
2046 ****************************************************************************/
2047 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2048 int mdrcnt,int mprcnt,
2049 char **rdata,char **rparam,
2050 int *rdata_len,int *rparam_len)
2052 char *str1 = param+2;
2053 char *str2 = skip_string(str1,1);
2054 char *p = skip_string(str2,1);
2055 int uLevel = SVAL(p,0);
2059 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2061 /* check it's a supported varient */
2062 if (!prefix_ok(str1,"WrLh")) return False;
2065 if (strcmp(str2,"B16") != 0) return False;
2069 if (strcmp(str2,"B16BBDz") != 0) return False;
2073 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2078 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2083 if (strcmp(str2,"DN") != 0) return False;
2087 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2090 default: return False;
2093 *rdata_len = mdrcnt;
2094 *rdata = REALLOC(*rdata,*rdata_len);
2097 p2 = p + struct_len;
2099 StrnCpy(p,local_machine,16);
2105 struct srv_info_struct *servers=NULL;
2108 uint32 servertype= lp_default_server_announce();
2110 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2112 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2113 for (i=0;i<count;i++)
2114 if (strequal(servers[i].name,local_machine))
2116 servertype = servers[i].type;
2117 pstrcpy(comment,servers[i].comment);
2120 if (servers) free(servers);
2122 SCVAL(p,0,lp_major_announce_version());
2123 SCVAL(p,1,lp_minor_announce_version());
2124 SIVAL(p,2,servertype);
2126 if (mdrcnt == struct_len) {
2129 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2130 standard_sub_conn(conn,comment);
2131 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2132 p2 = skip_string(p2,1);
2137 return False; /* not yet implemented */
2140 *rdata_len = PTR_DIFF(p2,*rdata);
2143 *rparam = REALLOC(*rparam,*rparam_len);
2144 SSVAL(*rparam,0,NERR_Success);
2145 SSVAL(*rparam,2,0); /* converter word */
2146 SSVAL(*rparam,4,*rdata_len);
2152 /****************************************************************************
2153 get info about the server
2154 ****************************************************************************/
2155 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2156 int mdrcnt,int mprcnt,
2157 char **rdata,char **rparam,
2158 int *rdata_len,int *rparam_len)
2160 char *str1 = param+2;
2161 char *str2 = skip_string(str1,1);
2162 char *p = skip_string(str2,1);
2164 extern pstring sesssetup_user;
2165 int level = SVAL(p,0);
2167 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2170 *rparam = REALLOC(*rparam,*rparam_len);
2172 /* check it's a supported varient */
2173 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2176 *rdata_len = mdrcnt + 1024;
2177 *rdata = REALLOC(*rdata,*rdata_len);
2179 SSVAL(*rparam,0,NERR_Success);
2180 SSVAL(*rparam,2,0); /* converter word */
2186 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2187 pstrcpy(p2,local_machine);
2189 p2 = skip_string(p2,1);
2192 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2193 pstrcpy(p2,sesssetup_user);
2194 p2 = skip_string(p2,1);
2197 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2198 pstrcpy(p2,global_myworkgroup);
2200 p2 = skip_string(p2,1);
2203 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2204 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2207 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2208 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2209 p2 = skip_string(p2,1);
2212 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2214 p2 = skip_string(p2,1);
2217 *rdata_len = PTR_DIFF(p2,*rdata);
2219 SSVAL(*rparam,4,*rdata_len);
2224 /****************************************************************************
2225 get info about a user
2227 struct user_info_11 {
2228 char usri11_name[21]; 0-20
2230 char *usri11_comment; 22-25
2231 char *usri11_usr_comment; 26-29
2232 unsigned short usri11_priv; 30-31
2233 unsigned long usri11_auth_flags; 32-35
2234 long usri11_password_age; 36-39
2235 char *usri11_homedir; 40-43
2236 char *usri11_parms; 44-47
2237 long usri11_last_logon; 48-51
2238 long usri11_last_logoff; 52-55
2239 unsigned short usri11_bad_pw_count; 56-57
2240 unsigned short usri11_num_logons; 58-59
2241 char *usri11_logon_server; 60-63
2242 unsigned short usri11_country_code; 64-65
2243 char *usri11_workstations; 66-69
2244 unsigned long usri11_max_storage; 70-73
2245 unsigned short usri11_units_per_week; 74-75
2246 unsigned char *usri11_logon_hours; 76-79
2247 unsigned short usri11_code_page; 80-81
2252 usri11_name specifies the user name for which information is retireved
2254 usri11_pad aligns the next data structure element to a word boundary
2256 usri11_comment is a null terminated ASCII comment
2258 usri11_user_comment is a null terminated ASCII comment about the user
2260 usri11_priv specifies the level of the privilege assigned to the user.
2261 The possible values are:
2263 Name Value Description
2264 USER_PRIV_GUEST 0 Guest privilege
2265 USER_PRIV_USER 1 User privilege
2266 USER_PRV_ADMIN 2 Administrator privilege
2268 usri11_auth_flags specifies the account operator privileges. The
2269 possible values are:
2271 Name Value Description
2272 AF_OP_PRINT 0 Print operator
2275 Leach, Naik [Page 28]
2279 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2282 AF_OP_COMM 1 Communications operator
2283 AF_OP_SERVER 2 Server operator
2284 AF_OP_ACCOUNTS 3 Accounts operator
2287 usri11_password_age specifies how many seconds have elapsed since the
2288 password was last changed.
2290 usri11_home_dir points to a null terminated ASCII string that contains
2291 the path name of the user's home directory.
2293 usri11_parms points to a null terminated ASCII string that is set
2294 aside for use by applications.
2296 usri11_last_logon specifies the time when the user last logged on.
2297 This value is stored as the number of seconds elapsed since
2298 00:00:00, January 1, 1970.
2300 usri11_last_logoff specifies the time when the user last logged off.
2301 This value is stored as the number of seconds elapsed since
2302 00:00:00, January 1, 1970. A value of 0 means the last logoff
2305 usri11_bad_pw_count specifies the number of incorrect passwords
2306 entered since the last successful logon.
2308 usri11_log1_num_logons specifies the number of times this user has
2309 logged on. A value of -1 means the number of logons is unknown.
2311 usri11_logon_server points to a null terminated ASCII string that
2312 contains the name of the server to which logon requests are sent.
2313 A null string indicates logon requests should be sent to the
2316 usri11_country_code specifies the country code for the user's language
2319 usri11_workstations points to a null terminated ASCII string that
2320 contains the names of workstations the user may log on from.
2321 There may be up to 8 workstations, with the names separated by
2322 commas. A null strings indicates there are no restrictions.
2324 usri11_max_storage specifies the maximum amount of disk space the user
2325 can occupy. A value of 0xffffffff indicates there are no
2328 usri11_units_per_week specifies the equal number of time units into
2329 which a week is divided. This value must be equal to 168.
2331 usri11_logon_hours points to a 21 byte (168 bits) string that
2332 specifies the time during which the user can log on. Each bit
2333 represents one unique hour in a week. The first bit (bit 0, word
2334 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2338 Leach, Naik [Page 29]
2342 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2345 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2346 are no restrictions.
2348 usri11_code_page specifies the code page for the user's language of
2351 All of the pointers in this data structure need to be treated
2352 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2353 to be ignored. The converter word returned in the parameters section
2354 needs to be subtracted from the lower 16 bits to calculate an offset
2355 into the return buffer where this ASCII string resides.
2357 There is no auxiliary data in the response.
2359 ****************************************************************************/
2361 #define usri11_name 0
2362 #define usri11_pad 21
2363 #define usri11_comment 22
2364 #define usri11_usr_comment 26
2365 #define usri11_full_name 30
2366 #define usri11_priv 34
2367 #define usri11_auth_flags 36
2368 #define usri11_password_age 40
2369 #define usri11_homedir 44
2370 #define usri11_parms 48
2371 #define usri11_last_logon 52
2372 #define usri11_last_logoff 56
2373 #define usri11_bad_pw_count 60
2374 #define usri11_num_logons 62
2375 #define usri11_logon_server 64
2376 #define usri11_country_code 68
2377 #define usri11_workstations 70
2378 #define usri11_max_storage 74
2379 #define usri11_units_per_week 78
2380 #define usri11_logon_hours 80
2381 #define usri11_code_page 84
2382 #define usri11_end 86
2384 #define USER_PRIV_GUEST 0
2385 #define USER_PRIV_USER 1
2386 #define USER_PRIV_ADMIN 2
2388 #define AF_OP_PRINT 0
2389 #define AF_OP_COMM 1
2390 #define AF_OP_SERVER 2
2391 #define AF_OP_ACCOUNTS 3
2394 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2395 int mdrcnt,int mprcnt,
2396 char **rdata,char **rparam,
2397 int *rdata_len,int *rparam_len)
2399 char *str1 = param+2;
2400 char *str2 = skip_string(str1,1);
2401 char *UserName = skip_string(str2,1);
2402 char *p = skip_string(UserName,1);
2403 int uLevel = SVAL(p,0);
2406 /* get NIS home of a previously validated user - simeon */
2407 /* With share level security vuid will always be zero.
2408 Don't depend on vuser being non-null !!. JRA */
2409 user_struct *vuser = get_valid_user_struct(vuid);
2411 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2412 vuser->user.unix_name));
2415 *rparam = REALLOC(*rparam,*rparam_len);
2417 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2419 /* check it's a supported variant */
2420 if (strcmp(str1,"zWrLh") != 0) return False;
2423 case 0: p2 = "B21"; break;
2424 case 1: p2 = "B21BB16DWzzWz"; break;
2425 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2426 case 10: p2 = "B21Bzzz"; break;
2427 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2428 default: return False;
2431 if (strcmp(p2,str2) != 0) return False;
2433 *rdata_len = mdrcnt + 1024;
2434 *rdata = REALLOC(*rdata,*rdata_len);
2436 SSVAL(*rparam,0,NERR_Success);
2437 SSVAL(*rparam,2,0); /* converter word */
2440 p2 = p + usri11_end;
2443 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2447 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2452 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2453 pstrcpy(p2,"Comment");
2454 p2 = skip_string(p2,1);
2456 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2457 pstrcpy(p2,"UserComment");
2458 p2 = skip_string(p2,1);
2460 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2461 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2462 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2463 p2 = skip_string(p2,1);
2466 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2468 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2469 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2470 SIVALS(p,usri11_password_age,-1); /* password age */
2471 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2472 pstrcpy(p2, lp_logon_home());
2473 p2 = skip_string(p2,1);
2474 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2476 p2 = skip_string(p2,1);
2477 SIVAL(p,usri11_last_logon,0); /* last logon */
2478 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2479 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2480 SSVALS(p,usri11_num_logons,-1); /* num logons */
2481 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2482 pstrcpy(p2,"\\\\*");
2483 p2 = skip_string(p2,1);
2484 SSVAL(p,usri11_country_code,0); /* country code */
2486 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2488 p2 = skip_string(p2,1);
2490 SIVALS(p,usri11_max_storage,-1); /* max storage */
2491 SSVAL(p,usri11_units_per_week,168); /* units per week */
2492 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2494 /* a simple way to get logon hours at all times. */
2496 SCVAL(p2,21,0); /* fix zero termination */
2497 p2 = skip_string(p2,1);
2499 SSVAL(p,usri11_code_page,0); /* code page */
2501 if (uLevel == 1 || uLevel == 2)
2503 memset(p+22,' ',16); /* password */
2504 SIVALS(p,38,-1); /* password age */
2506 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2507 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2508 pstrcpy(p2,lp_logon_home());
2509 p2 = skip_string(p2,1);
2510 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2512 SSVAL(p,52,0); /* flags */
2513 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2514 pstrcpy(p2,lp_logon_script());
2515 standard_sub_conn( conn, p2 );
2516 p2 = skip_string(p2,1);
2519 SIVAL(p,60,0); /* auth_flags */
2520 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2521 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2522 p2 = skip_string(p2,1);
2523 SIVAL(p,68,0); /* urs_comment */
2524 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2526 p2 = skip_string(p2,1);
2527 SIVAL(p,76,0); /* workstations */
2528 SIVAL(p,80,0); /* last_logon */
2529 SIVAL(p,84,0); /* last_logoff */
2530 SIVALS(p,88,-1); /* acct_expires */
2531 SIVALS(p,92,-1); /* max_storage */
2532 SSVAL(p,96,168); /* units_per_week */
2533 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2536 SSVALS(p,102,-1); /* bad_pw_count */
2537 SSVALS(p,104,-1); /* num_logons */
2538 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2539 pstrcpy(p2,"\\\\%L");
2540 standard_sub_conn(conn, p2);
2541 p2 = skip_string(p2,1);
2542 SSVAL(p,110,49); /* country_code */
2543 SSVAL(p,112,860); /* code page */
2547 *rdata_len = PTR_DIFF(p2,*rdata);
2549 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2554 /*******************************************************************
2555 get groups that a user is a member of
2556 ******************************************************************/
2557 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2558 int mdrcnt,int mprcnt,
2559 char **rdata,char **rparam,
2560 int *rdata_len,int *rparam_len)
2562 char *str1 = param+2;
2563 char *str2 = skip_string(str1,1);
2564 char *UserName = skip_string(str2,1);
2565 char *p = skip_string(UserName,1);
2566 int uLevel = SVAL(p,0);
2571 *rparam = REALLOC(*rparam,*rparam_len);
2573 /* check it's a supported varient */
2574 if (strcmp(str1,"zWrLeh") != 0) return False;
2576 case 0: p2 = "B21"; break;
2577 default: return False;
2579 if (strcmp(p2,str2) != 0) return False;
2581 *rdata_len = mdrcnt + 1024;
2582 *rdata = REALLOC(*rdata,*rdata_len);
2584 SSVAL(*rparam,0,NERR_Success);
2585 SSVAL(*rparam,2,0); /* converter word */
2589 /* XXXX we need a real SAM database some day */
2590 pstrcpy(p,"Users"); p += 21; count++;
2591 pstrcpy(p,"Domain Users"); p += 21; count++;
2592 pstrcpy(p,"Guests"); p += 21; count++;
2593 pstrcpy(p,"Domain Guests"); p += 21; count++;
2595 *rdata_len = PTR_DIFF(p,*rdata);
2597 SSVAL(*rparam,4,count); /* is this right?? */
2598 SSVAL(*rparam,6,count); /* is this right?? */
2604 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2605 int mdrcnt,int mprcnt,
2606 char **rdata,char **rparam,
2607 int *rdata_len,int *rparam_len)
2609 char *str1 = param+2;
2610 char *str2 = skip_string(str1,1);
2611 char *p = skip_string(str2,1);
2613 struct pack_desc desc;
2619 memset((char *)&desc,'\0',sizeof(desc));
2621 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2623 /* check it's a supported varient */
2624 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2625 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2626 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2628 desc.buflen = mdrcnt;
2629 desc.subformat = NULL;
2632 if (init_package(&desc,1,0))
2634 PACKI(&desc,"W",0); /* code */
2635 PACKS(&desc,"B21",name); /* eff. name */
2636 PACKS(&desc,"B",""); /* pad */
2638 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2639 PACKI(&desc,"D",0); /* auth flags XXX */
2640 PACKI(&desc,"W",0); /* num logons */
2641 PACKI(&desc,"W",0); /* bad pw count */
2642 PACKI(&desc,"D",0); /* last logon */
2643 PACKI(&desc,"D",-1); /* last logoff */
2644 PACKI(&desc,"D",-1); /* logoff time */
2645 PACKI(&desc,"D",-1); /* kickoff time */
2646 PACKI(&desc,"D",0); /* password age */
2647 PACKI(&desc,"D",0); /* password can change */
2648 PACKI(&desc,"D",-1); /* password must change */
2651 fstrcpy(mypath,"\\\\");
2652 fstrcat(mypath,local_machine);
2654 PACKS(&desc,"z",mypath); /* computer */
2656 PACKS(&desc,"z",global_myworkgroup);/* domain */
2658 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2659 /* made sure all macros are fully substituted and available */
2661 pstring logon_script;
2662 pstrcpy(logon_script,lp_logon_script());
2663 standard_sub_conn( conn, logon_script );
2664 PACKS(&desc,"z", logon_script); /* script path */
2666 /* End of JHT mods */
2668 PACKI(&desc,"D",0x00000000); /* reserved */
2671 *rdata_len = desc.usedlen;
2673 *rparam = REALLOC(*rparam,*rparam_len);
2674 SSVALS(*rparam,0,desc.errcode);
2676 SSVAL(*rparam,4,desc.neededlen);
2678 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2683 /****************************************************************************
2684 api_WAccessGetUserPerms
2685 ****************************************************************************/
2686 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2687 int mdrcnt,int mprcnt,
2688 char **rdata,char **rparam,
2689 int *rdata_len,int *rparam_len)
2691 char *str1 = param+2;
2692 char *str2 = skip_string(str1,1);
2693 char *user = skip_string(str2,1);
2694 char *resource = skip_string(user,1);
2696 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2698 /* check it's a supported varient */
2699 if (strcmp(str1,"zzh") != 0) return False;
2700 if (strcmp(str2,"") != 0) return False;
2703 *rparam = REALLOC(*rparam,*rparam_len);
2704 SSVALS(*rparam,0,0); /* errorcode */
2705 SSVAL(*rparam,2,0); /* converter word */
2706 SSVAL(*rparam,4,0x7f); /* permission flags */
2711 /****************************************************************************
2712 api_WPrintJobEnumerate
2713 ****************************************************************************/
2714 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2715 int mdrcnt,int mprcnt,
2716 char **rdata,char **rparam,
2717 int *rdata_len,int *rparam_len)
2719 char *str1 = param+2;
2720 char *str2 = skip_string(str1,1);
2721 char *p = skip_string(str2,1);
2727 struct pack_desc desc;
2728 print_queue_struct *queue=NULL;
2729 print_status_struct status;
2733 memset((char *)&desc,'\0',sizeof(desc));
2734 memset((char *)&status,'\0',sizeof(status));
2736 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2738 /* check it's a supported varient */
2739 if (strcmp(str1,"WWrLh") != 0) return False;
2740 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2743 snum = print_job_snum(job);
2745 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2747 count = print_queue_status(snum,&queue,&status);
2748 for (i = 0; i < count; i++) {
2749 if (queue[i].job == job) break;
2751 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2753 desc.buflen = mdrcnt;
2755 if (init_package(&desc,1,0)) {
2757 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2758 *rdata_len = desc.usedlen;
2761 desc.errcode = NERR_JobNotFound;
2767 *rparam = REALLOC(*rparam,*rparam_len);
2768 SSVALS(*rparam,0,desc.errcode);
2770 SSVAL(*rparam,4,desc.neededlen);
2772 if (queue) free(queue);
2774 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2778 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2779 int mdrcnt,int mprcnt,
2780 char **rdata,char **rparam,
2781 int *rdata_len,int *rparam_len)
2783 char *str1 = param+2;
2784 char *str2 = skip_string(str1,1);
2785 char *p = skip_string(str2,1);
2791 struct pack_desc desc;
2792 print_queue_struct *queue=NULL;
2793 print_status_struct status;
2795 memset((char *)&desc,'\0',sizeof(desc));
2796 memset((char *)&status,'\0',sizeof(status));
2798 p = skip_string(p,1);
2801 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2803 /* check it's a supported varient */
2804 if (strcmp(str1,"zWrLeh") != 0) return False;
2805 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2806 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2808 snum = lp_servicenumber(name);
2809 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2810 int pnum = lp_servicenumber(PRINTERS_NAME);
2812 lp_add_printer(name,pnum);
2813 snum = lp_servicenumber(name);
2817 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2819 count = print_queue_status(snum,&queue,&status);
2820 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2822 desc.buflen = mdrcnt;
2824 if (init_package(&desc,count,0)) {
2826 for (i = 0; i < count; i++) {
2827 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2828 if (desc.errcode == NERR_Success) succnt = i+1;
2832 *rdata_len = desc.usedlen;
2835 *rparam = REALLOC(*rparam,*rparam_len);
2836 SSVALS(*rparam,0,desc.errcode);
2838 SSVAL(*rparam,4,succnt);
2839 SSVAL(*rparam,6,count);
2841 if (queue) free(queue);
2843 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2847 static int check_printdest_info(struct pack_desc* desc,
2848 int uLevel, char* id)
2850 desc->subformat = NULL;
2852 case 0: desc->format = "B9"; break;
2853 case 1: desc->format = "B9B21WWzW"; break;
2854 case 2: desc->format = "z"; break;
2855 case 3: desc->format = "zzzWWzzzWW"; break;
2856 default: return False;
2858 if (strcmp(desc->format,id) != 0) return False;
2862 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2863 struct pack_desc* desc)
2866 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2867 buf[sizeof(buf)-1] = 0;
2870 PACKS(desc,"B9",buf); /* szName */
2872 PACKS(desc,"B21",""); /* szUserName */
2873 PACKI(desc,"W",0); /* uJobId */
2874 PACKI(desc,"W",0); /* fsStatus */
2875 PACKS(desc,"z",""); /* pszStatus */
2876 PACKI(desc,"W",0); /* time */
2879 if (uLevel == 2 || uLevel == 3) {
2880 PACKS(desc,"z",buf); /* pszPrinterName */
2882 PACKS(desc,"z",""); /* pszUserName */
2883 PACKS(desc,"z",""); /* pszLogAddr */
2884 PACKI(desc,"W",0); /* uJobId */
2885 PACKI(desc,"W",0); /* fsStatus */
2886 PACKS(desc,"z",""); /* pszStatus */
2887 PACKS(desc,"z",""); /* pszComment */
2888 PACKS(desc,"z","NULL"); /* pszDrivers */
2889 PACKI(desc,"W",0); /* time */
2890 PACKI(desc,"W",0); /* pad1 */
2895 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2896 int mdrcnt,int mprcnt,
2897 char **rdata,char **rparam,
2898 int *rdata_len,int *rparam_len)
2900 char *str1 = param+2;
2901 char *str2 = skip_string(str1,1);
2902 char *p = skip_string(str2,1);
2903 char* PrinterName = p;
2905 struct pack_desc desc;
2908 memset((char *)&desc,'\0',sizeof(desc));
2910 p = skip_string(p,1);
2913 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2915 /* check it's a supported varient */
2916 if (strcmp(str1,"zWrLh") != 0) return False;
2917 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2919 snum = lp_servicenumber(PrinterName);
2920 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2921 int pnum = lp_servicenumber(PRINTERS_NAME);
2923 lp_add_printer(PrinterName,pnum);
2924 snum = lp_servicenumber(PrinterName);
2930 desc.errcode = NERR_DestNotFound;
2934 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2936 desc.buflen = mdrcnt;
2937 if (init_package(&desc,1,0)) {
2938 fill_printdest_info(conn,snum,uLevel,&desc);
2940 *rdata_len = desc.usedlen;
2944 *rparam = REALLOC(*rparam,*rparam_len);
2945 SSVALS(*rparam,0,desc.errcode);
2947 SSVAL(*rparam,4,desc.neededlen);
2949 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2953 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2954 int mdrcnt,int mprcnt,
2955 char **rdata,char **rparam,
2956 int *rdata_len,int *rparam_len)
2958 char *str1 = param+2;
2959 char *str2 = skip_string(str1,1);
2960 char *p = skip_string(str2,1);
2964 struct pack_desc desc;
2965 int services = lp_numservices();
2967 memset((char *)&desc,'\0',sizeof(desc));
2971 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2973 /* check it's a supported varient */
2974 if (strcmp(str1,"WrLeh") != 0) return False;
2975 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2978 for (i = 0; i < services; i++)
2979 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2982 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2984 desc.buflen = mdrcnt;
2985 if (init_package(&desc,queuecnt,0)) {
2988 for (i = 0; i < services; i++) {
2989 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2990 fill_printdest_info(conn,i,uLevel,&desc);
2992 if (desc.errcode == NERR_Success) succnt = n;
2997 *rdata_len = desc.usedlen;
3000 *rparam = REALLOC(*rparam,*rparam_len);
3001 SSVALS(*rparam,0,desc.errcode);
3003 SSVAL(*rparam,4,succnt);
3004 SSVAL(*rparam,6,queuecnt);
3006 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3010 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3011 int mdrcnt,int mprcnt,
3012 char **rdata,char **rparam,
3013 int *rdata_len,int *rparam_len)
3015 char *str1 = param+2;
3016 char *str2 = skip_string(str1,1);
3017 char *p = skip_string(str2,1);
3020 struct pack_desc desc;
3022 memset((char *)&desc,'\0',sizeof(desc));
3026 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3028 /* check it's a supported varient */
3029 if (strcmp(str1,"WrLeh") != 0) return False;
3030 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3032 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3034 desc.buflen = mdrcnt;
3035 if (init_package(&desc,1,0)) {
3036 PACKS(&desc,"B41","NULL");
3039 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3041 *rdata_len = desc.usedlen;
3044 *rparam = REALLOC(*rparam,*rparam_len);
3045 SSVALS(*rparam,0,desc.errcode);
3047 SSVAL(*rparam,4,succnt);
3050 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3054 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3055 int mdrcnt,int mprcnt,
3056 char **rdata,char **rparam,
3057 int *rdata_len,int *rparam_len)
3059 char *str1 = param+2;
3060 char *str2 = skip_string(str1,1);
3061 char *p = skip_string(str2,1);
3064 struct pack_desc desc;
3066 memset((char *)&desc,'\0',sizeof(desc));
3070 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3072 /* check it's a supported varient */
3073 if (strcmp(str1,"WrLeh") != 0) return False;
3074 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3076 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3078 desc.buflen = mdrcnt;
3080 if (init_package(&desc,1,0)) {
3081 PACKS(&desc,"B13","lpd");
3084 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3086 *rdata_len = desc.usedlen;
3089 *rparam = REALLOC(*rparam,*rparam_len);
3090 SSVALS(*rparam,0,desc.errcode);
3092 SSVAL(*rparam,4,succnt);
3095 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3099 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3100 int mdrcnt,int mprcnt,
3101 char **rdata,char **rparam,
3102 int *rdata_len,int *rparam_len)
3104 char *str1 = param+2;
3105 char *str2 = skip_string(str1,1);
3106 char *p = skip_string(str2,1);
3109 struct pack_desc desc;
3111 memset((char *)&desc,'\0',sizeof(desc));
3115 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3117 /* check it's a supported varient */
3118 if (strcmp(str1,"WrLeh") != 0) return False;
3119 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3121 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3122 memset((char *)&desc,'\0',sizeof(desc));
3124 desc.buflen = mdrcnt;
3126 if (init_package(&desc,1,0)) {
3127 PACKS(&desc,"B13","lp0");
3130 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3132 *rdata_len = desc.usedlen;
3135 *rparam = REALLOC(*rparam,*rparam_len);
3136 SSVALS(*rparam,0,desc.errcode);
3138 SSVAL(*rparam,4,succnt);
3141 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3145 /****************************************************************************
3146 The buffer was too small
3147 ****************************************************************************/
3149 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3150 int mdrcnt,int mprcnt,
3151 char **rdata,char **rparam,
3152 int *rdata_len,int *rparam_len)
3154 *rparam_len = MIN(*rparam_len,mprcnt);
3155 *rparam = REALLOC(*rparam,*rparam_len);
3159 SSVAL(*rparam,0,NERR_BufTooSmall);
3161 DEBUG(3,("Supplied buffer too small in API command\n"));
3167 /****************************************************************************
3168 The request is not supported
3169 ****************************************************************************/
3171 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3172 int mdrcnt,int mprcnt,
3173 char **rdata,char **rparam,
3174 int *rdata_len,int *rparam_len)
3177 *rparam = REALLOC(*rparam,*rparam_len);
3181 SSVAL(*rparam,0,NERR_notsupported);
3182 SSVAL(*rparam,2,0); /* converter word */
3184 DEBUG(3,("Unsupported API command\n"));
3196 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3197 int,int,char **,char **,int *,int *);
3199 } api_commands[] = {
3200 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3201 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3202 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3203 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3204 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3205 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3206 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3207 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3208 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3209 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3210 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3211 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3212 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3213 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3214 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3215 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3216 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3217 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3218 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3219 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3220 {"NetServerEnum", 104, api_RNetServerEnum,0},
3221 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3222 {"SetUserPassword", 115, api_SetUserPassword,0},
3223 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3224 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3225 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3226 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3227 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3228 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3229 {NULL, -1, api_Unsupported,0}};
3232 /****************************************************************************
3233 Handle remote api calls
3234 ****************************************************************************/
3236 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3237 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3241 char *rparam = NULL;
3248 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3252 api_command = SVAL(params,0);
3254 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3257 skip_string(params+2,1),
3258 tdscnt,tpscnt,mdrcnt,mprcnt));
3260 for (i=0;api_commands[i].name;i++) {
3261 if (api_commands[i].id == api_command && api_commands[i].fn) {
3262 DEBUG(3,("Doing %s\n",api_commands[i].name));
3267 rdata = (char *)malloc(1024);
3269 memset(rdata,'\0',1024);
3271 rparam = (char *)malloc(1024);
3273 memset(rparam,'\0',1024);
3275 if(!rdata || !rparam) {
3276 DEBUG(0,("api_reply: malloc fail !\n"));
3280 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3281 &rdata,&rparam,&rdata_len,&rparam_len);
3284 if (rdata_len > mdrcnt ||
3285 rparam_len > mprcnt) {
3286 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3287 &rdata,&rparam,&rdata_len,&rparam_len);
3290 /* if we get False back then it's actually unsupported */
3292 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3293 &rdata,&rparam,&rdata_len,&rparam_len);
3295 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);