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 /****************************************************************************
1668 ****************************************************************************/
1669 static BOOL api_RDosPrintJobDel(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)
1674 int function = SVAL(param,0);
1675 char *str1 = param+2;
1676 char *str2 = skip_string(str1,1);
1677 char *p = skip_string(str2,1);
1681 printjob_decode(SVAL(p,0), &snum, &jobid);
1683 /* check it's a supported varient */
1684 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1688 *rparam = REALLOC(*rparam,*rparam_len);
1692 SSVAL(*rparam,0,NERR_Success);
1694 if (snum >= 0 && VALID_SNUM(snum))
1696 print_queue_struct *queue=NULL;
1698 count = get_printqueue(snum,cnum,&queue,NULL);
1700 for (i=0;i<count;i++)
1701 if ((queue[i].job&0xFF) == jobid)
1704 case 81: /* delete */
1705 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1706 del_printqueue(cnum,snum,queue[i].job);
1708 case 82: /* pause */
1709 case 83: /* resume */
1710 DEBUG(3,("%s queue entry %d\n",
1711 (function==82?"pausing":"resuming"),queue[i].job));
1712 status_printjob(cnum,snum,queue[i].job,
1713 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1720 SSVAL(*rparam,0,NERR_JobNotFound);
1722 if (queue) free(queue);
1725 SSVAL(*rparam,2,0); /* converter word */
1730 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1731 int mdrcnt,int mprcnt,
1732 char **rdata,char **rparam,
1733 int *rdata_len,int *rparam_len)
1735 char *str1 = param+2;
1736 char *str2 = skip_string(str1,1);
1737 char *QueueName = skip_string(str2,1);
1740 /* check it's a supported varient */
1741 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1745 *rparam = REALLOC(*rparam,*rparam_len);
1749 SSVAL(*rparam,0,NERR_Success);
1750 SSVAL(*rparam,2,0); /* converter word */
1752 snum = lp_servicenumber(QueueName);
1753 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1754 int pnum = lp_servicenumber(PRINTERS_NAME);
1756 lp_add_printer(QueueName,pnum);
1757 snum = lp_servicenumber(QueueName);
1761 if (snum >= 0 && VALID_SNUM(snum)) {
1762 print_queue_struct *queue=NULL;
1766 count = get_printqueue(snum,cnum,&queue,NULL);
1767 for (i = 0; i < count; i++)
1768 del_printqueue(cnum,snum,queue[i].job);
1770 if (queue) free(queue);
1773 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1779 /****************************************************************************
1780 set the property of a print job (undocumented?)
1781 ? function = 0xb -> set name of print job
1782 ? function = 0x6 -> move print job up/down
1783 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1784 or <WWsTP> <WB21BB16B10zWWzDDz>
1785 ****************************************************************************/
1786 static int check_printjob_info(struct pack_desc* desc,
1787 int uLevel, char* id)
1789 desc->subformat = NULL;
1791 case 0: desc->format = "W"; break;
1792 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1793 case 2: desc->format = "WWzWWDDzz"; break;
1794 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1795 default: return False;
1797 if (strcmp(desc->format,id) != 0) return False;
1801 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1802 int mdrcnt,int mprcnt,
1803 char **rdata,char **rparam,
1804 int *rdata_len,int *rparam_len)
1806 struct pack_desc desc;
1807 char *str1 = param+2;
1808 char *str2 = skip_string(str1,1);
1809 char *p = skip_string(str2,1);
1811 int uLevel = SVAL(p,2);
1812 int function = SVAL(p,4); /* what is this ?? */
1816 printjob_decode(SVAL(p,0), &snum, &jobid);
1819 *rparam = REALLOC(*rparam,*rparam_len);
1823 /* check it's a supported varient */
1824 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1828 case 0x6: /* change job place in the queue, data gives the new place */
1829 if (snum >= 0 && VALID_SNUM(snum))
1831 print_queue_struct *queue=NULL;
1835 count = get_printqueue(snum,cnum,&queue,NULL);
1836 for (i=0;i<count;i++) /* find job */
1837 if ((queue[i].job&0xFF) == jobid) break;
1840 desc.errcode=NERR_JobNotFound;
1841 if (queue) free(queue);
1844 desc.errcode=NERR_Success;
1848 int place= SVAL(data,0);
1849 /* we currently have no way of doing this. Can any unix do it? */
1850 if (i < place) /* move down */;
1851 else if (i > place ) /* move up */;
1854 desc.errcode=NERR_notsupported; /* not yet supported */
1855 if (queue) free(queue);
1858 else desc.errcode=NERR_JobNotFound;
1860 case 0xb: /* change print job name, data gives the name */
1861 /* jobid, snum should be zero */
1868 if (issafe(*s)) name[l++] = *s;
1873 DEBUG(3,("Setting print name to %s\n",name));
1877 for (i=0;i<MAX_OPEN_FILES;i++)
1878 if (Files[i].open && Files[i].print_file)
1881 int fcnum = Files[i].cnum;
1885 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1886 !become_service(fcnum,True))
1889 if (sys_rename(Files[i].name,name) == 0)
1890 string_set(&Files[i].name,name);
1894 unbecome_root(True);
1896 desc.errcode=NERR_Success;
1899 default: /* not implemented */
1903 SSVALS(*rparam,0,desc.errcode);
1904 SSVAL(*rparam,2,0); /* converter word */
1910 /****************************************************************************
1911 get info about the server
1912 ****************************************************************************/
1913 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1914 int mdrcnt,int mprcnt,
1915 char **rdata,char **rparam,
1916 int *rdata_len,int *rparam_len)
1918 char *str1 = param+2;
1919 char *str2 = skip_string(str1,1);
1920 char *p = skip_string(str2,1);
1921 int uLevel = SVAL(p,0);
1925 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1927 /* check it's a supported varient */
1928 if (!prefix_ok(str1,"WrLh")) return False;
1931 if (strcmp(str2,"B16") != 0) return False;
1935 if (strcmp(str2,"B16BBDz") != 0) return False;
1939 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1944 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1949 if (strcmp(str2,"DN") != 0) return False;
1953 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1956 default: return False;
1959 *rdata_len = mdrcnt;
1960 *rdata = REALLOC(*rdata,*rdata_len);
1963 p2 = p + struct_len;
1965 StrnCpy(p,local_machine,16);
1971 struct srv_info_struct *servers=NULL;
1974 uint32 servertype= lp_default_server_announce();
1976 pstrcpy(comment,lp_serverstring());
1978 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1979 for (i=0;i<count;i++)
1980 if (strequal(servers[i].name,local_machine))
1982 servertype = servers[i].type;
1983 pstrcpy(comment,servers[i].comment);
1986 if (servers) free(servers);
1988 SCVAL(p,0,lp_major_announce_version());
1989 SCVAL(p,1,lp_minor_announce_version());
1990 SIVAL(p,2,servertype);
1992 if (mdrcnt == struct_len) {
1995 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1996 standard_sub(cnum,comment);
1997 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1998 p2 = skip_string(p2,1);
2003 return False; /* not yet implemented */
2006 *rdata_len = PTR_DIFF(p2,*rdata);
2009 *rparam = REALLOC(*rparam,*rparam_len);
2010 SSVAL(*rparam,0,NERR_Success);
2011 SSVAL(*rparam,2,0); /* converter word */
2012 SSVAL(*rparam,4,*rdata_len);
2018 /****************************************************************************
2019 get info about the server
2020 ****************************************************************************/
2021 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
2022 int mdrcnt,int mprcnt,
2023 char **rdata,char **rparam,
2024 int *rdata_len,int *rparam_len)
2026 char *str1 = param+2;
2027 char *str2 = skip_string(str1,1);
2028 char *p = skip_string(str2,1);
2030 extern pstring sesssetup_user;
2031 int level = SVAL(p,0);
2033 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2036 *rparam = REALLOC(*rparam,*rparam_len);
2038 /* check it's a supported varient */
2039 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2042 *rdata_len = mdrcnt + 1024;
2043 *rdata = REALLOC(*rdata,*rdata_len);
2045 SSVAL(*rparam,0,NERR_Success);
2046 SSVAL(*rparam,2,0); /* converter word */
2052 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2053 strcpy(p2,local_machine);
2055 p2 = skip_string(p2,1);
2058 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2059 strcpy(p2,sesssetup_user);
2060 p2 = skip_string(p2,1);
2063 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2064 strcpy(p2,myworkgroup);
2066 p2 = skip_string(p2,1);
2069 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2070 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2073 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2074 strcpy(p2,myworkgroup); /* don't know. login domain?? */
2075 p2 = skip_string(p2,1);
2078 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2080 p2 = skip_string(p2,1);
2083 *rdata_len = PTR_DIFF(p2,*rdata);
2085 SSVAL(*rparam,4,*rdata_len);
2090 /****************************************************************************
2091 get info about a user
2093 struct user_info_11 {
2094 char usri11_name[21]; 0-20
2096 char *usri11_comment; 22-25
2097 char *usri11_usr_comment; 26-29
2098 unsigned short usri11_priv; 30-31
2099 unsigned long usri11_auth_flags; 32-35
2100 long usri11_password_age; 36-39
2101 char *usri11_homedir; 40-43
2102 char *usri11_parms; 44-47
2103 long usri11_last_logon; 48-51
2104 long usri11_last_logoff; 52-55
2105 unsigned short usri11_bad_pw_count; 56-57
2106 unsigned short usri11_num_logons; 58-59
2107 char *usri11_logon_server; 60-63
2108 unsigned short usri11_country_code; 64-65
2109 char *usri11_workstations; 66-69
2110 unsigned long usri11_max_storage; 70-73
2111 unsigned short usri11_units_per_week; 74-75
2112 unsigned char *usri11_logon_hours; 76-79
2113 unsigned short usri11_code_page; 80-81
2118 usri11_name specifies the user name for which information is retireved
2120 usri11_pad aligns the next data structure element to a word boundary
2122 usri11_comment is a null terminated ASCII comment
2124 usri11_user_comment is a null terminated ASCII comment about the user
2126 usri11_priv specifies the level of the privilege assigned to the user.
2127 The possible values are:
2129 Name Value Description
2130 USER_PRIV_GUEST 0 Guest privilege
2131 USER_PRIV_USER 1 User privilege
2132 USER_PRV_ADMIN 2 Administrator privilege
2134 usri11_auth_flags specifies the account operator privileges. The
2135 possible values are:
2137 Name Value Description
2138 AF_OP_PRINT 0 Print operator
2141 Leach, Naik [Page 28]
\r\f
2144 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2147 AF_OP_COMM 1 Communications operator
2148 AF_OP_SERVER 2 Server operator
2149 AF_OP_ACCOUNTS 3 Accounts operator
2152 usri11_password_age specifies how many seconds have elapsed since the
2153 password was last changed.
2155 usri11_home_dir points to a null terminated ASCII string that contains
2156 the path name of the user's home directory.
2158 usri11_parms points to a null terminated ASCII string that is set
2159 aside for use by applications.
2161 usri11_last_logon specifies the time when the user last logged on.
2162 This value is stored as the number of seconds elapsed since
2163 00:00:00, January 1, 1970.
2165 usri11_last_logoff specifies the time when the user last logged off.
2166 This value is stored as the number of seconds elapsed since
2167 00:00:00, January 1, 1970. A value of 0 means the last logoff
2170 usri11_bad_pw_count specifies the number of incorrect passwords
2171 entered since the last successful logon.
2173 usri11_log1_num_logons specifies the number of times this user has
2174 logged on. A value of -1 means the number of logons is unknown.
2176 usri11_logon_server points to a null terminated ASCII string that
2177 contains the name of the server to which logon requests are sent.
2178 A null string indicates logon requests should be sent to the
2181 usri11_country_code specifies the country code for the user's language
2184 usri11_workstations points to a null terminated ASCII string that
2185 contains the names of workstations the user may log on from.
2186 There may be up to 8 workstations, with the names separated by
2187 commas. A null strings indicates there are no restrictions.
2189 usri11_max_storage specifies the maximum amount of disk space the user
2190 can occupy. A value of 0xffffffff indicates there are no
2193 usri11_units_per_week specifies the equal number of time units into
2194 which a week is divided. This value must be equal to 168.
2196 usri11_logon_hours points to a 21 byte (168 bits) string that
2197 specifies the time during which the user can log on. Each bit
2198 represents one unique hour in a week. The first bit (bit 0, word
2199 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2203 Leach, Naik [Page 29]
\r\f
2206 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2209 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2210 are no restrictions.
2212 usri11_code_page specifies the code page for the user's language of
2215 All of the pointers in this data structure need to be treated
2216 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2217 to be ignored. The converter word returned in the parameters section
2218 needs to be subtracted from the lower 16 bits to calculate an offset
2219 into the return buffer where this ASCII string resides.
2221 There is no auxiliary data in the response.
2223 ****************************************************************************/
2225 #define usri11_name 0
2226 #define usri11_pad 21
2227 #define usri11_comment 22
2228 #define usri11_usr_comment 26
2229 #define usri11_full_name 30
2230 #define usri11_priv 34
2231 #define usri11_auth_flags 36
2232 #define usri11_password_age 40
2233 #define usri11_homedir 44
2234 #define usri11_parms 48
2235 #define usri11_last_logon 52
2236 #define usri11_last_logoff 56
2237 #define usri11_bad_pw_count 60
2238 #define usri11_num_logons 62
2239 #define usri11_logon_server 64
2240 #define usri11_country_code 68
2241 #define usri11_workstations 70
2242 #define usri11_max_storage 74
2243 #define usri11_units_per_week 78
2244 #define usri11_logon_hours 80
2245 #define usri11_code_page 84
2246 #define usri11_end 86
2248 #define USER_PRIV_GUEST 0
2249 #define USER_PRIV_USER 1
2250 #define USER_PRIV_ADMIN 2
2252 #define AF_OP_PRINT 0
2253 #define AF_OP_COMM 1
2254 #define AF_OP_SERVER 2
2255 #define AF_OP_ACCOUNTS 3
2258 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2259 int mdrcnt,int mprcnt,
2260 char **rdata,char **rparam,
2261 int *rdata_len,int *rparam_len)
2263 char *str1 = param+2;
2264 char *str2 = skip_string(str1,1);
2265 char *UserName = skip_string(str2,1);
2266 char *p = skip_string(UserName,1);
2267 int uLevel = SVAL(p,0);
2270 /* get NIS home of a previously validated user - simeon */
2271 /* With share level security vuid will always be zero.
2272 Don't depend on vuser being non-null !!. JRA */
2273 user_struct *vuser = get_valid_user_struct(vuid);
2275 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2278 *rparam = REALLOC(*rparam,*rparam_len);
2280 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2282 /* check it's a supported variant */
2283 if (strcmp(str1,"zWrLh") != 0) return False;
2286 case 0: p2 = "B21"; break;
2287 case 1: p2 = "B21BB16DWzzWz"; break;
2288 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2289 case 10: p2 = "B21Bzzz"; break;
2290 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2291 default: return False;
2294 if (strcmp(p2,str2) != 0) return False;
2296 *rdata_len = mdrcnt + 1024;
2297 *rdata = REALLOC(*rdata,*rdata_len);
2299 SSVAL(*rparam,0,NERR_Success);
2300 SSVAL(*rparam,2,0); /* converter word */
2303 p2 = p + usri11_end;
2306 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2310 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2315 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2316 strcpy(p2,"Comment");
2317 p2 = skip_string(p2,1);
2319 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2320 strcpy(p2,"UserComment");
2321 p2 = skip_string(p2,1);
2323 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2324 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2325 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2326 p2 = skip_string(p2,1);
2329 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2331 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2332 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2333 SIVALS(p,usri11_password_age,-1); /* password age */
2334 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2335 strcpy(p2, lp_logon_path());
2336 p2 = skip_string(p2,1);
2337 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2339 p2 = skip_string(p2,1);
2340 SIVAL(p,usri11_last_logon,0); /* last logon */
2341 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2342 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2343 SSVALS(p,usri11_num_logons,-1); /* num logons */
2344 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2346 p2 = skip_string(p2,1);
2347 SSVAL(p,usri11_country_code,0); /* country code */
2349 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2351 p2 = skip_string(p2,1);
2353 SIVALS(p,usri11_max_storage,-1); /* max storage */
2354 SSVAL(p,usri11_units_per_week,168); /* units per week */
2355 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2357 /* a simple way to get logon hours at all times. */
2359 SCVAL(p2,21,0); /* fix zero termination */
2360 p2 = skip_string(p2,1);
2362 SSVAL(p,usri11_code_page,0); /* code page */
2364 if (uLevel == 1 || uLevel == 2)
2366 memset(p+22,' ',16); /* password */
2367 SIVALS(p,38,-1); /* password age */
2369 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2370 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2371 strcpy(p2,lp_logon_path());
2372 p2 = skip_string(p2,1);
2373 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2375 SSVAL(p,52,0); /* flags */
2376 SIVAL(p,54,0); /* script_path */
2379 SIVAL(p,60,0); /* auth_flags */
2380 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2381 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2382 p2 = skip_string(p2,1);
2383 SIVAL(p,68,0); /* urs_comment */
2384 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2386 p2 = skip_string(p2,1);
2387 SIVAL(p,76,0); /* workstations */
2388 SIVAL(p,80,0); /* last_logon */
2389 SIVAL(p,84,0); /* last_logoff */
2390 SIVALS(p,88,-1); /* acct_expires */
2391 SIVALS(p,92,-1); /* max_storage */
2392 SSVAL(p,96,168); /* units_per_week */
2393 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2396 SSVALS(p,102,-1); /* bad_pw_count */
2397 SSVALS(p,104,-1); /* num_logons */
2398 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2399 strcpy(p2,"\\\\%L");
2400 standard_sub_basic(p2);
2401 p2 = skip_string(p2,1);
2402 SSVAL(p,110,49); /* country_code */
2403 SSVAL(p,112,860); /* code page */
2407 *rdata_len = PTR_DIFF(p2,*rdata);
2409 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2414 /*******************************************************************
2415 get groups that a user is a member of
2416 ******************************************************************/
2417 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2418 int mdrcnt,int mprcnt,
2419 char **rdata,char **rparam,
2420 int *rdata_len,int *rparam_len)
2422 char *str1 = param+2;
2423 char *str2 = skip_string(str1,1);
2424 char *UserName = skip_string(str2,1);
2425 char *p = skip_string(UserName,1);
2426 int uLevel = SVAL(p,0);
2431 *rparam = REALLOC(*rparam,*rparam_len);
2433 /* check it's a supported varient */
2434 if (strcmp(str1,"zWrLeh") != 0) return False;
2436 case 0: p2 = "B21"; break;
2437 default: return False;
2439 if (strcmp(p2,str2) != 0) return False;
2441 *rdata_len = mdrcnt + 1024;
2442 *rdata = REALLOC(*rdata,*rdata_len);
2444 SSVAL(*rparam,0,NERR_Success);
2445 SSVAL(*rparam,2,0); /* converter word */
2449 /* XXXX we need a real SAM database some day */
2450 strcpy(p,"Users"); p += 21; count++;
2451 strcpy(p,"Domain Users"); p += 21; count++;
2452 strcpy(p,"Guests"); p += 21; count++;
2453 strcpy(p,"Domain Guests"); p += 21; count++;
2455 *rdata_len = PTR_DIFF(p,*rdata);
2457 SSVAL(*rparam,4,count); /* is this right?? */
2458 SSVAL(*rparam,6,count); /* is this right?? */
2464 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2465 int mdrcnt,int mprcnt,
2466 char **rdata,char **rparam,
2467 int *rdata_len,int *rparam_len)
2469 char *str1 = param+2;
2470 char *str2 = skip_string(str1,1);
2471 char *p = skip_string(str2,1);
2473 struct pack_desc desc;
2480 bzero(&desc,sizeof(desc));
2482 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2484 /* check it's a supported varient */
2485 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2486 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2487 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2489 desc.buflen = mdrcnt;
2490 desc.subformat = NULL;
2493 if (init_package(&desc,1,0))
2495 PACKI(&desc,"W",0); /* code */
2496 PACKS(&desc,"B21",name); /* eff. name */
2497 PACKS(&desc,"B",""); /* pad */
2499 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2500 PACKI(&desc,"D",0); /* auth flags XXX */
2501 PACKI(&desc,"W",0); /* num logons */
2502 PACKI(&desc,"W",0); /* bad pw count */
2503 PACKI(&desc,"D",0); /* last logon */
2504 PACKI(&desc,"D",-1); /* last logoff */
2505 PACKI(&desc,"D",-1); /* logoff time */
2506 PACKI(&desc,"D",-1); /* kickoff time */
2507 PACKI(&desc,"D",0); /* password age */
2508 PACKI(&desc,"D",0); /* password can change */
2509 PACKI(&desc,"D",-1); /* password must change */
2512 strcpy(mypath,"\\\\");
2513 strcat(mypath,local_machine);
2515 PACKS(&desc,"z",mypath); /* computer */
2517 PACKS(&desc,"z",myworkgroup);/* domain */
2519 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2520 /* made sure all macros are fully substituted and available */
2521 logon_script = lp_logon_script();
2522 standard_sub( cnum, logon_script );
2523 PACKS(&desc,"z", logon_script); /* script path */
2524 /* End of JHT mods */
2526 PACKI(&desc,"D",0x00000000); /* reserved */
2529 *rdata_len = desc.usedlen;
2531 *rparam = REALLOC(*rparam,*rparam_len);
2532 SSVALS(*rparam,0,desc.errcode);
2534 SSVAL(*rparam,4,desc.neededlen);
2536 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2541 /****************************************************************************
2542 api_WAccessGetUserPerms
2543 ****************************************************************************/
2544 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2545 int mdrcnt,int mprcnt,
2546 char **rdata,char **rparam,
2547 int *rdata_len,int *rparam_len)
2549 char *str1 = param+2;
2550 char *str2 = skip_string(str1,1);
2551 char *user = skip_string(str2,1);
2552 char *resource = skip_string(user,1);
2554 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2556 /* check it's a supported varient */
2557 if (strcmp(str1,"zzh") != 0) return False;
2558 if (strcmp(str2,"") != 0) return False;
2561 *rparam = REALLOC(*rparam,*rparam_len);
2562 SSVALS(*rparam,0,0); /* errorcode */
2563 SSVAL(*rparam,2,0); /* converter word */
2564 SSVAL(*rparam,4,0x7f); /* permission flags */
2569 /****************************************************************************
2570 api_WPrintJobEnumerate
2571 ****************************************************************************/
2572 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2573 int mdrcnt,int mprcnt,
2574 char **rdata,char **rparam,
2575 int *rdata_len,int *rparam_len)
2577 char *str1 = param+2;
2578 char *str2 = skip_string(str1,1);
2579 char *p = skip_string(str2,1);
2585 struct pack_desc desc;
2586 print_queue_struct *queue=NULL;
2587 print_status_struct status;
2592 bzero(&desc,sizeof(desc));
2593 bzero(&status,sizeof(status));
2595 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2597 /* check it's a supported varient */
2598 if (strcmp(str1,"WWrLh") != 0) return False;
2599 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2601 printjob_decode(SVAL(p,0), &snum, &job);
2603 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2605 count = get_printqueue(snum,cnum,&queue,&status);
2606 for (i = 0; i < count; i++) {
2607 if ((queue[i].job & 0xFF) == job) break;
2609 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2611 desc.buflen = mdrcnt;
2613 if (init_package(&desc,1,0)) {
2615 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2616 *rdata_len = desc.usedlen;
2619 desc.errcode = NERR_JobNotFound;
2625 *rparam = REALLOC(*rparam,*rparam_len);
2626 SSVALS(*rparam,0,desc.errcode);
2628 SSVAL(*rparam,4,desc.neededlen);
2630 if (queue) free(queue);
2632 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2636 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2637 int mdrcnt,int mprcnt,
2638 char **rdata,char **rparam,
2639 int *rdata_len,int *rparam_len)
2641 char *str1 = param+2;
2642 char *str2 = skip_string(str1,1);
2643 char *p = skip_string(str2,1);
2649 struct pack_desc desc;
2650 print_queue_struct *queue=NULL;
2651 print_status_struct status;
2653 bzero(&desc,sizeof(desc));
2654 bzero(&status,sizeof(status));
2656 p = skip_string(p,1);
2660 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2662 /* check it's a supported varient */
2663 if (strcmp(str1,"zWrLeh") != 0) return False;
2664 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2665 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2667 snum = lp_servicenumber(name);
2668 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2669 int pnum = lp_servicenumber(PRINTERS_NAME);
2671 lp_add_printer(name,pnum);
2672 snum = lp_servicenumber(name);
2676 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2678 count = get_printqueue(snum,cnum,&queue,&status);
2679 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2681 desc.buflen = mdrcnt;
2683 if (init_package(&desc,count,0)) {
2685 for (i = 0; i < count; i++) {
2686 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2687 if (desc.errcode == NERR_Success) succnt = i+1;
2691 *rdata_len = desc.usedlen;
2694 *rparam = REALLOC(*rparam,*rparam_len);
2695 SSVALS(*rparam,0,desc.errcode);
2697 SSVAL(*rparam,4,succnt);
2698 SSVAL(*rparam,6,count);
2700 if (queue) free(queue);
2702 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2706 static int check_printdest_info(struct pack_desc* desc,
2707 int uLevel, char* id)
2709 desc->subformat = NULL;
2711 case 0: desc->format = "B9"; break;
2712 case 1: desc->format = "B9B21WWzW"; break;
2713 case 2: desc->format = "z"; break;
2714 case 3: desc->format = "zzzWWzzzWW"; break;
2715 default: return False;
2717 if (strcmp(desc->format,id) != 0) return False;
2721 static void fill_printdest_info(int cnum, int snum, int uLevel,
2722 struct pack_desc* desc)
2725 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2726 buf[sizeof(buf)-1] = 0;
2729 PACKS(desc,"B9",buf); /* szName */
2731 PACKS(desc,"B21",""); /* szUserName */
2732 PACKI(desc,"W",0); /* uJobId */
2733 PACKI(desc,"W",0); /* fsStatus */
2734 PACKS(desc,"z",""); /* pszStatus */
2735 PACKI(desc,"W",0); /* time */
2738 if (uLevel == 2 || uLevel == 3) {
2739 PACKS(desc,"z",buf); /* pszPrinterName */
2741 PACKS(desc,"z",""); /* pszUserName */
2742 PACKS(desc,"z",""); /* pszLogAddr */
2743 PACKI(desc,"W",0); /* uJobId */
2744 PACKI(desc,"W",0); /* fsStatus */
2745 PACKS(desc,"z",""); /* pszStatus */
2746 PACKS(desc,"z",""); /* pszComment */
2747 PACKS(desc,"z","NULL"); /* pszDrivers */
2748 PACKI(desc,"W",0); /* time */
2749 PACKI(desc,"W",0); /* pad1 */
2754 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2755 int mdrcnt,int mprcnt,
2756 char **rdata,char **rparam,
2757 int *rdata_len,int *rparam_len)
2759 char *str1 = param+2;
2760 char *str2 = skip_string(str1,1);
2761 char *p = skip_string(str2,1);
2762 char* PrinterName = p;
2764 struct pack_desc desc;
2767 bzero(&desc,sizeof(desc));
2769 p = skip_string(p,1);
2773 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2775 /* check it's a supported varient */
2776 if (strcmp(str1,"zWrLh") != 0) return False;
2777 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2779 snum = lp_servicenumber(PrinterName);
2780 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2781 int pnum = lp_servicenumber(PRINTERS_NAME);
2783 lp_add_printer(PrinterName,pnum);
2784 snum = lp_servicenumber(PrinterName);
2790 desc.errcode = NERR_DestNotFound;
2794 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2796 desc.buflen = mdrcnt;
2797 if (init_package(&desc,1,0)) {
2798 fill_printdest_info(cnum,snum,uLevel,&desc);
2800 *rdata_len = desc.usedlen;
2804 *rparam = REALLOC(*rparam,*rparam_len);
2805 SSVALS(*rparam,0,desc.errcode);
2807 SSVAL(*rparam,4,desc.neededlen);
2809 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2813 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2814 int mdrcnt,int mprcnt,
2815 char **rdata,char **rparam,
2816 int *rdata_len,int *rparam_len)
2818 char *str1 = param+2;
2819 char *str2 = skip_string(str1,1);
2820 char *p = skip_string(str2,1);
2824 struct pack_desc desc;
2825 int services = lp_numservices();
2827 bzero(&desc,sizeof(desc));
2832 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2834 /* check it's a supported varient */
2835 if (strcmp(str1,"WrLeh") != 0) return False;
2836 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2839 for (i = 0; i < services; i++)
2840 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2843 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2845 desc.buflen = mdrcnt;
2846 if (init_package(&desc,queuecnt,0)) {
2849 for (i = 0; i < services; i++) {
2850 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2851 fill_printdest_info(cnum,i,uLevel,&desc);
2853 if (desc.errcode == NERR_Success) succnt = n;
2858 *rdata_len = desc.usedlen;
2861 *rparam = REALLOC(*rparam,*rparam_len);
2862 SSVALS(*rparam,0,desc.errcode);
2864 SSVAL(*rparam,4,succnt);
2865 SSVAL(*rparam,6,queuecnt);
2867 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2871 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2872 int mdrcnt,int mprcnt,
2873 char **rdata,char **rparam,
2874 int *rdata_len,int *rparam_len)
2876 char *str1 = param+2;
2877 char *str2 = skip_string(str1,1);
2878 char *p = skip_string(str2,1);
2881 struct pack_desc desc;
2883 bzero(&desc,sizeof(desc));
2888 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2890 /* check it's a supported varient */
2891 if (strcmp(str1,"WrLeh") != 0) return False;
2892 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2894 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2896 desc.buflen = mdrcnt;
2897 if (init_package(&desc,1,0)) {
2898 PACKS(&desc,"B41","NULL");
2901 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2903 *rdata_len = desc.usedlen;
2906 *rparam = REALLOC(*rparam,*rparam_len);
2907 SSVALS(*rparam,0,desc.errcode);
2909 SSVAL(*rparam,4,succnt);
2912 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2916 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2917 int mdrcnt,int mprcnt,
2918 char **rdata,char **rparam,
2919 int *rdata_len,int *rparam_len)
2921 char *str1 = param+2;
2922 char *str2 = skip_string(str1,1);
2923 char *p = skip_string(str2,1);
2926 struct pack_desc desc;
2928 bzero(&desc,sizeof(desc));
2933 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2935 /* check it's a supported varient */
2936 if (strcmp(str1,"WrLeh") != 0) return False;
2937 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2939 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2941 desc.buflen = mdrcnt;
2943 if (init_package(&desc,1,0)) {
2944 PACKS(&desc,"B13","lpd");
2947 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2949 *rdata_len = desc.usedlen;
2952 *rparam = REALLOC(*rparam,*rparam_len);
2953 SSVALS(*rparam,0,desc.errcode);
2955 SSVAL(*rparam,4,succnt);
2958 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2962 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2963 int mdrcnt,int mprcnt,
2964 char **rdata,char **rparam,
2965 int *rdata_len,int *rparam_len)
2967 char *str1 = param+2;
2968 char *str2 = skip_string(str1,1);
2969 char *p = skip_string(str2,1);
2972 struct pack_desc desc;
2974 bzero(&desc,sizeof(desc));
2979 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2981 /* check it's a supported varient */
2982 if (strcmp(str1,"WrLeh") != 0) return False;
2983 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2985 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2986 bzero(&desc,sizeof(desc));
2988 desc.buflen = mdrcnt;
2990 if (init_package(&desc,1,0)) {
2991 PACKS(&desc,"B13","lp0");
2994 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2996 *rdata_len = desc.usedlen;
2999 *rparam = REALLOC(*rparam,*rparam_len);
3000 SSVALS(*rparam,0,desc.errcode);
3002 SSVAL(*rparam,4,succnt);
3005 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3011 char * pipe_clnt_name;
3012 char * pipe_srv_name;
3013 BOOL (*fn) (pipes_struct *, prs_struct *);
3016 static struct api_cmd api_fd_commands[] =
3018 { "lsarpc", "lsass", api_ntlsa_rpc },
3019 { "samr", "lsass", api_samr_rpc },
3020 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3021 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3022 { "NETLOGON", "lsass", api_netlog_rpc },
3023 { "winreg", "winreg", api_reg_rpc },
3024 { NULL, NULL, NULL }
3027 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3029 BOOL ntlmssp_auth = False;
3030 fstring ack_pipe_name;
3033 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3035 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3037 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3038 api_fd_commands[i].fn != NULL)
3040 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3041 api_fd_commands[i].pipe_clnt_name,
3042 api_fd_commands[i].pipe_srv_name));
3043 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3048 if (api_fd_commands[i].fn == NULL) return False;
3050 /* decode the bind request */
3051 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3053 if (pd->offset == 0) return False;
3055 if (p->hdr.auth_len != 0)
3057 /* decode the authentication verifier */
3058 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3060 if (pd->offset == 0) return False;
3062 /* ignore the version number for now */
3063 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3066 /* name has to be \PIPE\xxxxx */
3067 strcpy(ack_pipe_name, "\\PIPE\\");
3068 strcat(ack_pipe_name, p->pipe_srv_name);
3070 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3072 prs_init(&(p->rdata), 1024, 4, 0, False);
3073 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3074 prs_init(&(p->rauth), 1024, 4, 0, False);
3077 /*** do the bind ack first ***/
3080 make_rpc_hdr_ba(&p->hdr_ba,
3081 p->hdr_rb.bba.max_tsize,
3082 p->hdr_rb.bba.max_rsize,
3083 p->hdr_rb.bba.assoc_gid,
3086 &(p->hdr_rb.transfer));
3088 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3089 mem_realloc_data(p->rdata.data, p->rdata.offset);
3092 /*** now the authentication ***/
3098 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3100 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3103 0x00000000, 0x0000b2b3, 0x000082b1,
3105 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3106 mem_realloc_data(p->rauth.data, p->rauth.offset);
3110 /*** then do the header, now we know the length ***/
3113 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3115 p->rdata.offset + p->rauth.offset,
3118 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3119 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3122 /*** link rpc header, bind acknowledgment and authentication responses ***/
3125 p->rhdr.data->offset.start = 0;
3126 p->rhdr.data->offset.end = p->rhdr.offset;
3127 p->rhdr.data->next = p->rdata.data;
3131 p->rdata.data->offset.start = p->rhdr.offset;
3132 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3133 p->rdata.data->next = p->rauth.data;
3135 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3136 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3137 p->rauth.data->next = NULL;
3141 p->rdata.data->offset.start = p->rhdr.offset;
3142 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3143 p->rdata.data->next = NULL;
3149 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3153 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3155 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3156 api_fd_commands[i].fn != NULL)
3158 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3159 return api_fd_commands[i].fn(p, pd);
3165 static BOOL api_dce_rpc_command(char *outbuf,
3170 if (pd->data == NULL) return False;
3172 /* process the rpc header */
3173 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3175 if (pd->offset == 0) return False;
3177 switch (p->hdr.pkt_type)
3181 reply = api_pipe_bind_req(p, pd);
3186 reply = api_pipe_request (p, pd);
3193 /* now send the reply */
3194 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len);
3196 if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len)
3198 /* all of data was sent: no need to wait for SMBreadX calls */
3199 mem_free_data(p->rhdr .data);
3200 mem_free_data(p->rdata.data);
3207 /****************************************************************************
3208 SetNamedPipeHandleState
3209 ****************************************************************************/
3210 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3214 if (!param) return False;
3216 id = param[0] + (param[1] << 8);
3217 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3219 if (set_rpc_pipe_hnd_state(p, id))
3221 /* now send the reply */
3222 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len);
3230 /****************************************************************************
3231 when no reply is generated, indicate unsupported.
3232 ****************************************************************************/
3233 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3235 struct mem_buf rparam;
3237 mem_init(&rparam, 0);
3238 mem_alloc_data(&rparam, 4);
3240 rparam.offset.start = 0;
3241 rparam.offset.end = 4;
3244 SSVAL(rparam.data,0,NERR_notsupported);
3245 SSVAL(rparam.data,2,0); /* converter word */
3247 DEBUG(3,("Unsupported API fd command\n"));
3249 /* now send the reply */
3250 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3252 mem_free_data(&rparam);
3257 /****************************************************************************
3258 handle remote api calls delivered to a named pipe already opened.
3259 ****************************************************************************/
3260 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3261 uint16 *setup,char *data,char *params,
3262 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3268 pipes_struct *p = NULL;
3270 struct mem_buf data_buf;
3272 DEBUG(5,("api_fd_reply\n"));
3274 /* fake up a data buffer from the api_fd_reply data parameters */
3275 mem_create(&data_buf, data, tdscnt, 0, False);
3276 data_buf.offset.start = 0;
3277 data_buf.offset.end = tdscnt;
3279 /* fake up a parsing structure */
3280 pd.data = &data_buf;
3285 /* First find out the name of this file. */
3288 DEBUG(0,("Unexpected named pipe transaction.\n"));
3292 /* Get the file handle and hence the file name. */
3294 subcommand = setup[0];
3295 get_rpc_pipe(pnum, &p);
3299 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3300 subcommand, p->name, pnum));
3301 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3302 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3304 /* record maximum data length that can be transmitted in an SMBtrans */
3305 p->max_rdata_len = mdrcnt;
3311 /* dce/rpc command */
3312 reply = api_dce_rpc_command(outbuf, p, &pd);
3317 /* Set Named Pipe Handle state */
3318 reply = api_SNPHS(outbuf, p, params);
3325 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3330 return api_no_reply(outbuf, mdrcnt);
3335 /****************************************************************************
3336 the buffer was too small
3337 ****************************************************************************/
3338 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3339 int mdrcnt,int mprcnt,
3340 char **rdata,char **rparam,
3341 int *rdata_len,int *rparam_len)
3343 *rparam_len = MIN(*rparam_len,mprcnt);
3344 *rparam = REALLOC(*rparam,*rparam_len);
3348 SSVAL(*rparam,0,NERR_BufTooSmall);
3350 DEBUG(3,("Supplied buffer too small in API command\n"));
3356 /****************************************************************************
3357 the request is not supported
3358 ****************************************************************************/
3359 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3360 int mdrcnt,int mprcnt,
3361 char **rdata,char **rparam,
3362 int *rdata_len,int *rparam_len)
3365 *rparam = REALLOC(*rparam,*rparam_len);
3369 SSVAL(*rparam,0,NERR_notsupported);
3370 SSVAL(*rparam,2,0); /* converter word */
3372 DEBUG(3,("Unsupported API command\n"));
3386 } api_commands[] = {
3387 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
3388 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
3389 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
3390 {"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0},
3391 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
3392 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
3393 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
3394 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
3395 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
3396 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
3397 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
3398 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
3399 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
3400 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
3401 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
3402 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
3403 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
3404 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
3405 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
3406 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
3407 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
3408 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
3409 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
3410 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
3411 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
3412 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
3413 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
3416 /****************************************************************************
3417 handle remote api calls
3418 ****************************************************************************/
3419 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3420 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3422 int api_command = SVAL(params,0);
3423 struct mem_buf rdata_buf;
3424 struct mem_buf rparam_buf;
3426 char *rparam = NULL;
3432 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3433 api_command,params+2,skip_string(params+2,1),
3434 tdscnt,tpscnt,mdrcnt,mprcnt));
3436 for (i=0;api_commands[i].name;i++)
3437 if (api_commands[i].id == api_command && api_commands[i].fn)
3439 DEBUG(3,("Doing %s\n",api_commands[i].name));
3443 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3444 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3446 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3447 &rdata,&rparam,&rdata_len,&rparam_len);
3450 if (rdata_len > mdrcnt ||
3451 rparam_len > mprcnt)
3453 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3454 &rdata,&rparam,&rdata_len,&rparam_len);
3458 /* if we get False back then it's actually unsupported */
3460 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3461 &rdata,&rparam,&rdata_len,&rparam_len);
3464 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3465 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3467 rdata_buf.offset.start = 0;
3468 rdata_buf.offset.end = rdata_len;
3470 rparam_buf.offset.start = 0;
3471 rparam_buf.offset.end = rparam_len;
3473 /* now send the reply */
3474 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3476 if (rdata ) free(rdata);
3477 if (rparam) free(rparam);
3482 /****************************************************************************
3483 handle named pipe commands
3484 ****************************************************************************/
3485 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3486 uint16 *setup,char *data,char *params,
3487 int suwcnt,int tdscnt,int tpscnt,
3488 int msrcnt,int mdrcnt,int mprcnt)
3490 DEBUG(3,("named pipe command on <%s> name\n", name));
3492 if (strequal(name,"LANMAN"))
3494 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3497 if (strlen(name) < 1)
3499 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3504 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3511 /****************************************************************************
3513 ****************************************************************************/
3514 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3518 char *data=NULL,*params=NULL;
3522 int cnum = SVAL(inbuf,smb_tid);
3523 uint16 vuid = SVAL(inbuf,smb_uid);
3525 int tpscnt = SVAL(inbuf,smb_vwv0);
3526 int tdscnt = SVAL(inbuf,smb_vwv1);
3527 int mprcnt = SVAL(inbuf,smb_vwv2);
3528 int mdrcnt = SVAL(inbuf,smb_vwv3);
3529 int msrcnt = CVAL(inbuf,smb_vwv4);
3530 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3531 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3532 int pscnt = SVAL(inbuf,smb_vwv9);
3533 int psoff = SVAL(inbuf,smb_vwv10);
3534 int dscnt = SVAL(inbuf,smb_vwv11);
3535 int dsoff = SVAL(inbuf,smb_vwv12);
3536 int suwcnt = CVAL(inbuf,smb_vwv13);
3538 bzero(name, sizeof(name));
3539 fstrcpy(name,smb_buf(inbuf));
3541 if (dscnt > tdscnt || pscnt > tpscnt) {
3542 exit_server("invalid trans parameters\n");
3547 data = (char *)malloc(tdscnt);
3548 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3552 params = (char *)malloc(tpscnt);
3553 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3559 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3560 for (i=0;i<suwcnt;i++)
3561 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3565 if (pscnt < tpscnt || dscnt < tdscnt)
3567 /* We need to send an interim response then receive the rest
3568 of the parameter/data bytes */
3569 outsize = set_message(outbuf,0,0,True);
3571 send_smb(Client,outbuf);
3574 /* receive the rest of the trans packet */
3575 while (pscnt < tpscnt || dscnt < tdscnt)
3578 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3580 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3582 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3585 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3587 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3588 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3589 if (params) free(params);
3590 if (data) free(data);
3591 if (setup) free(setup);
3592 return(ERROR(ERRSRV,ERRerror));
3597 tpscnt = SVAL(inbuf,smb_vwv0);
3598 tdscnt = SVAL(inbuf,smb_vwv1);
3600 pcnt = SVAL(inbuf,smb_vwv2);
3601 poff = SVAL(inbuf,smb_vwv3);
3602 pdisp = SVAL(inbuf,smb_vwv4);
3604 dcnt = SVAL(inbuf,smb_vwv5);
3605 doff = SVAL(inbuf,smb_vwv6);
3606 ddisp = SVAL(inbuf,smb_vwv7);
3611 if (dscnt > tdscnt || pscnt > tpscnt) {
3612 exit_server("invalid trans parameters\n");
3616 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3618 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3622 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3624 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3626 DEBUG(5,("calling named_pipe\n"));
3627 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3628 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3632 DEBUG(3,("invalid pipe name\n"));
3637 if (data) free(data);
3638 if (params) free(params);
3639 if (setup) free(setup);
3641 if (close_on_completion)
3642 close_cnum(cnum,vuid);
3648 return(ERROR(ERRSRV,ERRnosupport));