2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
37 extern int DEBUGLEVEL;
39 extern files_struct Files[];
40 extern connection_struct Connections[];
42 extern fstring local_machine;
43 extern fstring global_myworkgroup;
45 #define NERR_Success 0
46 #define NERR_badpass 86
47 #define NERR_notsupported 50
49 #define NERR_BASE (2100)
50 #define NERR_BufTooSmall (NERR_BASE+23)
51 #define NERR_JobNotFound (NERR_BASE+51)
52 #define NERR_DestNotFound (NERR_BASE+52)
53 #define ERROR_INVALID_LEVEL 124
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;
335 p->errcode = ERROR_MORE_DATA;
338 p->errcode = NERR_Success;
341 p->stringbuf = p->base + i;
343 return(p->errcode == NERR_Success);
347 static int package(struct pack_desc* p, ...)
350 static int package(va_alist)
356 int needed=0, stringneeded;
358 int is_string=0, stringused;
365 p = va_arg(args,struct pack_desc *);
370 p->curpos = p->format;
372 p->curpos = p->subformat;
377 str = va_arg(args,char*);
378 if (strncmp(str,p->curpos,strlen(str)) != 0) {
379 DEBUG(2,("type error in package: %s instead of %*s\n",str,
380 strlen(str),p->curpos));
390 if (!p->curpos) return(0);
392 switch( *p->curpos++ ) {
393 case 'W': /* word (2 byte) */
395 temp = va_arg(args,int);
396 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
398 case 'N': /* count of substructures (word) at end */
400 p->subcount = va_arg(args,int);
401 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
403 case 'D': /* double word (4 byte) */
405 temp = va_arg(args,int);
406 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
408 case 'B': /* byte (with optional counter) */
409 needed = get_counter(&p->curpos);
411 char *s = va_arg(args,char*);
412 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
415 case 'z': /* offset to zero terminated string (4 byte) */
416 str = va_arg(args,char*);
417 stringneeded = (str ? strlen(str)+1 : 0);
420 case 'l': /* offset to user data (4 byte) */
421 str = va_arg(args,char*);
422 stringneeded = va_arg(args,int);
425 case 'b': /* offset to data (with counter) (4 byte) */
426 str = va_arg(args,char*);
427 stringneeded = get_counter(&p->curpos);
432 if (stringneeded >= 0) {
434 if (p->buflen >= needed) {
435 stringused = stringneeded;
436 if (stringused > p->stringlen) {
437 stringused = (is_string ? p->stringlen : 0);
438 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
441 SIVAL(p->structbuf,0,0);
443 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
444 memcpy(p->stringbuf,str?str:"",stringused);
445 if (is_string) p->stringbuf[stringused-1] = '\0';
446 p->stringbuf += stringused;
447 p->stringlen -= stringused;
448 p->usedlen += stringused;
451 p->neededlen += stringneeded;
453 p->neededlen += needed;
454 if (p->buflen >= needed) {
455 p->structbuf += needed;
457 p->usedlen += needed;
460 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
466 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
467 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
469 #define PACK(desc,t,v) package(desc,v)
470 #define PACKl(desc,t,v,l) package(desc,v,l)
473 static void PACKI(struct pack_desc* desc,char *t,int v)
478 static void PACKS(struct pack_desc* desc,char *t,char *v)
484 /****************************************************************************
486 ****************************************************************************/
488 static void PackDriverData(struct pack_desc* desc)
490 char drivdata[4+4+32];
491 SIVAL(drivdata,0,sizeof drivdata); /* cb */
492 SIVAL(drivdata,4,1000); /* lVersion */
493 memset(drivdata+8,0,32); /* szDeviceName */
494 strcpy(drivdata+8,"NULL");
495 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
498 static int check_printq_info(struct pack_desc* desc,
499 int uLevel, char *id1, char *id2)
501 desc->subformat = NULL;
504 desc->format = "B13";
507 desc->format = "B13BWWWzzzzzWW";
510 desc->format = "B13BWWWzzzzzWN";
511 desc->subformat = "WB21BB16B10zWWzDDz";
514 desc->format = "zWWWWzzzzWWzzl";
517 desc->format = "zWWWWzzzzWNzzl";
518 desc->subformat = "WWzWWDDzz";
524 desc->format = "WzzzzzzzzN";
525 desc->subformat = "z";
527 default: return False;
529 if (strcmp(desc->format,id1) != 0) return False;
530 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
534 static void fill_printjob_info(int cnum, int snum, int uLevel,
535 struct pack_desc* desc,
536 print_queue_struct* queue, int n)
538 time_t t = queue->time;
540 /* the client expects localtime */
543 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
545 PACKS(desc,"B21",queue->user); /* szUserName */
546 PACKS(desc,"B",""); /* pad */
547 PACKS(desc,"B16",""); /* szNotifyName */
548 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
549 PACKS(desc,"z",""); /* pszParms */
550 PACKI(desc,"W",n+1); /* uPosition */
551 PACKI(desc,"W",queue->status); /* fsStatus */
552 PACKS(desc,"z",""); /* pszStatus */
553 PACKI(desc,"D",t); /* ulSubmitted */
554 PACKI(desc,"D",queue->size); /* ulSize */
555 PACKS(desc,"z",queue->file); /* pszComment */
557 if (uLevel == 2 || uLevel == 3) {
558 PACKI(desc,"W",queue->priority); /* uPriority */
559 PACKS(desc,"z",queue->user); /* pszUserName */
560 PACKI(desc,"W",n+1); /* uPosition */
561 PACKI(desc,"W",queue->status); /* fsStatus */
562 PACKI(desc,"D",t); /* ulSubmitted */
563 PACKI(desc,"D",queue->size); /* ulSize */
564 PACKS(desc,"z","Samba"); /* pszComment */
565 PACKS(desc,"z",queue->file); /* pszDocument */
567 PACKS(desc,"z",""); /* pszNotifyName */
568 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
569 PACKS(desc,"z",""); /* pszParms */
570 PACKS(desc,"z",""); /* pszStatus */
571 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
572 PACKS(desc,"z","lpd"); /* pszQProcName */
573 PACKS(desc,"z",""); /* pszQProcParms */
574 PACKS(desc,"z","NULL"); /* pszDriverName */
575 PackDriverData(desc); /* pDriverData */
576 PACKS(desc,"z",""); /* pszPrinterName */
581 static void fill_printq_info(int cnum, int snum, int uLevel,
582 struct pack_desc* desc,
583 int count, print_queue_struct* queue,
584 print_status_struct* status)
589 PACKS(desc,"B13",SERVICE(snum));
594 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
598 if (uLevel == 1 || uLevel == 2) {
599 PACKS(desc,"B",""); /* alignment */
600 PACKI(desc,"W",5); /* priority */
601 PACKI(desc,"W",0); /* start time */
602 PACKI(desc,"W",0); /* until time */
603 PACKS(desc,"z",""); /* pSepFile */
604 PACKS(desc,"z","lpd"); /* pPrProc */
605 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
606 PACKS(desc,"z",""); /* pParms */
608 PACKS(desc,"z","UNKNOWN PRINTER");
609 PACKI(desc,"W",LPSTAT_ERROR);
611 else if (!status || !status->message[0]) {
612 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
613 PACKI(desc,"W",LPSTAT_OK); /* status */
615 PACKS(desc,"z",status->message);
616 PACKI(desc,"W",status->status); /* status */
618 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
620 if (uLevel == 3 || uLevel == 4) {
621 PACKI(desc,"W",5); /* uPriority */
622 PACKI(desc,"W",0); /* uStarttime */
623 PACKI(desc,"W",0); /* uUntiltime */
624 PACKI(desc,"W",5); /* pad1 */
625 PACKS(desc,"z",""); /* pszSepFile */
626 PACKS(desc,"z","WinPrint"); /* pszPrProc */
627 PACKS(desc,"z",""); /* pszParms */
628 if (!status || !status->message[0]) {
629 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
630 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
632 PACKS(desc,"z",status->message); /* pszComment */
633 PACKI(desc,"W",status->status); /* fsStatus */
635 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
636 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
637 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
638 PackDriverData(desc); /* pDriverData */
640 if (uLevel == 2 || uLevel == 4) {
642 for (i=0;i<count;i++)
643 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
648 pstring tok,driver,datafile,langmon,helpfile,datatype;
653 strcpy(fname,lp_driverfile());
656 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
657 desc->errcode=NERR_notsupported;
661 p=(char *)malloc(8192*sizeof(char));
662 bzero(p, 8192*sizeof(char));
665 /* lookup the long printer driver name in the file description */
666 while (f && !feof(f) && !ok)
668 p = q; /* reset string pointer */
671 if (next_token(&p,tok,":") &&
672 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
677 /* driver file name */
678 if (ok && !next_token(&p,driver,":")) ok = 0;
680 if (ok && !next_token(&p,datafile,":")) ok = 0;
682 * for the next tokens - which may be empty - I have to check for empty
683 * tokens first because the next_token function will skip all empty
691 } else if (!next_token(&p,helpfile,":")) ok = 0;
695 /* language monitor */
699 } else if (!next_token(&p,langmon,":")) ok = 0;
702 /* default data type */
703 if (ok && !next_token(&p,datatype,":")) ok = 0;
706 PACKI(desc,"W",0x0400); /* don't know */
707 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
708 PACKS(desc,"z",driver); /* Driverfile Name */
709 PACKS(desc,"z",datafile); /* Datafile name */
710 PACKS(desc,"z",langmon); /* language monitor */
711 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
712 PACKS(desc,"z",datatype); /* default data type */
713 PACKS(desc,"z",helpfile); /* helpfile name */
714 PACKS(desc,"z",driver); /* driver name */
715 DEBUG(3,("Driver:%s:\n",driver));
716 DEBUG(3,("Data File:%s:\n",datafile));
717 DEBUG(3,("Language Monitor:%s:\n",langmon));
718 DEBUG(3,("Data Type:%s:\n",datatype));
719 DEBUG(3,("Help File:%s:\n",helpfile));
720 PACKI(desc,"N",count); /* number of files to copy */
721 for (i=0;i<count;i++)
723 /* no need to check return value here - it was already tested in
724 * get_printerdrivernumber
726 next_token(&p,tok,",");
727 PACKS(desc,"z",tok); /* driver files to copy */
728 DEBUG(3,("file:%s:\n",tok));
731 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
732 SERVICE(snum),count));
734 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
735 desc->errcode=NERR_notsupported;
741 /* This function returns the number of files for a given driver */
742 int get_printerdrivernumber(int snum)
750 strcpy(fname,lp_driverfile());
752 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
755 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
759 p=(char *)malloc(8192*sizeof(char));
760 q=p; /* need it to free memory because p change ! */
762 /* lookup the long printer driver name in the file description */
763 while (!feof(f) && !ok)
765 p = q; /* reset string pointer */
767 if (next_token(&p,tok,":") &&
768 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
777 if (*p++ == ':') i--;
782 /* count the number of files */
783 while (next_token(&p,tok,","))
791 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
792 int mdrcnt,int mprcnt,
793 char **rdata,char **rparam,
794 int *rdata_len,int *rparam_len)
796 char *str1 = param+2;
797 char *str2 = skip_string(str1,1);
798 char *p = skip_string(str2,1);
804 struct pack_desc desc;
805 print_queue_struct *queue=NULL;
806 print_status_struct status;
808 bzero(&status,sizeof(status));
809 bzero(&desc,sizeof(desc));
811 p = skip_string(p,1);
816 /* remove any trailing username */
817 if ((p = strchr(QueueName,'%'))) *p = 0;
819 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
821 /* check it's a supported varient */
822 if (!prefix_ok(str1,"zWrLh")) return False;
823 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
825 snum = lp_servicenumber(QueueName);
826 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
827 int pnum = lp_servicenumber(PRINTERS_NAME);
829 lp_add_printer(QueueName,pnum);
830 snum = lp_servicenumber(QueueName);
834 if (snum < 0 || !VALID_SNUM(snum)) return(False);
838 count = get_printerdrivernumber(snum);
839 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
842 count = get_printqueue(snum,cnum,&queue,&status);
844 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
846 desc.buflen = mdrcnt;
847 if (init_package(&desc,1,count)) {
848 desc.subcount = count;
849 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
852 *rdata_len = desc.usedlen;
855 *rparam = REALLOC(*rparam,*rparam_len);
856 SSVALS(*rparam,0,desc.errcode);
858 SSVAL(*rparam,4,desc.neededlen);
860 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
862 if (queue) free(queue);
868 /****************************************************************************
869 view list of all print jobs on all queues
870 ****************************************************************************/
871 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
872 int mdrcnt, int mprcnt,
873 char **rdata, char** rparam,
874 int *rdata_len, int *rparam_len)
876 char *param_format = param+2;
877 char *output_format1 = skip_string(param_format,1);
878 char *p = skip_string(output_format1,1);
879 int uLevel = SVAL(p,0);
880 char *output_format2 = p + 4;
881 int services = lp_numservices();
883 struct pack_desc desc;
884 print_queue_struct **queue = NULL;
885 print_status_struct *status = NULL;
886 int* subcntarr = NULL;
887 int queuecnt, subcnt=0, succnt=0;
889 bzero(&desc,sizeof(desc));
891 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
893 if (!prefix_ok(param_format,"WrLeh")) return False;
894 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
897 for (i = 0; i < services; i++)
898 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
901 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
902 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
903 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
904 memset(status,0,queuecnt*sizeof(print_status_struct));
905 subcntarr = (int*)malloc(queuecnt*sizeof(int));
908 for (i = 0; i < services; i++)
909 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
910 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
911 subcnt += subcntarr[n];
915 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
917 desc.buflen = mdrcnt;
919 if (init_package(&desc,queuecnt,subcnt)) {
922 for (i = 0; i < services; i++)
923 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
924 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
926 if (desc.errcode == NERR_Success) succnt = n;
930 if (subcntarr) free(subcntarr);
932 *rdata_len = desc.usedlen;
934 *rparam = REALLOC(*rparam,*rparam_len);
935 SSVALS(*rparam,0,desc.errcode);
937 SSVAL(*rparam,4,succnt);
938 SSVAL(*rparam,6,queuecnt);
940 for (i = 0; i < queuecnt; i++) {
941 if (queue && queue[i]) free(queue[i]);
944 if (queue) free(queue);
945 if (status) free(status);
950 /****************************************************************************
951 get info level for a server list query
952 ****************************************************************************/
953 static BOOL check_server_info(int uLevel, char* id)
957 if (strcmp(id,"B16") != 0) return False;
960 if (strcmp(id,"B16BBDz") != 0) return False;
968 struct srv_info_struct
978 /*******************************************************************
979 get server info lists from the files saved by nmbd. Return the
981 ******************************************************************/
982 static int get_server_info(uint32 servertype,
983 struct srv_info_struct **servers,
991 BOOL local_list_only;
993 pstrcpy(fname,lp_lockdir());
994 trim_string(fname,NULL,"/");
996 strcat(fname,SERVER_LIST);
998 f = fopen(fname,"r");
1001 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1005 /* request for everything is code for request all servers */
1006 if (servertype == SV_TYPE_ALL)
1007 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1009 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1011 DEBUG(4,("Servertype search: %8x\n",servertype));
1016 struct srv_info_struct *s;
1021 fgets(line,sizeof(line)-1,f);
1022 if (!*line) continue;
1024 if (count == alloced) {
1026 (*servers) = (struct srv_info_struct *)
1027 Realloc(*servers,sizeof(**servers)*alloced);
1028 if (!(*servers)) return(0);
1029 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1031 s = &(*servers)[count];
1033 if (!next_token(&ptr,s->name , NULL)) continue;
1034 if (!next_token(&ptr,stype , NULL)) continue;
1035 if (!next_token(&ptr,s->comment, NULL)) continue;
1036 if (!next_token(&ptr,s->domain , NULL)) {
1037 /* this allows us to cope with an old nmbd */
1038 strcpy(s->domain,global_myworkgroup);
1041 if (sscanf(stype,"%X",&s->type) != 1) {
1042 DEBUG(4,("r:host file "));
1046 /* Filter the servers/domains we return based on what was asked for. */
1048 /* Check to see if we are being asked for a local list only. */
1049 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1050 DEBUG(4,("r: local list only"));
1054 /* doesn't match up: don't want it */
1055 if (!(servertype & s->type)) {
1056 DEBUG(4,("r:serv type "));
1060 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1061 (s->type & SV_TYPE_DOMAIN_ENUM))
1063 DEBUG(4,("s: dom mismatch "));
1067 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1072 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1073 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1077 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1078 s->name, s->type, s->comment, s->domain));
1080 s->server_added = True;
1085 DEBUG(4,("%20s %8x %25s %15s\n",
1086 s->name, s->type, s->comment, s->domain));
1095 /*******************************************************************
1096 fill in a server info structure
1097 ******************************************************************/
1098 static int fill_srv_info(struct srv_info_struct *service,
1099 int uLevel, char **buf, int *buflen,
1100 char **stringbuf, int *stringspace, char *baseaddr)
1109 case 0: struct_len = 16; break;
1110 case 1: struct_len = 26; break;
1120 len = strlen(service->comment)+1;
1124 if (buflen) *buflen = struct_len;
1125 if (stringspace) *stringspace = len;
1126 return struct_len + len;
1131 if (*buflen < struct_len) return -1;
1139 p2 = p + struct_len;
1140 l2 = *buflen - struct_len;
1142 if (!baseaddr) baseaddr = p;
1147 StrnCpy(p,service->name,15);
1151 StrnCpy(p,service->name,15);
1152 SIVAL(p,18,service->type);
1153 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1154 len += CopyAndAdvance(&p2,service->comment,&l2);
1160 *buf = p + struct_len;
1161 *buflen -= struct_len;
1174 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1176 return(strcmp(s1->name,s2->name));
1179 /****************************************************************************
1180 view list of servers available (or possibly domains). The info is
1181 extracted from lists saved by nmbd on the local host
1182 ****************************************************************************/
1183 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1184 int mdrcnt, int mprcnt, char **rdata,
1185 char **rparam, int *rdata_len, int *rparam_len)
1187 char *str1 = param+2;
1188 char *str2 = skip_string(str1,1);
1189 char *p = skip_string(str2,1);
1190 int uLevel = SVAL(p,0);
1191 int buf_len = SVAL(p,2);
1192 uint32 servertype = IVAL(p,4);
1194 int data_len, fixed_len, string_len;
1195 int f_len = 0, s_len = 0;
1196 struct srv_info_struct *servers=NULL;
1197 int counted=0,total=0;
1200 BOOL domain_request;
1203 /* If someone sets all the bits they don't really mean to set
1204 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1207 if (servertype == SV_TYPE_ALL)
1208 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1210 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1211 any other bit (they may just set this bit on it's own) they
1212 want all the locally seen servers. However this bit can be
1213 set on its own so set the requested servers to be
1214 ALL - DOMAIN_ENUM. */
1216 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1217 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1219 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1220 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1224 if (!prefix_ok(str1,"WrLehD")) return False;
1225 if (!check_server_info(uLevel,str2)) return False;
1227 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1228 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1229 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1231 if (strcmp(str1, "WrLehDz") == 0) {
1232 StrnCpy(domain, p, sizeof(fstring)-1);
1234 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1237 if (lp_browse_list())
1238 total = get_server_info(servertype,&servers,domain);
1240 data_len = fixed_len = string_len = 0;
1243 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1246 char *lastname=NULL;
1248 for (i=0;i<total;i++)
1250 struct srv_info_struct *s = &servers[i];
1251 if (lastname && strequal(lastname,s->name)) continue;
1253 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1254 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1255 s->name, s->type, s->comment, s->domain));
1257 if (data_len <= buf_len) {
1260 string_len += s_len;
1267 *rdata_len = fixed_len + string_len;
1268 *rdata = REALLOC(*rdata,*rdata_len);
1269 bzero(*rdata,*rdata_len);
1271 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1277 char *lastname=NULL;
1278 int count2 = counted;
1279 for (i = 0; i < total && count2;i++)
1281 struct srv_info_struct *s = &servers[i];
1282 if (lastname && strequal(lastname,s->name)) continue;
1284 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1285 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1286 s->name, s->type, s->comment, s->domain));
1292 *rparam = REALLOC(*rparam,*rparam_len);
1293 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1295 SSVAL(*rparam,4,counted);
1296 SSVAL(*rparam,6,counted+missed);
1298 if (servers) free(servers);
1300 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1301 domain,uLevel,counted,counted+missed));
1306 /****************************************************************************
1307 command 0x34 - suspected of being a "Lookup Names" stub api
1308 ****************************************************************************/
1309 static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data,
1310 int mdrcnt, int mprcnt, char **rdata,
1311 char **rparam, int *rdata_len, int *rparam_len)
1313 char *str1 = param+2;
1314 char *str2 = skip_string(str1,1);
1315 char *p = skip_string(str2,1);
1316 int uLevel = SVAL(p,0);
1317 int buf_len = SVAL(p,2);
1321 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1322 str1, str2, p, uLevel, buf_len));
1324 if (!prefix_ok(str1,"zWrLeh")) return False;
1330 *rparam = REALLOC(*rparam,*rparam_len);
1332 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1334 SSVAL(*rparam,4,counted);
1335 SSVAL(*rparam,6,counted+missed);
1340 /****************************************************************************
1341 get info about a share
1342 ****************************************************************************/
1343 static BOOL check_share_info(int uLevel, char* id)
1347 if (strcmp(id,"B13") != 0) return False;
1350 if (strcmp(id,"B13BWz") != 0) return False;
1353 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1356 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1358 default: return False;
1363 static int fill_share_info(int cnum, int snum, int uLevel,
1364 char** buf, int* buflen,
1365 char** stringbuf, int* stringspace, char* baseaddr)
1374 case 0: struct_len = 13; break;
1375 case 1: struct_len = 20; break;
1376 case 2: struct_len = 40; break;
1377 case 91: struct_len = 68; break;
1385 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1386 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1387 if (buflen) *buflen = struct_len;
1388 if (stringspace) *stringspace = len;
1389 return struct_len + len;
1394 if ((*buflen) < struct_len) return -1;
1402 p2 = p + struct_len;
1403 l2 = (*buflen) - struct_len;
1405 if (!baseaddr) baseaddr = p;
1407 StrnCpy(p,lp_servicename(snum),13);
1413 type = STYPE_DISKTREE;
1414 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1415 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1416 SSVAL(p,14,type); /* device type */
1417 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1418 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1423 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1424 SSVALS(p,22,-1); /* max uses */
1425 SSVAL(p,24,1); /* current uses */
1426 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1427 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1428 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1433 memset(p+40,0,SHPWLEN+2);
1445 (*buf) = p + struct_len;
1446 (*buflen) -= struct_len;
1448 (*stringspace) = l2;
1458 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1459 int mdrcnt,int mprcnt,
1460 char **rdata,char **rparam,
1461 int *rdata_len,int *rparam_len)
1463 char *str1 = param+2;
1464 char *str2 = skip_string(str1,1);
1465 char *netname = skip_string(str2,1);
1466 char *p = skip_string(netname,1);
1467 int uLevel = SVAL(p,0);
1468 int snum = find_service(netname);
1470 if (snum < 0) return False;
1472 /* check it's a supported varient */
1473 if (!prefix_ok(str1,"zWrLh")) return False;
1474 if (!check_share_info(uLevel,str2)) return False;
1476 *rdata = REALLOC(*rdata,mdrcnt);
1478 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1479 if (*rdata_len < 0) return False;
1482 *rparam = REALLOC(*rparam,*rparam_len);
1483 SSVAL(*rparam,0,NERR_Success);
1484 SSVAL(*rparam,2,0); /* converter word */
1485 SSVAL(*rparam,4,*rdata_len);
1490 /****************************************************************************
1491 view list of shares available
1492 ****************************************************************************/
1493 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1494 int mdrcnt,int mprcnt,
1495 char **rdata,char **rparam,
1496 int *rdata_len,int *rparam_len)
1498 char *str1 = param+2;
1499 char *str2 = skip_string(str1,1);
1500 char *p = skip_string(str2,1);
1501 int uLevel = SVAL(p,0);
1502 int buf_len = SVAL(p,2);
1504 int count=lp_numservices();
1505 int total=0,counted=0;
1507 int data_len, fixed_len, string_len;
1508 int f_len = 0, s_len = 0;
1510 if (!prefix_ok(str1,"WrLeh")) return False;
1511 if (!check_share_info(uLevel,str2)) return False;
1513 data_len = fixed_len = string_len = 0;
1514 for (i=0;i<count;i++)
1515 if (lp_browseable(i) && lp_snum_ok(i))
1518 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1519 if (data_len <= buf_len)
1523 string_len += s_len;
1526 *rdata_len = fixed_len + string_len;
1527 *rdata = REALLOC(*rdata,*rdata_len);
1528 memset(*rdata,0,*rdata_len);
1530 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1534 for (i = 0; i < count;i++)
1535 if (lp_browseable(i) && lp_snum_ok(i))
1536 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1540 *rparam = REALLOC(*rparam,*rparam_len);
1541 SSVAL(*rparam,0,NERR_Success);
1543 SSVAL(*rparam,4,counted);
1544 SSVAL(*rparam,6,total);
1546 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1547 counted,total,uLevel,
1548 buf_len,*rdata_len,mdrcnt));
1554 /****************************************************************************
1555 get the time of day info
1556 ****************************************************************************/
1557 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1558 int mdrcnt,int mprcnt,
1559 char **rdata,char **rparam,
1560 int *rdata_len,int *rparam_len)
1564 *rparam = REALLOC(*rparam,*rparam_len);
1567 *rdata = REALLOC(*rdata,*rdata_len);
1569 SSVAL(*rparam,0,NERR_Success);
1570 SSVAL(*rparam,2,0); /* converter word */
1576 time_t unixdate = time(NULL);
1578 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1579 by NT in a "net time" operation,
1580 it seems to ignore the one below */
1582 /* the client expects to get localtime, not GMT, in this bit
1583 (I think, this needs testing) */
1584 t = LocalTime(&unixdate);
1586 SIVAL(p,4,0); /* msecs ? */
1587 CVAL(p,8) = t->tm_hour;
1588 CVAL(p,9) = t->tm_min;
1589 CVAL(p,10) = t->tm_sec;
1590 CVAL(p,11) = 0; /* hundredths of seconds */
1591 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1592 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1593 CVAL(p,16) = t->tm_mday;
1594 CVAL(p,17) = t->tm_mon + 1;
1595 SSVAL(p,18,1900+t->tm_year);
1596 CVAL(p,20) = t->tm_wday;
1603 /****************************************************************************
1604 set the user password
1605 ****************************************************************************/
1606 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1607 int mdrcnt,int mprcnt,
1608 char **rdata,char **rparam,
1609 int *rdata_len,int *rparam_len)
1611 char *p = skip_string(param+2,2);
1613 fstring pass1,pass2;
1617 p = skip_string(p,1);
1620 memcpy(pass2,p+16,16);
1623 *rparam = REALLOC(*rparam,*rparam_len);
1627 SSVAL(*rparam,0,NERR_badpass);
1628 SSVAL(*rparam,2,0); /* converter word */
1630 DEBUG(3,("Set password for <%s>\n",user));
1633 * Attempt the plaintext password change first.
1634 * Older versions of Windows seem to do this.
1637 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1638 chgpasswd(user,pass1,pass2,False))
1640 SSVAL(*rparam,0,NERR_Success);
1644 * If the plaintext change failed, attempt
1645 * the encrypted. NT will generate this
1646 * after trying the samr method.
1649 if(SVAL(*rparam,0) != NERR_Success)
1651 struct smb_passwd *smbpw = NULL;
1653 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &smbpw) &&
1654 change_lanman_password(smbpw,(unsigned char *)pass1,(unsigned char *)pass2))
1656 SSVAL(*rparam,0,NERR_Success);
1660 bzero(pass1,sizeof(fstring));
1661 bzero(pass2,sizeof(fstring));
1666 /****************************************************************************
1667 Set the user password (SamOEM version - gets plaintext).
1668 ****************************************************************************/
1670 static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
1671 int mdrcnt,int mprcnt,
1672 char **rdata,char **rparam,
1673 int *rdata_len,int *rparam_len)
1677 struct smb_passwd *smbpw = NULL;
1678 char *p = param + 2;
1681 *rparam = REALLOC(*rparam,*rparam_len);
1685 SSVAL(*rparam,0,NERR_badpass);
1688 * Check the parameter definition is correct.
1690 if(!strequal(param + 2, "zsT")) {
1691 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1694 p = skip_string(p, 1);
1696 if(!strequal(p, "B516B16")) {
1697 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1700 p = skip_string(p,1);
1703 p = skip_string(p,1);
1705 if(check_oem_password( user, (unsigned char *)data, &smbpw,
1706 new_passwd, (int)sizeof(new_passwd)) == False) {
1711 * At this point we have the new case-sensitive plaintext
1712 * password in the fstring new_passwd. If we wanted to synchronise
1713 * with UNIX passwords we would call a UNIX password changing
1714 * function here. However it would have to be done as root
1715 * as the plaintext of the old users password is not
1719 if(lp_unix_password_sync())
1720 chgpasswd(user,"", new_passwd, True);
1722 if(change_oem_password( smbpw, new_passwd)) {
1723 SSVAL(*rparam,0,NERR_Success);
1729 /****************************************************************************
1732 ****************************************************************************/
1733 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1734 int mdrcnt,int mprcnt,
1735 char **rdata,char **rparam,
1736 int *rdata_len,int *rparam_len)
1738 int function = SVAL(param,0);
1739 char *str1 = param+2;
1740 char *str2 = skip_string(str1,1);
1741 char *p = skip_string(str2,1);
1745 printjob_decode(SVAL(p,0), &snum, &jobid);
1747 /* check it's a supported varient */
1748 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1752 *rparam = REALLOC(*rparam,*rparam_len);
1756 SSVAL(*rparam,0,NERR_Success);
1758 if (snum >= 0 && VALID_SNUM(snum))
1760 print_queue_struct *queue=NULL;
1762 count = get_printqueue(snum,cnum,&queue,NULL);
1764 for (i=0;i<count;i++)
1765 if ((queue[i].job&0xFF) == jobid)
1768 case 81: /* delete */
1769 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1770 del_printqueue(cnum,snum,queue[i].job);
1772 case 82: /* pause */
1773 case 83: /* resume */
1774 DEBUG(3,("%s queue entry %d\n",
1775 (function==82?"pausing":"resuming"),queue[i].job));
1776 status_printjob(cnum,snum,queue[i].job,
1777 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1784 SSVAL(*rparam,0,NERR_JobNotFound);
1786 if (queue) free(queue);
1789 SSVAL(*rparam,2,0); /* converter word */
1794 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1795 int mdrcnt,int mprcnt,
1796 char **rdata,char **rparam,
1797 int *rdata_len,int *rparam_len)
1799 char *str1 = param+2;
1800 char *str2 = skip_string(str1,1);
1801 char *QueueName = skip_string(str2,1);
1804 /* check it's a supported varient */
1805 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1809 *rparam = REALLOC(*rparam,*rparam_len);
1813 SSVAL(*rparam,0,NERR_Success);
1814 SSVAL(*rparam,2,0); /* converter word */
1816 snum = lp_servicenumber(QueueName);
1817 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1818 int pnum = lp_servicenumber(PRINTERS_NAME);
1820 lp_add_printer(QueueName,pnum);
1821 snum = lp_servicenumber(QueueName);
1825 if (snum >= 0 && VALID_SNUM(snum)) {
1826 print_queue_struct *queue=NULL;
1830 count = get_printqueue(snum,cnum,&queue,NULL);
1831 for (i = 0; i < count; i++)
1832 del_printqueue(cnum,snum,queue[i].job);
1834 if (queue) free(queue);
1837 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1843 /****************************************************************************
1844 set the property of a print job (undocumented?)
1845 ? function = 0xb -> set name of print job
1846 ? function = 0x6 -> move print job up/down
1847 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1848 or <WWsTP> <WB21BB16B10zWWzDDz>
1849 ****************************************************************************/
1850 static int check_printjob_info(struct pack_desc* desc,
1851 int uLevel, char* id)
1853 desc->subformat = NULL;
1855 case 0: desc->format = "W"; break;
1856 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1857 case 2: desc->format = "WWzWWDDzz"; break;
1858 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1859 default: return False;
1861 if (strcmp(desc->format,id) != 0) return False;
1865 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1866 int mdrcnt,int mprcnt,
1867 char **rdata,char **rparam,
1868 int *rdata_len,int *rparam_len)
1870 struct pack_desc desc;
1871 char *str1 = param+2;
1872 char *str2 = skip_string(str1,1);
1873 char *p = skip_string(str2,1);
1875 int uLevel = SVAL(p,2);
1876 int function = SVAL(p,4); /* what is this ?? */
1880 printjob_decode(SVAL(p,0), &snum, &jobid);
1883 *rparam = REALLOC(*rparam,*rparam_len);
1887 /* check it's a supported varient */
1888 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1892 case 0x6: /* change job place in the queue, data gives the new place */
1893 if (snum >= 0 && VALID_SNUM(snum))
1895 print_queue_struct *queue=NULL;
1899 count = get_printqueue(snum,cnum,&queue,NULL);
1900 for (i=0;i<count;i++) /* find job */
1901 if ((queue[i].job&0xFF) == jobid) break;
1904 desc.errcode=NERR_JobNotFound;
1905 if (queue) free(queue);
1908 desc.errcode=NERR_Success;
1912 int place= SVAL(data,0);
1913 /* we currently have no way of doing this. Can any unix do it? */
1914 if (i < place) /* move down */;
1915 else if (i > place ) /* move up */;
1918 desc.errcode=NERR_notsupported; /* not yet supported */
1919 if (queue) free(queue);
1922 else desc.errcode=NERR_JobNotFound;
1924 case 0xb: /* change print job name, data gives the name */
1925 /* jobid, snum should be zero */
1932 if (issafe(*s)) name[l++] = *s;
1937 DEBUG(3,("Setting print name to %s\n",name));
1941 for (i=0;i<MAX_OPEN_FILES;i++)
1942 if (Files[i].open && Files[i].print_file)
1945 int fcnum = Files[i].cnum;
1949 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1950 !become_service(fcnum,True))
1953 if (sys_rename(Files[i].name,name) == 0)
1954 string_set(&Files[i].name,name);
1958 unbecome_root(True);
1960 desc.errcode=NERR_Success;
1963 default: /* not implemented */
1967 SSVALS(*rparam,0,desc.errcode);
1968 SSVAL(*rparam,2,0); /* converter word */
1974 /****************************************************************************
1975 get info about the server
1976 ****************************************************************************/
1977 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1978 int mdrcnt,int mprcnt,
1979 char **rdata,char **rparam,
1980 int *rdata_len,int *rparam_len)
1982 char *str1 = param+2;
1983 char *str2 = skip_string(str1,1);
1984 char *p = skip_string(str2,1);
1985 int uLevel = SVAL(p,0);
1989 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1991 /* check it's a supported varient */
1992 if (!prefix_ok(str1,"WrLh")) return False;
1995 if (strcmp(str2,"B16") != 0) return False;
1999 if (strcmp(str2,"B16BBDz") != 0) return False;
2003 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2008 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2013 if (strcmp(str2,"DN") != 0) return False;
2017 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2020 default: return False;
2023 *rdata_len = mdrcnt;
2024 *rdata = REALLOC(*rdata,*rdata_len);
2027 p2 = p + struct_len;
2029 StrnCpy(p,local_machine,16);
2035 struct srv_info_struct *servers=NULL;
2038 uint32 servertype= lp_default_server_announce();
2040 pstrcpy(comment,lp_serverstring());
2042 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2043 for (i=0;i<count;i++)
2044 if (strequal(servers[i].name,local_machine))
2046 servertype = servers[i].type;
2047 pstrcpy(comment,servers[i].comment);
2050 if (servers) free(servers);
2052 SCVAL(p,0,lp_major_announce_version());
2053 SCVAL(p,1,lp_minor_announce_version());
2054 SIVAL(p,2,servertype);
2056 if (mdrcnt == struct_len) {
2059 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2060 standard_sub(cnum,comment);
2061 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2062 p2 = skip_string(p2,1);
2067 return False; /* not yet implemented */
2070 *rdata_len = PTR_DIFF(p2,*rdata);
2073 *rparam = REALLOC(*rparam,*rparam_len);
2074 SSVAL(*rparam,0,NERR_Success);
2075 SSVAL(*rparam,2,0); /* converter word */
2076 SSVAL(*rparam,4,*rdata_len);
2082 /****************************************************************************
2083 get info about the server
2084 ****************************************************************************/
2085 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
2086 int mdrcnt,int mprcnt,
2087 char **rdata,char **rparam,
2088 int *rdata_len,int *rparam_len)
2090 char *str1 = param+2;
2091 char *str2 = skip_string(str1,1);
2092 char *p = skip_string(str2,1);
2094 extern pstring sesssetup_user;
2095 int level = SVAL(p,0);
2097 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2100 *rparam = REALLOC(*rparam,*rparam_len);
2102 /* check it's a supported varient */
2103 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2106 *rdata_len = mdrcnt + 1024;
2107 *rdata = REALLOC(*rdata,*rdata_len);
2109 SSVAL(*rparam,0,NERR_Success);
2110 SSVAL(*rparam,2,0); /* converter word */
2116 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2117 strcpy(p2,local_machine);
2119 p2 = skip_string(p2,1);
2122 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2123 strcpy(p2,sesssetup_user);
2124 p2 = skip_string(p2,1);
2127 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2128 strcpy(p2,global_myworkgroup);
2130 p2 = skip_string(p2,1);
2133 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2134 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2137 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2138 strcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2139 p2 = skip_string(p2,1);
2142 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2144 p2 = skip_string(p2,1);
2147 *rdata_len = PTR_DIFF(p2,*rdata);
2149 SSVAL(*rparam,4,*rdata_len);
2154 /****************************************************************************
2155 get info about a user
2157 struct user_info_11 {
2158 char usri11_name[21]; 0-20
2160 char *usri11_comment; 22-25
2161 char *usri11_usr_comment; 26-29
2162 unsigned short usri11_priv; 30-31
2163 unsigned long usri11_auth_flags; 32-35
2164 long usri11_password_age; 36-39
2165 char *usri11_homedir; 40-43
2166 char *usri11_parms; 44-47
2167 long usri11_last_logon; 48-51
2168 long usri11_last_logoff; 52-55
2169 unsigned short usri11_bad_pw_count; 56-57
2170 unsigned short usri11_num_logons; 58-59
2171 char *usri11_logon_server; 60-63
2172 unsigned short usri11_country_code; 64-65
2173 char *usri11_workstations; 66-69
2174 unsigned long usri11_max_storage; 70-73
2175 unsigned short usri11_units_per_week; 74-75
2176 unsigned char *usri11_logon_hours; 76-79
2177 unsigned short usri11_code_page; 80-81
2182 usri11_name specifies the user name for which information is retireved
2184 usri11_pad aligns the next data structure element to a word boundary
2186 usri11_comment is a null terminated ASCII comment
2188 usri11_user_comment is a null terminated ASCII comment about the user
2190 usri11_priv specifies the level of the privilege assigned to the user.
2191 The possible values are:
2193 Name Value Description
2194 USER_PRIV_GUEST 0 Guest privilege
2195 USER_PRIV_USER 1 User privilege
2196 USER_PRV_ADMIN 2 Administrator privilege
2198 usri11_auth_flags specifies the account operator privileges. The
2199 possible values are:
2201 Name Value Description
2202 AF_OP_PRINT 0 Print operator
2205 Leach, Naik [Page 28]
\r\f
2208 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2211 AF_OP_COMM 1 Communications operator
2212 AF_OP_SERVER 2 Server operator
2213 AF_OP_ACCOUNTS 3 Accounts operator
2216 usri11_password_age specifies how many seconds have elapsed since the
2217 password was last changed.
2219 usri11_home_dir points to a null terminated ASCII string that contains
2220 the path name of the user's home directory.
2222 usri11_parms points to a null terminated ASCII string that is set
2223 aside for use by applications.
2225 usri11_last_logon specifies the time when the user last logged on.
2226 This value is stored as the number of seconds elapsed since
2227 00:00:00, January 1, 1970.
2229 usri11_last_logoff specifies the time when the user last logged off.
2230 This value is stored as the number of seconds elapsed since
2231 00:00:00, January 1, 1970. A value of 0 means the last logoff
2234 usri11_bad_pw_count specifies the number of incorrect passwords
2235 entered since the last successful logon.
2237 usri11_log1_num_logons specifies the number of times this user has
2238 logged on. A value of -1 means the number of logons is unknown.
2240 usri11_logon_server points to a null terminated ASCII string that
2241 contains the name of the server to which logon requests are sent.
2242 A null string indicates logon requests should be sent to the
2245 usri11_country_code specifies the country code for the user's language
2248 usri11_workstations points to a null terminated ASCII string that
2249 contains the names of workstations the user may log on from.
2250 There may be up to 8 workstations, with the names separated by
2251 commas. A null strings indicates there are no restrictions.
2253 usri11_max_storage specifies the maximum amount of disk space the user
2254 can occupy. A value of 0xffffffff indicates there are no
2257 usri11_units_per_week specifies the equal number of time units into
2258 which a week is divided. This value must be equal to 168.
2260 usri11_logon_hours points to a 21 byte (168 bits) string that
2261 specifies the time during which the user can log on. Each bit
2262 represents one unique hour in a week. The first bit (bit 0, word
2263 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2267 Leach, Naik [Page 29]
\r\f
2270 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2273 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2274 are no restrictions.
2276 usri11_code_page specifies the code page for the user's language of
2279 All of the pointers in this data structure need to be treated
2280 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2281 to be ignored. The converter word returned in the parameters section
2282 needs to be subtracted from the lower 16 bits to calculate an offset
2283 into the return buffer where this ASCII string resides.
2285 There is no auxiliary data in the response.
2287 ****************************************************************************/
2289 #define usri11_name 0
2290 #define usri11_pad 21
2291 #define usri11_comment 22
2292 #define usri11_usr_comment 26
2293 #define usri11_full_name 30
2294 #define usri11_priv 34
2295 #define usri11_auth_flags 36
2296 #define usri11_password_age 40
2297 #define usri11_homedir 44
2298 #define usri11_parms 48
2299 #define usri11_last_logon 52
2300 #define usri11_last_logoff 56
2301 #define usri11_bad_pw_count 60
2302 #define usri11_num_logons 62
2303 #define usri11_logon_server 64
2304 #define usri11_country_code 68
2305 #define usri11_workstations 70
2306 #define usri11_max_storage 74
2307 #define usri11_units_per_week 78
2308 #define usri11_logon_hours 80
2309 #define usri11_code_page 84
2310 #define usri11_end 86
2312 #define USER_PRIV_GUEST 0
2313 #define USER_PRIV_USER 1
2314 #define USER_PRIV_ADMIN 2
2316 #define AF_OP_PRINT 0
2317 #define AF_OP_COMM 1
2318 #define AF_OP_SERVER 2
2319 #define AF_OP_ACCOUNTS 3
2322 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2323 int mdrcnt,int mprcnt,
2324 char **rdata,char **rparam,
2325 int *rdata_len,int *rparam_len)
2327 char *str1 = param+2;
2328 char *str2 = skip_string(str1,1);
2329 char *UserName = skip_string(str2,1);
2330 char *p = skip_string(UserName,1);
2331 int uLevel = SVAL(p,0);
2334 /* get NIS home of a previously validated user - simeon */
2335 /* With share level security vuid will always be zero.
2336 Don't depend on vuser being non-null !!. JRA */
2337 user_struct *vuser = get_valid_user_struct(vuid);
2339 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2342 *rparam = REALLOC(*rparam,*rparam_len);
2344 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2346 /* check it's a supported variant */
2347 if (strcmp(str1,"zWrLh") != 0) return False;
2350 case 0: p2 = "B21"; break;
2351 case 1: p2 = "B21BB16DWzzWz"; break;
2352 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2353 case 10: p2 = "B21Bzzz"; break;
2354 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2355 default: return False;
2358 if (strcmp(p2,str2) != 0) return False;
2360 *rdata_len = mdrcnt + 1024;
2361 *rdata = REALLOC(*rdata,*rdata_len);
2363 SSVAL(*rparam,0,NERR_Success);
2364 SSVAL(*rparam,2,0); /* converter word */
2367 p2 = p + usri11_end;
2370 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2374 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2379 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2380 strcpy(p2,"Comment");
2381 p2 = skip_string(p2,1);
2383 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2384 strcpy(p2,"UserComment");
2385 p2 = skip_string(p2,1);
2387 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2388 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2389 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2390 p2 = skip_string(p2,1);
2393 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2395 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2396 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2397 SIVALS(p,usri11_password_age,-1); /* password age */
2398 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2399 strcpy(p2, lp_logon_path());
2400 p2 = skip_string(p2,1);
2401 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2403 p2 = skip_string(p2,1);
2404 SIVAL(p,usri11_last_logon,0); /* last logon */
2405 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2406 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2407 SSVALS(p,usri11_num_logons,-1); /* num logons */
2408 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2410 p2 = skip_string(p2,1);
2411 SSVAL(p,usri11_country_code,0); /* country code */
2413 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2415 p2 = skip_string(p2,1);
2417 SIVALS(p,usri11_max_storage,-1); /* max storage */
2418 SSVAL(p,usri11_units_per_week,168); /* units per week */
2419 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2421 /* a simple way to get logon hours at all times. */
2423 SCVAL(p2,21,0); /* fix zero termination */
2424 p2 = skip_string(p2,1);
2426 SSVAL(p,usri11_code_page,0); /* code page */
2428 if (uLevel == 1 || uLevel == 2)
2430 memset(p+22,' ',16); /* password */
2431 SIVALS(p,38,-1); /* password age */
2433 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2434 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2435 strcpy(p2,lp_logon_path());
2436 p2 = skip_string(p2,1);
2437 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2439 SSVAL(p,52,0); /* flags */
2440 SIVAL(p,54,0); /* script_path */
2443 SIVAL(p,60,0); /* auth_flags */
2444 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2445 strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2446 p2 = skip_string(p2,1);
2447 SIVAL(p,68,0); /* urs_comment */
2448 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2450 p2 = skip_string(p2,1);
2451 SIVAL(p,76,0); /* workstations */
2452 SIVAL(p,80,0); /* last_logon */
2453 SIVAL(p,84,0); /* last_logoff */
2454 SIVALS(p,88,-1); /* acct_expires */
2455 SIVALS(p,92,-1); /* max_storage */
2456 SSVAL(p,96,168); /* units_per_week */
2457 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2460 SSVALS(p,102,-1); /* bad_pw_count */
2461 SSVALS(p,104,-1); /* num_logons */
2462 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2463 strcpy(p2,"\\\\%L");
2464 standard_sub_basic(p2);
2465 p2 = skip_string(p2,1);
2466 SSVAL(p,110,49); /* country_code */
2467 SSVAL(p,112,860); /* code page */
2471 *rdata_len = PTR_DIFF(p2,*rdata);
2473 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2478 /*******************************************************************
2479 get groups that a user is a member of
2480 ******************************************************************/
2481 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2482 int mdrcnt,int mprcnt,
2483 char **rdata,char **rparam,
2484 int *rdata_len,int *rparam_len)
2486 char *str1 = param+2;
2487 char *str2 = skip_string(str1,1);
2488 char *UserName = skip_string(str2,1);
2489 char *p = skip_string(UserName,1);
2490 int uLevel = SVAL(p,0);
2495 *rparam = REALLOC(*rparam,*rparam_len);
2497 /* check it's a supported varient */
2498 if (strcmp(str1,"zWrLeh") != 0) return False;
2500 case 0: p2 = "B21"; break;
2501 default: return False;
2503 if (strcmp(p2,str2) != 0) return False;
2505 *rdata_len = mdrcnt + 1024;
2506 *rdata = REALLOC(*rdata,*rdata_len);
2508 SSVAL(*rparam,0,NERR_Success);
2509 SSVAL(*rparam,2,0); /* converter word */
2513 /* XXXX we need a real SAM database some day */
2514 strcpy(p,"Users"); p += 21; count++;
2515 strcpy(p,"Domain Users"); p += 21; count++;
2516 strcpy(p,"Guests"); p += 21; count++;
2517 strcpy(p,"Domain Guests"); p += 21; count++;
2519 *rdata_len = PTR_DIFF(p,*rdata);
2521 SSVAL(*rparam,4,count); /* is this right?? */
2522 SSVAL(*rparam,6,count); /* is this right?? */
2528 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2529 int mdrcnt,int mprcnt,
2530 char **rdata,char **rparam,
2531 int *rdata_len,int *rparam_len)
2533 char *str1 = param+2;
2534 char *str2 = skip_string(str1,1);
2535 char *p = skip_string(str2,1);
2537 struct pack_desc desc;
2544 bzero(&desc,sizeof(desc));
2546 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2548 /* check it's a supported varient */
2549 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2550 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2551 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2553 desc.buflen = mdrcnt;
2554 desc.subformat = NULL;
2557 if (init_package(&desc,1,0))
2559 PACKI(&desc,"W",0); /* code */
2560 PACKS(&desc,"B21",name); /* eff. name */
2561 PACKS(&desc,"B",""); /* pad */
2563 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2564 PACKI(&desc,"D",0); /* auth flags XXX */
2565 PACKI(&desc,"W",0); /* num logons */
2566 PACKI(&desc,"W",0); /* bad pw count */
2567 PACKI(&desc,"D",0); /* last logon */
2568 PACKI(&desc,"D",-1); /* last logoff */
2569 PACKI(&desc,"D",-1); /* logoff time */
2570 PACKI(&desc,"D",-1); /* kickoff time */
2571 PACKI(&desc,"D",0); /* password age */
2572 PACKI(&desc,"D",0); /* password can change */
2573 PACKI(&desc,"D",-1); /* password must change */
2576 strcpy(mypath,"\\\\");
2577 strcat(mypath,local_machine);
2579 PACKS(&desc,"z",mypath); /* computer */
2581 PACKS(&desc,"z",global_myworkgroup);/* domain */
2583 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2584 /* made sure all macros are fully substituted and available */
2585 logon_script = lp_logon_script();
2586 standard_sub( cnum, logon_script );
2587 PACKS(&desc,"z", logon_script); /* script path */
2588 /* End of JHT mods */
2590 PACKI(&desc,"D",0x00000000); /* reserved */
2593 *rdata_len = desc.usedlen;
2595 *rparam = REALLOC(*rparam,*rparam_len);
2596 SSVALS(*rparam,0,desc.errcode);
2598 SSVAL(*rparam,4,desc.neededlen);
2600 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2605 /****************************************************************************
2606 api_WAccessGetUserPerms
2607 ****************************************************************************/
2608 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2609 int mdrcnt,int mprcnt,
2610 char **rdata,char **rparam,
2611 int *rdata_len,int *rparam_len)
2613 char *str1 = param+2;
2614 char *str2 = skip_string(str1,1);
2615 char *user = skip_string(str2,1);
2616 char *resource = skip_string(user,1);
2618 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2620 /* check it's a supported varient */
2621 if (strcmp(str1,"zzh") != 0) return False;
2622 if (strcmp(str2,"") != 0) return False;
2625 *rparam = REALLOC(*rparam,*rparam_len);
2626 SSVALS(*rparam,0,0); /* errorcode */
2627 SSVAL(*rparam,2,0); /* converter word */
2628 SSVAL(*rparam,4,0x7f); /* permission flags */
2633 /****************************************************************************
2634 api_WPrintJobEnumerate
2635 ****************************************************************************/
2636 static BOOL api_WPrintJobGetInfo(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;
2656 bzero(&desc,sizeof(desc));
2657 bzero(&status,sizeof(status));
2659 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2661 /* check it's a supported varient */
2662 if (strcmp(str1,"WWrLh") != 0) return False;
2663 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2665 printjob_decode(SVAL(p,0), &snum, &job);
2667 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2669 count = get_printqueue(snum,cnum,&queue,&status);
2670 for (i = 0; i < count; i++) {
2671 if ((queue[i].job & 0xFF) == job) break;
2673 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2675 desc.buflen = mdrcnt;
2677 if (init_package(&desc,1,0)) {
2679 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2680 *rdata_len = desc.usedlen;
2683 desc.errcode = NERR_JobNotFound;
2689 *rparam = REALLOC(*rparam,*rparam_len);
2690 SSVALS(*rparam,0,desc.errcode);
2692 SSVAL(*rparam,4,desc.neededlen);
2694 if (queue) free(queue);
2696 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2700 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2701 int mdrcnt,int mprcnt,
2702 char **rdata,char **rparam,
2703 int *rdata_len,int *rparam_len)
2705 char *str1 = param+2;
2706 char *str2 = skip_string(str1,1);
2707 char *p = skip_string(str2,1);
2713 struct pack_desc desc;
2714 print_queue_struct *queue=NULL;
2715 print_status_struct status;
2717 bzero(&desc,sizeof(desc));
2718 bzero(&status,sizeof(status));
2720 p = skip_string(p,1);
2724 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2726 /* check it's a supported varient */
2727 if (strcmp(str1,"zWrLeh") != 0) return False;
2728 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2729 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2731 snum = lp_servicenumber(name);
2732 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2733 int pnum = lp_servicenumber(PRINTERS_NAME);
2735 lp_add_printer(name,pnum);
2736 snum = lp_servicenumber(name);
2740 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2742 count = get_printqueue(snum,cnum,&queue,&status);
2743 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2745 desc.buflen = mdrcnt;
2747 if (init_package(&desc,count,0)) {
2749 for (i = 0; i < count; i++) {
2750 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2751 if (desc.errcode == NERR_Success) succnt = i+1;
2755 *rdata_len = desc.usedlen;
2758 *rparam = REALLOC(*rparam,*rparam_len);
2759 SSVALS(*rparam,0,desc.errcode);
2761 SSVAL(*rparam,4,succnt);
2762 SSVAL(*rparam,6,count);
2764 if (queue) free(queue);
2766 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2770 static int check_printdest_info(struct pack_desc* desc,
2771 int uLevel, char* id)
2773 desc->subformat = NULL;
2775 case 0: desc->format = "B9"; break;
2776 case 1: desc->format = "B9B21WWzW"; break;
2777 case 2: desc->format = "z"; break;
2778 case 3: desc->format = "zzzWWzzzWW"; break;
2779 default: return False;
2781 if (strcmp(desc->format,id) != 0) return False;
2785 static void fill_printdest_info(int cnum, int snum, int uLevel,
2786 struct pack_desc* desc)
2789 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2790 buf[sizeof(buf)-1] = 0;
2793 PACKS(desc,"B9",buf); /* szName */
2795 PACKS(desc,"B21",""); /* szUserName */
2796 PACKI(desc,"W",0); /* uJobId */
2797 PACKI(desc,"W",0); /* fsStatus */
2798 PACKS(desc,"z",""); /* pszStatus */
2799 PACKI(desc,"W",0); /* time */
2802 if (uLevel == 2 || uLevel == 3) {
2803 PACKS(desc,"z",buf); /* pszPrinterName */
2805 PACKS(desc,"z",""); /* pszUserName */
2806 PACKS(desc,"z",""); /* pszLogAddr */
2807 PACKI(desc,"W",0); /* uJobId */
2808 PACKI(desc,"W",0); /* fsStatus */
2809 PACKS(desc,"z",""); /* pszStatus */
2810 PACKS(desc,"z",""); /* pszComment */
2811 PACKS(desc,"z","NULL"); /* pszDrivers */
2812 PACKI(desc,"W",0); /* time */
2813 PACKI(desc,"W",0); /* pad1 */
2818 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2819 int mdrcnt,int mprcnt,
2820 char **rdata,char **rparam,
2821 int *rdata_len,int *rparam_len)
2823 char *str1 = param+2;
2824 char *str2 = skip_string(str1,1);
2825 char *p = skip_string(str2,1);
2826 char* PrinterName = p;
2828 struct pack_desc desc;
2831 bzero(&desc,sizeof(desc));
2833 p = skip_string(p,1);
2837 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2839 /* check it's a supported varient */
2840 if (strcmp(str1,"zWrLh") != 0) return False;
2841 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2843 snum = lp_servicenumber(PrinterName);
2844 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2845 int pnum = lp_servicenumber(PRINTERS_NAME);
2847 lp_add_printer(PrinterName,pnum);
2848 snum = lp_servicenumber(PrinterName);
2854 desc.errcode = NERR_DestNotFound;
2858 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2860 desc.buflen = mdrcnt;
2861 if (init_package(&desc,1,0)) {
2862 fill_printdest_info(cnum,snum,uLevel,&desc);
2864 *rdata_len = desc.usedlen;
2868 *rparam = REALLOC(*rparam,*rparam_len);
2869 SSVALS(*rparam,0,desc.errcode);
2871 SSVAL(*rparam,4,desc.neededlen);
2873 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2877 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2878 int mdrcnt,int mprcnt,
2879 char **rdata,char **rparam,
2880 int *rdata_len,int *rparam_len)
2882 char *str1 = param+2;
2883 char *str2 = skip_string(str1,1);
2884 char *p = skip_string(str2,1);
2888 struct pack_desc desc;
2889 int services = lp_numservices();
2891 bzero(&desc,sizeof(desc));
2896 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2898 /* check it's a supported varient */
2899 if (strcmp(str1,"WrLeh") != 0) return False;
2900 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2903 for (i = 0; i < services; i++)
2904 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2907 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2909 desc.buflen = mdrcnt;
2910 if (init_package(&desc,queuecnt,0)) {
2913 for (i = 0; i < services; i++) {
2914 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2915 fill_printdest_info(cnum,i,uLevel,&desc);
2917 if (desc.errcode == NERR_Success) succnt = n;
2922 *rdata_len = desc.usedlen;
2925 *rparam = REALLOC(*rparam,*rparam_len);
2926 SSVALS(*rparam,0,desc.errcode);
2928 SSVAL(*rparam,4,succnt);
2929 SSVAL(*rparam,6,queuecnt);
2931 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2935 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2936 int mdrcnt,int mprcnt,
2937 char **rdata,char **rparam,
2938 int *rdata_len,int *rparam_len)
2940 char *str1 = param+2;
2941 char *str2 = skip_string(str1,1);
2942 char *p = skip_string(str2,1);
2945 struct pack_desc desc;
2947 bzero(&desc,sizeof(desc));
2952 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2954 /* check it's a supported varient */
2955 if (strcmp(str1,"WrLeh") != 0) return False;
2956 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2958 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2960 desc.buflen = mdrcnt;
2961 if (init_package(&desc,1,0)) {
2962 PACKS(&desc,"B41","NULL");
2965 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2967 *rdata_len = desc.usedlen;
2970 *rparam = REALLOC(*rparam,*rparam_len);
2971 SSVALS(*rparam,0,desc.errcode);
2973 SSVAL(*rparam,4,succnt);
2976 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2980 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2981 int mdrcnt,int mprcnt,
2982 char **rdata,char **rparam,
2983 int *rdata_len,int *rparam_len)
2985 char *str1 = param+2;
2986 char *str2 = skip_string(str1,1);
2987 char *p = skip_string(str2,1);
2990 struct pack_desc desc;
2992 bzero(&desc,sizeof(desc));
2997 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2999 /* check it's a supported varient */
3000 if (strcmp(str1,"WrLeh") != 0) return False;
3001 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3003 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3005 desc.buflen = mdrcnt;
3007 if (init_package(&desc,1,0)) {
3008 PACKS(&desc,"B13","lpd");
3011 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3013 *rdata_len = desc.usedlen;
3016 *rparam = REALLOC(*rparam,*rparam_len);
3017 SSVALS(*rparam,0,desc.errcode);
3019 SSVAL(*rparam,4,succnt);
3022 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3026 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
3027 int mdrcnt,int mprcnt,
3028 char **rdata,char **rparam,
3029 int *rdata_len,int *rparam_len)
3031 char *str1 = param+2;
3032 char *str2 = skip_string(str1,1);
3033 char *p = skip_string(str2,1);
3036 struct pack_desc desc;
3038 bzero(&desc,sizeof(desc));
3043 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3045 /* check it's a supported varient */
3046 if (strcmp(str1,"WrLeh") != 0) return False;
3047 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3049 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3050 bzero(&desc,sizeof(desc));
3052 desc.buflen = mdrcnt;
3054 if (init_package(&desc,1,0)) {
3055 PACKS(&desc,"B13","lp0");
3058 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3060 *rdata_len = desc.usedlen;
3063 *rparam = REALLOC(*rparam,*rparam_len);
3064 SSVALS(*rparam,0,desc.errcode);
3066 SSVAL(*rparam,4,succnt);
3069 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3075 char * pipe_clnt_name;
3076 char * pipe_srv_name;
3077 BOOL (*fn) (pipes_struct *, prs_struct *);
3080 static struct api_cmd api_fd_commands[] =
3082 { "lsarpc", "lsass", api_ntlsa_rpc },
3083 { "samr", "lsass", api_samr_rpc },
3084 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3085 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3086 { "NETLOGON", "lsass", api_netlog_rpc },
3087 { "winreg", "winreg", api_reg_rpc },
3088 { NULL, NULL, NULL }
3091 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3093 BOOL ntlmssp_auth = False;
3094 fstring ack_pipe_name;
3097 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3099 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3101 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3102 api_fd_commands[i].fn != NULL)
3104 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3105 api_fd_commands[i].pipe_clnt_name,
3106 api_fd_commands[i].pipe_srv_name));
3107 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3112 if (api_fd_commands[i].fn == NULL) return False;
3114 /* decode the bind request */
3115 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3117 if (pd->offset == 0) return False;
3119 if (p->hdr.auth_len != 0)
3121 /* decode the authentication verifier */
3122 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3124 if (pd->offset == 0) return False;
3126 /* ignore the version number for now */
3127 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3130 /* name has to be \PIPE\xxxxx */
3131 strcpy(ack_pipe_name, "\\PIPE\\");
3132 strcat(ack_pipe_name, p->pipe_srv_name);
3134 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3136 prs_init(&(p->rdata), 1024, 4, 0, False);
3137 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3138 prs_init(&(p->rauth), 1024, 4, 0, False);
3141 /*** do the bind ack first ***/
3144 make_rpc_hdr_ba(&p->hdr_ba,
3145 p->hdr_rb.bba.max_tsize,
3146 p->hdr_rb.bba.max_rsize,
3147 p->hdr_rb.bba.assoc_gid,
3150 &(p->hdr_rb.transfer));
3152 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3153 mem_realloc_data(p->rdata.data, p->rdata.offset);
3156 /*** now the authentication ***/
3162 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3164 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3167 0x00000000, 0x0000b2b3, 0x000082b1,
3169 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3170 mem_realloc_data(p->rauth.data, p->rauth.offset);
3174 /*** then do the header, now we know the length ***/
3177 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3179 p->rdata.offset + p->rauth.offset,
3182 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3183 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3186 /*** link rpc header, bind acknowledgment and authentication responses ***/
3189 p->rhdr.data->offset.start = 0;
3190 p->rhdr.data->offset.end = p->rhdr.offset;
3191 p->rhdr.data->next = p->rdata.data;
3195 p->rdata.data->offset.start = p->rhdr.offset;
3196 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3197 p->rdata.data->next = p->rauth.data;
3199 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3200 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3201 p->rauth.data->next = NULL;
3205 p->rdata.data->offset.start = p->rhdr.offset;
3206 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3207 p->rdata.data->next = NULL;
3213 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3217 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3219 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3220 api_fd_commands[i].fn != NULL)
3222 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3223 return api_fd_commands[i].fn(p, pd);
3229 static BOOL api_dce_rpc_command(char *outbuf,
3234 if (pd->data == NULL) return False;
3236 /* process the rpc header */
3237 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3239 if (pd->offset == 0) return False;
3241 switch (p->hdr.pkt_type)
3245 reply = api_pipe_bind_req(p, pd);
3250 reply = api_pipe_request (p, pd);
3257 /* now send the reply */
3258 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3260 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3262 /* all of data was sent: no need to wait for SMBreadX calls */
3263 mem_free_data(p->rhdr .data);
3264 mem_free_data(p->rdata.data);
3271 /****************************************************************************
3272 SetNamedPipeHandleState
3273 ****************************************************************************/
3274 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3278 if (!param) return False;
3280 id = param[0] + (param[1] << 8);
3281 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3283 if (set_rpc_pipe_hnd_state(p, id))
3285 /* now send the reply */
3286 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3294 /****************************************************************************
3295 when no reply is generated, indicate unsupported.
3296 ****************************************************************************/
3297 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3299 struct mem_buf rparam;
3301 mem_init(&rparam, 0);
3302 mem_alloc_data(&rparam, 4);
3304 rparam.offset.start = 0;
3305 rparam.offset.end = 4;
3308 SSVAL(rparam.data,0,NERR_notsupported);
3309 SSVAL(rparam.data,2,0); /* converter word */
3311 DEBUG(3,("Unsupported API fd command\n"));
3313 /* now send the reply */
3314 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3316 mem_free_data(&rparam);
3321 /****************************************************************************
3322 handle remote api calls delivered to a named pipe already opened.
3323 ****************************************************************************/
3324 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
3325 uint16 *setup,char *data,char *params,
3326 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3332 pipes_struct *p = NULL;
3334 struct mem_buf data_buf;
3336 DEBUG(5,("api_fd_reply\n"));
3338 /* fake up a data buffer from the api_fd_reply data parameters */
3339 mem_create(&data_buf, data, tdscnt, 0, False);
3340 data_buf.offset.start = 0;
3341 data_buf.offset.end = tdscnt;
3343 /* fake up a parsing structure */
3344 pd.data = &data_buf;
3349 /* First find out the name of this file. */
3352 DEBUG(0,("Unexpected named pipe transaction.\n"));
3356 /* Get the file handle and hence the file name. */
3358 subcommand = setup[0];
3359 get_rpc_pipe(pnum, &p);
3363 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3364 subcommand, p->name, pnum));
3365 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
3366 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
3368 /* record maximum data length that can be transmitted in an SMBtrans */
3369 p->file_offset = mdrcnt;
3371 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3372 p, p->file_offset));
3378 /* dce/rpc command */
3379 reply = api_dce_rpc_command(outbuf, p, &pd);
3384 /* Set Named Pipe Handle state */
3385 reply = api_SNPHS(outbuf, p, params);
3392 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3397 return api_no_reply(outbuf, mdrcnt);
3402 /****************************************************************************
3403 the buffer was too small
3404 ****************************************************************************/
3405 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3406 int mdrcnt,int mprcnt,
3407 char **rdata,char **rparam,
3408 int *rdata_len,int *rparam_len)
3410 *rparam_len = MIN(*rparam_len,mprcnt);
3411 *rparam = REALLOC(*rparam,*rparam_len);
3415 SSVAL(*rparam,0,NERR_BufTooSmall);
3417 DEBUG(3,("Supplied buffer too small in API command\n"));
3423 /****************************************************************************
3424 the request is not supported
3425 ****************************************************************************/
3426 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3427 int mdrcnt,int mprcnt,
3428 char **rdata,char **rparam,
3429 int *rdata_len,int *rparam_len)
3432 *rparam = REALLOC(*rparam,*rparam_len);
3436 SSVAL(*rparam,0,NERR_notsupported);
3437 SSVAL(*rparam,2,0); /* converter word */
3439 DEBUG(3,("Unsupported API command\n"));
3451 BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *);
3453 } api_commands[] = {
3454 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3455 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3456 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3457 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3458 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3459 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3460 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3461 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3462 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3463 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3464 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3465 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3466 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3467 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3468 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3469 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3470 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3471 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3472 {"NetServerEnum", 104, api_RNetServerEnum,0},
3473 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3474 {"SetUserPassword", 115, api_SetUserPassword,0},
3475 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3476 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3477 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3478 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3479 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3480 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3481 {NULL, -1, api_Unsupported,0}};
3484 /****************************************************************************
3485 handle remote api calls
3486 ****************************************************************************/
3487 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3488 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3490 int api_command = SVAL(params,0);
3491 struct mem_buf rdata_buf;
3492 struct mem_buf rparam_buf;
3494 char *rparam = NULL;
3500 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3501 api_command,params+2,skip_string(params+2,1),
3502 tdscnt,tpscnt,mdrcnt,mprcnt));
3504 for (i=0;api_commands[i].name;i++)
3505 if (api_commands[i].id == api_command && api_commands[i].fn)
3507 DEBUG(3,("Doing %s\n",api_commands[i].name));
3511 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3512 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3514 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3515 &rdata,&rparam,&rdata_len,&rparam_len);
3518 if (rdata_len > mdrcnt ||
3519 rparam_len > mprcnt)
3521 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3522 &rdata,&rparam,&rdata_len,&rparam_len);
3526 /* if we get False back then it's actually unsupported */
3528 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3529 &rdata,&rparam,&rdata_len,&rparam_len);
3532 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3533 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3535 rdata_buf.offset.start = 0;
3536 rdata_buf.offset.end = rdata_len;
3538 rparam_buf.offset.start = 0;
3539 rparam_buf.offset.end = rparam_len;
3541 /* now send the reply */
3542 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3544 if (rdata ) free(rdata);
3545 if (rparam) free(rparam);
3550 /****************************************************************************
3551 handle named pipe commands
3552 ****************************************************************************/
3553 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3554 uint16 *setup,char *data,char *params,
3555 int suwcnt,int tdscnt,int tpscnt,
3556 int msrcnt,int mdrcnt,int mprcnt)
3558 DEBUG(3,("named pipe command on <%s> name\n", name));
3560 if (strequal(name,"LANMAN"))
3562 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3565 if (strlen(name) < 1)
3567 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3572 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3579 /****************************************************************************
3581 ****************************************************************************/
3582 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3586 char *data=NULL,*params=NULL;
3590 int cnum = SVAL(inbuf,smb_tid);
3591 uint16 vuid = SVAL(inbuf,smb_uid);
3593 int tpscnt = SVAL(inbuf,smb_vwv0);
3594 int tdscnt = SVAL(inbuf,smb_vwv1);
3595 int mprcnt = SVAL(inbuf,smb_vwv2);
3596 int mdrcnt = SVAL(inbuf,smb_vwv3);
3597 int msrcnt = CVAL(inbuf,smb_vwv4);
3598 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3599 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3600 int pscnt = SVAL(inbuf,smb_vwv9);
3601 int psoff = SVAL(inbuf,smb_vwv10);
3602 int dscnt = SVAL(inbuf,smb_vwv11);
3603 int dsoff = SVAL(inbuf,smb_vwv12);
3604 int suwcnt = CVAL(inbuf,smb_vwv13);
3606 bzero(name, sizeof(name));
3607 fstrcpy(name,smb_buf(inbuf));
3609 if (dscnt > tdscnt || pscnt > tpscnt) {
3610 exit_server("invalid trans parameters\n");
3615 data = (char *)malloc(tdscnt);
3616 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3620 params = (char *)malloc(tpscnt);
3621 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3627 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3628 for (i=0;i<suwcnt;i++)
3629 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3633 if (pscnt < tpscnt || dscnt < tdscnt)
3635 /* We need to send an interim response then receive the rest
3636 of the parameter/data bytes */
3637 outsize = set_message(outbuf,0,0,True);
3639 send_smb(Client,outbuf);
3642 /* receive the rest of the trans packet */
3643 while (pscnt < tpscnt || dscnt < tdscnt)
3646 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3648 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3650 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3653 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3655 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3656 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3657 if (params) free(params);
3658 if (data) free(data);
3659 if (setup) free(setup);
3660 return(ERROR(ERRSRV,ERRerror));
3665 tpscnt = SVAL(inbuf,smb_vwv0);
3666 tdscnt = SVAL(inbuf,smb_vwv1);
3668 pcnt = SVAL(inbuf,smb_vwv2);
3669 poff = SVAL(inbuf,smb_vwv3);
3670 pdisp = SVAL(inbuf,smb_vwv4);
3672 dcnt = SVAL(inbuf,smb_vwv5);
3673 doff = SVAL(inbuf,smb_vwv6);
3674 ddisp = SVAL(inbuf,smb_vwv7);
3679 if (dscnt > tdscnt || pscnt > tpscnt) {
3680 exit_server("invalid trans parameters\n");
3684 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3686 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3690 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3692 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3694 DEBUG(5,("calling named_pipe\n"));
3695 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3696 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3700 DEBUG(3,("invalid pipe name\n"));
3705 if (data) free(data);
3706 if (params) free(params);
3707 if (setup) free(setup);
3709 if (close_on_completion)
3710 close_cnum(cnum,vuid);
3716 return(ERROR(ERRSRV,ERRnosupport));