2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
37 extern int DEBUGLEVEL;
39 extern files_struct Files[];
40 extern connection_struct Connections[];
42 extern fstring local_machine;
43 extern fstring global_myworkgroup;
45 #define NERR_Success 0
46 #define NERR_badpass 86
47 #define NERR_notsupported 50
49 #define NERR_BASE (2100)
50 #define NERR_BufTooSmall (NERR_BASE+23)
51 #define NERR_JobNotFound (NERR_BASE+51)
52 #define NERR_DestNotFound (NERR_BASE+52)
53 #define ERROR_INVALID_LEVEL 124
54 #define ERROR_MORE_DATA 234
56 #define ACCESS_READ 0x01
57 #define ACCESS_WRITE 0x02
58 #define ACCESS_CREATE 0x04
60 #define SHPWLEN 8 /* share password length */
61 #define NNLEN 12 /* 8.3 net name length */
62 #define SNLEN 15 /* service name length */
63 #define QNLEN 12 /* queue name maximum length */
66 extern int oplock_sock;
67 extern int smb_read_error;
69 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
70 int mdrcnt,int mprcnt,
71 char **rdata,char **rparam,
72 int *rdata_len,int *rparam_len);
73 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
74 int mdrcnt,int mprcnt,
75 char **rdata,char **rparam,
76 int *rdata_len,int *rparam_len);
79 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
84 if (!src || !dst || !n || !(*dst)) return(0);
86 StrnCpy(buf,src,sizeof(buf)/2);
87 string_sub(buf,"%S",lp_servicename(snum));
88 standard_sub(cnum,buf);
96 static int CopyAndAdvance(char** dst, char* src, int* n)
99 if (!src || !dst || !n || !(*dst)) return(0);
100 StrnCpy(*dst,src,*n);
101 l = strlen(*dst) + 1;
107 static int StrlenExpanded(int cnum, int snum, char* s)
111 StrnCpy(buf,s,sizeof(buf)/2);
112 string_sub(buf,"%S",lp_servicename(snum));
113 standard_sub(cnum,buf);
114 return strlen(buf) + 1;
117 static char* Expand(int cnum, int snum, char* s)
120 if (!s) return(NULL);
121 StrnCpy(buf,s,sizeof(buf)/2);
122 string_sub(buf,"%S",lp_servicename(snum));
123 standard_sub(cnum,buf);
127 /*******************************************************************
128 check a API string for validity when we only need to check the prefix
129 ******************************************************************/
130 static BOOL prefix_ok(char *str,char *prefix)
132 return(strncmp(str,prefix,strlen(prefix)) == 0);
135 /*******************************************************************
136 copies parameters and data, as needed, into the smb buffer
138 *both* the data and params sections should be aligned. this
139 is fudged in the rpc pipes by
140 at present, only the data section is. this may be a possible
141 cause of some of the ipc problems being experienced. lkcl26dec97
143 ******************************************************************/
144 static void copy_trans_params_and_data(char *outbuf, int align,
145 struct mem_buf *rparam, struct mem_buf *rdata,
146 int param_offset, int data_offset,
147 int param_len, int data_len)
149 char *copy_into = smb_buf(outbuf);
151 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
152 param_offset, param_offset + param_len,
153 data_offset , data_offset + data_len));
155 if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
156 copy_into += param_len + align;
157 if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
160 /****************************************************************************
162 ****************************************************************************/
163 static void send_trans_reply(char *outbuf,
164 struct mem_buf *rdata,
165 struct mem_buf *rparam,
166 uint16 *setup, int lsetup, int max_data_ret)
169 int this_ldata,this_lparam;
170 int tot_data=0,tot_param=0;
173 int ldata = rdata ? mem_buf_len(rdata ) : 0;
174 int lparam = rparam ? mem_buf_len(rparam) : 0;
176 BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
178 if (buffer_too_large)
180 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
181 ldata = max_data_ret;
184 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
185 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
187 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
188 /* if you don't want Net Monitor to decode your packets, do this!!! */
189 align = ((this_lparam+1)%4);
191 align = (this_lparam%4);
194 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
196 if (buffer_too_large)
198 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
199 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
200 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
203 copy_trans_params_and_data(outbuf, align,
205 tot_param , tot_data,
206 this_lparam, this_ldata);
208 SSVAL(outbuf,smb_vwv0,lparam);
209 SSVAL(outbuf,smb_vwv1,ldata);
210 SSVAL(outbuf,smb_vwv3,this_lparam);
211 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
212 SSVAL(outbuf,smb_vwv5,0);
213 SSVAL(outbuf,smb_vwv6,this_ldata);
214 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
215 SSVAL(outbuf,smb_vwv8,0);
216 SSVAL(outbuf,smb_vwv9,lsetup);
218 for (i=0;i<lsetup;i++)
220 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
224 send_smb(Client,outbuf);
226 tot_data = this_ldata;
227 tot_param = this_lparam;
229 while (tot_data < ldata || tot_param < lparam)
231 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
232 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
234 align = (this_lparam%4);
236 set_message(outbuf,10,this_ldata+this_lparam+align,False);
238 copy_trans_params_and_data(outbuf, align,
240 tot_param , tot_data,
241 this_lparam, this_ldata);
243 SSVAL(outbuf,smb_vwv3,this_lparam);
244 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
245 SSVAL(outbuf,smb_vwv5,tot_param);
246 SSVAL(outbuf,smb_vwv6,this_ldata);
247 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
248 SSVAL(outbuf,smb_vwv8,tot_data);
249 SSVAL(outbuf,smb_vwv9,0);
252 send_smb(Client,outbuf);
254 tot_data += this_ldata;
255 tot_param += this_lparam;
260 char* format; /* formatstring for structure */
261 char* subformat; /* subformat for structure */
262 char* base; /* baseaddress of buffer */
263 int buflen; /* remaining size for fixed part; on init: length of base */
264 int subcount; /* count of substructures */
265 char* structbuf; /* pointer into buffer for remaining fixed part */
266 int stringlen; /* remaining size for variable part */
267 char* stringbuf; /* pointer into buffer for remaining variable part */
268 int neededlen; /* total needed size */
269 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
270 char* curpos; /* current position; pointer into format or subformat */
274 static int get_counter(char** p)
277 if (!p || !(*p)) return(1);
278 if (!isdigit(**p)) return 1;
282 n = 10 * n + (i - '0');
289 static int getlen(char* p)
295 case 'W': /* word (2 byte) */
298 case 'N': /* count of substructures (word) at end */
301 case 'D': /* double word (4 byte) */
302 case 'z': /* offset to zero terminated string (4 byte) */
303 case 'l': /* offset to user data (4 byte) */
306 case 'b': /* offset to data (with counter) (4 byte) */
310 case 'B': /* byte (with optional counter) */
311 n += get_counter(&p);
318 static BOOL init_package(struct pack_desc* p, int count, int subcount)
323 if (!p->format || !p->base) return(False);
325 i = count * getlen(p->format);
326 if (p->subformat) i += subcount * getlen(p->subformat);
327 p->structbuf = p->base;
331 p->curpos = p->format;
335 p->errcode = ERROR_MORE_DATA;
338 p->errcode = NERR_Success;
341 p->stringbuf = p->base + i;
343 return(p->errcode == NERR_Success);
347 static int package(struct pack_desc* p, ...)
350 static int package(va_alist)
356 int needed=0, stringneeded;
358 int is_string=0, stringused;
365 p = va_arg(args,struct pack_desc *);
370 p->curpos = p->format;
372 p->curpos = p->subformat;
377 str = va_arg(args,char*);
378 if (strncmp(str,p->curpos,strlen(str)) != 0) {
379 DEBUG(2,("type error in package: %s instead of %*s\n",str,
380 strlen(str),p->curpos));
390 if (!p->curpos) return(0);
392 switch( *p->curpos++ ) {
393 case 'W': /* word (2 byte) */
395 temp = va_arg(args,int);
396 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
398 case 'N': /* count of substructures (word) at end */
400 p->subcount = va_arg(args,int);
401 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
403 case 'D': /* double word (4 byte) */
405 temp = va_arg(args,int);
406 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
408 case 'B': /* byte (with optional counter) */
409 needed = get_counter(&p->curpos);
411 char *s = va_arg(args,char*);
412 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
415 case 'z': /* offset to zero terminated string (4 byte) */
416 str = va_arg(args,char*);
417 stringneeded = (str ? strlen(str)+1 : 0);
420 case 'l': /* offset to user data (4 byte) */
421 str = va_arg(args,char*);
422 stringneeded = va_arg(args,int);
425 case 'b': /* offset to data (with counter) (4 byte) */
426 str = va_arg(args,char*);
427 stringneeded = get_counter(&p->curpos);
432 if (stringneeded >= 0) {
434 if (p->buflen >= needed) {
435 stringused = stringneeded;
436 if (stringused > p->stringlen) {
437 stringused = (is_string ? p->stringlen : 0);
438 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
441 SIVAL(p->structbuf,0,0);
443 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
444 memcpy(p->stringbuf,str?str:"",stringused);
445 if (is_string) p->stringbuf[stringused-1] = '\0';
446 p->stringbuf += stringused;
447 p->stringlen -= stringused;
448 p->usedlen += stringused;
451 p->neededlen += stringneeded;
453 p->neededlen += needed;
454 if (p->buflen >= needed) {
455 p->structbuf += needed;
457 p->usedlen += needed;
460 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
466 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
467 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
469 #define PACK(desc,t,v) package(desc,v)
470 #define PACKl(desc,t,v,l) package(desc,v,l)
473 static void PACKI(struct pack_desc* desc,char *t,int v)
478 static void PACKS(struct pack_desc* desc,char *t,char *v)
484 /****************************************************************************
486 ****************************************************************************/
488 static void PackDriverData(struct pack_desc* desc)
490 char drivdata[4+4+32];
491 SIVAL(drivdata,0,sizeof drivdata); /* cb */
492 SIVAL(drivdata,4,1000); /* lVersion */
493 memset(drivdata+8,0,32); /* szDeviceName */
494 strcpy(drivdata+8,"NULL");
495 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
498 static int check_printq_info(struct pack_desc* desc,
499 int uLevel, char *id1, char *id2)
501 desc->subformat = NULL;
504 desc->format = "B13";
507 desc->format = "B13BWWWzzzzzWW";
510 desc->format = "B13BWWWzzzzzWN";
511 desc->subformat = "WB21BB16B10zWWzDDz";
514 desc->format = "zWWWWzzzzWWzzl";
517 desc->format = "zWWWWzzzzWNzzl";
518 desc->subformat = "WWzWWDDzz";
524 desc->format = "WzzzzzzzzN";
525 desc->subformat = "z";
527 default: return False;
529 if (strcmp(desc->format,id1) != 0) return False;
530 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
534 static void fill_printjob_info(int cnum, int snum, int uLevel,
535 struct pack_desc* desc,
536 print_queue_struct* queue, int n)
538 time_t t = queue->time;
540 /* the client expects localtime */
543 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
545 PACKS(desc,"B21",queue->user); /* szUserName */
546 PACKS(desc,"B",""); /* pad */
547 PACKS(desc,"B16",""); /* szNotifyName */
548 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
549 PACKS(desc,"z",""); /* pszParms */
550 PACKI(desc,"W",n+1); /* uPosition */
551 PACKI(desc,"W",queue->status); /* fsStatus */
552 PACKS(desc,"z",""); /* pszStatus */
553 PACKI(desc,"D",t); /* ulSubmitted */
554 PACKI(desc,"D",queue->size); /* ulSize */
555 PACKS(desc,"z",queue->file); /* pszComment */
557 if (uLevel == 2 || uLevel == 3) {
558 PACKI(desc,"W",queue->priority); /* uPriority */
559 PACKS(desc,"z",queue->user); /* pszUserName */
560 PACKI(desc,"W",n+1); /* uPosition */
561 PACKI(desc,"W",queue->status); /* fsStatus */
562 PACKI(desc,"D",t); /* ulSubmitted */
563 PACKI(desc,"D",queue->size); /* ulSize */
564 PACKS(desc,"z","Samba"); /* pszComment */
565 PACKS(desc,"z",queue->file); /* pszDocument */
567 PACKS(desc,"z",""); /* pszNotifyName */
568 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
569 PACKS(desc,"z",""); /* pszParms */
570 PACKS(desc,"z",""); /* pszStatus */
571 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
572 PACKS(desc,"z","lpd"); /* pszQProcName */
573 PACKS(desc,"z",""); /* pszQProcParms */
574 PACKS(desc,"z","NULL"); /* pszDriverName */
575 PackDriverData(desc); /* pDriverData */
576 PACKS(desc,"z",""); /* pszPrinterName */
581 static void fill_printq_info(int cnum, int snum, int uLevel,
582 struct pack_desc* desc,
583 int count, print_queue_struct* queue,
584 print_status_struct* status)
589 PACKS(desc,"B13",SERVICE(snum));
594 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
598 if (uLevel == 1 || uLevel == 2) {
599 PACKS(desc,"B",""); /* alignment */
600 PACKI(desc,"W",5); /* priority */
601 PACKI(desc,"W",0); /* start time */
602 PACKI(desc,"W",0); /* until time */
603 PACKS(desc,"z",""); /* pSepFile */
604 PACKS(desc,"z","lpd"); /* pPrProc */
605 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
606 PACKS(desc,"z",""); /* pParms */
608 PACKS(desc,"z","UNKNOWN PRINTER");
609 PACKI(desc,"W",LPSTAT_ERROR);
611 else if (!status || !status->message[0]) {
612 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
613 PACKI(desc,"W",LPSTAT_OK); /* status */
615 PACKS(desc,"z",status->message);
616 PACKI(desc,"W",status->status); /* status */
618 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
620 if (uLevel == 3 || uLevel == 4) {
621 PACKI(desc,"W",5); /* uPriority */
622 PACKI(desc,"W",0); /* uStarttime */
623 PACKI(desc,"W",0); /* uUntiltime */
624 PACKI(desc,"W",5); /* pad1 */
625 PACKS(desc,"z",""); /* pszSepFile */
626 PACKS(desc,"z","WinPrint"); /* pszPrProc */
627 PACKS(desc,"z",""); /* pszParms */
628 if (!status || !status->message[0]) {
629 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
630 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
632 PACKS(desc,"z",status->message); /* pszComment */
633 PACKI(desc,"W",status->status); /* fsStatus */
635 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
636 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
637 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
638 PackDriverData(desc); /* pDriverData */
640 if (uLevel == 2 || uLevel == 4) {
642 for (i=0;i<count;i++)
643 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
648 pstring tok,driver,datafile,langmon,helpfile,datatype;
653 strcpy(fname,lp_driverfile());
656 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
657 desc->errcode=NERR_notsupported;
661 p=(char *)malloc(8192*sizeof(char));
662 bzero(p, 8192*sizeof(char));
665 /* lookup the long printer driver name in the file description */
666 while (f && !feof(f) && !ok)
668 p = q; /* reset string pointer */
671 if (next_token(&p,tok,":") &&
672 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
673 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
678 /* driver file name */
679 if (ok && !next_token(&p,driver,":")) ok = 0;
681 if (ok && !next_token(&p,datafile,":")) ok = 0;
683 * for the next tokens - which may be empty - I have to check for empty
684 * tokens first because the next_token function will skip all empty
692 } else if (!next_token(&p,helpfile,":")) ok = 0;
696 /* language monitor */
700 } else if (!next_token(&p,langmon,":")) ok = 0;
703 /* default data type */
704 if (ok && !next_token(&p,datatype,":")) ok = 0;
707 PACKI(desc,"W",0x0400); /* don't know */
708 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
709 PACKS(desc,"z",driver); /* Driverfile Name */
710 PACKS(desc,"z",datafile); /* Datafile name */
711 PACKS(desc,"z",langmon); /* language monitor */
712 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
713 PACKS(desc,"z",datatype); /* default data type */
714 PACKS(desc,"z",helpfile); /* helpfile name */
715 PACKS(desc,"z",driver); /* driver name */
716 DEBUG(3,("Driver:%s:\n",driver));
717 DEBUG(3,("Data File:%s:\n",datafile));
718 DEBUG(3,("Language Monitor:%s:\n",langmon));
719 DEBUG(3,("Data Type:%s:\n",datatype));
720 DEBUG(3,("Help File:%s:\n",helpfile));
721 PACKI(desc,"N",count); /* number of files to copy */
722 for (i=0;i<count;i++)
724 /* no need to check return value here - it was already tested in
725 * get_printerdrivernumber
727 next_token(&p,tok,",");
728 PACKS(desc,"z",tok); /* driver files to copy */
729 DEBUG(3,("file:%s:\n",tok));
732 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
733 SERVICE(snum),count));
735 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
736 desc->errcode=NERR_notsupported;
742 /* This function returns the number of files for a given driver */
743 int get_printerdrivernumber(int snum)
751 strcpy(fname,lp_driverfile());
753 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
756 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
760 p=(char *)malloc(8192*sizeof(char));
761 q=p; /* need it to free memory because p change ! */
763 /* lookup the long printer driver name in the file description */
764 while (!feof(f) && !ok)
766 p = q; /* reset string pointer */
768 if (next_token(&p,tok,":") &&
769 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
778 if (*p++ == ':') i--;
783 /* count the number of files */
784 while (next_token(&p,tok,","))
792 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
793 int mdrcnt,int mprcnt,
794 char **rdata,char **rparam,
795 int *rdata_len,int *rparam_len)
797 char *str1 = param+2;
798 char *str2 = skip_string(str1,1);
799 char *p = skip_string(str2,1);
805 struct pack_desc desc;
806 print_queue_struct *queue=NULL;
807 print_status_struct status;
809 bzero(&status,sizeof(status));
810 bzero(&desc,sizeof(desc));
812 p = skip_string(p,1);
817 /* remove any trailing username */
818 if ((p = strchr(QueueName,'%'))) *p = 0;
820 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
822 /* check it's a supported varient */
823 if (!prefix_ok(str1,"zWrLh")) return False;
824 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
826 snum = lp_servicenumber(QueueName);
827 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
828 int pnum = lp_servicenumber(PRINTERS_NAME);
830 lp_add_printer(QueueName,pnum);
831 snum = lp_servicenumber(QueueName);
835 if (snum < 0 || !VALID_SNUM(snum)) return(False);
839 count = get_printerdrivernumber(snum);
840 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
843 count = get_printqueue(snum,cnum,&queue,&status);
845 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
847 desc.buflen = mdrcnt;
848 if (init_package(&desc,1,count)) {
849 desc.subcount = count;
850 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
853 *rdata_len = desc.usedlen;
856 *rparam = REALLOC(*rparam,*rparam_len);
857 SSVALS(*rparam,0,desc.errcode);
859 SSVAL(*rparam,4,desc.neededlen);
861 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
863 if (queue) free(queue);
869 /****************************************************************************
870 view list of all print jobs on all queues
871 ****************************************************************************/
872 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
873 int mdrcnt, int mprcnt,
874 char **rdata, char** rparam,
875 int *rdata_len, int *rparam_len)
877 char *param_format = param+2;
878 char *output_format1 = skip_string(param_format,1);
879 char *p = skip_string(output_format1,1);
880 int uLevel = SVAL(p,0);
881 char *output_format2 = p + 4;
882 int services = lp_numservices();
884 struct pack_desc desc;
885 print_queue_struct **queue = NULL;
886 print_status_struct *status = NULL;
887 int* subcntarr = NULL;
888 int queuecnt, subcnt=0, succnt=0;
890 bzero(&desc,sizeof(desc));
892 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
894 if (!prefix_ok(param_format,"WrLeh")) return False;
895 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
898 for (i = 0; i < services; i++)
899 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
902 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
903 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
904 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
905 memset(status,0,queuecnt*sizeof(print_status_struct));
906 subcntarr = (int*)malloc(queuecnt*sizeof(int));
909 for (i = 0; i < services; i++)
910 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
911 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
912 subcnt += subcntarr[n];
916 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
918 desc.buflen = mdrcnt;
920 if (init_package(&desc,queuecnt,subcnt)) {
923 for (i = 0; i < services; i++)
924 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
925 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
927 if (desc.errcode == NERR_Success) succnt = n;
931 if (subcntarr) free(subcntarr);
933 *rdata_len = desc.usedlen;
935 *rparam = REALLOC(*rparam,*rparam_len);
936 SSVALS(*rparam,0,desc.errcode);
938 SSVAL(*rparam,4,succnt);
939 SSVAL(*rparam,6,queuecnt);
941 for (i = 0; i < queuecnt; i++) {
942 if (queue && queue[i]) free(queue[i]);
945 if (queue) free(queue);
946 if (status) free(status);
951 /****************************************************************************
952 get info level for a server list query
953 ****************************************************************************/
954 static BOOL check_server_info(int uLevel, char* id)
958 if (strcmp(id,"B16") != 0) return False;
961 if (strcmp(id,"B16BBDz") != 0) return False;
969 struct srv_info_struct
979 /*******************************************************************
980 get server info lists from the files saved by nmbd. Return the
982 ******************************************************************/
983 static int get_server_info(uint32 servertype,
984 struct srv_info_struct **servers,
992 BOOL local_list_only;
994 pstrcpy(fname,lp_lockdir());
995 trim_string(fname,NULL,"/");
997 strcat(fname,SERVER_LIST);
999 f = fopen(fname,"r");
1002 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1006 /* request for everything is code for request all servers */
1007 if (servertype == SV_TYPE_ALL)
1008 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1010 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1012 DEBUG(4,("Servertype search: %8x\n",servertype));
1017 struct srv_info_struct *s;
1022 fgets(line,sizeof(line)-1,f);
1023 if (!*line) continue;
1025 if (count == alloced) {
1027 (*servers) = (struct srv_info_struct *)
1028 Realloc(*servers,sizeof(**servers)*alloced);
1029 if (!(*servers)) return(0);
1030 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1032 s = &(*servers)[count];
1034 if (!next_token(&ptr,s->name , NULL)) continue;
1035 if (!next_token(&ptr,stype , NULL)) continue;
1036 if (!next_token(&ptr,s->comment, NULL)) continue;
1037 if (!next_token(&ptr,s->domain , NULL)) {
1038 /* this allows us to cope with an old nmbd */
1039 strcpy(s->domain,global_myworkgroup);
1042 if (sscanf(stype,"%X",&s->type) != 1) {
1043 DEBUG(4,("r:host file "));
1047 /* Filter the servers/domains we return based on what was asked for. */
1049 /* Check to see if we are being asked for a local list only. */
1050 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1051 DEBUG(4,("r: local list only"));
1055 /* doesn't match up: don't want it */
1056 if (!(servertype & s->type)) {
1057 DEBUG(4,("r:serv type "));
1061 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1062 (s->type & SV_TYPE_DOMAIN_ENUM))
1064 DEBUG(4,("s: dom mismatch "));
1068 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1073 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1074 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1078 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1079 s->name, s->type, s->comment, s->domain));
1081 s->server_added = True;
1086 DEBUG(4,("%20s %8x %25s %15s\n",
1087 s->name, s->type, s->comment, s->domain));
1096 /*******************************************************************
1097 fill in a server info structure
1098 ******************************************************************/
1099 static int fill_srv_info(struct srv_info_struct *service,
1100 int uLevel, char **buf, int *buflen,
1101 char **stringbuf, int *stringspace, char *baseaddr)
1110 case 0: struct_len = 16; break;
1111 case 1: struct_len = 26; break;
1121 len = strlen(service->comment)+1;
1125 if (buflen) *buflen = struct_len;
1126 if (stringspace) *stringspace = len;
1127 return struct_len + len;
1132 if (*buflen < struct_len) return -1;
1140 p2 = p + struct_len;
1141 l2 = *buflen - struct_len;
1143 if (!baseaddr) baseaddr = p;
1148 StrnCpy(p,service->name,15);
1152 StrnCpy(p,service->name,15);
1153 SIVAL(p,18,service->type);
1154 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1155 len += CopyAndAdvance(&p2,service->comment,&l2);
1161 *buf = p + struct_len;
1162 *buflen -= struct_len;
1175 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1177 return(strcmp(s1->name,s2->name));
1180 /****************************************************************************
1181 view list of servers available (or possibly domains). The info is
1182 extracted from lists saved by nmbd on the local host
1183 ****************************************************************************/
1184 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1185 int mdrcnt, int mprcnt, char **rdata,
1186 char **rparam, int *rdata_len, int *rparam_len)
1188 char *str1 = param+2;
1189 char *str2 = skip_string(str1,1);
1190 char *p = skip_string(str2,1);
1191 int uLevel = SVAL(p,0);
1192 int buf_len = SVAL(p,2);
1193 uint32 servertype = IVAL(p,4);
1195 int data_len, fixed_len, string_len;
1196 int f_len = 0, s_len = 0;
1197 struct srv_info_struct *servers=NULL;
1198 int counted=0,total=0;
1201 BOOL domain_request;
1204 /* If someone sets all the bits they don't really mean to set
1205 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1208 if (servertype == SV_TYPE_ALL)
1209 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1211 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1212 any other bit (they may just set this bit on it's own) they
1213 want all the locally seen servers. However this bit can be
1214 set on its own so set the requested servers to be
1215 ALL - DOMAIN_ENUM. */
1217 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1218 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1220 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1221 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1225 if (!prefix_ok(str1,"WrLehD")) return False;
1226 if (!check_server_info(uLevel,str2)) return False;
1228 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1229 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1230 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1232 if (strcmp(str1, "WrLehDz") == 0) {
1233 StrnCpy(domain, p, sizeof(fstring)-1);
1235 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1238 if (lp_browse_list())
1239 total = get_server_info(servertype,&servers,domain);
1241 data_len = fixed_len = string_len = 0;
1244 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1247 char *lastname=NULL;
1249 for (i=0;i<total;i++)
1251 struct srv_info_struct *s = &servers[i];
1252 if (lastname && strequal(lastname,s->name)) continue;
1254 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1255 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1256 s->name, s->type, s->comment, s->domain));
1258 if (data_len <= buf_len) {
1261 string_len += s_len;
1268 *rdata_len = fixed_len + string_len;
1269 *rdata = REALLOC(*rdata,*rdata_len);
1270 bzero(*rdata,*rdata_len);
1272 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1278 char *lastname=NULL;
1279 int count2 = counted;
1280 for (i = 0; i < total && count2;i++)
1282 struct srv_info_struct *s = &servers[i];
1283 if (lastname && strequal(lastname,s->name)) continue;
1285 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1286 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1287 s->name, s->type, s->comment, s->domain));
1293 *rparam = REALLOC(*rparam,*rparam_len);
1294 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1296 SSVAL(*rparam,4,counted);
1297 SSVAL(*rparam,6,counted+missed);
1299 if (servers) free(servers);
1301 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1302 domain,uLevel,counted,counted+missed));
1307 /****************************************************************************
1308 command 0x34 - suspected of being a "Lookup Names" stub api
1309 ****************************************************************************/
1310 static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data,
1311 int mdrcnt, int mprcnt, char **rdata,
1312 char **rparam, int *rdata_len, int *rparam_len)
1314 char *str1 = param+2;
1315 char *str2 = skip_string(str1,1);
1316 char *p = skip_string(str2,1);
1317 int uLevel = SVAL(p,0);
1318 int buf_len = SVAL(p,2);
1322 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1323 str1, str2, p, uLevel, buf_len));
1325 if (!prefix_ok(str1,"zWrLeh")) return False;
1331 *rparam = REALLOC(*rparam,*rparam_len);
1333 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1335 SSVAL(*rparam,4,counted);
1336 SSVAL(*rparam,6,counted+missed);
1341 /****************************************************************************
1342 get info about a share
1343 ****************************************************************************/
1344 static BOOL check_share_info(int uLevel, char* id)
1348 if (strcmp(id,"B13") != 0) return False;
1351 if (strcmp(id,"B13BWz") != 0) return False;
1354 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1357 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1359 default: return False;
1364 static int fill_share_info(int cnum, int snum, int uLevel,
1365 char** buf, int* buflen,
1366 char** stringbuf, int* stringspace, char* baseaddr)
1375 case 0: struct_len = 13; break;
1376 case 1: struct_len = 20; break;
1377 case 2: struct_len = 40; break;
1378 case 91: struct_len = 68; break;
1386 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1387 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1388 if (buflen) *buflen = struct_len;
1389 if (stringspace) *stringspace = len;
1390 return struct_len + len;
1395 if ((*buflen) < struct_len) return -1;
1403 p2 = p + struct_len;
1404 l2 = (*buflen) - struct_len;
1406 if (!baseaddr) baseaddr = p;
1408 StrnCpy(p,lp_servicename(snum),13);
1414 type = STYPE_DISKTREE;
1415 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1416 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1417 SSVAL(p,14,type); /* device type */
1418 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1419 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1424 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1425 SSVALS(p,22,-1); /* max uses */
1426 SSVAL(p,24,1); /* current uses */
1427 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1428 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1429 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1434 memset(p+40,0,SHPWLEN+2);
1446 (*buf) = p + struct_len;
1447 (*buflen) -= struct_len;
1449 (*stringspace) = l2;
1459 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1460 int mdrcnt,int mprcnt,
1461 char **rdata,char **rparam,
1462 int *rdata_len,int *rparam_len)
1464 char *str1 = param+2;
1465 char *str2 = skip_string(str1,1);
1466 char *netname = skip_string(str2,1);
1467 char *p = skip_string(netname,1);
1468 int uLevel = SVAL(p,0);
1469 int snum = find_service(netname);
1471 if (snum < 0) return False;
1473 /* check it's a supported varient */
1474 if (!prefix_ok(str1,"zWrLh")) return False;
1475 if (!check_share_info(uLevel,str2)) return False;
1477 *rdata = REALLOC(*rdata,mdrcnt);
1479 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1480 if (*rdata_len < 0) return False;
1483 *rparam = REALLOC(*rparam,*rparam_len);
1484 SSVAL(*rparam,0,NERR_Success);
1485 SSVAL(*rparam,2,0); /* converter word */
1486 SSVAL(*rparam,4,*rdata_len);
1491 /****************************************************************************
1492 view list of shares available
1493 ****************************************************************************/
1494 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1495 int mdrcnt,int mprcnt,
1496 char **rdata,char **rparam,
1497 int *rdata_len,int *rparam_len)
1499 char *str1 = param+2;
1500 char *str2 = skip_string(str1,1);
1501 char *p = skip_string(str2,1);
1502 int uLevel = SVAL(p,0);
1503 int buf_len = SVAL(p,2);
1505 int count=lp_numservices();
1506 int total=0,counted=0;
1508 int data_len, fixed_len, string_len;
1509 int f_len = 0, s_len = 0;
1511 if (!prefix_ok(str1,"WrLeh")) return False;
1512 if (!check_share_info(uLevel,str2)) return False;
1514 data_len = fixed_len = string_len = 0;
1515 for (i=0;i<count;i++)
1516 if (lp_browseable(i) && lp_snum_ok(i))
1519 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1520 if (data_len <= buf_len)
1524 string_len += s_len;
1527 *rdata_len = fixed_len + string_len;
1528 *rdata = REALLOC(*rdata,*rdata_len);
1529 memset(*rdata,0,*rdata_len);
1531 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1535 for (i = 0; i < count;i++)
1536 if (lp_browseable(i) && lp_snum_ok(i))
1537 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1541 *rparam = REALLOC(*rparam,*rparam_len);
1542 SSVAL(*rparam,0,NERR_Success);
1544 SSVAL(*rparam,4,counted);
1545 SSVAL(*rparam,6,total);
1547 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1548 counted,total,uLevel,
1549 buf_len,*rdata_len,mdrcnt));
1555 /****************************************************************************
1556 get the time of day info
1557 ****************************************************************************/
1558 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1559 int mdrcnt,int mprcnt,
1560 char **rdata,char **rparam,
1561 int *rdata_len,int *rparam_len)
1565 *rparam = REALLOC(*rparam,*rparam_len);
1568 *rdata = REALLOC(*rdata,*rdata_len);
1570 SSVAL(*rparam,0,NERR_Success);
1571 SSVAL(*rparam,2,0); /* converter word */
1577 time_t unixdate = time(NULL);
1579 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1580 by NT in a "net time" operation,
1581 it seems to ignore the one below */
1583 /* the client expects to get localtime, not GMT, in this bit
1584 (I think, this needs testing) */
1585 t = LocalTime(&unixdate);
1587 SIVAL(p,4,0); /* msecs ? */
1588 CVAL(p,8) = t->tm_hour;
1589 CVAL(p,9) = t->tm_min;
1590 CVAL(p,10) = t->tm_sec;
1591 CVAL(p,11) = 0; /* hundredths of seconds */
1592 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1593 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1594 CVAL(p,16) = t->tm_mday;
1595 CVAL(p,17) = t->tm_mon + 1;
1596 SSVAL(p,18,1900+t->tm_year);
1597 CVAL(p,20) = t->tm_wday;
1604 /****************************************************************************
1605 set the user password
1606 ****************************************************************************/
1607 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1608 int mdrcnt,int mprcnt,
1609 char **rdata,char **rparam,
1610 int *rdata_len,int *rparam_len)
1612 char *p = skip_string(param+2,2);
1614 fstring pass1,pass2;
1618 p = skip_string(p,1);
1621 memcpy(pass2,p+16,16);
1624 *rparam = REALLOC(*rparam,*rparam_len);
1628 SSVAL(*rparam,0,NERR_badpass);
1629 SSVAL(*rparam,2,0); /* converter word */
1631 DEBUG(3,("Set password for <%s>\n",user));
1634 * Attempt the plaintext password change first.
1635 * Older versions of Windows seem to do this.
1638 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1639 chgpasswd(user,pass1,pass2,False))
1641 SSVAL(*rparam,0,NERR_Success);
1645 * If the plaintext change failed, attempt
1646 * the encrypted. NT will generate this
1647 * after trying the samr method.
1650 if(SVAL(*rparam,0) != NERR_Success)
1652 struct smb_passwd *sampw = NULL;
1654 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1655 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1657 SSVAL(*rparam,0,NERR_Success);
1661 bzero(pass1,sizeof(fstring));
1662 bzero(pass2,sizeof(fstring));
1667 /****************************************************************************
1668 Set the user password (SamOEM version - gets plaintext).
1669 ****************************************************************************/
1671 static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
1672 int mdrcnt,int mprcnt,
1673 char **rdata,char **rparam,
1674 int *rdata_len,int *rparam_len)
1678 struct smb_passwd *sampw = NULL;
1679 char *p = param + 2;
1682 *rparam = REALLOC(*rparam,*rparam_len);
1686 SSVAL(*rparam,0,NERR_badpass);
1689 * Check the parameter definition is correct.
1691 if(!strequal(param + 2, "zsT")) {
1692 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1695 p = skip_string(p, 1);
1697 if(!strequal(p, "B516B16")) {
1698 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1701 p = skip_string(p,1);
1704 p = skip_string(p,1);
1706 if(check_oem_password( user, (unsigned char *)data, &sampw,
1707 new_passwd, (int)sizeof(new_passwd)) == False) {
1712 * At this point we have the new case-sensitive plaintext
1713 * password in the fstring new_passwd. If we wanted to synchronise
1714 * with UNIX passwords we would call a UNIX password changing
1715 * function here. However it would have to be done as root
1716 * as the plaintext of the old users password is not
1720 if(lp_unix_password_sync())
1721 chgpasswd(user,"", new_passwd, True);
1723 if(change_oem_password( sampw, new_passwd, False)) {
1724 SSVAL(*rparam,0,NERR_Success);
1730 /****************************************************************************
1733 ****************************************************************************/
1734 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1735 int mdrcnt,int mprcnt,
1736 char **rdata,char **rparam,
1737 int *rdata_len,int *rparam_len)
1739 int function = SVAL(param,0);
1740 char *str1 = param+2;
1741 char *str2 = skip_string(str1,1);
1742 char *p = skip_string(str2,1);
1746 printjob_decode(SVAL(p,0), &snum, &jobid);
1748 /* check it's a supported varient */
1749 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1753 *rparam = REALLOC(*rparam,*rparam_len);
1757 SSVAL(*rparam,0,NERR_Success);
1759 if (snum >= 0 && VALID_SNUM(snum))
1761 print_queue_struct *queue=NULL;
1763 count = get_printqueue(snum,cnum,&queue,NULL);
1765 for (i=0;i<count;i++)
1766 if ((queue[i].job&0xFF) == jobid)
1769 case 81: /* delete */
1770 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1771 del_printqueue(cnum,snum,queue[i].job);
1773 case 82: /* pause */
1774 case 83: /* resume */
1775 DEBUG(3,("%s queue entry %d\n",
1776 (function==82?"pausing":"resuming"),queue[i].job));
1777 status_printjob(cnum,snum,queue[i].job,
1778 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1785 SSVAL(*rparam,0,NERR_JobNotFound);
1787 if (queue) free(queue);
1790 SSVAL(*rparam,2,0); /* converter word */
1795 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1796 int mdrcnt,int mprcnt,
1797 char **rdata,char **rparam,
1798 int *rdata_len,int *rparam_len)
1800 char *str1 = param+2;
1801 char *str2 = skip_string(str1,1);
1802 char *QueueName = skip_string(str2,1);
1805 /* check it's a supported varient */
1806 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1810 *rparam = REALLOC(*rparam,*rparam_len);
1814 SSVAL(*rparam,0,NERR_Success);
1815 SSVAL(*rparam,2,0); /* converter word */
1817 snum = lp_servicenumber(QueueName);
1818 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1819 int pnum = lp_servicenumber(PRINTERS_NAME);
1821 lp_add_printer(QueueName,pnum);
1822 snum = lp_servicenumber(QueueName);
1826 if (snum >= 0 && VALID_SNUM(snum)) {
1827 print_queue_struct *queue=NULL;
1831 count = get_printqueue(snum,cnum,&queue,NULL);
1832 for (i = 0; i < count; i++)
1833 del_printqueue(cnum,snum,queue[i].job);
1835 if (queue) free(queue);
1838 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1844 /****************************************************************************
1845 set the property of a print job (undocumented?)
1846 ? function = 0xb -> set name of print job
1847 ? function = 0x6 -> move print job up/down
1848 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1849 or <WWsTP> <WB21BB16B10zWWzDDz>
1850 ****************************************************************************/
1851 static int check_printjob_info(struct pack_desc* desc,
1852 int uLevel, char* id)
1854 desc->subformat = NULL;
1856 case 0: desc->format = "W"; break;
1857 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1858 case 2: desc->format = "WWzWWDDzz"; break;
1859 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1860 default: return False;
1862 if (strcmp(desc->format,id) != 0) return False;
1866 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1867 int mdrcnt,int mprcnt,
1868 char **rdata,char **rparam,
1869 int *rdata_len,int *rparam_len)
1871 struct pack_desc desc;
1872 char *str1 = param+2;
1873 char *str2 = skip_string(str1,1);
1874 char *p = skip_string(str2,1);
1876 int uLevel = SVAL(p,2);
1877 int function = SVAL(p,4); /* what is this ?? */
1881 printjob_decode(SVAL(p,0), &snum, &jobid);
1884 *rparam = REALLOC(*rparam,*rparam_len);
1888 /* check it's a supported varient */
1889 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1893 case 0x6: /* change job place in the queue, data gives the new place */
1894 if (snum >= 0 && VALID_SNUM(snum))
1896 print_queue_struct *queue=NULL;
1900 count = get_printqueue(snum,cnum,&queue,NULL);
1901 for (i=0;i<count;i++) /* find job */
1902 if ((queue[i].job&0xFF) == jobid) break;
1905 desc.errcode=NERR_JobNotFound;
1906 if (queue) free(queue);
1909 desc.errcode=NERR_Success;
1913 int place= SVAL(data,0);
1914 /* we currently have no way of doing this. Can any unix do it? */
1915 if (i < place) /* move down */;
1916 else if (i > place ) /* move up */;
1919 desc.errcode=NERR_notsupported; /* not yet supported */
1920 if (queue) free(queue);
1923 else desc.errcode=NERR_JobNotFound;
1925 case 0xb: /* change print job name, data gives the name */
1926 /* jobid, snum should be zero */
1933 if (issafe(*s)) name[l++] = *s;
1938 DEBUG(3,("Setting print name to %s\n",name));
1942 for (i=0;i<MAX_OPEN_FILES;i++)
1943 if (Files[i].open && Files[i].print_file)
1946 int fcnum = Files[i].cnum;
1950 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1951 !become_service(fcnum,True))
1954 if (sys_rename(Files[i].name,name) == 0)
1955 string_set(&Files[i].name,name);
1959 unbecome_root(True);
1961 desc.errcode=NERR_Success;
1964 default: /* not implemented */
1968 SSVALS(*rparam,0,desc.errcode);
1969 SSVAL(*rparam,2,0); /* converter word */
1975 /****************************************************************************
1976 get info about the server
1977 ****************************************************************************/
1978 static BOOL api_RNetServerGetInfo(int cnum,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,lp_serverstring());
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(cnum,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(int cnum,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 strcpy(p2,local_machine);
2120 p2 = skip_string(p2,1);
2123 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2124 strcpy(p2,sesssetup_user);
2125 p2 = skip_string(p2,1);
2128 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2129 strcpy(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 strcpy(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(int cnum,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", vuser->uid, vuser->name));
2343 *rparam = REALLOC(*rparam,*rparam_len);
2345 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2347 /* check it's a supported variant */
2348 if (strcmp(str1,"zWrLh") != 0) return False;
2351 case 0: p2 = "B21"; break;
2352 case 1: p2 = "B21BB16DWzzWz"; break;
2353 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2354 case 10: p2 = "B21Bzzz"; break;
2355 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2356 default: return False;
2359 if (strcmp(p2,str2) != 0) return False;
2361 *rdata_len = mdrcnt + 1024;
2362 *rdata = REALLOC(*rdata,*rdata_len);
2364 SSVAL(*rparam,0,NERR_Success);
2365 SSVAL(*rparam,2,0); /* converter word */
2368 p2 = p + usri11_end;
2371 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2375 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2380 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2381 strcpy(p2,"Comment");
2382 p2 = skip_string(p2,1);
2384 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2385 strcpy(p2,"UserComment");
2386 p2 = skip_string(p2,1);
2388 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2389 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2390 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2391 p2 = skip_string(p2,1);
2394 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2396 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2397 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2398 SIVALS(p,usri11_password_age,-1); /* password age */
2399 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2400 strcpy(p2, lp_logon_path());
2401 p2 = skip_string(p2,1);
2402 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2404 p2 = skip_string(p2,1);
2405 SIVAL(p,usri11_last_logon,0); /* last logon */
2406 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2407 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2408 SSVALS(p,usri11_num_logons,-1); /* num logons */
2409 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2411 p2 = skip_string(p2,1);
2412 SSVAL(p,usri11_country_code,0); /* country code */
2414 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2416 p2 = skip_string(p2,1);
2418 SIVALS(p,usri11_max_storage,-1); /* max storage */
2419 SSVAL(p,usri11_units_per_week,168); /* units per week */
2420 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2422 /* a simple way to get logon hours at all times. */
2424 SCVAL(p2,21,0); /* fix zero termination */
2425 p2 = skip_string(p2,1);
2427 SSVAL(p,usri11_code_page,0); /* code page */
2429 if (uLevel == 1 || uLevel == 2)
2431 memset(p+22,' ',16); /* password */
2432 SIVALS(p,38,-1); /* password age */
2434 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2435 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2436 strcpy(p2,lp_logon_path());
2437 p2 = skip_string(p2,1);
2438 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2440 SSVAL(p,52,0); /* flags */
2441 SIVAL(p,54,0); /* script_path */
2444 SIVAL(p,60,0); /* auth_flags */
2445 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2446 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2447 p2 = skip_string(p2,1);
2448 SIVAL(p,68,0); /* urs_comment */
2449 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2451 p2 = skip_string(p2,1);
2452 SIVAL(p,76,0); /* workstations */
2453 SIVAL(p,80,0); /* last_logon */
2454 SIVAL(p,84,0); /* last_logoff */
2455 SIVALS(p,88,-1); /* acct_expires */
2456 SIVALS(p,92,-1); /* max_storage */
2457 SSVAL(p,96,168); /* units_per_week */
2458 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2461 SSVALS(p,102,-1); /* bad_pw_count */
2462 SSVALS(p,104,-1); /* num_logons */
2463 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2464 strcpy(p2,"\\\\%L");
2465 standard_sub_basic(p2);
2466 p2 = skip_string(p2,1);
2467 SSVAL(p,110,49); /* country_code */
2468 SSVAL(p,112,860); /* code page */
2472 *rdata_len = PTR_DIFF(p2,*rdata);
2474 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2479 /*******************************************************************
2480 get groups that a user is a member of
2481 ******************************************************************/
2482 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2483 int mdrcnt,int mprcnt,
2484 char **rdata,char **rparam,
2485 int *rdata_len,int *rparam_len)
2487 char *str1 = param+2;
2488 char *str2 = skip_string(str1,1);
2489 char *UserName = skip_string(str2,1);
2490 char *p = skip_string(UserName,1);
2491 int uLevel = SVAL(p,0);
2496 *rparam = REALLOC(*rparam,*rparam_len);
2498 /* check it's a supported varient */
2499 if (strcmp(str1,"zWrLeh") != 0) return False;
2501 case 0: p2 = "B21"; break;
2502 default: return False;
2504 if (strcmp(p2,str2) != 0) return False;
2506 *rdata_len = mdrcnt + 1024;
2507 *rdata = REALLOC(*rdata,*rdata_len);
2509 SSVAL(*rparam,0,NERR_Success);
2510 SSVAL(*rparam,2,0); /* converter word */
2514 /* XXXX we need a real SAM database some day */
2515 strcpy(p,"Users"); p += 21; count++;
2516 strcpy(p,"Domain Users"); p += 21; count++;
2517 strcpy(p,"Guests"); p += 21; count++;
2518 strcpy(p,"Domain Guests"); p += 21; count++;
2520 *rdata_len = PTR_DIFF(p,*rdata);
2522 SSVAL(*rparam,4,count); /* is this right?? */
2523 SSVAL(*rparam,6,count); /* is this right?? */
2529 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2530 int mdrcnt,int mprcnt,
2531 char **rdata,char **rparam,
2532 int *rdata_len,int *rparam_len)
2534 char *str1 = param+2;
2535 char *str2 = skip_string(str1,1);
2536 char *p = skip_string(str2,1);
2538 struct pack_desc desc;
2545 bzero(&desc,sizeof(desc));
2547 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2549 /* check it's a supported varient */
2550 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2551 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2552 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2554 desc.buflen = mdrcnt;
2555 desc.subformat = NULL;
2558 if (init_package(&desc,1,0))
2560 PACKI(&desc,"W",0); /* code */
2561 PACKS(&desc,"B21",name); /* eff. name */
2562 PACKS(&desc,"B",""); /* pad */
2564 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2565 PACKI(&desc,"D",0); /* auth flags XXX */
2566 PACKI(&desc,"W",0); /* num logons */
2567 PACKI(&desc,"W",0); /* bad pw count */
2568 PACKI(&desc,"D",0); /* last logon */
2569 PACKI(&desc,"D",-1); /* last logoff */
2570 PACKI(&desc,"D",-1); /* logoff time */
2571 PACKI(&desc,"D",-1); /* kickoff time */
2572 PACKI(&desc,"D",0); /* password age */
2573 PACKI(&desc,"D",0); /* password can change */
2574 PACKI(&desc,"D",-1); /* password must change */
2577 strcpy(mypath,"\\\\");
2578 strcat(mypath,local_machine);
2580 PACKS(&desc,"z",mypath); /* computer */
2582 PACKS(&desc,"z",global_myworkgroup);/* domain */
2584 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2585 /* made sure all macros are fully substituted and available */
2586 logon_script = lp_logon_script();
2587 standard_sub( cnum, logon_script );
2588 PACKS(&desc,"z", logon_script); /* script path */
2589 /* End of JHT mods */
2591 PACKI(&desc,"D",0x00000000); /* reserved */
2594 *rdata_len = desc.usedlen;
2596 *rparam = REALLOC(*rparam,*rparam_len);
2597 SSVALS(*rparam,0,desc.errcode);
2599 SSVAL(*rparam,4,desc.neededlen);
2601 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2606 /****************************************************************************
2607 api_WAccessGetUserPerms
2608 ****************************************************************************/
2609 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2610 int mdrcnt,int mprcnt,
2611 char **rdata,char **rparam,
2612 int *rdata_len,int *rparam_len)
2614 char *str1 = param+2;
2615 char *str2 = skip_string(str1,1);
2616 char *user = skip_string(str2,1);
2617 char *resource = skip_string(user,1);
2619 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2621 /* check it's a supported varient */
2622 if (strcmp(str1,"zzh") != 0) return False;
2623 if (strcmp(str2,"") != 0) return False;
2626 *rparam = REALLOC(*rparam,*rparam_len);
2627 SSVALS(*rparam,0,0); /* errorcode */
2628 SSVAL(*rparam,2,0); /* converter word */
2629 SSVAL(*rparam,4,0x7f); /* permission flags */
2634 /****************************************************************************
2635 api_WPrintJobEnumerate
2636 ****************************************************************************/
2637 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2638 int mdrcnt,int mprcnt,
2639 char **rdata,char **rparam,
2640 int *rdata_len,int *rparam_len)
2642 char *str1 = param+2;
2643 char *str2 = skip_string(str1,1);
2644 char *p = skip_string(str2,1);
2650 struct pack_desc desc;
2651 print_queue_struct *queue=NULL;
2652 print_status_struct status;
2657 bzero(&desc,sizeof(desc));
2658 bzero(&status,sizeof(status));
2660 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2662 /* check it's a supported varient */
2663 if (strcmp(str1,"WWrLh") != 0) return False;
2664 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2666 printjob_decode(SVAL(p,0), &snum, &job);
2668 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2670 count = get_printqueue(snum,cnum,&queue,&status);
2671 for (i = 0; i < count; i++) {
2672 if ((queue[i].job & 0xFF) == job) break;
2674 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2676 desc.buflen = mdrcnt;
2678 if (init_package(&desc,1,0)) {
2680 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2681 *rdata_len = desc.usedlen;
2684 desc.errcode = NERR_JobNotFound;
2690 *rparam = REALLOC(*rparam,*rparam_len);
2691 SSVALS(*rparam,0,desc.errcode);
2693 SSVAL(*rparam,4,desc.neededlen);
2695 if (queue) free(queue);
2697 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2701 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2702 int mdrcnt,int mprcnt,
2703 char **rdata,char **rparam,
2704 int *rdata_len,int *rparam_len)
2706 char *str1 = param+2;
2707 char *str2 = skip_string(str1,1);
2708 char *p = skip_string(str2,1);
2714 struct pack_desc desc;
2715 print_queue_struct *queue=NULL;
2716 print_status_struct status;
2718 bzero(&desc,sizeof(desc));
2719 bzero(&status,sizeof(status));
2721 p = skip_string(p,1);
2725 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2727 /* check it's a supported varient */
2728 if (strcmp(str1,"zWrLeh") != 0) return False;
2729 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2730 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2732 snum = lp_servicenumber(name);
2733 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2734 int pnum = lp_servicenumber(PRINTERS_NAME);
2736 lp_add_printer(name,pnum);
2737 snum = lp_servicenumber(name);
2741 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2743 count = get_printqueue(snum,cnum,&queue,&status);
2744 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2746 desc.buflen = mdrcnt;
2748 if (init_package(&desc,count,0)) {
2750 for (i = 0; i < count; i++) {
2751 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2752 if (desc.errcode == NERR_Success) succnt = i+1;
2756 *rdata_len = desc.usedlen;
2759 *rparam = REALLOC(*rparam,*rparam_len);
2760 SSVALS(*rparam,0,desc.errcode);
2762 SSVAL(*rparam,4,succnt);
2763 SSVAL(*rparam,6,count);
2765 if (queue) free(queue);
2767 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2771 static int check_printdest_info(struct pack_desc* desc,
2772 int uLevel, char* id)
2774 desc->subformat = NULL;
2776 case 0: desc->format = "B9"; break;
2777 case 1: desc->format = "B9B21WWzW"; break;
2778 case 2: desc->format = "z"; break;
2779 case 3: desc->format = "zzzWWzzzWW"; break;
2780 default: return False;
2782 if (strcmp(desc->format,id) != 0) return False;
2786 static void fill_printdest_info(int cnum, int snum, int uLevel,
2787 struct pack_desc* desc)
2790 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2791 buf[sizeof(buf)-1] = 0;
2794 PACKS(desc,"B9",buf); /* szName */
2796 PACKS(desc,"B21",""); /* szUserName */
2797 PACKI(desc,"W",0); /* uJobId */
2798 PACKI(desc,"W",0); /* fsStatus */
2799 PACKS(desc,"z",""); /* pszStatus */
2800 PACKI(desc,"W",0); /* time */
2803 if (uLevel == 2 || uLevel == 3) {
2804 PACKS(desc,"z",buf); /* pszPrinterName */
2806 PACKS(desc,"z",""); /* pszUserName */
2807 PACKS(desc,"z",""); /* pszLogAddr */
2808 PACKI(desc,"W",0); /* uJobId */
2809 PACKI(desc,"W",0); /* fsStatus */
2810 PACKS(desc,"z",""); /* pszStatus */
2811 PACKS(desc,"z",""); /* pszComment */
2812 PACKS(desc,"z","NULL"); /* pszDrivers */
2813 PACKI(desc,"W",0); /* time */
2814 PACKI(desc,"W",0); /* pad1 */
2819 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2820 int mdrcnt,int mprcnt,
2821 char **rdata,char **rparam,
2822 int *rdata_len,int *rparam_len)
2824 char *str1 = param+2;
2825 char *str2 = skip_string(str1,1);
2826 char *p = skip_string(str2,1);
2827 char* PrinterName = p;
2829 struct pack_desc desc;
2832 bzero(&desc,sizeof(desc));
2834 p = skip_string(p,1);
2838 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2840 /* check it's a supported varient */
2841 if (strcmp(str1,"zWrLh") != 0) return False;
2842 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2844 snum = lp_servicenumber(PrinterName);
2845 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2846 int pnum = lp_servicenumber(PRINTERS_NAME);
2848 lp_add_printer(PrinterName,pnum);
2849 snum = lp_servicenumber(PrinterName);
2855 desc.errcode = NERR_DestNotFound;
2859 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2861 desc.buflen = mdrcnt;
2862 if (init_package(&desc,1,0)) {
2863 fill_printdest_info(cnum,snum,uLevel,&desc);
2865 *rdata_len = desc.usedlen;
2869 *rparam = REALLOC(*rparam,*rparam_len);
2870 SSVALS(*rparam,0,desc.errcode);
2872 SSVAL(*rparam,4,desc.neededlen);
2874 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2878 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2879 int mdrcnt,int mprcnt,
2880 char **rdata,char **rparam,
2881 int *rdata_len,int *rparam_len)
2883 char *str1 = param+2;
2884 char *str2 = skip_string(str1,1);
2885 char *p = skip_string(str2,1);
2889 struct pack_desc desc;
2890 int services = lp_numservices();
2892 bzero(&desc,sizeof(desc));
2897 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2899 /* check it's a supported varient */
2900 if (strcmp(str1,"WrLeh") != 0) return False;
2901 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2904 for (i = 0; i < services; i++)
2905 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2908 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2910 desc.buflen = mdrcnt;
2911 if (init_package(&desc,queuecnt,0)) {
2914 for (i = 0; i < services; i++) {
2915 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2916 fill_printdest_info(cnum,i,uLevel,&desc);
2918 if (desc.errcode == NERR_Success) succnt = n;
2923 *rdata_len = desc.usedlen;
2926 *rparam = REALLOC(*rparam,*rparam_len);
2927 SSVALS(*rparam,0,desc.errcode);
2929 SSVAL(*rparam,4,succnt);
2930 SSVAL(*rparam,6,queuecnt);
2932 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2936 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2937 int mdrcnt,int mprcnt,
2938 char **rdata,char **rparam,
2939 int *rdata_len,int *rparam_len)
2941 char *str1 = param+2;
2942 char *str2 = skip_string(str1,1);
2943 char *p = skip_string(str2,1);
2946 struct pack_desc desc;
2948 bzero(&desc,sizeof(desc));
2953 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2955 /* check it's a supported varient */
2956 if (strcmp(str1,"WrLeh") != 0) return False;
2957 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2959 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2961 desc.buflen = mdrcnt;
2962 if (init_package(&desc,1,0)) {
2963 PACKS(&desc,"B41","NULL");
2966 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2968 *rdata_len = desc.usedlen;
2971 *rparam = REALLOC(*rparam,*rparam_len);
2972 SSVALS(*rparam,0,desc.errcode);
2974 SSVAL(*rparam,4,succnt);
2977 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2981 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2982 int mdrcnt,int mprcnt,
2983 char **rdata,char **rparam,
2984 int *rdata_len,int *rparam_len)
2986 char *str1 = param+2;
2987 char *str2 = skip_string(str1,1);
2988 char *p = skip_string(str2,1);
2991 struct pack_desc desc;
2993 bzero(&desc,sizeof(desc));
2998 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3000 /* check it's a supported varient */
3001 if (strcmp(str1,"WrLeh") != 0) return False;
3002 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3004 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3006 desc.buflen = mdrcnt;
3008 if (init_package(&desc,1,0)) {
3009 PACKS(&desc,"B13","lpd");
3012 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3014 *rdata_len = desc.usedlen;
3017 *rparam = REALLOC(*rparam,*rparam_len);
3018 SSVALS(*rparam,0,desc.errcode);
3020 SSVAL(*rparam,4,succnt);
3023 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3027 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
3028 int mdrcnt,int mprcnt,
3029 char **rdata,char **rparam,
3030 int *rdata_len,int *rparam_len)
3032 char *str1 = param+2;
3033 char *str2 = skip_string(str1,1);
3034 char *p = skip_string(str2,1);
3037 struct pack_desc desc;
3039 bzero(&desc,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 bzero(&desc,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));
3076 char * pipe_clnt_name;
3077 char * pipe_srv_name;
3078 BOOL (*fn) (pipes_struct *, prs_struct *);
3081 static struct api_cmd api_fd_commands[] =
3083 { "lsarpc", "lsass", api_ntlsa_rpc },
3084 { "samr", "lsass", api_samr_rpc },
3085 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3086 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3087 { "NETLOGON", "lsass", api_netlog_rpc },
3088 { "winreg", "winreg", api_reg_rpc },
3089 { NULL, NULL, NULL }
3092 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3094 BOOL ntlmssp_auth = False;
3095 fstring ack_pipe_name;
3098 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3100 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3102 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3103 api_fd_commands[i].fn != NULL)
3105 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3106 api_fd_commands[i].pipe_clnt_name,
3107 api_fd_commands[i].pipe_srv_name));
3108 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3113 if (api_fd_commands[i].fn == NULL) return False;
3115 /* decode the bind request */
3116 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3118 if (pd->offset == 0) return False;
3120 if (p->hdr.auth_len != 0)
3122 /* decode the authentication verifier */
3123 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3125 if (pd->offset == 0) return False;
3127 /* ignore the version number for now */
3128 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3131 /* name has to be \PIPE\xxxxx */
3132 strcpy(ack_pipe_name, "\\PIPE\\");
3133 strcat(ack_pipe_name, p->pipe_srv_name);
3135 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3137 prs_init(&(p->rdata), 1024, 4, 0, False);
3138 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3139 prs_init(&(p->rauth), 1024, 4, 0, False);
3142 /*** do the bind ack first ***/
3145 make_rpc_hdr_ba(&p->hdr_ba,
3146 p->hdr_rb.bba.max_tsize,
3147 p->hdr_rb.bba.max_rsize,
3148 p->hdr_rb.bba.assoc_gid,
3151 &(p->hdr_rb.transfer));
3153 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3154 mem_realloc_data(p->rdata.data, p->rdata.offset);
3157 /*** now the authentication ***/
3163 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3165 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3168 0x00000000, 0x0000b2b3, 0x000082b1,
3170 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3171 mem_realloc_data(p->rauth.data, p->rauth.offset);
3175 /*** then do the header, now we know the length ***/
3178 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3180 p->rdata.offset + p->rauth.offset,
3183 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3184 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3187 /*** link rpc header, bind acknowledgment and authentication responses ***/
3190 p->rhdr.data->offset.start = 0;
3191 p->rhdr.data->offset.end = p->rhdr.offset;
3192 p->rhdr.data->next = p->rdata.data;
3196 p->rdata.data->offset.start = p->rhdr.offset;
3197 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3198 p->rdata.data->next = p->rauth.data;
3200 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3201 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3202 p->rauth.data->next = NULL;
3206 p->rdata.data->offset.start = p->rhdr.offset;
3207 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3208 p->rdata.data->next = NULL;
3214 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3218 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3220 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3221 api_fd_commands[i].fn != NULL)
3223 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3224 return api_fd_commands[i].fn(p, pd);
3230 static BOOL api_dce_rpc_command(char *outbuf,
3235 if (pd->data == NULL) return False;
3237 /* process the rpc header */
3238 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3240 if (pd->offset == 0) return False;
3242 switch (p->hdr.pkt_type)
3246 reply = api_pipe_bind_req(p, pd);
3251 reply = api_pipe_request (p, pd);
3258 /* now send the reply */
3259 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3261 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3263 /* all of data was sent: no need to wait for SMBreadX calls */
3264 mem_free_data(p->rhdr .data);
3265 mem_free_data(p->rdata.data);
3272 /****************************************************************************
3273 SetNamedPipeHandleState
3274 ****************************************************************************/
3275 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3279 if (!param) return False;
3281 id = param[0] + (param[1] << 8);
3282 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3284 if (set_rpc_pipe_hnd_state(p, id))
3286 /* now send the reply */
3287 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3295 /****************************************************************************
3296 when no reply is generated, indicate unsupported.
3297 ****************************************************************************/
3298 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3300 struct mem_buf rparam;
3302 mem_init(&rparam, 0);
3303 mem_alloc_data(&rparam, 4);
3305 rparam.offset.start = 0;
3306 rparam.offset.end = 4;
3309 SSVAL(rparam.data,0,NERR_notsupported);
3310 SSVAL(rparam.data,2,0); /* converter word */
3312 DEBUG(3,("Unsupported API fd command\n"));
3314 /* now send the reply */
3315 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3317 mem_free_data(&rparam);
3322 /****************************************************************************
3323 handle remote api calls delivered to a named pipe already opened.
3324 ****************************************************************************/
3325 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3326 uint16 *setup,char *data,char *params,
3327 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3333 pipes_struct *p = NULL;
3335 struct mem_buf data_buf;
3337 DEBUG(5,("api_fd_reply\n"));
3339 /* fake up a data buffer from the api_fd_reply data parameters */
3340 mem_create(&data_buf, data, tdscnt, 0, False);
3341 data_buf.offset.start = 0;
3342 data_buf.offset.end = tdscnt;
3344 /* fake up a parsing structure */
3345 pd.data = &data_buf;
3350 /* First find out the name of this file. */
3353 DEBUG(0,("Unexpected named pipe transaction.\n"));
3357 /* Get the file handle and hence the file name. */
3359 subcommand = setup[0];
3360 get_rpc_pipe(pnum, &p);
3364 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3365 subcommand, p->name, pnum));
3366 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3367 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3369 /* record maximum data length that can be transmitted in an SMBtrans */
3370 p->file_offset = mdrcnt;
3372 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3373 p, p->file_offset));
3379 /* dce/rpc command */
3380 reply = api_dce_rpc_command(outbuf, p, &pd);
3385 /* Set Named Pipe Handle state */
3386 reply = api_SNPHS(outbuf, p, params);
3393 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3398 return api_no_reply(outbuf, mdrcnt);
3403 /****************************************************************************
3404 the buffer was too small
3405 ****************************************************************************/
3406 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3407 int mdrcnt,int mprcnt,
3408 char **rdata,char **rparam,
3409 int *rdata_len,int *rparam_len)
3411 *rparam_len = MIN(*rparam_len,mprcnt);
3412 *rparam = REALLOC(*rparam,*rparam_len);
3416 SSVAL(*rparam,0,NERR_BufTooSmall);
3418 DEBUG(3,("Supplied buffer too small in API command\n"));
3424 /****************************************************************************
3425 the request is not supported
3426 ****************************************************************************/
3427 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3428 int mdrcnt,int mprcnt,
3429 char **rdata,char **rparam,
3430 int *rdata_len,int *rparam_len)
3433 *rparam = REALLOC(*rparam,*rparam_len);
3437 SSVAL(*rparam,0,NERR_notsupported);
3438 SSVAL(*rparam,2,0); /* converter word */
3440 DEBUG(3,("Unsupported API command\n"));
3452 BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *);
3454 } api_commands[] = {
3455 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3456 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3457 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3458 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3459 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3460 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3461 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3462 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3463 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3464 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3465 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3466 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3467 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3468 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3469 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3470 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3471 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3472 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3473 {"NetServerEnum", 104, api_RNetServerEnum,0},
3474 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3475 {"SetUserPassword", 115, api_SetUserPassword,0},
3476 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3477 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3478 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3479 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3480 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3481 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3482 {NULL, -1, api_Unsupported,0}};
3485 /****************************************************************************
3486 handle remote api calls
3487 ****************************************************************************/
3488 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3489 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3491 int api_command = SVAL(params,0);
3492 struct mem_buf rdata_buf;
3493 struct mem_buf rparam_buf;
3495 char *rparam = NULL;
3501 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3502 api_command,params+2,skip_string(params+2,1),
3503 tdscnt,tpscnt,mdrcnt,mprcnt));
3505 for (i=0;api_commands[i].name;i++)
3506 if (api_commands[i].id == api_command && api_commands[i].fn)
3508 DEBUG(3,("Doing %s\n",api_commands[i].name));
3512 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3513 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3515 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3516 &rdata,&rparam,&rdata_len,&rparam_len);
3519 if (rdata_len > mdrcnt ||
3520 rparam_len > mprcnt)
3522 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3523 &rdata,&rparam,&rdata_len,&rparam_len);
3527 /* if we get False back then it's actually unsupported */
3529 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3530 &rdata,&rparam,&rdata_len,&rparam_len);
3533 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3534 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3536 rdata_buf.offset.start = 0;
3537 rdata_buf.offset.end = rdata_len;
3539 rparam_buf.offset.start = 0;
3540 rparam_buf.offset.end = rparam_len;
3542 /* now send the reply */
3543 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3545 if (rdata ) free(rdata);
3546 if (rparam) free(rparam);
3551 /****************************************************************************
3552 handle named pipe commands
3553 ****************************************************************************/
3554 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3555 uint16 *setup,char *data,char *params,
3556 int suwcnt,int tdscnt,int tpscnt,
3557 int msrcnt,int mdrcnt,int mprcnt)
3559 DEBUG(3,("named pipe command on <%s> name\n", name));
3561 if (strequal(name,"LANMAN"))
3563 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3566 if (strlen(name) < 1)
3568 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3573 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3580 /****************************************************************************
3582 ****************************************************************************/
3583 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3587 char *data=NULL,*params=NULL;
3591 int cnum = SVAL(inbuf,smb_tid);
3592 uint16 vuid = SVAL(inbuf,smb_uid);
3594 int tpscnt = SVAL(inbuf,smb_vwv0);
3595 int tdscnt = SVAL(inbuf,smb_vwv1);
3596 int mprcnt = SVAL(inbuf,smb_vwv2);
3597 int mdrcnt = SVAL(inbuf,smb_vwv3);
3598 int msrcnt = CVAL(inbuf,smb_vwv4);
3599 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3600 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3601 int pscnt = SVAL(inbuf,smb_vwv9);
3602 int psoff = SVAL(inbuf,smb_vwv10);
3603 int dscnt = SVAL(inbuf,smb_vwv11);
3604 int dsoff = SVAL(inbuf,smb_vwv12);
3605 int suwcnt = CVAL(inbuf,smb_vwv13);
3607 bzero(name, sizeof(name));
3608 fstrcpy(name,smb_buf(inbuf));
3610 if (dscnt > tdscnt || pscnt > tpscnt) {
3611 exit_server("invalid trans parameters\n");
3616 data = (char *)malloc(tdscnt);
3617 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3621 params = (char *)malloc(tpscnt);
3622 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3628 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3629 for (i=0;i<suwcnt;i++)
3630 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3634 if (pscnt < tpscnt || dscnt < tdscnt)
3636 /* We need to send an interim response then receive the rest
3637 of the parameter/data bytes */
3638 outsize = set_message(outbuf,0,0,True);
3640 send_smb(Client,outbuf);
3643 /* receive the rest of the trans packet */
3644 while (pscnt < tpscnt || dscnt < tdscnt)
3647 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3649 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3651 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3654 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3656 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3657 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3658 if (params) free(params);
3659 if (data) free(data);
3660 if (setup) free(setup);
3661 return(ERROR(ERRSRV,ERRerror));
3666 tpscnt = SVAL(inbuf,smb_vwv0);
3667 tdscnt = SVAL(inbuf,smb_vwv1);
3669 pcnt = SVAL(inbuf,smb_vwv2);
3670 poff = SVAL(inbuf,smb_vwv3);
3671 pdisp = SVAL(inbuf,smb_vwv4);
3673 dcnt = SVAL(inbuf,smb_vwv5);
3674 doff = SVAL(inbuf,smb_vwv6);
3675 ddisp = SVAL(inbuf,smb_vwv7);
3680 if (dscnt > tdscnt || pscnt > tpscnt) {
3681 exit_server("invalid trans parameters\n");
3685 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3687 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3691 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3693 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3695 DEBUG(5,("calling named_pipe\n"));
3696 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3697 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3701 DEBUG(3,("invalid pipe name\n"));
3706 if (data) free(data);
3707 if (params) free(params);
3708 if (setup) free(setup);
3710 if (close_on_completion)
3711 close_cnum(cnum,vuid);
3717 return(ERROR(ERRSRV,ERRnosupport));