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 * Attempt the plaintext password change first.
1637 * Older versions of Windows seem to do this.
1640 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1641 chgpasswd(user,pass1,pass2,False))
1643 SSVAL(*rparam,0,NERR_Success);
1647 * If the plaintext change failed, attempt
1648 * the encrypted. NT will generate this
1649 * after trying the samr method.
1652 if(SVAL(*rparam,0) != NERR_Success)
1654 struct smb_passwd *sampw = NULL;
1656 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1657 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1659 SSVAL(*rparam,0,NERR_Success);
1663 bzero(pass1,sizeof(fstring));
1664 bzero(pass2,sizeof(fstring));
1669 /****************************************************************************
1670 Set the user password (SamOEM version - gets plaintext).
1671 ****************************************************************************/
1673 static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
1674 int mdrcnt,int mprcnt,
1675 char **rdata,char **rparam,
1676 int *rdata_len,int *rparam_len)
1680 struct smb_passwd *sampw = NULL;
1681 char *p = param + 2;
1685 *rparam = REALLOC(*rparam,*rparam_len);
1689 SSVAL(*rparam,0,NERR_badpass);
1692 * Check the parameter definition is correct.
1694 if(!strequal(param + 2, "zsT")) {
1695 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1698 p = skip_string(p, 1);
1700 if(!strequal(p, "B516B16")) {
1701 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1704 p = skip_string(p,1);
1707 p = skip_string(p,1);
1709 if(check_oem_password( user, (unsigned char *)data, &sampw,
1710 new_passwd, (int)sizeof(new_passwd)) == False) {
1715 * At this point we have the new case-sensitive plaintext
1716 * password in the fstring new_passwd. If we wanted to synchronise
1717 * with UNIX passwords we would call a UNIX password changing
1718 * function here. However it would have to be done as root
1719 * as the plaintext of the old users password is not
1723 if(lp_unix_password_sync())
1724 ret = chgpasswd(user,"", new_passwd, True);
1726 if(ret && change_oem_password( sampw, new_passwd, False)) {
1727 SSVAL(*rparam,0,NERR_Success);
1733 /****************************************************************************
1736 ****************************************************************************/
1737 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1738 int mdrcnt,int mprcnt,
1739 char **rdata,char **rparam,
1740 int *rdata_len,int *rparam_len)
1742 int function = SVAL(param,0);
1743 char *str1 = param+2;
1744 char *str2 = skip_string(str1,1);
1745 char *p = skip_string(str2,1);
1749 printjob_decode(SVAL(p,0), &snum, &jobid);
1751 /* check it's a supported varient */
1752 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1756 *rparam = REALLOC(*rparam,*rparam_len);
1760 SSVAL(*rparam,0,NERR_Success);
1762 if (snum >= 0 && VALID_SNUM(snum))
1764 print_queue_struct *queue=NULL;
1766 count = get_printqueue(snum,cnum,&queue,NULL);
1768 for (i=0;i<count;i++)
1769 if ((queue[i].job&0xFF) == jobid)
1772 case 81: /* delete */
1773 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1774 del_printqueue(cnum,snum,queue[i].job);
1776 case 82: /* pause */
1777 case 83: /* resume */
1778 DEBUG(3,("%s queue entry %d\n",
1779 (function==82?"pausing":"resuming"),queue[i].job));
1780 status_printjob(cnum,snum,queue[i].job,
1781 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1788 SSVAL(*rparam,0,NERR_JobNotFound);
1790 if (queue) free(queue);
1793 SSVAL(*rparam,2,0); /* converter word */
1798 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1799 int mdrcnt,int mprcnt,
1800 char **rdata,char **rparam,
1801 int *rdata_len,int *rparam_len)
1803 char *str1 = param+2;
1804 char *str2 = skip_string(str1,1);
1805 char *QueueName = skip_string(str2,1);
1808 /* check it's a supported varient */
1809 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1813 *rparam = REALLOC(*rparam,*rparam_len);
1817 SSVAL(*rparam,0,NERR_Success);
1818 SSVAL(*rparam,2,0); /* converter word */
1820 snum = lp_servicenumber(QueueName);
1821 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1822 int pnum = lp_servicenumber(PRINTERS_NAME);
1824 lp_add_printer(QueueName,pnum);
1825 snum = lp_servicenumber(QueueName);
1829 if (snum >= 0 && VALID_SNUM(snum)) {
1830 print_queue_struct *queue=NULL;
1834 count = get_printqueue(snum,cnum,&queue,NULL);
1835 for (i = 0; i < count; i++)
1836 del_printqueue(cnum,snum,queue[i].job);
1838 if (queue) free(queue);
1841 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1847 /****************************************************************************
1848 set the property of a print job (undocumented?)
1849 ? function = 0xb -> set name of print job
1850 ? function = 0x6 -> move print job up/down
1851 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1852 or <WWsTP> <WB21BB16B10zWWzDDz>
1853 ****************************************************************************/
1854 static int check_printjob_info(struct pack_desc* desc,
1855 int uLevel, char* id)
1857 desc->subformat = NULL;
1859 case 0: desc->format = "W"; break;
1860 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1861 case 2: desc->format = "WWzWWDDzz"; break;
1862 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1863 default: return False;
1865 if (strcmp(desc->format,id) != 0) return False;
1869 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1870 int mdrcnt,int mprcnt,
1871 char **rdata,char **rparam,
1872 int *rdata_len,int *rparam_len)
1874 struct pack_desc desc;
1875 char *str1 = param+2;
1876 char *str2 = skip_string(str1,1);
1877 char *p = skip_string(str2,1);
1879 int uLevel = SVAL(p,2);
1880 int function = SVAL(p,4); /* what is this ?? */
1884 printjob_decode(SVAL(p,0), &snum, &jobid);
1887 *rparam = REALLOC(*rparam,*rparam_len);
1891 /* check it's a supported varient */
1892 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1896 case 0x6: /* change job place in the queue, data gives the new place */
1897 if (snum >= 0 && VALID_SNUM(snum))
1899 print_queue_struct *queue=NULL;
1903 count = get_printqueue(snum,cnum,&queue,NULL);
1904 for (i=0;i<count;i++) /* find job */
1905 if ((queue[i].job&0xFF) == jobid) break;
1908 desc.errcode=NERR_JobNotFound;
1909 if (queue) free(queue);
1912 desc.errcode=NERR_Success;
1916 int place= SVAL(data,0);
1917 /* we currently have no way of doing this. Can any unix do it? */
1918 if (i < place) /* move down */;
1919 else if (i > place ) /* move up */;
1922 desc.errcode=NERR_notsupported; /* not yet supported */
1923 if (queue) free(queue);
1926 else desc.errcode=NERR_JobNotFound;
1928 case 0xb: /* change print job name, data gives the name */
1929 /* jobid, snum should be zero */
1936 if (issafe(*s)) name[l++] = *s;
1941 DEBUG(3,("Setting print name to %s\n",name));
1945 for (i=0;i<MAX_OPEN_FILES;i++)
1946 if (Files[i].open && Files[i].print_file)
1949 int fcnum = Files[i].cnum;
1953 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1954 !become_service(fcnum,True))
1957 if (sys_rename(Files[i].name,name) == 0)
1958 string_set(&Files[i].name,name);
1962 unbecome_root(True);
1964 desc.errcode=NERR_Success;
1967 default: /* not implemented */
1971 SSVALS(*rparam,0,desc.errcode);
1972 SSVAL(*rparam,2,0); /* converter word */
1978 /****************************************************************************
1979 get info about the server
1980 ****************************************************************************/
1981 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1982 int mdrcnt,int mprcnt,
1983 char **rdata,char **rparam,
1984 int *rdata_len,int *rparam_len)
1986 char *str1 = param+2;
1987 char *str2 = skip_string(str1,1);
1988 char *p = skip_string(str2,1);
1989 int uLevel = SVAL(p,0);
1993 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1995 /* check it's a supported varient */
1996 if (!prefix_ok(str1,"WrLh")) return False;
1999 if (strcmp(str2,"B16") != 0) return False;
2003 if (strcmp(str2,"B16BBDz") != 0) return False;
2007 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2012 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2017 if (strcmp(str2,"DN") != 0) return False;
2021 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2024 default: return False;
2027 *rdata_len = mdrcnt;
2028 *rdata = REALLOC(*rdata,*rdata_len);
2031 p2 = p + struct_len;
2033 StrnCpy(p,local_machine,16);
2039 struct srv_info_struct *servers=NULL;
2042 uint32 servertype= lp_default_server_announce();
2044 pstrcpy(comment,lp_serverstring());
2046 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2047 for (i=0;i<count;i++)
2048 if (strequal(servers[i].name,local_machine))
2050 servertype = servers[i].type;
2051 pstrcpy(comment,servers[i].comment);
2054 if (servers) free(servers);
2056 SCVAL(p,0,lp_major_announce_version());
2057 SCVAL(p,1,lp_minor_announce_version());
2058 SIVAL(p,2,servertype);
2060 if (mdrcnt == struct_len) {
2063 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2064 standard_sub(cnum,comment);
2065 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2066 p2 = skip_string(p2,1);
2071 return False; /* not yet implemented */
2074 *rdata_len = PTR_DIFF(p2,*rdata);
2077 *rparam = REALLOC(*rparam,*rparam_len);
2078 SSVAL(*rparam,0,NERR_Success);
2079 SSVAL(*rparam,2,0); /* converter word */
2080 SSVAL(*rparam,4,*rdata_len);
2086 /****************************************************************************
2087 get info about the server
2088 ****************************************************************************/
2089 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
2090 int mdrcnt,int mprcnt,
2091 char **rdata,char **rparam,
2092 int *rdata_len,int *rparam_len)
2094 char *str1 = param+2;
2095 char *str2 = skip_string(str1,1);
2096 char *p = skip_string(str2,1);
2098 extern pstring sesssetup_user;
2099 int level = SVAL(p,0);
2101 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2104 *rparam = REALLOC(*rparam,*rparam_len);
2106 /* check it's a supported varient */
2107 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2110 *rdata_len = mdrcnt + 1024;
2111 *rdata = REALLOC(*rdata,*rdata_len);
2113 SSVAL(*rparam,0,NERR_Success);
2114 SSVAL(*rparam,2,0); /* converter word */
2120 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2121 pstrcpy(p2,local_machine);
2123 p2 = skip_string(p2,1);
2126 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2127 pstrcpy(p2,sesssetup_user);
2128 p2 = skip_string(p2,1);
2131 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2132 pstrcpy(p2,global_myworkgroup);
2134 p2 = skip_string(p2,1);
2137 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2138 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2141 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2142 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2143 p2 = skip_string(p2,1);
2146 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2148 p2 = skip_string(p2,1);
2151 *rdata_len = PTR_DIFF(p2,*rdata);
2153 SSVAL(*rparam,4,*rdata_len);
2158 /****************************************************************************
2159 get info about a user
2161 struct user_info_11 {
2162 char usri11_name[21]; 0-20
2164 char *usri11_comment; 22-25
2165 char *usri11_usr_comment; 26-29
2166 unsigned short usri11_priv; 30-31
2167 unsigned long usri11_auth_flags; 32-35
2168 long usri11_password_age; 36-39
2169 char *usri11_homedir; 40-43
2170 char *usri11_parms; 44-47
2171 long usri11_last_logon; 48-51
2172 long usri11_last_logoff; 52-55
2173 unsigned short usri11_bad_pw_count; 56-57
2174 unsigned short usri11_num_logons; 58-59
2175 char *usri11_logon_server; 60-63
2176 unsigned short usri11_country_code; 64-65
2177 char *usri11_workstations; 66-69
2178 unsigned long usri11_max_storage; 70-73
2179 unsigned short usri11_units_per_week; 74-75
2180 unsigned char *usri11_logon_hours; 76-79
2181 unsigned short usri11_code_page; 80-81
2186 usri11_name specifies the user name for which information is retireved
2188 usri11_pad aligns the next data structure element to a word boundary
2190 usri11_comment is a null terminated ASCII comment
2192 usri11_user_comment is a null terminated ASCII comment about the user
2194 usri11_priv specifies the level of the privilege assigned to the user.
2195 The possible values are:
2197 Name Value Description
2198 USER_PRIV_GUEST 0 Guest privilege
2199 USER_PRIV_USER 1 User privilege
2200 USER_PRV_ADMIN 2 Administrator privilege
2202 usri11_auth_flags specifies the account operator privileges. The
2203 possible values are:
2205 Name Value Description
2206 AF_OP_PRINT 0 Print operator
2209 Leach, Naik [Page 28]
\r\f
2212 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2215 AF_OP_COMM 1 Communications operator
2216 AF_OP_SERVER 2 Server operator
2217 AF_OP_ACCOUNTS 3 Accounts operator
2220 usri11_password_age specifies how many seconds have elapsed since the
2221 password was last changed.
2223 usri11_home_dir points to a null terminated ASCII string that contains
2224 the path name of the user's home directory.
2226 usri11_parms points to a null terminated ASCII string that is set
2227 aside for use by applications.
2229 usri11_last_logon specifies the time when the user last logged on.
2230 This value is stored as the number of seconds elapsed since
2231 00:00:00, January 1, 1970.
2233 usri11_last_logoff specifies the time when the user last logged off.
2234 This value is stored as the number of seconds elapsed since
2235 00:00:00, January 1, 1970. A value of 0 means the last logoff
2238 usri11_bad_pw_count specifies the number of incorrect passwords
2239 entered since the last successful logon.
2241 usri11_log1_num_logons specifies the number of times this user has
2242 logged on. A value of -1 means the number of logons is unknown.
2244 usri11_logon_server points to a null terminated ASCII string that
2245 contains the name of the server to which logon requests are sent.
2246 A null string indicates logon requests should be sent to the
2249 usri11_country_code specifies the country code for the user's language
2252 usri11_workstations points to a null terminated ASCII string that
2253 contains the names of workstations the user may log on from.
2254 There may be up to 8 workstations, with the names separated by
2255 commas. A null strings indicates there are no restrictions.
2257 usri11_max_storage specifies the maximum amount of disk space the user
2258 can occupy. A value of 0xffffffff indicates there are no
2261 usri11_units_per_week specifies the equal number of time units into
2262 which a week is divided. This value must be equal to 168.
2264 usri11_logon_hours points to a 21 byte (168 bits) string that
2265 specifies the time during which the user can log on. Each bit
2266 represents one unique hour in a week. The first bit (bit 0, word
2267 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2271 Leach, Naik [Page 29]
\r\f
2274 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2277 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2278 are no restrictions.
2280 usri11_code_page specifies the code page for the user's language of
2283 All of the pointers in this data structure need to be treated
2284 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2285 to be ignored. The converter word returned in the parameters section
2286 needs to be subtracted from the lower 16 bits to calculate an offset
2287 into the return buffer where this ASCII string resides.
2289 There is no auxiliary data in the response.
2291 ****************************************************************************/
2293 #define usri11_name 0
2294 #define usri11_pad 21
2295 #define usri11_comment 22
2296 #define usri11_usr_comment 26
2297 #define usri11_full_name 30
2298 #define usri11_priv 34
2299 #define usri11_auth_flags 36
2300 #define usri11_password_age 40
2301 #define usri11_homedir 44
2302 #define usri11_parms 48
2303 #define usri11_last_logon 52
2304 #define usri11_last_logoff 56
2305 #define usri11_bad_pw_count 60
2306 #define usri11_num_logons 62
2307 #define usri11_logon_server 64
2308 #define usri11_country_code 68
2309 #define usri11_workstations 70
2310 #define usri11_max_storage 74
2311 #define usri11_units_per_week 78
2312 #define usri11_logon_hours 80
2313 #define usri11_code_page 84
2314 #define usri11_end 86
2316 #define USER_PRIV_GUEST 0
2317 #define USER_PRIV_USER 1
2318 #define USER_PRIV_ADMIN 2
2320 #define AF_OP_PRINT 0
2321 #define AF_OP_COMM 1
2322 #define AF_OP_SERVER 2
2323 #define AF_OP_ACCOUNTS 3
2326 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2327 int mdrcnt,int mprcnt,
2328 char **rdata,char **rparam,
2329 int *rdata_len,int *rparam_len)
2331 char *str1 = param+2;
2332 char *str2 = skip_string(str1,1);
2333 char *UserName = skip_string(str2,1);
2334 char *p = skip_string(UserName,1);
2335 int uLevel = SVAL(p,0);
2338 /* get NIS home of a previously validated user - simeon */
2339 /* With share level security vuid will always be zero.
2340 Don't depend on vuser being non-null !!. JRA */
2341 user_struct *vuser = get_valid_user_struct(vuid);
2343 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2346 *rparam = REALLOC(*rparam,*rparam_len);
2348 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2350 /* check it's a supported variant */
2351 if (strcmp(str1,"zWrLh") != 0) return False;
2354 case 0: p2 = "B21"; break;
2355 case 1: p2 = "B21BB16DWzzWz"; break;
2356 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2357 case 10: p2 = "B21Bzzz"; break;
2358 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2359 default: return False;
2362 if (strcmp(p2,str2) != 0) return False;
2364 *rdata_len = mdrcnt + 1024;
2365 *rdata = REALLOC(*rdata,*rdata_len);
2367 SSVAL(*rparam,0,NERR_Success);
2368 SSVAL(*rparam,2,0); /* converter word */
2371 p2 = p + usri11_end;
2374 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2378 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2383 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2384 pstrcpy(p2,"Comment");
2385 p2 = skip_string(p2,1);
2387 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2388 pstrcpy(p2,"UserComment");
2389 p2 = skip_string(p2,1);
2391 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2392 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2393 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2394 p2 = skip_string(p2,1);
2397 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2399 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2400 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2401 SIVALS(p,usri11_password_age,-1); /* password age */
2402 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2403 pstrcpy(p2, lp_logon_path());
2404 p2 = skip_string(p2,1);
2405 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2407 p2 = skip_string(p2,1);
2408 SIVAL(p,usri11_last_logon,0); /* last logon */
2409 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2410 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2411 SSVALS(p,usri11_num_logons,-1); /* num logons */
2412 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2413 pstrcpy(p2,"\\\\*");
2414 p2 = skip_string(p2,1);
2415 SSVAL(p,usri11_country_code,0); /* country code */
2417 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2419 p2 = skip_string(p2,1);
2421 SIVALS(p,usri11_max_storage,-1); /* max storage */
2422 SSVAL(p,usri11_units_per_week,168); /* units per week */
2423 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2425 /* a simple way to get logon hours at all times. */
2427 SCVAL(p2,21,0); /* fix zero termination */
2428 p2 = skip_string(p2,1);
2430 SSVAL(p,usri11_code_page,0); /* code page */
2432 if (uLevel == 1 || uLevel == 2)
2434 memset(p+22,' ',16); /* password */
2435 SIVALS(p,38,-1); /* password age */
2437 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2438 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2439 pstrcpy(p2,lp_logon_path());
2440 p2 = skip_string(p2,1);
2441 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2443 SSVAL(p,52,0); /* flags */
2444 SIVAL(p,54,0); /* script_path */
2447 SIVAL(p,60,0); /* auth_flags */
2448 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2449 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2450 p2 = skip_string(p2,1);
2451 SIVAL(p,68,0); /* urs_comment */
2452 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2454 p2 = skip_string(p2,1);
2455 SIVAL(p,76,0); /* workstations */
2456 SIVAL(p,80,0); /* last_logon */
2457 SIVAL(p,84,0); /* last_logoff */
2458 SIVALS(p,88,-1); /* acct_expires */
2459 SIVALS(p,92,-1); /* max_storage */
2460 SSVAL(p,96,168); /* units_per_week */
2461 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2464 SSVALS(p,102,-1); /* bad_pw_count */
2465 SSVALS(p,104,-1); /* num_logons */
2466 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2467 pstrcpy(p2,"\\\\%L");
2468 standard_sub_basic(p2);
2469 p2 = skip_string(p2,1);
2470 SSVAL(p,110,49); /* country_code */
2471 SSVAL(p,112,860); /* code page */
2475 *rdata_len = PTR_DIFF(p2,*rdata);
2477 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2482 /*******************************************************************
2483 get groups that a user is a member of
2484 ******************************************************************/
2485 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2486 int mdrcnt,int mprcnt,
2487 char **rdata,char **rparam,
2488 int *rdata_len,int *rparam_len)
2490 char *str1 = param+2;
2491 char *str2 = skip_string(str1,1);
2492 char *UserName = skip_string(str2,1);
2493 char *p = skip_string(UserName,1);
2494 int uLevel = SVAL(p,0);
2499 *rparam = REALLOC(*rparam,*rparam_len);
2501 /* check it's a supported varient */
2502 if (strcmp(str1,"zWrLeh") != 0) return False;
2504 case 0: p2 = "B21"; break;
2505 default: return False;
2507 if (strcmp(p2,str2) != 0) return False;
2509 *rdata_len = mdrcnt + 1024;
2510 *rdata = REALLOC(*rdata,*rdata_len);
2512 SSVAL(*rparam,0,NERR_Success);
2513 SSVAL(*rparam,2,0); /* converter word */
2517 /* XXXX we need a real SAM database some day */
2518 pstrcpy(p,"Users"); p += 21; count++;
2519 pstrcpy(p,"Domain Users"); p += 21; count++;
2520 pstrcpy(p,"Guests"); p += 21; count++;
2521 pstrcpy(p,"Domain Guests"); p += 21; count++;
2523 *rdata_len = PTR_DIFF(p,*rdata);
2525 SSVAL(*rparam,4,count); /* is this right?? */
2526 SSVAL(*rparam,6,count); /* is this right?? */
2532 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2533 int mdrcnt,int mprcnt,
2534 char **rdata,char **rparam,
2535 int *rdata_len,int *rparam_len)
2537 char *str1 = param+2;
2538 char *str2 = skip_string(str1,1);
2539 char *p = skip_string(str2,1);
2541 struct pack_desc desc;
2548 bzero(&desc,sizeof(desc));
2550 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2552 /* check it's a supported varient */
2553 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2554 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2555 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2557 desc.buflen = mdrcnt;
2558 desc.subformat = NULL;
2561 if (init_package(&desc,1,0))
2563 PACKI(&desc,"W",0); /* code */
2564 PACKS(&desc,"B21",name); /* eff. name */
2565 PACKS(&desc,"B",""); /* pad */
2567 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2568 PACKI(&desc,"D",0); /* auth flags XXX */
2569 PACKI(&desc,"W",0); /* num logons */
2570 PACKI(&desc,"W",0); /* bad pw count */
2571 PACKI(&desc,"D",0); /* last logon */
2572 PACKI(&desc,"D",-1); /* last logoff */
2573 PACKI(&desc,"D",-1); /* logoff time */
2574 PACKI(&desc,"D",-1); /* kickoff time */
2575 PACKI(&desc,"D",0); /* password age */
2576 PACKI(&desc,"D",0); /* password can change */
2577 PACKI(&desc,"D",-1); /* password must change */
2580 fstrcpy(mypath,"\\\\");
2581 fstrcat(mypath,local_machine);
2583 PACKS(&desc,"z",mypath); /* computer */
2585 PACKS(&desc,"z",global_myworkgroup);/* domain */
2587 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2588 /* made sure all macros are fully substituted and available */
2589 logon_script = lp_logon_script();
2590 standard_sub( cnum, logon_script );
2591 PACKS(&desc,"z", logon_script); /* script path */
2592 /* End of JHT mods */
2594 PACKI(&desc,"D",0x00000000); /* reserved */
2597 *rdata_len = desc.usedlen;
2599 *rparam = REALLOC(*rparam,*rparam_len);
2600 SSVALS(*rparam,0,desc.errcode);
2602 SSVAL(*rparam,4,desc.neededlen);
2604 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2609 /****************************************************************************
2610 api_WAccessGetUserPerms
2611 ****************************************************************************/
2612 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2613 int mdrcnt,int mprcnt,
2614 char **rdata,char **rparam,
2615 int *rdata_len,int *rparam_len)
2617 char *str1 = param+2;
2618 char *str2 = skip_string(str1,1);
2619 char *user = skip_string(str2,1);
2620 char *resource = skip_string(user,1);
2622 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2624 /* check it's a supported varient */
2625 if (strcmp(str1,"zzh") != 0) return False;
2626 if (strcmp(str2,"") != 0) return False;
2629 *rparam = REALLOC(*rparam,*rparam_len);
2630 SSVALS(*rparam,0,0); /* errorcode */
2631 SSVAL(*rparam,2,0); /* converter word */
2632 SSVAL(*rparam,4,0x7f); /* permission flags */
2637 /****************************************************************************
2638 api_WPrintJobEnumerate
2639 ****************************************************************************/
2640 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2641 int mdrcnt,int mprcnt,
2642 char **rdata,char **rparam,
2643 int *rdata_len,int *rparam_len)
2645 char *str1 = param+2;
2646 char *str2 = skip_string(str1,1);
2647 char *p = skip_string(str2,1);
2653 struct pack_desc desc;
2654 print_queue_struct *queue=NULL;
2655 print_status_struct status;
2660 bzero(&desc,sizeof(desc));
2661 bzero(&status,sizeof(status));
2663 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2665 /* check it's a supported varient */
2666 if (strcmp(str1,"WWrLh") != 0) return False;
2667 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2669 printjob_decode(SVAL(p,0), &snum, &job);
2671 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2673 count = get_printqueue(snum,cnum,&queue,&status);
2674 for (i = 0; i < count; i++) {
2675 if ((queue[i].job & 0xFF) == job) break;
2677 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2679 desc.buflen = mdrcnt;
2681 if (init_package(&desc,1,0)) {
2683 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2684 *rdata_len = desc.usedlen;
2687 desc.errcode = NERR_JobNotFound;
2693 *rparam = REALLOC(*rparam,*rparam_len);
2694 SSVALS(*rparam,0,desc.errcode);
2696 SSVAL(*rparam,4,desc.neededlen);
2698 if (queue) free(queue);
2700 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2704 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2705 int mdrcnt,int mprcnt,
2706 char **rdata,char **rparam,
2707 int *rdata_len,int *rparam_len)
2709 char *str1 = param+2;
2710 char *str2 = skip_string(str1,1);
2711 char *p = skip_string(str2,1);
2717 struct pack_desc desc;
2718 print_queue_struct *queue=NULL;
2719 print_status_struct status;
2721 bzero(&desc,sizeof(desc));
2722 bzero(&status,sizeof(status));
2724 p = skip_string(p,1);
2728 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2730 /* check it's a supported varient */
2731 if (strcmp(str1,"zWrLeh") != 0) return False;
2732 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2733 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2735 snum = lp_servicenumber(name);
2736 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2737 int pnum = lp_servicenumber(PRINTERS_NAME);
2739 lp_add_printer(name,pnum);
2740 snum = lp_servicenumber(name);
2744 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2746 count = get_printqueue(snum,cnum,&queue,&status);
2747 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2749 desc.buflen = mdrcnt;
2751 if (init_package(&desc,count,0)) {
2753 for (i = 0; i < count; i++) {
2754 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2755 if (desc.errcode == NERR_Success) succnt = i+1;
2759 *rdata_len = desc.usedlen;
2762 *rparam = REALLOC(*rparam,*rparam_len);
2763 SSVALS(*rparam,0,desc.errcode);
2765 SSVAL(*rparam,4,succnt);
2766 SSVAL(*rparam,6,count);
2768 if (queue) free(queue);
2770 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2774 static int check_printdest_info(struct pack_desc* desc,
2775 int uLevel, char* id)
2777 desc->subformat = NULL;
2779 case 0: desc->format = "B9"; break;
2780 case 1: desc->format = "B9B21WWzW"; break;
2781 case 2: desc->format = "z"; break;
2782 case 3: desc->format = "zzzWWzzzWW"; break;
2783 default: return False;
2785 if (strcmp(desc->format,id) != 0) return False;
2789 static void fill_printdest_info(int cnum, int snum, int uLevel,
2790 struct pack_desc* desc)
2793 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2794 buf[sizeof(buf)-1] = 0;
2797 PACKS(desc,"B9",buf); /* szName */
2799 PACKS(desc,"B21",""); /* szUserName */
2800 PACKI(desc,"W",0); /* uJobId */
2801 PACKI(desc,"W",0); /* fsStatus */
2802 PACKS(desc,"z",""); /* pszStatus */
2803 PACKI(desc,"W",0); /* time */
2806 if (uLevel == 2 || uLevel == 3) {
2807 PACKS(desc,"z",buf); /* pszPrinterName */
2809 PACKS(desc,"z",""); /* pszUserName */
2810 PACKS(desc,"z",""); /* pszLogAddr */
2811 PACKI(desc,"W",0); /* uJobId */
2812 PACKI(desc,"W",0); /* fsStatus */
2813 PACKS(desc,"z",""); /* pszStatus */
2814 PACKS(desc,"z",""); /* pszComment */
2815 PACKS(desc,"z","NULL"); /* pszDrivers */
2816 PACKI(desc,"W",0); /* time */
2817 PACKI(desc,"W",0); /* pad1 */
2822 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2823 int mdrcnt,int mprcnt,
2824 char **rdata,char **rparam,
2825 int *rdata_len,int *rparam_len)
2827 char *str1 = param+2;
2828 char *str2 = skip_string(str1,1);
2829 char *p = skip_string(str2,1);
2830 char* PrinterName = p;
2832 struct pack_desc desc;
2835 bzero(&desc,sizeof(desc));
2837 p = skip_string(p,1);
2841 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2843 /* check it's a supported varient */
2844 if (strcmp(str1,"zWrLh") != 0) return False;
2845 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2847 snum = lp_servicenumber(PrinterName);
2848 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2849 int pnum = lp_servicenumber(PRINTERS_NAME);
2851 lp_add_printer(PrinterName,pnum);
2852 snum = lp_servicenumber(PrinterName);
2858 desc.errcode = NERR_DestNotFound;
2862 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2864 desc.buflen = mdrcnt;
2865 if (init_package(&desc,1,0)) {
2866 fill_printdest_info(cnum,snum,uLevel,&desc);
2868 *rdata_len = desc.usedlen;
2872 *rparam = REALLOC(*rparam,*rparam_len);
2873 SSVALS(*rparam,0,desc.errcode);
2875 SSVAL(*rparam,4,desc.neededlen);
2877 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2881 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2882 int mdrcnt,int mprcnt,
2883 char **rdata,char **rparam,
2884 int *rdata_len,int *rparam_len)
2886 char *str1 = param+2;
2887 char *str2 = skip_string(str1,1);
2888 char *p = skip_string(str2,1);
2892 struct pack_desc desc;
2893 int services = lp_numservices();
2895 bzero(&desc,sizeof(desc));
2900 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2902 /* check it's a supported varient */
2903 if (strcmp(str1,"WrLeh") != 0) return False;
2904 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2907 for (i = 0; i < services; i++)
2908 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2911 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2913 desc.buflen = mdrcnt;
2914 if (init_package(&desc,queuecnt,0)) {
2917 for (i = 0; i < services; i++) {
2918 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2919 fill_printdest_info(cnum,i,uLevel,&desc);
2921 if (desc.errcode == NERR_Success) succnt = n;
2926 *rdata_len = desc.usedlen;
2929 *rparam = REALLOC(*rparam,*rparam_len);
2930 SSVALS(*rparam,0,desc.errcode);
2932 SSVAL(*rparam,4,succnt);
2933 SSVAL(*rparam,6,queuecnt);
2935 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2939 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2940 int mdrcnt,int mprcnt,
2941 char **rdata,char **rparam,
2942 int *rdata_len,int *rparam_len)
2944 char *str1 = param+2;
2945 char *str2 = skip_string(str1,1);
2946 char *p = skip_string(str2,1);
2949 struct pack_desc desc;
2951 bzero(&desc,sizeof(desc));
2956 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2958 /* check it's a supported varient */
2959 if (strcmp(str1,"WrLeh") != 0) return False;
2960 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2962 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2964 desc.buflen = mdrcnt;
2965 if (init_package(&desc,1,0)) {
2966 PACKS(&desc,"B41","NULL");
2969 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2971 *rdata_len = desc.usedlen;
2974 *rparam = REALLOC(*rparam,*rparam_len);
2975 SSVALS(*rparam,0,desc.errcode);
2977 SSVAL(*rparam,4,succnt);
2980 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2984 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2985 int mdrcnt,int mprcnt,
2986 char **rdata,char **rparam,
2987 int *rdata_len,int *rparam_len)
2989 char *str1 = param+2;
2990 char *str2 = skip_string(str1,1);
2991 char *p = skip_string(str2,1);
2994 struct pack_desc desc;
2996 bzero(&desc,sizeof(desc));
3001 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3003 /* check it's a supported varient */
3004 if (strcmp(str1,"WrLeh") != 0) return False;
3005 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3007 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3009 desc.buflen = mdrcnt;
3011 if (init_package(&desc,1,0)) {
3012 PACKS(&desc,"B13","lpd");
3015 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3017 *rdata_len = desc.usedlen;
3020 *rparam = REALLOC(*rparam,*rparam_len);
3021 SSVALS(*rparam,0,desc.errcode);
3023 SSVAL(*rparam,4,succnt);
3026 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3030 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
3031 int mdrcnt,int mprcnt,
3032 char **rdata,char **rparam,
3033 int *rdata_len,int *rparam_len)
3035 char *str1 = param+2;
3036 char *str2 = skip_string(str1,1);
3037 char *p = skip_string(str2,1);
3040 struct pack_desc desc;
3042 bzero(&desc,sizeof(desc));
3047 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3049 /* check it's a supported varient */
3050 if (strcmp(str1,"WrLeh") != 0) return False;
3051 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3053 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3054 bzero(&desc,sizeof(desc));
3056 desc.buflen = mdrcnt;
3058 if (init_package(&desc,1,0)) {
3059 PACKS(&desc,"B13","lp0");
3062 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3064 *rdata_len = desc.usedlen;
3067 *rparam = REALLOC(*rparam,*rparam_len);
3068 SSVALS(*rparam,0,desc.errcode);
3070 SSVAL(*rparam,4,succnt);
3073 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3079 char * pipe_clnt_name;
3080 char * pipe_srv_name;
3081 BOOL (*fn) (pipes_struct *, prs_struct *);
3084 static struct api_cmd api_fd_commands[] =
3086 { "lsarpc", "lsass", api_ntlsa_rpc },
3087 { "samr", "lsass", api_samr_rpc },
3088 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3089 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3090 { "NETLOGON", "lsass", api_netlog_rpc },
3091 { "winreg", "winreg", api_reg_rpc },
3092 { NULL, NULL, NULL }
3095 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3097 BOOL ntlmssp_auth = False;
3098 fstring ack_pipe_name;
3101 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3103 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3105 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3106 api_fd_commands[i].fn != NULL)
3108 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3109 api_fd_commands[i].pipe_clnt_name,
3110 api_fd_commands[i].pipe_srv_name));
3111 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3116 if (api_fd_commands[i].fn == NULL) return False;
3118 /* decode the bind request */
3119 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3121 if (pd->offset == 0) return False;
3123 if (p->hdr.auth_len != 0)
3125 /* decode the authentication verifier */
3126 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3128 if (pd->offset == 0) return False;
3130 /* ignore the version number for now */
3131 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3134 /* name has to be \PIPE\xxxxx */
3135 fstrcpy(ack_pipe_name, "\\PIPE\\");
3136 fstrcat(ack_pipe_name, p->pipe_srv_name);
3138 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3140 prs_init(&(p->rdata), 1024, 4, 0, False);
3141 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3142 prs_init(&(p->rauth), 1024, 4, 0, False);
3145 /*** do the bind ack first ***/
3148 make_rpc_hdr_ba(&p->hdr_ba,
3149 p->hdr_rb.bba.max_tsize,
3150 p->hdr_rb.bba.max_rsize,
3151 p->hdr_rb.bba.assoc_gid,
3154 &(p->hdr_rb.transfer));
3156 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3157 mem_realloc_data(p->rdata.data, p->rdata.offset);
3160 /*** now the authentication ***/
3166 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3168 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3171 0x00000000, 0x0000b2b3, 0x000082b1,
3173 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3174 mem_realloc_data(p->rauth.data, p->rauth.offset);
3178 /*** then do the header, now we know the length ***/
3181 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3183 p->rdata.offset + p->rauth.offset,
3186 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3187 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3190 /*** link rpc header, bind acknowledgment and authentication responses ***/
3193 p->rhdr.data->offset.start = 0;
3194 p->rhdr.data->offset.end = p->rhdr.offset;
3195 p->rhdr.data->next = p->rdata.data;
3199 p->rdata.data->offset.start = p->rhdr.offset;
3200 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3201 p->rdata.data->next = p->rauth.data;
3203 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3204 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3205 p->rauth.data->next = NULL;
3209 p->rdata.data->offset.start = p->rhdr.offset;
3210 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3211 p->rdata.data->next = NULL;
3217 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3221 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3223 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3224 api_fd_commands[i].fn != NULL)
3226 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3227 return api_fd_commands[i].fn(p, pd);
3233 static BOOL api_dce_rpc_command(char *outbuf,
3238 if (pd->data == NULL) return False;
3240 /* process the rpc header */
3241 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3243 if (pd->offset == 0) return False;
3245 switch (p->hdr.pkt_type)
3249 reply = api_pipe_bind_req(p, pd);
3254 reply = api_pipe_request (p, pd);
3261 /* now send the reply */
3262 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3264 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3266 /* all of data was sent: no need to wait for SMBreadX calls */
3267 mem_free_data(p->rhdr .data);
3268 mem_free_data(p->rdata.data);
3275 /****************************************************************************
3276 SetNamedPipeHandleState
3277 ****************************************************************************/
3278 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3282 if (!param) return False;
3284 id = param[0] + (param[1] << 8);
3285 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3287 if (set_rpc_pipe_hnd_state(p, id))
3289 /* now send the reply */
3290 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3298 /****************************************************************************
3299 when no reply is generated, indicate unsupported.
3300 ****************************************************************************/
3301 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3303 struct mem_buf rparam;
3305 mem_init(&rparam, 0);
3306 mem_alloc_data(&rparam, 4);
3308 rparam.offset.start = 0;
3309 rparam.offset.end = 4;
3312 SSVAL(rparam.data,0,NERR_notsupported);
3313 SSVAL(rparam.data,2,0); /* converter word */
3315 DEBUG(3,("Unsupported API fd command\n"));
3317 /* now send the reply */
3318 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3320 mem_free_data(&rparam);
3325 /****************************************************************************
3326 handle remote api calls delivered to a named pipe already opened.
3327 ****************************************************************************/
3328 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3329 uint16 *setup,char *data,char *params,
3330 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3336 pipes_struct *p = NULL;
3338 struct mem_buf data_buf;
3340 DEBUG(5,("api_fd_reply\n"));
3342 /* fake up a data buffer from the api_fd_reply data parameters */
3343 mem_create(&data_buf, data, tdscnt, 0, False);
3344 data_buf.offset.start = 0;
3345 data_buf.offset.end = tdscnt;
3347 /* fake up a parsing structure */
3348 pd.data = &data_buf;
3353 /* First find out the name of this file. */
3356 DEBUG(0,("Unexpected named pipe transaction.\n"));
3360 /* Get the file handle and hence the file name. */
3362 subcommand = setup[0];
3363 get_rpc_pipe(pnum, &p);
3367 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3368 subcommand, p->name, pnum));
3369 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3370 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3372 /* record maximum data length that can be transmitted in an SMBtrans */
3373 p->file_offset = mdrcnt;
3375 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3376 p, p->file_offset));
3382 /* dce/rpc command */
3383 reply = api_dce_rpc_command(outbuf, p, &pd);
3388 /* Set Named Pipe Handle state */
3389 reply = api_SNPHS(outbuf, p, params);
3396 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3401 return api_no_reply(outbuf, mdrcnt);
3406 /****************************************************************************
3407 the buffer was too small
3408 ****************************************************************************/
3409 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3410 int mdrcnt,int mprcnt,
3411 char **rdata,char **rparam,
3412 int *rdata_len,int *rparam_len)
3414 *rparam_len = MIN(*rparam_len,mprcnt);
3415 *rparam = REALLOC(*rparam,*rparam_len);
3419 SSVAL(*rparam,0,NERR_BufTooSmall);
3421 DEBUG(3,("Supplied buffer too small in API command\n"));
3427 /****************************************************************************
3428 the request is not supported
3429 ****************************************************************************/
3430 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3431 int mdrcnt,int mprcnt,
3432 char **rdata,char **rparam,
3433 int *rdata_len,int *rparam_len)
3436 *rparam = REALLOC(*rparam,*rparam_len);
3440 SSVAL(*rparam,0,NERR_notsupported);
3441 SSVAL(*rparam,2,0); /* converter word */
3443 DEBUG(3,("Unsupported API command\n"));
3455 BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *);
3457 } api_commands[] = {
3458 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3459 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3460 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3461 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3462 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3463 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3464 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3465 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3466 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3467 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3468 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3469 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3470 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3471 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3472 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3473 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3474 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3475 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3476 {"NetServerEnum", 104, api_RNetServerEnum,0},
3477 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3478 {"SetUserPassword", 115, api_SetUserPassword,0},
3479 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3480 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3481 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3482 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3483 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3484 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3485 {NULL, -1, api_Unsupported,0}};
3488 /****************************************************************************
3489 handle remote api calls
3490 ****************************************************************************/
3491 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3492 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3494 int api_command = SVAL(params,0);
3495 struct mem_buf rdata_buf;
3496 struct mem_buf rparam_buf;
3498 char *rparam = NULL;
3504 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3505 api_command,params+2,skip_string(params+2,1),
3506 tdscnt,tpscnt,mdrcnt,mprcnt));
3508 for (i=0;api_commands[i].name;i++)
3509 if (api_commands[i].id == api_command && api_commands[i].fn)
3511 DEBUG(3,("Doing %s\n",api_commands[i].name));
3515 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3516 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3518 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3519 &rdata,&rparam,&rdata_len,&rparam_len);
3522 if (rdata_len > mdrcnt ||
3523 rparam_len > mprcnt)
3525 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3526 &rdata,&rparam,&rdata_len,&rparam_len);
3530 /* if we get False back then it's actually unsupported */
3532 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3533 &rdata,&rparam,&rdata_len,&rparam_len);
3536 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3537 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3539 rdata_buf.offset.start = 0;
3540 rdata_buf.offset.end = rdata_len;
3542 rparam_buf.offset.start = 0;
3543 rparam_buf.offset.end = rparam_len;
3545 /* now send the reply */
3546 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3548 if (rdata ) free(rdata);
3549 if (rparam) free(rparam);
3554 /****************************************************************************
3555 handle named pipe commands
3556 ****************************************************************************/
3557 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3558 uint16 *setup,char *data,char *params,
3559 int suwcnt,int tdscnt,int tpscnt,
3560 int msrcnt,int mdrcnt,int mprcnt)
3562 DEBUG(3,("named pipe command on <%s> name\n", name));
3564 if (strequal(name,"LANMAN"))
3566 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3569 if (strlen(name) < 1)
3571 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3576 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3583 /****************************************************************************
3585 ****************************************************************************/
3586 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3590 char *data=NULL,*params=NULL;
3594 int cnum = SVAL(inbuf,smb_tid);
3595 uint16 vuid = SVAL(inbuf,smb_uid);
3597 int tpscnt = SVAL(inbuf,smb_vwv0);
3598 int tdscnt = SVAL(inbuf,smb_vwv1);
3599 int mprcnt = SVAL(inbuf,smb_vwv2);
3600 int mdrcnt = SVAL(inbuf,smb_vwv3);
3601 int msrcnt = CVAL(inbuf,smb_vwv4);
3602 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3603 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3604 int pscnt = SVAL(inbuf,smb_vwv9);
3605 int psoff = SVAL(inbuf,smb_vwv10);
3606 int dscnt = SVAL(inbuf,smb_vwv11);
3607 int dsoff = SVAL(inbuf,smb_vwv12);
3608 int suwcnt = CVAL(inbuf,smb_vwv13);
3610 bzero(name, sizeof(name));
3611 fstrcpy(name,smb_buf(inbuf));
3613 if (dscnt > tdscnt || pscnt > tpscnt) {
3614 exit_server("invalid trans parameters\n");
3619 data = (char *)malloc(tdscnt);
3620 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3624 params = (char *)malloc(tpscnt);
3625 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3631 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3632 for (i=0;i<suwcnt;i++)
3633 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3637 if (pscnt < tpscnt || dscnt < tdscnt)
3639 /* We need to send an interim response then receive the rest
3640 of the parameter/data bytes */
3641 outsize = set_message(outbuf,0,0,True);
3643 send_smb(Client,outbuf);
3646 /* receive the rest of the trans packet */
3647 while (pscnt < tpscnt || dscnt < tdscnt)
3650 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3652 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3654 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3657 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3659 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3660 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3661 if (params) free(params);
3662 if (data) free(data);
3663 if (setup) free(setup);
3664 return(ERROR(ERRSRV,ERRerror));
3669 tpscnt = SVAL(inbuf,smb_vwv0);
3670 tdscnt = SVAL(inbuf,smb_vwv1);
3672 pcnt = SVAL(inbuf,smb_vwv2);
3673 poff = SVAL(inbuf,smb_vwv3);
3674 pdisp = SVAL(inbuf,smb_vwv4);
3676 dcnt = SVAL(inbuf,smb_vwv5);
3677 doff = SVAL(inbuf,smb_vwv6);
3678 ddisp = SVAL(inbuf,smb_vwv7);
3683 if (dscnt > tdscnt || pscnt > tpscnt) {
3684 exit_server("invalid trans parameters\n");
3688 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3690 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3694 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3696 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3698 DEBUG(5,("calling named_pipe\n"));
3699 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3700 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3704 DEBUG(3,("invalid pipe name\n"));
3709 if (data) free(data);
3710 if (params) free(params);
3711 if (setup) free(setup);
3713 if (close_on_completion)
3714 close_cnum(cnum,vuid);
3720 return(ERROR(ERRSRV,ERRnosupport));