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_myworkgroup;
42 #define NERR_Success 0
43 #define NERR_badpass 86
44 #define NERR_notsupported 50
46 #define NERR_BASE (2100)
47 #define NERR_BufTooSmall (NERR_BASE+23)
48 #define NERR_JobNotFound (NERR_BASE+51)
49 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ACCESS_READ 0x01
52 #define ACCESS_WRITE 0x02
53 #define ACCESS_CREATE 0x04
55 #define SHPWLEN 8 /* share password length */
57 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
58 int mdrcnt,int mprcnt,
59 char **rdata,char **rparam,
60 int *rdata_len,int *rparam_len);
61 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
62 int mdrcnt,int mprcnt,
63 char **rdata,char **rparam,
64 int *rdata_len,int *rparam_len);
67 static int CopyExpanded(connection_struct *conn,
68 int snum, char** dst, char* src, int* n)
73 if (!src || !dst || !n || !(*dst)) return(0);
75 StrnCpy(buf,src,sizeof(buf)/2);
76 pstring_sub(buf,"%S",lp_servicename(snum));
77 standard_sub_conn(conn,buf);
85 static int CopyAndAdvance(char** dst, char* src, int* n)
88 if (!src || !dst || !n || !(*dst)) return(0);
89 StrnCpy(*dst,src,*n-1);
96 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
100 StrnCpy(buf,s,sizeof(buf)/2);
101 pstring_sub(buf,"%S",lp_servicename(snum));
102 standard_sub_conn(conn,buf);
103 return strlen(buf) + 1;
106 static char* Expand(connection_struct *conn, int snum, char* s)
109 if (!s) return(NULL);
110 StrnCpy(buf,s,sizeof(buf)/2);
111 pstring_sub(buf,"%S",lp_servicename(snum));
112 standard_sub_conn(conn,buf);
116 /*******************************************************************
117 check a API string for validity when we only need to check the prefix
118 ******************************************************************/
119 static BOOL prefix_ok(char *str,char *prefix)
121 return(strncmp(str,prefix,strlen(prefix)) == 0);
125 char* format; /* formatstring for structure */
126 char* subformat; /* subformat for structure */
127 char* base; /* baseaddress of buffer */
128 int buflen; /* remaining size for fixed part; on init: length of base */
129 int subcount; /* count of substructures */
130 char* structbuf; /* pointer into buffer for remaining fixed part */
131 int stringlen; /* remaining size for variable part */
132 char* stringbuf; /* pointer into buffer for remaining variable part */
133 int neededlen; /* total needed size */
134 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
135 char* curpos; /* current position; pointer into format or subformat */
139 static int get_counter(char** p)
142 if (!p || !(*p)) return(1);
143 if (!isdigit((int)**p)) return 1;
147 n = 10 * n + (i - '0');
154 static int getlen(char* p)
160 case 'W': /* word (2 byte) */
163 case 'K': /* status word? (2 byte) */
166 case 'N': /* count of substructures (word) at end */
169 case 'D': /* double word (4 byte) */
170 case 'z': /* offset to zero terminated string (4 byte) */
171 case 'l': /* offset to user data (4 byte) */
174 case 'b': /* offset to data (with counter) (4 byte) */
178 case 'B': /* byte (with optional counter) */
179 n += get_counter(&p);
186 static BOOL init_package(struct pack_desc* p, int count, int subcount)
191 if (!p->format || !p->base) return(False);
193 i = count * getlen(p->format);
194 if (p->subformat) i += subcount * getlen(p->subformat);
195 p->structbuf = p->base;
199 p->curpos = p->format;
203 p->errcode = ERRmoredata;
206 p->errcode = NERR_Success;
209 p->stringbuf = p->base + i;
211 return(p->errcode == NERR_Success);
215 static int package(struct pack_desc* p, ...)
218 static int package(va_alist)
224 int needed=0, stringneeded;
226 int is_string=0, stringused;
233 p = va_arg(args,struct pack_desc *);
238 p->curpos = p->format;
240 p->curpos = p->subformat;
245 str = va_arg(args,char*);
246 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
255 switch( *p->curpos++ ) {
256 case 'W': /* word (2 byte) */
258 temp = va_arg(args,int);
259 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
261 case 'K': /* status word? (2 byte) */
263 temp = va_arg(args,int);
264 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
266 case 'N': /* count of substructures (word) at end */
268 p->subcount = va_arg(args,int);
269 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
271 case 'D': /* double word (4 byte) */
273 temp = va_arg(args,int);
274 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
276 case 'B': /* byte (with optional counter) */
277 needed = get_counter(&p->curpos);
279 char *s = va_arg(args,char*);
280 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
283 case 'z': /* offset to zero terminated string (4 byte) */
284 str = va_arg(args,char*);
285 stringneeded = (str ? strlen(str)+1 : 0);
288 case 'l': /* offset to user data (4 byte) */
289 str = va_arg(args,char*);
290 stringneeded = va_arg(args,int);
293 case 'b': /* offset to data (with counter) (4 byte) */
294 str = va_arg(args,char*);
295 stringneeded = get_counter(&p->curpos);
300 if (stringneeded >= 0) {
302 if (p->buflen >= needed) {
303 stringused = stringneeded;
304 if (stringused > p->stringlen) {
305 stringused = (is_string ? p->stringlen : 0);
306 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
309 SIVAL(p->structbuf,0,0);
311 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
312 memcpy(p->stringbuf,str?str:"",stringused);
313 if (is_string) p->stringbuf[stringused-1] = '\0';
314 p->stringbuf += stringused;
315 p->stringlen -= stringused;
316 p->usedlen += stringused;
319 p->neededlen += stringneeded;
321 p->neededlen += needed;
322 if (p->buflen >= needed) {
323 p->structbuf += needed;
325 p->usedlen += needed;
328 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
334 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
335 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
337 #define PACK(desc,t,v) package(desc,v)
338 #define PACKl(desc,t,v,l) package(desc,v,l)
341 static void PACKI(struct pack_desc* desc,char *t,int v)
346 static void PACKS(struct pack_desc* desc,char *t,char *v)
352 /****************************************************************************
354 ****************************************************************************/
355 static void PackDriverData(struct pack_desc* desc)
357 char drivdata[4+4+32];
358 SIVAL(drivdata,0,sizeof drivdata); /* cb */
359 SIVAL(drivdata,4,1000); /* lVersion */
360 memset(drivdata+8,0,32); /* szDeviceName */
361 pstrcpy(drivdata+8,"NULL");
362 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
365 static int check_printq_info(struct pack_desc* desc,
366 int uLevel, char *id1, char *id2)
368 desc->subformat = NULL;
371 desc->format = "B13";
374 desc->format = "B13BWWWzzzzzWW";
377 desc->format = "B13BWWWzzzzzWN";
378 desc->subformat = "WB21BB16B10zWWzDDz";
381 desc->format = "zWWWWzzzzWWzzl";
384 desc->format = "zWWWWzzzzWNzzl";
385 desc->subformat = "WWzWWDDzz";
394 desc->format = "WzzzzzzzzN";
395 desc->subformat = "z";
397 default: return False;
399 if (strcmp(desc->format,id1) != 0) return False;
400 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
405 #define JOB_STATUS_QUEUED 0
406 #define JOB_STATUS_PAUSED 1
407 #define JOB_STATUS_SPOOLING 2
408 #define JOB_STATUS_PRINTING 3
409 #define JOB_STATUS_PRINTED 4
411 #define QUEUE_STATUS_PAUSED 1
412 #define QUEUE_STATUS_ERROR 2
414 /* turn a print job status into a on the wire status
416 static int printj_status(int v)
420 return JOB_STATUS_QUEUED;
422 return JOB_STATUS_PAUSED;
424 return JOB_STATUS_SPOOLING;
426 return JOB_STATUS_PRINTING;
431 /* turn a print queue status into a on the wire status
433 static int printq_status(int v)
439 return QUEUE_STATUS_PAUSED;
441 return QUEUE_STATUS_ERROR;
444 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
445 struct pack_desc* desc,
446 print_queue_struct* queue, int n)
448 time_t t = queue->time;
450 /* the client expects localtime */
453 PACKI(desc,"W",queue->job); /* uJobId */
455 PACKS(desc,"B21",queue->user); /* szUserName */
456 PACKS(desc,"B",""); /* pad */
457 PACKS(desc,"B16",""); /* szNotifyName */
458 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
459 PACKS(desc,"z",""); /* pszParms */
460 PACKI(desc,"W",n+1); /* uPosition */
461 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
462 PACKS(desc,"z",""); /* pszStatus */
463 PACKI(desc,"D",t); /* ulSubmitted */
464 PACKI(desc,"D",queue->size); /* ulSize */
465 PACKS(desc,"z",queue->file); /* pszComment */
467 if (uLevel == 2 || uLevel == 3) {
468 PACKI(desc,"W",queue->priority); /* uPriority */
469 PACKS(desc,"z",queue->user); /* pszUserName */
470 PACKI(desc,"W",n+1); /* uPosition */
471 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
472 PACKI(desc,"D",t); /* ulSubmitted */
473 PACKI(desc,"D",queue->size); /* ulSize */
474 PACKS(desc,"z","Samba"); /* pszComment */
475 PACKS(desc,"z",queue->file); /* pszDocument */
477 PACKS(desc,"z",""); /* pszNotifyName */
478 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
479 PACKS(desc,"z",""); /* pszParms */
480 PACKS(desc,"z",""); /* pszStatus */
481 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
482 PACKS(desc,"z","lpd"); /* pszQProcName */
483 PACKS(desc,"z",""); /* pszQProcParms */
484 PACKS(desc,"z","NULL"); /* pszDriverName */
485 PackDriverData(desc); /* pDriverData */
486 PACKS(desc,"z",""); /* pszPrinterName */
492 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
493 struct pack_desc* desc,
494 int count, print_queue_struct* queue,
495 print_status_struct* status)
499 pstring tok,driver,datafile,langmon,helpfile,datatype;
505 * Check in the tdb *first* before checking the legacy
506 * files. This allows an NT upload to take precedence over
507 * the existing fileset. JRA.
510 if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)) ) == True) {
512 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
514 /* didn't find driver in tdb */
516 DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
517 snum, lp_printerdriver(snum), lp_driverfile(snum)));
519 lines = file_lines_load(lp_driverfile(snum),NULL);
521 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
522 desc->errcode=NERR_notsupported;
525 /* lookup the long printer driver name in the file description */
526 for (i=0;lines[i] && !ok;i++) {
528 if (next_token(&p,tok,":",sizeof(tok)) &&
529 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
530 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
538 /* driver file name */
539 if (!next_token(&p,driver,":",sizeof(driver)))
543 if (!next_token(&p,datafile,":",sizeof(datafile)))
547 * for the next tokens - which may be empty - I have
548 * to check for empty tokens first because the
549 * next_token function will skip all empty token
556 } else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
559 /* language monitor */
563 } else if (!next_token(&p,langmon,":",sizeof(langmon)))
566 /* default data type */
567 if (!next_token(&p,datatype,":",sizeof(datatype)))
570 PACKI(desc,"W",0x0400); /* don't know */
571 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
572 PACKS(desc,"z",driver); /* Driverfile Name */
573 PACKS(desc,"z",datafile); /* Datafile name */
574 PACKS(desc,"z",langmon); /* language monitor */
575 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
576 PACKS(desc,"z",datatype); /* default data type */
577 PACKS(desc,"z",helpfile); /* helpfile name */
578 PACKS(desc,"z",driver); /* driver name */
579 DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum)));
580 DEBUG(3,("Driver:%s:\n",driver));
581 DEBUG(3,("Data File:%s:\n",datafile));
582 DEBUG(3,("Language Monitor:%s:\n",langmon));
583 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
584 DEBUG(3,("Data Type:%s:\n",datatype));
585 DEBUG(3,("Help File:%s:\n",helpfile));
586 PACKI(desc,"N",count); /* number of files to copy */
588 for (i=0;i<count;i++) {
589 /* no need to check return value here
590 * - it was already tested in
591 * get_printerdrivernumber */
592 next_token(&p,tok,",",sizeof(tok));
593 PACKS(desc,"z",tok); /* driver files to copy */
594 DEBUG(3,("file:%s:\n",tok));
597 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
598 SERVICE(snum),count));
600 desc->errcode=NERR_Success;
601 file_lines_free(lines);
607 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
608 desc->errcode=NERR_notsupported;
609 file_lines_free(lines);
613 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
614 struct pack_desc* desc,
615 int count, print_queue_struct* queue,
616 print_status_struct* status)
621 PACKS(desc,"B13",SERVICE(snum));
626 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
629 PACKI(desc,"K",printq_status(status->status));
633 if (uLevel == 1 || uLevel == 2) {
634 PACKS(desc,"B",""); /* alignment */
635 PACKI(desc,"W",5); /* priority */
636 PACKI(desc,"W",0); /* start time */
637 PACKI(desc,"W",0); /* until time */
638 PACKS(desc,"z",""); /* pSepFile */
639 PACKS(desc,"z","lpd"); /* pPrProc */
640 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
641 PACKS(desc,"z",""); /* pParms */
643 PACKS(desc,"z","UNKNOWN PRINTER");
644 PACKI(desc,"W",LPSTAT_ERROR);
646 else if (!status || !status->message[0]) {
647 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
648 PACKI(desc,"W",LPSTAT_OK); /* status */
650 PACKS(desc,"z",status->message);
651 PACKI(desc,"W",printq_status(status->status)); /* status */
653 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
656 if (uLevel == 3 || uLevel == 4) {
657 PACKI(desc,"W",5); /* uPriority */
658 PACKI(desc,"W",0); /* uStarttime */
659 PACKI(desc,"W",0); /* uUntiltime */
660 PACKI(desc,"W",5); /* pad1 */
661 PACKS(desc,"z",""); /* pszSepFile */
662 PACKS(desc,"z","WinPrint"); /* pszPrProc */
663 PACKS(desc,"z",""); /* pszParms */
664 if (!status || !status->message[0]) {
665 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
666 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
668 PACKS(desc,"z",status->message); /* pszComment */
669 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
671 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
672 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
673 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
674 PackDriverData(desc); /* pDriverData */
677 if (uLevel == 2 || uLevel == 4) {
679 for (i=0;i<count;i++)
680 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
684 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
688 /* This function returns the number of files for a given driver */
689 static int get_printerdrivernumber(int snum)
699 * Check in the tdb *first* before checking the legacy
700 * files. This allows an NT upload to take precedence over
701 * the existing fileset. JRA.
704 if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum))) == True ) {
706 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
708 /* didn't find driver in tdb */
710 DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
711 snum, lp_printerdriver(snum), lp_driverfile(snum)));
713 lines = file_lines_load(lp_driverfile(snum), NULL);
715 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
717 /* lookup the long printer driver name in the file description */
718 for (i=0;lines[i] && !ok;i++) {
720 if (next_token(&p,tok,":",sizeof(tok)) &&
721 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
722 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
732 if (*p++ == ':') i--;
737 /* count the number of files */
738 while (next_token(&p,tok,",",sizeof(tok)))
741 file_lines_free(lines);
747 DEBUG(3,("Can't determine number of printer driver files\n"));
748 file_lines_free(lines);
752 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
753 uint16 vuid, char *param,char *data,
754 int mdrcnt,int mprcnt,
755 char **rdata,char **rparam,
756 int *rdata_len,int *rparam_len)
758 char *str1 = param+2;
759 char *str2 = skip_string(str1,1);
760 char *p = skip_string(str2,1);
766 struct pack_desc desc;
767 print_queue_struct *queue=NULL;
768 print_status_struct status;
770 memset((char *)&status,'\0',sizeof(status));
771 memset((char *)&desc,'\0',sizeof(desc));
773 p = skip_string(p,1);
777 /* remove any trailing username */
778 if ((p = strchr(QueueName,'%'))) *p = 0;
780 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
782 /* check it's a supported varient */
783 if (!prefix_ok(str1,"zWrLh")) return False;
784 if (!check_printq_info(&desc,uLevel,str2,str3)) {
786 * Patch from Scott Moomaw <scott@bridgewater.edu>
787 * to return the 'invalid info level' error if an
788 * unknown level was requested.
792 *rparam = REALLOC(*rparam,*rparam_len);
793 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
799 snum = lp_servicenumber(QueueName);
800 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
801 int pnum = lp_servicenumber(PRINTERS_NAME);
803 lp_add_printer(QueueName,pnum);
804 snum = lp_servicenumber(QueueName);
808 if (snum < 0 || !VALID_SNUM(snum)) return(False);
811 count = get_printerdrivernumber(snum);
812 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
814 count = print_queue_status(snum, &queue,&status);
817 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
819 desc.buflen = mdrcnt;
820 if (init_package(&desc,1,count)) {
821 desc.subcount = count;
822 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
823 } else if(uLevel == 0) {
826 * This is a *disgusting* hack.
827 * This is *so* bad that even I'm embarrassed (and I
828 * have no shame). Here's the deal :
829 * Until we get the correct SPOOLSS code into smbd
830 * then when we're running with NT SMB support then
831 * NT makes this call with a level of zero, and then
832 * immediately follows it with an open request to
833 * the \\SRVSVC pipe. If we allow that open to
834 * succeed then NT barfs when it cannot open the
835 * \\SPOOLSS pipe immediately after and continually
836 * whines saying "Printer name is invalid" forever
837 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
838 * to fail, then NT downgrades to using the downlevel code
839 * and everything works as well as before. I hate
840 * myself for adding this code.... JRA.
843 fail_next_srvsvc_open();
847 *rdata_len = desc.usedlen;
850 *rparam = REALLOC(*rparam,*rparam_len);
851 SSVALS(*rparam,0,desc.errcode);
853 SSVAL(*rparam,4,desc.neededlen);
855 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
857 if (queue) free(queue);
862 /****************************************************************************
863 View list of all print jobs on all queues.
864 ****************************************************************************/
866 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
867 int mdrcnt, int mprcnt,
868 char **rdata, char** rparam,
869 int *rdata_len, int *rparam_len)
871 char *param_format = param+2;
872 char *output_format1 = skip_string(param_format,1);
873 char *p = skip_string(output_format1,1);
874 int uLevel = SVAL(p,0);
875 char *output_format2 = p + 4;
876 int services = lp_numservices();
878 struct pack_desc desc;
879 print_queue_struct **queue = NULL;
880 print_status_struct *status = NULL;
881 int* subcntarr = NULL;
882 int queuecnt, subcnt=0, succnt=0;
884 memset((char *)&desc,'\0',sizeof(desc));
886 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
888 if (!prefix_ok(param_format,"WrLeh")) return False;
889 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
891 * Patch from Scott Moomaw <scott@bridgewater.edu>
892 * to return the 'invalid info level' error if an
893 * unknown level was requested.
897 *rparam = REALLOC(*rparam,*rparam_len);
898 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
905 for (i = 0; i < services; i++)
906 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
909 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
910 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
913 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
914 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
915 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
918 memset(status,0,queuecnt*sizeof(print_status_struct));
919 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
920 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
925 for (i = 0; i < services; i++)
926 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
927 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
928 subcnt += subcntarr[n];
932 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
934 desc.buflen = mdrcnt;
936 if (init_package(&desc,queuecnt,subcnt)) {
939 for (i = 0; i < services; i++)
940 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
941 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
943 if (desc.errcode == NERR_Success) succnt = n;
947 if (subcntarr) free(subcntarr);
949 *rdata_len = desc.usedlen;
951 *rparam = REALLOC(*rparam,*rparam_len);
952 SSVALS(*rparam,0,desc.errcode);
954 SSVAL(*rparam,4,succnt);
955 SSVAL(*rparam,6,queuecnt);
957 for (i = 0; i < queuecnt; i++) {
958 if (queue && queue[i]) free(queue[i]);
961 if (queue) free(queue);
962 if (status) free(status);
967 /****************************************************************************
968 get info level for a server list query
969 ****************************************************************************/
970 static BOOL check_server_info(int uLevel, char* id)
974 if (strcmp(id,"B16") != 0) return False;
977 if (strcmp(id,"B16BBDz") != 0) return False;
985 struct srv_info_struct
995 /*******************************************************************
996 get server info lists from the files saved by nmbd. Return the
998 ******************************************************************/
999 static int get_server_info(uint32 servertype,
1000 struct srv_info_struct **servers,
1006 BOOL local_list_only;
1009 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1011 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1015 /* request for everything is code for request all servers */
1016 if (servertype == SV_TYPE_ALL)
1017 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1019 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1021 DEBUG(4,("Servertype search: %8x\n",servertype));
1023 for (i=0;lines[i];i++) {
1025 struct srv_info_struct *s;
1026 char *ptr = lines[i];
1029 if (!*ptr) continue;
1031 if (count == alloced) {
1033 (*servers) = (struct srv_info_struct *)
1034 Realloc(*servers,sizeof(**servers)*alloced);
1035 if (!(*servers)) return(0);
1036 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1038 s = &(*servers)[count];
1040 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1041 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1042 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1043 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1044 /* this allows us to cope with an old nmbd */
1045 pstrcpy(s->domain,global_myworkgroup);
1048 if (sscanf(stype,"%X",&s->type) != 1) {
1049 DEBUG(4,("r:host file "));
1053 /* Filter the servers/domains we return based on what was asked for. */
1055 /* Check to see if we are being asked for a local list only. */
1056 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1057 DEBUG(4,("r: local list only"));
1061 /* doesn't match up: don't want it */
1062 if (!(servertype & s->type)) {
1063 DEBUG(4,("r:serv type "));
1067 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1068 (s->type & SV_TYPE_DOMAIN_ENUM))
1070 DEBUG(4,("s: dom mismatch "));
1074 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1079 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1080 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1084 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1085 s->name, s->type, s->comment, s->domain));
1087 s->server_added = True;
1092 DEBUG(4,("%20s %8x %25s %15s\n",
1093 s->name, s->type, s->comment, s->domain));
1097 file_lines_free(lines);
1102 /*******************************************************************
1103 fill in a server info structure
1104 ******************************************************************/
1105 static int fill_srv_info(struct srv_info_struct *service,
1106 int uLevel, char **buf, int *buflen,
1107 char **stringbuf, int *stringspace, char *baseaddr)
1116 case 0: struct_len = 16; break;
1117 case 1: struct_len = 26; break;
1127 len = strlen(service->comment)+1;
1131 if (buflen) *buflen = struct_len;
1132 if (stringspace) *stringspace = len;
1133 return struct_len + len;
1138 if (*buflen < struct_len) return -1;
1146 p2 = p + struct_len;
1147 l2 = *buflen - struct_len;
1149 if (!baseaddr) baseaddr = p;
1154 StrnCpy(p,service->name,15);
1158 StrnCpy(p,service->name,15);
1159 SIVAL(p,18,service->type);
1160 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1161 len += CopyAndAdvance(&p2,service->comment,&l2);
1167 *buf = p + struct_len;
1168 *buflen -= struct_len;
1181 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1183 return(strcmp(s1->name,s2->name));
1186 /****************************************************************************
1187 view list of servers available (or possibly domains). The info is
1188 extracted from lists saved by nmbd on the local host
1189 ****************************************************************************/
1190 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1191 int mdrcnt, int mprcnt, char **rdata,
1192 char **rparam, int *rdata_len, int *rparam_len)
1194 char *str1 = param+2;
1195 char *str2 = skip_string(str1,1);
1196 char *p = skip_string(str2,1);
1197 int uLevel = SVAL(p,0);
1198 int buf_len = SVAL(p,2);
1199 uint32 servertype = IVAL(p,4);
1201 int data_len, fixed_len, string_len;
1202 int f_len = 0, s_len = 0;
1203 struct srv_info_struct *servers=NULL;
1204 int counted=0,total=0;
1207 BOOL domain_request;
1210 /* If someone sets all the bits they don't really mean to set
1211 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1214 if (servertype == SV_TYPE_ALL)
1215 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1217 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1218 any other bit (they may just set this bit on it's own) they
1219 want all the locally seen servers. However this bit can be
1220 set on its own so set the requested servers to be
1221 ALL - DOMAIN_ENUM. */
1223 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1224 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1226 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1227 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1231 if (!prefix_ok(str1,"WrLehD")) return False;
1232 if (!check_server_info(uLevel,str2)) return False;
1234 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1235 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1236 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1238 if (strcmp(str1, "WrLehDz") == 0) {
1239 StrnCpy(domain, p, sizeof(fstring)-1);
1241 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1244 if (lp_browse_list())
1245 total = get_server_info(servertype,&servers,domain);
1247 data_len = fixed_len = string_len = 0;
1250 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1253 char *lastname=NULL;
1255 for (i=0;i<total;i++)
1257 struct srv_info_struct *s = &servers[i];
1258 if (lastname && strequal(lastname,s->name)) continue;
1260 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1261 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1262 s->name, s->type, s->comment, s->domain));
1264 if (data_len <= buf_len) {
1267 string_len += s_len;
1274 *rdata_len = fixed_len + string_len;
1275 *rdata = REALLOC(*rdata,*rdata_len);
1276 memset(*rdata,'\0',*rdata_len);
1278 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1284 char *lastname=NULL;
1285 int count2 = counted;
1286 for (i = 0; i < total && count2;i++)
1288 struct srv_info_struct *s = &servers[i];
1289 if (lastname && strequal(lastname,s->name)) continue;
1291 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1292 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1293 s->name, s->type, s->comment, s->domain));
1299 *rparam = REALLOC(*rparam,*rparam_len);
1300 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1302 SSVAL(*rparam,4,counted);
1303 SSVAL(*rparam,6,counted+missed);
1305 if (servers) free(servers);
1307 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1308 domain,uLevel,counted,counted+missed));
1313 /****************************************************************************
1314 command 0x34 - suspected of being a "Lookup Names" stub api
1315 ****************************************************************************/
1316 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1317 int mdrcnt, int mprcnt, char **rdata,
1318 char **rparam, int *rdata_len, int *rparam_len)
1320 char *str1 = param+2;
1321 char *str2 = skip_string(str1,1);
1322 char *p = skip_string(str2,1);
1323 int uLevel = SVAL(p,0);
1324 int buf_len = SVAL(p,2);
1328 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1329 str1, str2, p, uLevel, buf_len));
1331 if (!prefix_ok(str1,"zWrLeh")) return False;
1336 *rparam = REALLOC(*rparam,*rparam_len);
1338 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1340 SSVAL(*rparam,4,counted);
1341 SSVAL(*rparam,6,counted+missed);
1346 /****************************************************************************
1347 get info about a share
1348 ****************************************************************************/
1349 static BOOL check_share_info(int uLevel, char* id)
1353 if (strcmp(id,"B13") != 0) return False;
1356 if (strcmp(id,"B13BWz") != 0) return False;
1359 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1362 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1364 default: return False;
1369 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1370 char** buf, int* buflen,
1371 char** stringbuf, int* stringspace, char* baseaddr)
1380 case 0: struct_len = 13; break;
1381 case 1: struct_len = 20; break;
1382 case 2: struct_len = 40; break;
1383 case 91: struct_len = 68; break;
1391 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1392 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1393 if (buflen) *buflen = struct_len;
1394 if (stringspace) *stringspace = len;
1395 return struct_len + len;
1400 if ((*buflen) < struct_len) return -1;
1408 p2 = p + struct_len;
1409 l2 = (*buflen) - struct_len;
1411 if (!baseaddr) baseaddr = p;
1413 StrnCpy(p,lp_servicename(snum),13);
1419 type = STYPE_DISKTREE;
1420 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1421 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1422 SSVAL(p,14,type); /* device type */
1423 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1424 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1429 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1430 SSVALS(p,22,-1); /* max uses */
1431 SSVAL(p,24,1); /* current uses */
1432 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1433 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1434 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1439 memset(p+40,0,SHPWLEN+2);
1451 (*buf) = p + struct_len;
1452 (*buflen) -= struct_len;
1454 (*stringspace) = l2;
1464 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1465 int mdrcnt,int mprcnt,
1466 char **rdata,char **rparam,
1467 int *rdata_len,int *rparam_len)
1469 char *str1 = param+2;
1470 char *str2 = skip_string(str1,1);
1471 char *netname = skip_string(str2,1);
1472 char *p = skip_string(netname,1);
1473 int uLevel = SVAL(p,0);
1474 int snum = find_service(netname);
1476 if (snum < 0) return False;
1478 /* check it's a supported varient */
1479 if (!prefix_ok(str1,"zWrLh")) return False;
1480 if (!check_share_info(uLevel,str2)) return False;
1482 *rdata = REALLOC(*rdata,mdrcnt);
1484 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1485 if (*rdata_len < 0) return False;
1488 *rparam = REALLOC(*rparam,*rparam_len);
1489 SSVAL(*rparam,0,NERR_Success);
1490 SSVAL(*rparam,2,0); /* converter word */
1491 SSVAL(*rparam,4,*rdata_len);
1496 /****************************************************************************
1497 view list of shares available
1498 ****************************************************************************/
1499 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1500 int mdrcnt,int mprcnt,
1501 char **rdata,char **rparam,
1502 int *rdata_len,int *rparam_len)
1504 char *str1 = param+2;
1505 char *str2 = skip_string(str1,1);
1506 char *p = skip_string(str2,1);
1507 int uLevel = SVAL(p,0);
1508 int buf_len = SVAL(p,2);
1510 int count=lp_numservices();
1511 int total=0,counted=0;
1512 BOOL missed = False;
1514 int data_len, fixed_len, string_len;
1515 int f_len = 0, s_len = 0;
1517 if (!prefix_ok(str1,"WrLeh")) return False;
1518 if (!check_share_info(uLevel,str2)) return False;
1520 data_len = fixed_len = string_len = 0;
1521 for (i=0;i<count;i++)
1522 if (lp_browseable(i) && lp_snum_ok(i))
1525 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1526 if (data_len <= buf_len)
1530 string_len += s_len;
1535 *rdata_len = fixed_len + string_len;
1536 *rdata = REALLOC(*rdata,*rdata_len);
1537 memset(*rdata,0,*rdata_len);
1539 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1543 for (i = 0; i < count;i++)
1544 if (lp_browseable(i) && lp_snum_ok(i))
1545 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1549 *rparam = REALLOC(*rparam,*rparam_len);
1550 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1552 SSVAL(*rparam,4,counted);
1553 SSVAL(*rparam,6,total);
1555 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1556 counted,total,uLevel,
1557 buf_len,*rdata_len,mdrcnt));
1563 /****************************************************************************
1564 get the time of day info
1565 ****************************************************************************/
1566 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1567 int mdrcnt,int mprcnt,
1568 char **rdata,char **rparam,
1569 int *rdata_len,int *rparam_len)
1573 *rparam = REALLOC(*rparam,*rparam_len);
1576 *rdata = REALLOC(*rdata,*rdata_len);
1578 SSVAL(*rparam,0,NERR_Success);
1579 SSVAL(*rparam,2,0); /* converter word */
1585 time_t unixdate = time(NULL);
1587 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1588 by NT in a "net time" operation,
1589 it seems to ignore the one below */
1591 /* the client expects to get localtime, not GMT, in this bit
1592 (I think, this needs testing) */
1593 t = LocalTime(&unixdate);
1595 SIVAL(p,4,0); /* msecs ? */
1596 CVAL(p,8) = t->tm_hour;
1597 CVAL(p,9) = t->tm_min;
1598 CVAL(p,10) = t->tm_sec;
1599 CVAL(p,11) = 0; /* hundredths of seconds */
1600 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1601 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1602 CVAL(p,16) = t->tm_mday;
1603 CVAL(p,17) = t->tm_mon + 1;
1604 SSVAL(p,18,1900+t->tm_year);
1605 CVAL(p,20) = t->tm_wday;
1612 /****************************************************************************
1613 Set the user password.
1614 *****************************************************************************/
1616 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1617 int mdrcnt,int mprcnt,
1618 char **rdata,char **rparam,
1619 int *rdata_len,int *rparam_len)
1621 char *p = skip_string(param+2,2);
1623 fstring pass1,pass2;
1627 p = skip_string(p,1);
1629 memset(pass1,'\0',sizeof(pass1));
1630 memset(pass2,'\0',sizeof(pass2));
1632 memcpy(pass2,p+16,16);
1635 *rparam = REALLOC(*rparam,*rparam_len);
1639 SSVAL(*rparam,0,NERR_badpass);
1640 SSVAL(*rparam,2,0); /* converter word */
1642 DEBUG(3,("Set password for <%s>\n",user));
1645 * Pass the user through the NT -> unix user mapping
1649 (void)map_username(user);
1652 * Do any UNIX username case mangling.
1654 (void)Get_Pwnam( user, True);
1657 * Attempt to verify the old password against smbpasswd entries
1658 * Win98 clients send old and new password in plaintext for this call.
1662 fstring saved_pass2;
1663 struct smb_passwd *smbpw = NULL;
1666 * Save the new password as change_oem_password overwrites it
1670 fstrcpy(saved_pass2, pass2);
1672 if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
1673 change_oem_password(smbpw,pass2,False))
1675 SSVAL(*rparam,0,NERR_Success);
1678 * If unix password sync was requested, attempt to change
1679 * the /etc/passwd database also. Return failure if this cannot
1683 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1684 SSVAL(*rparam,0,NERR_badpass);
1689 * If the above failed, attempt the plaintext password change.
1690 * This tests against the /etc/passwd database only.
1693 if(SVAL(*rparam,0) != NERR_Success)
1695 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1696 chgpasswd(user,pass1,pass2,False))
1698 SSVAL(*rparam,0,NERR_Success);
1703 * If the plaintext change failed, attempt
1704 * the old encrypted method. NT will generate this
1705 * after trying the samr method. Note that this
1706 * method is done as a last resort as this
1707 * password change method loses the NT password hash
1708 * and cannot change the UNIX password as no plaintext
1712 if(SVAL(*rparam,0) != NERR_Success)
1714 struct smb_passwd *sampw = NULL;
1716 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1717 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1719 SSVAL(*rparam,0,NERR_Success);
1723 memset((char *)pass1,'\0',sizeof(fstring));
1724 memset((char *)pass2,'\0',sizeof(fstring));
1729 /****************************************************************************
1730 Set the user password (SamOEM version - gets plaintext).
1731 ****************************************************************************/
1733 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1734 int mdrcnt,int mprcnt,
1735 char **rdata,char **rparam,
1736 int *rdata_len,int *rparam_len)
1739 char *p = param + 2;
1741 *rparam = REALLOC(*rparam,*rparam_len);
1745 SSVAL(*rparam,0,NERR_badpass);
1748 * Check the parameter definition is correct.
1750 if(!strequal(param + 2, "zsT")) {
1751 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1754 p = skip_string(p, 1);
1756 if(!strequal(p, "B516B16")) {
1757 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1760 p = skip_string(p,1);
1763 p = skip_string(p,1);
1765 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1768 * Pass the user through the NT -> unix user mapping
1772 (void)map_username(user);
1775 * Do any UNIX username case mangling.
1777 (void)Get_Pwnam( user, True);
1779 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1781 SSVAL(*rparam,0,NERR_Success);
1787 /****************************************************************************
1790 ****************************************************************************/
1791 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1792 int mdrcnt,int mprcnt,
1793 char **rdata,char **rparam,
1794 int *rdata_len,int *rparam_len)
1796 int function = SVAL(param,0);
1797 char *str1 = param+2;
1798 char *str2 = skip_string(str1,1);
1799 char *p = skip_string(str2,1);
1801 extern struct current_user current_user;
1805 /* check it's a supported varient */
1806 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1810 *rparam = REALLOC(*rparam,*rparam_len);
1813 if (!print_job_exists(jobid)) {
1814 errcode = NERR_JobNotFound;
1818 errcode = NERR_notsupported;
1821 case 81: /* delete */
1822 if (print_job_delete(¤t_user, jobid))
1823 errcode = NERR_Success;
1825 case 82: /* pause */
1826 if (print_job_pause(¤t_user, jobid))
1827 errcode = NERR_Success;
1829 case 83: /* resume */
1830 if (print_job_resume(¤t_user, jobid))
1831 errcode = NERR_Success;
1836 SSVAL(*rparam,0,errcode);
1837 SSVAL(*rparam,2,0); /* converter word */
1842 /****************************************************************************
1843 Purge a print queue - or pause or resume it.
1844 ****************************************************************************/
1845 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1846 int mdrcnt,int mprcnt,
1847 char **rdata,char **rparam,
1848 int *rdata_len,int *rparam_len)
1850 int function = SVAL(param,0);
1851 char *str1 = param+2;
1852 char *str2 = skip_string(str1,1);
1853 char *QueueName = skip_string(str2,1);
1854 int errcode = NERR_notsupported;
1857 /* check it's a supported varient */
1858 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1862 *rparam = REALLOC(*rparam,*rparam_len);
1865 snum = print_queue_snum(QueueName);
1868 errcode = NERR_JobNotFound;
1873 case 74: /* Pause queue */
1874 if (print_queue_pause(NULL, snum)) errcode = NERR_Success;
1876 case 75: /* Resume queue */
1877 if (print_queue_resume(NULL, snum)) errcode = NERR_Success;
1879 case 103: /* Purge */
1880 if (print_queue_purge(NULL, snum)) errcode = NERR_Success;
1885 SSVAL(*rparam,0,errcode);
1886 SSVAL(*rparam,2,0); /* converter word */
1892 /****************************************************************************
1893 set the property of a print job (undocumented?)
1894 ? function = 0xb -> set name of print job
1895 ? function = 0x6 -> move print job up/down
1896 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1897 or <WWsTP> <WB21BB16B10zWWzDDz>
1898 ****************************************************************************/
1899 static int check_printjob_info(struct pack_desc* desc,
1900 int uLevel, char* id)
1902 desc->subformat = NULL;
1904 case 0: desc->format = "W"; break;
1905 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1906 case 2: desc->format = "WWzWWDDzz"; break;
1907 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1908 default: return False;
1910 if (strcmp(desc->format,id) != 0) return False;
1914 static BOOL api_PrintJobInfo(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 struct pack_desc desc;
1920 char *str1 = param+2;
1921 char *str2 = skip_string(str1,1);
1922 char *p = skip_string(str2,1);
1924 int uLevel = SVAL(p,2);
1925 int function = SVAL(p,4);
1930 *rparam = REALLOC(*rparam,*rparam_len);
1934 /* check it's a supported varient */
1935 if ((strcmp(str1,"WWsTP")) ||
1936 (!check_printjob_info(&desc,uLevel,str2)))
1939 if (!print_job_exists(jobid)) {
1940 errcode=NERR_JobNotFound;
1944 errcode = NERR_notsupported;
1948 /* change job place in the queue,
1949 data gives the new place */
1950 place = SVAL(data,0);
1951 if (print_job_set_place(jobid, place)) {
1952 errcode=NERR_Success;
1957 /* change print job name, data gives the name */
1958 if (print_job_set_name(jobid, data)) {
1959 errcode=NERR_Success;
1968 SSVALS(*rparam,0,errcode);
1969 SSVAL(*rparam,2,0); /* converter word */
1975 /****************************************************************************
1976 get info about the server
1977 ****************************************************************************/
1978 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1979 int mdrcnt,int mprcnt,
1980 char **rdata,char **rparam,
1981 int *rdata_len,int *rparam_len)
1983 char *str1 = param+2;
1984 char *str2 = skip_string(str1,1);
1985 char *p = skip_string(str2,1);
1986 int uLevel = SVAL(p,0);
1990 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1992 /* check it's a supported varient */
1993 if (!prefix_ok(str1,"WrLh")) return False;
1996 if (strcmp(str2,"B16") != 0) return False;
2000 if (strcmp(str2,"B16BBDz") != 0) return False;
2004 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2009 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2014 if (strcmp(str2,"DN") != 0) return False;
2018 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2021 default: return False;
2024 *rdata_len = mdrcnt;
2025 *rdata = REALLOC(*rdata,*rdata_len);
2028 p2 = p + struct_len;
2030 StrnCpy(p,local_machine,16);
2036 struct srv_info_struct *servers=NULL;
2039 uint32 servertype= lp_default_server_announce();
2041 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2043 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2044 for (i=0;i<count;i++)
2045 if (strequal(servers[i].name,local_machine))
2047 servertype = servers[i].type;
2048 pstrcpy(comment,servers[i].comment);
2051 if (servers) free(servers);
2053 SCVAL(p,0,lp_major_announce_version());
2054 SCVAL(p,1,lp_minor_announce_version());
2055 SIVAL(p,2,servertype);
2057 if (mdrcnt == struct_len) {
2060 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2061 standard_sub_conn(conn,comment);
2062 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2063 p2 = skip_string(p2,1);
2068 return False; /* not yet implemented */
2071 *rdata_len = PTR_DIFF(p2,*rdata);
2074 *rparam = REALLOC(*rparam,*rparam_len);
2075 SSVAL(*rparam,0,NERR_Success);
2076 SSVAL(*rparam,2,0); /* converter word */
2077 SSVAL(*rparam,4,*rdata_len);
2083 /****************************************************************************
2084 get info about the server
2085 ****************************************************************************/
2086 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2087 int mdrcnt,int mprcnt,
2088 char **rdata,char **rparam,
2089 int *rdata_len,int *rparam_len)
2091 char *str1 = param+2;
2092 char *str2 = skip_string(str1,1);
2093 char *p = skip_string(str2,1);
2095 extern pstring sesssetup_user;
2096 int level = SVAL(p,0);
2098 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2101 *rparam = REALLOC(*rparam,*rparam_len);
2103 /* check it's a supported varient */
2104 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2107 *rdata_len = mdrcnt + 1024;
2108 *rdata = REALLOC(*rdata,*rdata_len);
2110 SSVAL(*rparam,0,NERR_Success);
2111 SSVAL(*rparam,2,0); /* converter word */
2117 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2118 pstrcpy(p2,local_machine);
2120 p2 = skip_string(p2,1);
2123 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2124 pstrcpy(p2,sesssetup_user);
2125 p2 = skip_string(p2,1);
2128 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2129 pstrcpy(p2,global_myworkgroup);
2131 p2 = skip_string(p2,1);
2134 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2135 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2138 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2139 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2140 p2 = skip_string(p2,1);
2143 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2145 p2 = skip_string(p2,1);
2148 *rdata_len = PTR_DIFF(p2,*rdata);
2150 SSVAL(*rparam,4,*rdata_len);
2155 /****************************************************************************
2156 get info about a user
2158 struct user_info_11 {
2159 char usri11_name[21]; 0-20
2161 char *usri11_comment; 22-25
2162 char *usri11_usr_comment; 26-29
2163 unsigned short usri11_priv; 30-31
2164 unsigned long usri11_auth_flags; 32-35
2165 long usri11_password_age; 36-39
2166 char *usri11_homedir; 40-43
2167 char *usri11_parms; 44-47
2168 long usri11_last_logon; 48-51
2169 long usri11_last_logoff; 52-55
2170 unsigned short usri11_bad_pw_count; 56-57
2171 unsigned short usri11_num_logons; 58-59
2172 char *usri11_logon_server; 60-63
2173 unsigned short usri11_country_code; 64-65
2174 char *usri11_workstations; 66-69
2175 unsigned long usri11_max_storage; 70-73
2176 unsigned short usri11_units_per_week; 74-75
2177 unsigned char *usri11_logon_hours; 76-79
2178 unsigned short usri11_code_page; 80-81
2183 usri11_name specifies the user name for which information is retireved
2185 usri11_pad aligns the next data structure element to a word boundary
2187 usri11_comment is a null terminated ASCII comment
2189 usri11_user_comment is a null terminated ASCII comment about the user
2191 usri11_priv specifies the level of the privilege assigned to the user.
2192 The possible values are:
2194 Name Value Description
2195 USER_PRIV_GUEST 0 Guest privilege
2196 USER_PRIV_USER 1 User privilege
2197 USER_PRV_ADMIN 2 Administrator privilege
2199 usri11_auth_flags specifies the account operator privileges. The
2200 possible values are:
2202 Name Value Description
2203 AF_OP_PRINT 0 Print operator
2206 Leach, Naik [Page 28]
\r\f
2209 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2212 AF_OP_COMM 1 Communications operator
2213 AF_OP_SERVER 2 Server operator
2214 AF_OP_ACCOUNTS 3 Accounts operator
2217 usri11_password_age specifies how many seconds have elapsed since the
2218 password was last changed.
2220 usri11_home_dir points to a null terminated ASCII string that contains
2221 the path name of the user's home directory.
2223 usri11_parms points to a null terminated ASCII string that is set
2224 aside for use by applications.
2226 usri11_last_logon specifies the time when the user last logged on.
2227 This value is stored as the number of seconds elapsed since
2228 00:00:00, January 1, 1970.
2230 usri11_last_logoff specifies the time when the user last logged off.
2231 This value is stored as the number of seconds elapsed since
2232 00:00:00, January 1, 1970. A value of 0 means the last logoff
2235 usri11_bad_pw_count specifies the number of incorrect passwords
2236 entered since the last successful logon.
2238 usri11_log1_num_logons specifies the number of times this user has
2239 logged on. A value of -1 means the number of logons is unknown.
2241 usri11_logon_server points to a null terminated ASCII string that
2242 contains the name of the server to which logon requests are sent.
2243 A null string indicates logon requests should be sent to the
2246 usri11_country_code specifies the country code for the user's language
2249 usri11_workstations points to a null terminated ASCII string that
2250 contains the names of workstations the user may log on from.
2251 There may be up to 8 workstations, with the names separated by
2252 commas. A null strings indicates there are no restrictions.
2254 usri11_max_storage specifies the maximum amount of disk space the user
2255 can occupy. A value of 0xffffffff indicates there are no
2258 usri11_units_per_week specifies the equal number of time units into
2259 which a week is divided. This value must be equal to 168.
2261 usri11_logon_hours points to a 21 byte (168 bits) string that
2262 specifies the time during which the user can log on. Each bit
2263 represents one unique hour in a week. The first bit (bit 0, word
2264 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2268 Leach, Naik [Page 29]
\r\f
2271 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2274 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2275 are no restrictions.
2277 usri11_code_page specifies the code page for the user's language of
2280 All of the pointers in this data structure need to be treated
2281 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2282 to be ignored. The converter word returned in the parameters section
2283 needs to be subtracted from the lower 16 bits to calculate an offset
2284 into the return buffer where this ASCII string resides.
2286 There is no auxiliary data in the response.
2288 ****************************************************************************/
2290 #define usri11_name 0
2291 #define usri11_pad 21
2292 #define usri11_comment 22
2293 #define usri11_usr_comment 26
2294 #define usri11_full_name 30
2295 #define usri11_priv 34
2296 #define usri11_auth_flags 36
2297 #define usri11_password_age 40
2298 #define usri11_homedir 44
2299 #define usri11_parms 48
2300 #define usri11_last_logon 52
2301 #define usri11_last_logoff 56
2302 #define usri11_bad_pw_count 60
2303 #define usri11_num_logons 62
2304 #define usri11_logon_server 64
2305 #define usri11_country_code 68
2306 #define usri11_workstations 70
2307 #define usri11_max_storage 74
2308 #define usri11_units_per_week 78
2309 #define usri11_logon_hours 80
2310 #define usri11_code_page 84
2311 #define usri11_end 86
2313 #define USER_PRIV_GUEST 0
2314 #define USER_PRIV_USER 1
2315 #define USER_PRIV_ADMIN 2
2317 #define AF_OP_PRINT 0
2318 #define AF_OP_COMM 1
2319 #define AF_OP_SERVER 2
2320 #define AF_OP_ACCOUNTS 3
2323 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2324 int mdrcnt,int mprcnt,
2325 char **rdata,char **rparam,
2326 int *rdata_len,int *rparam_len)
2328 char *str1 = param+2;
2329 char *str2 = skip_string(str1,1);
2330 char *UserName = skip_string(str2,1);
2331 char *p = skip_string(UserName,1);
2332 int uLevel = SVAL(p,0);
2335 /* get NIS home of a previously validated user - simeon */
2336 /* With share level security vuid will always be zero.
2337 Don't depend on vuser being non-null !!. JRA */
2338 user_struct *vuser = get_valid_user_struct(vuid);
2340 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2341 vuser->user.unix_name));
2344 *rparam = REALLOC(*rparam,*rparam_len);
2346 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2348 /* check it's a supported variant */
2349 if (strcmp(str1,"zWrLh") != 0) return False;
2352 case 0: p2 = "B21"; break;
2353 case 1: p2 = "B21BB16DWzzWz"; break;
2354 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2355 case 10: p2 = "B21Bzzz"; break;
2356 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2357 default: return False;
2360 if (strcmp(p2,str2) != 0) return False;
2362 *rdata_len = mdrcnt + 1024;
2363 *rdata = REALLOC(*rdata,*rdata_len);
2365 SSVAL(*rparam,0,NERR_Success);
2366 SSVAL(*rparam,2,0); /* converter word */
2369 p2 = p + usri11_end;
2372 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2376 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2381 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2382 pstrcpy(p2,"Comment");
2383 p2 = skip_string(p2,1);
2385 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2386 pstrcpy(p2,"UserComment");
2387 p2 = skip_string(p2,1);
2389 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2390 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2391 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2392 p2 = skip_string(p2,1);
2395 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2397 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2398 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2399 SIVALS(p,usri11_password_age,-1); /* password age */
2400 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2401 pstrcpy(p2, lp_logon_home());
2402 p2 = skip_string(p2,1);
2403 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2405 p2 = skip_string(p2,1);
2406 SIVAL(p,usri11_last_logon,0); /* last logon */
2407 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2408 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2409 SSVALS(p,usri11_num_logons,-1); /* num logons */
2410 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2411 pstrcpy(p2,"\\\\*");
2412 p2 = skip_string(p2,1);
2413 SSVAL(p,usri11_country_code,0); /* country code */
2415 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2417 p2 = skip_string(p2,1);
2419 SIVALS(p,usri11_max_storage,-1); /* max storage */
2420 SSVAL(p,usri11_units_per_week,168); /* units per week */
2421 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2423 /* a simple way to get logon hours at all times. */
2425 SCVAL(p2,21,0); /* fix zero termination */
2426 p2 = skip_string(p2,1);
2428 SSVAL(p,usri11_code_page,0); /* code page */
2430 if (uLevel == 1 || uLevel == 2)
2432 memset(p+22,' ',16); /* password */
2433 SIVALS(p,38,-1); /* password age */
2435 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2436 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2437 pstrcpy(p2,lp_logon_home());
2438 p2 = skip_string(p2,1);
2439 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2441 SSVAL(p,52,0); /* flags */
2442 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2443 pstrcpy(p2,lp_logon_script());
2444 standard_sub_conn( conn, p2 );
2445 p2 = skip_string(p2,1);
2448 SIVAL(p,60,0); /* auth_flags */
2449 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2450 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2451 p2 = skip_string(p2,1);
2452 SIVAL(p,68,0); /* urs_comment */
2453 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2455 p2 = skip_string(p2,1);
2456 SIVAL(p,76,0); /* workstations */
2457 SIVAL(p,80,0); /* last_logon */
2458 SIVAL(p,84,0); /* last_logoff */
2459 SIVALS(p,88,-1); /* acct_expires */
2460 SIVALS(p,92,-1); /* max_storage */
2461 SSVAL(p,96,168); /* units_per_week */
2462 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2465 SSVALS(p,102,-1); /* bad_pw_count */
2466 SSVALS(p,104,-1); /* num_logons */
2467 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2468 pstrcpy(p2,"\\\\%L");
2469 standard_sub_conn(conn, p2);
2470 p2 = skip_string(p2,1);
2471 SSVAL(p,110,49); /* country_code */
2472 SSVAL(p,112,860); /* code page */
2476 *rdata_len = PTR_DIFF(p2,*rdata);
2478 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2483 /*******************************************************************
2484 get groups that a user is a member of
2485 ******************************************************************/
2486 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2487 int mdrcnt,int mprcnt,
2488 char **rdata,char **rparam,
2489 int *rdata_len,int *rparam_len)
2491 char *str1 = param+2;
2492 char *str2 = skip_string(str1,1);
2493 char *UserName = skip_string(str2,1);
2494 char *p = skip_string(UserName,1);
2495 int uLevel = SVAL(p,0);
2500 *rparam = REALLOC(*rparam,*rparam_len);
2502 /* check it's a supported varient */
2503 if (strcmp(str1,"zWrLeh") != 0) return False;
2505 case 0: p2 = "B21"; break;
2506 default: return False;
2508 if (strcmp(p2,str2) != 0) return False;
2510 *rdata_len = mdrcnt + 1024;
2511 *rdata = REALLOC(*rdata,*rdata_len);
2513 SSVAL(*rparam,0,NERR_Success);
2514 SSVAL(*rparam,2,0); /* converter word */
2518 /* XXXX we need a real SAM database some day */
2519 pstrcpy(p,"Users"); p += 21; count++;
2520 pstrcpy(p,"Domain Users"); p += 21; count++;
2521 pstrcpy(p,"Guests"); p += 21; count++;
2522 pstrcpy(p,"Domain Guests"); p += 21; count++;
2524 *rdata_len = PTR_DIFF(p,*rdata);
2526 SSVAL(*rparam,4,count); /* is this right?? */
2527 SSVAL(*rparam,6,count); /* is this right?? */
2533 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2534 int mdrcnt,int mprcnt,
2535 char **rdata,char **rparam,
2536 int *rdata_len,int *rparam_len)
2538 char *str1 = param+2;
2539 char *str2 = skip_string(str1,1);
2540 char *p = skip_string(str2,1);
2542 struct pack_desc desc;
2548 memset((char *)&desc,'\0',sizeof(desc));
2550 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2552 /* check it's a supported varient */
2553 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2554 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2555 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2557 desc.buflen = mdrcnt;
2558 desc.subformat = NULL;
2561 if (init_package(&desc,1,0))
2563 PACKI(&desc,"W",0); /* code */
2564 PACKS(&desc,"B21",name); /* eff. name */
2565 PACKS(&desc,"B",""); /* pad */
2567 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2568 PACKI(&desc,"D",0); /* auth flags XXX */
2569 PACKI(&desc,"W",0); /* num logons */
2570 PACKI(&desc,"W",0); /* bad pw count */
2571 PACKI(&desc,"D",0); /* last logon */
2572 PACKI(&desc,"D",-1); /* last logoff */
2573 PACKI(&desc,"D",-1); /* logoff time */
2574 PACKI(&desc,"D",-1); /* kickoff time */
2575 PACKI(&desc,"D",0); /* password age */
2576 PACKI(&desc,"D",0); /* password can change */
2577 PACKI(&desc,"D",-1); /* password must change */
2580 fstrcpy(mypath,"\\\\");
2581 fstrcat(mypath,local_machine);
2583 PACKS(&desc,"z",mypath); /* computer */
2585 PACKS(&desc,"z",global_myworkgroup);/* domain */
2587 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2588 /* made sure all macros are fully substituted and available */
2590 pstring logon_script;
2591 pstrcpy(logon_script,lp_logon_script());
2592 standard_sub_conn( conn, logon_script );
2593 PACKS(&desc,"z", logon_script); /* script path */
2595 /* End of JHT mods */
2597 PACKI(&desc,"D",0x00000000); /* reserved */
2600 *rdata_len = desc.usedlen;
2602 *rparam = REALLOC(*rparam,*rparam_len);
2603 SSVALS(*rparam,0,desc.errcode);
2605 SSVAL(*rparam,4,desc.neededlen);
2607 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2612 /****************************************************************************
2613 api_WAccessGetUserPerms
2614 ****************************************************************************/
2615 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2616 int mdrcnt,int mprcnt,
2617 char **rdata,char **rparam,
2618 int *rdata_len,int *rparam_len)
2620 char *str1 = param+2;
2621 char *str2 = skip_string(str1,1);
2622 char *user = skip_string(str2,1);
2623 char *resource = skip_string(user,1);
2625 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2627 /* check it's a supported varient */
2628 if (strcmp(str1,"zzh") != 0) return False;
2629 if (strcmp(str2,"") != 0) return False;
2632 *rparam = REALLOC(*rparam,*rparam_len);
2633 SSVALS(*rparam,0,0); /* errorcode */
2634 SSVAL(*rparam,2,0); /* converter word */
2635 SSVAL(*rparam,4,0x7f); /* permission flags */
2640 /****************************************************************************
2641 api_WPrintJobEnumerate
2642 ****************************************************************************/
2643 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2644 int mdrcnt,int mprcnt,
2645 char **rdata,char **rparam,
2646 int *rdata_len,int *rparam_len)
2648 char *str1 = param+2;
2649 char *str2 = skip_string(str1,1);
2650 char *p = skip_string(str2,1);
2656 struct pack_desc desc;
2657 print_queue_struct *queue=NULL;
2658 print_status_struct status;
2662 memset((char *)&desc,'\0',sizeof(desc));
2663 memset((char *)&status,'\0',sizeof(status));
2665 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2667 /* check it's a supported varient */
2668 if (strcmp(str1,"WWrLh") != 0) return False;
2669 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2672 snum = print_job_snum(job);
2674 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2676 count = print_queue_status(snum,&queue,&status);
2677 for (i = 0; i < count; i++) {
2678 if (queue[i].job == job) break;
2680 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2682 desc.buflen = mdrcnt;
2684 if (init_package(&desc,1,0)) {
2686 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2687 *rdata_len = desc.usedlen;
2690 desc.errcode = NERR_JobNotFound;
2696 *rparam = REALLOC(*rparam,*rparam_len);
2697 SSVALS(*rparam,0,desc.errcode);
2699 SSVAL(*rparam,4,desc.neededlen);
2701 if (queue) free(queue);
2703 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2707 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2708 int mdrcnt,int mprcnt,
2709 char **rdata,char **rparam,
2710 int *rdata_len,int *rparam_len)
2712 char *str1 = param+2;
2713 char *str2 = skip_string(str1,1);
2714 char *p = skip_string(str2,1);
2720 struct pack_desc desc;
2721 print_queue_struct *queue=NULL;
2722 print_status_struct status;
2724 memset((char *)&desc,'\0',sizeof(desc));
2725 memset((char *)&status,'\0',sizeof(status));
2727 p = skip_string(p,1);
2730 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2732 /* check it's a supported varient */
2733 if (strcmp(str1,"zWrLeh") != 0) return False;
2734 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2735 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2737 snum = lp_servicenumber(name);
2738 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2739 int pnum = lp_servicenumber(PRINTERS_NAME);
2741 lp_add_printer(name,pnum);
2742 snum = lp_servicenumber(name);
2746 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2748 count = print_queue_status(snum,&queue,&status);
2749 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2751 desc.buflen = mdrcnt;
2753 if (init_package(&desc,count,0)) {
2755 for (i = 0; i < count; i++) {
2756 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2757 if (desc.errcode == NERR_Success) succnt = i+1;
2761 *rdata_len = desc.usedlen;
2764 *rparam = REALLOC(*rparam,*rparam_len);
2765 SSVALS(*rparam,0,desc.errcode);
2767 SSVAL(*rparam,4,succnt);
2768 SSVAL(*rparam,6,count);
2770 if (queue) free(queue);
2772 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2776 static int check_printdest_info(struct pack_desc* desc,
2777 int uLevel, char* id)
2779 desc->subformat = NULL;
2781 case 0: desc->format = "B9"; break;
2782 case 1: desc->format = "B9B21WWzW"; break;
2783 case 2: desc->format = "z"; break;
2784 case 3: desc->format = "zzzWWzzzWW"; break;
2785 default: return False;
2787 if (strcmp(desc->format,id) != 0) return False;
2791 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2792 struct pack_desc* desc)
2795 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2796 buf[sizeof(buf)-1] = 0;
2799 PACKS(desc,"B9",buf); /* szName */
2801 PACKS(desc,"B21",""); /* szUserName */
2802 PACKI(desc,"W",0); /* uJobId */
2803 PACKI(desc,"W",0); /* fsStatus */
2804 PACKS(desc,"z",""); /* pszStatus */
2805 PACKI(desc,"W",0); /* time */
2808 if (uLevel == 2 || uLevel == 3) {
2809 PACKS(desc,"z",buf); /* pszPrinterName */
2811 PACKS(desc,"z",""); /* pszUserName */
2812 PACKS(desc,"z",""); /* pszLogAddr */
2813 PACKI(desc,"W",0); /* uJobId */
2814 PACKI(desc,"W",0); /* fsStatus */
2815 PACKS(desc,"z",""); /* pszStatus */
2816 PACKS(desc,"z",""); /* pszComment */
2817 PACKS(desc,"z","NULL"); /* pszDrivers */
2818 PACKI(desc,"W",0); /* time */
2819 PACKI(desc,"W",0); /* pad1 */
2824 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2825 int mdrcnt,int mprcnt,
2826 char **rdata,char **rparam,
2827 int *rdata_len,int *rparam_len)
2829 char *str1 = param+2;
2830 char *str2 = skip_string(str1,1);
2831 char *p = skip_string(str2,1);
2832 char* PrinterName = p;
2834 struct pack_desc desc;
2837 memset((char *)&desc,'\0',sizeof(desc));
2839 p = skip_string(p,1);
2842 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2844 /* check it's a supported varient */
2845 if (strcmp(str1,"zWrLh") != 0) return False;
2846 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2848 snum = lp_servicenumber(PrinterName);
2849 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2850 int pnum = lp_servicenumber(PRINTERS_NAME);
2852 lp_add_printer(PrinterName,pnum);
2853 snum = lp_servicenumber(PrinterName);
2859 desc.errcode = NERR_DestNotFound;
2863 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2865 desc.buflen = mdrcnt;
2866 if (init_package(&desc,1,0)) {
2867 fill_printdest_info(conn,snum,uLevel,&desc);
2869 *rdata_len = desc.usedlen;
2873 *rparam = REALLOC(*rparam,*rparam_len);
2874 SSVALS(*rparam,0,desc.errcode);
2876 SSVAL(*rparam,4,desc.neededlen);
2878 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2882 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2883 int mdrcnt,int mprcnt,
2884 char **rdata,char **rparam,
2885 int *rdata_len,int *rparam_len)
2887 char *str1 = param+2;
2888 char *str2 = skip_string(str1,1);
2889 char *p = skip_string(str2,1);
2893 struct pack_desc desc;
2894 int services = lp_numservices();
2896 memset((char *)&desc,'\0',sizeof(desc));
2900 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2902 /* check it's a supported varient */
2903 if (strcmp(str1,"WrLeh") != 0) return False;
2904 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2907 for (i = 0; i < services; i++)
2908 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2911 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2913 desc.buflen = mdrcnt;
2914 if (init_package(&desc,queuecnt,0)) {
2917 for (i = 0; i < services; i++) {
2918 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2919 fill_printdest_info(conn,i,uLevel,&desc);
2921 if (desc.errcode == NERR_Success) succnt = n;
2926 *rdata_len = desc.usedlen;
2929 *rparam = REALLOC(*rparam,*rparam_len);
2930 SSVALS(*rparam,0,desc.errcode);
2932 SSVAL(*rparam,4,succnt);
2933 SSVAL(*rparam,6,queuecnt);
2935 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2939 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2940 int mdrcnt,int mprcnt,
2941 char **rdata,char **rparam,
2942 int *rdata_len,int *rparam_len)
2944 char *str1 = param+2;
2945 char *str2 = skip_string(str1,1);
2946 char *p = skip_string(str2,1);
2949 struct pack_desc desc;
2951 memset((char *)&desc,'\0',sizeof(desc));
2955 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2957 /* check it's a supported varient */
2958 if (strcmp(str1,"WrLeh") != 0) return False;
2959 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2961 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2963 desc.buflen = mdrcnt;
2964 if (init_package(&desc,1,0)) {
2965 PACKS(&desc,"B41","NULL");
2968 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2970 *rdata_len = desc.usedlen;
2973 *rparam = REALLOC(*rparam,*rparam_len);
2974 SSVALS(*rparam,0,desc.errcode);
2976 SSVAL(*rparam,4,succnt);
2979 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2983 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2984 int mdrcnt,int mprcnt,
2985 char **rdata,char **rparam,
2986 int *rdata_len,int *rparam_len)
2988 char *str1 = param+2;
2989 char *str2 = skip_string(str1,1);
2990 char *p = skip_string(str2,1);
2993 struct pack_desc desc;
2995 memset((char *)&desc,'\0',sizeof(desc));
2999 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3001 /* check it's a supported varient */
3002 if (strcmp(str1,"WrLeh") != 0) return False;
3003 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3005 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3007 desc.buflen = mdrcnt;
3009 if (init_package(&desc,1,0)) {
3010 PACKS(&desc,"B13","lpd");
3013 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3015 *rdata_len = desc.usedlen;
3018 *rparam = REALLOC(*rparam,*rparam_len);
3019 SSVALS(*rparam,0,desc.errcode);
3021 SSVAL(*rparam,4,succnt);
3024 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3028 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3029 int mdrcnt,int mprcnt,
3030 char **rdata,char **rparam,
3031 int *rdata_len,int *rparam_len)
3033 char *str1 = param+2;
3034 char *str2 = skip_string(str1,1);
3035 char *p = skip_string(str2,1);
3038 struct pack_desc desc;
3040 memset((char *)&desc,'\0',sizeof(desc));
3044 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3046 /* check it's a supported varient */
3047 if (strcmp(str1,"WrLeh") != 0) return False;
3048 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3050 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3051 memset((char *)&desc,'\0',sizeof(desc));
3053 desc.buflen = mdrcnt;
3055 if (init_package(&desc,1,0)) {
3056 PACKS(&desc,"B13","lp0");
3059 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3061 *rdata_len = desc.usedlen;
3064 *rparam = REALLOC(*rparam,*rparam_len);
3065 SSVALS(*rparam,0,desc.errcode);
3067 SSVAL(*rparam,4,succnt);
3070 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3074 /****************************************************************************
3075 The buffer was too small
3076 ****************************************************************************/
3078 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3079 int mdrcnt,int mprcnt,
3080 char **rdata,char **rparam,
3081 int *rdata_len,int *rparam_len)
3083 *rparam_len = MIN(*rparam_len,mprcnt);
3084 *rparam = REALLOC(*rparam,*rparam_len);
3088 SSVAL(*rparam,0,NERR_BufTooSmall);
3090 DEBUG(3,("Supplied buffer too small in API command\n"));
3096 /****************************************************************************
3097 The request is not supported
3098 ****************************************************************************/
3100 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3101 int mdrcnt,int mprcnt,
3102 char **rdata,char **rparam,
3103 int *rdata_len,int *rparam_len)
3106 *rparam = REALLOC(*rparam,*rparam_len);
3110 SSVAL(*rparam,0,NERR_notsupported);
3111 SSVAL(*rparam,2,0); /* converter word */
3113 DEBUG(3,("Unsupported API command\n"));
3125 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3126 int,int,char **,char **,int *,int *);
3128 } api_commands[] = {
3129 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3130 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3131 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3132 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3133 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3134 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3135 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3136 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3137 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3138 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3139 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3140 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3141 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3142 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3143 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3144 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3145 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3146 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3147 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3148 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3149 {"NetServerEnum", 104, api_RNetServerEnum,0},
3150 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3151 {"SetUserPassword", 115, api_SetUserPassword,0},
3152 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3153 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3154 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3155 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3156 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3157 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3158 {NULL, -1, api_Unsupported,0}};
3161 /****************************************************************************
3162 Handle remote api calls
3163 ****************************************************************************/
3165 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3166 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3170 char *rparam = NULL;
3177 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3181 api_command = SVAL(params,0);
3183 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3186 skip_string(params+2,1),
3187 tdscnt,tpscnt,mdrcnt,mprcnt));
3189 for (i=0;api_commands[i].name;i++) {
3190 if (api_commands[i].id == api_command && api_commands[i].fn) {
3191 DEBUG(3,("Doing %s\n",api_commands[i].name));
3196 rdata = (char *)malloc(1024);
3198 memset(rdata,'\0',1024);
3200 rparam = (char *)malloc(1024);
3202 memset(rparam,'\0',1024);
3204 if(!rdata || !rparam) {
3205 DEBUG(0,("api_reply: malloc fail !\n"));
3209 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3210 &rdata,&rparam,&rdata_len,&rparam_len);
3213 if (rdata_len > mdrcnt ||
3214 rparam_len > mprcnt) {
3215 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3216 &rdata,&rparam,&rdata_len,&rparam_len);
3219 /* if we get False back then it's actually unsupported */
3221 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3222 &rdata,&rparam,&rdata_len,&rparam_len);
3224 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);