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[];
41 extern fstring local_machine;
42 extern fstring global_myworkgroup;
44 #define NERR_Success 0
45 #define NERR_badpass 86
46 #define NERR_notsupported 50
48 #define NERR_BASE (2100)
49 #define NERR_BufTooSmall (NERR_BASE+23)
50 #define NERR_JobNotFound (NERR_BASE+51)
51 #define NERR_DestNotFound (NERR_BASE+52)
52 #define ERROR_INVALID_LEVEL 124
54 #define ACCESS_READ 0x01
55 #define ACCESS_WRITE 0x02
56 #define ACCESS_CREATE 0x04
58 #define SHPWLEN 8 /* share password length */
59 #define NNLEN 12 /* 8.3 net name length */
60 #define SNLEN 15 /* service name length */
61 #define QNLEN 12 /* queue name maximum length */
64 extern int oplock_sock;
65 extern int smb_read_error;
67 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
68 int mdrcnt,int mprcnt,
69 char **rdata,char **rparam,
70 int *rdata_len,int *rparam_len);
71 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
72 int mdrcnt,int mprcnt,
73 char **rdata,char **rparam,
74 int *rdata_len,int *rparam_len);
77 static int CopyExpanded(connection_struct *conn,
78 int snum, char** dst, char* src, int* n)
83 if (!src || !dst || !n || !(*dst)) return(0);
85 StrnCpy(buf,src,sizeof(buf)/2);
86 string_sub(buf,"%S",lp_servicename(snum));
87 standard_sub(conn,buf);
95 static int CopyAndAdvance(char** dst, char* src, int* n)
98 if (!src || !dst || !n || !(*dst)) return(0);
100 l = strlen(*dst) + 1;
106 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
110 StrnCpy(buf,s,sizeof(buf)/2);
111 string_sub(buf,"%S",lp_servicename(snum));
112 standard_sub(conn,buf);
113 return strlen(buf) + 1;
116 static char* Expand(connection_struct *conn, int snum, char* s)
119 if (!s) return(NULL);
120 StrnCpy(buf,s,sizeof(buf)/2);
121 string_sub(buf,"%S",lp_servicename(snum));
122 standard_sub(conn,buf);
126 /*******************************************************************
127 check a API string for validity when we only need to check the prefix
128 ******************************************************************/
129 static BOOL prefix_ok(char *str,char *prefix)
131 return(strncmp(str,prefix,strlen(prefix)) == 0);
134 /*******************************************************************
135 copies parameters and data, as needed, into the smb buffer
137 *both* the data and params sections should be aligned. this
138 is fudged in the rpc pipes by
139 at present, only the data section is. this may be a possible
140 cause of some of the ipc problems being experienced. lkcl26dec97
142 ******************************************************************/
143 static void copy_trans_params_and_data(char *outbuf, int align,
144 struct mem_buf *rparam, struct mem_buf *rdata,
145 int param_offset, int data_offset,
146 int param_len, int data_len)
148 char *copy_into = smb_buf(outbuf);
150 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
151 param_offset, param_offset + param_len,
152 data_offset , data_offset + data_len));
154 if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
155 copy_into += param_len + align;
156 if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
159 /****************************************************************************
161 ****************************************************************************/
162 static void send_trans_reply(char *outbuf,
163 struct mem_buf *rdata,
164 struct mem_buf *rparam,
165 uint16 *setup, int lsetup, int max_data_ret)
168 int this_ldata,this_lparam;
169 int tot_data=0,tot_param=0;
172 int ldata = rdata ? mem_buf_len(rdata ) : 0;
173 int lparam = rparam ? mem_buf_len(rparam) : 0;
175 BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
177 if (buffer_too_large)
179 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
180 ldata = max_data_ret;
183 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
184 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
186 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
187 /* if you don't want Net Monitor to decode your packets, do this!!! */
188 align = ((this_lparam+1)%4);
190 align = (this_lparam%4);
193 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
195 if (buffer_too_large)
197 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
198 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
199 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
202 copy_trans_params_and_data(outbuf, align,
204 tot_param , tot_data,
205 this_lparam, this_ldata);
207 SSVAL(outbuf,smb_vwv0,lparam);
208 SSVAL(outbuf,smb_vwv1,ldata);
209 SSVAL(outbuf,smb_vwv3,this_lparam);
210 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
211 SSVAL(outbuf,smb_vwv5,0);
212 SSVAL(outbuf,smb_vwv6,this_ldata);
213 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
214 SSVAL(outbuf,smb_vwv8,0);
215 SSVAL(outbuf,smb_vwv9,lsetup);
217 for (i=0;i<lsetup;i++)
219 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
223 send_smb(Client,outbuf);
225 tot_data = this_ldata;
226 tot_param = this_lparam;
228 while (tot_data < ldata || tot_param < lparam)
230 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
231 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
233 align = (this_lparam%4);
235 set_message(outbuf,10,this_ldata+this_lparam+align,False);
237 copy_trans_params_and_data(outbuf, align,
239 tot_param , tot_data,
240 this_lparam, this_ldata);
242 SSVAL(outbuf,smb_vwv3,this_lparam);
243 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
244 SSVAL(outbuf,smb_vwv5,tot_param);
245 SSVAL(outbuf,smb_vwv6,this_ldata);
246 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
247 SSVAL(outbuf,smb_vwv8,tot_data);
248 SSVAL(outbuf,smb_vwv9,0);
251 send_smb(Client,outbuf);
253 tot_data += this_ldata;
254 tot_param += this_lparam;
259 char* format; /* formatstring for structure */
260 char* subformat; /* subformat for structure */
261 char* base; /* baseaddress of buffer */
262 int buflen; /* remaining size for fixed part; on init: length of base */
263 int subcount; /* count of substructures */
264 char* structbuf; /* pointer into buffer for remaining fixed part */
265 int stringlen; /* remaining size for variable part */
266 char* stringbuf; /* pointer into buffer for remaining variable part */
267 int neededlen; /* total needed size */
268 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
269 char* curpos; /* current position; pointer into format or subformat */
273 static int get_counter(char** p)
276 if (!p || !(*p)) return(1);
277 if (!isdigit(**p)) return 1;
281 n = 10 * n + (i - '0');
288 static int getlen(char* p)
294 case 'W': /* word (2 byte) */
297 case 'N': /* count of substructures (word) at end */
300 case 'D': /* double word (4 byte) */
301 case 'z': /* offset to zero terminated string (4 byte) */
302 case 'l': /* offset to user data (4 byte) */
305 case 'b': /* offset to data (with counter) (4 byte) */
309 case 'B': /* byte (with optional counter) */
310 n += get_counter(&p);
317 static BOOL init_package(struct pack_desc* p, int count, int subcount)
322 if (!p->format || !p->base) return(False);
324 i = count * getlen(p->format);
325 if (p->subformat) i += subcount * getlen(p->subformat);
326 p->structbuf = p->base;
330 p->curpos = p->format;
334 p->errcode = ERRmoredata;
337 p->errcode = NERR_Success;
340 p->stringbuf = p->base + i;
342 return(p->errcode == NERR_Success);
346 static int package(struct pack_desc* p, ...)
349 static int package(va_alist)
355 int needed=0, stringneeded;
357 int is_string=0, stringused;
364 p = va_arg(args,struct pack_desc *);
369 p->curpos = p->format;
371 p->curpos = p->subformat;
376 str = va_arg(args,char*);
377 if (strncmp(str,p->curpos,strlen(str)) != 0) {
378 DEBUG(2,("type error in package: %s instead of %*s\n",str,
379 strlen(str),p->curpos));
389 if (!p->curpos) return(0);
391 switch( *p->curpos++ ) {
392 case 'W': /* word (2 byte) */
394 temp = va_arg(args,int);
395 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
397 case 'N': /* count of substructures (word) at end */
399 p->subcount = va_arg(args,int);
400 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
402 case 'D': /* double word (4 byte) */
404 temp = va_arg(args,int);
405 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
407 case 'B': /* byte (with optional counter) */
408 needed = get_counter(&p->curpos);
410 char *s = va_arg(args,char*);
411 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
414 case 'z': /* offset to zero terminated string (4 byte) */
415 str = va_arg(args,char*);
416 stringneeded = (str ? strlen(str)+1 : 0);
419 case 'l': /* offset to user data (4 byte) */
420 str = va_arg(args,char*);
421 stringneeded = va_arg(args,int);
424 case 'b': /* offset to data (with counter) (4 byte) */
425 str = va_arg(args,char*);
426 stringneeded = get_counter(&p->curpos);
431 if (stringneeded >= 0) {
433 if (p->buflen >= needed) {
434 stringused = stringneeded;
435 if (stringused > p->stringlen) {
436 stringused = (is_string ? p->stringlen : 0);
437 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
440 SIVAL(p->structbuf,0,0);
442 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
443 memcpy(p->stringbuf,str?str:"",stringused);
444 if (is_string) p->stringbuf[stringused-1] = '\0';
445 p->stringbuf += stringused;
446 p->stringlen -= stringused;
447 p->usedlen += stringused;
450 p->neededlen += stringneeded;
452 p->neededlen += needed;
453 if (p->buflen >= needed) {
454 p->structbuf += needed;
456 p->usedlen += needed;
459 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
465 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
466 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
468 #define PACK(desc,t,v) package(desc,v)
469 #define PACKl(desc,t,v,l) package(desc,v,l)
472 static void PACKI(struct pack_desc* desc,char *t,int v)
477 static void PACKS(struct pack_desc* desc,char *t,char *v)
483 /****************************************************************************
485 ****************************************************************************/
487 static void PackDriverData(struct pack_desc* desc)
489 char drivdata[4+4+32];
490 SIVAL(drivdata,0,sizeof drivdata); /* cb */
491 SIVAL(drivdata,4,1000); /* lVersion */
492 memset(drivdata+8,0,32); /* szDeviceName */
493 pstrcpy(drivdata+8,"NULL");
494 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
497 static int check_printq_info(struct pack_desc* desc,
498 int uLevel, char *id1, char *id2)
500 desc->subformat = NULL;
503 desc->format = "B13";
506 desc->format = "B13BWWWzzzzzWW";
509 desc->format = "B13BWWWzzzzzWN";
510 desc->subformat = "WB21BB16B10zWWzDDz";
513 desc->format = "zWWWWzzzzWWzzl";
516 desc->format = "zWWWWzzzzWNzzl";
517 desc->subformat = "WWzWWDDzz";
523 desc->format = "WzzzzzzzzN";
524 desc->subformat = "z";
526 default: return False;
528 if (strcmp(desc->format,id1) != 0) return False;
529 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
533 static void fill_printjob_info(connection_struct *conn, 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(connection_struct *conn, 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(conn,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(conn,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(conn,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(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
647 pstring tok,driver,datafile,langmon,helpfile,datatype;
652 pstrcpy(fname,lp_driverfile());
655 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
656 desc->errcode=NERR_notsupported;
660 p=(char *)malloc(8192*sizeof(char));
661 bzero(p, 8192*sizeof(char));
664 /* lookup the long printer driver name in the file description */
665 while (f && !feof(f) && !ok)
667 p = q; /* reset string pointer */
670 if (next_token(&p,tok,":") &&
671 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
672 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
677 /* driver file name */
678 if (ok && !next_token(&p,driver,":")) ok = 0;
680 if (ok && !next_token(&p,datafile,":")) ok = 0;
682 * for the next tokens - which may be empty - I have to check for empty
683 * tokens first because the next_token function will skip all empty
691 } else if (!next_token(&p,helpfile,":")) ok = 0;
695 /* language monitor */
699 } else if (!next_token(&p,langmon,":")) ok = 0;
702 /* default data type */
703 if (ok && !next_token(&p,datatype,":")) ok = 0;
706 PACKI(desc,"W",0x0400); /* don't know */
707 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
708 PACKS(desc,"z",driver); /* Driverfile Name */
709 PACKS(desc,"z",datafile); /* Datafile name */
710 PACKS(desc,"z",langmon); /* language monitor */
711 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
712 PACKS(desc,"z",datatype); /* default data type */
713 PACKS(desc,"z",helpfile); /* helpfile name */
714 PACKS(desc,"z",driver); /* driver name */
715 DEBUG(3,("Driver:%s:\n",driver));
716 DEBUG(3,("Data File:%s:\n",datafile));
717 DEBUG(3,("Language Monitor:%s:\n",langmon));
718 DEBUG(3,("Data Type:%s:\n",datatype));
719 DEBUG(3,("Help File:%s:\n",helpfile));
720 PACKI(desc,"N",count); /* number of files to copy */
721 for (i=0;i<count;i++)
723 /* no need to check return value here - it was already tested in
724 * get_printerdrivernumber
726 next_token(&p,tok,",");
727 PACKS(desc,"z",tok); /* driver files to copy */
728 DEBUG(3,("file:%s:\n",tok));
731 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
732 SERVICE(snum),count));
734 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
735 desc->errcode=NERR_notsupported;
741 /* This function returns the number of files for a given driver */
742 int get_printerdrivernumber(int snum)
750 pstrcpy(fname,lp_driverfile());
752 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
755 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
759 p=(char *)malloc(8192*sizeof(char));
760 q=p; /* need it to free memory because p change ! */
762 /* lookup the long printer driver name in the file description */
763 while (!feof(f) && !ok)
765 p = q; /* reset string pointer */
767 if (next_token(&p,tok,":") &&
768 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
777 if (*p++ == ':') i--;
782 /* count the number of files */
783 while (next_token(&p,tok,","))
791 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
792 uint16 vuid, char *param,char *data,
793 int mdrcnt,int mprcnt,
794 char **rdata,char **rparam,
795 int *rdata_len,int *rparam_len)
797 char *str1 = param+2;
798 char *str2 = skip_string(str1,1);
799 char *p = skip_string(str2,1);
805 struct pack_desc desc;
806 print_queue_struct *queue=NULL;
807 print_status_struct status;
809 bzero(&status,sizeof(status));
810 bzero(&desc,sizeof(desc));
812 p = skip_string(p,1);
817 /* remove any trailing username */
818 if ((p = strchr(QueueName,'%'))) *p = 0;
820 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
822 /* check it's a supported varient */
823 if (!prefix_ok(str1,"zWrLh")) return False;
824 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
826 snum = lp_servicenumber(QueueName);
827 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
828 int pnum = lp_servicenumber(PRINTERS_NAME);
830 lp_add_printer(QueueName,pnum);
831 snum = lp_servicenumber(QueueName);
835 if (snum < 0 || !VALID_SNUM(snum)) return(False);
839 count = get_printerdrivernumber(snum);
840 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
842 count = get_printqueue(SNUM(conn), conn,&queue,&status);
845 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
847 desc.buflen = mdrcnt;
848 if (init_package(&desc,1,count)) {
849 desc.subcount = count;
850 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
853 *rdata_len = desc.usedlen;
856 *rparam = REALLOC(*rparam,*rparam_len);
857 SSVALS(*rparam,0,desc.errcode);
859 SSVAL(*rparam,4,desc.neededlen);
861 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
863 if (queue) free(queue);
869 /****************************************************************************
870 view list of all print jobs on all queues
871 ****************************************************************************/
872 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
873 int mdrcnt, int mprcnt,
874 char **rdata, char** rparam,
875 int *rdata_len, int *rparam_len)
877 char *param_format = param+2;
878 char *output_format1 = skip_string(param_format,1);
879 char *p = skip_string(output_format1,1);
880 int uLevel = SVAL(p,0);
881 char *output_format2 = p + 4;
882 int services = lp_numservices();
884 struct pack_desc desc;
885 print_queue_struct **queue = NULL;
886 print_status_struct *status = NULL;
887 int* subcntarr = NULL;
888 int queuecnt, subcnt=0, succnt=0;
890 bzero(&desc,sizeof(desc));
892 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
894 if (!prefix_ok(param_format,"WrLeh")) return False;
895 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
898 for (i = 0; i < services; i++)
899 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
902 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
903 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
904 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
905 memset(status,0,queuecnt*sizeof(print_status_struct));
906 subcntarr = (int*)malloc(queuecnt*sizeof(int));
909 for (i = 0; i < services; i++)
910 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
911 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
912 subcnt += subcntarr[n];
916 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
918 desc.buflen = mdrcnt;
920 if (init_package(&desc,queuecnt,subcnt)) {
923 for (i = 0; i < services; i++)
924 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
925 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
927 if (desc.errcode == NERR_Success) succnt = n;
931 if (subcntarr) free(subcntarr);
933 *rdata_len = desc.usedlen;
935 *rparam = REALLOC(*rparam,*rparam_len);
936 SSVALS(*rparam,0,desc.errcode);
938 SSVAL(*rparam,4,succnt);
939 SSVAL(*rparam,6,queuecnt);
941 for (i = 0; i < queuecnt; i++) {
942 if (queue && queue[i]) free(queue[i]);
945 if (queue) free(queue);
946 if (status) free(status);
951 /****************************************************************************
952 get info level for a server list query
953 ****************************************************************************/
954 static BOOL check_server_info(int uLevel, char* id)
958 if (strcmp(id,"B16") != 0) return False;
961 if (strcmp(id,"B16BBDz") != 0) return False;
969 struct srv_info_struct
979 /*******************************************************************
980 get server info lists from the files saved by nmbd. Return the
982 ******************************************************************/
983 static int get_server_info(uint32 servertype,
984 struct srv_info_struct **servers,
992 BOOL local_list_only;
994 pstrcpy(fname,lp_lockdir());
995 trim_string(fname,NULL,"/");
997 pstrcat(fname,SERVER_LIST);
999 f = fopen(fname,"r");
1002 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1006 /* request for everything is code for request all servers */
1007 if (servertype == SV_TYPE_ALL)
1008 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1010 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1012 DEBUG(4,("Servertype search: %8x\n",servertype));
1017 struct srv_info_struct *s;
1022 fgets(line,sizeof(line)-1,f);
1023 if (!*line) continue;
1025 if (count == alloced) {
1027 (*servers) = (struct srv_info_struct *)
1028 Realloc(*servers,sizeof(**servers)*alloced);
1029 if (!(*servers)) return(0);
1030 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1032 s = &(*servers)[count];
1034 if (!next_token(&ptr,s->name , NULL)) continue;
1035 if (!next_token(&ptr,stype , NULL)) continue;
1036 if (!next_token(&ptr,s->comment, NULL)) continue;
1037 if (!next_token(&ptr,s->domain , NULL)) {
1038 /* this allows us to cope with an old nmbd */
1039 pstrcpy(s->domain,global_myworkgroup);
1042 if (sscanf(stype,"%X",&s->type) != 1) {
1043 DEBUG(4,("r:host file "));
1047 /* Filter the servers/domains we return based on what was asked for. */
1049 /* Check to see if we are being asked for a local list only. */
1050 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1051 DEBUG(4,("r: local list only"));
1055 /* doesn't match up: don't want it */
1056 if (!(servertype & s->type)) {
1057 DEBUG(4,("r:serv type "));
1061 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1062 (s->type & SV_TYPE_DOMAIN_ENUM))
1064 DEBUG(4,("s: dom mismatch "));
1068 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1073 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1074 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1078 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1079 s->name, s->type, s->comment, s->domain));
1081 s->server_added = True;
1086 DEBUG(4,("%20s %8x %25s %15s\n",
1087 s->name, s->type, s->comment, s->domain));
1096 /*******************************************************************
1097 fill in a server info structure
1098 ******************************************************************/
1099 static int fill_srv_info(struct srv_info_struct *service,
1100 int uLevel, char **buf, int *buflen,
1101 char **stringbuf, int *stringspace, char *baseaddr)
1110 case 0: struct_len = 16; break;
1111 case 1: struct_len = 26; break;
1121 len = strlen(service->comment)+1;
1125 if (buflen) *buflen = struct_len;
1126 if (stringspace) *stringspace = len;
1127 return struct_len + len;
1132 if (*buflen < struct_len) return -1;
1140 p2 = p + struct_len;
1141 l2 = *buflen - struct_len;
1143 if (!baseaddr) baseaddr = p;
1148 StrnCpy(p,service->name,15);
1152 StrnCpy(p,service->name,15);
1153 SIVAL(p,18,service->type);
1154 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1155 len += CopyAndAdvance(&p2,service->comment,&l2);
1161 *buf = p + struct_len;
1162 *buflen -= struct_len;
1175 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1177 return(strcmp(s1->name,s2->name));
1180 /****************************************************************************
1181 view list of servers available (or possibly domains). The info is
1182 extracted from lists saved by nmbd on the local host
1183 ****************************************************************************/
1184 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1185 int mdrcnt, int mprcnt, char **rdata,
1186 char **rparam, int *rdata_len, int *rparam_len)
1188 char *str1 = param+2;
1189 char *str2 = skip_string(str1,1);
1190 char *p = skip_string(str2,1);
1191 int uLevel = SVAL(p,0);
1192 int buf_len = SVAL(p,2);
1193 uint32 servertype = IVAL(p,4);
1195 int data_len, fixed_len, string_len;
1196 int f_len = 0, s_len = 0;
1197 struct srv_info_struct *servers=NULL;
1198 int counted=0,total=0;
1201 BOOL domain_request;
1204 /* If someone sets all the bits they don't really mean to set
1205 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1208 if (servertype == SV_TYPE_ALL)
1209 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1211 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1212 any other bit (they may just set this bit on it's own) they
1213 want all the locally seen servers. However this bit can be
1214 set on its own so set the requested servers to be
1215 ALL - DOMAIN_ENUM. */
1217 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1218 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1220 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1221 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1225 if (!prefix_ok(str1,"WrLehD")) return False;
1226 if (!check_server_info(uLevel,str2)) return False;
1228 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1229 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1230 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1232 if (strcmp(str1, "WrLehDz") == 0) {
1233 StrnCpy(domain, p, sizeof(fstring)-1);
1235 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1238 if (lp_browse_list())
1239 total = get_server_info(servertype,&servers,domain);
1241 data_len = fixed_len = string_len = 0;
1244 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1247 char *lastname=NULL;
1249 for (i=0;i<total;i++)
1251 struct srv_info_struct *s = &servers[i];
1252 if (lastname && strequal(lastname,s->name)) continue;
1254 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1255 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1256 s->name, s->type, s->comment, s->domain));
1258 if (data_len <= buf_len) {
1261 string_len += s_len;
1268 *rdata_len = fixed_len + string_len;
1269 *rdata = REALLOC(*rdata,*rdata_len);
1270 bzero(*rdata,*rdata_len);
1272 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1278 char *lastname=NULL;
1279 int count2 = counted;
1280 for (i = 0; i < total && count2;i++)
1282 struct srv_info_struct *s = &servers[i];
1283 if (lastname && strequal(lastname,s->name)) continue;
1285 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1286 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1287 s->name, s->type, s->comment, s->domain));
1293 *rparam = REALLOC(*rparam,*rparam_len);
1294 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1296 SSVAL(*rparam,4,counted);
1297 SSVAL(*rparam,6,counted+missed);
1299 if (servers) free(servers);
1301 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1302 domain,uLevel,counted,counted+missed));
1307 /****************************************************************************
1308 command 0x34 - suspected of being a "Lookup Names" stub api
1309 ****************************************************************************/
1310 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1311 int mdrcnt, int mprcnt, char **rdata,
1312 char **rparam, int *rdata_len, int *rparam_len)
1314 char *str1 = param+2;
1315 char *str2 = skip_string(str1,1);
1316 char *p = skip_string(str2,1);
1317 int uLevel = SVAL(p,0);
1318 int buf_len = SVAL(p,2);
1322 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1323 str1, str2, p, uLevel, buf_len));
1325 if (!prefix_ok(str1,"zWrLeh")) return False;
1331 *rparam = REALLOC(*rparam,*rparam_len);
1333 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1335 SSVAL(*rparam,4,counted);
1336 SSVAL(*rparam,6,counted+missed);
1341 /****************************************************************************
1342 get info about a share
1343 ****************************************************************************/
1344 static BOOL check_share_info(int uLevel, char* id)
1348 if (strcmp(id,"B13") != 0) return False;
1351 if (strcmp(id,"B13BWz") != 0) return False;
1354 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1357 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1359 default: return False;
1364 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1365 char** buf, int* buflen,
1366 char** stringbuf, int* stringspace, char* baseaddr)
1375 case 0: struct_len = 13; break;
1376 case 1: struct_len = 20; break;
1377 case 2: struct_len = 40; break;
1378 case 91: struct_len = 68; break;
1386 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1387 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1388 if (buflen) *buflen = struct_len;
1389 if (stringspace) *stringspace = len;
1390 return struct_len + len;
1395 if ((*buflen) < struct_len) return -1;
1403 p2 = p + struct_len;
1404 l2 = (*buflen) - struct_len;
1406 if (!baseaddr) baseaddr = p;
1408 StrnCpy(p,lp_servicename(snum),13);
1414 type = STYPE_DISKTREE;
1415 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1416 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1417 SSVAL(p,14,type); /* device type */
1418 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1419 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1424 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1425 SSVALS(p,22,-1); /* max uses */
1426 SSVAL(p,24,1); /* current uses */
1427 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1428 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1429 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1434 memset(p+40,0,SHPWLEN+2);
1446 (*buf) = p + struct_len;
1447 (*buflen) -= struct_len;
1449 (*stringspace) = l2;
1459 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1460 int mdrcnt,int mprcnt,
1461 char **rdata,char **rparam,
1462 int *rdata_len,int *rparam_len)
1464 char *str1 = param+2;
1465 char *str2 = skip_string(str1,1);
1466 char *netname = skip_string(str2,1);
1467 char *p = skip_string(netname,1);
1468 int uLevel = SVAL(p,0);
1469 int snum = find_service(netname);
1471 if (snum < 0) return False;
1473 /* check it's a supported varient */
1474 if (!prefix_ok(str1,"zWrLh")) return False;
1475 if (!check_share_info(uLevel,str2)) return False;
1477 *rdata = REALLOC(*rdata,mdrcnt);
1479 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1480 if (*rdata_len < 0) return False;
1483 *rparam = REALLOC(*rparam,*rparam_len);
1484 SSVAL(*rparam,0,NERR_Success);
1485 SSVAL(*rparam,2,0); /* converter word */
1486 SSVAL(*rparam,4,*rdata_len);
1491 /****************************************************************************
1492 view list of shares available
1493 ****************************************************************************/
1494 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1495 int mdrcnt,int mprcnt,
1496 char **rdata,char **rparam,
1497 int *rdata_len,int *rparam_len)
1499 char *str1 = param+2;
1500 char *str2 = skip_string(str1,1);
1501 char *p = skip_string(str2,1);
1502 int uLevel = SVAL(p,0);
1503 int buf_len = SVAL(p,2);
1505 int count=lp_numservices();
1506 int total=0,counted=0;
1507 BOOL missed = False;
1509 int data_len, fixed_len, string_len;
1510 int f_len = 0, s_len = 0;
1512 if (!prefix_ok(str1,"WrLeh")) return False;
1513 if (!check_share_info(uLevel,str2)) return False;
1515 data_len = fixed_len = string_len = 0;
1516 for (i=0;i<count;i++)
1517 if (lp_browseable(i) && lp_snum_ok(i))
1520 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1521 if (data_len <= buf_len)
1525 string_len += s_len;
1530 *rdata_len = fixed_len + string_len;
1531 *rdata = REALLOC(*rdata,*rdata_len);
1532 memset(*rdata,0,*rdata_len);
1534 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1538 for (i = 0; i < count;i++)
1539 if (lp_browseable(i) && lp_snum_ok(i))
1540 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1544 *rparam = REALLOC(*rparam,*rparam_len);
1545 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1547 SSVAL(*rparam,4,counted);
1548 SSVAL(*rparam,6,total);
1550 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1551 counted,total,uLevel,
1552 buf_len,*rdata_len,mdrcnt));
1558 /****************************************************************************
1559 get the time of day info
1560 ****************************************************************************/
1561 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1562 int mdrcnt,int mprcnt,
1563 char **rdata,char **rparam,
1564 int *rdata_len,int *rparam_len)
1568 *rparam = REALLOC(*rparam,*rparam_len);
1571 *rdata = REALLOC(*rdata,*rdata_len);
1573 SSVAL(*rparam,0,NERR_Success);
1574 SSVAL(*rparam,2,0); /* converter word */
1580 time_t unixdate = time(NULL);
1582 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1583 by NT in a "net time" operation,
1584 it seems to ignore the one below */
1586 /* the client expects to get localtime, not GMT, in this bit
1587 (I think, this needs testing) */
1588 t = LocalTime(&unixdate);
1590 SIVAL(p,4,0); /* msecs ? */
1591 CVAL(p,8) = t->tm_hour;
1592 CVAL(p,9) = t->tm_min;
1593 CVAL(p,10) = t->tm_sec;
1594 CVAL(p,11) = 0; /* hundredths of seconds */
1595 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1596 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1597 CVAL(p,16) = t->tm_mday;
1598 CVAL(p,17) = t->tm_mon + 1;
1599 SSVAL(p,18,1900+t->tm_year);
1600 CVAL(p,20) = t->tm_wday;
1607 /****************************************************************************
1608 set the user password
1609 ****************************************************************************/
1610 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1611 int mdrcnt,int mprcnt,
1612 char **rdata,char **rparam,
1613 int *rdata_len,int *rparam_len)
1615 char *p = skip_string(param+2,2);
1617 fstring pass1,pass2;
1621 p = skip_string(p,1);
1624 memcpy(pass2,p+16,16);
1627 *rparam = REALLOC(*rparam,*rparam_len);
1631 SSVAL(*rparam,0,NERR_badpass);
1632 SSVAL(*rparam,2,0); /* converter word */
1634 DEBUG(3,("Set password for <%s>\n",user));
1637 * Pass the user through the NT -> unix user mapping
1641 (void)map_username(user);
1644 * Do any UNIX username case mangling.
1646 (void)Get_Pwnam( user, True);
1649 * Attempt the plaintext password change first.
1650 * Older versions of Windows seem to do this.
1653 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1654 chgpasswd(user,pass1,pass2,False))
1656 SSVAL(*rparam,0,NERR_Success);
1660 * If the plaintext change failed, attempt
1661 * the encrypted. NT will generate this
1662 * after trying the samr method.
1665 if(SVAL(*rparam,0) != NERR_Success)
1667 struct smb_passwd *sampw = NULL;
1669 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1670 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1672 SSVAL(*rparam,0,NERR_Success);
1676 bzero(pass1,sizeof(fstring));
1677 bzero(pass2,sizeof(fstring));
1682 /****************************************************************************
1683 Set the user password (SamOEM version - gets plaintext).
1684 ****************************************************************************/
1686 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1687 int mdrcnt,int mprcnt,
1688 char **rdata,char **rparam,
1689 int *rdata_len,int *rparam_len)
1693 struct smb_passwd *sampw = NULL;
1694 char *p = param + 2;
1698 *rparam = REALLOC(*rparam,*rparam_len);
1702 SSVAL(*rparam,0,NERR_badpass);
1705 * Check the parameter definition is correct.
1707 if(!strequal(param + 2, "zsT")) {
1708 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1711 p = skip_string(p, 1);
1713 if(!strequal(p, "B516B16")) {
1714 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1717 p = skip_string(p,1);
1720 p = skip_string(p,1);
1722 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1725 * Pass the user through the NT -> unix user mapping
1729 (void)map_username(user);
1732 * Do any UNIX username case mangling.
1734 (void)Get_Pwnam( user, True);
1736 if(check_oem_password( user, (unsigned char *)data, &sampw,
1737 new_passwd, (int)sizeof(new_passwd)) == False) {
1742 * At this point we have the new case-sensitive plaintext
1743 * password in the fstring new_passwd. If we wanted to synchronise
1744 * with UNIX passwords we would call a UNIX password changing
1745 * function here. However it would have to be done as root
1746 * as the plaintext of the old users password is not
1750 if(lp_unix_password_sync())
1751 ret = chgpasswd(user,"", new_passwd, True);
1753 if(ret && change_oem_password( sampw, new_passwd, False)) {
1754 SSVAL(*rparam,0,NERR_Success);
1760 /****************************************************************************
1763 ****************************************************************************/
1764 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1765 int mdrcnt,int mprcnt,
1766 char **rdata,char **rparam,
1767 int *rdata_len,int *rparam_len)
1769 int function = SVAL(param,0);
1770 char *str1 = param+2;
1771 char *str2 = skip_string(str1,1);
1772 char *p = skip_string(str2,1);
1776 printjob_decode(SVAL(p,0), &snum, &jobid);
1778 /* check it's a supported varient */
1779 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1783 *rparam = REALLOC(*rparam,*rparam_len);
1787 SSVAL(*rparam,0,NERR_Success);
1789 if (snum >= 0 && VALID_SNUM(snum))
1791 print_queue_struct *queue=NULL;
1793 count = get_printqueue(snum,conn,&queue,NULL);
1795 for (i=0;i<count;i++)
1796 if ((queue[i].job&0xFF) == jobid)
1799 case 81: /* delete */
1800 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1801 del_printqueue(conn,snum,queue[i].job);
1803 case 82: /* pause */
1804 case 83: /* resume */
1805 DEBUG(3,("%s queue entry %d\n",
1806 (function==82?"pausing":"resuming"),queue[i].job));
1807 status_printjob(conn,snum,queue[i].job,
1808 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1815 SSVAL(*rparam,0,NERR_JobNotFound);
1817 if (queue) free(queue);
1820 SSVAL(*rparam,2,0); /* converter word */
1825 /****************************************************************************
1826 Purge a print queue - or pause or resume it.
1827 ****************************************************************************/
1828 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1829 int mdrcnt,int mprcnt,
1830 char **rdata,char **rparam,
1831 int *rdata_len,int *rparam_len)
1833 int function = SVAL(param,0);
1834 char *str1 = param+2;
1835 char *str2 = skip_string(str1,1);
1836 char *QueueName = skip_string(str2,1);
1839 /* check it's a supported varient */
1840 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1844 *rparam = REALLOC(*rparam,*rparam_len);
1848 SSVAL(*rparam,0,NERR_Success);
1849 SSVAL(*rparam,2,0); /* converter word */
1851 snum = lp_servicenumber(QueueName);
1852 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1853 int pnum = lp_servicenumber(PRINTERS_NAME);
1855 lp_add_printer(QueueName,pnum);
1856 snum = lp_servicenumber(QueueName);
1860 if (snum >= 0 && VALID_SNUM(snum)) {
1864 case 74: /* Pause queue */
1865 case 75: /* Resume queue */
1866 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1867 DEBUG(3,("Print queue %s, queue=%s\n",
1868 (function==74?"pause":"resume"),QueueName));
1870 case 103: /* Purge */
1872 print_queue_struct *queue=NULL;
1874 count = get_printqueue(snum,conn,&queue,NULL);
1875 for (i = 0; i < count; i++)
1876 del_printqueue(conn,snum,queue[i].job);
1878 if (queue) free(queue);
1879 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1889 /****************************************************************************
1890 set the property of a print job (undocumented?)
1891 ? function = 0xb -> set name of print job
1892 ? function = 0x6 -> move print job up/down
1893 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1894 or <WWsTP> <WB21BB16B10zWWzDDz>
1895 ****************************************************************************/
1896 static int check_printjob_info(struct pack_desc* desc,
1897 int uLevel, char* id)
1899 desc->subformat = NULL;
1901 case 0: desc->format = "W"; break;
1902 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1903 case 2: desc->format = "WWzWWDDzz"; break;
1904 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1905 default: return False;
1907 if (strcmp(desc->format,id) != 0) return False;
1911 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1912 int mdrcnt,int mprcnt,
1913 char **rdata,char **rparam,
1914 int *rdata_len,int *rparam_len)
1916 struct pack_desc desc;
1917 char *str1 = param+2;
1918 char *str2 = skip_string(str1,1);
1919 char *p = skip_string(str2,1);
1921 int uLevel = SVAL(p,2);
1922 int function = SVAL(p,4); /* what is this ?? */
1926 printjob_decode(SVAL(p,0), &snum, &jobid);
1929 *rparam = REALLOC(*rparam,*rparam_len);
1933 /* check it's a supported varient */
1934 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1938 case 0x6: /* change job place in the queue, data gives the new place */
1939 if (snum >= 0 && VALID_SNUM(snum))
1941 print_queue_struct *queue=NULL;
1945 count = get_printqueue(snum,conn,&queue,NULL);
1946 for (i=0;i<count;i++) /* find job */
1947 if ((queue[i].job&0xFF) == jobid) break;
1950 desc.errcode=NERR_JobNotFound;
1951 if (queue) free(queue);
1954 desc.errcode=NERR_Success;
1958 int place= SVAL(data,0);
1959 /* we currently have no way of doing this. Can any unix do it? */
1960 if (i < place) /* move down */;
1961 else if (i > place ) /* move up */;
1964 desc.errcode=NERR_notsupported; /* not yet supported */
1965 if (queue) free(queue);
1968 else desc.errcode=NERR_JobNotFound;
1970 case 0xb: /* change print job name, data gives the name */
1971 /* jobid, snum should be zero */
1978 if (issafe(*s)) name[l++] = *s;
1983 DEBUG(3,("Setting print name to %s\n",name));
1987 for (i=0;i<MAX_FNUMS;i++)
1988 if (Files[i].open && Files[i].print_file)
1991 connection_struct *fconn = Files[i].conn;
1995 if (!become_user(fconn,vuid) ||
1996 !become_service(fconn,True))
1999 if (sys_rename(Files[i].fsp_name,name) == 0) {
2000 string_set(&Files[i].fsp_name,name);
2005 unbecome_root(True);
2007 desc.errcode=NERR_Success;
2010 default: /* not implemented */
2014 SSVALS(*rparam,0,desc.errcode);
2015 SSVAL(*rparam,2,0); /* converter word */
2021 /****************************************************************************
2022 get info about the server
2023 ****************************************************************************/
2024 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2025 int mdrcnt,int mprcnt,
2026 char **rdata,char **rparam,
2027 int *rdata_len,int *rparam_len)
2029 char *str1 = param+2;
2030 char *str2 = skip_string(str1,1);
2031 char *p = skip_string(str2,1);
2032 int uLevel = SVAL(p,0);
2036 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2038 /* check it's a supported varient */
2039 if (!prefix_ok(str1,"WrLh")) return False;
2042 if (strcmp(str2,"B16") != 0) return False;
2046 if (strcmp(str2,"B16BBDz") != 0) return False;
2050 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2055 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2060 if (strcmp(str2,"DN") != 0) return False;
2064 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2067 default: return False;
2070 *rdata_len = mdrcnt;
2071 *rdata = REALLOC(*rdata,*rdata_len);
2074 p2 = p + struct_len;
2076 StrnCpy(p,local_machine,16);
2082 struct srv_info_struct *servers=NULL;
2085 uint32 servertype= lp_default_server_announce();
2087 pstrcpy(comment,lp_serverstring());
2089 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2090 for (i=0;i<count;i++)
2091 if (strequal(servers[i].name,local_machine))
2093 servertype = servers[i].type;
2094 pstrcpy(comment,servers[i].comment);
2097 if (servers) free(servers);
2099 SCVAL(p,0,lp_major_announce_version());
2100 SCVAL(p,1,lp_minor_announce_version());
2101 SIVAL(p,2,servertype);
2103 if (mdrcnt == struct_len) {
2106 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2107 standard_sub(conn,comment);
2108 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2109 p2 = skip_string(p2,1);
2114 return False; /* not yet implemented */
2117 *rdata_len = PTR_DIFF(p2,*rdata);
2120 *rparam = REALLOC(*rparam,*rparam_len);
2121 SSVAL(*rparam,0,NERR_Success);
2122 SSVAL(*rparam,2,0); /* converter word */
2123 SSVAL(*rparam,4,*rdata_len);
2129 /****************************************************************************
2130 get info about the server
2131 ****************************************************************************/
2132 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2133 int mdrcnt,int mprcnt,
2134 char **rdata,char **rparam,
2135 int *rdata_len,int *rparam_len)
2137 char *str1 = param+2;
2138 char *str2 = skip_string(str1,1);
2139 char *p = skip_string(str2,1);
2141 extern pstring sesssetup_user;
2142 int level = SVAL(p,0);
2144 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2147 *rparam = REALLOC(*rparam,*rparam_len);
2149 /* check it's a supported varient */
2150 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2153 *rdata_len = mdrcnt + 1024;
2154 *rdata = REALLOC(*rdata,*rdata_len);
2156 SSVAL(*rparam,0,NERR_Success);
2157 SSVAL(*rparam,2,0); /* converter word */
2163 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2164 pstrcpy(p2,local_machine);
2166 p2 = skip_string(p2,1);
2169 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2170 pstrcpy(p2,sesssetup_user);
2171 p2 = skip_string(p2,1);
2174 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2175 pstrcpy(p2,global_myworkgroup);
2177 p2 = skip_string(p2,1);
2180 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2181 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2184 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2185 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2186 p2 = skip_string(p2,1);
2189 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2191 p2 = skip_string(p2,1);
2194 *rdata_len = PTR_DIFF(p2,*rdata);
2196 SSVAL(*rparam,4,*rdata_len);
2201 /****************************************************************************
2202 get info about a user
2204 struct user_info_11 {
2205 char usri11_name[21]; 0-20
2207 char *usri11_comment; 22-25
2208 char *usri11_usr_comment; 26-29
2209 unsigned short usri11_priv; 30-31
2210 unsigned long usri11_auth_flags; 32-35
2211 long usri11_password_age; 36-39
2212 char *usri11_homedir; 40-43
2213 char *usri11_parms; 44-47
2214 long usri11_last_logon; 48-51
2215 long usri11_last_logoff; 52-55
2216 unsigned short usri11_bad_pw_count; 56-57
2217 unsigned short usri11_num_logons; 58-59
2218 char *usri11_logon_server; 60-63
2219 unsigned short usri11_country_code; 64-65
2220 char *usri11_workstations; 66-69
2221 unsigned long usri11_max_storage; 70-73
2222 unsigned short usri11_units_per_week; 74-75
2223 unsigned char *usri11_logon_hours; 76-79
2224 unsigned short usri11_code_page; 80-81
2229 usri11_name specifies the user name for which information is retireved
2231 usri11_pad aligns the next data structure element to a word boundary
2233 usri11_comment is a null terminated ASCII comment
2235 usri11_user_comment is a null terminated ASCII comment about the user
2237 usri11_priv specifies the level of the privilege assigned to the user.
2238 The possible values are:
2240 Name Value Description
2241 USER_PRIV_GUEST 0 Guest privilege
2242 USER_PRIV_USER 1 User privilege
2243 USER_PRV_ADMIN 2 Administrator privilege
2245 usri11_auth_flags specifies the account operator privileges. The
2246 possible values are:
2248 Name Value Description
2249 AF_OP_PRINT 0 Print operator
2252 Leach, Naik [Page 28]
\r\f
2255 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2258 AF_OP_COMM 1 Communications operator
2259 AF_OP_SERVER 2 Server operator
2260 AF_OP_ACCOUNTS 3 Accounts operator
2263 usri11_password_age specifies how many seconds have elapsed since the
2264 password was last changed.
2266 usri11_home_dir points to a null terminated ASCII string that contains
2267 the path name of the user's home directory.
2269 usri11_parms points to a null terminated ASCII string that is set
2270 aside for use by applications.
2272 usri11_last_logon specifies the time when the user last logged on.
2273 This value is stored as the number of seconds elapsed since
2274 00:00:00, January 1, 1970.
2276 usri11_last_logoff specifies the time when the user last logged off.
2277 This value is stored as the number of seconds elapsed since
2278 00:00:00, January 1, 1970. A value of 0 means the last logoff
2281 usri11_bad_pw_count specifies the number of incorrect passwords
2282 entered since the last successful logon.
2284 usri11_log1_num_logons specifies the number of times this user has
2285 logged on. A value of -1 means the number of logons is unknown.
2287 usri11_logon_server points to a null terminated ASCII string that
2288 contains the name of the server to which logon requests are sent.
2289 A null string indicates logon requests should be sent to the
2292 usri11_country_code specifies the country code for the user's language
2295 usri11_workstations points to a null terminated ASCII string that
2296 contains the names of workstations the user may log on from.
2297 There may be up to 8 workstations, with the names separated by
2298 commas. A null strings indicates there are no restrictions.
2300 usri11_max_storage specifies the maximum amount of disk space the user
2301 can occupy. A value of 0xffffffff indicates there are no
2304 usri11_units_per_week specifies the equal number of time units into
2305 which a week is divided. This value must be equal to 168.
2307 usri11_logon_hours points to a 21 byte (168 bits) string that
2308 specifies the time during which the user can log on. Each bit
2309 represents one unique hour in a week. The first bit (bit 0, word
2310 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2314 Leach, Naik [Page 29]
\r\f
2317 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2320 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2321 are no restrictions.
2323 usri11_code_page specifies the code page for the user's language of
2326 All of the pointers in this data structure need to be treated
2327 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2328 to be ignored. The converter word returned in the parameters section
2329 needs to be subtracted from the lower 16 bits to calculate an offset
2330 into the return buffer where this ASCII string resides.
2332 There is no auxiliary data in the response.
2334 ****************************************************************************/
2336 #define usri11_name 0
2337 #define usri11_pad 21
2338 #define usri11_comment 22
2339 #define usri11_usr_comment 26
2340 #define usri11_full_name 30
2341 #define usri11_priv 34
2342 #define usri11_auth_flags 36
2343 #define usri11_password_age 40
2344 #define usri11_homedir 44
2345 #define usri11_parms 48
2346 #define usri11_last_logon 52
2347 #define usri11_last_logoff 56
2348 #define usri11_bad_pw_count 60
2349 #define usri11_num_logons 62
2350 #define usri11_logon_server 64
2351 #define usri11_country_code 68
2352 #define usri11_workstations 70
2353 #define usri11_max_storage 74
2354 #define usri11_units_per_week 78
2355 #define usri11_logon_hours 80
2356 #define usri11_code_page 84
2357 #define usri11_end 86
2359 #define USER_PRIV_GUEST 0
2360 #define USER_PRIV_USER 1
2361 #define USER_PRIV_ADMIN 2
2363 #define AF_OP_PRINT 0
2364 #define AF_OP_COMM 1
2365 #define AF_OP_SERVER 2
2366 #define AF_OP_ACCOUNTS 3
2369 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2370 int mdrcnt,int mprcnt,
2371 char **rdata,char **rparam,
2372 int *rdata_len,int *rparam_len)
2374 char *str1 = param+2;
2375 char *str2 = skip_string(str1,1);
2376 char *UserName = skip_string(str2,1);
2377 char *p = skip_string(UserName,1);
2378 int uLevel = SVAL(p,0);
2381 /* get NIS home of a previously validated user - simeon */
2382 /* With share level security vuid will always be zero.
2383 Don't depend on vuser being non-null !!. JRA */
2384 user_struct *vuser = get_valid_user_struct(vuid);
2386 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2389 *rparam = REALLOC(*rparam,*rparam_len);
2391 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2393 /* check it's a supported variant */
2394 if (strcmp(str1,"zWrLh") != 0) return False;
2397 case 0: p2 = "B21"; break;
2398 case 1: p2 = "B21BB16DWzzWz"; break;
2399 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2400 case 10: p2 = "B21Bzzz"; break;
2401 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2402 default: return False;
2405 if (strcmp(p2,str2) != 0) return False;
2407 *rdata_len = mdrcnt + 1024;
2408 *rdata = REALLOC(*rdata,*rdata_len);
2410 SSVAL(*rparam,0,NERR_Success);
2411 SSVAL(*rparam,2,0); /* converter word */
2414 p2 = p + usri11_end;
2417 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2421 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2426 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2427 pstrcpy(p2,"Comment");
2428 p2 = skip_string(p2,1);
2430 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2431 pstrcpy(p2,"UserComment");
2432 p2 = skip_string(p2,1);
2434 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2435 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2436 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2437 p2 = skip_string(p2,1);
2440 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2442 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2443 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2444 SIVALS(p,usri11_password_age,-1); /* password age */
2445 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2446 pstrcpy(p2, lp_logon_path());
2447 p2 = skip_string(p2,1);
2448 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2450 p2 = skip_string(p2,1);
2451 SIVAL(p,usri11_last_logon,0); /* last logon */
2452 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2453 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2454 SSVALS(p,usri11_num_logons,-1); /* num logons */
2455 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2456 pstrcpy(p2,"\\\\*");
2457 p2 = skip_string(p2,1);
2458 SSVAL(p,usri11_country_code,0); /* country code */
2460 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2462 p2 = skip_string(p2,1);
2464 SIVALS(p,usri11_max_storage,-1); /* max storage */
2465 SSVAL(p,usri11_units_per_week,168); /* units per week */
2466 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2468 /* a simple way to get logon hours at all times. */
2470 SCVAL(p2,21,0); /* fix zero termination */
2471 p2 = skip_string(p2,1);
2473 SSVAL(p,usri11_code_page,0); /* code page */
2475 if (uLevel == 1 || uLevel == 2)
2477 memset(p+22,' ',16); /* password */
2478 SIVALS(p,38,-1); /* password age */
2480 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2481 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2482 pstrcpy(p2,lp_logon_path());
2483 p2 = skip_string(p2,1);
2484 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2486 SSVAL(p,52,0); /* flags */
2487 SIVAL(p,54,0); /* script_path */
2490 SIVAL(p,60,0); /* auth_flags */
2491 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2492 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2493 p2 = skip_string(p2,1);
2494 SIVAL(p,68,0); /* urs_comment */
2495 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2497 p2 = skip_string(p2,1);
2498 SIVAL(p,76,0); /* workstations */
2499 SIVAL(p,80,0); /* last_logon */
2500 SIVAL(p,84,0); /* last_logoff */
2501 SIVALS(p,88,-1); /* acct_expires */
2502 SIVALS(p,92,-1); /* max_storage */
2503 SSVAL(p,96,168); /* units_per_week */
2504 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2507 SSVALS(p,102,-1); /* bad_pw_count */
2508 SSVALS(p,104,-1); /* num_logons */
2509 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2510 pstrcpy(p2,"\\\\%L");
2511 standard_sub_basic(p2);
2512 p2 = skip_string(p2,1);
2513 SSVAL(p,110,49); /* country_code */
2514 SSVAL(p,112,860); /* code page */
2518 *rdata_len = PTR_DIFF(p2,*rdata);
2520 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2525 /*******************************************************************
2526 get groups that a user is a member of
2527 ******************************************************************/
2528 static BOOL api_NetUserGetGroups(connection_struct *conn,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 *UserName = skip_string(str2,1);
2536 char *p = skip_string(UserName,1);
2537 int uLevel = SVAL(p,0);
2542 *rparam = REALLOC(*rparam,*rparam_len);
2544 /* check it's a supported varient */
2545 if (strcmp(str1,"zWrLeh") != 0) return False;
2547 case 0: p2 = "B21"; break;
2548 default: return False;
2550 if (strcmp(p2,str2) != 0) return False;
2552 *rdata_len = mdrcnt + 1024;
2553 *rdata = REALLOC(*rdata,*rdata_len);
2555 SSVAL(*rparam,0,NERR_Success);
2556 SSVAL(*rparam,2,0); /* converter word */
2560 /* XXXX we need a real SAM database some day */
2561 pstrcpy(p,"Users"); p += 21; count++;
2562 pstrcpy(p,"Domain Users"); p += 21; count++;
2563 pstrcpy(p,"Guests"); p += 21; count++;
2564 pstrcpy(p,"Domain Guests"); p += 21; count++;
2566 *rdata_len = PTR_DIFF(p,*rdata);
2568 SSVAL(*rparam,4,count); /* is this right?? */
2569 SSVAL(*rparam,6,count); /* is this right?? */
2575 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2576 int mdrcnt,int mprcnt,
2577 char **rdata,char **rparam,
2578 int *rdata_len,int *rparam_len)
2580 char *str1 = param+2;
2581 char *str2 = skip_string(str1,1);
2582 char *p = skip_string(str2,1);
2584 struct pack_desc desc;
2591 bzero(&desc,sizeof(desc));
2593 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2595 /* check it's a supported varient */
2596 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2597 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2598 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2600 desc.buflen = mdrcnt;
2601 desc.subformat = NULL;
2604 if (init_package(&desc,1,0))
2606 PACKI(&desc,"W",0); /* code */
2607 PACKS(&desc,"B21",name); /* eff. name */
2608 PACKS(&desc,"B",""); /* pad */
2610 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2611 PACKI(&desc,"D",0); /* auth flags XXX */
2612 PACKI(&desc,"W",0); /* num logons */
2613 PACKI(&desc,"W",0); /* bad pw count */
2614 PACKI(&desc,"D",0); /* last logon */
2615 PACKI(&desc,"D",-1); /* last logoff */
2616 PACKI(&desc,"D",-1); /* logoff time */
2617 PACKI(&desc,"D",-1); /* kickoff time */
2618 PACKI(&desc,"D",0); /* password age */
2619 PACKI(&desc,"D",0); /* password can change */
2620 PACKI(&desc,"D",-1); /* password must change */
2623 fstrcpy(mypath,"\\\\");
2624 fstrcat(mypath,local_machine);
2626 PACKS(&desc,"z",mypath); /* computer */
2628 PACKS(&desc,"z",global_myworkgroup);/* domain */
2630 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2631 /* made sure all macros are fully substituted and available */
2632 logon_script = lp_logon_script();
2633 standard_sub( conn, logon_script );
2634 PACKS(&desc,"z", logon_script); /* script path */
2635 /* End of JHT mods */
2637 PACKI(&desc,"D",0x00000000); /* reserved */
2640 *rdata_len = desc.usedlen;
2642 *rparam = REALLOC(*rparam,*rparam_len);
2643 SSVALS(*rparam,0,desc.errcode);
2645 SSVAL(*rparam,4,desc.neededlen);
2647 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2652 /****************************************************************************
2653 api_WAccessGetUserPerms
2654 ****************************************************************************/
2655 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2656 int mdrcnt,int mprcnt,
2657 char **rdata,char **rparam,
2658 int *rdata_len,int *rparam_len)
2660 char *str1 = param+2;
2661 char *str2 = skip_string(str1,1);
2662 char *user = skip_string(str2,1);
2663 char *resource = skip_string(user,1);
2665 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2667 /* check it's a supported varient */
2668 if (strcmp(str1,"zzh") != 0) return False;
2669 if (strcmp(str2,"") != 0) return False;
2672 *rparam = REALLOC(*rparam,*rparam_len);
2673 SSVALS(*rparam,0,0); /* errorcode */
2674 SSVAL(*rparam,2,0); /* converter word */
2675 SSVAL(*rparam,4,0x7f); /* permission flags */
2680 /****************************************************************************
2681 api_WPrintJobEnumerate
2682 ****************************************************************************/
2683 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2684 int mdrcnt,int mprcnt,
2685 char **rdata,char **rparam,
2686 int *rdata_len,int *rparam_len)
2688 char *str1 = param+2;
2689 char *str2 = skip_string(str1,1);
2690 char *p = skip_string(str2,1);
2696 struct pack_desc desc;
2697 print_queue_struct *queue=NULL;
2698 print_status_struct status;
2703 bzero(&desc,sizeof(desc));
2704 bzero(&status,sizeof(status));
2706 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2708 /* check it's a supported varient */
2709 if (strcmp(str1,"WWrLh") != 0) return False;
2710 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2712 printjob_decode(SVAL(p,0), &snum, &job);
2714 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2716 count = get_printqueue(snum,conn,&queue,&status);
2717 for (i = 0; i < count; i++) {
2718 if ((queue[i].job & 0xFF) == job) break;
2720 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2722 desc.buflen = mdrcnt;
2724 if (init_package(&desc,1,0)) {
2726 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2727 *rdata_len = desc.usedlen;
2730 desc.errcode = NERR_JobNotFound;
2736 *rparam = REALLOC(*rparam,*rparam_len);
2737 SSVALS(*rparam,0,desc.errcode);
2739 SSVAL(*rparam,4,desc.neededlen);
2741 if (queue) free(queue);
2743 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2747 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2748 int mdrcnt,int mprcnt,
2749 char **rdata,char **rparam,
2750 int *rdata_len,int *rparam_len)
2752 char *str1 = param+2;
2753 char *str2 = skip_string(str1,1);
2754 char *p = skip_string(str2,1);
2760 struct pack_desc desc;
2761 print_queue_struct *queue=NULL;
2762 print_status_struct status;
2764 bzero(&desc,sizeof(desc));
2765 bzero(&status,sizeof(status));
2767 p = skip_string(p,1);
2771 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2773 /* check it's a supported varient */
2774 if (strcmp(str1,"zWrLeh") != 0) return False;
2775 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2776 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2778 snum = lp_servicenumber(name);
2779 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2780 int pnum = lp_servicenumber(PRINTERS_NAME);
2782 lp_add_printer(name,pnum);
2783 snum = lp_servicenumber(name);
2787 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2789 count = get_printqueue(snum,conn,&queue,&status);
2790 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2792 desc.buflen = mdrcnt;
2794 if (init_package(&desc,count,0)) {
2796 for (i = 0; i < count; i++) {
2797 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2798 if (desc.errcode == NERR_Success) succnt = i+1;
2802 *rdata_len = desc.usedlen;
2805 *rparam = REALLOC(*rparam,*rparam_len);
2806 SSVALS(*rparam,0,desc.errcode);
2808 SSVAL(*rparam,4,succnt);
2809 SSVAL(*rparam,6,count);
2811 if (queue) free(queue);
2813 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2817 static int check_printdest_info(struct pack_desc* desc,
2818 int uLevel, char* id)
2820 desc->subformat = NULL;
2822 case 0: desc->format = "B9"; break;
2823 case 1: desc->format = "B9B21WWzW"; break;
2824 case 2: desc->format = "z"; break;
2825 case 3: desc->format = "zzzWWzzzWW"; break;
2826 default: return False;
2828 if (strcmp(desc->format,id) != 0) return False;
2832 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2833 struct pack_desc* desc)
2836 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2837 buf[sizeof(buf)-1] = 0;
2840 PACKS(desc,"B9",buf); /* szName */
2842 PACKS(desc,"B21",""); /* szUserName */
2843 PACKI(desc,"W",0); /* uJobId */
2844 PACKI(desc,"W",0); /* fsStatus */
2845 PACKS(desc,"z",""); /* pszStatus */
2846 PACKI(desc,"W",0); /* time */
2849 if (uLevel == 2 || uLevel == 3) {
2850 PACKS(desc,"z",buf); /* pszPrinterName */
2852 PACKS(desc,"z",""); /* pszUserName */
2853 PACKS(desc,"z",""); /* pszLogAddr */
2854 PACKI(desc,"W",0); /* uJobId */
2855 PACKI(desc,"W",0); /* fsStatus */
2856 PACKS(desc,"z",""); /* pszStatus */
2857 PACKS(desc,"z",""); /* pszComment */
2858 PACKS(desc,"z","NULL"); /* pszDrivers */
2859 PACKI(desc,"W",0); /* time */
2860 PACKI(desc,"W",0); /* pad1 */
2865 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2866 int mdrcnt,int mprcnt,
2867 char **rdata,char **rparam,
2868 int *rdata_len,int *rparam_len)
2870 char *str1 = param+2;
2871 char *str2 = skip_string(str1,1);
2872 char *p = skip_string(str2,1);
2873 char* PrinterName = p;
2875 struct pack_desc desc;
2878 bzero(&desc,sizeof(desc));
2880 p = skip_string(p,1);
2884 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2886 /* check it's a supported varient */
2887 if (strcmp(str1,"zWrLh") != 0) return False;
2888 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2890 snum = lp_servicenumber(PrinterName);
2891 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2892 int pnum = lp_servicenumber(PRINTERS_NAME);
2894 lp_add_printer(PrinterName,pnum);
2895 snum = lp_servicenumber(PrinterName);
2901 desc.errcode = NERR_DestNotFound;
2905 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2907 desc.buflen = mdrcnt;
2908 if (init_package(&desc,1,0)) {
2909 fill_printdest_info(conn,snum,uLevel,&desc);
2911 *rdata_len = desc.usedlen;
2915 *rparam = REALLOC(*rparam,*rparam_len);
2916 SSVALS(*rparam,0,desc.errcode);
2918 SSVAL(*rparam,4,desc.neededlen);
2920 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2924 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2925 int mdrcnt,int mprcnt,
2926 char **rdata,char **rparam,
2927 int *rdata_len,int *rparam_len)
2929 char *str1 = param+2;
2930 char *str2 = skip_string(str1,1);
2931 char *p = skip_string(str2,1);
2935 struct pack_desc desc;
2936 int services = lp_numservices();
2938 bzero(&desc,sizeof(desc));
2943 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2945 /* check it's a supported varient */
2946 if (strcmp(str1,"WrLeh") != 0) return False;
2947 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2950 for (i = 0; i < services; i++)
2951 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2954 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2956 desc.buflen = mdrcnt;
2957 if (init_package(&desc,queuecnt,0)) {
2960 for (i = 0; i < services; i++) {
2961 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2962 fill_printdest_info(conn,i,uLevel,&desc);
2964 if (desc.errcode == NERR_Success) succnt = n;
2969 *rdata_len = desc.usedlen;
2972 *rparam = REALLOC(*rparam,*rparam_len);
2973 SSVALS(*rparam,0,desc.errcode);
2975 SSVAL(*rparam,4,succnt);
2976 SSVAL(*rparam,6,queuecnt);
2978 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2982 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2983 int mdrcnt,int mprcnt,
2984 char **rdata,char **rparam,
2985 int *rdata_len,int *rparam_len)
2987 char *str1 = param+2;
2988 char *str2 = skip_string(str1,1);
2989 char *p = skip_string(str2,1);
2992 struct pack_desc desc;
2994 bzero(&desc,sizeof(desc));
2999 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3001 /* check it's a supported varient */
3002 if (strcmp(str1,"WrLeh") != 0) return False;
3003 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3005 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3007 desc.buflen = mdrcnt;
3008 if (init_package(&desc,1,0)) {
3009 PACKS(&desc,"B41","NULL");
3012 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3014 *rdata_len = desc.usedlen;
3017 *rparam = REALLOC(*rparam,*rparam_len);
3018 SSVALS(*rparam,0,desc.errcode);
3020 SSVAL(*rparam,4,succnt);
3023 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3027 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3028 int mdrcnt,int mprcnt,
3029 char **rdata,char **rparam,
3030 int *rdata_len,int *rparam_len)
3032 char *str1 = param+2;
3033 char *str2 = skip_string(str1,1);
3034 char *p = skip_string(str2,1);
3037 struct pack_desc desc;
3039 bzero(&desc,sizeof(desc));
3044 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3046 /* check it's a supported varient */
3047 if (strcmp(str1,"WrLeh") != 0) return False;
3048 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3050 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3052 desc.buflen = mdrcnt;
3054 if (init_package(&desc,1,0)) {
3055 PACKS(&desc,"B13","lpd");
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,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3073 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3074 int mdrcnt,int mprcnt,
3075 char **rdata,char **rparam,
3076 int *rdata_len,int *rparam_len)
3078 char *str1 = param+2;
3079 char *str2 = skip_string(str1,1);
3080 char *p = skip_string(str2,1);
3083 struct pack_desc desc;
3085 bzero(&desc,sizeof(desc));
3090 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3092 /* check it's a supported varient */
3093 if (strcmp(str1,"WrLeh") != 0) return False;
3094 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3096 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3097 bzero(&desc,sizeof(desc));
3099 desc.buflen = mdrcnt;
3101 if (init_package(&desc,1,0)) {
3102 PACKS(&desc,"B13","lp0");
3105 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3107 *rdata_len = desc.usedlen;
3110 *rparam = REALLOC(*rparam,*rparam_len);
3111 SSVALS(*rparam,0,desc.errcode);
3113 SSVAL(*rparam,4,succnt);
3116 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3122 char * pipe_clnt_name;
3123 char * pipe_srv_name;
3124 BOOL (*fn) (pipes_struct *, prs_struct *);
3127 static struct api_cmd api_fd_commands[] =
3129 { "lsarpc", "lsass", api_ntlsa_rpc },
3130 { "samr", "lsass", api_samr_rpc },
3131 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3132 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3133 { "NETLOGON", "lsass", api_netlog_rpc },
3134 { "winreg", "winreg", api_reg_rpc },
3135 { NULL, NULL, NULL }
3138 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3140 BOOL ntlmssp_auth = False;
3141 fstring ack_pipe_name;
3144 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3146 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3148 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3149 api_fd_commands[i].fn != NULL)
3151 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3152 api_fd_commands[i].pipe_clnt_name,
3153 api_fd_commands[i].pipe_srv_name));
3154 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3159 if (api_fd_commands[i].fn == NULL) return False;
3161 /* decode the bind request */
3162 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3164 if (pd->offset == 0) return False;
3166 if (p->hdr.auth_len != 0)
3168 /* decode the authentication verifier */
3169 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3171 if (pd->offset == 0) return False;
3173 /* ignore the version number for now */
3174 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3177 /* name has to be \PIPE\xxxxx */
3178 fstrcpy(ack_pipe_name, "\\PIPE\\");
3179 fstrcat(ack_pipe_name, p->pipe_srv_name);
3181 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3183 prs_init(&(p->rdata), 1024, 4, 0, False);
3184 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3185 prs_init(&(p->rauth), 1024, 4, 0, False);
3188 /*** do the bind ack first ***/
3191 make_rpc_hdr_ba(&p->hdr_ba,
3192 p->hdr_rb.bba.max_tsize,
3193 p->hdr_rb.bba.max_rsize,
3194 p->hdr_rb.bba.assoc_gid,
3197 &(p->hdr_rb.transfer));
3199 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3200 mem_realloc_data(p->rdata.data, p->rdata.offset);
3203 /*** now the authentication ***/
3209 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3211 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3214 0x00000000, 0x0000b2b3, 0x000082b1,
3216 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3217 mem_realloc_data(p->rauth.data, p->rauth.offset);
3221 /*** then do the header, now we know the length ***/
3224 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3226 p->rdata.offset + p->rauth.offset,
3229 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3230 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3233 /*** link rpc header, bind acknowledgment and authentication responses ***/
3236 p->rhdr.data->offset.start = 0;
3237 p->rhdr.data->offset.end = p->rhdr.offset;
3238 p->rhdr.data->next = p->rdata.data;
3242 p->rdata.data->offset.start = p->rhdr.offset;
3243 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3244 p->rdata.data->next = p->rauth.data;
3246 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3247 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3248 p->rauth.data->next = NULL;
3252 p->rdata.data->offset.start = p->rhdr.offset;
3253 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3254 p->rdata.data->next = NULL;
3260 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3264 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3266 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3267 api_fd_commands[i].fn != NULL)
3269 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3270 return api_fd_commands[i].fn(p, pd);
3276 static BOOL api_dce_rpc_command(char *outbuf,
3281 if (pd->data == NULL) return False;
3283 /* process the rpc header */
3284 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3286 if (pd->offset == 0) return False;
3288 switch (p->hdr.pkt_type)
3292 reply = api_pipe_bind_req(p, pd);
3297 reply = api_pipe_request (p, pd);
3304 /* now send the reply */
3305 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3307 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3309 /* all of data was sent: no need to wait for SMBreadX calls */
3310 mem_free_data(p->rhdr .data);
3311 mem_free_data(p->rdata.data);
3318 /****************************************************************************
3319 SetNamedPipeHandleState
3320 ****************************************************************************/
3321 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3325 if (!param) return False;
3327 id = param[0] + (param[1] << 8);
3328 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3330 if (set_rpc_pipe_hnd_state(p, id))
3332 /* now send the reply */
3333 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3341 /****************************************************************************
3342 when no reply is generated, indicate unsupported.
3343 ****************************************************************************/
3344 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3346 struct mem_buf rparam;
3348 mem_init(&rparam, 0);
3349 mem_alloc_data(&rparam, 4);
3351 rparam.offset.start = 0;
3352 rparam.offset.end = 4;
3355 SSVAL(rparam.data,0,NERR_notsupported);
3356 SSVAL(rparam.data,2,0); /* converter word */
3358 DEBUG(3,("Unsupported API fd command\n"));
3360 /* now send the reply */
3361 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3363 mem_free_data(&rparam);
3368 /****************************************************************************
3369 handle remote api calls delivered to a named pipe already opened.
3370 ****************************************************************************/
3371 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3372 uint16 *setup,char *data,char *params,
3373 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3379 pipes_struct *p = NULL;
3381 struct mem_buf data_buf;
3383 DEBUG(5,("api_fd_reply\n"));
3385 /* fake up a data buffer from the api_fd_reply data parameters */
3386 mem_create(&data_buf, data, tdscnt, 0, False);
3387 data_buf.offset.start = 0;
3388 data_buf.offset.end = tdscnt;
3390 /* fake up a parsing structure */
3391 pd.data = &data_buf;
3396 /* First find out the name of this file. */
3399 DEBUG(0,("Unexpected named pipe transaction.\n"));
3403 /* Get the file handle and hence the file name. */
3405 subcommand = setup[0];
3406 get_rpc_pipe(pnum, &p);
3410 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3411 subcommand, p->name, pnum));
3413 /* record maximum data length that can be transmitted in an SMBtrans */
3414 p->file_offset = mdrcnt;
3416 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3417 p, p->file_offset));
3423 /* dce/rpc command */
3424 reply = api_dce_rpc_command(outbuf, p, &pd);
3429 /* Set Named Pipe Handle state */
3430 reply = api_SNPHS(outbuf, p, params);
3437 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3442 return api_no_reply(outbuf, mdrcnt);
3447 /****************************************************************************
3448 the buffer was too small
3449 ****************************************************************************/
3450 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3451 int mdrcnt,int mprcnt,
3452 char **rdata,char **rparam,
3453 int *rdata_len,int *rparam_len)
3455 *rparam_len = MIN(*rparam_len,mprcnt);
3456 *rparam = REALLOC(*rparam,*rparam_len);
3460 SSVAL(*rparam,0,NERR_BufTooSmall);
3462 DEBUG(3,("Supplied buffer too small in API command\n"));
3468 /****************************************************************************
3469 the request is not supported
3470 ****************************************************************************/
3471 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3472 int mdrcnt,int mprcnt,
3473 char **rdata,char **rparam,
3474 int *rdata_len,int *rparam_len)
3477 *rparam = REALLOC(*rparam,*rparam_len);
3481 SSVAL(*rparam,0,NERR_notsupported);
3482 SSVAL(*rparam,2,0); /* converter word */
3484 DEBUG(3,("Unsupported API command\n"));
3496 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3497 int,int,char **,char **,int *,int *);
3499 } api_commands[] = {
3500 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3501 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3502 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3503 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3504 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3505 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3506 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3507 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3508 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3509 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3510 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3511 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3512 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3513 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3514 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3515 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3516 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3517 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3518 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3519 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3520 {"NetServerEnum", 104, api_RNetServerEnum,0},
3521 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3522 {"SetUserPassword", 115, api_SetUserPassword,0},
3523 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3524 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3525 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3526 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3527 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3528 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3529 {NULL, -1, api_Unsupported,0}};
3532 /****************************************************************************
3533 handle remote api calls
3534 ****************************************************************************/
3535 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3536 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3538 int api_command = SVAL(params,0);
3539 struct mem_buf rdata_buf;
3540 struct mem_buf rparam_buf;
3542 char *rparam = NULL;
3548 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3549 api_command,params+2,skip_string(params+2,1),
3550 tdscnt,tpscnt,mdrcnt,mprcnt));
3552 for (i=0;api_commands[i].name;i++)
3553 if (api_commands[i].id == api_command && api_commands[i].fn)
3555 DEBUG(3,("Doing %s\n",api_commands[i].name));
3559 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3560 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3562 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3563 &rdata,&rparam,&rdata_len,&rparam_len);
3566 if (rdata_len > mdrcnt ||
3567 rparam_len > mprcnt)
3569 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3570 &rdata,&rparam,&rdata_len,&rparam_len);
3574 /* if we get False back then it's actually unsupported */
3576 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3577 &rdata,&rparam,&rdata_len,&rparam_len);
3580 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3581 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3583 rdata_buf.offset.start = 0;
3584 rdata_buf.offset.end = rdata_len;
3586 rparam_buf.offset.start = 0;
3587 rparam_buf.offset.end = rparam_len;
3589 /* now send the reply */
3590 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3592 if (rdata ) free(rdata);
3593 if (rparam) free(rparam);
3598 /****************************************************************************
3599 handle named pipe commands
3600 ****************************************************************************/
3601 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3602 uint16 *setup,char *data,char *params,
3603 int suwcnt,int tdscnt,int tpscnt,
3604 int msrcnt,int mdrcnt,int mprcnt)
3606 DEBUG(3,("named pipe command on <%s> name\n", name));
3608 if (strequal(name,"LANMAN"))
3610 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3613 if (strlen(name) < 1)
3615 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3620 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3627 /****************************************************************************
3629 ****************************************************************************/
3630 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3634 char *data=NULL,*params=NULL;
3637 uint16 vuid = SVAL(inbuf,smb_uid);
3638 int tpscnt = SVAL(inbuf,smb_vwv0);
3639 int tdscnt = SVAL(inbuf,smb_vwv1);
3640 int mprcnt = SVAL(inbuf,smb_vwv2);
3641 int mdrcnt = SVAL(inbuf,smb_vwv3);
3642 int msrcnt = CVAL(inbuf,smb_vwv4);
3643 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3644 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3645 int pscnt = SVAL(inbuf,smb_vwv9);
3646 int psoff = SVAL(inbuf,smb_vwv10);
3647 int dscnt = SVAL(inbuf,smb_vwv11);
3648 int dsoff = SVAL(inbuf,smb_vwv12);
3649 int suwcnt = CVAL(inbuf,smb_vwv13);
3651 bzero(name, sizeof(name));
3652 fstrcpy(name,smb_buf(inbuf));
3654 if (dscnt > tdscnt || pscnt > tpscnt) {
3655 exit_server("invalid trans parameters\n");
3659 data = (char *)malloc(tdscnt);
3660 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3664 params = (char *)malloc(tpscnt);
3665 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3670 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3671 for (i=0;i<suwcnt;i++)
3672 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3676 if (pscnt < tpscnt || dscnt < tdscnt) {
3677 /* We need to send an interim response then receive the rest
3678 of the parameter/data bytes */
3679 outsize = set_message(outbuf,0,0,True);
3681 send_smb(Client,outbuf);
3684 /* receive the rest of the trans packet */
3685 while (pscnt < tpscnt || dscnt < tdscnt) {
3687 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3689 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3691 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3693 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3695 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3696 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3698 if (params) free(params);
3699 if (data) free(data);
3700 if (setup) free(setup);
3701 return(ERROR(ERRSRV,ERRerror));
3706 tpscnt = SVAL(inbuf,smb_vwv0);
3707 tdscnt = SVAL(inbuf,smb_vwv1);
3709 pcnt = SVAL(inbuf,smb_vwv2);
3710 poff = SVAL(inbuf,smb_vwv3);
3711 pdisp = SVAL(inbuf,smb_vwv4);
3713 dcnt = SVAL(inbuf,smb_vwv5);
3714 doff = SVAL(inbuf,smb_vwv6);
3715 ddisp = SVAL(inbuf,smb_vwv7);
3720 if (dscnt > tdscnt || pscnt > tpscnt) {
3721 exit_server("invalid trans parameters\n");
3725 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3727 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3731 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3732 name,tdscnt,tpscnt,suwcnt));
3734 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3735 DEBUG(5,("calling named_pipe\n"));
3736 outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3737 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3739 DEBUG(3,("invalid pipe name\n"));
3744 if (data) free(data);
3745 if (params) free(params);
3746 if (setup) free(setup);
3748 if (close_on_completion)
3749 close_cnum(conn,vuid);
3755 return(ERROR(ERRSRV,ERRnosupport));