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
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
60 #define NNLEN 12 /* 8.3 net name length */
61 #define SNLEN 15 /* service name length */
62 #define QNLEN 12 /* queue name maximum length */
65 extern int oplock_sock;
66 extern int smb_read_error;
68 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
69 int mdrcnt,int mprcnt,
70 char **rdata,char **rparam,
71 int *rdata_len,int *rparam_len);
72 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
73 int mdrcnt,int mprcnt,
74 char **rdata,char **rparam,
75 int *rdata_len,int *rparam_len);
78 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
83 if (!src || !dst || !n || !(*dst)) return(0);
85 StrnCpy(buf,src,sizeof(buf)/2);
86 string_sub(buf,"%S",lp_servicename(snum));
87 standard_sub(cnum,buf);
95 static int CopyAndAdvance(char** dst, char* src, int* n)
98 if (!src || !dst || !n || !(*dst)) return(0);
100 l = strlen(*dst) + 1;
106 static int StrlenExpanded(int cnum, int snum, char* s)
110 StrnCpy(buf,s,sizeof(buf)/2);
111 string_sub(buf,"%S",lp_servicename(snum));
112 standard_sub(cnum,buf);
113 return strlen(buf) + 1;
116 static char* Expand(int cnum, int snum, char* s)
119 if (!s) return(NULL);
120 StrnCpy(buf,s,sizeof(buf)/2);
121 string_sub(buf,"%S",lp_servicename(snum));
122 standard_sub(cnum,buf);
126 /*******************************************************************
127 check a API string for validity when we only need to check the prefix
128 ******************************************************************/
129 static BOOL prefix_ok(char *str,char *prefix)
131 return(strncmp(str,prefix,strlen(prefix)) == 0);
134 /*******************************************************************
135 copies parameters and data, as needed, into the smb buffer
137 *both* the data and params sections should be aligned. this
138 is fudged in the rpc pipes by
139 at present, only the data section is. this may be a possible
140 cause of some of the ipc problems being experienced. lkcl26dec97
142 ******************************************************************/
143 static void copy_trans_params_and_data(char *outbuf, int align,
144 struct mem_buf *rparam, struct mem_buf *rdata,
145 int param_offset, int data_offset,
146 int param_len, int data_len)
148 char *copy_into = smb_buf(outbuf);
150 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
151 param_offset, param_offset + param_len,
152 data_offset , data_offset + data_len));
154 if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
155 copy_into += param_len + align;
156 if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
159 /****************************************************************************
161 ****************************************************************************/
162 static void send_trans_reply(char *outbuf,
163 struct mem_buf *rdata,
164 struct mem_buf *rparam,
165 uint16 *setup, int lsetup, int max_data_ret)
168 int this_ldata,this_lparam;
169 int tot_data=0,tot_param=0;
172 int ldata = rdata ? mem_buf_len(rdata ) : 0;
173 int lparam = rparam ? mem_buf_len(rparam) : 0;
175 BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
177 if (buffer_too_large)
179 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
180 ldata = max_data_ret;
183 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
184 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
186 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
187 /* if you don't want Net Monitor to decode your packets, do this!!! */
188 align = ((this_lparam+1)%4);
190 align = (this_lparam%4);
193 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
195 if (buffer_too_large)
197 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
198 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
199 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
202 copy_trans_params_and_data(outbuf, align,
204 tot_param , tot_data,
205 this_lparam, this_ldata);
207 SSVAL(outbuf,smb_vwv0,lparam);
208 SSVAL(outbuf,smb_vwv1,ldata);
209 SSVAL(outbuf,smb_vwv3,this_lparam);
210 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
211 SSVAL(outbuf,smb_vwv5,0);
212 SSVAL(outbuf,smb_vwv6,this_ldata);
213 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
214 SSVAL(outbuf,smb_vwv8,0);
215 SSVAL(outbuf,smb_vwv9,lsetup);
217 for (i=0;i<lsetup;i++)
219 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
223 send_smb(Client,outbuf);
225 tot_data = this_ldata;
226 tot_param = this_lparam;
228 while (tot_data < ldata || tot_param < lparam)
230 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
231 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
233 align = (this_lparam%4);
235 set_message(outbuf,10,this_ldata+this_lparam+align,False);
237 copy_trans_params_and_data(outbuf, align,
239 tot_param , tot_data,
240 this_lparam, this_ldata);
242 SSVAL(outbuf,smb_vwv3,this_lparam);
243 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
244 SSVAL(outbuf,smb_vwv5,tot_param);
245 SSVAL(outbuf,smb_vwv6,this_ldata);
246 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
247 SSVAL(outbuf,smb_vwv8,tot_data);
248 SSVAL(outbuf,smb_vwv9,0);
251 send_smb(Client,outbuf);
253 tot_data += this_ldata;
254 tot_param += this_lparam;
259 char* format; /* formatstring for structure */
260 char* subformat; /* subformat for structure */
261 char* base; /* baseaddress of buffer */
262 int buflen; /* remaining size for fixed part; on init: length of base */
263 int subcount; /* count of substructures */
264 char* structbuf; /* pointer into buffer for remaining fixed part */
265 int stringlen; /* remaining size for variable part */
266 char* stringbuf; /* pointer into buffer for remaining variable part */
267 int neededlen; /* total needed size */
268 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
269 char* curpos; /* current position; pointer into format or subformat */
273 static int get_counter(char** p)
276 if (!p || !(*p)) return(1);
277 if (!isdigit(**p)) return 1;
281 n = 10 * n + (i - '0');
288 static int getlen(char* p)
294 case 'W': /* word (2 byte) */
297 case 'N': /* count of substructures (word) at end */
300 case 'D': /* double word (4 byte) */
301 case 'z': /* offset to zero terminated string (4 byte) */
302 case 'l': /* offset to user data (4 byte) */
305 case 'b': /* offset to data (with counter) (4 byte) */
309 case 'B': /* byte (with optional counter) */
310 n += get_counter(&p);
317 static BOOL init_package(struct pack_desc* p, int count, int subcount)
322 if (!p->format || !p->base) return(False);
324 i = count * getlen(p->format);
325 if (p->subformat) i += subcount * getlen(p->subformat);
326 p->structbuf = p->base;
330 p->curpos = p->format;
334 p->errcode = ERRmoredata;
337 p->errcode = NERR_Success;
340 p->stringbuf = p->base + i;
342 return(p->errcode == NERR_Success);
346 static int package(struct pack_desc* p, ...)
349 static int package(va_alist)
355 int needed=0, stringneeded;
357 int is_string=0, stringused;
364 p = va_arg(args,struct pack_desc *);
369 p->curpos = p->format;
371 p->curpos = p->subformat;
376 str = va_arg(args,char*);
377 if (strncmp(str,p->curpos,strlen(str)) != 0) {
378 DEBUG(2,("type error in package: %s instead of %*s\n",str,
379 strlen(str),p->curpos));
389 if (!p->curpos) return(0);
391 switch( *p->curpos++ ) {
392 case 'W': /* word (2 byte) */
394 temp = va_arg(args,int);
395 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
397 case 'N': /* count of substructures (word) at end */
399 p->subcount = va_arg(args,int);
400 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
402 case 'D': /* double word (4 byte) */
404 temp = va_arg(args,int);
405 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
407 case 'B': /* byte (with optional counter) */
408 needed = get_counter(&p->curpos);
410 char *s = va_arg(args,char*);
411 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
414 case 'z': /* offset to zero terminated string (4 byte) */
415 str = va_arg(args,char*);
416 stringneeded = (str ? strlen(str)+1 : 0);
419 case 'l': /* offset to user data (4 byte) */
420 str = va_arg(args,char*);
421 stringneeded = va_arg(args,int);
424 case 'b': /* offset to data (with counter) (4 byte) */
425 str = va_arg(args,char*);
426 stringneeded = get_counter(&p->curpos);
431 if (stringneeded >= 0) {
433 if (p->buflen >= needed) {
434 stringused = stringneeded;
435 if (stringused > p->stringlen) {
436 stringused = (is_string ? p->stringlen : 0);
437 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
440 SIVAL(p->structbuf,0,0);
442 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
443 memcpy(p->stringbuf,str?str:"",stringused);
444 if (is_string) p->stringbuf[stringused-1] = '\0';
445 p->stringbuf += stringused;
446 p->stringlen -= stringused;
447 p->usedlen += stringused;
450 p->neededlen += stringneeded;
452 p->neededlen += needed;
453 if (p->buflen >= needed) {
454 p->structbuf += needed;
456 p->usedlen += needed;
459 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
465 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
466 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
468 #define PACK(desc,t,v) package(desc,v)
469 #define PACKl(desc,t,v,l) package(desc,v,l)
472 static void PACKI(struct pack_desc* desc,char *t,int v)
477 static void PACKS(struct pack_desc* desc,char *t,char *v)
483 /****************************************************************************
485 ****************************************************************************/
487 static void PackDriverData(struct pack_desc* desc)
489 char drivdata[4+4+32];
490 SIVAL(drivdata,0,sizeof drivdata); /* cb */
491 SIVAL(drivdata,4,1000); /* lVersion */
492 memset(drivdata+8,0,32); /* szDeviceName */
493 pstrcpy(drivdata+8,"NULL");
494 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
497 static int check_printq_info(struct pack_desc* desc,
498 int uLevel, char *id1, char *id2)
500 desc->subformat = NULL;
503 desc->format = "B13";
506 desc->format = "B13BWWWzzzzzWW";
509 desc->format = "B13BWWWzzzzzWN";
510 desc->subformat = "WB21BB16B10zWWzDDz";
513 desc->format = "zWWWWzzzzWWzzl";
516 desc->format = "zWWWWzzzzWNzzl";
517 desc->subformat = "WWzWWDDzz";
523 desc->format = "WzzzzzzzzN";
524 desc->subformat = "z";
526 default: return False;
528 if (strcmp(desc->format,id1) != 0) return False;
529 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
533 static void fill_printjob_info(int cnum, int snum, int uLevel,
534 struct pack_desc* desc,
535 print_queue_struct* queue, int n)
537 time_t t = queue->time;
539 /* the client expects localtime */
542 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
544 PACKS(desc,"B21",queue->user); /* szUserName */
545 PACKS(desc,"B",""); /* pad */
546 PACKS(desc,"B16",""); /* szNotifyName */
547 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
548 PACKS(desc,"z",""); /* pszParms */
549 PACKI(desc,"W",n+1); /* uPosition */
550 PACKI(desc,"W",queue->status); /* fsStatus */
551 PACKS(desc,"z",""); /* pszStatus */
552 PACKI(desc,"D",t); /* ulSubmitted */
553 PACKI(desc,"D",queue->size); /* ulSize */
554 PACKS(desc,"z",queue->file); /* pszComment */
556 if (uLevel == 2 || uLevel == 3) {
557 PACKI(desc,"W",queue->priority); /* uPriority */
558 PACKS(desc,"z",queue->user); /* pszUserName */
559 PACKI(desc,"W",n+1); /* uPosition */
560 PACKI(desc,"W",queue->status); /* fsStatus */
561 PACKI(desc,"D",t); /* ulSubmitted */
562 PACKI(desc,"D",queue->size); /* ulSize */
563 PACKS(desc,"z","Samba"); /* pszComment */
564 PACKS(desc,"z",queue->file); /* pszDocument */
566 PACKS(desc,"z",""); /* pszNotifyName */
567 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
568 PACKS(desc,"z",""); /* pszParms */
569 PACKS(desc,"z",""); /* pszStatus */
570 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
571 PACKS(desc,"z","lpd"); /* pszQProcName */
572 PACKS(desc,"z",""); /* pszQProcParms */
573 PACKS(desc,"z","NULL"); /* pszDriverName */
574 PackDriverData(desc); /* pDriverData */
575 PACKS(desc,"z",""); /* pszPrinterName */
580 static void fill_printq_info(int cnum, int snum, int uLevel,
581 struct pack_desc* desc,
582 int count, print_queue_struct* queue,
583 print_status_struct* status)
588 PACKS(desc,"B13",SERVICE(snum));
593 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
597 if (uLevel == 1 || uLevel == 2) {
598 PACKS(desc,"B",""); /* alignment */
599 PACKI(desc,"W",5); /* priority */
600 PACKI(desc,"W",0); /* start time */
601 PACKI(desc,"W",0); /* until time */
602 PACKS(desc,"z",""); /* pSepFile */
603 PACKS(desc,"z","lpd"); /* pPrProc */
604 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
605 PACKS(desc,"z",""); /* pParms */
607 PACKS(desc,"z","UNKNOWN PRINTER");
608 PACKI(desc,"W",LPSTAT_ERROR);
610 else if (!status || !status->message[0]) {
611 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
612 PACKI(desc,"W",LPSTAT_OK); /* status */
614 PACKS(desc,"z",status->message);
615 PACKI(desc,"W",status->status); /* status */
617 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
619 if (uLevel == 3 || uLevel == 4) {
620 PACKI(desc,"W",5); /* uPriority */
621 PACKI(desc,"W",0); /* uStarttime */
622 PACKI(desc,"W",0); /* uUntiltime */
623 PACKI(desc,"W",5); /* pad1 */
624 PACKS(desc,"z",""); /* pszSepFile */
625 PACKS(desc,"z","WinPrint"); /* pszPrProc */
626 PACKS(desc,"z",""); /* pszParms */
627 if (!status || !status->message[0]) {
628 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
629 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
631 PACKS(desc,"z",status->message); /* pszComment */
632 PACKI(desc,"W",status->status); /* fsStatus */
634 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
635 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
636 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
637 PackDriverData(desc); /* pDriverData */
639 if (uLevel == 2 || uLevel == 4) {
641 for (i=0;i<count;i++)
642 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
647 pstring tok,driver,datafile,langmon,helpfile,datatype;
652 pstrcpy(fname,lp_driverfile());
655 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
656 desc->errcode=NERR_notsupported;
660 p=(char *)malloc(8192*sizeof(char));
661 bzero(p, 8192*sizeof(char));
664 /* lookup the long printer driver name in the file description */
665 while (f && !feof(f) && !ok)
667 p = q; /* reset string pointer */
670 if (next_token(&p,tok,":") &&
671 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
672 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
677 /* driver file name */
678 if (ok && !next_token(&p,driver,":")) ok = 0;
680 if (ok && !next_token(&p,datafile,":")) ok = 0;
682 * for the next tokens - which may be empty - I have to check for empty
683 * tokens first because the next_token function will skip all empty
691 } else if (!next_token(&p,helpfile,":")) ok = 0;
695 /* language monitor */
699 } else if (!next_token(&p,langmon,":")) ok = 0;
702 /* default data type */
703 if (ok && !next_token(&p,datatype,":")) ok = 0;
706 PACKI(desc,"W",0x0400); /* don't know */
707 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
708 PACKS(desc,"z",driver); /* Driverfile Name */
709 PACKS(desc,"z",datafile); /* Datafile name */
710 PACKS(desc,"z",langmon); /* language monitor */
711 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
712 PACKS(desc,"z",datatype); /* default data type */
713 PACKS(desc,"z",helpfile); /* helpfile name */
714 PACKS(desc,"z",driver); /* driver name */
715 DEBUG(3,("Driver:%s:\n",driver));
716 DEBUG(3,("Data File:%s:\n",datafile));
717 DEBUG(3,("Language Monitor:%s:\n",langmon));
718 DEBUG(3,("Data Type:%s:\n",datatype));
719 DEBUG(3,("Help File:%s:\n",helpfile));
720 PACKI(desc,"N",count); /* number of files to copy */
721 for (i=0;i<count;i++)
723 /* no need to check return value here - it was already tested in
724 * get_printerdrivernumber
726 next_token(&p,tok,",");
727 PACKS(desc,"z",tok); /* driver files to copy */
728 DEBUG(3,("file:%s:\n",tok));
731 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
732 SERVICE(snum),count));
734 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
735 desc->errcode=NERR_notsupported;
741 /* This function returns the number of files for a given driver */
742 int get_printerdrivernumber(int snum)
750 pstrcpy(fname,lp_driverfile());
752 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
755 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
759 p=(char *)malloc(8192*sizeof(char));
760 q=p; /* need it to free memory because p change ! */
762 /* lookup the long printer driver name in the file description */
763 while (!feof(f) && !ok)
765 p = q; /* reset string pointer */
767 if (next_token(&p,tok,":") &&
768 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
777 if (*p++ == ':') i--;
782 /* count the number of files */
783 while (next_token(&p,tok,","))
791 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
792 int mdrcnt,int mprcnt,
793 char **rdata,char **rparam,
794 int *rdata_len,int *rparam_len)
796 char *str1 = param+2;
797 char *str2 = skip_string(str1,1);
798 char *p = skip_string(str2,1);
804 struct pack_desc desc;
805 print_queue_struct *queue=NULL;
806 print_status_struct status;
808 bzero(&status,sizeof(status));
809 bzero(&desc,sizeof(desc));
811 p = skip_string(p,1);
816 /* remove any trailing username */
817 if ((p = strchr(QueueName,'%'))) *p = 0;
819 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
821 /* check it's a supported varient */
822 if (!prefix_ok(str1,"zWrLh")) return False;
823 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
825 snum = lp_servicenumber(QueueName);
826 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
827 int pnum = lp_servicenumber(PRINTERS_NAME);
829 lp_add_printer(QueueName,pnum);
830 snum = lp_servicenumber(QueueName);
834 if (snum < 0 || !VALID_SNUM(snum)) return(False);
838 count = get_printerdrivernumber(snum);
839 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
842 count = get_printqueue(snum,cnum,&queue,&status);
844 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
846 desc.buflen = mdrcnt;
847 if (init_package(&desc,1,count)) {
848 desc.subcount = count;
849 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
852 *rdata_len = desc.usedlen;
855 *rparam = REALLOC(*rparam,*rparam_len);
856 SSVALS(*rparam,0,desc.errcode);
858 SSVAL(*rparam,4,desc.neededlen);
860 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
862 if (queue) free(queue);
868 /****************************************************************************
869 view list of all print jobs on all queues
870 ****************************************************************************/
871 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
872 int mdrcnt, int mprcnt,
873 char **rdata, char** rparam,
874 int *rdata_len, int *rparam_len)
876 char *param_format = param+2;
877 char *output_format1 = skip_string(param_format,1);
878 char *p = skip_string(output_format1,1);
879 int uLevel = SVAL(p,0);
880 char *output_format2 = p + 4;
881 int services = lp_numservices();
883 struct pack_desc desc;
884 print_queue_struct **queue = NULL;
885 print_status_struct *status = NULL;
886 int* subcntarr = NULL;
887 int queuecnt, subcnt=0, succnt=0;
889 bzero(&desc,sizeof(desc));
891 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
893 if (!prefix_ok(param_format,"WrLeh")) return False;
894 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
897 for (i = 0; i < services; i++)
898 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
901 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
902 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
903 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
904 memset(status,0,queuecnt*sizeof(print_status_struct));
905 subcntarr = (int*)malloc(queuecnt*sizeof(int));
908 for (i = 0; i < services; i++)
909 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
910 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
911 subcnt += subcntarr[n];
915 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
917 desc.buflen = mdrcnt;
919 if (init_package(&desc,queuecnt,subcnt)) {
922 for (i = 0; i < services; i++)
923 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
924 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
926 if (desc.errcode == NERR_Success) succnt = n;
930 if (subcntarr) free(subcntarr);
932 *rdata_len = desc.usedlen;
934 *rparam = REALLOC(*rparam,*rparam_len);
935 SSVALS(*rparam,0,desc.errcode);
937 SSVAL(*rparam,4,succnt);
938 SSVAL(*rparam,6,queuecnt);
940 for (i = 0; i < queuecnt; i++) {
941 if (queue && queue[i]) free(queue[i]);
944 if (queue) free(queue);
945 if (status) free(status);
950 /****************************************************************************
951 get info level for a server list query
952 ****************************************************************************/
953 static BOOL check_server_info(int uLevel, char* id)
957 if (strcmp(id,"B16") != 0) return False;
960 if (strcmp(id,"B16BBDz") != 0) return False;
968 struct srv_info_struct
978 /*******************************************************************
979 get server info lists from the files saved by nmbd. Return the
981 ******************************************************************/
982 static int get_server_info(uint32 servertype,
983 struct srv_info_struct **servers,
991 BOOL local_list_only;
993 pstrcpy(fname,lp_lockdir());
994 trim_string(fname,NULL,"/");
996 pstrcat(fname,SERVER_LIST);
998 f = fopen(fname,"r");
1001 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1005 /* request for everything is code for request all servers */
1006 if (servertype == SV_TYPE_ALL)
1007 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1009 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1011 DEBUG(4,("Servertype search: %8x\n",servertype));
1016 struct srv_info_struct *s;
1021 fgets(line,sizeof(line)-1,f);
1022 if (!*line) continue;
1024 if (count == alloced) {
1026 (*servers) = (struct srv_info_struct *)
1027 Realloc(*servers,sizeof(**servers)*alloced);
1028 if (!(*servers)) return(0);
1029 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1031 s = &(*servers)[count];
1033 if (!next_token(&ptr,s->name , NULL)) continue;
1034 if (!next_token(&ptr,stype , NULL)) continue;
1035 if (!next_token(&ptr,s->comment, NULL)) continue;
1036 if (!next_token(&ptr,s->domain , NULL)) {
1037 /* this allows us to cope with an old nmbd */
1038 pstrcpy(s->domain,global_myworkgroup);
1041 if (sscanf(stype,"%X",&s->type) != 1) {
1042 DEBUG(4,("r:host file "));
1046 /* Filter the servers/domains we return based on what was asked for. */
1048 /* Check to see if we are being asked for a local list only. */
1049 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1050 DEBUG(4,("r: local list only"));
1054 /* doesn't match up: don't want it */
1055 if (!(servertype & s->type)) {
1056 DEBUG(4,("r:serv type "));
1060 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1061 (s->type & SV_TYPE_DOMAIN_ENUM))
1063 DEBUG(4,("s: dom mismatch "));
1067 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1072 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1073 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1077 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1078 s->name, s->type, s->comment, s->domain));
1080 s->server_added = True;
1085 DEBUG(4,("%20s %8x %25s %15s\n",
1086 s->name, s->type, s->comment, s->domain));
1095 /*******************************************************************
1096 fill in a server info structure
1097 ******************************************************************/
1098 static int fill_srv_info(struct srv_info_struct *service,
1099 int uLevel, char **buf, int *buflen,
1100 char **stringbuf, int *stringspace, char *baseaddr)
1109 case 0: struct_len = 16; break;
1110 case 1: struct_len = 26; break;
1120 len = strlen(service->comment)+1;
1124 if (buflen) *buflen = struct_len;
1125 if (stringspace) *stringspace = len;
1126 return struct_len + len;
1131 if (*buflen < struct_len) return -1;
1139 p2 = p + struct_len;
1140 l2 = *buflen - struct_len;
1142 if (!baseaddr) baseaddr = p;
1147 StrnCpy(p,service->name,15);
1151 StrnCpy(p,service->name,15);
1152 SIVAL(p,18,service->type);
1153 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1154 len += CopyAndAdvance(&p2,service->comment,&l2);
1160 *buf = p + struct_len;
1161 *buflen -= struct_len;
1174 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1176 return(strcmp(s1->name,s2->name));
1179 /****************************************************************************
1180 view list of servers available (or possibly domains). The info is
1181 extracted from lists saved by nmbd on the local host
1182 ****************************************************************************/
1183 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1184 int mdrcnt, int mprcnt, char **rdata,
1185 char **rparam, int *rdata_len, int *rparam_len)
1187 char *str1 = param+2;
1188 char *str2 = skip_string(str1,1);
1189 char *p = skip_string(str2,1);
1190 int uLevel = SVAL(p,0);
1191 int buf_len = SVAL(p,2);
1192 uint32 servertype = IVAL(p,4);
1194 int data_len, fixed_len, string_len;
1195 int f_len = 0, s_len = 0;
1196 struct srv_info_struct *servers=NULL;
1197 int counted=0,total=0;
1200 BOOL domain_request;
1203 /* If someone sets all the bits they don't really mean to set
1204 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1207 if (servertype == SV_TYPE_ALL)
1208 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1210 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1211 any other bit (they may just set this bit on it's own) they
1212 want all the locally seen servers. However this bit can be
1213 set on its own so set the requested servers to be
1214 ALL - DOMAIN_ENUM. */
1216 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1217 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1219 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1220 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1224 if (!prefix_ok(str1,"WrLehD")) return False;
1225 if (!check_server_info(uLevel,str2)) return False;
1227 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1228 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1229 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1231 if (strcmp(str1, "WrLehDz") == 0) {
1232 StrnCpy(domain, p, sizeof(fstring)-1);
1234 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1237 if (lp_browse_list())
1238 total = get_server_info(servertype,&servers,domain);
1240 data_len = fixed_len = string_len = 0;
1243 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1246 char *lastname=NULL;
1248 for (i=0;i<total;i++)
1250 struct srv_info_struct *s = &servers[i];
1251 if (lastname && strequal(lastname,s->name)) continue;
1253 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1254 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1255 s->name, s->type, s->comment, s->domain));
1257 if (data_len <= buf_len) {
1260 string_len += s_len;
1267 *rdata_len = fixed_len + string_len;
1268 *rdata = REALLOC(*rdata,*rdata_len);
1269 bzero(*rdata,*rdata_len);
1271 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1277 char *lastname=NULL;
1278 int count2 = counted;
1279 for (i = 0; i < total && count2;i++)
1281 struct srv_info_struct *s = &servers[i];
1282 if (lastname && strequal(lastname,s->name)) continue;
1284 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1285 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1286 s->name, s->type, s->comment, s->domain));
1292 *rparam = REALLOC(*rparam,*rparam_len);
1293 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1295 SSVAL(*rparam,4,counted);
1296 SSVAL(*rparam,6,counted+missed);
1298 if (servers) free(servers);
1300 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1301 domain,uLevel,counted,counted+missed));
1306 /****************************************************************************
1307 command 0x34 - suspected of being a "Lookup Names" stub api
1308 ****************************************************************************/
1309 static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data,
1310 int mdrcnt, int mprcnt, char **rdata,
1311 char **rparam, int *rdata_len, int *rparam_len)
1313 char *str1 = param+2;
1314 char *str2 = skip_string(str1,1);
1315 char *p = skip_string(str2,1);
1316 int uLevel = SVAL(p,0);
1317 int buf_len = SVAL(p,2);
1321 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1322 str1, str2, p, uLevel, buf_len));
1324 if (!prefix_ok(str1,"zWrLeh")) return False;
1330 *rparam = REALLOC(*rparam,*rparam_len);
1332 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1334 SSVAL(*rparam,4,counted);
1335 SSVAL(*rparam,6,counted+missed);
1340 /****************************************************************************
1341 get info about a share
1342 ****************************************************************************/
1343 static BOOL check_share_info(int uLevel, char* id)
1347 if (strcmp(id,"B13") != 0) return False;
1350 if (strcmp(id,"B13BWz") != 0) return False;
1353 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1356 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1358 default: return False;
1363 static int fill_share_info(int cnum, int snum, int uLevel,
1364 char** buf, int* buflen,
1365 char** stringbuf, int* stringspace, char* baseaddr)
1374 case 0: struct_len = 13; break;
1375 case 1: struct_len = 20; break;
1376 case 2: struct_len = 40; break;
1377 case 91: struct_len = 68; break;
1385 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1386 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1387 if (buflen) *buflen = struct_len;
1388 if (stringspace) *stringspace = len;
1389 return struct_len + len;
1394 if ((*buflen) < struct_len) return -1;
1402 p2 = p + struct_len;
1403 l2 = (*buflen) - struct_len;
1405 if (!baseaddr) baseaddr = p;
1407 StrnCpy(p,lp_servicename(snum),13);
1413 type = STYPE_DISKTREE;
1414 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1415 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1416 SSVAL(p,14,type); /* device type */
1417 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1418 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1423 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1424 SSVALS(p,22,-1); /* max uses */
1425 SSVAL(p,24,1); /* current uses */
1426 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1427 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1428 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1433 memset(p+40,0,SHPWLEN+2);
1445 (*buf) = p + struct_len;
1446 (*buflen) -= struct_len;
1448 (*stringspace) = l2;
1458 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1459 int mdrcnt,int mprcnt,
1460 char **rdata,char **rparam,
1461 int *rdata_len,int *rparam_len)
1463 char *str1 = param+2;
1464 char *str2 = skip_string(str1,1);
1465 char *netname = skip_string(str2,1);
1466 char *p = skip_string(netname,1);
1467 int uLevel = SVAL(p,0);
1468 int snum = find_service(netname);
1470 if (snum < 0) return False;
1472 /* check it's a supported varient */
1473 if (!prefix_ok(str1,"zWrLh")) return False;
1474 if (!check_share_info(uLevel,str2)) return False;
1476 *rdata = REALLOC(*rdata,mdrcnt);
1478 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1479 if (*rdata_len < 0) return False;
1482 *rparam = REALLOC(*rparam,*rparam_len);
1483 SSVAL(*rparam,0,NERR_Success);
1484 SSVAL(*rparam,2,0); /* converter word */
1485 SSVAL(*rparam,4,*rdata_len);
1490 /****************************************************************************
1491 view list of shares available
1492 ****************************************************************************/
1493 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1494 int mdrcnt,int mprcnt,
1495 char **rdata,char **rparam,
1496 int *rdata_len,int *rparam_len)
1498 char *str1 = param+2;
1499 char *str2 = skip_string(str1,1);
1500 char *p = skip_string(str2,1);
1501 int uLevel = SVAL(p,0);
1502 int buf_len = SVAL(p,2);
1504 int count=lp_numservices();
1505 int total=0,counted=0;
1506 BOOL missed = False;
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;
1529 *rdata_len = fixed_len + string_len;
1530 *rdata = REALLOC(*rdata,*rdata_len);
1531 memset(*rdata,0,*rdata_len);
1533 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1537 for (i = 0; i < count;i++)
1538 if (lp_browseable(i) && lp_snum_ok(i))
1539 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1543 *rparam = REALLOC(*rparam,*rparam_len);
1544 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1546 SSVAL(*rparam,4,counted);
1547 SSVAL(*rparam,6,total);
1549 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1550 counted,total,uLevel,
1551 buf_len,*rdata_len,mdrcnt));
1557 /****************************************************************************
1558 get the time of day info
1559 ****************************************************************************/
1560 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1561 int mdrcnt,int mprcnt,
1562 char **rdata,char **rparam,
1563 int *rdata_len,int *rparam_len)
1567 *rparam = REALLOC(*rparam,*rparam_len);
1570 *rdata = REALLOC(*rdata,*rdata_len);
1572 SSVAL(*rparam,0,NERR_Success);
1573 SSVAL(*rparam,2,0); /* converter word */
1579 time_t unixdate = time(NULL);
1581 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1582 by NT in a "net time" operation,
1583 it seems to ignore the one below */
1585 /* the client expects to get localtime, not GMT, in this bit
1586 (I think, this needs testing) */
1587 t = LocalTime(&unixdate);
1589 SIVAL(p,4,0); /* msecs ? */
1590 CVAL(p,8) = t->tm_hour;
1591 CVAL(p,9) = t->tm_min;
1592 CVAL(p,10) = t->tm_sec;
1593 CVAL(p,11) = 0; /* hundredths of seconds */
1594 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1595 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1596 CVAL(p,16) = t->tm_mday;
1597 CVAL(p,17) = t->tm_mon + 1;
1598 SSVAL(p,18,1900+t->tm_year);
1599 CVAL(p,20) = t->tm_wday;
1606 /****************************************************************************
1607 set the user password
1608 ****************************************************************************/
1609 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1610 int mdrcnt,int mprcnt,
1611 char **rdata,char **rparam,
1612 int *rdata_len,int *rparam_len)
1614 char *p = skip_string(param+2,2);
1616 fstring pass1,pass2;
1620 p = skip_string(p,1);
1623 memcpy(pass2,p+16,16);
1626 *rparam = REALLOC(*rparam,*rparam_len);
1630 SSVAL(*rparam,0,NERR_badpass);
1631 SSVAL(*rparam,2,0); /* converter word */
1633 DEBUG(3,("Set password for <%s>\n",user));
1636 * Pass the user through the NT -> unix user mapping
1643 * Do any UNIX username case mangling.
1645 (void)Get_Pwnam( user, True);
1648 * Attempt the plaintext password change first.
1649 * Older versions of Windows seem to do this.
1652 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1653 chgpasswd(user,pass1,pass2,False))
1655 SSVAL(*rparam,0,NERR_Success);
1659 * If the plaintext change failed, attempt
1660 * the encrypted. NT will generate this
1661 * after trying the samr method.
1664 if(SVAL(*rparam,0) != NERR_Success)
1666 struct smb_passwd *sampw = NULL;
1668 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1669 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1671 SSVAL(*rparam,0,NERR_Success);
1675 bzero(pass1,sizeof(fstring));
1676 bzero(pass2,sizeof(fstring));
1681 /****************************************************************************
1682 Set the user password (SamOEM version - gets plaintext).
1683 ****************************************************************************/
1685 static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
1686 int mdrcnt,int mprcnt,
1687 char **rdata,char **rparam,
1688 int *rdata_len,int *rparam_len)
1692 struct smb_passwd *sampw = NULL;
1693 char *p = param + 2;
1697 *rparam = REALLOC(*rparam,*rparam_len);
1701 SSVAL(*rparam,0,NERR_badpass);
1704 * Check the parameter definition is correct.
1706 if(!strequal(param + 2, "zsT")) {
1707 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1710 p = skip_string(p, 1);
1712 if(!strequal(p, "B516B16")) {
1713 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1716 p = skip_string(p,1);
1719 p = skip_string(p,1);
1721 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1724 * Pass the user through the NT -> unix user mapping
1731 * Do any UNIX username case mangling.
1733 (void)Get_Pwnam( user, True);
1735 if(check_oem_password( user, (unsigned char *)data, &sampw,
1736 new_passwd, (int)sizeof(new_passwd)) == False) {
1741 * At this point we have the new case-sensitive plaintext
1742 * password in the fstring new_passwd. If we wanted to synchronise
1743 * with UNIX passwords we would call a UNIX password changing
1744 * function here. However it would have to be done as root
1745 * as the plaintext of the old users password is not
1749 if(lp_unix_password_sync())
1750 ret = chgpasswd(user,"", new_passwd, True);
1752 if(ret && change_oem_password( sampw, new_passwd, False)) {
1753 SSVAL(*rparam,0,NERR_Success);
1759 /****************************************************************************
1762 ****************************************************************************/
1763 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1764 int mdrcnt,int mprcnt,
1765 char **rdata,char **rparam,
1766 int *rdata_len,int *rparam_len)
1768 int function = SVAL(param,0);
1769 char *str1 = param+2;
1770 char *str2 = skip_string(str1,1);
1771 char *p = skip_string(str2,1);
1775 printjob_decode(SVAL(p,0), &snum, &jobid);
1777 /* check it's a supported varient */
1778 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1782 *rparam = REALLOC(*rparam,*rparam_len);
1786 SSVAL(*rparam,0,NERR_Success);
1788 if (snum >= 0 && VALID_SNUM(snum))
1790 print_queue_struct *queue=NULL;
1792 count = get_printqueue(snum,cnum,&queue,NULL);
1794 for (i=0;i<count;i++)
1795 if ((queue[i].job&0xFF) == jobid)
1798 case 81: /* delete */
1799 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1800 del_printqueue(cnum,snum,queue[i].job);
1802 case 82: /* pause */
1803 case 83: /* resume */
1804 DEBUG(3,("%s queue entry %d\n",
1805 (function==82?"pausing":"resuming"),queue[i].job));
1806 status_printjob(cnum,snum,queue[i].job,
1807 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1814 SSVAL(*rparam,0,NERR_JobNotFound);
1816 if (queue) free(queue);
1819 SSVAL(*rparam,2,0); /* converter word */
1824 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1825 int mdrcnt,int mprcnt,
1826 char **rdata,char **rparam,
1827 int *rdata_len,int *rparam_len)
1829 char *str1 = param+2;
1830 char *str2 = skip_string(str1,1);
1831 char *QueueName = skip_string(str2,1);
1834 /* check it's a supported varient */
1835 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1839 *rparam = REALLOC(*rparam,*rparam_len);
1843 SSVAL(*rparam,0,NERR_Success);
1844 SSVAL(*rparam,2,0); /* converter word */
1846 snum = lp_servicenumber(QueueName);
1847 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1848 int pnum = lp_servicenumber(PRINTERS_NAME);
1850 lp_add_printer(QueueName,pnum);
1851 snum = lp_servicenumber(QueueName);
1855 if (snum >= 0 && VALID_SNUM(snum)) {
1856 print_queue_struct *queue=NULL;
1860 count = get_printqueue(snum,cnum,&queue,NULL);
1861 for (i = 0; i < count; i++)
1862 del_printqueue(cnum,snum,queue[i].job);
1864 if (queue) free(queue);
1867 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1873 /****************************************************************************
1874 set the property of a print job (undocumented?)
1875 ? function = 0xb -> set name of print job
1876 ? function = 0x6 -> move print job up/down
1877 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1878 or <WWsTP> <WB21BB16B10zWWzDDz>
1879 ****************************************************************************/
1880 static int check_printjob_info(struct pack_desc* desc,
1881 int uLevel, char* id)
1883 desc->subformat = NULL;
1885 case 0: desc->format = "W"; break;
1886 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1887 case 2: desc->format = "WWzWWDDzz"; break;
1888 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1889 default: return False;
1891 if (strcmp(desc->format,id) != 0) return False;
1895 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1896 int mdrcnt,int mprcnt,
1897 char **rdata,char **rparam,
1898 int *rdata_len,int *rparam_len)
1900 struct pack_desc desc;
1901 char *str1 = param+2;
1902 char *str2 = skip_string(str1,1);
1903 char *p = skip_string(str2,1);
1905 int uLevel = SVAL(p,2);
1906 int function = SVAL(p,4); /* what is this ?? */
1910 printjob_decode(SVAL(p,0), &snum, &jobid);
1913 *rparam = REALLOC(*rparam,*rparam_len);
1917 /* check it's a supported varient */
1918 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1922 case 0x6: /* change job place in the queue, data gives the new place */
1923 if (snum >= 0 && VALID_SNUM(snum))
1925 print_queue_struct *queue=NULL;
1929 count = get_printqueue(snum,cnum,&queue,NULL);
1930 for (i=0;i<count;i++) /* find job */
1931 if ((queue[i].job&0xFF) == jobid) break;
1934 desc.errcode=NERR_JobNotFound;
1935 if (queue) free(queue);
1938 desc.errcode=NERR_Success;
1942 int place= SVAL(data,0);
1943 /* we currently have no way of doing this. Can any unix do it? */
1944 if (i < place) /* move down */;
1945 else if (i > place ) /* move up */;
1948 desc.errcode=NERR_notsupported; /* not yet supported */
1949 if (queue) free(queue);
1952 else desc.errcode=NERR_JobNotFound;
1954 case 0xb: /* change print job name, data gives the name */
1955 /* jobid, snum should be zero */
1962 if (issafe(*s)) name[l++] = *s;
1967 DEBUG(3,("Setting print name to %s\n",name));
1971 for (i=0;i<MAX_OPEN_FILES;i++)
1972 if (Files[i].open && Files[i].print_file)
1975 int fcnum = Files[i].cnum;
1979 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1980 !become_service(fcnum,True))
1983 if (sys_rename(Files[i].name,name) == 0)
1984 string_set(&Files[i].name,name);
1988 unbecome_root(True);
1990 desc.errcode=NERR_Success;
1993 default: /* not implemented */
1997 SSVALS(*rparam,0,desc.errcode);
1998 SSVAL(*rparam,2,0); /* converter word */
2004 /****************************************************************************
2005 get info about the server
2006 ****************************************************************************/
2007 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
2008 int mdrcnt,int mprcnt,
2009 char **rdata,char **rparam,
2010 int *rdata_len,int *rparam_len)
2012 char *str1 = param+2;
2013 char *str2 = skip_string(str1,1);
2014 char *p = skip_string(str2,1);
2015 int uLevel = SVAL(p,0);
2019 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2021 /* check it's a supported varient */
2022 if (!prefix_ok(str1,"WrLh")) return False;
2025 if (strcmp(str2,"B16") != 0) return False;
2029 if (strcmp(str2,"B16BBDz") != 0) return False;
2033 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2038 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2043 if (strcmp(str2,"DN") != 0) return False;
2047 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2050 default: return False;
2053 *rdata_len = mdrcnt;
2054 *rdata = REALLOC(*rdata,*rdata_len);
2057 p2 = p + struct_len;
2059 StrnCpy(p,local_machine,16);
2065 struct srv_info_struct *servers=NULL;
2068 uint32 servertype= lp_default_server_announce();
2070 pstrcpy(comment,lp_serverstring());
2072 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2073 for (i=0;i<count;i++)
2074 if (strequal(servers[i].name,local_machine))
2076 servertype = servers[i].type;
2077 pstrcpy(comment,servers[i].comment);
2080 if (servers) free(servers);
2082 SCVAL(p,0,lp_major_announce_version());
2083 SCVAL(p,1,lp_minor_announce_version());
2084 SIVAL(p,2,servertype);
2086 if (mdrcnt == struct_len) {
2089 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2090 standard_sub(cnum,comment);
2091 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2092 p2 = skip_string(p2,1);
2097 return False; /* not yet implemented */
2100 *rdata_len = PTR_DIFF(p2,*rdata);
2103 *rparam = REALLOC(*rparam,*rparam_len);
2104 SSVAL(*rparam,0,NERR_Success);
2105 SSVAL(*rparam,2,0); /* converter word */
2106 SSVAL(*rparam,4,*rdata_len);
2112 /****************************************************************************
2113 get info about the server
2114 ****************************************************************************/
2115 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
2116 int mdrcnt,int mprcnt,
2117 char **rdata,char **rparam,
2118 int *rdata_len,int *rparam_len)
2120 char *str1 = param+2;
2121 char *str2 = skip_string(str1,1);
2122 char *p = skip_string(str2,1);
2124 extern pstring sesssetup_user;
2125 int level = SVAL(p,0);
2127 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2130 *rparam = REALLOC(*rparam,*rparam_len);
2132 /* check it's a supported varient */
2133 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2136 *rdata_len = mdrcnt + 1024;
2137 *rdata = REALLOC(*rdata,*rdata_len);
2139 SSVAL(*rparam,0,NERR_Success);
2140 SSVAL(*rparam,2,0); /* converter word */
2146 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2147 pstrcpy(p2,local_machine);
2149 p2 = skip_string(p2,1);
2152 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2153 pstrcpy(p2,sesssetup_user);
2154 p2 = skip_string(p2,1);
2157 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2158 pstrcpy(p2,global_myworkgroup);
2160 p2 = skip_string(p2,1);
2163 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2164 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2167 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2168 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2169 p2 = skip_string(p2,1);
2172 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2174 p2 = skip_string(p2,1);
2177 *rdata_len = PTR_DIFF(p2,*rdata);
2179 SSVAL(*rparam,4,*rdata_len);
2184 /****************************************************************************
2185 get info about a user
2187 struct user_info_11 {
2188 char usri11_name[21]; 0-20
2190 char *usri11_comment; 22-25
2191 char *usri11_usr_comment; 26-29
2192 unsigned short usri11_priv; 30-31
2193 unsigned long usri11_auth_flags; 32-35
2194 long usri11_password_age; 36-39
2195 char *usri11_homedir; 40-43
2196 char *usri11_parms; 44-47
2197 long usri11_last_logon; 48-51
2198 long usri11_last_logoff; 52-55
2199 unsigned short usri11_bad_pw_count; 56-57
2200 unsigned short usri11_num_logons; 58-59
2201 char *usri11_logon_server; 60-63
2202 unsigned short usri11_country_code; 64-65
2203 char *usri11_workstations; 66-69
2204 unsigned long usri11_max_storage; 70-73
2205 unsigned short usri11_units_per_week; 74-75
2206 unsigned char *usri11_logon_hours; 76-79
2207 unsigned short usri11_code_page; 80-81
2212 usri11_name specifies the user name for which information is retireved
2214 usri11_pad aligns the next data structure element to a word boundary
2216 usri11_comment is a null terminated ASCII comment
2218 usri11_user_comment is a null terminated ASCII comment about the user
2220 usri11_priv specifies the level of the privilege assigned to the user.
2221 The possible values are:
2223 Name Value Description
2224 USER_PRIV_GUEST 0 Guest privilege
2225 USER_PRIV_USER 1 User privilege
2226 USER_PRV_ADMIN 2 Administrator privilege
2228 usri11_auth_flags specifies the account operator privileges. The
2229 possible values are:
2231 Name Value Description
2232 AF_OP_PRINT 0 Print operator
2235 Leach, Naik [Page 28]
\r\f
2238 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2241 AF_OP_COMM 1 Communications operator
2242 AF_OP_SERVER 2 Server operator
2243 AF_OP_ACCOUNTS 3 Accounts operator
2246 usri11_password_age specifies how many seconds have elapsed since the
2247 password was last changed.
2249 usri11_home_dir points to a null terminated ASCII string that contains
2250 the path name of the user's home directory.
2252 usri11_parms points to a null terminated ASCII string that is set
2253 aside for use by applications.
2255 usri11_last_logon specifies the time when the user last logged on.
2256 This value is stored as the number of seconds elapsed since
2257 00:00:00, January 1, 1970.
2259 usri11_last_logoff specifies the time when the user last logged off.
2260 This value is stored as the number of seconds elapsed since
2261 00:00:00, January 1, 1970. A value of 0 means the last logoff
2264 usri11_bad_pw_count specifies the number of incorrect passwords
2265 entered since the last successful logon.
2267 usri11_log1_num_logons specifies the number of times this user has
2268 logged on. A value of -1 means the number of logons is unknown.
2270 usri11_logon_server points to a null terminated ASCII string that
2271 contains the name of the server to which logon requests are sent.
2272 A null string indicates logon requests should be sent to the
2275 usri11_country_code specifies the country code for the user's language
2278 usri11_workstations points to a null terminated ASCII string that
2279 contains the names of workstations the user may log on from.
2280 There may be up to 8 workstations, with the names separated by
2281 commas. A null strings indicates there are no restrictions.
2283 usri11_max_storage specifies the maximum amount of disk space the user
2284 can occupy. A value of 0xffffffff indicates there are no
2287 usri11_units_per_week specifies the equal number of time units into
2288 which a week is divided. This value must be equal to 168.
2290 usri11_logon_hours points to a 21 byte (168 bits) string that
2291 specifies the time during which the user can log on. Each bit
2292 represents one unique hour in a week. The first bit (bit 0, word
2293 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2297 Leach, Naik [Page 29]
\r\f
2300 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2303 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2304 are no restrictions.
2306 usri11_code_page specifies the code page for the user's language of
2309 All of the pointers in this data structure need to be treated
2310 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2311 to be ignored. The converter word returned in the parameters section
2312 needs to be subtracted from the lower 16 bits to calculate an offset
2313 into the return buffer where this ASCII string resides.
2315 There is no auxiliary data in the response.
2317 ****************************************************************************/
2319 #define usri11_name 0
2320 #define usri11_pad 21
2321 #define usri11_comment 22
2322 #define usri11_usr_comment 26
2323 #define usri11_full_name 30
2324 #define usri11_priv 34
2325 #define usri11_auth_flags 36
2326 #define usri11_password_age 40
2327 #define usri11_homedir 44
2328 #define usri11_parms 48
2329 #define usri11_last_logon 52
2330 #define usri11_last_logoff 56
2331 #define usri11_bad_pw_count 60
2332 #define usri11_num_logons 62
2333 #define usri11_logon_server 64
2334 #define usri11_country_code 68
2335 #define usri11_workstations 70
2336 #define usri11_max_storage 74
2337 #define usri11_units_per_week 78
2338 #define usri11_logon_hours 80
2339 #define usri11_code_page 84
2340 #define usri11_end 86
2342 #define USER_PRIV_GUEST 0
2343 #define USER_PRIV_USER 1
2344 #define USER_PRIV_ADMIN 2
2346 #define AF_OP_PRINT 0
2347 #define AF_OP_COMM 1
2348 #define AF_OP_SERVER 2
2349 #define AF_OP_ACCOUNTS 3
2352 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2353 int mdrcnt,int mprcnt,
2354 char **rdata,char **rparam,
2355 int *rdata_len,int *rparam_len)
2357 char *str1 = param+2;
2358 char *str2 = skip_string(str1,1);
2359 char *UserName = skip_string(str2,1);
2360 char *p = skip_string(UserName,1);
2361 int uLevel = SVAL(p,0);
2364 /* get NIS home of a previously validated user - simeon */
2365 /* With share level security vuid will always be zero.
2366 Don't depend on vuser being non-null !!. JRA */
2367 user_struct *vuser = get_valid_user_struct(vuid);
2369 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2372 *rparam = REALLOC(*rparam,*rparam_len);
2374 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2376 /* check it's a supported variant */
2377 if (strcmp(str1,"zWrLh") != 0) return False;
2380 case 0: p2 = "B21"; break;
2381 case 1: p2 = "B21BB16DWzzWz"; break;
2382 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2383 case 10: p2 = "B21Bzzz"; break;
2384 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2385 default: return False;
2388 if (strcmp(p2,str2) != 0) return False;
2390 *rdata_len = mdrcnt + 1024;
2391 *rdata = REALLOC(*rdata,*rdata_len);
2393 SSVAL(*rparam,0,NERR_Success);
2394 SSVAL(*rparam,2,0); /* converter word */
2397 p2 = p + usri11_end;
2400 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2404 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2409 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2410 pstrcpy(p2,"Comment");
2411 p2 = skip_string(p2,1);
2413 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2414 pstrcpy(p2,"UserComment");
2415 p2 = skip_string(p2,1);
2417 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2418 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2419 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2420 p2 = skip_string(p2,1);
2423 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2425 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2426 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2427 SIVALS(p,usri11_password_age,-1); /* password age */
2428 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2429 pstrcpy(p2, lp_logon_path());
2430 p2 = skip_string(p2,1);
2431 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2433 p2 = skip_string(p2,1);
2434 SIVAL(p,usri11_last_logon,0); /* last logon */
2435 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2436 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2437 SSVALS(p,usri11_num_logons,-1); /* num logons */
2438 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2439 pstrcpy(p2,"\\\\*");
2440 p2 = skip_string(p2,1);
2441 SSVAL(p,usri11_country_code,0); /* country code */
2443 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2445 p2 = skip_string(p2,1);
2447 SIVALS(p,usri11_max_storage,-1); /* max storage */
2448 SSVAL(p,usri11_units_per_week,168); /* units per week */
2449 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2451 /* a simple way to get logon hours at all times. */
2453 SCVAL(p2,21,0); /* fix zero termination */
2454 p2 = skip_string(p2,1);
2456 SSVAL(p,usri11_code_page,0); /* code page */
2458 if (uLevel == 1 || uLevel == 2)
2460 memset(p+22,' ',16); /* password */
2461 SIVALS(p,38,-1); /* password age */
2463 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2464 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2465 pstrcpy(p2,lp_logon_path());
2466 p2 = skip_string(p2,1);
2467 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2469 SSVAL(p,52,0); /* flags */
2470 SIVAL(p,54,0); /* script_path */
2473 SIVAL(p,60,0); /* auth_flags */
2474 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2475 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2476 p2 = skip_string(p2,1);
2477 SIVAL(p,68,0); /* urs_comment */
2478 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2480 p2 = skip_string(p2,1);
2481 SIVAL(p,76,0); /* workstations */
2482 SIVAL(p,80,0); /* last_logon */
2483 SIVAL(p,84,0); /* last_logoff */
2484 SIVALS(p,88,-1); /* acct_expires */
2485 SIVALS(p,92,-1); /* max_storage */
2486 SSVAL(p,96,168); /* units_per_week */
2487 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2490 SSVALS(p,102,-1); /* bad_pw_count */
2491 SSVALS(p,104,-1); /* num_logons */
2492 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2493 pstrcpy(p2,"\\\\%L");
2494 standard_sub_basic(p2);
2495 p2 = skip_string(p2,1);
2496 SSVAL(p,110,49); /* country_code */
2497 SSVAL(p,112,860); /* code page */
2501 *rdata_len = PTR_DIFF(p2,*rdata);
2503 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2508 /*******************************************************************
2509 get groups that a user is a member of
2510 ******************************************************************/
2511 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2512 int mdrcnt,int mprcnt,
2513 char **rdata,char **rparam,
2514 int *rdata_len,int *rparam_len)
2516 char *str1 = param+2;
2517 char *str2 = skip_string(str1,1);
2518 char *UserName = skip_string(str2,1);
2519 char *p = skip_string(UserName,1);
2520 int uLevel = SVAL(p,0);
2525 *rparam = REALLOC(*rparam,*rparam_len);
2527 /* check it's a supported varient */
2528 if (strcmp(str1,"zWrLeh") != 0) return False;
2530 case 0: p2 = "B21"; break;
2531 default: return False;
2533 if (strcmp(p2,str2) != 0) return False;
2535 *rdata_len = mdrcnt + 1024;
2536 *rdata = REALLOC(*rdata,*rdata_len);
2538 SSVAL(*rparam,0,NERR_Success);
2539 SSVAL(*rparam,2,0); /* converter word */
2543 /* XXXX we need a real SAM database some day */
2544 pstrcpy(p,"Users"); p += 21; count++;
2545 pstrcpy(p,"Domain Users"); p += 21; count++;
2546 pstrcpy(p,"Guests"); p += 21; count++;
2547 pstrcpy(p,"Domain Guests"); p += 21; count++;
2549 *rdata_len = PTR_DIFF(p,*rdata);
2551 SSVAL(*rparam,4,count); /* is this right?? */
2552 SSVAL(*rparam,6,count); /* is this right?? */
2558 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2559 int mdrcnt,int mprcnt,
2560 char **rdata,char **rparam,
2561 int *rdata_len,int *rparam_len)
2563 char *str1 = param+2;
2564 char *str2 = skip_string(str1,1);
2565 char *p = skip_string(str2,1);
2567 struct pack_desc desc;
2574 bzero(&desc,sizeof(desc));
2576 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2578 /* check it's a supported varient */
2579 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2580 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2581 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2583 desc.buflen = mdrcnt;
2584 desc.subformat = NULL;
2587 if (init_package(&desc,1,0))
2589 PACKI(&desc,"W",0); /* code */
2590 PACKS(&desc,"B21",name); /* eff. name */
2591 PACKS(&desc,"B",""); /* pad */
2593 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2594 PACKI(&desc,"D",0); /* auth flags XXX */
2595 PACKI(&desc,"W",0); /* num logons */
2596 PACKI(&desc,"W",0); /* bad pw count */
2597 PACKI(&desc,"D",0); /* last logon */
2598 PACKI(&desc,"D",-1); /* last logoff */
2599 PACKI(&desc,"D",-1); /* logoff time */
2600 PACKI(&desc,"D",-1); /* kickoff time */
2601 PACKI(&desc,"D",0); /* password age */
2602 PACKI(&desc,"D",0); /* password can change */
2603 PACKI(&desc,"D",-1); /* password must change */
2606 fstrcpy(mypath,"\\\\");
2607 fstrcat(mypath,local_machine);
2609 PACKS(&desc,"z",mypath); /* computer */
2611 PACKS(&desc,"z",global_myworkgroup);/* domain */
2613 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2614 /* made sure all macros are fully substituted and available */
2615 logon_script = lp_logon_script();
2616 standard_sub( cnum, logon_script );
2617 PACKS(&desc,"z", logon_script); /* script path */
2618 /* End of JHT mods */
2620 PACKI(&desc,"D",0x00000000); /* reserved */
2623 *rdata_len = desc.usedlen;
2625 *rparam = REALLOC(*rparam,*rparam_len);
2626 SSVALS(*rparam,0,desc.errcode);
2628 SSVAL(*rparam,4,desc.neededlen);
2630 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2635 /****************************************************************************
2636 api_WAccessGetUserPerms
2637 ****************************************************************************/
2638 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2639 int mdrcnt,int mprcnt,
2640 char **rdata,char **rparam,
2641 int *rdata_len,int *rparam_len)
2643 char *str1 = param+2;
2644 char *str2 = skip_string(str1,1);
2645 char *user = skip_string(str2,1);
2646 char *resource = skip_string(user,1);
2648 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2650 /* check it's a supported varient */
2651 if (strcmp(str1,"zzh") != 0) return False;
2652 if (strcmp(str2,"") != 0) return False;
2655 *rparam = REALLOC(*rparam,*rparam_len);
2656 SSVALS(*rparam,0,0); /* errorcode */
2657 SSVAL(*rparam,2,0); /* converter word */
2658 SSVAL(*rparam,4,0x7f); /* permission flags */
2663 /****************************************************************************
2664 api_WPrintJobEnumerate
2665 ****************************************************************************/
2666 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2667 int mdrcnt,int mprcnt,
2668 char **rdata,char **rparam,
2669 int *rdata_len,int *rparam_len)
2671 char *str1 = param+2;
2672 char *str2 = skip_string(str1,1);
2673 char *p = skip_string(str2,1);
2679 struct pack_desc desc;
2680 print_queue_struct *queue=NULL;
2681 print_status_struct status;
2686 bzero(&desc,sizeof(desc));
2687 bzero(&status,sizeof(status));
2689 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2691 /* check it's a supported varient */
2692 if (strcmp(str1,"WWrLh") != 0) return False;
2693 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2695 printjob_decode(SVAL(p,0), &snum, &job);
2697 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2699 count = get_printqueue(snum,cnum,&queue,&status);
2700 for (i = 0; i < count; i++) {
2701 if ((queue[i].job & 0xFF) == job) break;
2703 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2705 desc.buflen = mdrcnt;
2707 if (init_package(&desc,1,0)) {
2709 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2710 *rdata_len = desc.usedlen;
2713 desc.errcode = NERR_JobNotFound;
2719 *rparam = REALLOC(*rparam,*rparam_len);
2720 SSVALS(*rparam,0,desc.errcode);
2722 SSVAL(*rparam,4,desc.neededlen);
2724 if (queue) free(queue);
2726 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2730 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2731 int mdrcnt,int mprcnt,
2732 char **rdata,char **rparam,
2733 int *rdata_len,int *rparam_len)
2735 char *str1 = param+2;
2736 char *str2 = skip_string(str1,1);
2737 char *p = skip_string(str2,1);
2743 struct pack_desc desc;
2744 print_queue_struct *queue=NULL;
2745 print_status_struct status;
2747 bzero(&desc,sizeof(desc));
2748 bzero(&status,sizeof(status));
2750 p = skip_string(p,1);
2754 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2756 /* check it's a supported varient */
2757 if (strcmp(str1,"zWrLeh") != 0) return False;
2758 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2759 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2761 snum = lp_servicenumber(name);
2762 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2763 int pnum = lp_servicenumber(PRINTERS_NAME);
2765 lp_add_printer(name,pnum);
2766 snum = lp_servicenumber(name);
2770 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2772 count = get_printqueue(snum,cnum,&queue,&status);
2773 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2775 desc.buflen = mdrcnt;
2777 if (init_package(&desc,count,0)) {
2779 for (i = 0; i < count; i++) {
2780 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2781 if (desc.errcode == NERR_Success) succnt = i+1;
2785 *rdata_len = desc.usedlen;
2788 *rparam = REALLOC(*rparam,*rparam_len);
2789 SSVALS(*rparam,0,desc.errcode);
2791 SSVAL(*rparam,4,succnt);
2792 SSVAL(*rparam,6,count);
2794 if (queue) free(queue);
2796 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2800 static int check_printdest_info(struct pack_desc* desc,
2801 int uLevel, char* id)
2803 desc->subformat = NULL;
2805 case 0: desc->format = "B9"; break;
2806 case 1: desc->format = "B9B21WWzW"; break;
2807 case 2: desc->format = "z"; break;
2808 case 3: desc->format = "zzzWWzzzWW"; break;
2809 default: return False;
2811 if (strcmp(desc->format,id) != 0) return False;
2815 static void fill_printdest_info(int cnum, int snum, int uLevel,
2816 struct pack_desc* desc)
2819 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2820 buf[sizeof(buf)-1] = 0;
2823 PACKS(desc,"B9",buf); /* szName */
2825 PACKS(desc,"B21",""); /* szUserName */
2826 PACKI(desc,"W",0); /* uJobId */
2827 PACKI(desc,"W",0); /* fsStatus */
2828 PACKS(desc,"z",""); /* pszStatus */
2829 PACKI(desc,"W",0); /* time */
2832 if (uLevel == 2 || uLevel == 3) {
2833 PACKS(desc,"z",buf); /* pszPrinterName */
2835 PACKS(desc,"z",""); /* pszUserName */
2836 PACKS(desc,"z",""); /* pszLogAddr */
2837 PACKI(desc,"W",0); /* uJobId */
2838 PACKI(desc,"W",0); /* fsStatus */
2839 PACKS(desc,"z",""); /* pszStatus */
2840 PACKS(desc,"z",""); /* pszComment */
2841 PACKS(desc,"z","NULL"); /* pszDrivers */
2842 PACKI(desc,"W",0); /* time */
2843 PACKI(desc,"W",0); /* pad1 */
2848 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2849 int mdrcnt,int mprcnt,
2850 char **rdata,char **rparam,
2851 int *rdata_len,int *rparam_len)
2853 char *str1 = param+2;
2854 char *str2 = skip_string(str1,1);
2855 char *p = skip_string(str2,1);
2856 char* PrinterName = p;
2858 struct pack_desc desc;
2861 bzero(&desc,sizeof(desc));
2863 p = skip_string(p,1);
2867 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2869 /* check it's a supported varient */
2870 if (strcmp(str1,"zWrLh") != 0) return False;
2871 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2873 snum = lp_servicenumber(PrinterName);
2874 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2875 int pnum = lp_servicenumber(PRINTERS_NAME);
2877 lp_add_printer(PrinterName,pnum);
2878 snum = lp_servicenumber(PrinterName);
2884 desc.errcode = NERR_DestNotFound;
2888 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2890 desc.buflen = mdrcnt;
2891 if (init_package(&desc,1,0)) {
2892 fill_printdest_info(cnum,snum,uLevel,&desc);
2894 *rdata_len = desc.usedlen;
2898 *rparam = REALLOC(*rparam,*rparam_len);
2899 SSVALS(*rparam,0,desc.errcode);
2901 SSVAL(*rparam,4,desc.neededlen);
2903 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2907 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2908 int mdrcnt,int mprcnt,
2909 char **rdata,char **rparam,
2910 int *rdata_len,int *rparam_len)
2912 char *str1 = param+2;
2913 char *str2 = skip_string(str1,1);
2914 char *p = skip_string(str2,1);
2918 struct pack_desc desc;
2919 int services = lp_numservices();
2921 bzero(&desc,sizeof(desc));
2926 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2928 /* check it's a supported varient */
2929 if (strcmp(str1,"WrLeh") != 0) return False;
2930 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2933 for (i = 0; i < services; i++)
2934 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2937 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2939 desc.buflen = mdrcnt;
2940 if (init_package(&desc,queuecnt,0)) {
2943 for (i = 0; i < services; i++) {
2944 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2945 fill_printdest_info(cnum,i,uLevel,&desc);
2947 if (desc.errcode == NERR_Success) succnt = n;
2952 *rdata_len = desc.usedlen;
2955 *rparam = REALLOC(*rparam,*rparam_len);
2956 SSVALS(*rparam,0,desc.errcode);
2958 SSVAL(*rparam,4,succnt);
2959 SSVAL(*rparam,6,queuecnt);
2961 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2965 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2966 int mdrcnt,int mprcnt,
2967 char **rdata,char **rparam,
2968 int *rdata_len,int *rparam_len)
2970 char *str1 = param+2;
2971 char *str2 = skip_string(str1,1);
2972 char *p = skip_string(str2,1);
2975 struct pack_desc desc;
2977 bzero(&desc,sizeof(desc));
2982 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2984 /* check it's a supported varient */
2985 if (strcmp(str1,"WrLeh") != 0) return False;
2986 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2988 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2990 desc.buflen = mdrcnt;
2991 if (init_package(&desc,1,0)) {
2992 PACKS(&desc,"B41","NULL");
2995 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2997 *rdata_len = desc.usedlen;
3000 *rparam = REALLOC(*rparam,*rparam_len);
3001 SSVALS(*rparam,0,desc.errcode);
3003 SSVAL(*rparam,4,succnt);
3006 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3010 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
3011 int mdrcnt,int mprcnt,
3012 char **rdata,char **rparam,
3013 int *rdata_len,int *rparam_len)
3015 char *str1 = param+2;
3016 char *str2 = skip_string(str1,1);
3017 char *p = skip_string(str2,1);
3020 struct pack_desc desc;
3022 bzero(&desc,sizeof(desc));
3027 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3029 /* check it's a supported varient */
3030 if (strcmp(str1,"WrLeh") != 0) return False;
3031 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3033 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3035 desc.buflen = mdrcnt;
3037 if (init_package(&desc,1,0)) {
3038 PACKS(&desc,"B13","lpd");
3041 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3043 *rdata_len = desc.usedlen;
3046 *rparam = REALLOC(*rparam,*rparam_len);
3047 SSVALS(*rparam,0,desc.errcode);
3049 SSVAL(*rparam,4,succnt);
3052 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3056 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
3057 int mdrcnt,int mprcnt,
3058 char **rdata,char **rparam,
3059 int *rdata_len,int *rparam_len)
3061 char *str1 = param+2;
3062 char *str2 = skip_string(str1,1);
3063 char *p = skip_string(str2,1);
3066 struct pack_desc desc;
3068 bzero(&desc,sizeof(desc));
3073 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3075 /* check it's a supported varient */
3076 if (strcmp(str1,"WrLeh") != 0) return False;
3077 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3079 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3080 bzero(&desc,sizeof(desc));
3082 desc.buflen = mdrcnt;
3084 if (init_package(&desc,1,0)) {
3085 PACKS(&desc,"B13","lp0");
3088 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3090 *rdata_len = desc.usedlen;
3093 *rparam = REALLOC(*rparam,*rparam_len);
3094 SSVALS(*rparam,0,desc.errcode);
3096 SSVAL(*rparam,4,succnt);
3099 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3105 char * pipe_clnt_name;
3106 char * pipe_srv_name;
3107 BOOL (*fn) (pipes_struct *, prs_struct *);
3110 static struct api_cmd api_fd_commands[] =
3112 { "lsarpc", "lsass", api_ntlsa_rpc },
3113 { "samr", "lsass", api_samr_rpc },
3114 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3115 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3116 { "NETLOGON", "lsass", api_netlog_rpc },
3117 { "winreg", "winreg", api_reg_rpc },
3118 { NULL, NULL, NULL }
3121 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3123 BOOL ntlmssp_auth = False;
3124 fstring ack_pipe_name;
3127 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3129 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3131 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3132 api_fd_commands[i].fn != NULL)
3134 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3135 api_fd_commands[i].pipe_clnt_name,
3136 api_fd_commands[i].pipe_srv_name));
3137 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3142 if (api_fd_commands[i].fn == NULL) return False;
3144 /* decode the bind request */
3145 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3147 if (pd->offset == 0) return False;
3149 if (p->hdr.auth_len != 0)
3151 /* decode the authentication verifier */
3152 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3154 if (pd->offset == 0) return False;
3156 /* ignore the version number for now */
3157 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3160 /* name has to be \PIPE\xxxxx */
3161 fstrcpy(ack_pipe_name, "\\PIPE\\");
3162 fstrcat(ack_pipe_name, p->pipe_srv_name);
3164 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3166 prs_init(&(p->rdata), 1024, 4, 0, False);
3167 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3168 prs_init(&(p->rauth), 1024, 4, 0, False);
3171 /*** do the bind ack first ***/
3174 make_rpc_hdr_ba(&p->hdr_ba,
3175 p->hdr_rb.bba.max_tsize,
3176 p->hdr_rb.bba.max_rsize,
3177 p->hdr_rb.bba.assoc_gid,
3180 &(p->hdr_rb.transfer));
3182 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3183 mem_realloc_data(p->rdata.data, p->rdata.offset);
3186 /*** now the authentication ***/
3192 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3194 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3197 0x00000000, 0x0000b2b3, 0x000082b1,
3199 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3200 mem_realloc_data(p->rauth.data, p->rauth.offset);
3204 /*** then do the header, now we know the length ***/
3207 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3209 p->rdata.offset + p->rauth.offset,
3212 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3213 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3216 /*** link rpc header, bind acknowledgment and authentication responses ***/
3219 p->rhdr.data->offset.start = 0;
3220 p->rhdr.data->offset.end = p->rhdr.offset;
3221 p->rhdr.data->next = p->rdata.data;
3225 p->rdata.data->offset.start = p->rhdr.offset;
3226 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3227 p->rdata.data->next = p->rauth.data;
3229 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3230 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3231 p->rauth.data->next = NULL;
3235 p->rdata.data->offset.start = p->rhdr.offset;
3236 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3237 p->rdata.data->next = NULL;
3243 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3247 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3249 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3250 api_fd_commands[i].fn != NULL)
3252 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3253 return api_fd_commands[i].fn(p, pd);
3259 static BOOL api_dce_rpc_command(char *outbuf,
3264 if (pd->data == NULL) return False;
3266 /* process the rpc header */
3267 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3269 if (pd->offset == 0) return False;
3271 switch (p->hdr.pkt_type)
3275 reply = api_pipe_bind_req(p, pd);
3280 reply = api_pipe_request (p, pd);
3287 /* now send the reply */
3288 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3290 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3292 /* all of data was sent: no need to wait for SMBreadX calls */
3293 mem_free_data(p->rhdr .data);
3294 mem_free_data(p->rdata.data);
3301 /****************************************************************************
3302 SetNamedPipeHandleState
3303 ****************************************************************************/
3304 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3308 if (!param) return False;
3310 id = param[0] + (param[1] << 8);
3311 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3313 if (set_rpc_pipe_hnd_state(p, id))
3315 /* now send the reply */
3316 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3324 /****************************************************************************
3325 when no reply is generated, indicate unsupported.
3326 ****************************************************************************/
3327 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3329 struct mem_buf rparam;
3331 mem_init(&rparam, 0);
3332 mem_alloc_data(&rparam, 4);
3334 rparam.offset.start = 0;
3335 rparam.offset.end = 4;
3338 SSVAL(rparam.data,0,NERR_notsupported);
3339 SSVAL(rparam.data,2,0); /* converter word */
3341 DEBUG(3,("Unsupported API fd command\n"));
3343 /* now send the reply */
3344 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3346 mem_free_data(&rparam);
3351 /****************************************************************************
3352 handle remote api calls delivered to a named pipe already opened.
3353 ****************************************************************************/
3354 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3355 uint16 *setup,char *data,char *params,
3356 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3362 pipes_struct *p = NULL;
3364 struct mem_buf data_buf;
3366 DEBUG(5,("api_fd_reply\n"));
3368 /* fake up a data buffer from the api_fd_reply data parameters */
3369 mem_create(&data_buf, data, tdscnt, 0, False);
3370 data_buf.offset.start = 0;
3371 data_buf.offset.end = tdscnt;
3373 /* fake up a parsing structure */
3374 pd.data = &data_buf;
3379 /* First find out the name of this file. */
3382 DEBUG(0,("Unexpected named pipe transaction.\n"));
3386 /* Get the file handle and hence the file name. */
3388 subcommand = setup[0];
3389 get_rpc_pipe(pnum, &p);
3393 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3394 subcommand, p->name, pnum));
3395 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3396 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3398 /* record maximum data length that can be transmitted in an SMBtrans */
3399 p->file_offset = mdrcnt;
3401 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3402 p, p->file_offset));
3408 /* dce/rpc command */
3409 reply = api_dce_rpc_command(outbuf, p, &pd);
3414 /* Set Named Pipe Handle state */
3415 reply = api_SNPHS(outbuf, p, params);
3422 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3427 return api_no_reply(outbuf, mdrcnt);
3432 /****************************************************************************
3433 the buffer was too small
3434 ****************************************************************************/
3435 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3436 int mdrcnt,int mprcnt,
3437 char **rdata,char **rparam,
3438 int *rdata_len,int *rparam_len)
3440 *rparam_len = MIN(*rparam_len,mprcnt);
3441 *rparam = REALLOC(*rparam,*rparam_len);
3445 SSVAL(*rparam,0,NERR_BufTooSmall);
3447 DEBUG(3,("Supplied buffer too small in API command\n"));
3453 /****************************************************************************
3454 the request is not supported
3455 ****************************************************************************/
3456 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3457 int mdrcnt,int mprcnt,
3458 char **rdata,char **rparam,
3459 int *rdata_len,int *rparam_len)
3462 *rparam = REALLOC(*rparam,*rparam_len);
3466 SSVAL(*rparam,0,NERR_notsupported);
3467 SSVAL(*rparam,2,0); /* converter word */
3469 DEBUG(3,("Unsupported API command\n"));
3481 BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *);
3483 } api_commands[] = {
3484 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3485 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3486 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3487 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3488 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3489 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3490 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3491 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3492 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3493 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3494 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3495 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3496 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3497 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3498 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3499 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3500 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3501 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3502 {"NetServerEnum", 104, api_RNetServerEnum,0},
3503 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3504 {"SetUserPassword", 115, api_SetUserPassword,0},
3505 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3506 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3507 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3508 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3509 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3510 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3511 {NULL, -1, api_Unsupported,0}};
3514 /****************************************************************************
3515 handle remote api calls
3516 ****************************************************************************/
3517 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3518 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3520 int api_command = SVAL(params,0);
3521 struct mem_buf rdata_buf;
3522 struct mem_buf rparam_buf;
3524 char *rparam = NULL;
3530 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3531 api_command,params+2,skip_string(params+2,1),
3532 tdscnt,tpscnt,mdrcnt,mprcnt));
3534 for (i=0;api_commands[i].name;i++)
3535 if (api_commands[i].id == api_command && api_commands[i].fn)
3537 DEBUG(3,("Doing %s\n",api_commands[i].name));
3541 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3542 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3544 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3545 &rdata,&rparam,&rdata_len,&rparam_len);
3548 if (rdata_len > mdrcnt ||
3549 rparam_len > mprcnt)
3551 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3552 &rdata,&rparam,&rdata_len,&rparam_len);
3556 /* if we get False back then it's actually unsupported */
3558 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3559 &rdata,&rparam,&rdata_len,&rparam_len);
3562 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3563 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3565 rdata_buf.offset.start = 0;
3566 rdata_buf.offset.end = rdata_len;
3568 rparam_buf.offset.start = 0;
3569 rparam_buf.offset.end = rparam_len;
3571 /* now send the reply */
3572 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3574 if (rdata ) free(rdata);
3575 if (rparam) free(rparam);
3580 /****************************************************************************
3581 handle named pipe commands
3582 ****************************************************************************/
3583 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3584 uint16 *setup,char *data,char *params,
3585 int suwcnt,int tdscnt,int tpscnt,
3586 int msrcnt,int mdrcnt,int mprcnt)
3588 DEBUG(3,("named pipe command on <%s> name\n", name));
3590 if (strequal(name,"LANMAN"))
3592 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3595 if (strlen(name) < 1)
3597 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3602 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3609 /****************************************************************************
3611 ****************************************************************************/
3612 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3616 char *data=NULL,*params=NULL;
3620 int cnum = SVAL(inbuf,smb_tid);
3621 uint16 vuid = SVAL(inbuf,smb_uid);
3623 int tpscnt = SVAL(inbuf,smb_vwv0);
3624 int tdscnt = SVAL(inbuf,smb_vwv1);
3625 int mprcnt = SVAL(inbuf,smb_vwv2);
3626 int mdrcnt = SVAL(inbuf,smb_vwv3);
3627 int msrcnt = CVAL(inbuf,smb_vwv4);
3628 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3629 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3630 int pscnt = SVAL(inbuf,smb_vwv9);
3631 int psoff = SVAL(inbuf,smb_vwv10);
3632 int dscnt = SVAL(inbuf,smb_vwv11);
3633 int dsoff = SVAL(inbuf,smb_vwv12);
3634 int suwcnt = CVAL(inbuf,smb_vwv13);
3636 bzero(name, sizeof(name));
3637 fstrcpy(name,smb_buf(inbuf));
3639 if (dscnt > tdscnt || pscnt > tpscnt) {
3640 exit_server("invalid trans parameters\n");
3645 data = (char *)malloc(tdscnt);
3646 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3650 params = (char *)malloc(tpscnt);
3651 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3657 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3658 for (i=0;i<suwcnt;i++)
3659 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3663 if (pscnt < tpscnt || dscnt < tdscnt)
3665 /* We need to send an interim response then receive the rest
3666 of the parameter/data bytes */
3667 outsize = set_message(outbuf,0,0,True);
3669 send_smb(Client,outbuf);
3672 /* receive the rest of the trans packet */
3673 while (pscnt < tpscnt || dscnt < tdscnt)
3676 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3678 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3680 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3683 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3685 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3686 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3687 if (params) free(params);
3688 if (data) free(data);
3689 if (setup) free(setup);
3690 return(ERROR(ERRSRV,ERRerror));
3695 tpscnt = SVAL(inbuf,smb_vwv0);
3696 tdscnt = SVAL(inbuf,smb_vwv1);
3698 pcnt = SVAL(inbuf,smb_vwv2);
3699 poff = SVAL(inbuf,smb_vwv3);
3700 pdisp = SVAL(inbuf,smb_vwv4);
3702 dcnt = SVAL(inbuf,smb_vwv5);
3703 doff = SVAL(inbuf,smb_vwv6);
3704 ddisp = SVAL(inbuf,smb_vwv7);
3709 if (dscnt > tdscnt || pscnt > tpscnt) {
3710 exit_server("invalid trans parameters\n");
3714 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3716 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3720 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3722 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3724 DEBUG(5,("calling named_pipe\n"));
3725 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3726 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3730 DEBUG(3,("invalid pipe name\n"));
3735 if (data) free(data);
3736 if (params) free(params);
3737 if (setup) free(setup);
3739 if (close_on_completion)
3740 close_cnum(cnum,vuid);
3746 return(ERROR(ERRSRV,ERRnosupport));