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;
40 extern fstring local_machine;
41 extern fstring global_myworkgroup;
43 #define NERR_Success 0
44 #define NERR_badpass 86
45 #define NERR_notsupported 50
47 #define NERR_BASE (2100)
48 #define NERR_BufTooSmall (NERR_BASE+23)
49 #define NERR_JobNotFound (NERR_BASE+51)
50 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ERROR_INVALID_LEVEL 124
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
63 extern int oplock_sock;
64 extern int smb_read_error;
66 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
67 int mdrcnt,int mprcnt,
68 char **rdata,char **rparam,
69 int *rdata_len,int *rparam_len);
70 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
71 int mdrcnt,int mprcnt,
72 char **rdata,char **rparam,
73 int *rdata_len,int *rparam_len);
76 static int CopyExpanded(connection_struct *conn,
77 int snum, char** dst, char* src, int* n)
82 if (!src || !dst || !n || !(*dst)) return(0);
84 StrnCpy(buf,src,sizeof(buf)/2);
85 string_sub(buf,"%S",lp_servicename(snum));
86 standard_sub(conn,buf);
94 static int CopyAndAdvance(char** dst, char* src, int* n)
97 if (!src || !dst || !n || !(*dst)) return(0);
105 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
109 StrnCpy(buf,s,sizeof(buf)/2);
110 string_sub(buf,"%S",lp_servicename(snum));
111 standard_sub(conn,buf);
112 return strlen(buf) + 1;
115 static char* Expand(connection_struct *conn, int snum, char* s)
118 if (!s) return(NULL);
119 StrnCpy(buf,s,sizeof(buf)/2);
120 string_sub(buf,"%S",lp_servicename(snum));
121 standard_sub(conn,buf);
125 /*******************************************************************
126 check a API string for validity when we only need to check the prefix
127 ******************************************************************/
128 static BOOL prefix_ok(char *str,char *prefix)
130 return(strncmp(str,prefix,strlen(prefix)) == 0);
133 /*******************************************************************
134 copies parameters and data, as needed, into the smb buffer
136 *both* the data and params sections should be aligned. this
137 is fudged in the rpc pipes by
138 at present, only the data section is. this may be a possible
139 cause of some of the ipc problems being experienced. lkcl26dec97
141 ******************************************************************/
142 static void copy_trans_params_and_data(char *outbuf, int align,
143 struct mem_buf *rparam, struct mem_buf *rdata,
144 int param_offset, int data_offset,
145 int param_len, int data_len)
147 char *copy_into = smb_buf(outbuf);
149 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
150 param_offset, param_offset + param_len,
151 data_offset , data_offset + data_len));
153 if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
154 copy_into += param_len + align;
155 if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
158 /****************************************************************************
160 ****************************************************************************/
161 static void send_trans_reply(char *outbuf,
162 struct mem_buf *rdata,
163 struct mem_buf *rparam,
164 uint16 *setup, int lsetup, int max_data_ret)
167 int this_ldata,this_lparam;
168 int tot_data=0,tot_param=0;
171 int ldata = rdata ? mem_buf_len(rdata ) : 0;
172 int lparam = rparam ? mem_buf_len(rparam) : 0;
174 BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
176 if (buffer_too_large)
178 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
179 ldata = max_data_ret;
182 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
183 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
185 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
186 /* if you don't want Net Monitor to decode your packets, do this!!! */
187 align = ((this_lparam+1)%4);
189 align = (this_lparam%4);
192 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
194 if (buffer_too_large)
196 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
197 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
198 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
201 copy_trans_params_and_data(outbuf, align,
203 tot_param , tot_data,
204 this_lparam, this_ldata);
206 SSVAL(outbuf,smb_vwv0,lparam);
207 SSVAL(outbuf,smb_vwv1,ldata);
208 SSVAL(outbuf,smb_vwv3,this_lparam);
209 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
210 SSVAL(outbuf,smb_vwv5,0);
211 SSVAL(outbuf,smb_vwv6,this_ldata);
212 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
213 SSVAL(outbuf,smb_vwv8,0);
214 SSVAL(outbuf,smb_vwv9,lsetup);
216 for (i=0;i<lsetup;i++)
218 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
222 send_smb(Client,outbuf);
224 tot_data = this_ldata;
225 tot_param = this_lparam;
227 while (tot_data < ldata || tot_param < lparam)
229 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
230 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
232 align = (this_lparam%4);
234 set_message(outbuf,10,this_ldata+this_lparam+align,False);
236 copy_trans_params_and_data(outbuf, align,
238 tot_param , tot_data,
239 this_lparam, this_ldata);
241 SSVAL(outbuf,smb_vwv3,this_lparam);
242 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
243 SSVAL(outbuf,smb_vwv5,tot_param);
244 SSVAL(outbuf,smb_vwv6,this_ldata);
245 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
246 SSVAL(outbuf,smb_vwv8,tot_data);
247 SSVAL(outbuf,smb_vwv9,0);
250 send_smb(Client,outbuf);
252 tot_data += this_ldata;
253 tot_param += this_lparam;
258 char* format; /* formatstring for structure */
259 char* subformat; /* subformat for structure */
260 char* base; /* baseaddress of buffer */
261 int buflen; /* remaining size for fixed part; on init: length of base */
262 int subcount; /* count of substructures */
263 char* structbuf; /* pointer into buffer for remaining fixed part */
264 int stringlen; /* remaining size for variable part */
265 char* stringbuf; /* pointer into buffer for remaining variable part */
266 int neededlen; /* total needed size */
267 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
268 char* curpos; /* current position; pointer into format or subformat */
272 static int get_counter(char** p)
275 if (!p || !(*p)) return(1);
276 if (!isdigit((int)**p)) return 1;
280 n = 10 * n + (i - '0');
287 static int getlen(char* p)
293 case 'W': /* word (2 byte) */
296 case 'N': /* count of substructures (word) at end */
299 case 'D': /* double word (4 byte) */
300 case 'z': /* offset to zero terminated string (4 byte) */
301 case 'l': /* offset to user data (4 byte) */
304 case 'b': /* offset to data (with counter) (4 byte) */
308 case 'B': /* byte (with optional counter) */
309 n += get_counter(&p);
316 static BOOL init_package(struct pack_desc* p, int count, int subcount)
321 if (!p->format || !p->base) return(False);
323 i = count * getlen(p->format);
324 if (p->subformat) i += subcount * getlen(p->subformat);
325 p->structbuf = p->base;
329 p->curpos = p->format;
333 p->errcode = ERRmoredata;
336 p->errcode = NERR_Success;
339 p->stringbuf = p->base + i;
341 return(p->errcode == NERR_Success);
345 static int package(struct pack_desc* p, ...)
348 static int package(va_alist)
354 int needed=0, stringneeded;
356 int is_string=0, stringused;
363 p = va_arg(args,struct pack_desc *);
368 p->curpos = p->format;
370 p->curpos = p->subformat;
375 str = va_arg(args,char*);
376 if (strncmp(str,p->curpos,strlen(str)) != 0) {
377 DEBUG(2,("type error in package: %s instead of %*s\n",str,
378 strlen(str),p->curpos));
380 smb_panic("invalid types in ipc");
386 if (!p->curpos) return(0);
388 switch( *p->curpos++ ) {
389 case 'W': /* word (2 byte) */
391 temp = va_arg(args,int);
392 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
394 case 'N': /* count of substructures (word) at end */
396 p->subcount = va_arg(args,int);
397 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
399 case 'D': /* double word (4 byte) */
401 temp = va_arg(args,int);
402 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
404 case 'B': /* byte (with optional counter) */
405 needed = get_counter(&p->curpos);
407 char *s = va_arg(args,char*);
408 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
411 case 'z': /* offset to zero terminated string (4 byte) */
412 str = va_arg(args,char*);
413 stringneeded = (str ? strlen(str)+1 : 0);
416 case 'l': /* offset to user data (4 byte) */
417 str = va_arg(args,char*);
418 stringneeded = va_arg(args,int);
421 case 'b': /* offset to data (with counter) (4 byte) */
422 str = va_arg(args,char*);
423 stringneeded = get_counter(&p->curpos);
428 if (stringneeded >= 0) {
430 if (p->buflen >= needed) {
431 stringused = stringneeded;
432 if (stringused > p->stringlen) {
433 stringused = (is_string ? p->stringlen : 0);
434 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
437 SIVAL(p->structbuf,0,0);
439 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
440 memcpy(p->stringbuf,str?str:"",stringused);
441 if (is_string) p->stringbuf[stringused-1] = '\0';
442 p->stringbuf += stringused;
443 p->stringlen -= stringused;
444 p->usedlen += stringused;
447 p->neededlen += stringneeded;
449 p->neededlen += needed;
450 if (p->buflen >= needed) {
451 p->structbuf += needed;
453 p->usedlen += needed;
456 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
462 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
463 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
465 #define PACK(desc,t,v) package(desc,v)
466 #define PACKl(desc,t,v,l) package(desc,v,l)
469 static void PACKI(struct pack_desc* desc,char *t,int v)
474 static void PACKS(struct pack_desc* desc,char *t,char *v)
480 /****************************************************************************
482 ****************************************************************************/
484 static void PackDriverData(struct pack_desc* desc)
486 char drivdata[4+4+32];
487 SIVAL(drivdata,0,sizeof drivdata); /* cb */
488 SIVAL(drivdata,4,1000); /* lVersion */
489 memset(drivdata+8,0,32); /* szDeviceName */
490 pstrcpy(drivdata+8,"NULL");
491 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
494 static int check_printq_info(struct pack_desc* desc,
495 int uLevel, char *id1, char *id2)
497 desc->subformat = NULL;
500 desc->format = "B13";
503 desc->format = "B13BWWWzzzzzWW";
506 desc->format = "B13BWWWzzzzzWN";
507 desc->subformat = "WB21BB16B10zWWzDDz";
510 desc->format = "zWWWWzzzzWWzzl";
513 desc->format = "zWWWWzzzzWNzzl";
514 desc->subformat = "WWzWWDDzz";
520 desc->format = "WzzzzzzzzN";
521 desc->subformat = "z";
523 default: return False;
525 if (strcmp(desc->format,id1) != 0) return False;
526 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
530 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
531 struct pack_desc* desc,
532 print_queue_struct* queue, int n)
534 time_t t = queue->time;
536 /* the client expects localtime */
539 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
541 PACKS(desc,"B21",queue->user); /* szUserName */
542 PACKS(desc,"B",""); /* pad */
543 PACKS(desc,"B16",""); /* szNotifyName */
544 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
545 PACKS(desc,"z",""); /* pszParms */
546 PACKI(desc,"W",n+1); /* uPosition */
547 PACKI(desc,"W",queue->status); /* fsStatus */
548 PACKS(desc,"z",""); /* pszStatus */
549 PACKI(desc,"D",t); /* ulSubmitted */
550 PACKI(desc,"D",queue->size); /* ulSize */
551 PACKS(desc,"z",queue->file); /* pszComment */
553 if (uLevel == 2 || uLevel == 3) {
554 PACKI(desc,"W",queue->priority); /* uPriority */
555 PACKS(desc,"z",queue->user); /* pszUserName */
556 PACKI(desc,"W",n+1); /* uPosition */
557 PACKI(desc,"W",queue->status); /* fsStatus */
558 PACKI(desc,"D",t); /* ulSubmitted */
559 PACKI(desc,"D",queue->size); /* ulSize */
560 PACKS(desc,"z","Samba"); /* pszComment */
561 PACKS(desc,"z",queue->file); /* pszDocument */
563 PACKS(desc,"z",""); /* pszNotifyName */
564 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
565 PACKS(desc,"z",""); /* pszParms */
566 PACKS(desc,"z",""); /* pszStatus */
567 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
568 PACKS(desc,"z","lpd"); /* pszQProcName */
569 PACKS(desc,"z",""); /* pszQProcParms */
570 PACKS(desc,"z","NULL"); /* pszDriverName */
571 PackDriverData(desc); /* pDriverData */
572 PACKS(desc,"z",""); /* pszPrinterName */
577 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
578 struct pack_desc* desc,
579 int count, print_queue_struct* queue,
580 print_status_struct* status)
585 PACKS(desc,"B13",SERVICE(snum));
590 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
594 if (uLevel == 1 || uLevel == 2) {
595 PACKS(desc,"B",""); /* alignment */
596 PACKI(desc,"W",5); /* priority */
597 PACKI(desc,"W",0); /* start time */
598 PACKI(desc,"W",0); /* until time */
599 PACKS(desc,"z",""); /* pSepFile */
600 PACKS(desc,"z","lpd"); /* pPrProc */
601 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
602 PACKS(desc,"z",""); /* pParms */
604 PACKS(desc,"z","UNKNOWN PRINTER");
605 PACKI(desc,"W",LPSTAT_ERROR);
607 else if (!status || !status->message[0]) {
608 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
609 PACKI(desc,"W",LPSTAT_OK); /* status */
611 PACKS(desc,"z",status->message);
612 PACKI(desc,"W",status->status); /* status */
614 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
616 if (uLevel == 3 || uLevel == 4) {
617 PACKI(desc,"W",5); /* uPriority */
618 PACKI(desc,"W",0); /* uStarttime */
619 PACKI(desc,"W",0); /* uUntiltime */
620 PACKI(desc,"W",5); /* pad1 */
621 PACKS(desc,"z",""); /* pszSepFile */
622 PACKS(desc,"z","WinPrint"); /* pszPrProc */
623 PACKS(desc,"z",""); /* pszParms */
624 if (!status || !status->message[0]) {
625 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
626 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
628 PACKS(desc,"z",status->message); /* pszComment */
629 PACKI(desc,"W",status->status); /* fsStatus */
631 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
632 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
633 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
634 PackDriverData(desc); /* pDriverData */
636 if (uLevel == 2 || uLevel == 4) {
638 for (i=0;i<count;i++)
639 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
644 pstring tok,driver,datafile,langmon,helpfile,datatype;
649 pstrcpy(fname,lp_driverfile());
652 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
653 desc->errcode=NERR_notsupported;
657 p=(char *)malloc(8192*sizeof(char));
658 bzero(p, 8192*sizeof(char));
661 /* lookup the long printer driver name in the file description */
662 while (f && !feof(f) && !ok)
664 p = q; /* reset string pointer */
667 if (next_token(&p,tok,":") &&
668 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
669 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
674 /* driver file name */
675 if (ok && !next_token(&p,driver,":")) ok = 0;
677 if (ok && !next_token(&p,datafile,":")) ok = 0;
679 * for the next tokens - which may be empty - I have to check for empty
680 * tokens first because the next_token function will skip all empty
688 } else if (!next_token(&p,helpfile,":")) ok = 0;
692 /* language monitor */
696 } else if (!next_token(&p,langmon,":")) ok = 0;
699 /* default data type */
700 if (ok && !next_token(&p,datatype,":")) ok = 0;
703 PACKI(desc,"W",0x0400); /* don't know */
704 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
705 PACKS(desc,"z",driver); /* Driverfile Name */
706 PACKS(desc,"z",datafile); /* Datafile name */
707 PACKS(desc,"z",langmon); /* language monitor */
708 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
709 PACKS(desc,"z",datatype); /* default data type */
710 PACKS(desc,"z",helpfile); /* helpfile name */
711 PACKS(desc,"z",driver); /* driver name */
712 DEBUG(3,("Driver:%s:\n",driver));
713 DEBUG(3,("Data File:%s:\n",datafile));
714 DEBUG(3,("Language Monitor:%s:\n",langmon));
715 DEBUG(3,("Data Type:%s:\n",datatype));
716 DEBUG(3,("Help File:%s:\n",helpfile));
717 PACKI(desc,"N",count); /* number of files to copy */
718 for (i=0;i<count;i++)
720 /* no need to check return value here - it was already tested in
721 * get_printerdrivernumber
723 next_token(&p,tok,",");
724 PACKS(desc,"z",tok); /* driver files to copy */
725 DEBUG(3,("file:%s:\n",tok));
728 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
729 SERVICE(snum),count));
731 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
732 desc->errcode=NERR_notsupported;
738 /* This function returns the number of files for a given driver */
739 int get_printerdrivernumber(int snum)
747 pstrcpy(fname,lp_driverfile());
749 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
752 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
756 p=(char *)malloc(8192*sizeof(char));
757 q=p; /* need it to free memory because p change ! */
759 /* lookup the long printer driver name in the file description */
760 while (!feof(f) && !ok)
762 p = q; /* reset string pointer */
764 if (next_token(&p,tok,":") &&
765 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
774 if (*p++ == ':') i--;
779 /* count the number of files */
780 while (next_token(&p,tok,","))
788 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
789 uint16 vuid, char *param,char *data,
790 int mdrcnt,int mprcnt,
791 char **rdata,char **rparam,
792 int *rdata_len,int *rparam_len)
794 char *str1 = param+2;
795 char *str2 = skip_string(str1,1);
796 char *p = skip_string(str2,1);
802 struct pack_desc desc;
803 print_queue_struct *queue=NULL;
804 print_status_struct status;
806 bzero(&status,sizeof(status));
807 bzero(&desc,sizeof(desc));
809 p = skip_string(p,1);
814 /* remove any trailing username */
815 if ((p = strchr(QueueName,'%'))) *p = 0;
817 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
819 /* check it's a supported varient */
820 if (!prefix_ok(str1,"zWrLh")) return False;
821 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
823 snum = lp_servicenumber(QueueName);
824 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
825 int pnum = lp_servicenumber(PRINTERS_NAME);
827 lp_add_printer(QueueName,pnum);
828 snum = lp_servicenumber(QueueName);
832 if (snum < 0 || !VALID_SNUM(snum)) return(False);
835 count = get_printerdrivernumber(snum);
836 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
838 count = get_printqueue(snum, conn,&queue,&status);
841 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
843 desc.buflen = mdrcnt;
844 if (init_package(&desc,1,count)) {
845 desc.subcount = count;
846 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
849 *rdata_len = desc.usedlen;
852 *rparam = REALLOC(*rparam,*rparam_len);
853 SSVALS(*rparam,0,desc.errcode);
855 SSVAL(*rparam,4,desc.neededlen);
857 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
859 if (queue) free(queue);
865 /****************************************************************************
866 view list of all print jobs on all queues
867 ****************************************************************************/
868 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
869 int mdrcnt, int mprcnt,
870 char **rdata, char** rparam,
871 int *rdata_len, int *rparam_len)
873 char *param_format = param+2;
874 char *output_format1 = skip_string(param_format,1);
875 char *p = skip_string(output_format1,1);
876 int uLevel = SVAL(p,0);
877 char *output_format2 = p + 4;
878 int services = lp_numservices();
880 struct pack_desc desc;
881 print_queue_struct **queue = NULL;
882 print_status_struct *status = NULL;
883 int* subcntarr = NULL;
884 int queuecnt, subcnt=0, succnt=0;
886 bzero(&desc,sizeof(desc));
888 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
890 if (!prefix_ok(param_format,"WrLeh")) return False;
891 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
894 for (i = 0; i < services; i++)
895 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
898 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
899 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
900 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
901 memset(status,0,queuecnt*sizeof(print_status_struct));
902 subcntarr = (int*)malloc(queuecnt*sizeof(int));
905 for (i = 0; i < services; i++)
906 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
907 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
908 subcnt += subcntarr[n];
912 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
914 desc.buflen = mdrcnt;
916 if (init_package(&desc,queuecnt,subcnt)) {
919 for (i = 0; i < services; i++)
920 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
921 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
923 if (desc.errcode == NERR_Success) succnt = n;
927 if (subcntarr) free(subcntarr);
929 *rdata_len = desc.usedlen;
931 *rparam = REALLOC(*rparam,*rparam_len);
932 SSVALS(*rparam,0,desc.errcode);
934 SSVAL(*rparam,4,succnt);
935 SSVAL(*rparam,6,queuecnt);
937 for (i = 0; i < queuecnt; i++) {
938 if (queue && queue[i]) free(queue[i]);
941 if (queue) free(queue);
942 if (status) free(status);
947 /****************************************************************************
948 get info level for a server list query
949 ****************************************************************************/
950 static BOOL check_server_info(int uLevel, char* id)
954 if (strcmp(id,"B16") != 0) return False;
957 if (strcmp(id,"B16BBDz") != 0) return False;
965 struct srv_info_struct
975 /*******************************************************************
976 get server info lists from the files saved by nmbd. Return the
978 ******************************************************************/
979 static int get_server_info(uint32 servertype,
980 struct srv_info_struct **servers,
988 BOOL local_list_only;
990 pstrcpy(fname,lp_lockdir());
991 trim_string(fname,NULL,"/");
993 pstrcat(fname,SERVER_LIST);
995 f = fopen(fname,"r");
998 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1002 /* request for everything is code for request all servers */
1003 if (servertype == SV_TYPE_ALL)
1004 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1006 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1008 DEBUG(4,("Servertype search: %8x\n",servertype));
1013 struct srv_info_struct *s;
1018 fgets(line,sizeof(line)-1,f);
1019 if (!*line) continue;
1021 if (count == alloced) {
1023 (*servers) = (struct srv_info_struct *)
1024 Realloc(*servers,sizeof(**servers)*alloced);
1025 if (!(*servers)) return(0);
1026 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1028 s = &(*servers)[count];
1030 if (!next_token(&ptr,s->name , NULL)) continue;
1031 if (!next_token(&ptr,stype , NULL)) continue;
1032 if (!next_token(&ptr,s->comment, NULL)) continue;
1033 if (!next_token(&ptr,s->domain , NULL)) {
1034 /* this allows us to cope with an old nmbd */
1035 pstrcpy(s->domain,global_myworkgroup);
1038 if (sscanf(stype,"%X",&s->type) != 1) {
1039 DEBUG(4,("r:host file "));
1043 /* Filter the servers/domains we return based on what was asked for. */
1045 /* Check to see if we are being asked for a local list only. */
1046 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1047 DEBUG(4,("r: local list only"));
1051 /* doesn't match up: don't want it */
1052 if (!(servertype & s->type)) {
1053 DEBUG(4,("r:serv type "));
1057 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1058 (s->type & SV_TYPE_DOMAIN_ENUM))
1060 DEBUG(4,("s: dom mismatch "));
1064 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1069 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1070 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1074 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1075 s->name, s->type, s->comment, s->domain));
1077 s->server_added = True;
1082 DEBUG(4,("%20s %8x %25s %15s\n",
1083 s->name, s->type, s->comment, s->domain));
1092 /*******************************************************************
1093 fill in a server info structure
1094 ******************************************************************/
1095 static int fill_srv_info(struct srv_info_struct *service,
1096 int uLevel, char **buf, int *buflen,
1097 char **stringbuf, int *stringspace, char *baseaddr)
1106 case 0: struct_len = 16; break;
1107 case 1: struct_len = 26; break;
1117 len = strlen(service->comment)+1;
1121 if (buflen) *buflen = struct_len;
1122 if (stringspace) *stringspace = len;
1123 return struct_len + len;
1128 if (*buflen < struct_len) return -1;
1136 p2 = p + struct_len;
1137 l2 = *buflen - struct_len;
1139 if (!baseaddr) baseaddr = p;
1144 StrnCpy(p,service->name,15);
1148 StrnCpy(p,service->name,15);
1149 SIVAL(p,18,service->type);
1150 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1151 len += CopyAndAdvance(&p2,service->comment,&l2);
1157 *buf = p + struct_len;
1158 *buflen -= struct_len;
1171 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1173 return(strcmp(s1->name,s2->name));
1176 /****************************************************************************
1177 view list of servers available (or possibly domains). The info is
1178 extracted from lists saved by nmbd on the local host
1179 ****************************************************************************/
1180 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1181 int mdrcnt, int mprcnt, char **rdata,
1182 char **rparam, int *rdata_len, int *rparam_len)
1184 char *str1 = param+2;
1185 char *str2 = skip_string(str1,1);
1186 char *p = skip_string(str2,1);
1187 int uLevel = SVAL(p,0);
1188 int buf_len = SVAL(p,2);
1189 uint32 servertype = IVAL(p,4);
1191 int data_len, fixed_len, string_len;
1192 int f_len = 0, s_len = 0;
1193 struct srv_info_struct *servers=NULL;
1194 int counted=0,total=0;
1197 BOOL domain_request;
1200 /* If someone sets all the bits they don't really mean to set
1201 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1204 if (servertype == SV_TYPE_ALL)
1205 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1207 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1208 any other bit (they may just set this bit on it's own) they
1209 want all the locally seen servers. However this bit can be
1210 set on its own so set the requested servers to be
1211 ALL - DOMAIN_ENUM. */
1213 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1214 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1216 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1217 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1221 if (!prefix_ok(str1,"WrLehD")) return False;
1222 if (!check_server_info(uLevel,str2)) return False;
1224 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1225 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1226 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1228 if (strcmp(str1, "WrLehDz") == 0) {
1229 StrnCpy(domain, p, sizeof(fstring)-1);
1231 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1234 if (lp_browse_list())
1235 total = get_server_info(servertype,&servers,domain);
1237 data_len = fixed_len = string_len = 0;
1240 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1243 char *lastname=NULL;
1245 for (i=0;i<total;i++)
1247 struct srv_info_struct *s = &servers[i];
1248 if (lastname && strequal(lastname,s->name)) continue;
1250 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1251 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1252 s->name, s->type, s->comment, s->domain));
1254 if (data_len <= buf_len) {
1257 string_len += s_len;
1264 *rdata_len = fixed_len + string_len;
1265 *rdata = REALLOC(*rdata,*rdata_len);
1266 bzero(*rdata,*rdata_len);
1268 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1274 char *lastname=NULL;
1275 int count2 = counted;
1276 for (i = 0; i < total && count2;i++)
1278 struct srv_info_struct *s = &servers[i];
1279 if (lastname && strequal(lastname,s->name)) continue;
1281 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1282 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1283 s->name, s->type, s->comment, s->domain));
1289 *rparam = REALLOC(*rparam,*rparam_len);
1290 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1292 SSVAL(*rparam,4,counted);
1293 SSVAL(*rparam,6,counted+missed);
1295 if (servers) free(servers);
1297 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1298 domain,uLevel,counted,counted+missed));
1303 /****************************************************************************
1304 command 0x34 - suspected of being a "Lookup Names" stub api
1305 ****************************************************************************/
1306 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1307 int mdrcnt, int mprcnt, char **rdata,
1308 char **rparam, int *rdata_len, int *rparam_len)
1310 char *str1 = param+2;
1311 char *str2 = skip_string(str1,1);
1312 char *p = skip_string(str2,1);
1313 int uLevel = SVAL(p,0);
1314 int buf_len = SVAL(p,2);
1318 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1319 str1, str2, p, uLevel, buf_len));
1321 if (!prefix_ok(str1,"zWrLeh")) return False;
1327 *rparam = REALLOC(*rparam,*rparam_len);
1329 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1331 SSVAL(*rparam,4,counted);
1332 SSVAL(*rparam,6,counted+missed);
1337 /****************************************************************************
1338 get info about a share
1339 ****************************************************************************/
1340 static BOOL check_share_info(int uLevel, char* id)
1344 if (strcmp(id,"B13") != 0) return False;
1347 if (strcmp(id,"B13BWz") != 0) return False;
1350 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1353 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1355 default: return False;
1360 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1361 char** buf, int* buflen,
1362 char** stringbuf, int* stringspace, char* baseaddr)
1371 case 0: struct_len = 13; break;
1372 case 1: struct_len = 20; break;
1373 case 2: struct_len = 40; break;
1374 case 91: struct_len = 68; break;
1382 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1383 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1384 if (buflen) *buflen = struct_len;
1385 if (stringspace) *stringspace = len;
1386 return struct_len + len;
1391 if ((*buflen) < struct_len) return -1;
1399 p2 = p + struct_len;
1400 l2 = (*buflen) - struct_len;
1402 if (!baseaddr) baseaddr = p;
1404 StrnCpy(p,lp_servicename(snum),13);
1410 type = STYPE_DISKTREE;
1411 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1412 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1413 SSVAL(p,14,type); /* device type */
1414 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1415 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1420 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1421 SSVALS(p,22,-1); /* max uses */
1422 SSVAL(p,24,1); /* current uses */
1423 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1424 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1425 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1430 memset(p+40,0,SHPWLEN+2);
1442 (*buf) = p + struct_len;
1443 (*buflen) -= struct_len;
1445 (*stringspace) = l2;
1455 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1456 int mdrcnt,int mprcnt,
1457 char **rdata,char **rparam,
1458 int *rdata_len,int *rparam_len)
1460 char *str1 = param+2;
1461 char *str2 = skip_string(str1,1);
1462 char *netname = skip_string(str2,1);
1463 char *p = skip_string(netname,1);
1464 int uLevel = SVAL(p,0);
1465 int snum = find_service(netname);
1467 if (snum < 0) return False;
1469 /* check it's a supported varient */
1470 if (!prefix_ok(str1,"zWrLh")) return False;
1471 if (!check_share_info(uLevel,str2)) return False;
1473 *rdata = REALLOC(*rdata,mdrcnt);
1475 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1476 if (*rdata_len < 0) return False;
1479 *rparam = REALLOC(*rparam,*rparam_len);
1480 SSVAL(*rparam,0,NERR_Success);
1481 SSVAL(*rparam,2,0); /* converter word */
1482 SSVAL(*rparam,4,*rdata_len);
1487 /****************************************************************************
1488 view list of shares available
1489 ****************************************************************************/
1490 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1491 int mdrcnt,int mprcnt,
1492 char **rdata,char **rparam,
1493 int *rdata_len,int *rparam_len)
1495 char *str1 = param+2;
1496 char *str2 = skip_string(str1,1);
1497 char *p = skip_string(str2,1);
1498 int uLevel = SVAL(p,0);
1499 int buf_len = SVAL(p,2);
1501 int count=lp_numservices();
1502 int total=0,counted=0;
1503 BOOL missed = False;
1505 int data_len, fixed_len, string_len;
1506 int f_len = 0, s_len = 0;
1508 if (!prefix_ok(str1,"WrLeh")) return False;
1509 if (!check_share_info(uLevel,str2)) return False;
1511 data_len = fixed_len = string_len = 0;
1512 for (i=0;i<count;i++)
1513 if (lp_browseable(i) && lp_snum_ok(i))
1516 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1517 if (data_len <= buf_len)
1521 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(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1540 *rparam = REALLOC(*rparam,*rparam_len);
1541 SSVAL(*rparam,0,missed ? ERRmoredata : 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(connection_struct *conn,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(connection_struct *conn,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 * Pass the user through the NT -> unix user mapping
1637 (void)map_username(user);
1640 * Do any UNIX username case mangling.
1642 (void)Get_Pwnam( user, True);
1645 * Attempt the plaintext password change first.
1646 * Older versions of Windows seem to do this.
1649 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1650 chgpasswd(user,pass1,pass2,False))
1652 SSVAL(*rparam,0,NERR_Success);
1656 * If the plaintext change failed, attempt
1657 * the encrypted. NT will generate this
1658 * after trying the samr method.
1661 if(SVAL(*rparam,0) != NERR_Success)
1663 struct smb_passwd *sampw = NULL;
1665 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1666 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1668 SSVAL(*rparam,0,NERR_Success);
1672 bzero(pass1,sizeof(fstring));
1673 bzero(pass2,sizeof(fstring));
1678 /****************************************************************************
1679 Set the user password (SamOEM version - gets plaintext).
1680 ****************************************************************************/
1682 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1683 int mdrcnt,int mprcnt,
1684 char **rdata,char **rparam,
1685 int *rdata_len,int *rparam_len)
1689 struct smb_passwd *sampw = NULL;
1690 char *p = param + 2;
1694 *rparam = REALLOC(*rparam,*rparam_len);
1698 SSVAL(*rparam,0,NERR_badpass);
1701 * Check the parameter definition is correct.
1703 if(!strequal(param + 2, "zsT")) {
1704 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1707 p = skip_string(p, 1);
1709 if(!strequal(p, "B516B16")) {
1710 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1713 p = skip_string(p,1);
1716 p = skip_string(p,1);
1718 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1721 * Pass the user through the NT -> unix user mapping
1725 (void)map_username(user);
1728 * Do any UNIX username case mangling.
1730 (void)Get_Pwnam( user, True);
1732 if(check_oem_password( user, (unsigned char *)data, &sampw,
1733 new_passwd, (int)sizeof(new_passwd)) == False) {
1738 * At this point we have the new case-sensitive plaintext
1739 * password in the fstring new_passwd. If we wanted to synchronise
1740 * with UNIX passwords we would call a UNIX password changing
1741 * function here. However it would have to be done as root
1742 * as the plaintext of the old users password is not
1746 if(lp_unix_password_sync())
1747 ret = chgpasswd(user,"", new_passwd, True);
1749 if(ret && change_oem_password( sampw, new_passwd, False)) {
1750 SSVAL(*rparam,0,NERR_Success);
1756 /****************************************************************************
1759 ****************************************************************************/
1760 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1761 int mdrcnt,int mprcnt,
1762 char **rdata,char **rparam,
1763 int *rdata_len,int *rparam_len)
1765 int function = SVAL(param,0);
1766 char *str1 = param+2;
1767 char *str2 = skip_string(str1,1);
1768 char *p = skip_string(str2,1);
1772 printjob_decode(SVAL(p,0), &snum, &jobid);
1774 /* check it's a supported varient */
1775 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1779 *rparam = REALLOC(*rparam,*rparam_len);
1783 SSVAL(*rparam,0,NERR_Success);
1785 if (snum >= 0 && VALID_SNUM(snum))
1787 print_queue_struct *queue=NULL;
1789 count = get_printqueue(snum,conn,&queue,NULL);
1791 for (i=0;i<count;i++)
1792 if ((queue[i].job&0xFF) == jobid)
1795 case 81: /* delete */
1796 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1797 del_printqueue(conn,snum,queue[i].job);
1799 case 82: /* pause */
1800 case 83: /* resume */
1801 DEBUG(3,("%s queue entry %d\n",
1802 (function==82?"pausing":"resuming"),queue[i].job));
1803 status_printjob(conn,snum,queue[i].job,
1804 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1811 SSVAL(*rparam,0,NERR_JobNotFound);
1813 if (queue) free(queue);
1816 SSVAL(*rparam,2,0); /* converter word */
1821 /****************************************************************************
1822 Purge a print queue - or pause or resume it.
1823 ****************************************************************************/
1824 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1825 int mdrcnt,int mprcnt,
1826 char **rdata,char **rparam,
1827 int *rdata_len,int *rparam_len)
1829 int function = SVAL(param,0);
1830 char *str1 = param+2;
1831 char *str2 = skip_string(str1,1);
1832 char *QueueName = skip_string(str2,1);
1835 /* check it's a supported varient */
1836 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1840 *rparam = REALLOC(*rparam,*rparam_len);
1844 SSVAL(*rparam,0,NERR_Success);
1845 SSVAL(*rparam,2,0); /* converter word */
1847 snum = lp_servicenumber(QueueName);
1848 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1849 int pnum = lp_servicenumber(PRINTERS_NAME);
1851 lp_add_printer(QueueName,pnum);
1852 snum = lp_servicenumber(QueueName);
1856 if (snum >= 0 && VALID_SNUM(snum)) {
1860 case 74: /* Pause queue */
1861 case 75: /* Resume queue */
1862 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1863 DEBUG(3,("Print queue %s, queue=%s\n",
1864 (function==74?"pause":"resume"),QueueName));
1866 case 103: /* Purge */
1868 print_queue_struct *queue=NULL;
1870 count = get_printqueue(snum,conn,&queue,NULL);
1871 for (i = 0; i < count; i++)
1872 del_printqueue(conn,snum,queue[i].job);
1874 if (queue) free(queue);
1875 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1885 /****************************************************************************
1886 set the property of a print job (undocumented?)
1887 ? function = 0xb -> set name of print job
1888 ? function = 0x6 -> move print job up/down
1889 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1890 or <WWsTP> <WB21BB16B10zWWzDDz>
1891 ****************************************************************************/
1892 static int check_printjob_info(struct pack_desc* desc,
1893 int uLevel, char* id)
1895 desc->subformat = NULL;
1897 case 0: desc->format = "W"; break;
1898 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1899 case 2: desc->format = "WWzWWDDzz"; break;
1900 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1901 default: return False;
1903 if (strcmp(desc->format,id) != 0) return False;
1907 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1908 int mdrcnt,int mprcnt,
1909 char **rdata,char **rparam,
1910 int *rdata_len,int *rparam_len)
1912 struct pack_desc desc;
1913 char *str1 = param+2;
1914 char *str2 = skip_string(str1,1);
1915 char *p = skip_string(str2,1);
1917 int uLevel = SVAL(p,2);
1918 int function = SVAL(p,4); /* what is this ?? */
1923 printjob_decode(SVAL(p,0), &snum, &jobid);
1926 *rparam = REALLOC(*rparam,*rparam_len);
1930 /* check it's a supported varient */
1931 if ((strcmp(str1,"WWsTP")) ||
1932 (!check_printjob_info(&desc,uLevel,str2)))
1936 case 0x6: /* change job place in the queue,
1937 data gives the new place */
1938 if (snum >= 0 && VALID_SNUM(snum)) {
1939 print_queue_struct *queue=NULL;
1943 count = get_printqueue(snum,conn,&queue,NULL);
1944 for (i=0;i<count;i++) /* find job */
1945 if ((queue[i].job&0xFF) == jobid) break;
1948 desc.errcode=NERR_JobNotFound;
1949 if (queue) free(queue);
1951 desc.errcode=NERR_Success;
1955 int place= SVAL(data,0);
1956 /* we currently have no way of
1957 doing this. Can any unix do it? */
1958 if (i < place) /* move down */;
1959 else if (i > place ) /* move up */;
1962 desc.errcode=NERR_notsupported; /* not yet
1964 if (queue) free(queue);
1967 desc.errcode=NERR_JobNotFound;
1971 case 0xb: /* change print job name, data gives the name */
1972 /* jobid, snum should be zero */
1973 if (isalpha((int)*s)) {
1976 while (l<64 && *s) {
1977 if (issafe(*s)) name[l++] = *s;
1982 DEBUG(3,("Setting print name to %s\n",name));
1984 fsp = file_find_print();
1987 connection_struct *fconn = fsp->conn;
1990 if (!become_user(fconn,vuid) ||
1991 !become_service(fconn,True))
1994 if (sys_rename(fsp->fsp_name,name) == 0) {
1995 string_set(&fsp->fsp_name,name);
2000 desc.errcode=NERR_Success;
2003 default: /* not implemented */
2007 SSVALS(*rparam,0,desc.errcode);
2008 SSVAL(*rparam,2,0); /* converter word */
2014 /****************************************************************************
2015 get info about the server
2016 ****************************************************************************/
2017 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2018 int mdrcnt,int mprcnt,
2019 char **rdata,char **rparam,
2020 int *rdata_len,int *rparam_len)
2022 char *str1 = param+2;
2023 char *str2 = skip_string(str1,1);
2024 char *p = skip_string(str2,1);
2025 int uLevel = SVAL(p,0);
2029 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2031 /* check it's a supported varient */
2032 if (!prefix_ok(str1,"WrLh")) return False;
2035 if (strcmp(str2,"B16") != 0) return False;
2039 if (strcmp(str2,"B16BBDz") != 0) return False;
2043 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2048 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2053 if (strcmp(str2,"DN") != 0) return False;
2057 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2060 default: return False;
2063 *rdata_len = mdrcnt;
2064 *rdata = REALLOC(*rdata,*rdata_len);
2067 p2 = p + struct_len;
2069 StrnCpy(p,local_machine,16);
2075 struct srv_info_struct *servers=NULL;
2078 uint32 servertype= lp_default_server_announce();
2080 pstrcpy(comment,lp_serverstring());
2082 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2083 for (i=0;i<count;i++)
2084 if (strequal(servers[i].name,local_machine))
2086 servertype = servers[i].type;
2087 pstrcpy(comment,servers[i].comment);
2090 if (servers) free(servers);
2092 SCVAL(p,0,lp_major_announce_version());
2093 SCVAL(p,1,lp_minor_announce_version());
2094 SIVAL(p,2,servertype);
2096 if (mdrcnt == struct_len) {
2099 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2100 standard_sub(conn,comment);
2101 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2102 p2 = skip_string(p2,1);
2107 return False; /* not yet implemented */
2110 *rdata_len = PTR_DIFF(p2,*rdata);
2113 *rparam = REALLOC(*rparam,*rparam_len);
2114 SSVAL(*rparam,0,NERR_Success);
2115 SSVAL(*rparam,2,0); /* converter word */
2116 SSVAL(*rparam,4,*rdata_len);
2122 /****************************************************************************
2123 get info about the server
2124 ****************************************************************************/
2125 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2126 int mdrcnt,int mprcnt,
2127 char **rdata,char **rparam,
2128 int *rdata_len,int *rparam_len)
2130 char *str1 = param+2;
2131 char *str2 = skip_string(str1,1);
2132 char *p = skip_string(str2,1);
2134 extern pstring sesssetup_user;
2135 int level = SVAL(p,0);
2137 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2140 *rparam = REALLOC(*rparam,*rparam_len);
2142 /* check it's a supported varient */
2143 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2146 *rdata_len = mdrcnt + 1024;
2147 *rdata = REALLOC(*rdata,*rdata_len);
2149 SSVAL(*rparam,0,NERR_Success);
2150 SSVAL(*rparam,2,0); /* converter word */
2156 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2157 pstrcpy(p2,local_machine);
2159 p2 = skip_string(p2,1);
2162 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2163 pstrcpy(p2,sesssetup_user);
2164 p2 = skip_string(p2,1);
2167 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2168 pstrcpy(p2,global_myworkgroup);
2170 p2 = skip_string(p2,1);
2173 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2174 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2177 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2178 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2179 p2 = skip_string(p2,1);
2182 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2184 p2 = skip_string(p2,1);
2187 *rdata_len = PTR_DIFF(p2,*rdata);
2189 SSVAL(*rparam,4,*rdata_len);
2194 /****************************************************************************
2195 get info about a user
2197 struct user_info_11 {
2198 char usri11_name[21]; 0-20
2200 char *usri11_comment; 22-25
2201 char *usri11_usr_comment; 26-29
2202 unsigned short usri11_priv; 30-31
2203 unsigned long usri11_auth_flags; 32-35
2204 long usri11_password_age; 36-39
2205 char *usri11_homedir; 40-43
2206 char *usri11_parms; 44-47
2207 long usri11_last_logon; 48-51
2208 long usri11_last_logoff; 52-55
2209 unsigned short usri11_bad_pw_count; 56-57
2210 unsigned short usri11_num_logons; 58-59
2211 char *usri11_logon_server; 60-63
2212 unsigned short usri11_country_code; 64-65
2213 char *usri11_workstations; 66-69
2214 unsigned long usri11_max_storage; 70-73
2215 unsigned short usri11_units_per_week; 74-75
2216 unsigned char *usri11_logon_hours; 76-79
2217 unsigned short usri11_code_page; 80-81
2222 usri11_name specifies the user name for which information is retireved
2224 usri11_pad aligns the next data structure element to a word boundary
2226 usri11_comment is a null terminated ASCII comment
2228 usri11_user_comment is a null terminated ASCII comment about the user
2230 usri11_priv specifies the level of the privilege assigned to the user.
2231 The possible values are:
2233 Name Value Description
2234 USER_PRIV_GUEST 0 Guest privilege
2235 USER_PRIV_USER 1 User privilege
2236 USER_PRV_ADMIN 2 Administrator privilege
2238 usri11_auth_flags specifies the account operator privileges. The
2239 possible values are:
2241 Name Value Description
2242 AF_OP_PRINT 0 Print operator
2245 Leach, Naik [Page 28]
\r\f
2248 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2251 AF_OP_COMM 1 Communications operator
2252 AF_OP_SERVER 2 Server operator
2253 AF_OP_ACCOUNTS 3 Accounts operator
2256 usri11_password_age specifies how many seconds have elapsed since the
2257 password was last changed.
2259 usri11_home_dir points to a null terminated ASCII string that contains
2260 the path name of the user's home directory.
2262 usri11_parms points to a null terminated ASCII string that is set
2263 aside for use by applications.
2265 usri11_last_logon specifies the time when the user last logged on.
2266 This value is stored as the number of seconds elapsed since
2267 00:00:00, January 1, 1970.
2269 usri11_last_logoff specifies the time when the user last logged off.
2270 This value is stored as the number of seconds elapsed since
2271 00:00:00, January 1, 1970. A value of 0 means the last logoff
2274 usri11_bad_pw_count specifies the number of incorrect passwords
2275 entered since the last successful logon.
2277 usri11_log1_num_logons specifies the number of times this user has
2278 logged on. A value of -1 means the number of logons is unknown.
2280 usri11_logon_server points to a null terminated ASCII string that
2281 contains the name of the server to which logon requests are sent.
2282 A null string indicates logon requests should be sent to the
2285 usri11_country_code specifies the country code for the user's language
2288 usri11_workstations points to a null terminated ASCII string that
2289 contains the names of workstations the user may log on from.
2290 There may be up to 8 workstations, with the names separated by
2291 commas. A null strings indicates there are no restrictions.
2293 usri11_max_storage specifies the maximum amount of disk space the user
2294 can occupy. A value of 0xffffffff indicates there are no
2297 usri11_units_per_week specifies the equal number of time units into
2298 which a week is divided. This value must be equal to 168.
2300 usri11_logon_hours points to a 21 byte (168 bits) string that
2301 specifies the time during which the user can log on. Each bit
2302 represents one unique hour in a week. The first bit (bit 0, word
2303 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2307 Leach, Naik [Page 29]
\r\f
2310 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2313 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2314 are no restrictions.
2316 usri11_code_page specifies the code page for the user's language of
2319 All of the pointers in this data structure need to be treated
2320 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2321 to be ignored. The converter word returned in the parameters section
2322 needs to be subtracted from the lower 16 bits to calculate an offset
2323 into the return buffer where this ASCII string resides.
2325 There is no auxiliary data in the response.
2327 ****************************************************************************/
2329 #define usri11_name 0
2330 #define usri11_pad 21
2331 #define usri11_comment 22
2332 #define usri11_usr_comment 26
2333 #define usri11_full_name 30
2334 #define usri11_priv 34
2335 #define usri11_auth_flags 36
2336 #define usri11_password_age 40
2337 #define usri11_homedir 44
2338 #define usri11_parms 48
2339 #define usri11_last_logon 52
2340 #define usri11_last_logoff 56
2341 #define usri11_bad_pw_count 60
2342 #define usri11_num_logons 62
2343 #define usri11_logon_server 64
2344 #define usri11_country_code 68
2345 #define usri11_workstations 70
2346 #define usri11_max_storage 74
2347 #define usri11_units_per_week 78
2348 #define usri11_logon_hours 80
2349 #define usri11_code_page 84
2350 #define usri11_end 86
2352 #define USER_PRIV_GUEST 0
2353 #define USER_PRIV_USER 1
2354 #define USER_PRIV_ADMIN 2
2356 #define AF_OP_PRINT 0
2357 #define AF_OP_COMM 1
2358 #define AF_OP_SERVER 2
2359 #define AF_OP_ACCOUNTS 3
2362 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2363 int mdrcnt,int mprcnt,
2364 char **rdata,char **rparam,
2365 int *rdata_len,int *rparam_len)
2367 char *str1 = param+2;
2368 char *str2 = skip_string(str1,1);
2369 char *UserName = skip_string(str2,1);
2370 char *p = skip_string(UserName,1);
2371 int uLevel = SVAL(p,0);
2374 /* get NIS home of a previously validated user - simeon */
2375 /* With share level security vuid will always be zero.
2376 Don't depend on vuser being non-null !!. JRA */
2377 user_struct *vuser = get_valid_user_struct(vuid);
2379 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2382 *rparam = REALLOC(*rparam,*rparam_len);
2384 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2386 /* check it's a supported variant */
2387 if (strcmp(str1,"zWrLh") != 0) return False;
2390 case 0: p2 = "B21"; break;
2391 case 1: p2 = "B21BB16DWzzWz"; break;
2392 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2393 case 10: p2 = "B21Bzzz"; break;
2394 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2395 default: return False;
2398 if (strcmp(p2,str2) != 0) return False;
2400 *rdata_len = mdrcnt + 1024;
2401 *rdata = REALLOC(*rdata,*rdata_len);
2403 SSVAL(*rparam,0,NERR_Success);
2404 SSVAL(*rparam,2,0); /* converter word */
2407 p2 = p + usri11_end;
2410 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2414 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2419 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2420 pstrcpy(p2,"Comment");
2421 p2 = skip_string(p2,1);
2423 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2424 pstrcpy(p2,"UserComment");
2425 p2 = skip_string(p2,1);
2427 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2428 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2429 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2430 p2 = skip_string(p2,1);
2433 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2435 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2436 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2437 SIVALS(p,usri11_password_age,-1); /* password age */
2438 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2439 pstrcpy(p2, lp_logon_path());
2440 p2 = skip_string(p2,1);
2441 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2443 p2 = skip_string(p2,1);
2444 SIVAL(p,usri11_last_logon,0); /* last logon */
2445 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2446 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2447 SSVALS(p,usri11_num_logons,-1); /* num logons */
2448 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2449 pstrcpy(p2,"\\\\*");
2450 p2 = skip_string(p2,1);
2451 SSVAL(p,usri11_country_code,0); /* country code */
2453 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2455 p2 = skip_string(p2,1);
2457 SIVALS(p,usri11_max_storage,-1); /* max storage */
2458 SSVAL(p,usri11_units_per_week,168); /* units per week */
2459 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2461 /* a simple way to get logon hours at all times. */
2463 SCVAL(p2,21,0); /* fix zero termination */
2464 p2 = skip_string(p2,1);
2466 SSVAL(p,usri11_code_page,0); /* code page */
2468 if (uLevel == 1 || uLevel == 2)
2470 memset(p+22,' ',16); /* password */
2471 SIVALS(p,38,-1); /* password age */
2473 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2474 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2475 pstrcpy(p2,lp_logon_path());
2476 p2 = skip_string(p2,1);
2477 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2479 SSVAL(p,52,0); /* flags */
2480 SIVAL(p,54,0); /* script_path */
2483 SIVAL(p,60,0); /* auth_flags */
2484 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2485 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2486 p2 = skip_string(p2,1);
2487 SIVAL(p,68,0); /* urs_comment */
2488 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2490 p2 = skip_string(p2,1);
2491 SIVAL(p,76,0); /* workstations */
2492 SIVAL(p,80,0); /* last_logon */
2493 SIVAL(p,84,0); /* last_logoff */
2494 SIVALS(p,88,-1); /* acct_expires */
2495 SIVALS(p,92,-1); /* max_storage */
2496 SSVAL(p,96,168); /* units_per_week */
2497 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2500 SSVALS(p,102,-1); /* bad_pw_count */
2501 SSVALS(p,104,-1); /* num_logons */
2502 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2503 pstrcpy(p2,"\\\\%L");
2504 standard_sub_basic(p2);
2505 p2 = skip_string(p2,1);
2506 SSVAL(p,110,49); /* country_code */
2507 SSVAL(p,112,860); /* code page */
2511 *rdata_len = PTR_DIFF(p2,*rdata);
2513 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2518 /*******************************************************************
2519 get groups that a user is a member of
2520 ******************************************************************/
2521 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2522 int mdrcnt,int mprcnt,
2523 char **rdata,char **rparam,
2524 int *rdata_len,int *rparam_len)
2526 char *str1 = param+2;
2527 char *str2 = skip_string(str1,1);
2528 char *UserName = skip_string(str2,1);
2529 char *p = skip_string(UserName,1);
2530 int uLevel = SVAL(p,0);
2535 *rparam = REALLOC(*rparam,*rparam_len);
2537 /* check it's a supported varient */
2538 if (strcmp(str1,"zWrLeh") != 0) return False;
2540 case 0: p2 = "B21"; break;
2541 default: return False;
2543 if (strcmp(p2,str2) != 0) return False;
2545 *rdata_len = mdrcnt + 1024;
2546 *rdata = REALLOC(*rdata,*rdata_len);
2548 SSVAL(*rparam,0,NERR_Success);
2549 SSVAL(*rparam,2,0); /* converter word */
2553 /* XXXX we need a real SAM database some day */
2554 pstrcpy(p,"Users"); p += 21; count++;
2555 pstrcpy(p,"Domain Users"); p += 21; count++;
2556 pstrcpy(p,"Guests"); p += 21; count++;
2557 pstrcpy(p,"Domain Guests"); p += 21; count++;
2559 *rdata_len = PTR_DIFF(p,*rdata);
2561 SSVAL(*rparam,4,count); /* is this right?? */
2562 SSVAL(*rparam,6,count); /* is this right?? */
2568 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2569 int mdrcnt,int mprcnt,
2570 char **rdata,char **rparam,
2571 int *rdata_len,int *rparam_len)
2573 char *str1 = param+2;
2574 char *str2 = skip_string(str1,1);
2575 char *p = skip_string(str2,1);
2577 struct pack_desc desc;
2584 bzero(&desc,sizeof(desc));
2586 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2588 /* check it's a supported varient */
2589 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2590 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2591 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2593 desc.buflen = mdrcnt;
2594 desc.subformat = NULL;
2597 if (init_package(&desc,1,0))
2599 PACKI(&desc,"W",0); /* code */
2600 PACKS(&desc,"B21",name); /* eff. name */
2601 PACKS(&desc,"B",""); /* pad */
2603 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2604 PACKI(&desc,"D",0); /* auth flags XXX */
2605 PACKI(&desc,"W",0); /* num logons */
2606 PACKI(&desc,"W",0); /* bad pw count */
2607 PACKI(&desc,"D",0); /* last logon */
2608 PACKI(&desc,"D",-1); /* last logoff */
2609 PACKI(&desc,"D",-1); /* logoff time */
2610 PACKI(&desc,"D",-1); /* kickoff time */
2611 PACKI(&desc,"D",0); /* password age */
2612 PACKI(&desc,"D",0); /* password can change */
2613 PACKI(&desc,"D",-1); /* password must change */
2616 fstrcpy(mypath,"\\\\");
2617 fstrcat(mypath,local_machine);
2619 PACKS(&desc,"z",mypath); /* computer */
2621 PACKS(&desc,"z",global_myworkgroup);/* domain */
2623 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2624 /* made sure all macros are fully substituted and available */
2625 logon_script = lp_logon_script();
2626 standard_sub( conn, logon_script );
2627 PACKS(&desc,"z", logon_script); /* script path */
2628 /* End of JHT mods */
2630 PACKI(&desc,"D",0x00000000); /* reserved */
2633 *rdata_len = desc.usedlen;
2635 *rparam = REALLOC(*rparam,*rparam_len);
2636 SSVALS(*rparam,0,desc.errcode);
2638 SSVAL(*rparam,4,desc.neededlen);
2640 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2645 /****************************************************************************
2646 api_WAccessGetUserPerms
2647 ****************************************************************************/
2648 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2649 int mdrcnt,int mprcnt,
2650 char **rdata,char **rparam,
2651 int *rdata_len,int *rparam_len)
2653 char *str1 = param+2;
2654 char *str2 = skip_string(str1,1);
2655 char *user = skip_string(str2,1);
2656 char *resource = skip_string(user,1);
2658 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2660 /* check it's a supported varient */
2661 if (strcmp(str1,"zzh") != 0) return False;
2662 if (strcmp(str2,"") != 0) return False;
2665 *rparam = REALLOC(*rparam,*rparam_len);
2666 SSVALS(*rparam,0,0); /* errorcode */
2667 SSVAL(*rparam,2,0); /* converter word */
2668 SSVAL(*rparam,4,0x7f); /* permission flags */
2673 /****************************************************************************
2674 api_WPrintJobEnumerate
2675 ****************************************************************************/
2676 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2677 int mdrcnt,int mprcnt,
2678 char **rdata,char **rparam,
2679 int *rdata_len,int *rparam_len)
2681 char *str1 = param+2;
2682 char *str2 = skip_string(str1,1);
2683 char *p = skip_string(str2,1);
2689 struct pack_desc desc;
2690 print_queue_struct *queue=NULL;
2691 print_status_struct status;
2696 bzero(&desc,sizeof(desc));
2697 bzero(&status,sizeof(status));
2699 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2701 /* check it's a supported varient */
2702 if (strcmp(str1,"WWrLh") != 0) return False;
2703 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2705 printjob_decode(SVAL(p,0), &snum, &job);
2707 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2709 count = get_printqueue(snum,conn,&queue,&status);
2710 for (i = 0; i < count; i++) {
2711 if ((queue[i].job & 0xFF) == job) break;
2713 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2715 desc.buflen = mdrcnt;
2717 if (init_package(&desc,1,0)) {
2719 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2720 *rdata_len = desc.usedlen;
2723 desc.errcode = NERR_JobNotFound;
2729 *rparam = REALLOC(*rparam,*rparam_len);
2730 SSVALS(*rparam,0,desc.errcode);
2732 SSVAL(*rparam,4,desc.neededlen);
2734 if (queue) free(queue);
2736 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2740 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2741 int mdrcnt,int mprcnt,
2742 char **rdata,char **rparam,
2743 int *rdata_len,int *rparam_len)
2745 char *str1 = param+2;
2746 char *str2 = skip_string(str1,1);
2747 char *p = skip_string(str2,1);
2753 struct pack_desc desc;
2754 print_queue_struct *queue=NULL;
2755 print_status_struct status;
2757 bzero(&desc,sizeof(desc));
2758 bzero(&status,sizeof(status));
2760 p = skip_string(p,1);
2764 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2766 /* check it's a supported varient */
2767 if (strcmp(str1,"zWrLeh") != 0) return False;
2768 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2769 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2771 snum = lp_servicenumber(name);
2772 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2773 int pnum = lp_servicenumber(PRINTERS_NAME);
2775 lp_add_printer(name,pnum);
2776 snum = lp_servicenumber(name);
2780 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2782 count = get_printqueue(snum,conn,&queue,&status);
2783 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2785 desc.buflen = mdrcnt;
2787 if (init_package(&desc,count,0)) {
2789 for (i = 0; i < count; i++) {
2790 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2791 if (desc.errcode == NERR_Success) succnt = i+1;
2795 *rdata_len = desc.usedlen;
2798 *rparam = REALLOC(*rparam,*rparam_len);
2799 SSVALS(*rparam,0,desc.errcode);
2801 SSVAL(*rparam,4,succnt);
2802 SSVAL(*rparam,6,count);
2804 if (queue) free(queue);
2806 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2810 static int check_printdest_info(struct pack_desc* desc,
2811 int uLevel, char* id)
2813 desc->subformat = NULL;
2815 case 0: desc->format = "B9"; break;
2816 case 1: desc->format = "B9B21WWzW"; break;
2817 case 2: desc->format = "z"; break;
2818 case 3: desc->format = "zzzWWzzzWW"; break;
2819 default: return False;
2821 if (strcmp(desc->format,id) != 0) return False;
2825 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2826 struct pack_desc* desc)
2829 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2830 buf[sizeof(buf)-1] = 0;
2833 PACKS(desc,"B9",buf); /* szName */
2835 PACKS(desc,"B21",""); /* szUserName */
2836 PACKI(desc,"W",0); /* uJobId */
2837 PACKI(desc,"W",0); /* fsStatus */
2838 PACKS(desc,"z",""); /* pszStatus */
2839 PACKI(desc,"W",0); /* time */
2842 if (uLevel == 2 || uLevel == 3) {
2843 PACKS(desc,"z",buf); /* pszPrinterName */
2845 PACKS(desc,"z",""); /* pszUserName */
2846 PACKS(desc,"z",""); /* pszLogAddr */
2847 PACKI(desc,"W",0); /* uJobId */
2848 PACKI(desc,"W",0); /* fsStatus */
2849 PACKS(desc,"z",""); /* pszStatus */
2850 PACKS(desc,"z",""); /* pszComment */
2851 PACKS(desc,"z","NULL"); /* pszDrivers */
2852 PACKI(desc,"W",0); /* time */
2853 PACKI(desc,"W",0); /* pad1 */
2858 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2859 int mdrcnt,int mprcnt,
2860 char **rdata,char **rparam,
2861 int *rdata_len,int *rparam_len)
2863 char *str1 = param+2;
2864 char *str2 = skip_string(str1,1);
2865 char *p = skip_string(str2,1);
2866 char* PrinterName = p;
2868 struct pack_desc desc;
2871 bzero(&desc,sizeof(desc));
2873 p = skip_string(p,1);
2877 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2879 /* check it's a supported varient */
2880 if (strcmp(str1,"zWrLh") != 0) return False;
2881 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2883 snum = lp_servicenumber(PrinterName);
2884 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2885 int pnum = lp_servicenumber(PRINTERS_NAME);
2887 lp_add_printer(PrinterName,pnum);
2888 snum = lp_servicenumber(PrinterName);
2894 desc.errcode = NERR_DestNotFound;
2898 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2900 desc.buflen = mdrcnt;
2901 if (init_package(&desc,1,0)) {
2902 fill_printdest_info(conn,snum,uLevel,&desc);
2904 *rdata_len = desc.usedlen;
2908 *rparam = REALLOC(*rparam,*rparam_len);
2909 SSVALS(*rparam,0,desc.errcode);
2911 SSVAL(*rparam,4,desc.neededlen);
2913 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2917 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2918 int mdrcnt,int mprcnt,
2919 char **rdata,char **rparam,
2920 int *rdata_len,int *rparam_len)
2922 char *str1 = param+2;
2923 char *str2 = skip_string(str1,1);
2924 char *p = skip_string(str2,1);
2928 struct pack_desc desc;
2929 int services = lp_numservices();
2931 bzero(&desc,sizeof(desc));
2936 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2938 /* check it's a supported varient */
2939 if (strcmp(str1,"WrLeh") != 0) return False;
2940 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2943 for (i = 0; i < services; i++)
2944 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2947 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2949 desc.buflen = mdrcnt;
2950 if (init_package(&desc,queuecnt,0)) {
2953 for (i = 0; i < services; i++) {
2954 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2955 fill_printdest_info(conn,i,uLevel,&desc);
2957 if (desc.errcode == NERR_Success) succnt = n;
2962 *rdata_len = desc.usedlen;
2965 *rparam = REALLOC(*rparam,*rparam_len);
2966 SSVALS(*rparam,0,desc.errcode);
2968 SSVAL(*rparam,4,succnt);
2969 SSVAL(*rparam,6,queuecnt);
2971 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2975 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2976 int mdrcnt,int mprcnt,
2977 char **rdata,char **rparam,
2978 int *rdata_len,int *rparam_len)
2980 char *str1 = param+2;
2981 char *str2 = skip_string(str1,1);
2982 char *p = skip_string(str2,1);
2985 struct pack_desc desc;
2987 bzero(&desc,sizeof(desc));
2992 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2994 /* check it's a supported varient */
2995 if (strcmp(str1,"WrLeh") != 0) return False;
2996 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2998 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3000 desc.buflen = mdrcnt;
3001 if (init_package(&desc,1,0)) {
3002 PACKS(&desc,"B41","NULL");
3005 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3007 *rdata_len = desc.usedlen;
3010 *rparam = REALLOC(*rparam,*rparam_len);
3011 SSVALS(*rparam,0,desc.errcode);
3013 SSVAL(*rparam,4,succnt);
3016 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3020 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3021 int mdrcnt,int mprcnt,
3022 char **rdata,char **rparam,
3023 int *rdata_len,int *rparam_len)
3025 char *str1 = param+2;
3026 char *str2 = skip_string(str1,1);
3027 char *p = skip_string(str2,1);
3030 struct pack_desc desc;
3032 bzero(&desc,sizeof(desc));
3037 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3039 /* check it's a supported varient */
3040 if (strcmp(str1,"WrLeh") != 0) return False;
3041 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3043 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3045 desc.buflen = mdrcnt;
3047 if (init_package(&desc,1,0)) {
3048 PACKS(&desc,"B13","lpd");
3051 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3053 *rdata_len = desc.usedlen;
3056 *rparam = REALLOC(*rparam,*rparam_len);
3057 SSVALS(*rparam,0,desc.errcode);
3059 SSVAL(*rparam,4,succnt);
3062 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3066 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3067 int mdrcnt,int mprcnt,
3068 char **rdata,char **rparam,
3069 int *rdata_len,int *rparam_len)
3071 char *str1 = param+2;
3072 char *str2 = skip_string(str1,1);
3073 char *p = skip_string(str2,1);
3076 struct pack_desc desc;
3078 bzero(&desc,sizeof(desc));
3083 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3085 /* check it's a supported varient */
3086 if (strcmp(str1,"WrLeh") != 0) return False;
3087 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3089 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3090 bzero(&desc,sizeof(desc));
3092 desc.buflen = mdrcnt;
3094 if (init_package(&desc,1,0)) {
3095 PACKS(&desc,"B13","lp0");
3098 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3100 *rdata_len = desc.usedlen;
3103 *rparam = REALLOC(*rparam,*rparam_len);
3104 SSVALS(*rparam,0,desc.errcode);
3106 SSVAL(*rparam,4,succnt);
3109 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3115 char * pipe_clnt_name;
3116 char * pipe_srv_name;
3117 BOOL (*fn) (pipes_struct *, prs_struct *);
3120 static struct api_cmd api_fd_commands[] =
3122 { "lsarpc", "lsass", api_ntlsa_rpc },
3123 { "samr", "lsass", api_samr_rpc },
3124 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3125 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3126 { "NETLOGON", "lsass", api_netlog_rpc },
3127 { "winreg", "winreg", api_reg_rpc },
3128 { NULL, NULL, NULL }
3131 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3133 BOOL ntlmssp_auth = False;
3134 fstring ack_pipe_name;
3137 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3139 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3141 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3142 api_fd_commands[i].fn != NULL)
3144 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3145 api_fd_commands[i].pipe_clnt_name,
3146 api_fd_commands[i].pipe_srv_name));
3147 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3152 if (api_fd_commands[i].fn == NULL) return False;
3154 /* decode the bind request */
3155 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3157 if (pd->offset == 0) return False;
3159 if (p->hdr.auth_len != 0)
3161 /* decode the authentication verifier */
3162 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3164 if (pd->offset == 0) return False;
3166 /* ignore the version number for now */
3167 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3170 /* name has to be \PIPE\xxxxx */
3171 fstrcpy(ack_pipe_name, "\\PIPE\\");
3172 fstrcat(ack_pipe_name, p->pipe_srv_name);
3174 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3176 prs_init(&(p->rdata), 1024, 4, 0, False);
3177 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3178 prs_init(&(p->rauth), 1024, 4, 0, False);
3181 /*** do the bind ack first ***/
3184 make_rpc_hdr_ba(&p->hdr_ba,
3185 p->hdr_rb.bba.max_tsize,
3186 p->hdr_rb.bba.max_rsize,
3187 p->hdr_rb.bba.assoc_gid,
3190 &(p->hdr_rb.transfer));
3192 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3193 mem_realloc_data(p->rdata.data, p->rdata.offset);
3196 /*** now the authentication ***/
3202 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3204 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3207 0x00000000, 0x0000b2b3, 0x000082b1,
3209 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3210 mem_realloc_data(p->rauth.data, p->rauth.offset);
3214 /*** then do the header, now we know the length ***/
3217 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3219 p->rdata.offset + p->rauth.offset,
3222 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3223 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3226 /*** link rpc header, bind acknowledgment and authentication responses ***/
3229 p->rhdr.data->offset.start = 0;
3230 p->rhdr.data->offset.end = p->rhdr.offset;
3231 p->rhdr.data->next = p->rdata.data;
3235 p->rdata.data->offset.start = p->rhdr.offset;
3236 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3237 p->rdata.data->next = p->rauth.data;
3239 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3240 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3241 p->rauth.data->next = NULL;
3245 p->rdata.data->offset.start = p->rhdr.offset;
3246 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3247 p->rdata.data->next = NULL;
3253 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3257 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3259 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3260 api_fd_commands[i].fn != NULL)
3262 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3263 return api_fd_commands[i].fn(p, pd);
3269 static BOOL api_dce_rpc_command(char *outbuf,
3274 if (pd->data == NULL) return False;
3276 /* process the rpc header */
3277 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3279 if (pd->offset == 0) return False;
3281 switch (p->hdr.pkt_type)
3285 reply = api_pipe_bind_req(p, pd);
3290 reply = api_pipe_request (p, pd);
3297 /* now send the reply */
3298 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3300 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3302 /* all of data was sent: no need to wait for SMBreadX calls */
3303 mem_free_data(p->rhdr .data);
3304 mem_free_data(p->rdata.data);
3311 /****************************************************************************
3312 SetNamedPipeHandleState
3313 ****************************************************************************/
3314 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3318 if (!param) return False;
3320 id = param[0] + (param[1] << 8);
3321 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3323 if (set_rpc_pipe_hnd_state(p, id))
3325 /* now send the reply */
3326 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3334 /****************************************************************************
3335 when no reply is generated, indicate unsupported.
3336 ****************************************************************************/
3337 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3339 struct mem_buf rparam;
3341 mem_init(&rparam, 0);
3342 mem_alloc_data(&rparam, 4);
3344 rparam.offset.start = 0;
3345 rparam.offset.end = 4;
3348 SSVAL(rparam.data,0,NERR_notsupported);
3349 SSVAL(rparam.data,2,0); /* converter word */
3351 DEBUG(3,("Unsupported API fd command\n"));
3353 /* now send the reply */
3354 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3356 mem_free_data(&rparam);
3361 /****************************************************************************
3362 handle remote api calls delivered to a named pipe already opened.
3363 ****************************************************************************/
3364 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3365 uint16 *setup,char *data,char *params,
3366 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3372 pipes_struct *p = NULL;
3374 struct mem_buf data_buf;
3376 DEBUG(5,("api_fd_reply\n"));
3378 /* fake up a data buffer from the api_fd_reply data parameters */
3379 mem_create(&data_buf, data, tdscnt, 0, False);
3380 data_buf.offset.start = 0;
3381 data_buf.offset.end = tdscnt;
3383 /* fake up a parsing structure */
3384 pd.data = &data_buf;
3389 /* First find out the name of this file. */
3392 DEBUG(0,("Unexpected named pipe transaction.\n"));
3396 /* Get the file handle and hence the file name. */
3398 subcommand = setup[0];
3399 p = get_rpc_pipe(pnum);
3403 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3404 subcommand, p->name, pnum));
3406 /* record maximum data length that can be transmitted in an SMBtrans */
3407 p->file_offset = mdrcnt;
3409 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3410 p, p->file_offset));
3416 /* dce/rpc command */
3417 reply = api_dce_rpc_command(outbuf, p, &pd);
3422 /* Set Named Pipe Handle state */
3423 reply = api_SNPHS(outbuf, p, params);
3430 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3435 return api_no_reply(outbuf, mdrcnt);
3440 /****************************************************************************
3441 the buffer was too small
3442 ****************************************************************************/
3443 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3444 int mdrcnt,int mprcnt,
3445 char **rdata,char **rparam,
3446 int *rdata_len,int *rparam_len)
3448 *rparam_len = MIN(*rparam_len,mprcnt);
3449 *rparam = REALLOC(*rparam,*rparam_len);
3453 SSVAL(*rparam,0,NERR_BufTooSmall);
3455 DEBUG(3,("Supplied buffer too small in API command\n"));
3461 /****************************************************************************
3462 the request is not supported
3463 ****************************************************************************/
3464 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3465 int mdrcnt,int mprcnt,
3466 char **rdata,char **rparam,
3467 int *rdata_len,int *rparam_len)
3470 *rparam = REALLOC(*rparam,*rparam_len);
3474 SSVAL(*rparam,0,NERR_notsupported);
3475 SSVAL(*rparam,2,0); /* converter word */
3477 DEBUG(3,("Unsupported API command\n"));
3489 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3490 int,int,char **,char **,int *,int *);
3492 } api_commands[] = {
3493 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3494 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3495 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3496 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3497 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3498 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3499 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3500 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3501 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3502 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3503 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3504 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3505 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3506 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3507 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3508 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3509 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3510 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3511 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3512 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3513 {"NetServerEnum", 104, api_RNetServerEnum,0},
3514 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3515 {"SetUserPassword", 115, api_SetUserPassword,0},
3516 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3517 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3518 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3519 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3520 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3521 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3522 {NULL, -1, api_Unsupported,0}};
3525 /****************************************************************************
3526 handle remote api calls
3527 ****************************************************************************/
3528 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3529 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3531 int api_command = SVAL(params,0);
3532 struct mem_buf rdata_buf;
3533 struct mem_buf rparam_buf;
3535 char *rparam = NULL;
3541 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3542 api_command,params+2,skip_string(params+2,1),
3543 tdscnt,tpscnt,mdrcnt,mprcnt));
3545 for (i=0;api_commands[i].name;i++)
3546 if (api_commands[i].id == api_command && api_commands[i].fn)
3548 DEBUG(3,("Doing %s\n",api_commands[i].name));
3552 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3553 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3555 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3556 &rdata,&rparam,&rdata_len,&rparam_len);
3559 if (rdata_len > mdrcnt ||
3560 rparam_len > mprcnt)
3562 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3563 &rdata,&rparam,&rdata_len,&rparam_len);
3567 /* if we get False back then it's actually unsupported */
3569 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3570 &rdata,&rparam,&rdata_len,&rparam_len);
3573 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3574 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3576 rdata_buf.offset.start = 0;
3577 rdata_buf.offset.end = rdata_len;
3579 rparam_buf.offset.start = 0;
3580 rparam_buf.offset.end = rparam_len;
3582 /* now send the reply */
3583 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3585 if (rdata ) free(rdata);
3586 if (rparam) free(rparam);
3591 /****************************************************************************
3592 handle named pipe commands
3593 ****************************************************************************/
3594 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3595 uint16 *setup,char *data,char *params,
3596 int suwcnt,int tdscnt,int tpscnt,
3597 int msrcnt,int mdrcnt,int mprcnt)
3599 DEBUG(3,("named pipe command on <%s> name\n", name));
3601 if (strequal(name,"LANMAN"))
3603 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3606 if (strlen(name) < 1)
3608 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3613 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3620 /****************************************************************************
3622 ****************************************************************************/
3623 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3627 char *data=NULL,*params=NULL;
3630 uint16 vuid = SVAL(inbuf,smb_uid);
3631 int tpscnt = SVAL(inbuf,smb_vwv0);
3632 int tdscnt = SVAL(inbuf,smb_vwv1);
3633 int mprcnt = SVAL(inbuf,smb_vwv2);
3634 int mdrcnt = SVAL(inbuf,smb_vwv3);
3635 int msrcnt = CVAL(inbuf,smb_vwv4);
3636 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3637 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3638 int pscnt = SVAL(inbuf,smb_vwv9);
3639 int psoff = SVAL(inbuf,smb_vwv10);
3640 int dscnt = SVAL(inbuf,smb_vwv11);
3641 int dsoff = SVAL(inbuf,smb_vwv12);
3642 int suwcnt = CVAL(inbuf,smb_vwv13);
3644 bzero(name, sizeof(name));
3645 fstrcpy(name,smb_buf(inbuf));
3647 if (dscnt > tdscnt || pscnt > tpscnt) {
3648 exit_server("invalid trans parameters\n");
3652 data = (char *)malloc(tdscnt);
3653 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3657 params = (char *)malloc(tpscnt);
3658 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3663 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3664 for (i=0;i<suwcnt;i++)
3665 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3669 if (pscnt < tpscnt || dscnt < tdscnt) {
3670 /* We need to send an interim response then receive the rest
3671 of the parameter/data bytes */
3672 outsize = set_message(outbuf,0,0,True);
3674 send_smb(Client,outbuf);
3677 /* receive the rest of the trans packet */
3678 while (pscnt < tpscnt || dscnt < tdscnt) {
3680 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3682 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3684 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3686 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3688 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3689 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3691 if (params) free(params);
3692 if (data) free(data);
3693 if (setup) free(setup);
3694 return(ERROR(ERRSRV,ERRerror));
3699 tpscnt = SVAL(inbuf,smb_vwv0);
3700 tdscnt = SVAL(inbuf,smb_vwv1);
3702 pcnt = SVAL(inbuf,smb_vwv2);
3703 poff = SVAL(inbuf,smb_vwv3);
3704 pdisp = SVAL(inbuf,smb_vwv4);
3706 dcnt = SVAL(inbuf,smb_vwv5);
3707 doff = SVAL(inbuf,smb_vwv6);
3708 ddisp = SVAL(inbuf,smb_vwv7);
3713 if (dscnt > tdscnt || pscnt > tpscnt) {
3714 exit_server("invalid trans parameters\n");
3718 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3720 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3724 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3725 name,tdscnt,tpscnt,suwcnt));
3727 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3728 DEBUG(5,("calling named_pipe\n"));
3729 outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3730 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3732 DEBUG(3,("invalid pipe name\n"));
3737 if (data) free(data);
3738 if (params) free(params);
3739 if (setup) free(setup);
3741 if (close_on_completion)
3742 close_cnum(conn,vuid);
3748 return(ERROR(ERRSRV,ERRnosupport));