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
1640 (void)map_username(user);
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
1728 (void)map_username(user);
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 /****************************************************************************
1825 Purge a print queue - or pause or resume it.
1826 ****************************************************************************/
1827 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1828 int mdrcnt,int mprcnt,
1829 char **rdata,char **rparam,
1830 int *rdata_len,int *rparam_len)
1832 int function = SVAL(param,0);
1833 char *str1 = param+2;
1834 char *str2 = skip_string(str1,1);
1835 char *QueueName = skip_string(str2,1);
1838 /* check it's a supported varient */
1839 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1843 *rparam = REALLOC(*rparam,*rparam_len);
1847 SSVAL(*rparam,0,NERR_Success);
1848 SSVAL(*rparam,2,0); /* converter word */
1850 snum = lp_servicenumber(QueueName);
1851 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1852 int pnum = lp_servicenumber(PRINTERS_NAME);
1854 lp_add_printer(QueueName,pnum);
1855 snum = lp_servicenumber(QueueName);
1859 if (snum >= 0 && VALID_SNUM(snum)) {
1863 case 74: /* Pause queue */
1864 case 75: /* Resume queue */
1865 status_printqueue(cnum,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1866 DEBUG(3,("Print queue %s, queue=%s\n",
1867 (function==74?"pause":"resume"),QueueName));
1869 case 103: /* Purge */
1871 print_queue_struct *queue=NULL;
1873 count = get_printqueue(snum,cnum,&queue,NULL);
1874 for (i = 0; i < count; i++)
1875 del_printqueue(cnum,snum,queue[i].job);
1877 if (queue) free(queue);
1878 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1888 /****************************************************************************
1889 set the property of a print job (undocumented?)
1890 ? function = 0xb -> set name of print job
1891 ? function = 0x6 -> move print job up/down
1892 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1893 or <WWsTP> <WB21BB16B10zWWzDDz>
1894 ****************************************************************************/
1895 static int check_printjob_info(struct pack_desc* desc,
1896 int uLevel, char* id)
1898 desc->subformat = NULL;
1900 case 0: desc->format = "W"; break;
1901 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1902 case 2: desc->format = "WWzWWDDzz"; break;
1903 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1904 default: return False;
1906 if (strcmp(desc->format,id) != 0) return False;
1910 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1911 int mdrcnt,int mprcnt,
1912 char **rdata,char **rparam,
1913 int *rdata_len,int *rparam_len)
1915 struct pack_desc desc;
1916 char *str1 = param+2;
1917 char *str2 = skip_string(str1,1);
1918 char *p = skip_string(str2,1);
1920 int uLevel = SVAL(p,2);
1921 int function = SVAL(p,4); /* what is this ?? */
1925 printjob_decode(SVAL(p,0), &snum, &jobid);
1928 *rparam = REALLOC(*rparam,*rparam_len);
1932 /* check it's a supported varient */
1933 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1937 case 0x6: /* change job place in the queue, data gives the new place */
1938 if (snum >= 0 && VALID_SNUM(snum))
1940 print_queue_struct *queue=NULL;
1944 count = get_printqueue(snum,cnum,&queue,NULL);
1945 for (i=0;i<count;i++) /* find job */
1946 if ((queue[i].job&0xFF) == jobid) break;
1949 desc.errcode=NERR_JobNotFound;
1950 if (queue) free(queue);
1953 desc.errcode=NERR_Success;
1957 int place= SVAL(data,0);
1958 /* we currently have no way of doing this. Can any unix do it? */
1959 if (i < place) /* move down */;
1960 else if (i > place ) /* move up */;
1963 desc.errcode=NERR_notsupported; /* not yet supported */
1964 if (queue) free(queue);
1967 else desc.errcode=NERR_JobNotFound;
1969 case 0xb: /* change print job name, data gives the name */
1970 /* jobid, snum should be zero */
1977 if (issafe(*s)) name[l++] = *s;
1982 DEBUG(3,("Setting print name to %s\n",name));
1986 for (i=0;i<MAX_FNUMS;i++)
1987 if (Files[i].open && Files[i].print_file)
1990 int fcnum = Files[i].cnum;
1994 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1995 !become_service(fcnum,True))
1998 if (sys_rename(Files[i].name,name) == 0)
1999 string_set(&Files[i].name,name);
2003 unbecome_root(True);
2005 desc.errcode=NERR_Success;
2008 default: /* not implemented */
2012 SSVALS(*rparam,0,desc.errcode);
2013 SSVAL(*rparam,2,0); /* converter word */
2019 /****************************************************************************
2020 get info about the server
2021 ****************************************************************************/
2022 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
2023 int mdrcnt,int mprcnt,
2024 char **rdata,char **rparam,
2025 int *rdata_len,int *rparam_len)
2027 char *str1 = param+2;
2028 char *str2 = skip_string(str1,1);
2029 char *p = skip_string(str2,1);
2030 int uLevel = SVAL(p,0);
2034 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2036 /* check it's a supported varient */
2037 if (!prefix_ok(str1,"WrLh")) return False;
2040 if (strcmp(str2,"B16") != 0) return False;
2044 if (strcmp(str2,"B16BBDz") != 0) return False;
2048 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2053 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2058 if (strcmp(str2,"DN") != 0) return False;
2062 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2065 default: return False;
2068 *rdata_len = mdrcnt;
2069 *rdata = REALLOC(*rdata,*rdata_len);
2072 p2 = p + struct_len;
2074 StrnCpy(p,local_machine,16);
2080 struct srv_info_struct *servers=NULL;
2083 uint32 servertype= lp_default_server_announce();
2085 pstrcpy(comment,lp_serverstring());
2087 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2088 for (i=0;i<count;i++)
2089 if (strequal(servers[i].name,local_machine))
2091 servertype = servers[i].type;
2092 pstrcpy(comment,servers[i].comment);
2095 if (servers) free(servers);
2097 SCVAL(p,0,lp_major_announce_version());
2098 SCVAL(p,1,lp_minor_announce_version());
2099 SIVAL(p,2,servertype);
2101 if (mdrcnt == struct_len) {
2104 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2105 standard_sub(cnum,comment);
2106 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2107 p2 = skip_string(p2,1);
2112 return False; /* not yet implemented */
2115 *rdata_len = PTR_DIFF(p2,*rdata);
2118 *rparam = REALLOC(*rparam,*rparam_len);
2119 SSVAL(*rparam,0,NERR_Success);
2120 SSVAL(*rparam,2,0); /* converter word */
2121 SSVAL(*rparam,4,*rdata_len);
2127 /****************************************************************************
2128 get info about the server
2129 ****************************************************************************/
2130 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
2131 int mdrcnt,int mprcnt,
2132 char **rdata,char **rparam,
2133 int *rdata_len,int *rparam_len)
2135 char *str1 = param+2;
2136 char *str2 = skip_string(str1,1);
2137 char *p = skip_string(str2,1);
2139 extern pstring sesssetup_user;
2140 int level = SVAL(p,0);
2142 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2145 *rparam = REALLOC(*rparam,*rparam_len);
2147 /* check it's a supported varient */
2148 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2151 *rdata_len = mdrcnt + 1024;
2152 *rdata = REALLOC(*rdata,*rdata_len);
2154 SSVAL(*rparam,0,NERR_Success);
2155 SSVAL(*rparam,2,0); /* converter word */
2161 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2162 pstrcpy(p2,local_machine);
2164 p2 = skip_string(p2,1);
2167 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2168 pstrcpy(p2,sesssetup_user);
2169 p2 = skip_string(p2,1);
2172 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2173 pstrcpy(p2,global_myworkgroup);
2175 p2 = skip_string(p2,1);
2178 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2179 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2182 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2183 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2184 p2 = skip_string(p2,1);
2187 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2189 p2 = skip_string(p2,1);
2192 *rdata_len = PTR_DIFF(p2,*rdata);
2194 SSVAL(*rparam,4,*rdata_len);
2199 /****************************************************************************
2200 get info about a user
2202 struct user_info_11 {
2203 char usri11_name[21]; 0-20
2205 char *usri11_comment; 22-25
2206 char *usri11_usr_comment; 26-29
2207 unsigned short usri11_priv; 30-31
2208 unsigned long usri11_auth_flags; 32-35
2209 long usri11_password_age; 36-39
2210 char *usri11_homedir; 40-43
2211 char *usri11_parms; 44-47
2212 long usri11_last_logon; 48-51
2213 long usri11_last_logoff; 52-55
2214 unsigned short usri11_bad_pw_count; 56-57
2215 unsigned short usri11_num_logons; 58-59
2216 char *usri11_logon_server; 60-63
2217 unsigned short usri11_country_code; 64-65
2218 char *usri11_workstations; 66-69
2219 unsigned long usri11_max_storage; 70-73
2220 unsigned short usri11_units_per_week; 74-75
2221 unsigned char *usri11_logon_hours; 76-79
2222 unsigned short usri11_code_page; 80-81
2227 usri11_name specifies the user name for which information is retireved
2229 usri11_pad aligns the next data structure element to a word boundary
2231 usri11_comment is a null terminated ASCII comment
2233 usri11_user_comment is a null terminated ASCII comment about the user
2235 usri11_priv specifies the level of the privilege assigned to the user.
2236 The possible values are:
2238 Name Value Description
2239 USER_PRIV_GUEST 0 Guest privilege
2240 USER_PRIV_USER 1 User privilege
2241 USER_PRV_ADMIN 2 Administrator privilege
2243 usri11_auth_flags specifies the account operator privileges. The
2244 possible values are:
2246 Name Value Description
2247 AF_OP_PRINT 0 Print operator
2250 Leach, Naik [Page 28]
\r\f
2253 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2256 AF_OP_COMM 1 Communications operator
2257 AF_OP_SERVER 2 Server operator
2258 AF_OP_ACCOUNTS 3 Accounts operator
2261 usri11_password_age specifies how many seconds have elapsed since the
2262 password was last changed.
2264 usri11_home_dir points to a null terminated ASCII string that contains
2265 the path name of the user's home directory.
2267 usri11_parms points to a null terminated ASCII string that is set
2268 aside for use by applications.
2270 usri11_last_logon specifies the time when the user last logged on.
2271 This value is stored as the number of seconds elapsed since
2272 00:00:00, January 1, 1970.
2274 usri11_last_logoff specifies the time when the user last logged off.
2275 This value is stored as the number of seconds elapsed since
2276 00:00:00, January 1, 1970. A value of 0 means the last logoff
2279 usri11_bad_pw_count specifies the number of incorrect passwords
2280 entered since the last successful logon.
2282 usri11_log1_num_logons specifies the number of times this user has
2283 logged on. A value of -1 means the number of logons is unknown.
2285 usri11_logon_server points to a null terminated ASCII string that
2286 contains the name of the server to which logon requests are sent.
2287 A null string indicates logon requests should be sent to the
2290 usri11_country_code specifies the country code for the user's language
2293 usri11_workstations points to a null terminated ASCII string that
2294 contains the names of workstations the user may log on from.
2295 There may be up to 8 workstations, with the names separated by
2296 commas. A null strings indicates there are no restrictions.
2298 usri11_max_storage specifies the maximum amount of disk space the user
2299 can occupy. A value of 0xffffffff indicates there are no
2302 usri11_units_per_week specifies the equal number of time units into
2303 which a week is divided. This value must be equal to 168.
2305 usri11_logon_hours points to a 21 byte (168 bits) string that
2306 specifies the time during which the user can log on. Each bit
2307 represents one unique hour in a week. The first bit (bit 0, word
2308 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2312 Leach, Naik [Page 29]
\r\f
2315 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2318 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2319 are no restrictions.
2321 usri11_code_page specifies the code page for the user's language of
2324 All of the pointers in this data structure need to be treated
2325 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2326 to be ignored. The converter word returned in the parameters section
2327 needs to be subtracted from the lower 16 bits to calculate an offset
2328 into the return buffer where this ASCII string resides.
2330 There is no auxiliary data in the response.
2332 ****************************************************************************/
2334 #define usri11_name 0
2335 #define usri11_pad 21
2336 #define usri11_comment 22
2337 #define usri11_usr_comment 26
2338 #define usri11_full_name 30
2339 #define usri11_priv 34
2340 #define usri11_auth_flags 36
2341 #define usri11_password_age 40
2342 #define usri11_homedir 44
2343 #define usri11_parms 48
2344 #define usri11_last_logon 52
2345 #define usri11_last_logoff 56
2346 #define usri11_bad_pw_count 60
2347 #define usri11_num_logons 62
2348 #define usri11_logon_server 64
2349 #define usri11_country_code 68
2350 #define usri11_workstations 70
2351 #define usri11_max_storage 74
2352 #define usri11_units_per_week 78
2353 #define usri11_logon_hours 80
2354 #define usri11_code_page 84
2355 #define usri11_end 86
2357 #define USER_PRIV_GUEST 0
2358 #define USER_PRIV_USER 1
2359 #define USER_PRIV_ADMIN 2
2361 #define AF_OP_PRINT 0
2362 #define AF_OP_COMM 1
2363 #define AF_OP_SERVER 2
2364 #define AF_OP_ACCOUNTS 3
2367 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2368 int mdrcnt,int mprcnt,
2369 char **rdata,char **rparam,
2370 int *rdata_len,int *rparam_len)
2372 char *str1 = param+2;
2373 char *str2 = skip_string(str1,1);
2374 char *UserName = skip_string(str2,1);
2375 char *p = skip_string(UserName,1);
2376 int uLevel = SVAL(p,0);
2379 /* get NIS home of a previously validated user - simeon */
2380 /* With share level security vuid will always be zero.
2381 Don't depend on vuser being non-null !!. JRA */
2382 user_struct *vuser = get_valid_user_struct(vuid);
2384 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2387 *rparam = REALLOC(*rparam,*rparam_len);
2389 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2391 /* check it's a supported variant */
2392 if (strcmp(str1,"zWrLh") != 0) return False;
2395 case 0: p2 = "B21"; break;
2396 case 1: p2 = "B21BB16DWzzWz"; break;
2397 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2398 case 10: p2 = "B21Bzzz"; break;
2399 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2400 default: return False;
2403 if (strcmp(p2,str2) != 0) return False;
2405 *rdata_len = mdrcnt + 1024;
2406 *rdata = REALLOC(*rdata,*rdata_len);
2408 SSVAL(*rparam,0,NERR_Success);
2409 SSVAL(*rparam,2,0); /* converter word */
2412 p2 = p + usri11_end;
2415 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2419 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2424 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2425 pstrcpy(p2,"Comment");
2426 p2 = skip_string(p2,1);
2428 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2429 pstrcpy(p2,"UserComment");
2430 p2 = skip_string(p2,1);
2432 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2433 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2434 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2435 p2 = skip_string(p2,1);
2438 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2440 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2441 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2442 SIVALS(p,usri11_password_age,-1); /* password age */
2443 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2444 pstrcpy(p2, lp_logon_path());
2445 p2 = skip_string(p2,1);
2446 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2448 p2 = skip_string(p2,1);
2449 SIVAL(p,usri11_last_logon,0); /* last logon */
2450 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2451 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2452 SSVALS(p,usri11_num_logons,-1); /* num logons */
2453 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2454 pstrcpy(p2,"\\\\*");
2455 p2 = skip_string(p2,1);
2456 SSVAL(p,usri11_country_code,0); /* country code */
2458 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2460 p2 = skip_string(p2,1);
2462 SIVALS(p,usri11_max_storage,-1); /* max storage */
2463 SSVAL(p,usri11_units_per_week,168); /* units per week */
2464 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2466 /* a simple way to get logon hours at all times. */
2468 SCVAL(p2,21,0); /* fix zero termination */
2469 p2 = skip_string(p2,1);
2471 SSVAL(p,usri11_code_page,0); /* code page */
2473 if (uLevel == 1 || uLevel == 2)
2475 memset(p+22,' ',16); /* password */
2476 SIVALS(p,38,-1); /* password age */
2478 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2479 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2480 pstrcpy(p2,lp_logon_path());
2481 p2 = skip_string(p2,1);
2482 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2484 SSVAL(p,52,0); /* flags */
2485 SIVAL(p,54,0); /* script_path */
2488 SIVAL(p,60,0); /* auth_flags */
2489 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2490 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2491 p2 = skip_string(p2,1);
2492 SIVAL(p,68,0); /* urs_comment */
2493 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2495 p2 = skip_string(p2,1);
2496 SIVAL(p,76,0); /* workstations */
2497 SIVAL(p,80,0); /* last_logon */
2498 SIVAL(p,84,0); /* last_logoff */
2499 SIVALS(p,88,-1); /* acct_expires */
2500 SIVALS(p,92,-1); /* max_storage */
2501 SSVAL(p,96,168); /* units_per_week */
2502 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2505 SSVALS(p,102,-1); /* bad_pw_count */
2506 SSVALS(p,104,-1); /* num_logons */
2507 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2508 pstrcpy(p2,"\\\\%L");
2509 standard_sub_basic(p2);
2510 p2 = skip_string(p2,1);
2511 SSVAL(p,110,49); /* country_code */
2512 SSVAL(p,112,860); /* code page */
2516 *rdata_len = PTR_DIFF(p2,*rdata);
2518 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2523 /*******************************************************************
2524 get groups that a user is a member of
2525 ******************************************************************/
2526 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2527 int mdrcnt,int mprcnt,
2528 char **rdata,char **rparam,
2529 int *rdata_len,int *rparam_len)
2531 char *str1 = param+2;
2532 char *str2 = skip_string(str1,1);
2533 char *UserName = skip_string(str2,1);
2534 char *p = skip_string(UserName,1);
2535 int uLevel = SVAL(p,0);
2540 *rparam = REALLOC(*rparam,*rparam_len);
2542 /* check it's a supported varient */
2543 if (strcmp(str1,"zWrLeh") != 0) return False;
2545 case 0: p2 = "B21"; break;
2546 default: return False;
2548 if (strcmp(p2,str2) != 0) return False;
2550 *rdata_len = mdrcnt + 1024;
2551 *rdata = REALLOC(*rdata,*rdata_len);
2553 SSVAL(*rparam,0,NERR_Success);
2554 SSVAL(*rparam,2,0); /* converter word */
2558 /* XXXX we need a real SAM database some day */
2559 pstrcpy(p,"Users"); p += 21; count++;
2560 pstrcpy(p,"Domain Users"); p += 21; count++;
2561 pstrcpy(p,"Guests"); p += 21; count++;
2562 pstrcpy(p,"Domain Guests"); p += 21; count++;
2564 *rdata_len = PTR_DIFF(p,*rdata);
2566 SSVAL(*rparam,4,count); /* is this right?? */
2567 SSVAL(*rparam,6,count); /* is this right?? */
2573 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2574 int mdrcnt,int mprcnt,
2575 char **rdata,char **rparam,
2576 int *rdata_len,int *rparam_len)
2578 char *str1 = param+2;
2579 char *str2 = skip_string(str1,1);
2580 char *p = skip_string(str2,1);
2582 struct pack_desc desc;
2589 bzero(&desc,sizeof(desc));
2591 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2593 /* check it's a supported varient */
2594 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2595 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2596 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2598 desc.buflen = mdrcnt;
2599 desc.subformat = NULL;
2602 if (init_package(&desc,1,0))
2604 PACKI(&desc,"W",0); /* code */
2605 PACKS(&desc,"B21",name); /* eff. name */
2606 PACKS(&desc,"B",""); /* pad */
2608 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2609 PACKI(&desc,"D",0); /* auth flags XXX */
2610 PACKI(&desc,"W",0); /* num logons */
2611 PACKI(&desc,"W",0); /* bad pw count */
2612 PACKI(&desc,"D",0); /* last logon */
2613 PACKI(&desc,"D",-1); /* last logoff */
2614 PACKI(&desc,"D",-1); /* logoff time */
2615 PACKI(&desc,"D",-1); /* kickoff time */
2616 PACKI(&desc,"D",0); /* password age */
2617 PACKI(&desc,"D",0); /* password can change */
2618 PACKI(&desc,"D",-1); /* password must change */
2621 fstrcpy(mypath,"\\\\");
2622 fstrcat(mypath,local_machine);
2624 PACKS(&desc,"z",mypath); /* computer */
2626 PACKS(&desc,"z",global_myworkgroup);/* domain */
2628 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2629 /* made sure all macros are fully substituted and available */
2630 logon_script = lp_logon_script();
2631 standard_sub( cnum, logon_script );
2632 PACKS(&desc,"z", logon_script); /* script path */
2633 /* End of JHT mods */
2635 PACKI(&desc,"D",0x00000000); /* reserved */
2638 *rdata_len = desc.usedlen;
2640 *rparam = REALLOC(*rparam,*rparam_len);
2641 SSVALS(*rparam,0,desc.errcode);
2643 SSVAL(*rparam,4,desc.neededlen);
2645 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2650 /****************************************************************************
2651 api_WAccessGetUserPerms
2652 ****************************************************************************/
2653 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2654 int mdrcnt,int mprcnt,
2655 char **rdata,char **rparam,
2656 int *rdata_len,int *rparam_len)
2658 char *str1 = param+2;
2659 char *str2 = skip_string(str1,1);
2660 char *user = skip_string(str2,1);
2661 char *resource = skip_string(user,1);
2663 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2665 /* check it's a supported varient */
2666 if (strcmp(str1,"zzh") != 0) return False;
2667 if (strcmp(str2,"") != 0) return False;
2670 *rparam = REALLOC(*rparam,*rparam_len);
2671 SSVALS(*rparam,0,0); /* errorcode */
2672 SSVAL(*rparam,2,0); /* converter word */
2673 SSVAL(*rparam,4,0x7f); /* permission flags */
2678 /****************************************************************************
2679 api_WPrintJobEnumerate
2680 ****************************************************************************/
2681 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2682 int mdrcnt,int mprcnt,
2683 char **rdata,char **rparam,
2684 int *rdata_len,int *rparam_len)
2686 char *str1 = param+2;
2687 char *str2 = skip_string(str1,1);
2688 char *p = skip_string(str2,1);
2694 struct pack_desc desc;
2695 print_queue_struct *queue=NULL;
2696 print_status_struct status;
2701 bzero(&desc,sizeof(desc));
2702 bzero(&status,sizeof(status));
2704 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2706 /* check it's a supported varient */
2707 if (strcmp(str1,"WWrLh") != 0) return False;
2708 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2710 printjob_decode(SVAL(p,0), &snum, &job);
2712 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2714 count = get_printqueue(snum,cnum,&queue,&status);
2715 for (i = 0; i < count; i++) {
2716 if ((queue[i].job & 0xFF) == job) break;
2718 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2720 desc.buflen = mdrcnt;
2722 if (init_package(&desc,1,0)) {
2724 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2725 *rdata_len = desc.usedlen;
2728 desc.errcode = NERR_JobNotFound;
2734 *rparam = REALLOC(*rparam,*rparam_len);
2735 SSVALS(*rparam,0,desc.errcode);
2737 SSVAL(*rparam,4,desc.neededlen);
2739 if (queue) free(queue);
2741 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2745 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2746 int mdrcnt,int mprcnt,
2747 char **rdata,char **rparam,
2748 int *rdata_len,int *rparam_len)
2750 char *str1 = param+2;
2751 char *str2 = skip_string(str1,1);
2752 char *p = skip_string(str2,1);
2758 struct pack_desc desc;
2759 print_queue_struct *queue=NULL;
2760 print_status_struct status;
2762 bzero(&desc,sizeof(desc));
2763 bzero(&status,sizeof(status));
2765 p = skip_string(p,1);
2769 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2771 /* check it's a supported varient */
2772 if (strcmp(str1,"zWrLeh") != 0) return False;
2773 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2774 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2776 snum = lp_servicenumber(name);
2777 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2778 int pnum = lp_servicenumber(PRINTERS_NAME);
2780 lp_add_printer(name,pnum);
2781 snum = lp_servicenumber(name);
2785 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2787 count = get_printqueue(snum,cnum,&queue,&status);
2788 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2790 desc.buflen = mdrcnt;
2792 if (init_package(&desc,count,0)) {
2794 for (i = 0; i < count; i++) {
2795 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2796 if (desc.errcode == NERR_Success) succnt = i+1;
2800 *rdata_len = desc.usedlen;
2803 *rparam = REALLOC(*rparam,*rparam_len);
2804 SSVALS(*rparam,0,desc.errcode);
2806 SSVAL(*rparam,4,succnt);
2807 SSVAL(*rparam,6,count);
2809 if (queue) free(queue);
2811 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2815 static int check_printdest_info(struct pack_desc* desc,
2816 int uLevel, char* id)
2818 desc->subformat = NULL;
2820 case 0: desc->format = "B9"; break;
2821 case 1: desc->format = "B9B21WWzW"; break;
2822 case 2: desc->format = "z"; break;
2823 case 3: desc->format = "zzzWWzzzWW"; break;
2824 default: return False;
2826 if (strcmp(desc->format,id) != 0) return False;
2830 static void fill_printdest_info(int cnum, int snum, int uLevel,
2831 struct pack_desc* desc)
2834 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2835 buf[sizeof(buf)-1] = 0;
2838 PACKS(desc,"B9",buf); /* szName */
2840 PACKS(desc,"B21",""); /* szUserName */
2841 PACKI(desc,"W",0); /* uJobId */
2842 PACKI(desc,"W",0); /* fsStatus */
2843 PACKS(desc,"z",""); /* pszStatus */
2844 PACKI(desc,"W",0); /* time */
2847 if (uLevel == 2 || uLevel == 3) {
2848 PACKS(desc,"z",buf); /* pszPrinterName */
2850 PACKS(desc,"z",""); /* pszUserName */
2851 PACKS(desc,"z",""); /* pszLogAddr */
2852 PACKI(desc,"W",0); /* uJobId */
2853 PACKI(desc,"W",0); /* fsStatus */
2854 PACKS(desc,"z",""); /* pszStatus */
2855 PACKS(desc,"z",""); /* pszComment */
2856 PACKS(desc,"z","NULL"); /* pszDrivers */
2857 PACKI(desc,"W",0); /* time */
2858 PACKI(desc,"W",0); /* pad1 */
2863 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2864 int mdrcnt,int mprcnt,
2865 char **rdata,char **rparam,
2866 int *rdata_len,int *rparam_len)
2868 char *str1 = param+2;
2869 char *str2 = skip_string(str1,1);
2870 char *p = skip_string(str2,1);
2871 char* PrinterName = p;
2873 struct pack_desc desc;
2876 bzero(&desc,sizeof(desc));
2878 p = skip_string(p,1);
2882 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2884 /* check it's a supported varient */
2885 if (strcmp(str1,"zWrLh") != 0) return False;
2886 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2888 snum = lp_servicenumber(PrinterName);
2889 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2890 int pnum = lp_servicenumber(PRINTERS_NAME);
2892 lp_add_printer(PrinterName,pnum);
2893 snum = lp_servicenumber(PrinterName);
2899 desc.errcode = NERR_DestNotFound;
2903 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2905 desc.buflen = mdrcnt;
2906 if (init_package(&desc,1,0)) {
2907 fill_printdest_info(cnum,snum,uLevel,&desc);
2909 *rdata_len = desc.usedlen;
2913 *rparam = REALLOC(*rparam,*rparam_len);
2914 SSVALS(*rparam,0,desc.errcode);
2916 SSVAL(*rparam,4,desc.neededlen);
2918 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2922 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2923 int mdrcnt,int mprcnt,
2924 char **rdata,char **rparam,
2925 int *rdata_len,int *rparam_len)
2927 char *str1 = param+2;
2928 char *str2 = skip_string(str1,1);
2929 char *p = skip_string(str2,1);
2933 struct pack_desc desc;
2934 int services = lp_numservices();
2936 bzero(&desc,sizeof(desc));
2941 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2943 /* check it's a supported varient */
2944 if (strcmp(str1,"WrLeh") != 0) return False;
2945 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2948 for (i = 0; i < services; i++)
2949 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2952 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2954 desc.buflen = mdrcnt;
2955 if (init_package(&desc,queuecnt,0)) {
2958 for (i = 0; i < services; i++) {
2959 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2960 fill_printdest_info(cnum,i,uLevel,&desc);
2962 if (desc.errcode == NERR_Success) succnt = n;
2967 *rdata_len = desc.usedlen;
2970 *rparam = REALLOC(*rparam,*rparam_len);
2971 SSVALS(*rparam,0,desc.errcode);
2973 SSVAL(*rparam,4,succnt);
2974 SSVAL(*rparam,6,queuecnt);
2976 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2980 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2981 int mdrcnt,int mprcnt,
2982 char **rdata,char **rparam,
2983 int *rdata_len,int *rparam_len)
2985 char *str1 = param+2;
2986 char *str2 = skip_string(str1,1);
2987 char *p = skip_string(str2,1);
2990 struct pack_desc desc;
2992 bzero(&desc,sizeof(desc));
2997 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2999 /* check it's a supported varient */
3000 if (strcmp(str1,"WrLeh") != 0) return False;
3001 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3003 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3005 desc.buflen = mdrcnt;
3006 if (init_package(&desc,1,0)) {
3007 PACKS(&desc,"B41","NULL");
3010 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3012 *rdata_len = desc.usedlen;
3015 *rparam = REALLOC(*rparam,*rparam_len);
3016 SSVALS(*rparam,0,desc.errcode);
3018 SSVAL(*rparam,4,succnt);
3021 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3025 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
3026 int mdrcnt,int mprcnt,
3027 char **rdata,char **rparam,
3028 int *rdata_len,int *rparam_len)
3030 char *str1 = param+2;
3031 char *str2 = skip_string(str1,1);
3032 char *p = skip_string(str2,1);
3035 struct pack_desc desc;
3037 bzero(&desc,sizeof(desc));
3042 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3044 /* check it's a supported varient */
3045 if (strcmp(str1,"WrLeh") != 0) return False;
3046 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3048 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3050 desc.buflen = mdrcnt;
3052 if (init_package(&desc,1,0)) {
3053 PACKS(&desc,"B13","lpd");
3056 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3058 *rdata_len = desc.usedlen;
3061 *rparam = REALLOC(*rparam,*rparam_len);
3062 SSVALS(*rparam,0,desc.errcode);
3064 SSVAL(*rparam,4,succnt);
3067 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3071 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
3072 int mdrcnt,int mprcnt,
3073 char **rdata,char **rparam,
3074 int *rdata_len,int *rparam_len)
3076 char *str1 = param+2;
3077 char *str2 = skip_string(str1,1);
3078 char *p = skip_string(str2,1);
3081 struct pack_desc desc;
3083 bzero(&desc,sizeof(desc));
3088 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3090 /* check it's a supported varient */
3091 if (strcmp(str1,"WrLeh") != 0) return False;
3092 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3094 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3095 bzero(&desc,sizeof(desc));
3097 desc.buflen = mdrcnt;
3099 if (init_package(&desc,1,0)) {
3100 PACKS(&desc,"B13","lp0");
3103 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3105 *rdata_len = desc.usedlen;
3108 *rparam = REALLOC(*rparam,*rparam_len);
3109 SSVALS(*rparam,0,desc.errcode);
3111 SSVAL(*rparam,4,succnt);
3114 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3120 char * pipe_clnt_name;
3121 char * pipe_srv_name;
3122 BOOL (*fn) (pipes_struct *, prs_struct *);
3125 static struct api_cmd api_fd_commands[] =
3127 { "lsarpc", "lsass", api_ntlsa_rpc },
3128 { "samr", "lsass", api_samr_rpc },
3129 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3130 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3131 { "NETLOGON", "lsass", api_netlog_rpc },
3132 { "winreg", "winreg", api_reg_rpc },
3133 { NULL, NULL, NULL }
3136 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3138 BOOL ntlmssp_auth = False;
3139 fstring ack_pipe_name;
3142 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3144 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3146 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3147 api_fd_commands[i].fn != NULL)
3149 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3150 api_fd_commands[i].pipe_clnt_name,
3151 api_fd_commands[i].pipe_srv_name));
3152 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3157 if (api_fd_commands[i].fn == NULL) return False;
3159 /* decode the bind request */
3160 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3162 if (pd->offset == 0) return False;
3164 if (p->hdr.auth_len != 0)
3166 /* decode the authentication verifier */
3167 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3169 if (pd->offset == 0) return False;
3171 /* ignore the version number for now */
3172 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3175 /* name has to be \PIPE\xxxxx */
3176 fstrcpy(ack_pipe_name, "\\PIPE\\");
3177 fstrcat(ack_pipe_name, p->pipe_srv_name);
3179 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3181 prs_init(&(p->rdata), 1024, 4, 0, False);
3182 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3183 prs_init(&(p->rauth), 1024, 4, 0, False);
3186 /*** do the bind ack first ***/
3189 make_rpc_hdr_ba(&p->hdr_ba,
3190 p->hdr_rb.bba.max_tsize,
3191 p->hdr_rb.bba.max_rsize,
3192 p->hdr_rb.bba.assoc_gid,
3195 &(p->hdr_rb.transfer));
3197 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3198 mem_realloc_data(p->rdata.data, p->rdata.offset);
3201 /*** now the authentication ***/
3207 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3209 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3212 0x00000000, 0x0000b2b3, 0x000082b1,
3214 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3215 mem_realloc_data(p->rauth.data, p->rauth.offset);
3219 /*** then do the header, now we know the length ***/
3222 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3224 p->rdata.offset + p->rauth.offset,
3227 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3228 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3231 /*** link rpc header, bind acknowledgment and authentication responses ***/
3234 p->rhdr.data->offset.start = 0;
3235 p->rhdr.data->offset.end = p->rhdr.offset;
3236 p->rhdr.data->next = p->rdata.data;
3240 p->rdata.data->offset.start = p->rhdr.offset;
3241 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3242 p->rdata.data->next = p->rauth.data;
3244 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3245 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3246 p->rauth.data->next = NULL;
3250 p->rdata.data->offset.start = p->rhdr.offset;
3251 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3252 p->rdata.data->next = NULL;
3258 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3262 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3264 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3265 api_fd_commands[i].fn != NULL)
3267 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3268 return api_fd_commands[i].fn(p, pd);
3274 static BOOL api_dce_rpc_command(char *outbuf,
3279 if (pd->data == NULL) return False;
3281 /* process the rpc header */
3282 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3284 if (pd->offset == 0) return False;
3286 switch (p->hdr.pkt_type)
3290 reply = api_pipe_bind_req(p, pd);
3295 reply = api_pipe_request (p, pd);
3302 /* now send the reply */
3303 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3305 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3307 /* all of data was sent: no need to wait for SMBreadX calls */
3308 mem_free_data(p->rhdr .data);
3309 mem_free_data(p->rdata.data);
3316 /****************************************************************************
3317 SetNamedPipeHandleState
3318 ****************************************************************************/
3319 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3323 if (!param) return False;
3325 id = param[0] + (param[1] << 8);
3326 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3328 if (set_rpc_pipe_hnd_state(p, id))
3330 /* now send the reply */
3331 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3339 /****************************************************************************
3340 when no reply is generated, indicate unsupported.
3341 ****************************************************************************/
3342 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3344 struct mem_buf rparam;
3346 mem_init(&rparam, 0);
3347 mem_alloc_data(&rparam, 4);
3349 rparam.offset.start = 0;
3350 rparam.offset.end = 4;
3353 SSVAL(rparam.data,0,NERR_notsupported);
3354 SSVAL(rparam.data,2,0); /* converter word */
3356 DEBUG(3,("Unsupported API fd command\n"));
3358 /* now send the reply */
3359 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3361 mem_free_data(&rparam);
3366 /****************************************************************************
3367 handle remote api calls delivered to a named pipe already opened.
3368 ****************************************************************************/
3369 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3370 uint16 *setup,char *data,char *params,
3371 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3377 pipes_struct *p = NULL;
3379 struct mem_buf data_buf;
3381 DEBUG(5,("api_fd_reply\n"));
3383 /* fake up a data buffer from the api_fd_reply data parameters */
3384 mem_create(&data_buf, data, tdscnt, 0, False);
3385 data_buf.offset.start = 0;
3386 data_buf.offset.end = tdscnt;
3388 /* fake up a parsing structure */
3389 pd.data = &data_buf;
3394 /* First find out the name of this file. */
3397 DEBUG(0,("Unexpected named pipe transaction.\n"));
3401 /* Get the file handle and hence the file name. */
3403 subcommand = setup[0];
3404 get_rpc_pipe(pnum, &p);
3408 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3409 subcommand, p->name, pnum));
3410 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3411 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3413 /* record maximum data length that can be transmitted in an SMBtrans */
3414 p->file_offset = mdrcnt;
3416 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3417 p, p->file_offset));
3423 /* dce/rpc command */
3424 reply = api_dce_rpc_command(outbuf, p, &pd);
3429 /* Set Named Pipe Handle state */
3430 reply = api_SNPHS(outbuf, p, params);
3437 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3442 return api_no_reply(outbuf, mdrcnt);
3447 /****************************************************************************
3448 the buffer was too small
3449 ****************************************************************************/
3450 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3451 int mdrcnt,int mprcnt,
3452 char **rdata,char **rparam,
3453 int *rdata_len,int *rparam_len)
3455 *rparam_len = MIN(*rparam_len,mprcnt);
3456 *rparam = REALLOC(*rparam,*rparam_len);
3460 SSVAL(*rparam,0,NERR_BufTooSmall);
3462 DEBUG(3,("Supplied buffer too small in API command\n"));
3468 /****************************************************************************
3469 the request is not supported
3470 ****************************************************************************/
3471 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3472 int mdrcnt,int mprcnt,
3473 char **rdata,char **rparam,
3474 int *rdata_len,int *rparam_len)
3477 *rparam = REALLOC(*rparam,*rparam_len);
3481 SSVAL(*rparam,0,NERR_notsupported);
3482 SSVAL(*rparam,2,0); /* converter word */
3484 DEBUG(3,("Unsupported API command\n"));
3496 BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *);
3498 } api_commands[] = {
3499 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3500 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3501 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3502 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3503 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3504 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3505 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3506 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3507 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3508 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3509 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3510 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3511 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3512 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3513 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3514 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3515 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3516 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3517 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3518 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3519 {"NetServerEnum", 104, api_RNetServerEnum,0},
3520 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3521 {"SetUserPassword", 115, api_SetUserPassword,0},
3522 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3523 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3524 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3525 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3526 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3527 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3528 {NULL, -1, api_Unsupported,0}};
3531 /****************************************************************************
3532 handle remote api calls
3533 ****************************************************************************/
3534 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3535 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3537 int api_command = SVAL(params,0);
3538 struct mem_buf rdata_buf;
3539 struct mem_buf rparam_buf;
3541 char *rparam = NULL;
3547 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3548 api_command,params+2,skip_string(params+2,1),
3549 tdscnt,tpscnt,mdrcnt,mprcnt));
3551 for (i=0;api_commands[i].name;i++)
3552 if (api_commands[i].id == api_command && api_commands[i].fn)
3554 DEBUG(3,("Doing %s\n",api_commands[i].name));
3558 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3559 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3561 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3562 &rdata,&rparam,&rdata_len,&rparam_len);
3565 if (rdata_len > mdrcnt ||
3566 rparam_len > mprcnt)
3568 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3569 &rdata,&rparam,&rdata_len,&rparam_len);
3573 /* if we get False back then it's actually unsupported */
3575 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3576 &rdata,&rparam,&rdata_len,&rparam_len);
3579 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3580 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3582 rdata_buf.offset.start = 0;
3583 rdata_buf.offset.end = rdata_len;
3585 rparam_buf.offset.start = 0;
3586 rparam_buf.offset.end = rparam_len;
3588 /* now send the reply */
3589 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3591 if (rdata ) free(rdata);
3592 if (rparam) free(rparam);
3597 /****************************************************************************
3598 handle named pipe commands
3599 ****************************************************************************/
3600 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3601 uint16 *setup,char *data,char *params,
3602 int suwcnt,int tdscnt,int tpscnt,
3603 int msrcnt,int mdrcnt,int mprcnt)
3605 DEBUG(3,("named pipe command on <%s> name\n", name));
3607 if (strequal(name,"LANMAN"))
3609 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3612 if (strlen(name) < 1)
3614 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3619 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3626 /****************************************************************************
3628 ****************************************************************************/
3629 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3633 char *data=NULL,*params=NULL;
3637 int cnum = SVAL(inbuf,smb_tid);
3638 uint16 vuid = SVAL(inbuf,smb_uid);
3640 int tpscnt = SVAL(inbuf,smb_vwv0);
3641 int tdscnt = SVAL(inbuf,smb_vwv1);
3642 int mprcnt = SVAL(inbuf,smb_vwv2);
3643 int mdrcnt = SVAL(inbuf,smb_vwv3);
3644 int msrcnt = CVAL(inbuf,smb_vwv4);
3645 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3646 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3647 int pscnt = SVAL(inbuf,smb_vwv9);
3648 int psoff = SVAL(inbuf,smb_vwv10);
3649 int dscnt = SVAL(inbuf,smb_vwv11);
3650 int dsoff = SVAL(inbuf,smb_vwv12);
3651 int suwcnt = CVAL(inbuf,smb_vwv13);
3653 bzero(name, sizeof(name));
3654 fstrcpy(name,smb_buf(inbuf));
3656 if (dscnt > tdscnt || pscnt > tpscnt) {
3657 exit_server("invalid trans parameters\n");
3662 data = (char *)malloc(tdscnt);
3663 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3667 params = (char *)malloc(tpscnt);
3668 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3674 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3675 for (i=0;i<suwcnt;i++)
3676 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3680 if (pscnt < tpscnt || dscnt < tdscnt)
3682 /* We need to send an interim response then receive the rest
3683 of the parameter/data bytes */
3684 outsize = set_message(outbuf,0,0,True);
3686 send_smb(Client,outbuf);
3689 /* receive the rest of the trans packet */
3690 while (pscnt < tpscnt || dscnt < tdscnt)
3693 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3695 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3697 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3700 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3702 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3703 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3704 if (params) free(params);
3705 if (data) free(data);
3706 if (setup) free(setup);
3707 return(ERROR(ERRSRV,ERRerror));
3712 tpscnt = SVAL(inbuf,smb_vwv0);
3713 tdscnt = SVAL(inbuf,smb_vwv1);
3715 pcnt = SVAL(inbuf,smb_vwv2);
3716 poff = SVAL(inbuf,smb_vwv3);
3717 pdisp = SVAL(inbuf,smb_vwv4);
3719 dcnt = SVAL(inbuf,smb_vwv5);
3720 doff = SVAL(inbuf,smb_vwv6);
3721 ddisp = SVAL(inbuf,smb_vwv7);
3726 if (dscnt > tdscnt || pscnt > tpscnt) {
3727 exit_server("invalid trans parameters\n");
3731 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3733 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3737 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3739 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3741 DEBUG(5,("calling named_pipe\n"));
3742 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3743 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3747 DEBUG(3,("invalid pipe name\n"));
3752 if (data) free(data);
3753 if (params) free(params);
3754 if (setup) free(setup);
3756 if (close_on_completion)
3757 close_cnum(cnum,vuid);
3763 return(ERROR(ERRSRV,ERRnosupport));