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));
388 if (!p->curpos) return(0);
390 switch( *p->curpos++ ) {
391 case 'W': /* word (2 byte) */
393 temp = va_arg(args,int);
394 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
396 case 'N': /* count of substructures (word) at end */
398 p->subcount = va_arg(args,int);
399 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
401 case 'D': /* double word (4 byte) */
403 temp = va_arg(args,int);
404 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
406 case 'B': /* byte (with optional counter) */
407 needed = get_counter(&p->curpos);
409 char *s = va_arg(args,char*);
410 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
413 case 'z': /* offset to zero terminated string (4 byte) */
414 str = va_arg(args,char*);
415 stringneeded = (str ? strlen(str)+1 : 0);
418 case 'l': /* offset to user data (4 byte) */
419 str = va_arg(args,char*);
420 stringneeded = va_arg(args,int);
423 case 'b': /* offset to data (with counter) (4 byte) */
424 str = va_arg(args,char*);
425 stringneeded = get_counter(&p->curpos);
430 if (stringneeded >= 0) {
432 if (p->buflen >= needed) {
433 stringused = stringneeded;
434 if (stringused > p->stringlen) {
435 stringused = (is_string ? p->stringlen : 0);
436 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
439 SIVAL(p->structbuf,0,0);
441 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
442 memcpy(p->stringbuf,str?str:"",stringused);
443 if (is_string) p->stringbuf[stringused-1] = '\0';
444 p->stringbuf += stringused;
445 p->stringlen -= stringused;
446 p->usedlen += stringused;
449 p->neededlen += stringneeded;
451 p->neededlen += needed;
452 if (p->buflen >= needed) {
453 p->structbuf += needed;
455 p->usedlen += needed;
458 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
464 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
465 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
467 #define PACK(desc,t,v) package(desc,v)
468 #define PACKl(desc,t,v,l) package(desc,v,l)
471 static void PACKI(struct pack_desc* desc,char *t,int v)
476 static void PACKS(struct pack_desc* desc,char *t,char *v)
482 /****************************************************************************
484 ****************************************************************************/
486 static void PackDriverData(struct pack_desc* desc)
488 char drivdata[4+4+32];
489 SIVAL(drivdata,0,sizeof drivdata); /* cb */
490 SIVAL(drivdata,4,1000); /* lVersion */
491 memset(drivdata+8,0,32); /* szDeviceName */
492 pstrcpy(drivdata+8,"NULL");
493 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
496 static int check_printq_info(struct pack_desc* desc,
497 int uLevel, char *id1, char *id2)
499 desc->subformat = NULL;
502 desc->format = "B13";
505 desc->format = "B13BWWWzzzzzWW";
508 desc->format = "B13BWWWzzzzzWN";
509 desc->subformat = "WB21BB16B10zWWzDDz";
512 desc->format = "zWWWWzzzzWWzzl";
515 desc->format = "zWWWWzzzzWNzzl";
516 desc->subformat = "WWzWWDDzz";
522 desc->format = "WzzzzzzzzN";
523 desc->subformat = "z";
525 default: return False;
527 if (strcmp(desc->format,id1) != 0) return False;
528 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
532 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
533 struct pack_desc* desc,
534 print_queue_struct* queue, int n)
536 time_t t = queue->time;
538 /* the client expects localtime */
541 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
543 PACKS(desc,"B21",queue->user); /* szUserName */
544 PACKS(desc,"B",""); /* pad */
545 PACKS(desc,"B16",""); /* szNotifyName */
546 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
547 PACKS(desc,"z",""); /* pszParms */
548 PACKI(desc,"W",n+1); /* uPosition */
549 PACKI(desc,"W",queue->status); /* fsStatus */
550 PACKS(desc,"z",""); /* pszStatus */
551 PACKI(desc,"D",t); /* ulSubmitted */
552 PACKI(desc,"D",queue->size); /* ulSize */
553 PACKS(desc,"z",queue->file); /* pszComment */
555 if (uLevel == 2 || uLevel == 3) {
556 PACKI(desc,"W",queue->priority); /* uPriority */
557 PACKS(desc,"z",queue->user); /* pszUserName */
558 PACKI(desc,"W",n+1); /* uPosition */
559 PACKI(desc,"W",queue->status); /* fsStatus */
560 PACKI(desc,"D",t); /* ulSubmitted */
561 PACKI(desc,"D",queue->size); /* ulSize */
562 PACKS(desc,"z","Samba"); /* pszComment */
563 PACKS(desc,"z",queue->file); /* pszDocument */
565 PACKS(desc,"z",""); /* pszNotifyName */
566 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
567 PACKS(desc,"z",""); /* pszParms */
568 PACKS(desc,"z",""); /* pszStatus */
569 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
570 PACKS(desc,"z","lpd"); /* pszQProcName */
571 PACKS(desc,"z",""); /* pszQProcParms */
572 PACKS(desc,"z","NULL"); /* pszDriverName */
573 PackDriverData(desc); /* pDriverData */
574 PACKS(desc,"z",""); /* pszPrinterName */
579 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
580 struct pack_desc* desc,
581 int count, print_queue_struct* queue,
582 print_status_struct* status)
587 PACKS(desc,"B13",SERVICE(snum));
592 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
596 if (uLevel == 1 || uLevel == 2) {
597 PACKS(desc,"B",""); /* alignment */
598 PACKI(desc,"W",5); /* priority */
599 PACKI(desc,"W",0); /* start time */
600 PACKI(desc,"W",0); /* until time */
601 PACKS(desc,"z",""); /* pSepFile */
602 PACKS(desc,"z","lpd"); /* pPrProc */
603 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
604 PACKS(desc,"z",""); /* pParms */
606 PACKS(desc,"z","UNKNOWN PRINTER");
607 PACKI(desc,"W",LPSTAT_ERROR);
609 else if (!status || !status->message[0]) {
610 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
611 PACKI(desc,"W",LPSTAT_OK); /* status */
613 PACKS(desc,"z",status->message);
614 PACKI(desc,"W",status->status); /* status */
616 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
618 if (uLevel == 3 || uLevel == 4) {
619 PACKI(desc,"W",5); /* uPriority */
620 PACKI(desc,"W",0); /* uStarttime */
621 PACKI(desc,"W",0); /* uUntiltime */
622 PACKI(desc,"W",5); /* pad1 */
623 PACKS(desc,"z",""); /* pszSepFile */
624 PACKS(desc,"z","WinPrint"); /* pszPrProc */
625 PACKS(desc,"z",""); /* pszParms */
626 if (!status || !status->message[0]) {
627 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
628 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
630 PACKS(desc,"z",status->message); /* pszComment */
631 PACKI(desc,"W",status->status); /* fsStatus */
633 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
634 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
635 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
636 PackDriverData(desc); /* pDriverData */
638 if (uLevel == 2 || uLevel == 4) {
640 for (i=0;i<count;i++)
641 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
646 pstring tok,driver,datafile,langmon,helpfile,datatype;
651 pstrcpy(fname,lp_driverfile());
654 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
655 desc->errcode=NERR_notsupported;
659 p=(char *)malloc(8192*sizeof(char));
660 bzero(p, 8192*sizeof(char));
663 /* lookup the long printer driver name in the file description */
664 while (f && !feof(f) && !ok)
666 p = q; /* reset string pointer */
669 if (next_token(&p,tok,":") &&
670 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
671 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
676 /* driver file name */
677 if (ok && !next_token(&p,driver,":")) ok = 0;
679 if (ok && !next_token(&p,datafile,":")) ok = 0;
681 * for the next tokens - which may be empty - I have to check for empty
682 * tokens first because the next_token function will skip all empty
690 } else if (!next_token(&p,helpfile,":")) ok = 0;
694 /* language monitor */
698 } else if (!next_token(&p,langmon,":")) ok = 0;
701 /* default data type */
702 if (ok && !next_token(&p,datatype,":")) ok = 0;
705 PACKI(desc,"W",0x0400); /* don't know */
706 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
707 PACKS(desc,"z",driver); /* Driverfile Name */
708 PACKS(desc,"z",datafile); /* Datafile name */
709 PACKS(desc,"z",langmon); /* language monitor */
710 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
711 PACKS(desc,"z",datatype); /* default data type */
712 PACKS(desc,"z",helpfile); /* helpfile name */
713 PACKS(desc,"z",driver); /* driver name */
714 DEBUG(3,("Driver:%s:\n",driver));
715 DEBUG(3,("Data File:%s:\n",datafile));
716 DEBUG(3,("Language Monitor:%s:\n",langmon));
717 DEBUG(3,("Data Type:%s:\n",datatype));
718 DEBUG(3,("Help File:%s:\n",helpfile));
719 PACKI(desc,"N",count); /* number of files to copy */
720 for (i=0;i<count;i++)
722 /* no need to check return value here - it was already tested in
723 * get_printerdrivernumber
725 next_token(&p,tok,",");
726 PACKS(desc,"z",tok); /* driver files to copy */
727 DEBUG(3,("file:%s:\n",tok));
730 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
731 SERVICE(snum),count));
733 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
734 desc->errcode=NERR_notsupported;
740 /* This function returns the number of files for a given driver */
741 int get_printerdrivernumber(int snum)
749 pstrcpy(fname,lp_driverfile());
751 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
754 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
758 p=(char *)malloc(8192*sizeof(char));
759 q=p; /* need it to free memory because p change ! */
761 /* lookup the long printer driver name in the file description */
762 while (!feof(f) && !ok)
764 p = q; /* reset string pointer */
766 if (next_token(&p,tok,":") &&
767 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
776 if (*p++ == ':') i--;
781 /* count the number of files */
782 while (next_token(&p,tok,","))
790 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
791 uint16 vuid, char *param,char *data,
792 int mdrcnt,int mprcnt,
793 char **rdata,char **rparam,
794 int *rdata_len,int *rparam_len)
796 char *str1 = param+2;
797 char *str2 = skip_string(str1,1);
798 char *p = skip_string(str2,1);
804 struct pack_desc desc;
805 print_queue_struct *queue=NULL;
806 print_status_struct status;
808 bzero(&status,sizeof(status));
809 bzero(&desc,sizeof(desc));
811 p = skip_string(p,1);
816 /* remove any trailing username */
817 if ((p = strchr(QueueName,'%'))) *p = 0;
819 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
821 /* check it's a supported varient */
822 if (!prefix_ok(str1,"zWrLh")) return False;
823 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
825 snum = lp_servicenumber(QueueName);
826 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
827 int pnum = lp_servicenumber(PRINTERS_NAME);
829 lp_add_printer(QueueName,pnum);
830 snum = lp_servicenumber(QueueName);
834 if (snum < 0 || !VALID_SNUM(snum)) return(False);
837 count = get_printerdrivernumber(snum);
838 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
840 count = get_printqueue(snum, conn,&queue,&status);
843 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
845 desc.buflen = mdrcnt;
846 if (init_package(&desc,1,count)) {
847 desc.subcount = count;
848 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
851 *rdata_len = desc.usedlen;
854 *rparam = REALLOC(*rparam,*rparam_len);
855 SSVALS(*rparam,0,desc.errcode);
857 SSVAL(*rparam,4,desc.neededlen);
859 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
861 if (queue) free(queue);
867 /****************************************************************************
868 view list of all print jobs on all queues
869 ****************************************************************************/
870 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
871 int mdrcnt, int mprcnt,
872 char **rdata, char** rparam,
873 int *rdata_len, int *rparam_len)
875 char *param_format = param+2;
876 char *output_format1 = skip_string(param_format,1);
877 char *p = skip_string(output_format1,1);
878 int uLevel = SVAL(p,0);
879 char *output_format2 = p + 4;
880 int services = lp_numservices();
882 struct pack_desc desc;
883 print_queue_struct **queue = NULL;
884 print_status_struct *status = NULL;
885 int* subcntarr = NULL;
886 int queuecnt, subcnt=0, succnt=0;
888 bzero(&desc,sizeof(desc));
890 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
892 if (!prefix_ok(param_format,"WrLeh")) return False;
893 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
896 for (i = 0; i < services; i++)
897 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
900 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
901 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
902 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
903 memset(status,0,queuecnt*sizeof(print_status_struct));
904 subcntarr = (int*)malloc(queuecnt*sizeof(int));
907 for (i = 0; i < services; i++)
908 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
909 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
910 subcnt += subcntarr[n];
914 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
916 desc.buflen = mdrcnt;
918 if (init_package(&desc,queuecnt,subcnt)) {
921 for (i = 0; i < services; i++)
922 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
923 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
925 if (desc.errcode == NERR_Success) succnt = n;
929 if (subcntarr) free(subcntarr);
931 *rdata_len = desc.usedlen;
933 *rparam = REALLOC(*rparam,*rparam_len);
934 SSVALS(*rparam,0,desc.errcode);
936 SSVAL(*rparam,4,succnt);
937 SSVAL(*rparam,6,queuecnt);
939 for (i = 0; i < queuecnt; i++) {
940 if (queue && queue[i]) free(queue[i]);
943 if (queue) free(queue);
944 if (status) free(status);
949 /****************************************************************************
950 get info level for a server list query
951 ****************************************************************************/
952 static BOOL check_server_info(int uLevel, char* id)
956 if (strcmp(id,"B16") != 0) return False;
959 if (strcmp(id,"B16BBDz") != 0) return False;
967 struct srv_info_struct
977 /*******************************************************************
978 get server info lists from the files saved by nmbd. Return the
980 ******************************************************************/
981 static int get_server_info(uint32 servertype,
982 struct srv_info_struct **servers,
990 BOOL local_list_only;
992 pstrcpy(fname,lp_lockdir());
993 trim_string(fname,NULL,"/");
995 pstrcat(fname,SERVER_LIST);
997 f = fopen(fname,"r");
1000 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1004 /* request for everything is code for request all servers */
1005 if (servertype == SV_TYPE_ALL)
1006 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1008 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1010 DEBUG(4,("Servertype search: %8x\n",servertype));
1015 struct srv_info_struct *s;
1020 fgets(line,sizeof(line)-1,f);
1021 if (!*line) continue;
1023 if (count == alloced) {
1025 (*servers) = (struct srv_info_struct *)
1026 Realloc(*servers,sizeof(**servers)*alloced);
1027 if (!(*servers)) return(0);
1028 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1030 s = &(*servers)[count];
1032 if (!next_token(&ptr,s->name , NULL)) continue;
1033 if (!next_token(&ptr,stype , NULL)) continue;
1034 if (!next_token(&ptr,s->comment, NULL)) continue;
1035 if (!next_token(&ptr,s->domain , NULL)) {
1036 /* this allows us to cope with an old nmbd */
1037 pstrcpy(s->domain,global_myworkgroup);
1040 if (sscanf(stype,"%X",&s->type) != 1) {
1041 DEBUG(4,("r:host file "));
1045 /* Filter the servers/domains we return based on what was asked for. */
1047 /* Check to see if we are being asked for a local list only. */
1048 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1049 DEBUG(4,("r: local list only"));
1053 /* doesn't match up: don't want it */
1054 if (!(servertype & s->type)) {
1055 DEBUG(4,("r:serv type "));
1059 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1060 (s->type & SV_TYPE_DOMAIN_ENUM))
1062 DEBUG(4,("s: dom mismatch "));
1066 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1071 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1072 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1076 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1077 s->name, s->type, s->comment, s->domain));
1079 s->server_added = True;
1084 DEBUG(4,("%20s %8x %25s %15s\n",
1085 s->name, s->type, s->comment, s->domain));
1094 /*******************************************************************
1095 fill in a server info structure
1096 ******************************************************************/
1097 static int fill_srv_info(struct srv_info_struct *service,
1098 int uLevel, char **buf, int *buflen,
1099 char **stringbuf, int *stringspace, char *baseaddr)
1108 case 0: struct_len = 16; break;
1109 case 1: struct_len = 26; break;
1119 len = strlen(service->comment)+1;
1123 if (buflen) *buflen = struct_len;
1124 if (stringspace) *stringspace = len;
1125 return struct_len + len;
1130 if (*buflen < struct_len) return -1;
1138 p2 = p + struct_len;
1139 l2 = *buflen - struct_len;
1141 if (!baseaddr) baseaddr = p;
1146 StrnCpy(p,service->name,15);
1150 StrnCpy(p,service->name,15);
1151 SIVAL(p,18,service->type);
1152 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1153 len += CopyAndAdvance(&p2,service->comment,&l2);
1159 *buf = p + struct_len;
1160 *buflen -= struct_len;
1173 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1175 return(strcmp(s1->name,s2->name));
1178 /****************************************************************************
1179 view list of servers available (or possibly domains). The info is
1180 extracted from lists saved by nmbd on the local host
1181 ****************************************************************************/
1182 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1183 int mdrcnt, int mprcnt, char **rdata,
1184 char **rparam, int *rdata_len, int *rparam_len)
1186 char *str1 = param+2;
1187 char *str2 = skip_string(str1,1);
1188 char *p = skip_string(str2,1);
1189 int uLevel = SVAL(p,0);
1190 int buf_len = SVAL(p,2);
1191 uint32 servertype = IVAL(p,4);
1193 int data_len, fixed_len, string_len;
1194 int f_len = 0, s_len = 0;
1195 struct srv_info_struct *servers=NULL;
1196 int counted=0,total=0;
1199 BOOL domain_request;
1202 /* If someone sets all the bits they don't really mean to set
1203 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1206 if (servertype == SV_TYPE_ALL)
1207 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1209 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1210 any other bit (they may just set this bit on it's own) they
1211 want all the locally seen servers. However this bit can be
1212 set on its own so set the requested servers to be
1213 ALL - DOMAIN_ENUM. */
1215 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1216 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1218 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1219 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1223 if (!prefix_ok(str1,"WrLehD")) return False;
1224 if (!check_server_info(uLevel,str2)) return False;
1226 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1227 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1228 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1230 if (strcmp(str1, "WrLehDz") == 0) {
1231 StrnCpy(domain, p, sizeof(fstring)-1);
1233 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1236 if (lp_browse_list())
1237 total = get_server_info(servertype,&servers,domain);
1239 data_len = fixed_len = string_len = 0;
1242 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1245 char *lastname=NULL;
1247 for (i=0;i<total;i++)
1249 struct srv_info_struct *s = &servers[i];
1250 if (lastname && strequal(lastname,s->name)) continue;
1252 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1253 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1254 s->name, s->type, s->comment, s->domain));
1256 if (data_len <= buf_len) {
1259 string_len += s_len;
1266 *rdata_len = fixed_len + string_len;
1267 *rdata = REALLOC(*rdata,*rdata_len);
1268 bzero(*rdata,*rdata_len);
1270 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1276 char *lastname=NULL;
1277 int count2 = counted;
1278 for (i = 0; i < total && count2;i++)
1280 struct srv_info_struct *s = &servers[i];
1281 if (lastname && strequal(lastname,s->name)) continue;
1283 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1284 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1285 s->name, s->type, s->comment, s->domain));
1291 *rparam = REALLOC(*rparam,*rparam_len);
1292 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1294 SSVAL(*rparam,4,counted);
1295 SSVAL(*rparam,6,counted+missed);
1297 if (servers) free(servers);
1299 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1300 domain,uLevel,counted,counted+missed));
1305 /****************************************************************************
1306 command 0x34 - suspected of being a "Lookup Names" stub api
1307 ****************************************************************************/
1308 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1309 int mdrcnt, int mprcnt, char **rdata,
1310 char **rparam, int *rdata_len, int *rparam_len)
1312 char *str1 = param+2;
1313 char *str2 = skip_string(str1,1);
1314 char *p = skip_string(str2,1);
1315 int uLevel = SVAL(p,0);
1316 int buf_len = SVAL(p,2);
1320 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1321 str1, str2, p, uLevel, buf_len));
1323 if (!prefix_ok(str1,"zWrLeh")) return False;
1329 *rparam = REALLOC(*rparam,*rparam_len);
1331 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1333 SSVAL(*rparam,4,counted);
1334 SSVAL(*rparam,6,counted+missed);
1339 /****************************************************************************
1340 get info about a share
1341 ****************************************************************************/
1342 static BOOL check_share_info(int uLevel, char* id)
1346 if (strcmp(id,"B13") != 0) return False;
1349 if (strcmp(id,"B13BWz") != 0) return False;
1352 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1355 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1357 default: return False;
1362 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1363 char** buf, int* buflen,
1364 char** stringbuf, int* stringspace, char* baseaddr)
1373 case 0: struct_len = 13; break;
1374 case 1: struct_len = 20; break;
1375 case 2: struct_len = 40; break;
1376 case 91: struct_len = 68; break;
1384 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1385 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1386 if (buflen) *buflen = struct_len;
1387 if (stringspace) *stringspace = len;
1388 return struct_len + len;
1393 if ((*buflen) < struct_len) return -1;
1401 p2 = p + struct_len;
1402 l2 = (*buflen) - struct_len;
1404 if (!baseaddr) baseaddr = p;
1406 StrnCpy(p,lp_servicename(snum),13);
1412 type = STYPE_DISKTREE;
1413 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1414 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1415 SSVAL(p,14,type); /* device type */
1416 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1417 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1422 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1423 SSVALS(p,22,-1); /* max uses */
1424 SSVAL(p,24,1); /* current uses */
1425 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1426 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1427 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1432 memset(p+40,0,SHPWLEN+2);
1444 (*buf) = p + struct_len;
1445 (*buflen) -= struct_len;
1447 (*stringspace) = l2;
1457 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1458 int mdrcnt,int mprcnt,
1459 char **rdata,char **rparam,
1460 int *rdata_len,int *rparam_len)
1462 char *str1 = param+2;
1463 char *str2 = skip_string(str1,1);
1464 char *netname = skip_string(str2,1);
1465 char *p = skip_string(netname,1);
1466 int uLevel = SVAL(p,0);
1467 int snum = find_service(netname);
1469 if (snum < 0) return False;
1471 /* check it's a supported varient */
1472 if (!prefix_ok(str1,"zWrLh")) return False;
1473 if (!check_share_info(uLevel,str2)) return False;
1475 *rdata = REALLOC(*rdata,mdrcnt);
1477 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1478 if (*rdata_len < 0) return False;
1481 *rparam = REALLOC(*rparam,*rparam_len);
1482 SSVAL(*rparam,0,NERR_Success);
1483 SSVAL(*rparam,2,0); /* converter word */
1484 SSVAL(*rparam,4,*rdata_len);
1489 /****************************************************************************
1490 view list of shares available
1491 ****************************************************************************/
1492 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1493 int mdrcnt,int mprcnt,
1494 char **rdata,char **rparam,
1495 int *rdata_len,int *rparam_len)
1497 char *str1 = param+2;
1498 char *str2 = skip_string(str1,1);
1499 char *p = skip_string(str2,1);
1500 int uLevel = SVAL(p,0);
1501 int buf_len = SVAL(p,2);
1503 int count=lp_numservices();
1504 int total=0,counted=0;
1505 BOOL missed = False;
1507 int data_len, fixed_len, string_len;
1508 int f_len = 0, s_len = 0;
1510 if (!prefix_ok(str1,"WrLeh")) return False;
1511 if (!check_share_info(uLevel,str2)) return False;
1513 data_len = fixed_len = string_len = 0;
1514 for (i=0;i<count;i++)
1515 if (lp_browseable(i) && lp_snum_ok(i))
1518 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1519 if (data_len <= buf_len)
1523 string_len += s_len;
1528 *rdata_len = fixed_len + string_len;
1529 *rdata = REALLOC(*rdata,*rdata_len);
1530 memset(*rdata,0,*rdata_len);
1532 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1536 for (i = 0; i < count;i++)
1537 if (lp_browseable(i) && lp_snum_ok(i))
1538 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1542 *rparam = REALLOC(*rparam,*rparam_len);
1543 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1545 SSVAL(*rparam,4,counted);
1546 SSVAL(*rparam,6,total);
1548 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1549 counted,total,uLevel,
1550 buf_len,*rdata_len,mdrcnt));
1556 /****************************************************************************
1557 get the time of day info
1558 ****************************************************************************/
1559 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1560 int mdrcnt,int mprcnt,
1561 char **rdata,char **rparam,
1562 int *rdata_len,int *rparam_len)
1566 *rparam = REALLOC(*rparam,*rparam_len);
1569 *rdata = REALLOC(*rdata,*rdata_len);
1571 SSVAL(*rparam,0,NERR_Success);
1572 SSVAL(*rparam,2,0); /* converter word */
1578 time_t unixdate = time(NULL);
1580 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1581 by NT in a "net time" operation,
1582 it seems to ignore the one below */
1584 /* the client expects to get localtime, not GMT, in this bit
1585 (I think, this needs testing) */
1586 t = LocalTime(&unixdate);
1588 SIVAL(p,4,0); /* msecs ? */
1589 CVAL(p,8) = t->tm_hour;
1590 CVAL(p,9) = t->tm_min;
1591 CVAL(p,10) = t->tm_sec;
1592 CVAL(p,11) = 0; /* hundredths of seconds */
1593 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1594 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1595 CVAL(p,16) = t->tm_mday;
1596 CVAL(p,17) = t->tm_mon + 1;
1597 SSVAL(p,18,1900+t->tm_year);
1598 CVAL(p,20) = t->tm_wday;
1605 /****************************************************************************
1606 set the user password
1607 ****************************************************************************/
1608 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1609 int mdrcnt,int mprcnt,
1610 char **rdata,char **rparam,
1611 int *rdata_len,int *rparam_len)
1613 char *p = skip_string(param+2,2);
1615 fstring pass1,pass2;
1619 p = skip_string(p,1);
1622 memcpy(pass2,p+16,16);
1625 *rparam = REALLOC(*rparam,*rparam_len);
1629 SSVAL(*rparam,0,NERR_badpass);
1630 SSVAL(*rparam,2,0); /* converter word */
1632 DEBUG(3,("Set password for <%s>\n",user));
1635 * Pass the user through the NT -> unix user mapping
1639 (void)map_username(user);
1642 * Do any UNIX username case mangling.
1644 (void)Get_Pwnam( user, True);
1647 * Attempt the plaintext password change first.
1648 * Older versions of Windows seem to do this.
1651 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1652 chgpasswd(user,pass1,pass2,False))
1654 SSVAL(*rparam,0,NERR_Success);
1658 * If the plaintext change failed, attempt
1659 * the encrypted. NT will generate this
1660 * after trying the samr method.
1663 if(SVAL(*rparam,0) != NERR_Success)
1665 struct smb_passwd *sampw = NULL;
1667 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1668 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1670 SSVAL(*rparam,0,NERR_Success);
1674 bzero(pass1,sizeof(fstring));
1675 bzero(pass2,sizeof(fstring));
1680 /****************************************************************************
1681 Set the user password (SamOEM version - gets plaintext).
1682 ****************************************************************************/
1684 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1685 int mdrcnt,int mprcnt,
1686 char **rdata,char **rparam,
1687 int *rdata_len,int *rparam_len)
1691 struct smb_passwd *sampw = NULL;
1692 char *p = param + 2;
1696 *rparam = REALLOC(*rparam,*rparam_len);
1700 SSVAL(*rparam,0,NERR_badpass);
1703 * Check the parameter definition is correct.
1705 if(!strequal(param + 2, "zsT")) {
1706 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1709 p = skip_string(p, 1);
1711 if(!strequal(p, "B516B16")) {
1712 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1715 p = skip_string(p,1);
1718 p = skip_string(p,1);
1720 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1723 * Pass the user through the NT -> unix user mapping
1727 (void)map_username(user);
1730 * Do any UNIX username case mangling.
1732 (void)Get_Pwnam( user, True);
1734 if(check_oem_password( user, (unsigned char *)data, &sampw,
1735 new_passwd, (int)sizeof(new_passwd)) == False) {
1740 * At this point we have the new case-sensitive plaintext
1741 * password in the fstring new_passwd. If we wanted to synchronise
1742 * with UNIX passwords we would call a UNIX password changing
1743 * function here. However it would have to be done as root
1744 * as the plaintext of the old users password is not
1748 if(lp_unix_password_sync())
1749 ret = chgpasswd(user,"", new_passwd, True);
1751 if(ret && change_oem_password( sampw, new_passwd, False)) {
1752 SSVAL(*rparam,0,NERR_Success);
1758 /****************************************************************************
1761 ****************************************************************************/
1762 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1763 int mdrcnt,int mprcnt,
1764 char **rdata,char **rparam,
1765 int *rdata_len,int *rparam_len)
1767 int function = SVAL(param,0);
1768 char *str1 = param+2;
1769 char *str2 = skip_string(str1,1);
1770 char *p = skip_string(str2,1);
1774 printjob_decode(SVAL(p,0), &snum, &jobid);
1776 /* check it's a supported varient */
1777 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1781 *rparam = REALLOC(*rparam,*rparam_len);
1785 SSVAL(*rparam,0,NERR_Success);
1787 if (snum >= 0 && VALID_SNUM(snum))
1789 print_queue_struct *queue=NULL;
1791 count = get_printqueue(snum,conn,&queue,NULL);
1793 for (i=0;i<count;i++)
1794 if ((queue[i].job&0xFF) == jobid)
1797 case 81: /* delete */
1798 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1799 del_printqueue(conn,snum,queue[i].job);
1801 case 82: /* pause */
1802 case 83: /* resume */
1803 DEBUG(3,("%s queue entry %d\n",
1804 (function==82?"pausing":"resuming"),queue[i].job));
1805 status_printjob(conn,snum,queue[i].job,
1806 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1813 SSVAL(*rparam,0,NERR_JobNotFound);
1815 if (queue) free(queue);
1818 SSVAL(*rparam,2,0); /* converter word */
1823 /****************************************************************************
1824 Purge a print queue - or pause or resume it.
1825 ****************************************************************************/
1826 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1827 int mdrcnt,int mprcnt,
1828 char **rdata,char **rparam,
1829 int *rdata_len,int *rparam_len)
1831 int function = SVAL(param,0);
1832 char *str1 = param+2;
1833 char *str2 = skip_string(str1,1);
1834 char *QueueName = skip_string(str2,1);
1837 /* check it's a supported varient */
1838 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1842 *rparam = REALLOC(*rparam,*rparam_len);
1846 SSVAL(*rparam,0,NERR_Success);
1847 SSVAL(*rparam,2,0); /* converter word */
1849 snum = lp_servicenumber(QueueName);
1850 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1851 int pnum = lp_servicenumber(PRINTERS_NAME);
1853 lp_add_printer(QueueName,pnum);
1854 snum = lp_servicenumber(QueueName);
1858 if (snum >= 0 && VALID_SNUM(snum)) {
1862 case 74: /* Pause queue */
1863 case 75: /* Resume queue */
1864 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1865 DEBUG(3,("Print queue %s, queue=%s\n",
1866 (function==74?"pause":"resume"),QueueName));
1868 case 103: /* Purge */
1870 print_queue_struct *queue=NULL;
1872 count = get_printqueue(snum,conn,&queue,NULL);
1873 for (i = 0; i < count; i++)
1874 del_printqueue(conn,snum,queue[i].job);
1876 if (queue) free(queue);
1877 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1887 /****************************************************************************
1888 set the property of a print job (undocumented?)
1889 ? function = 0xb -> set name of print job
1890 ? function = 0x6 -> move print job up/down
1891 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1892 or <WWsTP> <WB21BB16B10zWWzDDz>
1893 ****************************************************************************/
1894 static int check_printjob_info(struct pack_desc* desc,
1895 int uLevel, char* id)
1897 desc->subformat = NULL;
1899 case 0: desc->format = "W"; break;
1900 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1901 case 2: desc->format = "WWzWWDDzz"; break;
1902 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1903 default: return False;
1905 if (strcmp(desc->format,id) != 0) return False;
1909 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1910 int mdrcnt,int mprcnt,
1911 char **rdata,char **rparam,
1912 int *rdata_len,int *rparam_len)
1914 struct pack_desc desc;
1915 char *str1 = param+2;
1916 char *str2 = skip_string(str1,1);
1917 char *p = skip_string(str2,1);
1919 int uLevel = SVAL(p,2);
1920 int function = SVAL(p,4); /* what is this ?? */
1925 printjob_decode(SVAL(p,0), &snum, &jobid);
1928 *rparam = REALLOC(*rparam,*rparam_len);
1932 /* check it's a supported varient */
1933 if ((strcmp(str1,"WWsTP")) ||
1934 (!check_printjob_info(&desc,uLevel,str2)))
1938 case 0x6: /* change job place in the queue,
1939 data gives the new place */
1940 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);
1953 desc.errcode=NERR_Success;
1957 int place= SVAL(data,0);
1958 /* we currently have no way of
1959 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
1966 if (queue) free(queue);
1969 desc.errcode=NERR_JobNotFound;
1973 case 0xb: /* change print job name, data gives the name */
1974 /* jobid, snum should be zero */
1975 if (isalpha((int)*s)) {
1978 while (l<64 && *s) {
1979 if (issafe(*s)) name[l++] = *s;
1984 DEBUG(3,("Setting print name to %s\n",name));
1986 fsp = file_find_print();
1989 connection_struct *fconn = fsp->conn;
1992 if (!become_user(fconn,vuid) ||
1993 !become_service(fconn,True))
1996 if (sys_rename(fsp->fsp_name,name) == 0) {
1997 string_set(&fsp->fsp_name,name);
2002 desc.errcode=NERR_Success;
2005 default: /* not implemented */
2009 SSVALS(*rparam,0,desc.errcode);
2010 SSVAL(*rparam,2,0); /* converter word */
2016 /****************************************************************************
2017 get info about the server
2018 ****************************************************************************/
2019 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2020 int mdrcnt,int mprcnt,
2021 char **rdata,char **rparam,
2022 int *rdata_len,int *rparam_len)
2024 char *str1 = param+2;
2025 char *str2 = skip_string(str1,1);
2026 char *p = skip_string(str2,1);
2027 int uLevel = SVAL(p,0);
2031 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2033 /* check it's a supported varient */
2034 if (!prefix_ok(str1,"WrLh")) return False;
2037 if (strcmp(str2,"B16") != 0) return False;
2041 if (strcmp(str2,"B16BBDz") != 0) return False;
2045 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2050 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2055 if (strcmp(str2,"DN") != 0) return False;
2059 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2062 default: return False;
2065 *rdata_len = mdrcnt;
2066 *rdata = REALLOC(*rdata,*rdata_len);
2069 p2 = p + struct_len;
2071 StrnCpy(p,local_machine,16);
2077 struct srv_info_struct *servers=NULL;
2080 uint32 servertype= lp_default_server_announce();
2082 pstrcpy(comment,lp_serverstring());
2084 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2085 for (i=0;i<count;i++)
2086 if (strequal(servers[i].name,local_machine))
2088 servertype = servers[i].type;
2089 pstrcpy(comment,servers[i].comment);
2092 if (servers) free(servers);
2094 SCVAL(p,0,lp_major_announce_version());
2095 SCVAL(p,1,lp_minor_announce_version());
2096 SIVAL(p,2,servertype);
2098 if (mdrcnt == struct_len) {
2101 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2102 standard_sub(conn,comment);
2103 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2104 p2 = skip_string(p2,1);
2109 return False; /* not yet implemented */
2112 *rdata_len = PTR_DIFF(p2,*rdata);
2115 *rparam = REALLOC(*rparam,*rparam_len);
2116 SSVAL(*rparam,0,NERR_Success);
2117 SSVAL(*rparam,2,0); /* converter word */
2118 SSVAL(*rparam,4,*rdata_len);
2124 /****************************************************************************
2125 get info about the server
2126 ****************************************************************************/
2127 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2128 int mdrcnt,int mprcnt,
2129 char **rdata,char **rparam,
2130 int *rdata_len,int *rparam_len)
2132 char *str1 = param+2;
2133 char *str2 = skip_string(str1,1);
2134 char *p = skip_string(str2,1);
2136 extern pstring sesssetup_user;
2137 int level = SVAL(p,0);
2139 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2142 *rparam = REALLOC(*rparam,*rparam_len);
2144 /* check it's a supported varient */
2145 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2148 *rdata_len = mdrcnt + 1024;
2149 *rdata = REALLOC(*rdata,*rdata_len);
2151 SSVAL(*rparam,0,NERR_Success);
2152 SSVAL(*rparam,2,0); /* converter word */
2158 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2159 pstrcpy(p2,local_machine);
2161 p2 = skip_string(p2,1);
2164 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2165 pstrcpy(p2,sesssetup_user);
2166 p2 = skip_string(p2,1);
2169 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2170 pstrcpy(p2,global_myworkgroup);
2172 p2 = skip_string(p2,1);
2175 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2176 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2179 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2180 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2181 p2 = skip_string(p2,1);
2184 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2186 p2 = skip_string(p2,1);
2189 *rdata_len = PTR_DIFF(p2,*rdata);
2191 SSVAL(*rparam,4,*rdata_len);
2196 /****************************************************************************
2197 get info about a user
2199 struct user_info_11 {
2200 char usri11_name[21]; 0-20
2202 char *usri11_comment; 22-25
2203 char *usri11_usr_comment; 26-29
2204 unsigned short usri11_priv; 30-31
2205 unsigned long usri11_auth_flags; 32-35
2206 long usri11_password_age; 36-39
2207 char *usri11_homedir; 40-43
2208 char *usri11_parms; 44-47
2209 long usri11_last_logon; 48-51
2210 long usri11_last_logoff; 52-55
2211 unsigned short usri11_bad_pw_count; 56-57
2212 unsigned short usri11_num_logons; 58-59
2213 char *usri11_logon_server; 60-63
2214 unsigned short usri11_country_code; 64-65
2215 char *usri11_workstations; 66-69
2216 unsigned long usri11_max_storage; 70-73
2217 unsigned short usri11_units_per_week; 74-75
2218 unsigned char *usri11_logon_hours; 76-79
2219 unsigned short usri11_code_page; 80-81
2224 usri11_name specifies the user name for which information is retireved
2226 usri11_pad aligns the next data structure element to a word boundary
2228 usri11_comment is a null terminated ASCII comment
2230 usri11_user_comment is a null terminated ASCII comment about the user
2232 usri11_priv specifies the level of the privilege assigned to the user.
2233 The possible values are:
2235 Name Value Description
2236 USER_PRIV_GUEST 0 Guest privilege
2237 USER_PRIV_USER 1 User privilege
2238 USER_PRV_ADMIN 2 Administrator privilege
2240 usri11_auth_flags specifies the account operator privileges. The
2241 possible values are:
2243 Name Value Description
2244 AF_OP_PRINT 0 Print operator
2247 Leach, Naik [Page 28]
\r\f
2250 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2253 AF_OP_COMM 1 Communications operator
2254 AF_OP_SERVER 2 Server operator
2255 AF_OP_ACCOUNTS 3 Accounts operator
2258 usri11_password_age specifies how many seconds have elapsed since the
2259 password was last changed.
2261 usri11_home_dir points to a null terminated ASCII string that contains
2262 the path name of the user's home directory.
2264 usri11_parms points to a null terminated ASCII string that is set
2265 aside for use by applications.
2267 usri11_last_logon specifies the time when the user last logged on.
2268 This value is stored as the number of seconds elapsed since
2269 00:00:00, January 1, 1970.
2271 usri11_last_logoff specifies the time when the user last logged off.
2272 This value is stored as the number of seconds elapsed since
2273 00:00:00, January 1, 1970. A value of 0 means the last logoff
2276 usri11_bad_pw_count specifies the number of incorrect passwords
2277 entered since the last successful logon.
2279 usri11_log1_num_logons specifies the number of times this user has
2280 logged on. A value of -1 means the number of logons is unknown.
2282 usri11_logon_server points to a null terminated ASCII string that
2283 contains the name of the server to which logon requests are sent.
2284 A null string indicates logon requests should be sent to the
2287 usri11_country_code specifies the country code for the user's language
2290 usri11_workstations points to a null terminated ASCII string that
2291 contains the names of workstations the user may log on from.
2292 There may be up to 8 workstations, with the names separated by
2293 commas. A null strings indicates there are no restrictions.
2295 usri11_max_storage specifies the maximum amount of disk space the user
2296 can occupy. A value of 0xffffffff indicates there are no
2299 usri11_units_per_week specifies the equal number of time units into
2300 which a week is divided. This value must be equal to 168.
2302 usri11_logon_hours points to a 21 byte (168 bits) string that
2303 specifies the time during which the user can log on. Each bit
2304 represents one unique hour in a week. The first bit (bit 0, word
2305 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2309 Leach, Naik [Page 29]
\r\f
2312 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2315 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2316 are no restrictions.
2318 usri11_code_page specifies the code page for the user's language of
2321 All of the pointers in this data structure need to be treated
2322 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2323 to be ignored. The converter word returned in the parameters section
2324 needs to be subtracted from the lower 16 bits to calculate an offset
2325 into the return buffer where this ASCII string resides.
2327 There is no auxiliary data in the response.
2329 ****************************************************************************/
2331 #define usri11_name 0
2332 #define usri11_pad 21
2333 #define usri11_comment 22
2334 #define usri11_usr_comment 26
2335 #define usri11_full_name 30
2336 #define usri11_priv 34
2337 #define usri11_auth_flags 36
2338 #define usri11_password_age 40
2339 #define usri11_homedir 44
2340 #define usri11_parms 48
2341 #define usri11_last_logon 52
2342 #define usri11_last_logoff 56
2343 #define usri11_bad_pw_count 60
2344 #define usri11_num_logons 62
2345 #define usri11_logon_server 64
2346 #define usri11_country_code 68
2347 #define usri11_workstations 70
2348 #define usri11_max_storage 74
2349 #define usri11_units_per_week 78
2350 #define usri11_logon_hours 80
2351 #define usri11_code_page 84
2352 #define usri11_end 86
2354 #define USER_PRIV_GUEST 0
2355 #define USER_PRIV_USER 1
2356 #define USER_PRIV_ADMIN 2
2358 #define AF_OP_PRINT 0
2359 #define AF_OP_COMM 1
2360 #define AF_OP_SERVER 2
2361 #define AF_OP_ACCOUNTS 3
2364 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2365 int mdrcnt,int mprcnt,
2366 char **rdata,char **rparam,
2367 int *rdata_len,int *rparam_len)
2369 char *str1 = param+2;
2370 char *str2 = skip_string(str1,1);
2371 char *UserName = skip_string(str2,1);
2372 char *p = skip_string(UserName,1);
2373 int uLevel = SVAL(p,0);
2376 /* get NIS home of a previously validated user - simeon */
2377 /* With share level security vuid will always be zero.
2378 Don't depend on vuser being non-null !!. JRA */
2379 user_struct *vuser = get_valid_user_struct(vuid);
2381 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2384 *rparam = REALLOC(*rparam,*rparam_len);
2386 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2388 /* check it's a supported variant */
2389 if (strcmp(str1,"zWrLh") != 0) return False;
2392 case 0: p2 = "B21"; break;
2393 case 1: p2 = "B21BB16DWzzWz"; break;
2394 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2395 case 10: p2 = "B21Bzzz"; break;
2396 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2397 default: return False;
2400 if (strcmp(p2,str2) != 0) return False;
2402 *rdata_len = mdrcnt + 1024;
2403 *rdata = REALLOC(*rdata,*rdata_len);
2405 SSVAL(*rparam,0,NERR_Success);
2406 SSVAL(*rparam,2,0); /* converter word */
2409 p2 = p + usri11_end;
2412 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2416 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2421 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2422 pstrcpy(p2,"Comment");
2423 p2 = skip_string(p2,1);
2425 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2426 pstrcpy(p2,"UserComment");
2427 p2 = skip_string(p2,1);
2429 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2430 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2431 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2432 p2 = skip_string(p2,1);
2435 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2437 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2438 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2439 SIVALS(p,usri11_password_age,-1); /* password age */
2440 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2441 pstrcpy(p2, lp_logon_path());
2442 p2 = skip_string(p2,1);
2443 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2445 p2 = skip_string(p2,1);
2446 SIVAL(p,usri11_last_logon,0); /* last logon */
2447 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2448 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2449 SSVALS(p,usri11_num_logons,-1); /* num logons */
2450 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2451 pstrcpy(p2,"\\\\*");
2452 p2 = skip_string(p2,1);
2453 SSVAL(p,usri11_country_code,0); /* country code */
2455 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2457 p2 = skip_string(p2,1);
2459 SIVALS(p,usri11_max_storage,-1); /* max storage */
2460 SSVAL(p,usri11_units_per_week,168); /* units per week */
2461 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2463 /* a simple way to get logon hours at all times. */
2465 SCVAL(p2,21,0); /* fix zero termination */
2466 p2 = skip_string(p2,1);
2468 SSVAL(p,usri11_code_page,0); /* code page */
2470 if (uLevel == 1 || uLevel == 2)
2472 memset(p+22,' ',16); /* password */
2473 SIVALS(p,38,-1); /* password age */
2475 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2476 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2477 pstrcpy(p2,lp_logon_path());
2478 p2 = skip_string(p2,1);
2479 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2481 SSVAL(p,52,0); /* flags */
2482 SIVAL(p,54,0); /* script_path */
2485 SIVAL(p,60,0); /* auth_flags */
2486 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2487 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2488 p2 = skip_string(p2,1);
2489 SIVAL(p,68,0); /* urs_comment */
2490 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2492 p2 = skip_string(p2,1);
2493 SIVAL(p,76,0); /* workstations */
2494 SIVAL(p,80,0); /* last_logon */
2495 SIVAL(p,84,0); /* last_logoff */
2496 SIVALS(p,88,-1); /* acct_expires */
2497 SIVALS(p,92,-1); /* max_storage */
2498 SSVAL(p,96,168); /* units_per_week */
2499 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2502 SSVALS(p,102,-1); /* bad_pw_count */
2503 SSVALS(p,104,-1); /* num_logons */
2504 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2505 pstrcpy(p2,"\\\\%L");
2506 standard_sub_basic(p2);
2507 p2 = skip_string(p2,1);
2508 SSVAL(p,110,49); /* country_code */
2509 SSVAL(p,112,860); /* code page */
2513 *rdata_len = PTR_DIFF(p2,*rdata);
2515 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2520 /*******************************************************************
2521 get groups that a user is a member of
2522 ******************************************************************/
2523 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2524 int mdrcnt,int mprcnt,
2525 char **rdata,char **rparam,
2526 int *rdata_len,int *rparam_len)
2528 char *str1 = param+2;
2529 char *str2 = skip_string(str1,1);
2530 char *UserName = skip_string(str2,1);
2531 char *p = skip_string(UserName,1);
2532 int uLevel = SVAL(p,0);
2537 *rparam = REALLOC(*rparam,*rparam_len);
2539 /* check it's a supported varient */
2540 if (strcmp(str1,"zWrLeh") != 0) return False;
2542 case 0: p2 = "B21"; break;
2543 default: return False;
2545 if (strcmp(p2,str2) != 0) return False;
2547 *rdata_len = mdrcnt + 1024;
2548 *rdata = REALLOC(*rdata,*rdata_len);
2550 SSVAL(*rparam,0,NERR_Success);
2551 SSVAL(*rparam,2,0); /* converter word */
2555 /* XXXX we need a real SAM database some day */
2556 pstrcpy(p,"Users"); p += 21; count++;
2557 pstrcpy(p,"Domain Users"); p += 21; count++;
2558 pstrcpy(p,"Guests"); p += 21; count++;
2559 pstrcpy(p,"Domain Guests"); p += 21; count++;
2561 *rdata_len = PTR_DIFF(p,*rdata);
2563 SSVAL(*rparam,4,count); /* is this right?? */
2564 SSVAL(*rparam,6,count); /* is this right?? */
2570 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2571 int mdrcnt,int mprcnt,
2572 char **rdata,char **rparam,
2573 int *rdata_len,int *rparam_len)
2575 char *str1 = param+2;
2576 char *str2 = skip_string(str1,1);
2577 char *p = skip_string(str2,1);
2579 struct pack_desc desc;
2586 bzero(&desc,sizeof(desc));
2588 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2590 /* check it's a supported varient */
2591 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2592 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2593 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2595 desc.buflen = mdrcnt;
2596 desc.subformat = NULL;
2599 if (init_package(&desc,1,0))
2601 PACKI(&desc,"W",0); /* code */
2602 PACKS(&desc,"B21",name); /* eff. name */
2603 PACKS(&desc,"B",""); /* pad */
2605 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2606 PACKI(&desc,"D",0); /* auth flags XXX */
2607 PACKI(&desc,"W",0); /* num logons */
2608 PACKI(&desc,"W",0); /* bad pw count */
2609 PACKI(&desc,"D",0); /* last logon */
2610 PACKI(&desc,"D",-1); /* last logoff */
2611 PACKI(&desc,"D",-1); /* logoff time */
2612 PACKI(&desc,"D",-1); /* kickoff time */
2613 PACKI(&desc,"D",0); /* password age */
2614 PACKI(&desc,"D",0); /* password can change */
2615 PACKI(&desc,"D",-1); /* password must change */
2618 fstrcpy(mypath,"\\\\");
2619 fstrcat(mypath,local_machine);
2621 PACKS(&desc,"z",mypath); /* computer */
2623 PACKS(&desc,"z",global_myworkgroup);/* domain */
2625 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2626 /* made sure all macros are fully substituted and available */
2627 logon_script = lp_logon_script();
2628 standard_sub( conn, logon_script );
2629 PACKS(&desc,"z", logon_script); /* script path */
2630 /* End of JHT mods */
2632 PACKI(&desc,"D",0x00000000); /* reserved */
2635 *rdata_len = desc.usedlen;
2637 *rparam = REALLOC(*rparam,*rparam_len);
2638 SSVALS(*rparam,0,desc.errcode);
2640 SSVAL(*rparam,4,desc.neededlen);
2642 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2647 /****************************************************************************
2648 api_WAccessGetUserPerms
2649 ****************************************************************************/
2650 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2651 int mdrcnt,int mprcnt,
2652 char **rdata,char **rparam,
2653 int *rdata_len,int *rparam_len)
2655 char *str1 = param+2;
2656 char *str2 = skip_string(str1,1);
2657 char *user = skip_string(str2,1);
2658 char *resource = skip_string(user,1);
2660 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2662 /* check it's a supported varient */
2663 if (strcmp(str1,"zzh") != 0) return False;
2664 if (strcmp(str2,"") != 0) return False;
2667 *rparam = REALLOC(*rparam,*rparam_len);
2668 SSVALS(*rparam,0,0); /* errorcode */
2669 SSVAL(*rparam,2,0); /* converter word */
2670 SSVAL(*rparam,4,0x7f); /* permission flags */
2675 /****************************************************************************
2676 api_WPrintJobEnumerate
2677 ****************************************************************************/
2678 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2679 int mdrcnt,int mprcnt,
2680 char **rdata,char **rparam,
2681 int *rdata_len,int *rparam_len)
2683 char *str1 = param+2;
2684 char *str2 = skip_string(str1,1);
2685 char *p = skip_string(str2,1);
2691 struct pack_desc desc;
2692 print_queue_struct *queue=NULL;
2693 print_status_struct status;
2698 bzero(&desc,sizeof(desc));
2699 bzero(&status,sizeof(status));
2701 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2703 /* check it's a supported varient */
2704 if (strcmp(str1,"WWrLh") != 0) return False;
2705 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2707 printjob_decode(SVAL(p,0), &snum, &job);
2709 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2711 count = get_printqueue(snum,conn,&queue,&status);
2712 for (i = 0; i < count; i++) {
2713 if ((queue[i].job & 0xFF) == job) break;
2715 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2717 desc.buflen = mdrcnt;
2719 if (init_package(&desc,1,0)) {
2721 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2722 *rdata_len = desc.usedlen;
2725 desc.errcode = NERR_JobNotFound;
2731 *rparam = REALLOC(*rparam,*rparam_len);
2732 SSVALS(*rparam,0,desc.errcode);
2734 SSVAL(*rparam,4,desc.neededlen);
2736 if (queue) free(queue);
2738 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2742 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2743 int mdrcnt,int mprcnt,
2744 char **rdata,char **rparam,
2745 int *rdata_len,int *rparam_len)
2747 char *str1 = param+2;
2748 char *str2 = skip_string(str1,1);
2749 char *p = skip_string(str2,1);
2755 struct pack_desc desc;
2756 print_queue_struct *queue=NULL;
2757 print_status_struct status;
2759 bzero(&desc,sizeof(desc));
2760 bzero(&status,sizeof(status));
2762 p = skip_string(p,1);
2766 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2768 /* check it's a supported varient */
2769 if (strcmp(str1,"zWrLeh") != 0) return False;
2770 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2771 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2773 snum = lp_servicenumber(name);
2774 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2775 int pnum = lp_servicenumber(PRINTERS_NAME);
2777 lp_add_printer(name,pnum);
2778 snum = lp_servicenumber(name);
2782 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2784 count = get_printqueue(snum,conn,&queue,&status);
2785 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2787 desc.buflen = mdrcnt;
2789 if (init_package(&desc,count,0)) {
2791 for (i = 0; i < count; i++) {
2792 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2793 if (desc.errcode == NERR_Success) succnt = i+1;
2797 *rdata_len = desc.usedlen;
2800 *rparam = REALLOC(*rparam,*rparam_len);
2801 SSVALS(*rparam,0,desc.errcode);
2803 SSVAL(*rparam,4,succnt);
2804 SSVAL(*rparam,6,count);
2806 if (queue) free(queue);
2808 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2812 static int check_printdest_info(struct pack_desc* desc,
2813 int uLevel, char* id)
2815 desc->subformat = NULL;
2817 case 0: desc->format = "B9"; break;
2818 case 1: desc->format = "B9B21WWzW"; break;
2819 case 2: desc->format = "z"; break;
2820 case 3: desc->format = "zzzWWzzzWW"; break;
2821 default: return False;
2823 if (strcmp(desc->format,id) != 0) return False;
2827 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2828 struct pack_desc* desc)
2831 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2832 buf[sizeof(buf)-1] = 0;
2835 PACKS(desc,"B9",buf); /* szName */
2837 PACKS(desc,"B21",""); /* szUserName */
2838 PACKI(desc,"W",0); /* uJobId */
2839 PACKI(desc,"W",0); /* fsStatus */
2840 PACKS(desc,"z",""); /* pszStatus */
2841 PACKI(desc,"W",0); /* time */
2844 if (uLevel == 2 || uLevel == 3) {
2845 PACKS(desc,"z",buf); /* pszPrinterName */
2847 PACKS(desc,"z",""); /* pszUserName */
2848 PACKS(desc,"z",""); /* pszLogAddr */
2849 PACKI(desc,"W",0); /* uJobId */
2850 PACKI(desc,"W",0); /* fsStatus */
2851 PACKS(desc,"z",""); /* pszStatus */
2852 PACKS(desc,"z",""); /* pszComment */
2853 PACKS(desc,"z","NULL"); /* pszDrivers */
2854 PACKI(desc,"W",0); /* time */
2855 PACKI(desc,"W",0); /* pad1 */
2860 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2861 int mdrcnt,int mprcnt,
2862 char **rdata,char **rparam,
2863 int *rdata_len,int *rparam_len)
2865 char *str1 = param+2;
2866 char *str2 = skip_string(str1,1);
2867 char *p = skip_string(str2,1);
2868 char* PrinterName = p;
2870 struct pack_desc desc;
2873 bzero(&desc,sizeof(desc));
2875 p = skip_string(p,1);
2879 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2881 /* check it's a supported varient */
2882 if (strcmp(str1,"zWrLh") != 0) return False;
2883 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2885 snum = lp_servicenumber(PrinterName);
2886 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2887 int pnum = lp_servicenumber(PRINTERS_NAME);
2889 lp_add_printer(PrinterName,pnum);
2890 snum = lp_servicenumber(PrinterName);
2896 desc.errcode = NERR_DestNotFound;
2900 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2902 desc.buflen = mdrcnt;
2903 if (init_package(&desc,1,0)) {
2904 fill_printdest_info(conn,snum,uLevel,&desc);
2906 *rdata_len = desc.usedlen;
2910 *rparam = REALLOC(*rparam,*rparam_len);
2911 SSVALS(*rparam,0,desc.errcode);
2913 SSVAL(*rparam,4,desc.neededlen);
2915 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2919 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2920 int mdrcnt,int mprcnt,
2921 char **rdata,char **rparam,
2922 int *rdata_len,int *rparam_len)
2924 char *str1 = param+2;
2925 char *str2 = skip_string(str1,1);
2926 char *p = skip_string(str2,1);
2930 struct pack_desc desc;
2931 int services = lp_numservices();
2933 bzero(&desc,sizeof(desc));
2938 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2940 /* check it's a supported varient */
2941 if (strcmp(str1,"WrLeh") != 0) return False;
2942 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2945 for (i = 0; i < services; i++)
2946 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2949 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2951 desc.buflen = mdrcnt;
2952 if (init_package(&desc,queuecnt,0)) {
2955 for (i = 0; i < services; i++) {
2956 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2957 fill_printdest_info(conn,i,uLevel,&desc);
2959 if (desc.errcode == NERR_Success) succnt = n;
2964 *rdata_len = desc.usedlen;
2967 *rparam = REALLOC(*rparam,*rparam_len);
2968 SSVALS(*rparam,0,desc.errcode);
2970 SSVAL(*rparam,4,succnt);
2971 SSVAL(*rparam,6,queuecnt);
2973 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2977 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2978 int mdrcnt,int mprcnt,
2979 char **rdata,char **rparam,
2980 int *rdata_len,int *rparam_len)
2982 char *str1 = param+2;
2983 char *str2 = skip_string(str1,1);
2984 char *p = skip_string(str2,1);
2987 struct pack_desc desc;
2989 bzero(&desc,sizeof(desc));
2994 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2996 /* check it's a supported varient */
2997 if (strcmp(str1,"WrLeh") != 0) return False;
2998 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3000 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3002 desc.buflen = mdrcnt;
3003 if (init_package(&desc,1,0)) {
3004 PACKS(&desc,"B41","NULL");
3007 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3009 *rdata_len = desc.usedlen;
3012 *rparam = REALLOC(*rparam,*rparam_len);
3013 SSVALS(*rparam,0,desc.errcode);
3015 SSVAL(*rparam,4,succnt);
3018 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3022 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3023 int mdrcnt,int mprcnt,
3024 char **rdata,char **rparam,
3025 int *rdata_len,int *rparam_len)
3027 char *str1 = param+2;
3028 char *str2 = skip_string(str1,1);
3029 char *p = skip_string(str2,1);
3032 struct pack_desc desc;
3034 bzero(&desc,sizeof(desc));
3039 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3041 /* check it's a supported varient */
3042 if (strcmp(str1,"WrLeh") != 0) return False;
3043 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3045 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3047 desc.buflen = mdrcnt;
3049 if (init_package(&desc,1,0)) {
3050 PACKS(&desc,"B13","lpd");
3053 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3055 *rdata_len = desc.usedlen;
3058 *rparam = REALLOC(*rparam,*rparam_len);
3059 SSVALS(*rparam,0,desc.errcode);
3061 SSVAL(*rparam,4,succnt);
3064 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3068 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3069 int mdrcnt,int mprcnt,
3070 char **rdata,char **rparam,
3071 int *rdata_len,int *rparam_len)
3073 char *str1 = param+2;
3074 char *str2 = skip_string(str1,1);
3075 char *p = skip_string(str2,1);
3078 struct pack_desc desc;
3080 bzero(&desc,sizeof(desc));
3085 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3087 /* check it's a supported varient */
3088 if (strcmp(str1,"WrLeh") != 0) return False;
3089 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3091 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3092 bzero(&desc,sizeof(desc));
3094 desc.buflen = mdrcnt;
3096 if (init_package(&desc,1,0)) {
3097 PACKS(&desc,"B13","lp0");
3100 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3102 *rdata_len = desc.usedlen;
3105 *rparam = REALLOC(*rparam,*rparam_len);
3106 SSVALS(*rparam,0,desc.errcode);
3108 SSVAL(*rparam,4,succnt);
3111 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3117 char * pipe_clnt_name;
3118 char * pipe_srv_name;
3119 BOOL (*fn) (pipes_struct *, prs_struct *);
3122 static struct api_cmd api_fd_commands[] =
3124 { "lsarpc", "lsass", api_ntlsa_rpc },
3125 { "samr", "lsass", api_samr_rpc },
3126 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3127 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3128 { "NETLOGON", "lsass", api_netlog_rpc },
3129 { "winreg", "winreg", api_reg_rpc },
3130 { NULL, NULL, NULL }
3133 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3135 BOOL ntlmssp_auth = False;
3136 fstring ack_pipe_name;
3139 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3141 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3143 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3144 api_fd_commands[i].fn != NULL)
3146 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3147 api_fd_commands[i].pipe_clnt_name,
3148 api_fd_commands[i].pipe_srv_name));
3149 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3154 if (api_fd_commands[i].fn == NULL) return False;
3156 /* decode the bind request */
3157 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3159 if (pd->offset == 0) return False;
3161 if (p->hdr.auth_len != 0)
3163 /* decode the authentication verifier */
3164 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3166 if (pd->offset == 0) return False;
3168 /* ignore the version number for now */
3169 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3172 /* name has to be \PIPE\xxxxx */
3173 fstrcpy(ack_pipe_name, "\\PIPE\\");
3174 fstrcat(ack_pipe_name, p->pipe_srv_name);
3176 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3178 prs_init(&(p->rdata), 1024, 4, 0, False);
3179 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3180 prs_init(&(p->rauth), 1024, 4, 0, False);
3183 /*** do the bind ack first ***/
3186 make_rpc_hdr_ba(&p->hdr_ba,
3187 p->hdr_rb.bba.max_tsize,
3188 p->hdr_rb.bba.max_rsize,
3189 p->hdr_rb.bba.assoc_gid,
3192 &(p->hdr_rb.transfer));
3194 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3195 mem_realloc_data(p->rdata.data, p->rdata.offset);
3198 /*** now the authentication ***/
3204 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3206 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3209 0x00000000, 0x0000b2b3, 0x000082b1,
3211 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3212 mem_realloc_data(p->rauth.data, p->rauth.offset);
3216 /*** then do the header, now we know the length ***/
3219 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3221 p->rdata.offset + p->rauth.offset,
3224 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3225 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3228 /*** link rpc header, bind acknowledgment and authentication responses ***/
3231 p->rhdr.data->offset.start = 0;
3232 p->rhdr.data->offset.end = p->rhdr.offset;
3233 p->rhdr.data->next = p->rdata.data;
3237 p->rdata.data->offset.start = p->rhdr.offset;
3238 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3239 p->rdata.data->next = p->rauth.data;
3241 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3242 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3243 p->rauth.data->next = NULL;
3247 p->rdata.data->offset.start = p->rhdr.offset;
3248 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3249 p->rdata.data->next = NULL;
3255 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3259 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3261 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3262 api_fd_commands[i].fn != NULL)
3264 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3265 return api_fd_commands[i].fn(p, pd);
3271 static BOOL api_dce_rpc_command(char *outbuf,
3276 if (pd->data == NULL) return False;
3278 /* process the rpc header */
3279 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3281 if (pd->offset == 0) return False;
3283 switch (p->hdr.pkt_type)
3287 reply = api_pipe_bind_req(p, pd);
3292 reply = api_pipe_request (p, pd);
3299 /* now send the reply */
3300 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3302 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3304 /* all of data was sent: no need to wait for SMBreadX calls */
3305 mem_free_data(p->rhdr .data);
3306 mem_free_data(p->rdata.data);
3313 /****************************************************************************
3314 SetNamedPipeHandleState
3315 ****************************************************************************/
3316 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3320 if (!param) return False;
3322 id = param[0] + (param[1] << 8);
3323 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3325 if (set_rpc_pipe_hnd_state(p, id))
3327 /* now send the reply */
3328 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3336 /****************************************************************************
3337 when no reply is generated, indicate unsupported.
3338 ****************************************************************************/
3339 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3341 struct mem_buf rparam;
3343 mem_init(&rparam, 0);
3344 mem_alloc_data(&rparam, 4);
3346 rparam.offset.start = 0;
3347 rparam.offset.end = 4;
3350 SSVAL(rparam.data,0,NERR_notsupported);
3351 SSVAL(rparam.data,2,0); /* converter word */
3353 DEBUG(3,("Unsupported API fd command\n"));
3355 /* now send the reply */
3356 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3358 mem_free_data(&rparam);
3363 /****************************************************************************
3364 handle remote api calls delivered to a named pipe already opened.
3365 ****************************************************************************/
3366 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3367 uint16 *setup,char *data,char *params,
3368 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3374 pipes_struct *p = NULL;
3376 struct mem_buf data_buf;
3378 DEBUG(5,("api_fd_reply\n"));
3380 /* fake up a data buffer from the api_fd_reply data parameters */
3381 mem_create(&data_buf, data, tdscnt, 0, False);
3382 data_buf.offset.start = 0;
3383 data_buf.offset.end = tdscnt;
3385 /* fake up a parsing structure */
3386 pd.data = &data_buf;
3391 /* First find out the name of this file. */
3394 DEBUG(0,("Unexpected named pipe transaction.\n"));
3398 /* Get the file handle and hence the file name. */
3400 subcommand = setup[0];
3401 p = get_rpc_pipe(pnum);
3405 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3406 subcommand, p->name, pnum));
3408 /* record maximum data length that can be transmitted in an SMBtrans */
3409 p->file_offset = mdrcnt;
3411 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3412 p, p->file_offset));
3418 /* dce/rpc command */
3419 reply = api_dce_rpc_command(outbuf, p, &pd);
3424 /* Set Named Pipe Handle state */
3425 reply = api_SNPHS(outbuf, p, params);
3432 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3437 return api_no_reply(outbuf, mdrcnt);
3442 /****************************************************************************
3443 the buffer was too small
3444 ****************************************************************************/
3445 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3446 int mdrcnt,int mprcnt,
3447 char **rdata,char **rparam,
3448 int *rdata_len,int *rparam_len)
3450 *rparam_len = MIN(*rparam_len,mprcnt);
3451 *rparam = REALLOC(*rparam,*rparam_len);
3455 SSVAL(*rparam,0,NERR_BufTooSmall);
3457 DEBUG(3,("Supplied buffer too small in API command\n"));
3463 /****************************************************************************
3464 the request is not supported
3465 ****************************************************************************/
3466 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3467 int mdrcnt,int mprcnt,
3468 char **rdata,char **rparam,
3469 int *rdata_len,int *rparam_len)
3472 *rparam = REALLOC(*rparam,*rparam_len);
3476 SSVAL(*rparam,0,NERR_notsupported);
3477 SSVAL(*rparam,2,0); /* converter word */
3479 DEBUG(3,("Unsupported API command\n"));
3491 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3492 int,int,char **,char **,int *,int *);
3494 } api_commands[] = {
3495 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3496 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3497 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3498 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3499 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3500 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3501 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3502 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3503 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3504 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3505 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3506 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3507 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3508 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3509 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3510 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3511 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3512 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3513 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3514 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3515 {"NetServerEnum", 104, api_RNetServerEnum,0},
3516 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3517 {"SetUserPassword", 115, api_SetUserPassword,0},
3518 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3519 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3520 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3521 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3522 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3523 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3524 {NULL, -1, api_Unsupported,0}};
3527 /****************************************************************************
3528 handle remote api calls
3529 ****************************************************************************/
3530 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3531 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3533 int api_command = SVAL(params,0);
3534 struct mem_buf rdata_buf;
3535 struct mem_buf rparam_buf;
3537 char *rparam = NULL;
3543 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3544 api_command,params+2,skip_string(params+2,1),
3545 tdscnt,tpscnt,mdrcnt,mprcnt));
3547 for (i=0;api_commands[i].name;i++)
3548 if (api_commands[i].id == api_command && api_commands[i].fn)
3550 DEBUG(3,("Doing %s\n",api_commands[i].name));
3554 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3555 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3557 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3558 &rdata,&rparam,&rdata_len,&rparam_len);
3561 if (rdata_len > mdrcnt ||
3562 rparam_len > mprcnt)
3564 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3565 &rdata,&rparam,&rdata_len,&rparam_len);
3569 /* if we get False back then it's actually unsupported */
3571 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3572 &rdata,&rparam,&rdata_len,&rparam_len);
3575 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3576 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3578 rdata_buf.offset.start = 0;
3579 rdata_buf.offset.end = rdata_len;
3581 rparam_buf.offset.start = 0;
3582 rparam_buf.offset.end = rparam_len;
3584 /* now send the reply */
3585 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3587 if (rdata ) free(rdata);
3588 if (rparam) free(rparam);
3593 /****************************************************************************
3594 handle named pipe commands
3595 ****************************************************************************/
3596 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3597 uint16 *setup,char *data,char *params,
3598 int suwcnt,int tdscnt,int tpscnt,
3599 int msrcnt,int mdrcnt,int mprcnt)
3601 DEBUG(3,("named pipe command on <%s> name\n", name));
3603 if (strequal(name,"LANMAN"))
3605 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3608 if (strlen(name) < 1)
3610 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3615 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3622 /****************************************************************************
3624 ****************************************************************************/
3625 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3629 char *data=NULL,*params=NULL;
3632 uint16 vuid = SVAL(inbuf,smb_uid);
3633 int tpscnt = SVAL(inbuf,smb_vwv0);
3634 int tdscnt = SVAL(inbuf,smb_vwv1);
3635 int mprcnt = SVAL(inbuf,smb_vwv2);
3636 int mdrcnt = SVAL(inbuf,smb_vwv3);
3637 int msrcnt = CVAL(inbuf,smb_vwv4);
3638 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3639 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3640 int pscnt = SVAL(inbuf,smb_vwv9);
3641 int psoff = SVAL(inbuf,smb_vwv10);
3642 int dscnt = SVAL(inbuf,smb_vwv11);
3643 int dsoff = SVAL(inbuf,smb_vwv12);
3644 int suwcnt = CVAL(inbuf,smb_vwv13);
3646 bzero(name, sizeof(name));
3647 fstrcpy(name,smb_buf(inbuf));
3649 if (dscnt > tdscnt || pscnt > tpscnt) {
3650 exit_server("invalid trans parameters\n");
3654 data = (char *)malloc(tdscnt);
3655 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3659 params = (char *)malloc(tpscnt);
3660 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3665 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3666 for (i=0;i<suwcnt;i++)
3667 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3671 if (pscnt < tpscnt || dscnt < tdscnt) {
3672 /* We need to send an interim response then receive the rest
3673 of the parameter/data bytes */
3674 outsize = set_message(outbuf,0,0,True);
3676 send_smb(Client,outbuf);
3679 /* receive the rest of the trans packet */
3680 while (pscnt < tpscnt || dscnt < tdscnt) {
3682 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3684 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3686 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3688 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3690 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3691 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3693 if (params) free(params);
3694 if (data) free(data);
3695 if (setup) free(setup);
3696 return(ERROR(ERRSRV,ERRerror));
3701 tpscnt = SVAL(inbuf,smb_vwv0);
3702 tdscnt = SVAL(inbuf,smb_vwv1);
3704 pcnt = SVAL(inbuf,smb_vwv2);
3705 poff = SVAL(inbuf,smb_vwv3);
3706 pdisp = SVAL(inbuf,smb_vwv4);
3708 dcnt = SVAL(inbuf,smb_vwv5);
3709 doff = SVAL(inbuf,smb_vwv6);
3710 ddisp = SVAL(inbuf,smb_vwv7);
3715 if (dscnt > tdscnt || pscnt > tpscnt) {
3716 exit_server("invalid trans parameters\n");
3720 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3722 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3726 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3727 name,tdscnt,tpscnt,suwcnt));
3729 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3730 DEBUG(5,("calling named_pipe\n"));
3731 outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3732 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3734 DEBUG(3,("invalid pipe name\n"));
3739 if (data) free(data);
3740 if (params) free(params);
3741 if (setup) free(setup);
3743 if (close_on_completion)
3744 close_cnum(conn,vuid);
3750 return(ERROR(ERRSRV,ERRnosupport));