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 = ERROR_MORE_DATA;
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,False))
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(lp_unix_password_sync())
1719 chgpasswd(user,"", new_passwd, True);
1721 if(change_oem_password( smbpw, new_passwd)) {
1722 SSVAL(*rparam,0,NERR_Success);
1728 /****************************************************************************
1731 ****************************************************************************/
1732 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1733 int mdrcnt,int mprcnt,
1734 char **rdata,char **rparam,
1735 int *rdata_len,int *rparam_len)
1737 int function = SVAL(param,0);
1738 char *str1 = param+2;
1739 char *str2 = skip_string(str1,1);
1740 char *p = skip_string(str2,1);
1744 printjob_decode(SVAL(p,0), &snum, &jobid);
1746 /* check it's a supported varient */
1747 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1751 *rparam = REALLOC(*rparam,*rparam_len);
1755 SSVAL(*rparam,0,NERR_Success);
1757 if (snum >= 0 && VALID_SNUM(snum))
1759 print_queue_struct *queue=NULL;
1761 count = get_printqueue(snum,cnum,&queue,NULL);
1763 for (i=0;i<count;i++)
1764 if ((queue[i].job&0xFF) == jobid)
1767 case 81: /* delete */
1768 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1769 del_printqueue(cnum,snum,queue[i].job);
1771 case 82: /* pause */
1772 case 83: /* resume */
1773 DEBUG(3,("%s queue entry %d\n",
1774 (function==82?"pausing":"resuming"),queue[i].job));
1775 status_printjob(cnum,snum,queue[i].job,
1776 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1783 SSVAL(*rparam,0,NERR_JobNotFound);
1785 if (queue) free(queue);
1788 SSVAL(*rparam,2,0); /* converter word */
1793 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1794 int mdrcnt,int mprcnt,
1795 char **rdata,char **rparam,
1796 int *rdata_len,int *rparam_len)
1798 char *str1 = param+2;
1799 char *str2 = skip_string(str1,1);
1800 char *QueueName = skip_string(str2,1);
1803 /* check it's a supported varient */
1804 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1808 *rparam = REALLOC(*rparam,*rparam_len);
1812 SSVAL(*rparam,0,NERR_Success);
1813 SSVAL(*rparam,2,0); /* converter word */
1815 snum = lp_servicenumber(QueueName);
1816 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1817 int pnum = lp_servicenumber(PRINTERS_NAME);
1819 lp_add_printer(QueueName,pnum);
1820 snum = lp_servicenumber(QueueName);
1824 if (snum >= 0 && VALID_SNUM(snum)) {
1825 print_queue_struct *queue=NULL;
1829 count = get_printqueue(snum,cnum,&queue,NULL);
1830 for (i = 0; i < count; i++)
1831 del_printqueue(cnum,snum,queue[i].job);
1833 if (queue) free(queue);
1836 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1842 /****************************************************************************
1843 set the property of a print job (undocumented?)
1844 ? function = 0xb -> set name of print job
1845 ? function = 0x6 -> move print job up/down
1846 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1847 or <WWsTP> <WB21BB16B10zWWzDDz>
1848 ****************************************************************************/
1849 static int check_printjob_info(struct pack_desc* desc,
1850 int uLevel, char* id)
1852 desc->subformat = NULL;
1854 case 0: desc->format = "W"; break;
1855 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1856 case 2: desc->format = "WWzWWDDzz"; break;
1857 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1858 default: return False;
1860 if (strcmp(desc->format,id) != 0) return False;
1864 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1865 int mdrcnt,int mprcnt,
1866 char **rdata,char **rparam,
1867 int *rdata_len,int *rparam_len)
1869 struct pack_desc desc;
1870 char *str1 = param+2;
1871 char *str2 = skip_string(str1,1);
1872 char *p = skip_string(str2,1);
1874 int uLevel = SVAL(p,2);
1875 int function = SVAL(p,4); /* what is this ?? */
1879 printjob_decode(SVAL(p,0), &snum, &jobid);
1882 *rparam = REALLOC(*rparam,*rparam_len);
1886 /* check it's a supported varient */
1887 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1891 case 0x6: /* change job place in the queue, data gives the new place */
1892 if (snum >= 0 && VALID_SNUM(snum))
1894 print_queue_struct *queue=NULL;
1898 count = get_printqueue(snum,cnum,&queue,NULL);
1899 for (i=0;i<count;i++) /* find job */
1900 if ((queue[i].job&0xFF) == jobid) break;
1903 desc.errcode=NERR_JobNotFound;
1904 if (queue) free(queue);
1907 desc.errcode=NERR_Success;
1911 int place= SVAL(data,0);
1912 /* we currently have no way of doing this. Can any unix do it? */
1913 if (i < place) /* move down */;
1914 else if (i > place ) /* move up */;
1917 desc.errcode=NERR_notsupported; /* not yet supported */
1918 if (queue) free(queue);
1921 else desc.errcode=NERR_JobNotFound;
1923 case 0xb: /* change print job name, data gives the name */
1924 /* jobid, snum should be zero */
1931 if (issafe(*s)) name[l++] = *s;
1936 DEBUG(3,("Setting print name to %s\n",name));
1940 for (i=0;i<MAX_OPEN_FILES;i++)
1941 if (Files[i].open && Files[i].print_file)
1944 int fcnum = Files[i].cnum;
1948 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1949 !become_service(fcnum,True))
1952 if (sys_rename(Files[i].name,name) == 0)
1953 string_set(&Files[i].name,name);
1957 unbecome_root(True);
1959 desc.errcode=NERR_Success;
1962 default: /* not implemented */
1966 SSVALS(*rparam,0,desc.errcode);
1967 SSVAL(*rparam,2,0); /* converter word */
1973 /****************************************************************************
1974 get info about the server
1975 ****************************************************************************/
1976 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1977 int mdrcnt,int mprcnt,
1978 char **rdata,char **rparam,
1979 int *rdata_len,int *rparam_len)
1981 char *str1 = param+2;
1982 char *str2 = skip_string(str1,1);
1983 char *p = skip_string(str2,1);
1984 int uLevel = SVAL(p,0);
1988 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1990 /* check it's a supported varient */
1991 if (!prefix_ok(str1,"WrLh")) return False;
1994 if (strcmp(str2,"B16") != 0) return False;
1998 if (strcmp(str2,"B16BBDz") != 0) return False;
2002 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2007 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2012 if (strcmp(str2,"DN") != 0) return False;
2016 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2019 default: return False;
2022 *rdata_len = mdrcnt;
2023 *rdata = REALLOC(*rdata,*rdata_len);
2026 p2 = p + struct_len;
2028 StrnCpy(p,local_machine,16);
2034 struct srv_info_struct *servers=NULL;
2037 uint32 servertype= lp_default_server_announce();
2039 pstrcpy(comment,lp_serverstring());
2041 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
2042 for (i=0;i<count;i++)
2043 if (strequal(servers[i].name,local_machine))
2045 servertype = servers[i].type;
2046 pstrcpy(comment,servers[i].comment);
2049 if (servers) free(servers);
2051 SCVAL(p,0,lp_major_announce_version());
2052 SCVAL(p,1,lp_minor_announce_version());
2053 SIVAL(p,2,servertype);
2055 if (mdrcnt == struct_len) {
2058 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2059 standard_sub(cnum,comment);
2060 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2061 p2 = skip_string(p2,1);
2066 return False; /* not yet implemented */
2069 *rdata_len = PTR_DIFF(p2,*rdata);
2072 *rparam = REALLOC(*rparam,*rparam_len);
2073 SSVAL(*rparam,0,NERR_Success);
2074 SSVAL(*rparam,2,0); /* converter word */
2075 SSVAL(*rparam,4,*rdata_len);
2081 /****************************************************************************
2082 get info about the server
2083 ****************************************************************************/
2084 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
2085 int mdrcnt,int mprcnt,
2086 char **rdata,char **rparam,
2087 int *rdata_len,int *rparam_len)
2089 char *str1 = param+2;
2090 char *str2 = skip_string(str1,1);
2091 char *p = skip_string(str2,1);
2093 extern pstring sesssetup_user;
2094 int level = SVAL(p,0);
2096 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2099 *rparam = REALLOC(*rparam,*rparam_len);
2101 /* check it's a supported varient */
2102 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2105 *rdata_len = mdrcnt + 1024;
2106 *rdata = REALLOC(*rdata,*rdata_len);
2108 SSVAL(*rparam,0,NERR_Success);
2109 SSVAL(*rparam,2,0); /* converter word */
2115 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2116 strcpy(p2,local_machine);
2118 p2 = skip_string(p2,1);
2121 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2122 strcpy(p2,sesssetup_user);
2123 p2 = skip_string(p2,1);
2126 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2127 strcpy(p2,myworkgroup);
2129 p2 = skip_string(p2,1);
2132 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2133 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2136 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2137 strcpy(p2,myworkgroup); /* don't know. login domain?? */
2138 p2 = skip_string(p2,1);
2141 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2143 p2 = skip_string(p2,1);
2146 *rdata_len = PTR_DIFF(p2,*rdata);
2148 SSVAL(*rparam,4,*rdata_len);
2153 /****************************************************************************
2154 get info about a user
2156 struct user_info_11 {
2157 char usri11_name[21]; 0-20
2159 char *usri11_comment; 22-25
2160 char *usri11_usr_comment; 26-29
2161 unsigned short usri11_priv; 30-31
2162 unsigned long usri11_auth_flags; 32-35
2163 long usri11_password_age; 36-39
2164 char *usri11_homedir; 40-43
2165 char *usri11_parms; 44-47
2166 long usri11_last_logon; 48-51
2167 long usri11_last_logoff; 52-55
2168 unsigned short usri11_bad_pw_count; 56-57
2169 unsigned short usri11_num_logons; 58-59
2170 char *usri11_logon_server; 60-63
2171 unsigned short usri11_country_code; 64-65
2172 char *usri11_workstations; 66-69
2173 unsigned long usri11_max_storage; 70-73
2174 unsigned short usri11_units_per_week; 74-75
2175 unsigned char *usri11_logon_hours; 76-79
2176 unsigned short usri11_code_page; 80-81
2181 usri11_name specifies the user name for which information is retireved
2183 usri11_pad aligns the next data structure element to a word boundary
2185 usri11_comment is a null terminated ASCII comment
2187 usri11_user_comment is a null terminated ASCII comment about the user
2189 usri11_priv specifies the level of the privilege assigned to the user.
2190 The possible values are:
2192 Name Value Description
2193 USER_PRIV_GUEST 0 Guest privilege
2194 USER_PRIV_USER 1 User privilege
2195 USER_PRV_ADMIN 2 Administrator privilege
2197 usri11_auth_flags specifies the account operator privileges. The
2198 possible values are:
2200 Name Value Description
2201 AF_OP_PRINT 0 Print operator
2204 Leach, Naik [Page 28]
\r\f
2207 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2210 AF_OP_COMM 1 Communications operator
2211 AF_OP_SERVER 2 Server operator
2212 AF_OP_ACCOUNTS 3 Accounts operator
2215 usri11_password_age specifies how many seconds have elapsed since the
2216 password was last changed.
2218 usri11_home_dir points to a null terminated ASCII string that contains
2219 the path name of the user's home directory.
2221 usri11_parms points to a null terminated ASCII string that is set
2222 aside for use by applications.
2224 usri11_last_logon specifies the time when the user last logged on.
2225 This value is stored as the number of seconds elapsed since
2226 00:00:00, January 1, 1970.
2228 usri11_last_logoff specifies the time when the user last logged off.
2229 This value is stored as the number of seconds elapsed since
2230 00:00:00, January 1, 1970. A value of 0 means the last logoff
2233 usri11_bad_pw_count specifies the number of incorrect passwords
2234 entered since the last successful logon.
2236 usri11_log1_num_logons specifies the number of times this user has
2237 logged on. A value of -1 means the number of logons is unknown.
2239 usri11_logon_server points to a null terminated ASCII string that
2240 contains the name of the server to which logon requests are sent.
2241 A null string indicates logon requests should be sent to the
2244 usri11_country_code specifies the country code for the user's language
2247 usri11_workstations points to a null terminated ASCII string that
2248 contains the names of workstations the user may log on from.
2249 There may be up to 8 workstations, with the names separated by
2250 commas. A null strings indicates there are no restrictions.
2252 usri11_max_storage specifies the maximum amount of disk space the user
2253 can occupy. A value of 0xffffffff indicates there are no
2256 usri11_units_per_week specifies the equal number of time units into
2257 which a week is divided. This value must be equal to 168.
2259 usri11_logon_hours points to a 21 byte (168 bits) string that
2260 specifies the time during which the user can log on. Each bit
2261 represents one unique hour in a week. The first bit (bit 0, word
2262 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2266 Leach, Naik [Page 29]
\r\f
2269 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2272 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2273 are no restrictions.
2275 usri11_code_page specifies the code page for the user's language of
2278 All of the pointers in this data structure need to be treated
2279 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2280 to be ignored. The converter word returned in the parameters section
2281 needs to be subtracted from the lower 16 bits to calculate an offset
2282 into the return buffer where this ASCII string resides.
2284 There is no auxiliary data in the response.
2286 ****************************************************************************/
2288 #define usri11_name 0
2289 #define usri11_pad 21
2290 #define usri11_comment 22
2291 #define usri11_usr_comment 26
2292 #define usri11_full_name 30
2293 #define usri11_priv 34
2294 #define usri11_auth_flags 36
2295 #define usri11_password_age 40
2296 #define usri11_homedir 44
2297 #define usri11_parms 48
2298 #define usri11_last_logon 52
2299 #define usri11_last_logoff 56
2300 #define usri11_bad_pw_count 60
2301 #define usri11_num_logons 62
2302 #define usri11_logon_server 64
2303 #define usri11_country_code 68
2304 #define usri11_workstations 70
2305 #define usri11_max_storage 74
2306 #define usri11_units_per_week 78
2307 #define usri11_logon_hours 80
2308 #define usri11_code_page 84
2309 #define usri11_end 86
2311 #define USER_PRIV_GUEST 0
2312 #define USER_PRIV_USER 1
2313 #define USER_PRIV_ADMIN 2
2315 #define AF_OP_PRINT 0
2316 #define AF_OP_COMM 1
2317 #define AF_OP_SERVER 2
2318 #define AF_OP_ACCOUNTS 3
2321 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2322 int mdrcnt,int mprcnt,
2323 char **rdata,char **rparam,
2324 int *rdata_len,int *rparam_len)
2326 char *str1 = param+2;
2327 char *str2 = skip_string(str1,1);
2328 char *UserName = skip_string(str2,1);
2329 char *p = skip_string(UserName,1);
2330 int uLevel = SVAL(p,0);
2333 /* get NIS home of a previously validated user - simeon */
2334 /* With share level security vuid will always be zero.
2335 Don't depend on vuser being non-null !!. JRA */
2336 user_struct *vuser = get_valid_user_struct(vuid);
2338 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2341 *rparam = REALLOC(*rparam,*rparam_len);
2343 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2345 /* check it's a supported variant */
2346 if (strcmp(str1,"zWrLh") != 0) return False;
2349 case 0: p2 = "B21"; break;
2350 case 1: p2 = "B21BB16DWzzWz"; break;
2351 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2352 case 10: p2 = "B21Bzzz"; break;
2353 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2354 default: return False;
2357 if (strcmp(p2,str2) != 0) return False;
2359 *rdata_len = mdrcnt + 1024;
2360 *rdata = REALLOC(*rdata,*rdata_len);
2362 SSVAL(*rparam,0,NERR_Success);
2363 SSVAL(*rparam,2,0); /* converter word */
2366 p2 = p + usri11_end;
2369 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2373 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2378 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2379 strcpy(p2,"Comment");
2380 p2 = skip_string(p2,1);
2382 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2383 strcpy(p2,"UserComment");
2384 p2 = skip_string(p2,1);
2386 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2387 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2388 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2389 p2 = skip_string(p2,1);
2392 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2394 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2395 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2396 SIVALS(p,usri11_password_age,-1); /* password age */
2397 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2398 strcpy(p2, lp_logon_path());
2399 p2 = skip_string(p2,1);
2400 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2402 p2 = skip_string(p2,1);
2403 SIVAL(p,usri11_last_logon,0); /* last logon */
2404 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2405 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2406 SSVALS(p,usri11_num_logons,-1); /* num logons */
2407 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2409 p2 = skip_string(p2,1);
2410 SSVAL(p,usri11_country_code,0); /* country code */
2412 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2414 p2 = skip_string(p2,1);
2416 SIVALS(p,usri11_max_storage,-1); /* max storage */
2417 SSVAL(p,usri11_units_per_week,168); /* units per week */
2418 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2420 /* a simple way to get logon hours at all times. */
2422 SCVAL(p2,21,0); /* fix zero termination */
2423 p2 = skip_string(p2,1);
2425 SSVAL(p,usri11_code_page,0); /* code page */
2427 if (uLevel == 1 || uLevel == 2)
2429 memset(p+22,' ',16); /* password */
2430 SIVALS(p,38,-1); /* password age */
2432 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2433 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2434 strcpy(p2,lp_logon_path());
2435 p2 = skip_string(p2,1);
2436 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2438 SSVAL(p,52,0); /* flags */
2439 SIVAL(p,54,0); /* script_path */
2442 SIVAL(p,60,0); /* auth_flags */
2443 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2444 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2445 p2 = skip_string(p2,1);
2446 SIVAL(p,68,0); /* urs_comment */
2447 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2449 p2 = skip_string(p2,1);
2450 SIVAL(p,76,0); /* workstations */
2451 SIVAL(p,80,0); /* last_logon */
2452 SIVAL(p,84,0); /* last_logoff */
2453 SIVALS(p,88,-1); /* acct_expires */
2454 SIVALS(p,92,-1); /* max_storage */
2455 SSVAL(p,96,168); /* units_per_week */
2456 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2459 SSVALS(p,102,-1); /* bad_pw_count */
2460 SSVALS(p,104,-1); /* num_logons */
2461 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2462 strcpy(p2,"\\\\%L");
2463 standard_sub_basic(p2);
2464 p2 = skip_string(p2,1);
2465 SSVAL(p,110,49); /* country_code */
2466 SSVAL(p,112,860); /* code page */
2470 *rdata_len = PTR_DIFF(p2,*rdata);
2472 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2477 /*******************************************************************
2478 get groups that a user is a member of
2479 ******************************************************************/
2480 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2481 int mdrcnt,int mprcnt,
2482 char **rdata,char **rparam,
2483 int *rdata_len,int *rparam_len)
2485 char *str1 = param+2;
2486 char *str2 = skip_string(str1,1);
2487 char *UserName = skip_string(str2,1);
2488 char *p = skip_string(UserName,1);
2489 int uLevel = SVAL(p,0);
2494 *rparam = REALLOC(*rparam,*rparam_len);
2496 /* check it's a supported varient */
2497 if (strcmp(str1,"zWrLeh") != 0) return False;
2499 case 0: p2 = "B21"; break;
2500 default: return False;
2502 if (strcmp(p2,str2) != 0) return False;
2504 *rdata_len = mdrcnt + 1024;
2505 *rdata = REALLOC(*rdata,*rdata_len);
2507 SSVAL(*rparam,0,NERR_Success);
2508 SSVAL(*rparam,2,0); /* converter word */
2512 /* XXXX we need a real SAM database some day */
2513 strcpy(p,"Users"); p += 21; count++;
2514 strcpy(p,"Domain Users"); p += 21; count++;
2515 strcpy(p,"Guests"); p += 21; count++;
2516 strcpy(p,"Domain Guests"); p += 21; count++;
2518 *rdata_len = PTR_DIFF(p,*rdata);
2520 SSVAL(*rparam,4,count); /* is this right?? */
2521 SSVAL(*rparam,6,count); /* is this right?? */
2527 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2528 int mdrcnt,int mprcnt,
2529 char **rdata,char **rparam,
2530 int *rdata_len,int *rparam_len)
2532 char *str1 = param+2;
2533 char *str2 = skip_string(str1,1);
2534 char *p = skip_string(str2,1);
2536 struct pack_desc desc;
2543 bzero(&desc,sizeof(desc));
2545 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2547 /* check it's a supported varient */
2548 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2549 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2550 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2552 desc.buflen = mdrcnt;
2553 desc.subformat = NULL;
2556 if (init_package(&desc,1,0))
2558 PACKI(&desc,"W",0); /* code */
2559 PACKS(&desc,"B21",name); /* eff. name */
2560 PACKS(&desc,"B",""); /* pad */
2562 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2563 PACKI(&desc,"D",0); /* auth flags XXX */
2564 PACKI(&desc,"W",0); /* num logons */
2565 PACKI(&desc,"W",0); /* bad pw count */
2566 PACKI(&desc,"D",0); /* last logon */
2567 PACKI(&desc,"D",-1); /* last logoff */
2568 PACKI(&desc,"D",-1); /* logoff time */
2569 PACKI(&desc,"D",-1); /* kickoff time */
2570 PACKI(&desc,"D",0); /* password age */
2571 PACKI(&desc,"D",0); /* password can change */
2572 PACKI(&desc,"D",-1); /* password must change */
2575 strcpy(mypath,"\\\\");
2576 strcat(mypath,local_machine);
2578 PACKS(&desc,"z",mypath); /* computer */
2580 PACKS(&desc,"z",myworkgroup);/* domain */
2582 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2583 /* made sure all macros are fully substituted and available */
2584 logon_script = lp_logon_script();
2585 standard_sub( cnum, logon_script );
2586 PACKS(&desc,"z", logon_script); /* script path */
2587 /* End of JHT mods */
2589 PACKI(&desc,"D",0x00000000); /* reserved */
2592 *rdata_len = desc.usedlen;
2594 *rparam = REALLOC(*rparam,*rparam_len);
2595 SSVALS(*rparam,0,desc.errcode);
2597 SSVAL(*rparam,4,desc.neededlen);
2599 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2604 /****************************************************************************
2605 api_WAccessGetUserPerms
2606 ****************************************************************************/
2607 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2608 int mdrcnt,int mprcnt,
2609 char **rdata,char **rparam,
2610 int *rdata_len,int *rparam_len)
2612 char *str1 = param+2;
2613 char *str2 = skip_string(str1,1);
2614 char *user = skip_string(str2,1);
2615 char *resource = skip_string(user,1);
2617 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2619 /* check it's a supported varient */
2620 if (strcmp(str1,"zzh") != 0) return False;
2621 if (strcmp(str2,"") != 0) return False;
2624 *rparam = REALLOC(*rparam,*rparam_len);
2625 SSVALS(*rparam,0,0); /* errorcode */
2626 SSVAL(*rparam,2,0); /* converter word */
2627 SSVAL(*rparam,4,0x7f); /* permission flags */
2632 /****************************************************************************
2633 api_WPrintJobEnumerate
2634 ****************************************************************************/
2635 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2636 int mdrcnt,int mprcnt,
2637 char **rdata,char **rparam,
2638 int *rdata_len,int *rparam_len)
2640 char *str1 = param+2;
2641 char *str2 = skip_string(str1,1);
2642 char *p = skip_string(str2,1);
2648 struct pack_desc desc;
2649 print_queue_struct *queue=NULL;
2650 print_status_struct status;
2655 bzero(&desc,sizeof(desc));
2656 bzero(&status,sizeof(status));
2658 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2660 /* check it's a supported varient */
2661 if (strcmp(str1,"WWrLh") != 0) return False;
2662 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2664 printjob_decode(SVAL(p,0), &snum, &job);
2666 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2668 count = get_printqueue(snum,cnum,&queue,&status);
2669 for (i = 0; i < count; i++) {
2670 if ((queue[i].job & 0xFF) == job) break;
2672 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2674 desc.buflen = mdrcnt;
2676 if (init_package(&desc,1,0)) {
2678 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2679 *rdata_len = desc.usedlen;
2682 desc.errcode = NERR_JobNotFound;
2688 *rparam = REALLOC(*rparam,*rparam_len);
2689 SSVALS(*rparam,0,desc.errcode);
2691 SSVAL(*rparam,4,desc.neededlen);
2693 if (queue) free(queue);
2695 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2699 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2700 int mdrcnt,int mprcnt,
2701 char **rdata,char **rparam,
2702 int *rdata_len,int *rparam_len)
2704 char *str1 = param+2;
2705 char *str2 = skip_string(str1,1);
2706 char *p = skip_string(str2,1);
2712 struct pack_desc desc;
2713 print_queue_struct *queue=NULL;
2714 print_status_struct status;
2716 bzero(&desc,sizeof(desc));
2717 bzero(&status,sizeof(status));
2719 p = skip_string(p,1);
2723 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2725 /* check it's a supported varient */
2726 if (strcmp(str1,"zWrLeh") != 0) return False;
2727 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2728 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2730 snum = lp_servicenumber(name);
2731 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2732 int pnum = lp_servicenumber(PRINTERS_NAME);
2734 lp_add_printer(name,pnum);
2735 snum = lp_servicenumber(name);
2739 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2741 count = get_printqueue(snum,cnum,&queue,&status);
2742 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2744 desc.buflen = mdrcnt;
2746 if (init_package(&desc,count,0)) {
2748 for (i = 0; i < count; i++) {
2749 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2750 if (desc.errcode == NERR_Success) succnt = i+1;
2754 *rdata_len = desc.usedlen;
2757 *rparam = REALLOC(*rparam,*rparam_len);
2758 SSVALS(*rparam,0,desc.errcode);
2760 SSVAL(*rparam,4,succnt);
2761 SSVAL(*rparam,6,count);
2763 if (queue) free(queue);
2765 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2769 static int check_printdest_info(struct pack_desc* desc,
2770 int uLevel, char* id)
2772 desc->subformat = NULL;
2774 case 0: desc->format = "B9"; break;
2775 case 1: desc->format = "B9B21WWzW"; break;
2776 case 2: desc->format = "z"; break;
2777 case 3: desc->format = "zzzWWzzzWW"; break;
2778 default: return False;
2780 if (strcmp(desc->format,id) != 0) return False;
2784 static void fill_printdest_info(int cnum, int snum, int uLevel,
2785 struct pack_desc* desc)
2788 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2789 buf[sizeof(buf)-1] = 0;
2792 PACKS(desc,"B9",buf); /* szName */
2794 PACKS(desc,"B21",""); /* szUserName */
2795 PACKI(desc,"W",0); /* uJobId */
2796 PACKI(desc,"W",0); /* fsStatus */
2797 PACKS(desc,"z",""); /* pszStatus */
2798 PACKI(desc,"W",0); /* time */
2801 if (uLevel == 2 || uLevel == 3) {
2802 PACKS(desc,"z",buf); /* pszPrinterName */
2804 PACKS(desc,"z",""); /* pszUserName */
2805 PACKS(desc,"z",""); /* pszLogAddr */
2806 PACKI(desc,"W",0); /* uJobId */
2807 PACKI(desc,"W",0); /* fsStatus */
2808 PACKS(desc,"z",""); /* pszStatus */
2809 PACKS(desc,"z",""); /* pszComment */
2810 PACKS(desc,"z","NULL"); /* pszDrivers */
2811 PACKI(desc,"W",0); /* time */
2812 PACKI(desc,"W",0); /* pad1 */
2817 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2818 int mdrcnt,int mprcnt,
2819 char **rdata,char **rparam,
2820 int *rdata_len,int *rparam_len)
2822 char *str1 = param+2;
2823 char *str2 = skip_string(str1,1);
2824 char *p = skip_string(str2,1);
2825 char* PrinterName = p;
2827 struct pack_desc desc;
2830 bzero(&desc,sizeof(desc));
2832 p = skip_string(p,1);
2836 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2838 /* check it's a supported varient */
2839 if (strcmp(str1,"zWrLh") != 0) return False;
2840 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2842 snum = lp_servicenumber(PrinterName);
2843 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2844 int pnum = lp_servicenumber(PRINTERS_NAME);
2846 lp_add_printer(PrinterName,pnum);
2847 snum = lp_servicenumber(PrinterName);
2853 desc.errcode = NERR_DestNotFound;
2857 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2859 desc.buflen = mdrcnt;
2860 if (init_package(&desc,1,0)) {
2861 fill_printdest_info(cnum,snum,uLevel,&desc);
2863 *rdata_len = desc.usedlen;
2867 *rparam = REALLOC(*rparam,*rparam_len);
2868 SSVALS(*rparam,0,desc.errcode);
2870 SSVAL(*rparam,4,desc.neededlen);
2872 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2876 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2877 int mdrcnt,int mprcnt,
2878 char **rdata,char **rparam,
2879 int *rdata_len,int *rparam_len)
2881 char *str1 = param+2;
2882 char *str2 = skip_string(str1,1);
2883 char *p = skip_string(str2,1);
2887 struct pack_desc desc;
2888 int services = lp_numservices();
2890 bzero(&desc,sizeof(desc));
2895 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2897 /* check it's a supported varient */
2898 if (strcmp(str1,"WrLeh") != 0) return False;
2899 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2902 for (i = 0; i < services; i++)
2903 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2906 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2908 desc.buflen = mdrcnt;
2909 if (init_package(&desc,queuecnt,0)) {
2912 for (i = 0; i < services; i++) {
2913 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2914 fill_printdest_info(cnum,i,uLevel,&desc);
2916 if (desc.errcode == NERR_Success) succnt = n;
2921 *rdata_len = desc.usedlen;
2924 *rparam = REALLOC(*rparam,*rparam_len);
2925 SSVALS(*rparam,0,desc.errcode);
2927 SSVAL(*rparam,4,succnt);
2928 SSVAL(*rparam,6,queuecnt);
2930 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2934 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2935 int mdrcnt,int mprcnt,
2936 char **rdata,char **rparam,
2937 int *rdata_len,int *rparam_len)
2939 char *str1 = param+2;
2940 char *str2 = skip_string(str1,1);
2941 char *p = skip_string(str2,1);
2944 struct pack_desc desc;
2946 bzero(&desc,sizeof(desc));
2951 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2953 /* check it's a supported varient */
2954 if (strcmp(str1,"WrLeh") != 0) return False;
2955 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2957 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2959 desc.buflen = mdrcnt;
2960 if (init_package(&desc,1,0)) {
2961 PACKS(&desc,"B41","NULL");
2964 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2966 *rdata_len = desc.usedlen;
2969 *rparam = REALLOC(*rparam,*rparam_len);
2970 SSVALS(*rparam,0,desc.errcode);
2972 SSVAL(*rparam,4,succnt);
2975 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2979 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2980 int mdrcnt,int mprcnt,
2981 char **rdata,char **rparam,
2982 int *rdata_len,int *rparam_len)
2984 char *str1 = param+2;
2985 char *str2 = skip_string(str1,1);
2986 char *p = skip_string(str2,1);
2989 struct pack_desc desc;
2991 bzero(&desc,sizeof(desc));
2996 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2998 /* check it's a supported varient */
2999 if (strcmp(str1,"WrLeh") != 0) return False;
3000 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3002 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3004 desc.buflen = mdrcnt;
3006 if (init_package(&desc,1,0)) {
3007 PACKS(&desc,"B13","lpd");
3010 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3012 *rdata_len = desc.usedlen;
3015 *rparam = REALLOC(*rparam,*rparam_len);
3016 SSVALS(*rparam,0,desc.errcode);
3018 SSVAL(*rparam,4,succnt);
3021 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3025 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
3026 int mdrcnt,int mprcnt,
3027 char **rdata,char **rparam,
3028 int *rdata_len,int *rparam_len)
3030 char *str1 = param+2;
3031 char *str2 = skip_string(str1,1);
3032 char *p = skip_string(str2,1);
3035 struct pack_desc desc;
3037 bzero(&desc,sizeof(desc));
3042 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3044 /* check it's a supported varient */
3045 if (strcmp(str1,"WrLeh") != 0) return False;
3046 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3048 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3049 bzero(&desc,sizeof(desc));
3051 desc.buflen = mdrcnt;
3053 if (init_package(&desc,1,0)) {
3054 PACKS(&desc,"B13","lp0");
3057 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3059 *rdata_len = desc.usedlen;
3062 *rparam = REALLOC(*rparam,*rparam_len);
3063 SSVALS(*rparam,0,desc.errcode);
3065 SSVAL(*rparam,4,succnt);
3068 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3074 char * pipe_clnt_name;
3075 char * pipe_srv_name;
3076 BOOL (*fn) (pipes_struct *, prs_struct *);
3079 static struct api_cmd api_fd_commands[] =
3081 { "lsarpc", "lsass", api_ntlsa_rpc },
3082 { "samr", "lsass", api_samr_rpc },
3083 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3084 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3085 { "NETLOGON", "lsass", api_netlog_rpc },
3086 { "winreg", "winreg", api_reg_rpc },
3087 { NULL, NULL, NULL }
3090 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3092 BOOL ntlmssp_auth = False;
3093 fstring ack_pipe_name;
3096 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3098 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3100 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3101 api_fd_commands[i].fn != NULL)
3103 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3104 api_fd_commands[i].pipe_clnt_name,
3105 api_fd_commands[i].pipe_srv_name));
3106 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3111 if (api_fd_commands[i].fn == NULL) return False;
3113 /* decode the bind request */
3114 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3116 if (pd->offset == 0) return False;
3118 if (p->hdr.auth_len != 0)
3120 /* decode the authentication verifier */
3121 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3123 if (pd->offset == 0) return False;
3125 /* ignore the version number for now */
3126 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3129 /* name has to be \PIPE\xxxxx */
3130 strcpy(ack_pipe_name, "\\PIPE\\");
3131 strcat(ack_pipe_name, p->pipe_srv_name);
3133 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3135 prs_init(&(p->rdata), 1024, 4, 0, False);
3136 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3137 prs_init(&(p->rauth), 1024, 4, 0, False);
3140 /*** do the bind ack first ***/
3143 make_rpc_hdr_ba(&p->hdr_ba,
3144 p->hdr_rb.bba.max_tsize,
3145 p->hdr_rb.bba.max_rsize,
3146 p->hdr_rb.bba.assoc_gid,
3149 &(p->hdr_rb.transfer));
3151 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3152 mem_realloc_data(p->rdata.data, p->rdata.offset);
3155 /*** now the authentication ***/
3161 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3163 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3166 0x00000000, 0x0000b2b3, 0x000082b1,
3168 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3169 mem_realloc_data(p->rauth.data, p->rauth.offset);
3173 /*** then do the header, now we know the length ***/
3176 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3178 p->rdata.offset + p->rauth.offset,
3181 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3182 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3185 /*** link rpc header, bind acknowledgment and authentication responses ***/
3188 p->rhdr.data->offset.start = 0;
3189 p->rhdr.data->offset.end = p->rhdr.offset;
3190 p->rhdr.data->next = p->rdata.data;
3194 p->rdata.data->offset.start = p->rhdr.offset;
3195 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3196 p->rdata.data->next = p->rauth.data;
3198 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3199 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3200 p->rauth.data->next = NULL;
3204 p->rdata.data->offset.start = p->rhdr.offset;
3205 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3206 p->rdata.data->next = NULL;
3212 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3216 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3218 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3219 api_fd_commands[i].fn != NULL)
3221 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3222 return api_fd_commands[i].fn(p, pd);
3228 static BOOL api_dce_rpc_command(char *outbuf,
3233 if (pd->data == NULL) return False;
3235 /* process the rpc header */
3236 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3238 if (pd->offset == 0) return False;
3240 switch (p->hdr.pkt_type)
3244 reply = api_pipe_bind_req(p, pd);
3249 reply = api_pipe_request (p, pd);
3256 /* now send the reply */
3257 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len);
3259 if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len)
3261 /* all of data was sent: no need to wait for SMBreadX calls */
3262 mem_free_data(p->rhdr .data);
3263 mem_free_data(p->rdata.data);
3270 /****************************************************************************
3271 SetNamedPipeHandleState
3272 ****************************************************************************/
3273 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3277 if (!param) return False;
3279 id = param[0] + (param[1] << 8);
3280 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3282 if (set_rpc_pipe_hnd_state(p, id))
3284 /* now send the reply */
3285 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len);
3293 /****************************************************************************
3294 when no reply is generated, indicate unsupported.
3295 ****************************************************************************/
3296 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3298 struct mem_buf rparam;
3300 mem_init(&rparam, 0);
3301 mem_alloc_data(&rparam, 4);
3303 rparam.offset.start = 0;
3304 rparam.offset.end = 4;
3307 SSVAL(rparam.data,0,NERR_notsupported);
3308 SSVAL(rparam.data,2,0); /* converter word */
3310 DEBUG(3,("Unsupported API fd command\n"));
3312 /* now send the reply */
3313 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3315 mem_free_data(&rparam);
3320 /****************************************************************************
3321 handle remote api calls delivered to a named pipe already opened.
3322 ****************************************************************************/
3323 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3324 uint16 *setup,char *data,char *params,
3325 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3331 pipes_struct *p = NULL;
3333 struct mem_buf data_buf;
3335 DEBUG(5,("api_fd_reply\n"));
3337 /* fake up a data buffer from the api_fd_reply data parameters */
3338 mem_create(&data_buf, data, tdscnt, 0, False);
3339 data_buf.offset.start = 0;
3340 data_buf.offset.end = tdscnt;
3342 /* fake up a parsing structure */
3343 pd.data = &data_buf;
3348 /* First find out the name of this file. */
3351 DEBUG(0,("Unexpected named pipe transaction.\n"));
3355 /* Get the file handle and hence the file name. */
3357 subcommand = setup[0];
3358 get_rpc_pipe(pnum, &p);
3362 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3363 subcommand, p->name, pnum));
3364 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3365 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3367 /* record maximum data length that can be transmitted in an SMBtrans */
3368 p->max_rdata_len = mdrcnt;
3374 /* dce/rpc command */
3375 reply = api_dce_rpc_command(outbuf, p, &pd);
3380 /* Set Named Pipe Handle state */
3381 reply = api_SNPHS(outbuf, p, params);
3388 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3393 return api_no_reply(outbuf, mdrcnt);
3398 /****************************************************************************
3399 the buffer was too small
3400 ****************************************************************************/
3401 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3402 int mdrcnt,int mprcnt,
3403 char **rdata,char **rparam,
3404 int *rdata_len,int *rparam_len)
3406 *rparam_len = MIN(*rparam_len,mprcnt);
3407 *rparam = REALLOC(*rparam,*rparam_len);
3411 SSVAL(*rparam,0,NERR_BufTooSmall);
3413 DEBUG(3,("Supplied buffer too small in API command\n"));
3419 /****************************************************************************
3420 the request is not supported
3421 ****************************************************************************/
3422 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3423 int mdrcnt,int mprcnt,
3424 char **rdata,char **rparam,
3425 int *rdata_len,int *rparam_len)
3428 *rparam = REALLOC(*rparam,*rparam_len);
3432 SSVAL(*rparam,0,NERR_notsupported);
3433 SSVAL(*rparam,2,0); /* converter word */
3435 DEBUG(3,("Unsupported API command\n"));
3449 } api_commands[] = {
3450 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
3451 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
3452 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
3453 {"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0},
3454 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
3455 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
3456 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
3457 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
3458 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
3459 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
3460 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
3461 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
3462 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
3463 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
3464 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
3465 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
3466 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
3467 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
3468 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
3469 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
3470 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
3471 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
3472 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
3473 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
3474 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
3475 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
3476 {"SamOEMChangePassword", 214, (BOOL (*)())api_SamOEMChangePassword,0},
3477 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
3480 /****************************************************************************
3481 handle remote api calls
3482 ****************************************************************************/
3483 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3484 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3486 int api_command = SVAL(params,0);
3487 struct mem_buf rdata_buf;
3488 struct mem_buf rparam_buf;
3490 char *rparam = NULL;
3496 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3497 api_command,params+2,skip_string(params+2,1),
3498 tdscnt,tpscnt,mdrcnt,mprcnt));
3500 for (i=0;api_commands[i].name;i++)
3501 if (api_commands[i].id == api_command && api_commands[i].fn)
3503 DEBUG(3,("Doing %s\n",api_commands[i].name));
3507 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3508 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3510 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3511 &rdata,&rparam,&rdata_len,&rparam_len);
3514 if (rdata_len > mdrcnt ||
3515 rparam_len > mprcnt)
3517 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3518 &rdata,&rparam,&rdata_len,&rparam_len);
3522 /* if we get False back then it's actually unsupported */
3524 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3525 &rdata,&rparam,&rdata_len,&rparam_len);
3528 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3529 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3531 rdata_buf.offset.start = 0;
3532 rdata_buf.offset.end = rdata_len;
3534 rparam_buf.offset.start = 0;
3535 rparam_buf.offset.end = rparam_len;
3537 /* now send the reply */
3538 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3540 if (rdata ) free(rdata);
3541 if (rparam) free(rparam);
3546 /****************************************************************************
3547 handle named pipe commands
3548 ****************************************************************************/
3549 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3550 uint16 *setup,char *data,char *params,
3551 int suwcnt,int tdscnt,int tpscnt,
3552 int msrcnt,int mdrcnt,int mprcnt)
3554 DEBUG(3,("named pipe command on <%s> name\n", name));
3556 if (strequal(name,"LANMAN"))
3558 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3561 if (strlen(name) < 1)
3563 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3568 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3575 /****************************************************************************
3577 ****************************************************************************/
3578 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3582 char *data=NULL,*params=NULL;
3586 int cnum = SVAL(inbuf,smb_tid);
3587 uint16 vuid = SVAL(inbuf,smb_uid);
3589 int tpscnt = SVAL(inbuf,smb_vwv0);
3590 int tdscnt = SVAL(inbuf,smb_vwv1);
3591 int mprcnt = SVAL(inbuf,smb_vwv2);
3592 int mdrcnt = SVAL(inbuf,smb_vwv3);
3593 int msrcnt = CVAL(inbuf,smb_vwv4);
3594 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3595 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3596 int pscnt = SVAL(inbuf,smb_vwv9);
3597 int psoff = SVAL(inbuf,smb_vwv10);
3598 int dscnt = SVAL(inbuf,smb_vwv11);
3599 int dsoff = SVAL(inbuf,smb_vwv12);
3600 int suwcnt = CVAL(inbuf,smb_vwv13);
3602 bzero(name, sizeof(name));
3603 fstrcpy(name,smb_buf(inbuf));
3605 if (dscnt > tdscnt || pscnt > tpscnt) {
3606 exit_server("invalid trans parameters\n");
3611 data = (char *)malloc(tdscnt);
3612 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3616 params = (char *)malloc(tpscnt);
3617 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3623 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3624 for (i=0;i<suwcnt;i++)
3625 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3629 if (pscnt < tpscnt || dscnt < tdscnt)
3631 /* We need to send an interim response then receive the rest
3632 of the parameter/data bytes */
3633 outsize = set_message(outbuf,0,0,True);
3635 send_smb(Client,outbuf);
3638 /* receive the rest of the trans packet */
3639 while (pscnt < tpscnt || dscnt < tdscnt)
3642 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3644 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3646 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3649 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3651 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3652 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3653 if (params) free(params);
3654 if (data) free(data);
3655 if (setup) free(setup);
3656 return(ERROR(ERRSRV,ERRerror));
3661 tpscnt = SVAL(inbuf,smb_vwv0);
3662 tdscnt = SVAL(inbuf,smb_vwv1);
3664 pcnt = SVAL(inbuf,smb_vwv2);
3665 poff = SVAL(inbuf,smb_vwv3);
3666 pdisp = SVAL(inbuf,smb_vwv4);
3668 dcnt = SVAL(inbuf,smb_vwv5);
3669 doff = SVAL(inbuf,smb_vwv6);
3670 ddisp = SVAL(inbuf,smb_vwv7);
3675 if (dscnt > tdscnt || pscnt > tpscnt) {
3676 exit_server("invalid trans parameters\n");
3680 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3682 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3686 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3688 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3690 DEBUG(5,("calling named_pipe\n"));
3691 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3692 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3696 DEBUG(3,("invalid pipe name\n"));
3701 if (data) free(data);
3702 if (params) free(params);
3703 if (setup) free(setup);
3705 if (close_on_completion)
3706 close_cnum(cnum,vuid);
3712 return(ERROR(ERRSRV,ERRnosupport));