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 myworkgroup;
45 #define NERR_Success 0
46 #define NERR_badpass 86
47 #define NERR_notsupported 50
49 #define NERR_BASE (2100)
50 #define NERR_BufTooSmall (NERR_BASE+23)
51 #define NERR_JobNotFound (NERR_BASE+51)
52 #define NERR_DestNotFound (NERR_BASE+52)
53 #define ERROR_INVALID_LEVEL 124
54 #define ERROR_MORE_DATA 234
56 #define ACCESS_READ 0x01
57 #define ACCESS_WRITE 0x02
58 #define ACCESS_CREATE 0x04
60 #define SHPWLEN 8 /* share password length */
61 #define NNLEN 12 /* 8.3 net name length */
62 #define SNLEN 15 /* service name length */
63 #define QNLEN 12 /* queue name maximum length */
66 extern int oplock_sock;
67 extern int smb_read_error;
69 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
70 int mdrcnt,int mprcnt,
71 char **rdata,char **rparam,
72 int *rdata_len,int *rparam_len);
73 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
74 int mdrcnt,int mprcnt,
75 char **rdata,char **rparam,
76 int *rdata_len,int *rparam_len);
79 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
84 if (!src || !dst || !n || !(*dst)) return(0);
86 StrnCpy(buf,src,sizeof(buf)/2);
87 string_sub(buf,"%S",lp_servicename(snum));
88 standard_sub(cnum,buf);
96 static int CopyAndAdvance(char** dst, char* src, int* n)
99 if (!src || !dst || !n || !(*dst)) return(0);
100 StrnCpy(*dst,src,*n);
101 l = strlen(*dst) + 1;
107 static int StrlenExpanded(int cnum, int snum, char* s)
111 StrnCpy(buf,s,sizeof(buf)/2);
112 string_sub(buf,"%S",lp_servicename(snum));
113 standard_sub(cnum,buf);
114 return strlen(buf) + 1;
117 static char* Expand(int cnum, int snum, char* s)
120 if (!s) return(NULL);
121 StrnCpy(buf,s,sizeof(buf)/2);
122 string_sub(buf,"%S",lp_servicename(snum));
123 standard_sub(cnum,buf);
127 /*******************************************************************
128 check a API string for validity when we only need to check the prefix
129 ******************************************************************/
130 static BOOL prefix_ok(char *str,char *prefix)
132 return(strncmp(str,prefix,strlen(prefix)) == 0);
135 /*******************************************************************
136 copies parameters and data, as needed, into the smb buffer
138 *both* the data and params sections should be aligned. this
139 is fudged in the rpc pipes by
140 at present, only the data section is. this may be a possible
141 cause of some of the ipc problems being experienced. lkcl26dec97
143 ******************************************************************/
144 static void copy_trans_params_and_data(char *outbuf, int align,
145 struct mem_buf *rparam, struct mem_buf *rdata,
146 int param_offset, int data_offset,
147 int param_len, int data_len)
149 char *copy_into = smb_buf(outbuf);
151 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
152 param_offset, param_offset + param_len,
153 data_offset , data_offset + data_len));
155 if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
156 copy_into += param_len + align;
157 if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
160 /****************************************************************************
162 ****************************************************************************/
163 static void send_trans_reply(char *outbuf,
164 struct mem_buf *rdata,
165 struct mem_buf *rparam,
166 uint16 *setup, int lsetup, int max_data_ret)
169 int this_ldata,this_lparam;
170 int tot_data=0,tot_param=0;
173 int ldata = rdata ? mem_buf_len(rdata ) : 0;
174 int lparam = rparam ? mem_buf_len(rparam) : 0;
176 BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
178 if (buffer_too_large)
180 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
181 ldata = max_data_ret;
184 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
185 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
187 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
188 /* if you don't want Net Monitor to decode your packets, do this!!! */
189 align = ((this_lparam+1)%4);
191 align = (this_lparam%4);
194 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
196 if (buffer_too_large)
198 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
199 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
200 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
203 copy_trans_params_and_data(outbuf, align,
205 tot_param , tot_data,
206 this_lparam, this_ldata);
208 SSVAL(outbuf,smb_vwv0,lparam);
209 SSVAL(outbuf,smb_vwv1,ldata);
210 SSVAL(outbuf,smb_vwv3,this_lparam);
211 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
212 SSVAL(outbuf,smb_vwv5,0);
213 SSVAL(outbuf,smb_vwv6,this_ldata);
214 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
215 SSVAL(outbuf,smb_vwv8,0);
216 SSVAL(outbuf,smb_vwv9,lsetup);
218 for (i=0;i<lsetup;i++)
220 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
224 send_smb(Client,outbuf);
226 tot_data = this_ldata;
227 tot_param = this_lparam;
229 while (tot_data < ldata || tot_param < lparam)
231 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
232 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
234 align = (this_lparam%4);
236 set_message(outbuf,10,this_ldata+this_lparam+align,False);
238 copy_trans_params_and_data(outbuf, align,
240 tot_param , tot_data,
241 this_lparam, this_ldata);
243 SSVAL(outbuf,smb_vwv3,this_lparam);
244 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
245 SSVAL(outbuf,smb_vwv5,tot_param);
246 SSVAL(outbuf,smb_vwv6,this_ldata);
247 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
248 SSVAL(outbuf,smb_vwv8,tot_data);
249 SSVAL(outbuf,smb_vwv9,0);
252 send_smb(Client,outbuf);
254 tot_data += this_ldata;
255 tot_param += this_lparam;
260 char* format; /* formatstring for structure */
261 char* subformat; /* subformat for structure */
262 char* base; /* baseaddress of buffer */
263 int buflen; /* remaining size for fixed part; on init: length of base */
264 int subcount; /* count of substructures */
265 char* structbuf; /* pointer into buffer for remaining fixed part */
266 int stringlen; /* remaining size for variable part */
267 char* stringbuf; /* pointer into buffer for remaining variable part */
268 int neededlen; /* total needed size */
269 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
270 char* curpos; /* current position; pointer into format or subformat */
274 static int get_counter(char** p)
277 if (!p || !(*p)) return(1);
278 if (!isdigit(**p)) return 1;
282 n = 10 * n + (i - '0');
289 static int getlen(char* p)
295 case 'W': /* word (2 byte) */
298 case 'N': /* count of substructures (word) at end */
301 case 'D': /* double word (4 byte) */
302 case 'z': /* offset to zero terminated string (4 byte) */
303 case 'l': /* offset to user data (4 byte) */
306 case 'b': /* offset to data (with counter) (4 byte) */
310 case 'B': /* byte (with optional counter) */
311 n += get_counter(&p);
318 static BOOL init_package(struct pack_desc* p, int count, int subcount)
323 if (!p->format || !p->base) return(False);
325 i = count * getlen(p->format);
326 if (p->subformat) i += subcount * getlen(p->subformat);
327 p->structbuf = p->base;
331 p->curpos = p->format;
334 p->errcode = NERR_BufTooSmall;
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 = ERROR_MORE_DATA;
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 = NERR_BufTooSmall;
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 strcpy(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 strcpy(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 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
676 /* driver file name */
677 if (ok && !next_token(&p,driver,":")) ok = 0;
679 if (ok && !next_token(&p,datafile,":")) ok = 0;
681 * for the next tokens - which may be empty - I have to check for empty
682 * tokens first because the next_token function will skip all empty
690 } else if (!next_token(&p,helpfile,":")) ok = 0;
694 /* language monitor */
698 } else if (!next_token(&p,langmon,":")) ok = 0;
701 /* default data type */
702 if (ok && !next_token(&p,datatype,":")) ok = 0;
705 PACKI(desc,"W",0x0400); /* don't know */
706 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
707 PACKS(desc,"z",driver); /* Driverfile Name */
708 PACKS(desc,"z",datafile); /* Datafile name */
709 PACKS(desc,"z",langmon); /* language monitor */
710 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
711 PACKS(desc,"z",datatype); /* default data type */
712 PACKS(desc,"z",helpfile); /* helpfile name */
713 PACKS(desc,"z",driver); /* driver name */
714 DEBUG(3,("Driver:%s:\n",driver));
715 DEBUG(3,("Data File:%s:\n",datafile));
716 DEBUG(3,("Language Monitor:%s:\n",langmon));
717 DEBUG(3,("Data Type:%s:\n",datatype));
718 DEBUG(3,("Help File:%s:\n",helpfile));
719 PACKI(desc,"N",count); /* number of files to copy */
720 for (i=0;i<count;i++)
722 /* no need to check return value here - it was already tested in
723 * get_printerdrivernumber
725 next_token(&p,tok,",");
726 PACKS(desc,"z",tok); /* driver files to copy */
727 DEBUG(3,("file:%s:\n",tok));
730 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
731 SERVICE(snum),count));
733 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
734 desc->errcode=NERR_notsupported;
740 /* This function returns the number of files for a given driver */
741 int get_printerdrivernumber(int snum)
749 strcpy(fname,lp_driverfile());
751 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
754 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
758 p=(char *)malloc(8192*sizeof(char));
759 q=p; /* need it to free memory because p change ! */
761 /* lookup the long printer driver name in the file description */
762 while (!feof(f) && !ok)
764 p = q; /* reset string pointer */
766 if (next_token(&p,tok,":") &&
767 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
776 if (*p++ == ':') i--;
781 /* count the number of files */
782 while (next_token(&p,tok,","))
790 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
791 int mdrcnt,int mprcnt,
792 char **rdata,char **rparam,
793 int *rdata_len,int *rparam_len)
795 char *str1 = param+2;
796 char *str2 = skip_string(str1,1);
797 char *p = skip_string(str2,1);
803 struct pack_desc desc;
804 print_queue_struct *queue=NULL;
805 print_status_struct status;
807 bzero(&status,sizeof(status));
808 bzero(&desc,sizeof(desc));
810 p = skip_string(p,1);
815 /* remove any trailing username */
816 if ((p = strchr(QueueName,'%'))) *p = 0;
818 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
820 /* check it's a supported varient */
821 if (!prefix_ok(str1,"zWrLh")) return False;
822 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
824 snum = lp_servicenumber(QueueName);
825 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
826 int pnum = lp_servicenumber(PRINTERS_NAME);
828 lp_add_printer(QueueName,pnum);
829 snum = lp_servicenumber(QueueName);
833 if (snum < 0 || !VALID_SNUM(snum)) return(False);
837 count = get_printerdrivernumber(snum);
838 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
841 count = get_printqueue(snum,cnum,&queue,&status);
843 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
845 desc.buflen = mdrcnt;
846 if (init_package(&desc,1,count)) {
847 desc.subcount = count;
848 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
851 *rdata_len = desc.usedlen;
854 *rparam = REALLOC(*rparam,*rparam_len);
855 SSVALS(*rparam,0,desc.errcode);
857 SSVAL(*rparam,4,desc.neededlen);
859 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
861 if (queue) free(queue);
867 /****************************************************************************
868 view list of all print jobs on all queues
869 ****************************************************************************/
870 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
871 int mdrcnt, int mprcnt,
872 char **rdata, char** rparam,
873 int *rdata_len, int *rparam_len)
875 char *param_format = param+2;
876 char *output_format1 = skip_string(param_format,1);
877 char *p = skip_string(output_format1,1);
878 int uLevel = SVAL(p,0);
879 char *output_format2 = p + 4;
880 int services = lp_numservices();
882 struct pack_desc desc;
883 print_queue_struct **queue = NULL;
884 print_status_struct *status = NULL;
885 int* subcntarr = NULL;
886 int queuecnt, subcnt=0, succnt=0;
888 bzero(&desc,sizeof(desc));
890 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
892 if (!prefix_ok(param_format,"WrLeh")) return False;
893 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
896 for (i = 0; i < services; i++)
897 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
900 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
901 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
902 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
903 memset(status,0,queuecnt*sizeof(print_status_struct));
904 subcntarr = (int*)malloc(queuecnt*sizeof(int));
907 for (i = 0; i < services; i++)
908 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
909 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
910 subcnt += subcntarr[n];
914 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
916 desc.buflen = mdrcnt;
918 if (init_package(&desc,queuecnt,subcnt)) {
921 for (i = 0; i < services; i++)
922 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
923 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
925 if (desc.errcode == NERR_Success) succnt = n;
929 if (subcntarr) free(subcntarr);
931 *rdata_len = desc.usedlen;
933 *rparam = REALLOC(*rparam,*rparam_len);
934 SSVALS(*rparam,0,desc.errcode);
936 SSVAL(*rparam,4,succnt);
937 SSVAL(*rparam,6,queuecnt);
939 for (i = 0; i < queuecnt; i++) {
940 if (queue && queue[i]) free(queue[i]);
943 if (queue) free(queue);
944 if (status) free(status);
949 /****************************************************************************
950 get info level for a server list query
951 ****************************************************************************/
952 static BOOL check_server_info(int uLevel, char* id)
956 if (strcmp(id,"B16") != 0) return False;
959 if (strcmp(id,"B16BBDz") != 0) return False;
967 struct srv_info_struct
977 /*******************************************************************
978 get server info lists from the files saved by nmbd. Return the
980 ******************************************************************/
981 static int get_server_info(uint32 servertype,
982 struct srv_info_struct **servers,
990 BOOL local_list_only;
992 pstrcpy(fname,lp_lockdir());
993 trim_string(fname,NULL,"/");
995 strcat(fname,SERVER_LIST);
997 f = fopen(fname,"r");
1000 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1004 /* request for everything is code for request all servers */
1005 if (servertype == SV_TYPE_ALL)
1006 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1008 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1010 DEBUG(4,("Servertype search: %8x\n",servertype));
1015 struct srv_info_struct *s;
1020 fgets(line,sizeof(line)-1,f);
1021 if (!*line) continue;
1023 if (count == alloced) {
1025 (*servers) = (struct srv_info_struct *)
1026 Realloc(*servers,sizeof(**servers)*alloced);
1027 if (!(*servers)) return(0);
1028 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1030 s = &(*servers)[count];
1032 if (!next_token(&ptr,s->name , NULL)) continue;
1033 if (!next_token(&ptr,stype , NULL)) continue;
1034 if (!next_token(&ptr,s->comment, NULL)) continue;
1035 if (!next_token(&ptr,s->domain , NULL)) {
1036 /* this allows us to cope with an old nmbd */
1037 strcpy(s->domain,myworkgroup);
1040 if (sscanf(stype,"%X",&s->type) != 1) {
1041 DEBUG(4,("r:host file "));
1045 /* Filter the servers/domains we return based on what was asked for. */
1047 /* Check to see if we are being asked for a local list only. */
1048 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1049 DEBUG(4,("r: local list only"));
1053 /* doesn't match up: don't want it */
1054 if (!(servertype & s->type)) {
1055 DEBUG(4,("r:serv type "));
1059 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1060 (s->type & SV_TYPE_DOMAIN_ENUM))
1062 DEBUG(4,("s: dom mismatch "));
1066 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1071 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1072 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1076 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1077 s->name, s->type, s->comment, s->domain));
1079 s->server_added = True;
1084 DEBUG(4,("%20s %8x %25s %15s\n",
1085 s->name, s->type, s->comment, s->domain));
1094 /*******************************************************************
1095 fill in a server info structure
1096 ******************************************************************/
1097 static int fill_srv_info(struct srv_info_struct *service,
1098 int uLevel, char **buf, int *buflen,
1099 char **stringbuf, int *stringspace, char *baseaddr)
1108 case 0: struct_len = 16; break;
1109 case 1: struct_len = 26; break;
1119 len = strlen(service->comment)+1;
1123 if (buflen) *buflen = struct_len;
1124 if (stringspace) *stringspace = len;
1125 return struct_len + len;
1130 if (*buflen < struct_len) return -1;
1138 p2 = p + struct_len;
1139 l2 = *buflen - struct_len;
1141 if (!baseaddr) baseaddr = p;
1146 StrnCpy(p,service->name,15);
1150 StrnCpy(p,service->name,15);
1151 SIVAL(p,18,service->type);
1152 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1153 len += CopyAndAdvance(&p2,service->comment,&l2);
1159 *buf = p + struct_len;
1160 *buflen -= struct_len;
1173 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1175 return(strcmp(s1->name,s2->name));
1178 /****************************************************************************
1179 view list of servers available (or possibly domains). The info is
1180 extracted from lists saved by nmbd on the local host
1181 ****************************************************************************/
1182 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1183 int mdrcnt, int mprcnt, char **rdata,
1184 char **rparam, int *rdata_len, int *rparam_len)
1186 char *str1 = param+2;
1187 char *str2 = skip_string(str1,1);
1188 char *p = skip_string(str2,1);
1189 int uLevel = SVAL(p,0);
1190 int buf_len = SVAL(p,2);
1191 uint32 servertype = IVAL(p,4);
1193 int data_len, fixed_len, string_len;
1194 int f_len = 0, s_len = 0;
1195 struct srv_info_struct *servers=NULL;
1196 int counted=0,total=0;
1199 BOOL domain_request;
1202 /* If someone sets all the bits they don't really mean to set
1203 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1206 if (servertype == SV_TYPE_ALL)
1207 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1209 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1210 any other bit (they may just set this bit on it's own) they
1211 want all the locally seen servers. However this bit can be
1212 set on its own so set the requested servers to be
1213 ALL - DOMAIN_ENUM. */
1215 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1216 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1218 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1219 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1223 if (!prefix_ok(str1,"WrLehD")) return False;
1224 if (!check_server_info(uLevel,str2)) return False;
1226 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1227 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1228 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1230 if (strcmp(str1, "WrLehDz") == 0) {
1231 StrnCpy(domain, p, sizeof(fstring)-1);
1233 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1236 if (lp_browse_list())
1237 total = get_server_info(servertype,&servers,domain);
1239 data_len = fixed_len = string_len = 0;
1242 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1245 char *lastname=NULL;
1247 for (i=0;i<total;i++)
1249 struct srv_info_struct *s = &servers[i];
1250 if (lastname && strequal(lastname,s->name)) continue;
1252 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1253 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1254 s->name, s->type, s->comment, s->domain));
1256 if (data_len <= buf_len) {
1259 string_len += s_len;
1266 *rdata_len = fixed_len + string_len;
1267 *rdata = REALLOC(*rdata,*rdata_len);
1268 bzero(*rdata,*rdata_len);
1270 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1276 char *lastname=NULL;
1277 int count2 = counted;
1278 for (i = 0; i < total && count2;i++)
1280 struct srv_info_struct *s = &servers[i];
1281 if (lastname && strequal(lastname,s->name)) continue;
1283 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1284 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1285 s->name, s->type, s->comment, s->domain));
1291 *rparam = REALLOC(*rparam,*rparam_len);
1292 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1294 SSVAL(*rparam,4,counted);
1295 SSVAL(*rparam,6,counted+missed);
1297 if (servers) free(servers);
1299 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1300 domain,uLevel,counted,counted+missed));
1305 /****************************************************************************
1306 command 0x34 - suspected of being a "Lookup Names" stub api
1307 ****************************************************************************/
1308 static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data,
1309 int mdrcnt, int mprcnt, char **rdata,
1310 char **rparam, int *rdata_len, int *rparam_len)
1312 char *str1 = param+2;
1313 char *str2 = skip_string(str1,1);
1314 char *p = skip_string(str2,1);
1315 int uLevel = SVAL(p,0);
1316 int buf_len = SVAL(p,2);
1320 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1321 str1, str2, p, uLevel, buf_len));
1323 if (!prefix_ok(str1,"zWrLeh")) return False;
1329 *rparam = REALLOC(*rparam,*rparam_len);
1331 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1333 SSVAL(*rparam,4,counted);
1334 SSVAL(*rparam,6,counted+missed);
1339 /****************************************************************************
1340 get info about a share
1341 ****************************************************************************/
1342 static BOOL check_share_info(int uLevel, char* id)
1346 if (strcmp(id,"B13") != 0) return False;
1349 if (strcmp(id,"B13BWz") != 0) return False;
1352 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1355 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1357 default: return False;
1362 static int fill_share_info(int cnum, int snum, int uLevel,
1363 char** buf, int* buflen,
1364 char** stringbuf, int* stringspace, char* baseaddr)
1373 case 0: struct_len = 13; break;
1374 case 1: struct_len = 20; break;
1375 case 2: struct_len = 40; break;
1376 case 91: struct_len = 68; break;
1384 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1385 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1386 if (buflen) *buflen = struct_len;
1387 if (stringspace) *stringspace = len;
1388 return struct_len + len;
1393 if ((*buflen) < struct_len) return -1;
1401 p2 = p + struct_len;
1402 l2 = (*buflen) - struct_len;
1404 if (!baseaddr) baseaddr = p;
1406 StrnCpy(p,lp_servicename(snum),13);
1412 type = STYPE_DISKTREE;
1413 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1414 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1415 SSVAL(p,14,type); /* device type */
1416 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1417 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1422 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1423 SSVALS(p,22,-1); /* max uses */
1424 SSVAL(p,24,1); /* current uses */
1425 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1426 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1427 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1432 memset(p+40,0,SHPWLEN+2);
1444 (*buf) = p + struct_len;
1445 (*buflen) -= struct_len;
1447 (*stringspace) = l2;
1457 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1458 int mdrcnt,int mprcnt,
1459 char **rdata,char **rparam,
1460 int *rdata_len,int *rparam_len)
1462 char *str1 = param+2;
1463 char *str2 = skip_string(str1,1);
1464 char *netname = skip_string(str2,1);
1465 char *p = skip_string(netname,1);
1466 int uLevel = SVAL(p,0);
1467 int snum = find_service(netname);
1469 if (snum < 0) return False;
1471 /* check it's a supported varient */
1472 if (!prefix_ok(str1,"zWrLh")) return False;
1473 if (!check_share_info(uLevel,str2)) return False;
1475 *rdata = REALLOC(*rdata,mdrcnt);
1477 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1478 if (*rdata_len < 0) return False;
1481 *rparam = REALLOC(*rparam,*rparam_len);
1482 SSVAL(*rparam,0,NERR_Success);
1483 SSVAL(*rparam,2,0); /* converter word */
1484 SSVAL(*rparam,4,*rdata_len);
1489 /****************************************************************************
1490 view list of shares available
1491 ****************************************************************************/
1492 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1493 int mdrcnt,int mprcnt,
1494 char **rdata,char **rparam,
1495 int *rdata_len,int *rparam_len)
1497 char *str1 = param+2;
1498 char *str2 = skip_string(str1,1);
1499 char *p = skip_string(str2,1);
1500 int uLevel = SVAL(p,0);
1501 int buf_len = SVAL(p,2);
1503 int count=lp_numservices();
1504 int total=0,counted=0;
1506 int data_len, fixed_len, string_len;
1507 int f_len = 0, s_len = 0;
1509 if (!prefix_ok(str1,"WrLeh")) return False;
1510 if (!check_share_info(uLevel,str2)) return False;
1512 data_len = fixed_len = string_len = 0;
1513 for (i=0;i<count;i++)
1514 if (lp_browseable(i) && lp_snum_ok(i))
1517 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1518 if (data_len <= buf_len)
1522 string_len += s_len;
1525 *rdata_len = fixed_len + string_len;
1526 *rdata = REALLOC(*rdata,*rdata_len);
1527 memset(*rdata,0,*rdata_len);
1529 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1533 for (i = 0; i < count;i++)
1534 if (lp_browseable(i) && lp_snum_ok(i))
1535 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1539 *rparam = REALLOC(*rparam,*rparam_len);
1540 SSVAL(*rparam,0,NERR_Success);
1542 SSVAL(*rparam,4,counted);
1543 SSVAL(*rparam,6,total);
1545 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1546 counted,total,uLevel,
1547 buf_len,*rdata_len,mdrcnt));
1553 /****************************************************************************
1554 get the time of day info
1555 ****************************************************************************/
1556 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1557 int mdrcnt,int mprcnt,
1558 char **rdata,char **rparam,
1559 int *rdata_len,int *rparam_len)
1563 *rparam = REALLOC(*rparam,*rparam_len);
1566 *rdata = REALLOC(*rdata,*rdata_len);
1568 SSVAL(*rparam,0,NERR_Success);
1569 SSVAL(*rparam,2,0); /* converter word */
1575 time_t unixdate = time(NULL);
1577 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1578 by NT in a "net time" operation,
1579 it seems to ignore the one below */
1581 /* the client expects to get localtime, not GMT, in this bit
1582 (I think, this needs testing) */
1583 t = LocalTime(&unixdate);
1585 SIVAL(p,4,0); /* msecs ? */
1586 CVAL(p,8) = t->tm_hour;
1587 CVAL(p,9) = t->tm_min;
1588 CVAL(p,10) = t->tm_sec;
1589 CVAL(p,11) = 0; /* hundredths of seconds */
1590 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1591 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1592 CVAL(p,16) = t->tm_mday;
1593 CVAL(p,17) = t->tm_mon + 1;
1594 SSVAL(p,18,1900+t->tm_year);
1595 CVAL(p,20) = t->tm_wday;
1602 /****************************************************************************
1603 set the user password
1604 ****************************************************************************/
1605 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1606 int mdrcnt,int mprcnt,
1607 char **rdata,char **rparam,
1608 int *rdata_len,int *rparam_len)
1610 char *p = skip_string(param+2,2);
1612 fstring pass1,pass2;
1616 p = skip_string(p,1);
1619 memcpy(pass2,p+16,16);
1622 *rparam = REALLOC(*rparam,*rparam_len);
1626 SSVAL(*rparam,0,NERR_badpass);
1627 SSVAL(*rparam,2,0); /* converter word */
1629 DEBUG(3,("Set password for <%s>\n",user));
1632 * Attempt the plaintext password change first.
1633 * Older versions of Windows seem to do this.
1636 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1637 chgpasswd(user,pass1,pass2))
1639 SSVAL(*rparam,0,NERR_Success);
1643 * If the plaintext change failed, attempt
1644 * the encrypted. NT will generate this
1645 * after trying the samr method.
1648 if(SVAL(*rparam,0) != NERR_Success)
1650 struct smb_passwd *smbpw = NULL;
1652 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &smbpw) &&
1653 change_lanman_password(smbpw,(unsigned char *)pass1,(unsigned char *)pass2))
1655 SSVAL(*rparam,0,NERR_Success);
1659 bzero(pass1,sizeof(fstring));
1660 bzero(pass2,sizeof(fstring));
1665 /****************************************************************************
1666 Set the user password (SamOEM version - gets plaintext).
1667 ****************************************************************************/
1669 static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
1670 int mdrcnt,int mprcnt,
1671 char **rdata,char **rparam,
1672 int *rdata_len,int *rparam_len)
1676 struct smb_passwd *smbpw = NULL;
1677 char *p = param + 2;
1680 *rparam = REALLOC(*rparam,*rparam_len);
1684 SSVAL(*rparam,0,NERR_badpass);
1687 * Check the parameter definition is correct.
1689 if(!strequal(param + 2, "zsT")) {
1690 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1693 p = skip_string(p, 1);
1695 if(!strequal(p, "B516B16")) {
1696 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1699 p = skip_string(p,1);
1702 p = skip_string(p,1);
1704 if(check_oem_password( user, (unsigned char *)data, &smbpw,
1705 new_passwd, (int)sizeof(new_passwd)) == False) {
1710 * At this point we have the new case-sensitive plaintext
1711 * password in the fstring new_passwd. If we wanted to synchronise
1712 * with UNIX passwords we would call a UNIX password changing
1713 * function here. However it would have to be done as root
1714 * as the plaintext of the old users password is not
1718 if(change_oem_password( smbpw, new_passwd)) {
1719 SSVAL(*rparam,0,NERR_Success);
1725 /****************************************************************************
1728 ****************************************************************************/
1729 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1730 int mdrcnt,int mprcnt,
1731 char **rdata,char **rparam,
1732 int *rdata_len,int *rparam_len)
1734 int function = SVAL(param,0);
1735 char *str1 = param+2;
1736 char *str2 = skip_string(str1,1);
1737 char *p = skip_string(str2,1);
1741 printjob_decode(SVAL(p,0), &snum, &jobid);
1743 /* check it's a supported varient */
1744 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1748 *rparam = REALLOC(*rparam,*rparam_len);
1752 SSVAL(*rparam,0,NERR_Success);
1754 if (snum >= 0 && VALID_SNUM(snum))
1756 print_queue_struct *queue=NULL;
1758 count = get_printqueue(snum,cnum,&queue,NULL);
1760 for (i=0;i<count;i++)
1761 if ((queue[i].job&0xFF) == jobid)
1764 case 81: /* delete */
1765 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1766 del_printqueue(cnum,snum,queue[i].job);
1768 case 82: /* pause */
1769 case 83: /* resume */
1770 DEBUG(3,("%s queue entry %d\n",
1771 (function==82?"pausing":"resuming"),queue[i].job));
1772 status_printjob(cnum,snum,queue[i].job,
1773 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1780 SSVAL(*rparam,0,NERR_JobNotFound);
1782 if (queue) free(queue);
1785 SSVAL(*rparam,2,0); /* converter word */
1790 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1791 int mdrcnt,int mprcnt,
1792 char **rdata,char **rparam,
1793 int *rdata_len,int *rparam_len)
1795 char *str1 = param+2;
1796 char *str2 = skip_string(str1,1);
1797 char *QueueName = skip_string(str2,1);
1800 /* check it's a supported varient */
1801 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1805 *rparam = REALLOC(*rparam,*rparam_len);
1809 SSVAL(*rparam,0,NERR_Success);
1810 SSVAL(*rparam,2,0); /* converter word */
1812 snum = lp_servicenumber(QueueName);
1813 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1814 int pnum = lp_servicenumber(PRINTERS_NAME);
1816 lp_add_printer(QueueName,pnum);
1817 snum = lp_servicenumber(QueueName);
1821 if (snum >= 0 && VALID_SNUM(snum)) {
1822 print_queue_struct *queue=NULL;
1826 count = get_printqueue(snum,cnum,&queue,NULL);
1827 for (i = 0; i < count; i++)
1828 del_printqueue(cnum,snum,queue[i].job);
1830 if (queue) free(queue);
1833 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1839 /****************************************************************************
1840 set the property of a print job (undocumented?)
1841 ? function = 0xb -> set name of print job
1842 ? function = 0x6 -> move print job up/down
1843 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1844 or <WWsTP> <WB21BB16B10zWWzDDz>
1845 ****************************************************************************/
1846 static int check_printjob_info(struct pack_desc* desc,
1847 int uLevel, char* id)
1849 desc->subformat = NULL;
1851 case 0: desc->format = "W"; break;
1852 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1853 case 2: desc->format = "WWzWWDDzz"; break;
1854 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1855 default: return False;
1857 if (strcmp(desc->format,id) != 0) return False;
1861 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1862 int mdrcnt,int mprcnt,
1863 char **rdata,char **rparam,
1864 int *rdata_len,int *rparam_len)
1866 struct pack_desc desc;
1867 char *str1 = param+2;
1868 char *str2 = skip_string(str1,1);
1869 char *p = skip_string(str2,1);
1871 int uLevel = SVAL(p,2);
1872 int function = SVAL(p,4); /* what is this ?? */
1876 printjob_decode(SVAL(p,0), &snum, &jobid);
1879 *rparam = REALLOC(*rparam,*rparam_len);
1883 /* check it's a supported varient */
1884 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1888 case 0x6: /* change job place in the queue, data gives the new place */
1889 if (snum >= 0 && VALID_SNUM(snum))
1891 print_queue_struct *queue=NULL;
1895 count = get_printqueue(snum,cnum,&queue,NULL);
1896 for (i=0;i<count;i++) /* find job */
1897 if ((queue[i].job&0xFF) == jobid) break;
1900 desc.errcode=NERR_JobNotFound;
1901 if (queue) free(queue);
1904 desc.errcode=NERR_Success;
1908 int place= SVAL(data,0);
1909 /* we currently have no way of doing this. Can any unix do it? */
1910 if (i < place) /* move down */;
1911 else if (i > place ) /* move up */;
1914 desc.errcode=NERR_notsupported; /* not yet supported */
1915 if (queue) free(queue);
1918 else desc.errcode=NERR_JobNotFound;
1920 case 0xb: /* change print job name, data gives the name */
1921 /* jobid, snum should be zero */
1928 if (issafe(*s)) name[l++] = *s;
1933 DEBUG(3,("Setting print name to %s\n",name));
1937 for (i=0;i<MAX_OPEN_FILES;i++)
1938 if (Files[i].open && Files[i].print_file)
1941 int fcnum = Files[i].cnum;
1945 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1946 !become_service(fcnum,True))
1949 if (sys_rename(Files[i].name,name) == 0)
1950 string_set(&Files[i].name,name);
1954 unbecome_root(True);
1956 desc.errcode=NERR_Success;
1959 default: /* not implemented */
1963 SSVALS(*rparam,0,desc.errcode);
1964 SSVAL(*rparam,2,0); /* converter word */
1970 /****************************************************************************
1971 get info about the server
1972 ****************************************************************************/
1973 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1974 int mdrcnt,int mprcnt,
1975 char **rdata,char **rparam,
1976 int *rdata_len,int *rparam_len)
1978 char *str1 = param+2;
1979 char *str2 = skip_string(str1,1);
1980 char *p = skip_string(str2,1);
1981 int uLevel = SVAL(p,0);
1985 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1987 /* check it's a supported varient */
1988 if (!prefix_ok(str1,"WrLh")) return False;
1991 if (strcmp(str2,"B16") != 0) return False;
1995 if (strcmp(str2,"B16BBDz") != 0) return False;
1999 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2004 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2009 if (strcmp(str2,"DN") != 0) return False;
2013 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2016 default: return False;
2019 *rdata_len = mdrcnt;
2020 *rdata = REALLOC(*rdata,*rdata_len);
2023 p2 = p + struct_len;
2025 StrnCpy(p,local_machine,16);
2031 struct srv_info_struct *servers=NULL;
2034 uint32 servertype= lp_default_server_announce();
2036 pstrcpy(comment,lp_serverstring());
2038 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
2039 for (i=0;i<count;i++)
2040 if (strequal(servers[i].name,local_machine))
2042 servertype = servers[i].type;
2043 pstrcpy(comment,servers[i].comment);
2046 if (servers) free(servers);
2048 SCVAL(p,0,lp_major_announce_version());
2049 SCVAL(p,1,lp_minor_announce_version());
2050 SIVAL(p,2,servertype);
2052 if (mdrcnt == struct_len) {
2055 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2056 standard_sub(cnum,comment);
2057 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2058 p2 = skip_string(p2,1);
2063 return False; /* not yet implemented */
2066 *rdata_len = PTR_DIFF(p2,*rdata);
2069 *rparam = REALLOC(*rparam,*rparam_len);
2070 SSVAL(*rparam,0,NERR_Success);
2071 SSVAL(*rparam,2,0); /* converter word */
2072 SSVAL(*rparam,4,*rdata_len);
2078 /****************************************************************************
2079 get info about the server
2080 ****************************************************************************/
2081 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
2082 int mdrcnt,int mprcnt,
2083 char **rdata,char **rparam,
2084 int *rdata_len,int *rparam_len)
2086 char *str1 = param+2;
2087 char *str2 = skip_string(str1,1);
2088 char *p = skip_string(str2,1);
2090 extern pstring sesssetup_user;
2091 int level = SVAL(p,0);
2093 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2096 *rparam = REALLOC(*rparam,*rparam_len);
2098 /* check it's a supported varient */
2099 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2102 *rdata_len = mdrcnt + 1024;
2103 *rdata = REALLOC(*rdata,*rdata_len);
2105 SSVAL(*rparam,0,NERR_Success);
2106 SSVAL(*rparam,2,0); /* converter word */
2112 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2113 strcpy(p2,local_machine);
2115 p2 = skip_string(p2,1);
2118 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2119 strcpy(p2,sesssetup_user);
2120 p2 = skip_string(p2,1);
2123 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2124 strcpy(p2,myworkgroup);
2126 p2 = skip_string(p2,1);
2129 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2130 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2133 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2134 strcpy(p2,myworkgroup); /* don't know. login domain?? */
2135 p2 = skip_string(p2,1);
2138 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2140 p2 = skip_string(p2,1);
2143 *rdata_len = PTR_DIFF(p2,*rdata);
2145 SSVAL(*rparam,4,*rdata_len);
2150 /****************************************************************************
2151 get info about a user
2153 struct user_info_11 {
2154 char usri11_name[21]; 0-20
2156 char *usri11_comment; 22-25
2157 char *usri11_usr_comment; 26-29
2158 unsigned short usri11_priv; 30-31
2159 unsigned long usri11_auth_flags; 32-35
2160 long usri11_password_age; 36-39
2161 char *usri11_homedir; 40-43
2162 char *usri11_parms; 44-47
2163 long usri11_last_logon; 48-51
2164 long usri11_last_logoff; 52-55
2165 unsigned short usri11_bad_pw_count; 56-57
2166 unsigned short usri11_num_logons; 58-59
2167 char *usri11_logon_server; 60-63
2168 unsigned short usri11_country_code; 64-65
2169 char *usri11_workstations; 66-69
2170 unsigned long usri11_max_storage; 70-73
2171 unsigned short usri11_units_per_week; 74-75
2172 unsigned char *usri11_logon_hours; 76-79
2173 unsigned short usri11_code_page; 80-81
2178 usri11_name specifies the user name for which information is retireved
2180 usri11_pad aligns the next data structure element to a word boundary
2182 usri11_comment is a null terminated ASCII comment
2184 usri11_user_comment is a null terminated ASCII comment about the user
2186 usri11_priv specifies the level of the privilege assigned to the user.
2187 The possible values are:
2189 Name Value Description
2190 USER_PRIV_GUEST 0 Guest privilege
2191 USER_PRIV_USER 1 User privilege
2192 USER_PRV_ADMIN 2 Administrator privilege
2194 usri11_auth_flags specifies the account operator privileges. The
2195 possible values are:
2197 Name Value Description
2198 AF_OP_PRINT 0 Print operator
2201 Leach, Naik [Page 28]
\r\f
2204 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2207 AF_OP_COMM 1 Communications operator
2208 AF_OP_SERVER 2 Server operator
2209 AF_OP_ACCOUNTS 3 Accounts operator
2212 usri11_password_age specifies how many seconds have elapsed since the
2213 password was last changed.
2215 usri11_home_dir points to a null terminated ASCII string that contains
2216 the path name of the user's home directory.
2218 usri11_parms points to a null terminated ASCII string that is set
2219 aside for use by applications.
2221 usri11_last_logon specifies the time when the user last logged on.
2222 This value is stored as the number of seconds elapsed since
2223 00:00:00, January 1, 1970.
2225 usri11_last_logoff specifies the time when the user last logged off.
2226 This value is stored as the number of seconds elapsed since
2227 00:00:00, January 1, 1970. A value of 0 means the last logoff
2230 usri11_bad_pw_count specifies the number of incorrect passwords
2231 entered since the last successful logon.
2233 usri11_log1_num_logons specifies the number of times this user has
2234 logged on. A value of -1 means the number of logons is unknown.
2236 usri11_logon_server points to a null terminated ASCII string that
2237 contains the name of the server to which logon requests are sent.
2238 A null string indicates logon requests should be sent to the
2241 usri11_country_code specifies the country code for the user's language
2244 usri11_workstations points to a null terminated ASCII string that
2245 contains the names of workstations the user may log on from.
2246 There may be up to 8 workstations, with the names separated by
2247 commas. A null strings indicates there are no restrictions.
2249 usri11_max_storage specifies the maximum amount of disk space the user
2250 can occupy. A value of 0xffffffff indicates there are no
2253 usri11_units_per_week specifies the equal number of time units into
2254 which a week is divided. This value must be equal to 168.
2256 usri11_logon_hours points to a 21 byte (168 bits) string that
2257 specifies the time during which the user can log on. Each bit
2258 represents one unique hour in a week. The first bit (bit 0, word
2259 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2263 Leach, Naik [Page 29]
\r\f
2266 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2269 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2270 are no restrictions.
2272 usri11_code_page specifies the code page for the user's language of
2275 All of the pointers in this data structure need to be treated
2276 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2277 to be ignored. The converter word returned in the parameters section
2278 needs to be subtracted from the lower 16 bits to calculate an offset
2279 into the return buffer where this ASCII string resides.
2281 There is no auxiliary data in the response.
2283 ****************************************************************************/
2285 #define usri11_name 0
2286 #define usri11_pad 21
2287 #define usri11_comment 22
2288 #define usri11_usr_comment 26
2289 #define usri11_full_name 30
2290 #define usri11_priv 34
2291 #define usri11_auth_flags 36
2292 #define usri11_password_age 40
2293 #define usri11_homedir 44
2294 #define usri11_parms 48
2295 #define usri11_last_logon 52
2296 #define usri11_last_logoff 56
2297 #define usri11_bad_pw_count 60
2298 #define usri11_num_logons 62
2299 #define usri11_logon_server 64
2300 #define usri11_country_code 68
2301 #define usri11_workstations 70
2302 #define usri11_max_storage 74
2303 #define usri11_units_per_week 78
2304 #define usri11_logon_hours 80
2305 #define usri11_code_page 84
2306 #define usri11_end 86
2308 #define USER_PRIV_GUEST 0
2309 #define USER_PRIV_USER 1
2310 #define USER_PRIV_ADMIN 2
2312 #define AF_OP_PRINT 0
2313 #define AF_OP_COMM 1
2314 #define AF_OP_SERVER 2
2315 #define AF_OP_ACCOUNTS 3
2318 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2319 int mdrcnt,int mprcnt,
2320 char **rdata,char **rparam,
2321 int *rdata_len,int *rparam_len)
2323 char *str1 = param+2;
2324 char *str2 = skip_string(str1,1);
2325 char *UserName = skip_string(str2,1);
2326 char *p = skip_string(UserName,1);
2327 int uLevel = SVAL(p,0);
2330 /* get NIS home of a previously validated user - simeon */
2331 /* With share level security vuid will always be zero.
2332 Don't depend on vuser being non-null !!. JRA */
2333 user_struct *vuser = get_valid_user_struct(vuid);
2335 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2338 *rparam = REALLOC(*rparam,*rparam_len);
2340 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2342 /* check it's a supported variant */
2343 if (strcmp(str1,"zWrLh") != 0) return False;
2346 case 0: p2 = "B21"; break;
2347 case 1: p2 = "B21BB16DWzzWz"; break;
2348 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2349 case 10: p2 = "B21Bzzz"; break;
2350 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2351 default: return False;
2354 if (strcmp(p2,str2) != 0) return False;
2356 *rdata_len = mdrcnt + 1024;
2357 *rdata = REALLOC(*rdata,*rdata_len);
2359 SSVAL(*rparam,0,NERR_Success);
2360 SSVAL(*rparam,2,0); /* converter word */
2363 p2 = p + usri11_end;
2366 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2370 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2375 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2376 strcpy(p2,"Comment");
2377 p2 = skip_string(p2,1);
2379 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2380 strcpy(p2,"UserComment");
2381 p2 = skip_string(p2,1);
2383 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2384 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2385 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2386 p2 = skip_string(p2,1);
2389 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2391 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2392 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2393 SIVALS(p,usri11_password_age,-1); /* password age */
2394 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2395 strcpy(p2, lp_logon_path());
2396 p2 = skip_string(p2,1);
2397 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2399 p2 = skip_string(p2,1);
2400 SIVAL(p,usri11_last_logon,0); /* last logon */
2401 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2402 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2403 SSVALS(p,usri11_num_logons,-1); /* num logons */
2404 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2406 p2 = skip_string(p2,1);
2407 SSVAL(p,usri11_country_code,0); /* country code */
2409 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2411 p2 = skip_string(p2,1);
2413 SIVALS(p,usri11_max_storage,-1); /* max storage */
2414 SSVAL(p,usri11_units_per_week,168); /* units per week */
2415 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2417 /* a simple way to get logon hours at all times. */
2419 SCVAL(p2,21,0); /* fix zero termination */
2420 p2 = skip_string(p2,1);
2422 SSVAL(p,usri11_code_page,0); /* code page */
2424 if (uLevel == 1 || uLevel == 2)
2426 memset(p+22,' ',16); /* password */
2427 SIVALS(p,38,-1); /* password age */
2429 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2430 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2431 strcpy(p2,lp_logon_path());
2432 p2 = skip_string(p2,1);
2433 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2435 SSVAL(p,52,0); /* flags */
2436 SIVAL(p,54,0); /* script_path */
2439 SIVAL(p,60,0); /* auth_flags */
2440 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2441 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2442 p2 = skip_string(p2,1);
2443 SIVAL(p,68,0); /* urs_comment */
2444 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2446 p2 = skip_string(p2,1);
2447 SIVAL(p,76,0); /* workstations */
2448 SIVAL(p,80,0); /* last_logon */
2449 SIVAL(p,84,0); /* last_logoff */
2450 SIVALS(p,88,-1); /* acct_expires */
2451 SIVALS(p,92,-1); /* max_storage */
2452 SSVAL(p,96,168); /* units_per_week */
2453 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2456 SSVALS(p,102,-1); /* bad_pw_count */
2457 SSVALS(p,104,-1); /* num_logons */
2458 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2459 strcpy(p2,"\\\\%L");
2460 standard_sub_basic(p2);
2461 p2 = skip_string(p2,1);
2462 SSVAL(p,110,49); /* country_code */
2463 SSVAL(p,112,860); /* code page */
2467 *rdata_len = PTR_DIFF(p2,*rdata);
2469 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2474 /*******************************************************************
2475 get groups that a user is a member of
2476 ******************************************************************/
2477 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2478 int mdrcnt,int mprcnt,
2479 char **rdata,char **rparam,
2480 int *rdata_len,int *rparam_len)
2482 char *str1 = param+2;
2483 char *str2 = skip_string(str1,1);
2484 char *UserName = skip_string(str2,1);
2485 char *p = skip_string(UserName,1);
2486 int uLevel = SVAL(p,0);
2491 *rparam = REALLOC(*rparam,*rparam_len);
2493 /* check it's a supported varient */
2494 if (strcmp(str1,"zWrLeh") != 0) return False;
2496 case 0: p2 = "B21"; break;
2497 default: return False;
2499 if (strcmp(p2,str2) != 0) return False;
2501 *rdata_len = mdrcnt + 1024;
2502 *rdata = REALLOC(*rdata,*rdata_len);
2504 SSVAL(*rparam,0,NERR_Success);
2505 SSVAL(*rparam,2,0); /* converter word */
2509 /* XXXX we need a real SAM database some day */
2510 strcpy(p,"Users"); p += 21; count++;
2511 strcpy(p,"Domain Users"); p += 21; count++;
2512 strcpy(p,"Guests"); p += 21; count++;
2513 strcpy(p,"Domain Guests"); p += 21; count++;
2515 *rdata_len = PTR_DIFF(p,*rdata);
2517 SSVAL(*rparam,4,count); /* is this right?? */
2518 SSVAL(*rparam,6,count); /* is this right?? */
2524 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2525 int mdrcnt,int mprcnt,
2526 char **rdata,char **rparam,
2527 int *rdata_len,int *rparam_len)
2529 char *str1 = param+2;
2530 char *str2 = skip_string(str1,1);
2531 char *p = skip_string(str2,1);
2533 struct pack_desc desc;
2540 bzero(&desc,sizeof(desc));
2542 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2544 /* check it's a supported varient */
2545 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2546 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2547 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2549 desc.buflen = mdrcnt;
2550 desc.subformat = NULL;
2553 if (init_package(&desc,1,0))
2555 PACKI(&desc,"W",0); /* code */
2556 PACKS(&desc,"B21",name); /* eff. name */
2557 PACKS(&desc,"B",""); /* pad */
2559 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2560 PACKI(&desc,"D",0); /* auth flags XXX */
2561 PACKI(&desc,"W",0); /* num logons */
2562 PACKI(&desc,"W",0); /* bad pw count */
2563 PACKI(&desc,"D",0); /* last logon */
2564 PACKI(&desc,"D",-1); /* last logoff */
2565 PACKI(&desc,"D",-1); /* logoff time */
2566 PACKI(&desc,"D",-1); /* kickoff time */
2567 PACKI(&desc,"D",0); /* password age */
2568 PACKI(&desc,"D",0); /* password can change */
2569 PACKI(&desc,"D",-1); /* password must change */
2572 strcpy(mypath,"\\\\");
2573 strcat(mypath,local_machine);
2575 PACKS(&desc,"z",mypath); /* computer */
2577 PACKS(&desc,"z",myworkgroup);/* domain */
2579 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2580 /* made sure all macros are fully substituted and available */
2581 logon_script = lp_logon_script();
2582 standard_sub( cnum, logon_script );
2583 PACKS(&desc,"z", logon_script); /* script path */
2584 /* End of JHT mods */
2586 PACKI(&desc,"D",0x00000000); /* reserved */
2589 *rdata_len = desc.usedlen;
2591 *rparam = REALLOC(*rparam,*rparam_len);
2592 SSVALS(*rparam,0,desc.errcode);
2594 SSVAL(*rparam,4,desc.neededlen);
2596 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2601 /****************************************************************************
2602 api_WAccessGetUserPerms
2603 ****************************************************************************/
2604 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2605 int mdrcnt,int mprcnt,
2606 char **rdata,char **rparam,
2607 int *rdata_len,int *rparam_len)
2609 char *str1 = param+2;
2610 char *str2 = skip_string(str1,1);
2611 char *user = skip_string(str2,1);
2612 char *resource = skip_string(user,1);
2614 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2616 /* check it's a supported varient */
2617 if (strcmp(str1,"zzh") != 0) return False;
2618 if (strcmp(str2,"") != 0) return False;
2621 *rparam = REALLOC(*rparam,*rparam_len);
2622 SSVALS(*rparam,0,0); /* errorcode */
2623 SSVAL(*rparam,2,0); /* converter word */
2624 SSVAL(*rparam,4,0x7f); /* permission flags */
2629 /****************************************************************************
2630 api_WPrintJobEnumerate
2631 ****************************************************************************/
2632 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2633 int mdrcnt,int mprcnt,
2634 char **rdata,char **rparam,
2635 int *rdata_len,int *rparam_len)
2637 char *str1 = param+2;
2638 char *str2 = skip_string(str1,1);
2639 char *p = skip_string(str2,1);
2645 struct pack_desc desc;
2646 print_queue_struct *queue=NULL;
2647 print_status_struct status;
2652 bzero(&desc,sizeof(desc));
2653 bzero(&status,sizeof(status));
2655 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2657 /* check it's a supported varient */
2658 if (strcmp(str1,"WWrLh") != 0) return False;
2659 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2661 printjob_decode(SVAL(p,0), &snum, &job);
2663 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2665 count = get_printqueue(snum,cnum,&queue,&status);
2666 for (i = 0; i < count; i++) {
2667 if ((queue[i].job & 0xFF) == job) break;
2669 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2671 desc.buflen = mdrcnt;
2673 if (init_package(&desc,1,0)) {
2675 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2676 *rdata_len = desc.usedlen;
2679 desc.errcode = NERR_JobNotFound;
2685 *rparam = REALLOC(*rparam,*rparam_len);
2686 SSVALS(*rparam,0,desc.errcode);
2688 SSVAL(*rparam,4,desc.neededlen);
2690 if (queue) free(queue);
2692 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2696 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2697 int mdrcnt,int mprcnt,
2698 char **rdata,char **rparam,
2699 int *rdata_len,int *rparam_len)
2701 char *str1 = param+2;
2702 char *str2 = skip_string(str1,1);
2703 char *p = skip_string(str2,1);
2709 struct pack_desc desc;
2710 print_queue_struct *queue=NULL;
2711 print_status_struct status;
2713 bzero(&desc,sizeof(desc));
2714 bzero(&status,sizeof(status));
2716 p = skip_string(p,1);
2720 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2722 /* check it's a supported varient */
2723 if (strcmp(str1,"zWrLeh") != 0) return False;
2724 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2725 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2727 snum = lp_servicenumber(name);
2728 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2729 int pnum = lp_servicenumber(PRINTERS_NAME);
2731 lp_add_printer(name,pnum);
2732 snum = lp_servicenumber(name);
2736 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2738 count = get_printqueue(snum,cnum,&queue,&status);
2739 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2741 desc.buflen = mdrcnt;
2743 if (init_package(&desc,count,0)) {
2745 for (i = 0; i < count; i++) {
2746 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2747 if (desc.errcode == NERR_Success) succnt = i+1;
2751 *rdata_len = desc.usedlen;
2754 *rparam = REALLOC(*rparam,*rparam_len);
2755 SSVALS(*rparam,0,desc.errcode);
2757 SSVAL(*rparam,4,succnt);
2758 SSVAL(*rparam,6,count);
2760 if (queue) free(queue);
2762 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2766 static int check_printdest_info(struct pack_desc* desc,
2767 int uLevel, char* id)
2769 desc->subformat = NULL;
2771 case 0: desc->format = "B9"; break;
2772 case 1: desc->format = "B9B21WWzW"; break;
2773 case 2: desc->format = "z"; break;
2774 case 3: desc->format = "zzzWWzzzWW"; break;
2775 default: return False;
2777 if (strcmp(desc->format,id) != 0) return False;
2781 static void fill_printdest_info(int cnum, int snum, int uLevel,
2782 struct pack_desc* desc)
2785 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2786 buf[sizeof(buf)-1] = 0;
2789 PACKS(desc,"B9",buf); /* szName */
2791 PACKS(desc,"B21",""); /* szUserName */
2792 PACKI(desc,"W",0); /* uJobId */
2793 PACKI(desc,"W",0); /* fsStatus */
2794 PACKS(desc,"z",""); /* pszStatus */
2795 PACKI(desc,"W",0); /* time */
2798 if (uLevel == 2 || uLevel == 3) {
2799 PACKS(desc,"z",buf); /* pszPrinterName */
2801 PACKS(desc,"z",""); /* pszUserName */
2802 PACKS(desc,"z",""); /* pszLogAddr */
2803 PACKI(desc,"W",0); /* uJobId */
2804 PACKI(desc,"W",0); /* fsStatus */
2805 PACKS(desc,"z",""); /* pszStatus */
2806 PACKS(desc,"z",""); /* pszComment */
2807 PACKS(desc,"z","NULL"); /* pszDrivers */
2808 PACKI(desc,"W",0); /* time */
2809 PACKI(desc,"W",0); /* pad1 */
2814 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2815 int mdrcnt,int mprcnt,
2816 char **rdata,char **rparam,
2817 int *rdata_len,int *rparam_len)
2819 char *str1 = param+2;
2820 char *str2 = skip_string(str1,1);
2821 char *p = skip_string(str2,1);
2822 char* PrinterName = p;
2824 struct pack_desc desc;
2827 bzero(&desc,sizeof(desc));
2829 p = skip_string(p,1);
2833 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2835 /* check it's a supported varient */
2836 if (strcmp(str1,"zWrLh") != 0) return False;
2837 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2839 snum = lp_servicenumber(PrinterName);
2840 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2841 int pnum = lp_servicenumber(PRINTERS_NAME);
2843 lp_add_printer(PrinterName,pnum);
2844 snum = lp_servicenumber(PrinterName);
2850 desc.errcode = NERR_DestNotFound;
2854 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2856 desc.buflen = mdrcnt;
2857 if (init_package(&desc,1,0)) {
2858 fill_printdest_info(cnum,snum,uLevel,&desc);
2860 *rdata_len = desc.usedlen;
2864 *rparam = REALLOC(*rparam,*rparam_len);
2865 SSVALS(*rparam,0,desc.errcode);
2867 SSVAL(*rparam,4,desc.neededlen);
2869 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2873 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2874 int mdrcnt,int mprcnt,
2875 char **rdata,char **rparam,
2876 int *rdata_len,int *rparam_len)
2878 char *str1 = param+2;
2879 char *str2 = skip_string(str1,1);
2880 char *p = skip_string(str2,1);
2884 struct pack_desc desc;
2885 int services = lp_numservices();
2887 bzero(&desc,sizeof(desc));
2892 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2894 /* check it's a supported varient */
2895 if (strcmp(str1,"WrLeh") != 0) return False;
2896 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2899 for (i = 0; i < services; i++)
2900 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2903 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2905 desc.buflen = mdrcnt;
2906 if (init_package(&desc,queuecnt,0)) {
2909 for (i = 0; i < services; i++) {
2910 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2911 fill_printdest_info(cnum,i,uLevel,&desc);
2913 if (desc.errcode == NERR_Success) succnt = n;
2918 *rdata_len = desc.usedlen;
2921 *rparam = REALLOC(*rparam,*rparam_len);
2922 SSVALS(*rparam,0,desc.errcode);
2924 SSVAL(*rparam,4,succnt);
2925 SSVAL(*rparam,6,queuecnt);
2927 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2931 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2932 int mdrcnt,int mprcnt,
2933 char **rdata,char **rparam,
2934 int *rdata_len,int *rparam_len)
2936 char *str1 = param+2;
2937 char *str2 = skip_string(str1,1);
2938 char *p = skip_string(str2,1);
2941 struct pack_desc desc;
2943 bzero(&desc,sizeof(desc));
2948 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2950 /* check it's a supported varient */
2951 if (strcmp(str1,"WrLeh") != 0) return False;
2952 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2954 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2956 desc.buflen = mdrcnt;
2957 if (init_package(&desc,1,0)) {
2958 PACKS(&desc,"B41","NULL");
2961 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2963 *rdata_len = desc.usedlen;
2966 *rparam = REALLOC(*rparam,*rparam_len);
2967 SSVALS(*rparam,0,desc.errcode);
2969 SSVAL(*rparam,4,succnt);
2972 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2976 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2977 int mdrcnt,int mprcnt,
2978 char **rdata,char **rparam,
2979 int *rdata_len,int *rparam_len)
2981 char *str1 = param+2;
2982 char *str2 = skip_string(str1,1);
2983 char *p = skip_string(str2,1);
2986 struct pack_desc desc;
2988 bzero(&desc,sizeof(desc));
2993 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2995 /* check it's a supported varient */
2996 if (strcmp(str1,"WrLeh") != 0) return False;
2997 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2999 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3001 desc.buflen = mdrcnt;
3003 if (init_package(&desc,1,0)) {
3004 PACKS(&desc,"B13","lpd");
3007 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3009 *rdata_len = desc.usedlen;
3012 *rparam = REALLOC(*rparam,*rparam_len);
3013 SSVALS(*rparam,0,desc.errcode);
3015 SSVAL(*rparam,4,succnt);
3018 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3022 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
3023 int mdrcnt,int mprcnt,
3024 char **rdata,char **rparam,
3025 int *rdata_len,int *rparam_len)
3027 char *str1 = param+2;
3028 char *str2 = skip_string(str1,1);
3029 char *p = skip_string(str2,1);
3032 struct pack_desc desc;
3034 bzero(&desc,sizeof(desc));
3039 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3041 /* check it's a supported varient */
3042 if (strcmp(str1,"WrLeh") != 0) return False;
3043 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3045 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3046 bzero(&desc,sizeof(desc));
3048 desc.buflen = mdrcnt;
3050 if (init_package(&desc,1,0)) {
3051 PACKS(&desc,"B13","lp0");
3054 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3056 *rdata_len = desc.usedlen;
3059 *rparam = REALLOC(*rparam,*rparam_len);
3060 SSVALS(*rparam,0,desc.errcode);
3062 SSVAL(*rparam,4,succnt);
3065 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3071 char * pipe_clnt_name;
3072 char * pipe_srv_name;
3073 BOOL (*fn) (pipes_struct *, prs_struct *);
3076 static struct api_cmd api_fd_commands[] =
3078 { "lsarpc", "lsass", api_ntlsa_rpc },
3079 { "samr", "lsass", api_samr_rpc },
3080 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3081 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3082 { "NETLOGON", "lsass", api_netlog_rpc },
3083 { "winreg", "winreg", api_reg_rpc },
3084 { NULL, NULL, NULL }
3087 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3089 BOOL ntlmssp_auth = False;
3090 fstring ack_pipe_name;
3093 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3095 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3097 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3098 api_fd_commands[i].fn != NULL)
3100 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3101 api_fd_commands[i].pipe_clnt_name,
3102 api_fd_commands[i].pipe_srv_name));
3103 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3108 if (api_fd_commands[i].fn == NULL) return False;
3110 /* decode the bind request */
3111 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3113 if (pd->offset == 0) return False;
3115 if (p->hdr.auth_len != 0)
3117 /* decode the authentication verifier */
3118 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3120 if (pd->offset == 0) return False;
3122 /* ignore the version number for now */
3123 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3126 /* name has to be \PIPE\xxxxx */
3127 strcpy(ack_pipe_name, "\\PIPE\\");
3128 strcat(ack_pipe_name, p->pipe_srv_name);
3130 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3132 prs_init(&(p->rdata), 1024, 4, 0, False);
3133 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3134 prs_init(&(p->rauth), 1024, 4, 0, False);
3137 /*** do the bind ack first ***/
3140 make_rpc_hdr_ba(&p->hdr_ba,
3141 p->hdr_rb.bba.max_tsize,
3142 p->hdr_rb.bba.max_rsize,
3143 p->hdr_rb.bba.assoc_gid,
3146 &(p->hdr_rb.transfer));
3148 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3149 mem_realloc_data(p->rdata.data, p->rdata.offset);
3152 /*** now the authentication ***/
3158 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3160 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3163 0x00000000, 0x0000b2b3, 0x000082b1,
3165 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3166 mem_realloc_data(p->rauth.data, p->rauth.offset);
3170 /*** then do the header, now we know the length ***/
3173 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3175 p->rdata.offset + p->rauth.offset,
3178 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3179 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3182 /*** link rpc header, bind acknowledgment and authentication responses ***/
3185 p->rhdr.data->offset.start = 0;
3186 p->rhdr.data->offset.end = p->rhdr.offset;
3187 p->rhdr.data->next = p->rdata.data;
3191 p->rdata.data->offset.start = p->rhdr.offset;
3192 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3193 p->rdata.data->next = p->rauth.data;
3195 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3196 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3197 p->rauth.data->next = NULL;
3201 p->rdata.data->offset.start = p->rhdr.offset;
3202 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3203 p->rdata.data->next = NULL;
3209 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3213 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3215 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3216 api_fd_commands[i].fn != NULL)
3218 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3219 return api_fd_commands[i].fn(p, pd);
3225 static BOOL api_dce_rpc_command(char *outbuf,
3230 if (pd->data == NULL) return False;
3232 /* process the rpc header */
3233 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3235 if (pd->offset == 0) return False;
3237 switch (p->hdr.pkt_type)
3241 reply = api_pipe_bind_req(p, pd);
3246 reply = api_pipe_request (p, pd);
3253 /* now send the reply */
3254 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len);
3256 if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len)
3258 /* all of data was sent: no need to wait for SMBreadX calls */
3259 mem_free_data(p->rhdr .data);
3260 mem_free_data(p->rdata.data);
3267 /****************************************************************************
3268 SetNamedPipeHandleState
3269 ****************************************************************************/
3270 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3274 if (!param) return False;
3276 id = param[0] + (param[1] << 8);
3277 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3279 if (set_rpc_pipe_hnd_state(p, id))
3281 /* now send the reply */
3282 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len);
3290 /****************************************************************************
3291 when no reply is generated, indicate unsupported.
3292 ****************************************************************************/
3293 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3295 struct mem_buf rparam;
3297 mem_init(&rparam, 0);
3298 mem_alloc_data(&rparam, 4);
3300 rparam.offset.start = 0;
3301 rparam.offset.end = 4;
3304 SSVAL(rparam.data,0,NERR_notsupported);
3305 SSVAL(rparam.data,2,0); /* converter word */
3307 DEBUG(3,("Unsupported API fd command\n"));
3309 /* now send the reply */
3310 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3312 mem_free_data(&rparam);
3317 /****************************************************************************
3318 handle remote api calls delivered to a named pipe already opened.
3319 ****************************************************************************/
3320 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3321 uint16 *setup,char *data,char *params,
3322 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3328 pipes_struct *p = NULL;
3330 struct mem_buf data_buf;
3332 DEBUG(5,("api_fd_reply\n"));
3334 /* fake up a data buffer from the api_fd_reply data parameters */
3335 mem_create(&data_buf, data, tdscnt, 0, False);
3336 data_buf.offset.start = 0;
3337 data_buf.offset.end = tdscnt;
3339 /* fake up a parsing structure */
3340 pd.data = &data_buf;
3345 /* First find out the name of this file. */
3348 DEBUG(0,("Unexpected named pipe transaction.\n"));
3352 /* Get the file handle and hence the file name. */
3354 subcommand = setup[0];
3355 get_rpc_pipe(pnum, &p);
3359 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3360 subcommand, p->name, pnum));
3361 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3362 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3364 /* record maximum data length that can be transmitted in an SMBtrans */
3365 p->max_rdata_len = mdrcnt;
3371 /* dce/rpc command */
3372 reply = api_dce_rpc_command(outbuf, p, &pd);
3377 /* Set Named Pipe Handle state */
3378 reply = api_SNPHS(outbuf, p, params);
3385 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3390 return api_no_reply(outbuf, mdrcnt);
3395 /****************************************************************************
3396 the buffer was too small
3397 ****************************************************************************/
3398 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3399 int mdrcnt,int mprcnt,
3400 char **rdata,char **rparam,
3401 int *rdata_len,int *rparam_len)
3403 *rparam_len = MIN(*rparam_len,mprcnt);
3404 *rparam = REALLOC(*rparam,*rparam_len);
3408 SSVAL(*rparam,0,NERR_BufTooSmall);
3410 DEBUG(3,("Supplied buffer too small in API command\n"));
3416 /****************************************************************************
3417 the request is not supported
3418 ****************************************************************************/
3419 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3420 int mdrcnt,int mprcnt,
3421 char **rdata,char **rparam,
3422 int *rdata_len,int *rparam_len)
3425 *rparam = REALLOC(*rparam,*rparam_len);
3429 SSVAL(*rparam,0,NERR_notsupported);
3430 SSVAL(*rparam,2,0); /* converter word */
3432 DEBUG(3,("Unsupported API command\n"));
3446 } api_commands[] = {
3447 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
3448 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
3449 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
3450 {"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0},
3451 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
3452 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
3453 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
3454 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
3455 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
3456 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
3457 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
3458 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
3459 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
3460 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
3461 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
3462 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
3463 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
3464 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
3465 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
3466 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
3467 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
3468 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
3469 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
3470 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
3471 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
3472 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
3473 {"SamOEMChangePassword", 214, (BOOL (*)())api_SamOEMChangePassword,0},
3474 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
3477 /****************************************************************************
3478 handle remote api calls
3479 ****************************************************************************/
3480 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3481 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3483 int api_command = SVAL(params,0);
3484 struct mem_buf rdata_buf;
3485 struct mem_buf rparam_buf;
3487 char *rparam = NULL;
3493 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3494 api_command,params+2,skip_string(params+2,1),
3495 tdscnt,tpscnt,mdrcnt,mprcnt));
3497 for (i=0;api_commands[i].name;i++)
3498 if (api_commands[i].id == api_command && api_commands[i].fn)
3500 DEBUG(3,("Doing %s\n",api_commands[i].name));
3504 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3505 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3507 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3508 &rdata,&rparam,&rdata_len,&rparam_len);
3511 if (rdata_len > mdrcnt ||
3512 rparam_len > mprcnt)
3514 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3515 &rdata,&rparam,&rdata_len,&rparam_len);
3519 /* if we get False back then it's actually unsupported */
3521 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3522 &rdata,&rparam,&rdata_len,&rparam_len);
3525 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3526 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3528 rdata_buf.offset.start = 0;
3529 rdata_buf.offset.end = rdata_len;
3531 rparam_buf.offset.start = 0;
3532 rparam_buf.offset.end = rparam_len;
3534 /* now send the reply */
3535 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3537 if (rdata ) free(rdata);
3538 if (rparam) free(rparam);
3543 /****************************************************************************
3544 handle named pipe commands
3545 ****************************************************************************/
3546 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3547 uint16 *setup,char *data,char *params,
3548 int suwcnt,int tdscnt,int tpscnt,
3549 int msrcnt,int mdrcnt,int mprcnt)
3551 DEBUG(3,("named pipe command on <%s> name\n", name));
3553 if (strequal(name,"LANMAN"))
3555 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3558 if (strlen(name) < 1)
3560 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3565 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3572 /****************************************************************************
3574 ****************************************************************************/
3575 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3579 char *data=NULL,*params=NULL;
3583 int cnum = SVAL(inbuf,smb_tid);
3584 uint16 vuid = SVAL(inbuf,smb_uid);
3586 int tpscnt = SVAL(inbuf,smb_vwv0);
3587 int tdscnt = SVAL(inbuf,smb_vwv1);
3588 int mprcnt = SVAL(inbuf,smb_vwv2);
3589 int mdrcnt = SVAL(inbuf,smb_vwv3);
3590 int msrcnt = CVAL(inbuf,smb_vwv4);
3591 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3592 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3593 int pscnt = SVAL(inbuf,smb_vwv9);
3594 int psoff = SVAL(inbuf,smb_vwv10);
3595 int dscnt = SVAL(inbuf,smb_vwv11);
3596 int dsoff = SVAL(inbuf,smb_vwv12);
3597 int suwcnt = CVAL(inbuf,smb_vwv13);
3599 bzero(name, sizeof(name));
3600 fstrcpy(name,smb_buf(inbuf));
3602 if (dscnt > tdscnt || pscnt > tpscnt) {
3603 exit_server("invalid trans parameters\n");
3608 data = (char *)malloc(tdscnt);
3609 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3613 params = (char *)malloc(tpscnt);
3614 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3620 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3621 for (i=0;i<suwcnt;i++)
3622 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3626 if (pscnt < tpscnt || dscnt < tdscnt)
3628 /* We need to send an interim response then receive the rest
3629 of the parameter/data bytes */
3630 outsize = set_message(outbuf,0,0,True);
3632 send_smb(Client,outbuf);
3635 /* receive the rest of the trans packet */
3636 while (pscnt < tpscnt || dscnt < tdscnt)
3639 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3641 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3643 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3646 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3648 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3649 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3650 if (params) free(params);
3651 if (data) free(data);
3652 if (setup) free(setup);
3653 return(ERROR(ERRSRV,ERRerror));
3658 tpscnt = SVAL(inbuf,smb_vwv0);
3659 tdscnt = SVAL(inbuf,smb_vwv1);
3661 pcnt = SVAL(inbuf,smb_vwv2);
3662 poff = SVAL(inbuf,smb_vwv3);
3663 pdisp = SVAL(inbuf,smb_vwv4);
3665 dcnt = SVAL(inbuf,smb_vwv5);
3666 doff = SVAL(inbuf,smb_vwv6);
3667 ddisp = SVAL(inbuf,smb_vwv7);
3672 if (dscnt > tdscnt || pscnt > tpscnt) {
3673 exit_server("invalid trans parameters\n");
3677 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3679 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3683 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3685 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3687 DEBUG(5,("calling named_pipe\n"));
3688 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3689 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3693 DEBUG(3,("invalid pipe name\n"));
3698 if (data) free(data);
3699 if (params) free(params);
3700 if (setup) free(setup);
3702 if (close_on_completion)
3703 close_cnum(cnum,vuid);
3709 return(ERROR(ERRSRV,ERRnosupport));