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);
838 count = get_printerdrivernumber(snum);
839 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
841 count = get_printqueue(SNUM(conn), conn,&queue,&status);
844 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
846 desc.buflen = mdrcnt;
847 if (init_package(&desc,1,count)) {
848 desc.subcount = count;
849 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
852 *rdata_len = desc.usedlen;
855 *rparam = REALLOC(*rparam,*rparam_len);
856 SSVALS(*rparam,0,desc.errcode);
858 SSVAL(*rparam,4,desc.neededlen);
860 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
862 if (queue) free(queue);
868 /****************************************************************************
869 view list of all print jobs on all queues
870 ****************************************************************************/
871 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
872 int mdrcnt, int mprcnt,
873 char **rdata, char** rparam,
874 int *rdata_len, int *rparam_len)
876 char *param_format = param+2;
877 char *output_format1 = skip_string(param_format,1);
878 char *p = skip_string(output_format1,1);
879 int uLevel = SVAL(p,0);
880 char *output_format2 = p + 4;
881 int services = lp_numservices();
883 struct pack_desc desc;
884 print_queue_struct **queue = NULL;
885 print_status_struct *status = NULL;
886 int* subcntarr = NULL;
887 int queuecnt, subcnt=0, succnt=0;
889 bzero(&desc,sizeof(desc));
891 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
893 if (!prefix_ok(param_format,"WrLeh")) return False;
894 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
897 for (i = 0; i < services; i++)
898 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
901 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
902 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
903 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
904 memset(status,0,queuecnt*sizeof(print_status_struct));
905 subcntarr = (int*)malloc(queuecnt*sizeof(int));
908 for (i = 0; i < services; i++)
909 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
910 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
911 subcnt += subcntarr[n];
915 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
917 desc.buflen = mdrcnt;
919 if (init_package(&desc,queuecnt,subcnt)) {
922 for (i = 0; i < services; i++)
923 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
924 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
926 if (desc.errcode == NERR_Success) succnt = n;
930 if (subcntarr) free(subcntarr);
932 *rdata_len = desc.usedlen;
934 *rparam = REALLOC(*rparam,*rparam_len);
935 SSVALS(*rparam,0,desc.errcode);
937 SSVAL(*rparam,4,succnt);
938 SSVAL(*rparam,6,queuecnt);
940 for (i = 0; i < queuecnt; i++) {
941 if (queue && queue[i]) free(queue[i]);
944 if (queue) free(queue);
945 if (status) free(status);
950 /****************************************************************************
951 get info level for a server list query
952 ****************************************************************************/
953 static BOOL check_server_info(int uLevel, char* id)
957 if (strcmp(id,"B16") != 0) return False;
960 if (strcmp(id,"B16BBDz") != 0) return False;
968 struct srv_info_struct
978 /*******************************************************************
979 get server info lists from the files saved by nmbd. Return the
981 ******************************************************************/
982 static int get_server_info(uint32 servertype,
983 struct srv_info_struct **servers,
991 BOOL local_list_only;
993 pstrcpy(fname,lp_lockdir());
994 trim_string(fname,NULL,"/");
996 pstrcat(fname,SERVER_LIST);
998 f = fopen(fname,"r");
1001 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1005 /* request for everything is code for request all servers */
1006 if (servertype == SV_TYPE_ALL)
1007 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1009 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1011 DEBUG(4,("Servertype search: %8x\n",servertype));
1016 struct srv_info_struct *s;
1021 fgets(line,sizeof(line)-1,f);
1022 if (!*line) continue;
1024 if (count == alloced) {
1026 (*servers) = (struct srv_info_struct *)
1027 Realloc(*servers,sizeof(**servers)*alloced);
1028 if (!(*servers)) return(0);
1029 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1031 s = &(*servers)[count];
1033 if (!next_token(&ptr,s->name , NULL)) continue;
1034 if (!next_token(&ptr,stype , NULL)) continue;
1035 if (!next_token(&ptr,s->comment, NULL)) continue;
1036 if (!next_token(&ptr,s->domain , NULL)) {
1037 /* this allows us to cope with an old nmbd */
1038 pstrcpy(s->domain,global_myworkgroup);
1041 if (sscanf(stype,"%X",&s->type) != 1) {
1042 DEBUG(4,("r:host file "));
1046 /* Filter the servers/domains we return based on what was asked for. */
1048 /* Check to see if we are being asked for a local list only. */
1049 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1050 DEBUG(4,("r: local list only"));
1054 /* doesn't match up: don't want it */
1055 if (!(servertype & s->type)) {
1056 DEBUG(4,("r:serv type "));
1060 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1061 (s->type & SV_TYPE_DOMAIN_ENUM))
1063 DEBUG(4,("s: dom mismatch "));
1067 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1072 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1073 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1077 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1078 s->name, s->type, s->comment, s->domain));
1080 s->server_added = True;
1085 DEBUG(4,("%20s %8x %25s %15s\n",
1086 s->name, s->type, s->comment, s->domain));
1095 /*******************************************************************
1096 fill in a server info structure
1097 ******************************************************************/
1098 static int fill_srv_info(struct srv_info_struct *service,
1099 int uLevel, char **buf, int *buflen,
1100 char **stringbuf, int *stringspace, char *baseaddr)
1109 case 0: struct_len = 16; break;
1110 case 1: struct_len = 26; break;
1120 len = strlen(service->comment)+1;
1124 if (buflen) *buflen = struct_len;
1125 if (stringspace) *stringspace = len;
1126 return struct_len + len;
1131 if (*buflen < struct_len) return -1;
1139 p2 = p + struct_len;
1140 l2 = *buflen - struct_len;
1142 if (!baseaddr) baseaddr = p;
1147 StrnCpy(p,service->name,15);
1151 StrnCpy(p,service->name,15);
1152 SIVAL(p,18,service->type);
1153 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1154 len += CopyAndAdvance(&p2,service->comment,&l2);
1160 *buf = p + struct_len;
1161 *buflen -= struct_len;
1174 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1176 return(strcmp(s1->name,s2->name));
1179 /****************************************************************************
1180 view list of servers available (or possibly domains). The info is
1181 extracted from lists saved by nmbd on the local host
1182 ****************************************************************************/
1183 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1184 int mdrcnt, int mprcnt, char **rdata,
1185 char **rparam, int *rdata_len, int *rparam_len)
1187 char *str1 = param+2;
1188 char *str2 = skip_string(str1,1);
1189 char *p = skip_string(str2,1);
1190 int uLevel = SVAL(p,0);
1191 int buf_len = SVAL(p,2);
1192 uint32 servertype = IVAL(p,4);
1194 int data_len, fixed_len, string_len;
1195 int f_len = 0, s_len = 0;
1196 struct srv_info_struct *servers=NULL;
1197 int counted=0,total=0;
1200 BOOL domain_request;
1203 /* If someone sets all the bits they don't really mean to set
1204 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1207 if (servertype == SV_TYPE_ALL)
1208 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1210 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1211 any other bit (they may just set this bit on it's own) they
1212 want all the locally seen servers. However this bit can be
1213 set on its own so set the requested servers to be
1214 ALL - DOMAIN_ENUM. */
1216 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1217 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1219 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1220 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1224 if (!prefix_ok(str1,"WrLehD")) return False;
1225 if (!check_server_info(uLevel,str2)) return False;
1227 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1228 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1229 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1231 if (strcmp(str1, "WrLehDz") == 0) {
1232 StrnCpy(domain, p, sizeof(fstring)-1);
1234 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1237 if (lp_browse_list())
1238 total = get_server_info(servertype,&servers,domain);
1240 data_len = fixed_len = string_len = 0;
1243 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1246 char *lastname=NULL;
1248 for (i=0;i<total;i++)
1250 struct srv_info_struct *s = &servers[i];
1251 if (lastname && strequal(lastname,s->name)) continue;
1253 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1254 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1255 s->name, s->type, s->comment, s->domain));
1257 if (data_len <= buf_len) {
1260 string_len += s_len;
1267 *rdata_len = fixed_len + string_len;
1268 *rdata = REALLOC(*rdata,*rdata_len);
1269 bzero(*rdata,*rdata_len);
1271 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1277 char *lastname=NULL;
1278 int count2 = counted;
1279 for (i = 0; i < total && count2;i++)
1281 struct srv_info_struct *s = &servers[i];
1282 if (lastname && strequal(lastname,s->name)) continue;
1284 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1285 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1286 s->name, s->type, s->comment, s->domain));
1292 *rparam = REALLOC(*rparam,*rparam_len);
1293 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1295 SSVAL(*rparam,4,counted);
1296 SSVAL(*rparam,6,counted+missed);
1298 if (servers) free(servers);
1300 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1301 domain,uLevel,counted,counted+missed));
1306 /****************************************************************************
1307 command 0x34 - suspected of being a "Lookup Names" stub api
1308 ****************************************************************************/
1309 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1310 int mdrcnt, int mprcnt, char **rdata,
1311 char **rparam, int *rdata_len, int *rparam_len)
1313 char *str1 = param+2;
1314 char *str2 = skip_string(str1,1);
1315 char *p = skip_string(str2,1);
1316 int uLevel = SVAL(p,0);
1317 int buf_len = SVAL(p,2);
1321 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1322 str1, str2, p, uLevel, buf_len));
1324 if (!prefix_ok(str1,"zWrLeh")) return False;
1330 *rparam = REALLOC(*rparam,*rparam_len);
1332 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1334 SSVAL(*rparam,4,counted);
1335 SSVAL(*rparam,6,counted+missed);
1340 /****************************************************************************
1341 get info about a share
1342 ****************************************************************************/
1343 static BOOL check_share_info(int uLevel, char* id)
1347 if (strcmp(id,"B13") != 0) return False;
1350 if (strcmp(id,"B13BWz") != 0) return False;
1353 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1356 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1358 default: return False;
1363 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1364 char** buf, int* buflen,
1365 char** stringbuf, int* stringspace, char* baseaddr)
1374 case 0: struct_len = 13; break;
1375 case 1: struct_len = 20; break;
1376 case 2: struct_len = 40; break;
1377 case 91: struct_len = 68; break;
1385 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1386 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1387 if (buflen) *buflen = struct_len;
1388 if (stringspace) *stringspace = len;
1389 return struct_len + len;
1394 if ((*buflen) < struct_len) return -1;
1402 p2 = p + struct_len;
1403 l2 = (*buflen) - struct_len;
1405 if (!baseaddr) baseaddr = p;
1407 StrnCpy(p,lp_servicename(snum),13);
1413 type = STYPE_DISKTREE;
1414 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1415 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1416 SSVAL(p,14,type); /* device type */
1417 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1418 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1423 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1424 SSVALS(p,22,-1); /* max uses */
1425 SSVAL(p,24,1); /* current uses */
1426 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1427 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1428 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1433 memset(p+40,0,SHPWLEN+2);
1445 (*buf) = p + struct_len;
1446 (*buflen) -= struct_len;
1448 (*stringspace) = l2;
1458 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1459 int mdrcnt,int mprcnt,
1460 char **rdata,char **rparam,
1461 int *rdata_len,int *rparam_len)
1463 char *str1 = param+2;
1464 char *str2 = skip_string(str1,1);
1465 char *netname = skip_string(str2,1);
1466 char *p = skip_string(netname,1);
1467 int uLevel = SVAL(p,0);
1468 int snum = find_service(netname);
1470 if (snum < 0) return False;
1472 /* check it's a supported varient */
1473 if (!prefix_ok(str1,"zWrLh")) return False;
1474 if (!check_share_info(uLevel,str2)) return False;
1476 *rdata = REALLOC(*rdata,mdrcnt);
1478 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1479 if (*rdata_len < 0) return False;
1482 *rparam = REALLOC(*rparam,*rparam_len);
1483 SSVAL(*rparam,0,NERR_Success);
1484 SSVAL(*rparam,2,0); /* converter word */
1485 SSVAL(*rparam,4,*rdata_len);
1490 /****************************************************************************
1491 view list of shares available
1492 ****************************************************************************/
1493 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1494 int mdrcnt,int mprcnt,
1495 char **rdata,char **rparam,
1496 int *rdata_len,int *rparam_len)
1498 char *str1 = param+2;
1499 char *str2 = skip_string(str1,1);
1500 char *p = skip_string(str2,1);
1501 int uLevel = SVAL(p,0);
1502 int buf_len = SVAL(p,2);
1504 int count=lp_numservices();
1505 int total=0,counted=0;
1506 BOOL missed = False;
1508 int data_len, fixed_len, string_len;
1509 int f_len = 0, s_len = 0;
1511 if (!prefix_ok(str1,"WrLeh")) return False;
1512 if (!check_share_info(uLevel,str2)) return False;
1514 data_len = fixed_len = string_len = 0;
1515 for (i=0;i<count;i++)
1516 if (lp_browseable(i) && lp_snum_ok(i))
1519 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1520 if (data_len <= buf_len)
1524 string_len += s_len;
1529 *rdata_len = fixed_len + string_len;
1530 *rdata = REALLOC(*rdata,*rdata_len);
1531 memset(*rdata,0,*rdata_len);
1533 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1537 for (i = 0; i < count;i++)
1538 if (lp_browseable(i) && lp_snum_ok(i))
1539 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1543 *rparam = REALLOC(*rparam,*rparam_len);
1544 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1546 SSVAL(*rparam,4,counted);
1547 SSVAL(*rparam,6,total);
1549 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1550 counted,total,uLevel,
1551 buf_len,*rdata_len,mdrcnt));
1557 /****************************************************************************
1558 get the time of day info
1559 ****************************************************************************/
1560 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1561 int mdrcnt,int mprcnt,
1562 char **rdata,char **rparam,
1563 int *rdata_len,int *rparam_len)
1567 *rparam = REALLOC(*rparam,*rparam_len);
1570 *rdata = REALLOC(*rdata,*rdata_len);
1572 SSVAL(*rparam,0,NERR_Success);
1573 SSVAL(*rparam,2,0); /* converter word */
1579 time_t unixdate = time(NULL);
1581 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1582 by NT in a "net time" operation,
1583 it seems to ignore the one below */
1585 /* the client expects to get localtime, not GMT, in this bit
1586 (I think, this needs testing) */
1587 t = LocalTime(&unixdate);
1589 SIVAL(p,4,0); /* msecs ? */
1590 CVAL(p,8) = t->tm_hour;
1591 CVAL(p,9) = t->tm_min;
1592 CVAL(p,10) = t->tm_sec;
1593 CVAL(p,11) = 0; /* hundredths of seconds */
1594 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1595 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1596 CVAL(p,16) = t->tm_mday;
1597 CVAL(p,17) = t->tm_mon + 1;
1598 SSVAL(p,18,1900+t->tm_year);
1599 CVAL(p,20) = t->tm_wday;
1606 /****************************************************************************
1607 set the user password
1608 ****************************************************************************/
1609 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1610 int mdrcnt,int mprcnt,
1611 char **rdata,char **rparam,
1612 int *rdata_len,int *rparam_len)
1614 char *p = skip_string(param+2,2);
1616 fstring pass1,pass2;
1620 p = skip_string(p,1);
1623 memcpy(pass2,p+16,16);
1626 *rparam = REALLOC(*rparam,*rparam_len);
1630 SSVAL(*rparam,0,NERR_badpass);
1631 SSVAL(*rparam,2,0); /* converter word */
1633 DEBUG(3,("Set password for <%s>\n",user));
1636 * Pass the user through the NT -> unix user mapping
1640 (void)map_username(user);
1643 * Do any UNIX username case mangling.
1645 (void)Get_Pwnam( user, True);
1648 * Attempt the plaintext password change first.
1649 * Older versions of Windows seem to do this.
1652 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1653 chgpasswd(user,pass1,pass2,False))
1655 SSVAL(*rparam,0,NERR_Success);
1659 * If the plaintext change failed, attempt
1660 * the encrypted. NT will generate this
1661 * after trying the samr method.
1664 if(SVAL(*rparam,0) != NERR_Success)
1666 struct smb_passwd *sampw = NULL;
1668 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1669 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1671 SSVAL(*rparam,0,NERR_Success);
1675 bzero(pass1,sizeof(fstring));
1676 bzero(pass2,sizeof(fstring));
1681 /****************************************************************************
1682 Set the user password (SamOEM version - gets plaintext).
1683 ****************************************************************************/
1685 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1686 int mdrcnt,int mprcnt,
1687 char **rdata,char **rparam,
1688 int *rdata_len,int *rparam_len)
1692 struct smb_passwd *sampw = NULL;
1693 char *p = param + 2;
1697 *rparam = REALLOC(*rparam,*rparam_len);
1701 SSVAL(*rparam,0,NERR_badpass);
1704 * Check the parameter definition is correct.
1706 if(!strequal(param + 2, "zsT")) {
1707 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
1710 p = skip_string(p, 1);
1712 if(!strequal(p, "B516B16")) {
1713 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
1716 p = skip_string(p,1);
1719 p = skip_string(p,1);
1721 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1724 * Pass the user through the NT -> unix user mapping
1728 (void)map_username(user);
1731 * Do any UNIX username case mangling.
1733 (void)Get_Pwnam( user, True);
1735 if(check_oem_password( user, (unsigned char *)data, &sampw,
1736 new_passwd, (int)sizeof(new_passwd)) == False) {
1741 * At this point we have the new case-sensitive plaintext
1742 * password in the fstring new_passwd. If we wanted to synchronise
1743 * with UNIX passwords we would call a UNIX password changing
1744 * function here. However it would have to be done as root
1745 * as the plaintext of the old users password is not
1749 if(lp_unix_password_sync())
1750 ret = chgpasswd(user,"", new_passwd, True);
1752 if(ret && change_oem_password( sampw, new_passwd, False)) {
1753 SSVAL(*rparam,0,NERR_Success);
1759 /****************************************************************************
1762 ****************************************************************************/
1763 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1764 int mdrcnt,int mprcnt,
1765 char **rdata,char **rparam,
1766 int *rdata_len,int *rparam_len)
1768 int function = SVAL(param,0);
1769 char *str1 = param+2;
1770 char *str2 = skip_string(str1,1);
1771 char *p = skip_string(str2,1);
1775 printjob_decode(SVAL(p,0), &snum, &jobid);
1777 /* check it's a supported varient */
1778 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1782 *rparam = REALLOC(*rparam,*rparam_len);
1786 SSVAL(*rparam,0,NERR_Success);
1788 if (snum >= 0 && VALID_SNUM(snum))
1790 print_queue_struct *queue=NULL;
1792 count = get_printqueue(snum,conn,&queue,NULL);
1794 for (i=0;i<count;i++)
1795 if ((queue[i].job&0xFF) == jobid)
1798 case 81: /* delete */
1799 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1800 del_printqueue(conn,snum,queue[i].job);
1802 case 82: /* pause */
1803 case 83: /* resume */
1804 DEBUG(3,("%s queue entry %d\n",
1805 (function==82?"pausing":"resuming"),queue[i].job));
1806 status_printjob(conn,snum,queue[i].job,
1807 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1814 SSVAL(*rparam,0,NERR_JobNotFound);
1816 if (queue) free(queue);
1819 SSVAL(*rparam,2,0); /* converter word */
1824 /****************************************************************************
1825 Purge a print queue - or pause or resume it.
1826 ****************************************************************************/
1827 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1828 int mdrcnt,int mprcnt,
1829 char **rdata,char **rparam,
1830 int *rdata_len,int *rparam_len)
1832 int function = SVAL(param,0);
1833 char *str1 = param+2;
1834 char *str2 = skip_string(str1,1);
1835 char *QueueName = skip_string(str2,1);
1838 /* check it's a supported varient */
1839 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1843 *rparam = REALLOC(*rparam,*rparam_len);
1847 SSVAL(*rparam,0,NERR_Success);
1848 SSVAL(*rparam,2,0); /* converter word */
1850 snum = lp_servicenumber(QueueName);
1851 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1852 int pnum = lp_servicenumber(PRINTERS_NAME);
1854 lp_add_printer(QueueName,pnum);
1855 snum = lp_servicenumber(QueueName);
1859 if (snum >= 0 && VALID_SNUM(snum)) {
1863 case 74: /* Pause queue */
1864 case 75: /* Resume queue */
1865 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1866 DEBUG(3,("Print queue %s, queue=%s\n",
1867 (function==74?"pause":"resume"),QueueName));
1869 case 103: /* Purge */
1871 print_queue_struct *queue=NULL;
1873 count = get_printqueue(snum,conn,&queue,NULL);
1874 for (i = 0; i < count; i++)
1875 del_printqueue(conn,snum,queue[i].job);
1877 if (queue) free(queue);
1878 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1888 /****************************************************************************
1889 set the property of a print job (undocumented?)
1890 ? function = 0xb -> set name of print job
1891 ? function = 0x6 -> move print job up/down
1892 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1893 or <WWsTP> <WB21BB16B10zWWzDDz>
1894 ****************************************************************************/
1895 static int check_printjob_info(struct pack_desc* desc,
1896 int uLevel, char* id)
1898 desc->subformat = NULL;
1900 case 0: desc->format = "W"; break;
1901 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1902 case 2: desc->format = "WWzWWDDzz"; break;
1903 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1904 default: return False;
1906 if (strcmp(desc->format,id) != 0) return False;
1910 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1911 int mdrcnt,int mprcnt,
1912 char **rdata,char **rparam,
1913 int *rdata_len,int *rparam_len)
1915 struct pack_desc desc;
1916 char *str1 = param+2;
1917 char *str2 = skip_string(str1,1);
1918 char *p = skip_string(str2,1);
1920 int uLevel = SVAL(p,2);
1921 int function = SVAL(p,4); /* what is this ?? */
1926 printjob_decode(SVAL(p,0), &snum, &jobid);
1929 *rparam = REALLOC(*rparam,*rparam_len);
1933 /* check it's a supported varient */
1934 if ((strcmp(str1,"WWsTP")) ||
1935 (!check_printjob_info(&desc,uLevel,str2)))
1939 case 0x6: /* change job place in the queue,
1940 data gives the new place */
1941 if (snum >= 0 && VALID_SNUM(snum)) {
1942 print_queue_struct *queue=NULL;
1946 count = get_printqueue(snum,conn,&queue,NULL);
1947 for (i=0;i<count;i++) /* find job */
1948 if ((queue[i].job&0xFF) == jobid) break;
1951 desc.errcode=NERR_JobNotFound;
1952 if (queue) free(queue);
1954 desc.errcode=NERR_Success;
1958 int place= SVAL(data,0);
1959 /* we currently have no way of
1960 doing this. Can any unix do it? */
1961 if (i < place) /* move down */;
1962 else if (i > place ) /* move up */;
1965 desc.errcode=NERR_notsupported; /* not yet
1967 if (queue) free(queue);
1970 desc.errcode=NERR_JobNotFound;
1974 case 0xb: /* change print job name, data gives the name */
1975 /* jobid, snum should be zero */
1976 if (isalpha((int)*s)) {
1979 while (l<64 && *s) {
1980 if (issafe(*s)) name[l++] = *s;
1985 DEBUG(3,("Setting print name to %s\n",name));
1987 fsp = file_find_print();
1990 connection_struct *fconn = fsp->conn;
1993 if (!become_user(fconn,vuid) ||
1994 !become_service(fconn,True))
1997 if (sys_rename(fsp->fsp_name,name) == 0) {
1998 string_set(&fsp->fsp_name,name);
2003 desc.errcode=NERR_Success;
2006 default: /* not implemented */
2010 SSVALS(*rparam,0,desc.errcode);
2011 SSVAL(*rparam,2,0); /* converter word */
2017 /****************************************************************************
2018 get info about the server
2019 ****************************************************************************/
2020 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2021 int mdrcnt,int mprcnt,
2022 char **rdata,char **rparam,
2023 int *rdata_len,int *rparam_len)
2025 char *str1 = param+2;
2026 char *str2 = skip_string(str1,1);
2027 char *p = skip_string(str2,1);
2028 int uLevel = SVAL(p,0);
2032 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2034 /* check it's a supported varient */
2035 if (!prefix_ok(str1,"WrLh")) return False;
2038 if (strcmp(str2,"B16") != 0) return False;
2042 if (strcmp(str2,"B16BBDz") != 0) return False;
2046 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2051 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2056 if (strcmp(str2,"DN") != 0) return False;
2060 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2063 default: return False;
2066 *rdata_len = mdrcnt;
2067 *rdata = REALLOC(*rdata,*rdata_len);
2070 p2 = p + struct_len;
2072 StrnCpy(p,local_machine,16);
2078 struct srv_info_struct *servers=NULL;
2081 uint32 servertype= lp_default_server_announce();
2083 pstrcpy(comment,lp_serverstring());
2085 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2086 for (i=0;i<count;i++)
2087 if (strequal(servers[i].name,local_machine))
2089 servertype = servers[i].type;
2090 pstrcpy(comment,servers[i].comment);
2093 if (servers) free(servers);
2095 SCVAL(p,0,lp_major_announce_version());
2096 SCVAL(p,1,lp_minor_announce_version());
2097 SIVAL(p,2,servertype);
2099 if (mdrcnt == struct_len) {
2102 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2103 standard_sub(conn,comment);
2104 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2105 p2 = skip_string(p2,1);
2110 return False; /* not yet implemented */
2113 *rdata_len = PTR_DIFF(p2,*rdata);
2116 *rparam = REALLOC(*rparam,*rparam_len);
2117 SSVAL(*rparam,0,NERR_Success);
2118 SSVAL(*rparam,2,0); /* converter word */
2119 SSVAL(*rparam,4,*rdata_len);
2125 /****************************************************************************
2126 get info about the server
2127 ****************************************************************************/
2128 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2129 int mdrcnt,int mprcnt,
2130 char **rdata,char **rparam,
2131 int *rdata_len,int *rparam_len)
2133 char *str1 = param+2;
2134 char *str2 = skip_string(str1,1);
2135 char *p = skip_string(str2,1);
2137 extern pstring sesssetup_user;
2138 int level = SVAL(p,0);
2140 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2143 *rparam = REALLOC(*rparam,*rparam_len);
2145 /* check it's a supported varient */
2146 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2149 *rdata_len = mdrcnt + 1024;
2150 *rdata = REALLOC(*rdata,*rdata_len);
2152 SSVAL(*rparam,0,NERR_Success);
2153 SSVAL(*rparam,2,0); /* converter word */
2159 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2160 pstrcpy(p2,local_machine);
2162 p2 = skip_string(p2,1);
2165 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2166 pstrcpy(p2,sesssetup_user);
2167 p2 = skip_string(p2,1);
2170 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2171 pstrcpy(p2,global_myworkgroup);
2173 p2 = skip_string(p2,1);
2176 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2177 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2180 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2181 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2182 p2 = skip_string(p2,1);
2185 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2187 p2 = skip_string(p2,1);
2190 *rdata_len = PTR_DIFF(p2,*rdata);
2192 SSVAL(*rparam,4,*rdata_len);
2197 /****************************************************************************
2198 get info about a user
2200 struct user_info_11 {
2201 char usri11_name[21]; 0-20
2203 char *usri11_comment; 22-25
2204 char *usri11_usr_comment; 26-29
2205 unsigned short usri11_priv; 30-31
2206 unsigned long usri11_auth_flags; 32-35
2207 long usri11_password_age; 36-39
2208 char *usri11_homedir; 40-43
2209 char *usri11_parms; 44-47
2210 long usri11_last_logon; 48-51
2211 long usri11_last_logoff; 52-55
2212 unsigned short usri11_bad_pw_count; 56-57
2213 unsigned short usri11_num_logons; 58-59
2214 char *usri11_logon_server; 60-63
2215 unsigned short usri11_country_code; 64-65
2216 char *usri11_workstations; 66-69
2217 unsigned long usri11_max_storage; 70-73
2218 unsigned short usri11_units_per_week; 74-75
2219 unsigned char *usri11_logon_hours; 76-79
2220 unsigned short usri11_code_page; 80-81
2225 usri11_name specifies the user name for which information is retireved
2227 usri11_pad aligns the next data structure element to a word boundary
2229 usri11_comment is a null terminated ASCII comment
2231 usri11_user_comment is a null terminated ASCII comment about the user
2233 usri11_priv specifies the level of the privilege assigned to the user.
2234 The possible values are:
2236 Name Value Description
2237 USER_PRIV_GUEST 0 Guest privilege
2238 USER_PRIV_USER 1 User privilege
2239 USER_PRV_ADMIN 2 Administrator privilege
2241 usri11_auth_flags specifies the account operator privileges. The
2242 possible values are:
2244 Name Value Description
2245 AF_OP_PRINT 0 Print operator
2248 Leach, Naik [Page 28]
\r\f
2251 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2254 AF_OP_COMM 1 Communications operator
2255 AF_OP_SERVER 2 Server operator
2256 AF_OP_ACCOUNTS 3 Accounts operator
2259 usri11_password_age specifies how many seconds have elapsed since the
2260 password was last changed.
2262 usri11_home_dir points to a null terminated ASCII string that contains
2263 the path name of the user's home directory.
2265 usri11_parms points to a null terminated ASCII string that is set
2266 aside for use by applications.
2268 usri11_last_logon specifies the time when the user last logged on.
2269 This value is stored as the number of seconds elapsed since
2270 00:00:00, January 1, 1970.
2272 usri11_last_logoff specifies the time when the user last logged off.
2273 This value is stored as the number of seconds elapsed since
2274 00:00:00, January 1, 1970. A value of 0 means the last logoff
2277 usri11_bad_pw_count specifies the number of incorrect passwords
2278 entered since the last successful logon.
2280 usri11_log1_num_logons specifies the number of times this user has
2281 logged on. A value of -1 means the number of logons is unknown.
2283 usri11_logon_server points to a null terminated ASCII string that
2284 contains the name of the server to which logon requests are sent.
2285 A null string indicates logon requests should be sent to the
2288 usri11_country_code specifies the country code for the user's language
2291 usri11_workstations points to a null terminated ASCII string that
2292 contains the names of workstations the user may log on from.
2293 There may be up to 8 workstations, with the names separated by
2294 commas. A null strings indicates there are no restrictions.
2296 usri11_max_storage specifies the maximum amount of disk space the user
2297 can occupy. A value of 0xffffffff indicates there are no
2300 usri11_units_per_week specifies the equal number of time units into
2301 which a week is divided. This value must be equal to 168.
2303 usri11_logon_hours points to a 21 byte (168 bits) string that
2304 specifies the time during which the user can log on. Each bit
2305 represents one unique hour in a week. The first bit (bit 0, word
2306 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2310 Leach, Naik [Page 29]
\r\f
2313 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2316 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2317 are no restrictions.
2319 usri11_code_page specifies the code page for the user's language of
2322 All of the pointers in this data structure need to be treated
2323 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2324 to be ignored. The converter word returned in the parameters section
2325 needs to be subtracted from the lower 16 bits to calculate an offset
2326 into the return buffer where this ASCII string resides.
2328 There is no auxiliary data in the response.
2330 ****************************************************************************/
2332 #define usri11_name 0
2333 #define usri11_pad 21
2334 #define usri11_comment 22
2335 #define usri11_usr_comment 26
2336 #define usri11_full_name 30
2337 #define usri11_priv 34
2338 #define usri11_auth_flags 36
2339 #define usri11_password_age 40
2340 #define usri11_homedir 44
2341 #define usri11_parms 48
2342 #define usri11_last_logon 52
2343 #define usri11_last_logoff 56
2344 #define usri11_bad_pw_count 60
2345 #define usri11_num_logons 62
2346 #define usri11_logon_server 64
2347 #define usri11_country_code 68
2348 #define usri11_workstations 70
2349 #define usri11_max_storage 74
2350 #define usri11_units_per_week 78
2351 #define usri11_logon_hours 80
2352 #define usri11_code_page 84
2353 #define usri11_end 86
2355 #define USER_PRIV_GUEST 0
2356 #define USER_PRIV_USER 1
2357 #define USER_PRIV_ADMIN 2
2359 #define AF_OP_PRINT 0
2360 #define AF_OP_COMM 1
2361 #define AF_OP_SERVER 2
2362 #define AF_OP_ACCOUNTS 3
2365 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2366 int mdrcnt,int mprcnt,
2367 char **rdata,char **rparam,
2368 int *rdata_len,int *rparam_len)
2370 char *str1 = param+2;
2371 char *str2 = skip_string(str1,1);
2372 char *UserName = skip_string(str2,1);
2373 char *p = skip_string(UserName,1);
2374 int uLevel = SVAL(p,0);
2377 /* get NIS home of a previously validated user - simeon */
2378 /* With share level security vuid will always be zero.
2379 Don't depend on vuser being non-null !!. JRA */
2380 user_struct *vuser = get_valid_user_struct(vuid);
2382 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2385 *rparam = REALLOC(*rparam,*rparam_len);
2387 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2389 /* check it's a supported variant */
2390 if (strcmp(str1,"zWrLh") != 0) return False;
2393 case 0: p2 = "B21"; break;
2394 case 1: p2 = "B21BB16DWzzWz"; break;
2395 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2396 case 10: p2 = "B21Bzzz"; break;
2397 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2398 default: return False;
2401 if (strcmp(p2,str2) != 0) return False;
2403 *rdata_len = mdrcnt + 1024;
2404 *rdata = REALLOC(*rdata,*rdata_len);
2406 SSVAL(*rparam,0,NERR_Success);
2407 SSVAL(*rparam,2,0); /* converter word */
2410 p2 = p + usri11_end;
2413 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2417 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2422 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2423 pstrcpy(p2,"Comment");
2424 p2 = skip_string(p2,1);
2426 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2427 pstrcpy(p2,"UserComment");
2428 p2 = skip_string(p2,1);
2430 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2431 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2432 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2433 p2 = skip_string(p2,1);
2436 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2438 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2439 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2440 SIVALS(p,usri11_password_age,-1); /* password age */
2441 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2442 pstrcpy(p2, lp_logon_path());
2443 p2 = skip_string(p2,1);
2444 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2446 p2 = skip_string(p2,1);
2447 SIVAL(p,usri11_last_logon,0); /* last logon */
2448 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2449 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2450 SSVALS(p,usri11_num_logons,-1); /* num logons */
2451 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2452 pstrcpy(p2,"\\\\*");
2453 p2 = skip_string(p2,1);
2454 SSVAL(p,usri11_country_code,0); /* country code */
2456 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2458 p2 = skip_string(p2,1);
2460 SIVALS(p,usri11_max_storage,-1); /* max storage */
2461 SSVAL(p,usri11_units_per_week,168); /* units per week */
2462 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2464 /* a simple way to get logon hours at all times. */
2466 SCVAL(p2,21,0); /* fix zero termination */
2467 p2 = skip_string(p2,1);
2469 SSVAL(p,usri11_code_page,0); /* code page */
2471 if (uLevel == 1 || uLevel == 2)
2473 memset(p+22,' ',16); /* password */
2474 SIVALS(p,38,-1); /* password age */
2476 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2477 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2478 pstrcpy(p2,lp_logon_path());
2479 p2 = skip_string(p2,1);
2480 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2482 SSVAL(p,52,0); /* flags */
2483 SIVAL(p,54,0); /* script_path */
2486 SIVAL(p,60,0); /* auth_flags */
2487 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2488 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2489 p2 = skip_string(p2,1);
2490 SIVAL(p,68,0); /* urs_comment */
2491 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2493 p2 = skip_string(p2,1);
2494 SIVAL(p,76,0); /* workstations */
2495 SIVAL(p,80,0); /* last_logon */
2496 SIVAL(p,84,0); /* last_logoff */
2497 SIVALS(p,88,-1); /* acct_expires */
2498 SIVALS(p,92,-1); /* max_storage */
2499 SSVAL(p,96,168); /* units_per_week */
2500 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2503 SSVALS(p,102,-1); /* bad_pw_count */
2504 SSVALS(p,104,-1); /* num_logons */
2505 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2506 pstrcpy(p2,"\\\\%L");
2507 standard_sub_basic(p2);
2508 p2 = skip_string(p2,1);
2509 SSVAL(p,110,49); /* country_code */
2510 SSVAL(p,112,860); /* code page */
2514 *rdata_len = PTR_DIFF(p2,*rdata);
2516 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2521 /*******************************************************************
2522 get groups that a user is a member of
2523 ******************************************************************/
2524 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2525 int mdrcnt,int mprcnt,
2526 char **rdata,char **rparam,
2527 int *rdata_len,int *rparam_len)
2529 char *str1 = param+2;
2530 char *str2 = skip_string(str1,1);
2531 char *UserName = skip_string(str2,1);
2532 char *p = skip_string(UserName,1);
2533 int uLevel = SVAL(p,0);
2538 *rparam = REALLOC(*rparam,*rparam_len);
2540 /* check it's a supported varient */
2541 if (strcmp(str1,"zWrLeh") != 0) return False;
2543 case 0: p2 = "B21"; break;
2544 default: return False;
2546 if (strcmp(p2,str2) != 0) return False;
2548 *rdata_len = mdrcnt + 1024;
2549 *rdata = REALLOC(*rdata,*rdata_len);
2551 SSVAL(*rparam,0,NERR_Success);
2552 SSVAL(*rparam,2,0); /* converter word */
2556 /* XXXX we need a real SAM database some day */
2557 pstrcpy(p,"Users"); p += 21; count++;
2558 pstrcpy(p,"Domain Users"); p += 21; count++;
2559 pstrcpy(p,"Guests"); p += 21; count++;
2560 pstrcpy(p,"Domain Guests"); p += 21; count++;
2562 *rdata_len = PTR_DIFF(p,*rdata);
2564 SSVAL(*rparam,4,count); /* is this right?? */
2565 SSVAL(*rparam,6,count); /* is this right?? */
2571 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2572 int mdrcnt,int mprcnt,
2573 char **rdata,char **rparam,
2574 int *rdata_len,int *rparam_len)
2576 char *str1 = param+2;
2577 char *str2 = skip_string(str1,1);
2578 char *p = skip_string(str2,1);
2580 struct pack_desc desc;
2587 bzero(&desc,sizeof(desc));
2589 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2591 /* check it's a supported varient */
2592 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2593 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2594 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2596 desc.buflen = mdrcnt;
2597 desc.subformat = NULL;
2600 if (init_package(&desc,1,0))
2602 PACKI(&desc,"W",0); /* code */
2603 PACKS(&desc,"B21",name); /* eff. name */
2604 PACKS(&desc,"B",""); /* pad */
2606 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2607 PACKI(&desc,"D",0); /* auth flags XXX */
2608 PACKI(&desc,"W",0); /* num logons */
2609 PACKI(&desc,"W",0); /* bad pw count */
2610 PACKI(&desc,"D",0); /* last logon */
2611 PACKI(&desc,"D",-1); /* last logoff */
2612 PACKI(&desc,"D",-1); /* logoff time */
2613 PACKI(&desc,"D",-1); /* kickoff time */
2614 PACKI(&desc,"D",0); /* password age */
2615 PACKI(&desc,"D",0); /* password can change */
2616 PACKI(&desc,"D",-1); /* password must change */
2619 fstrcpy(mypath,"\\\\");
2620 fstrcat(mypath,local_machine);
2622 PACKS(&desc,"z",mypath); /* computer */
2624 PACKS(&desc,"z",global_myworkgroup);/* domain */
2626 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2627 /* made sure all macros are fully substituted and available */
2628 logon_script = lp_logon_script();
2629 standard_sub( conn, logon_script );
2630 PACKS(&desc,"z", logon_script); /* script path */
2631 /* End of JHT mods */
2633 PACKI(&desc,"D",0x00000000); /* reserved */
2636 *rdata_len = desc.usedlen;
2638 *rparam = REALLOC(*rparam,*rparam_len);
2639 SSVALS(*rparam,0,desc.errcode);
2641 SSVAL(*rparam,4,desc.neededlen);
2643 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2648 /****************************************************************************
2649 api_WAccessGetUserPerms
2650 ****************************************************************************/
2651 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2652 int mdrcnt,int mprcnt,
2653 char **rdata,char **rparam,
2654 int *rdata_len,int *rparam_len)
2656 char *str1 = param+2;
2657 char *str2 = skip_string(str1,1);
2658 char *user = skip_string(str2,1);
2659 char *resource = skip_string(user,1);
2661 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2663 /* check it's a supported varient */
2664 if (strcmp(str1,"zzh") != 0) return False;
2665 if (strcmp(str2,"") != 0) return False;
2668 *rparam = REALLOC(*rparam,*rparam_len);
2669 SSVALS(*rparam,0,0); /* errorcode */
2670 SSVAL(*rparam,2,0); /* converter word */
2671 SSVAL(*rparam,4,0x7f); /* permission flags */
2676 /****************************************************************************
2677 api_WPrintJobEnumerate
2678 ****************************************************************************/
2679 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2680 int mdrcnt,int mprcnt,
2681 char **rdata,char **rparam,
2682 int *rdata_len,int *rparam_len)
2684 char *str1 = param+2;
2685 char *str2 = skip_string(str1,1);
2686 char *p = skip_string(str2,1);
2692 struct pack_desc desc;
2693 print_queue_struct *queue=NULL;
2694 print_status_struct status;
2699 bzero(&desc,sizeof(desc));
2700 bzero(&status,sizeof(status));
2702 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2704 /* check it's a supported varient */
2705 if (strcmp(str1,"WWrLh") != 0) return False;
2706 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2708 printjob_decode(SVAL(p,0), &snum, &job);
2710 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2712 count = get_printqueue(snum,conn,&queue,&status);
2713 for (i = 0; i < count; i++) {
2714 if ((queue[i].job & 0xFF) == job) break;
2716 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2718 desc.buflen = mdrcnt;
2720 if (init_package(&desc,1,0)) {
2722 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2723 *rdata_len = desc.usedlen;
2726 desc.errcode = NERR_JobNotFound;
2732 *rparam = REALLOC(*rparam,*rparam_len);
2733 SSVALS(*rparam,0,desc.errcode);
2735 SSVAL(*rparam,4,desc.neededlen);
2737 if (queue) free(queue);
2739 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2743 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2744 int mdrcnt,int mprcnt,
2745 char **rdata,char **rparam,
2746 int *rdata_len,int *rparam_len)
2748 char *str1 = param+2;
2749 char *str2 = skip_string(str1,1);
2750 char *p = skip_string(str2,1);
2756 struct pack_desc desc;
2757 print_queue_struct *queue=NULL;
2758 print_status_struct status;
2760 bzero(&desc,sizeof(desc));
2761 bzero(&status,sizeof(status));
2763 p = skip_string(p,1);
2767 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2769 /* check it's a supported varient */
2770 if (strcmp(str1,"zWrLeh") != 0) return False;
2771 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2772 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2774 snum = lp_servicenumber(name);
2775 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2776 int pnum = lp_servicenumber(PRINTERS_NAME);
2778 lp_add_printer(name,pnum);
2779 snum = lp_servicenumber(name);
2783 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2785 count = get_printqueue(snum,conn,&queue,&status);
2786 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2788 desc.buflen = mdrcnt;
2790 if (init_package(&desc,count,0)) {
2792 for (i = 0; i < count; i++) {
2793 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2794 if (desc.errcode == NERR_Success) succnt = i+1;
2798 *rdata_len = desc.usedlen;
2801 *rparam = REALLOC(*rparam,*rparam_len);
2802 SSVALS(*rparam,0,desc.errcode);
2804 SSVAL(*rparam,4,succnt);
2805 SSVAL(*rparam,6,count);
2807 if (queue) free(queue);
2809 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2813 static int check_printdest_info(struct pack_desc* desc,
2814 int uLevel, char* id)
2816 desc->subformat = NULL;
2818 case 0: desc->format = "B9"; break;
2819 case 1: desc->format = "B9B21WWzW"; break;
2820 case 2: desc->format = "z"; break;
2821 case 3: desc->format = "zzzWWzzzWW"; break;
2822 default: return False;
2824 if (strcmp(desc->format,id) != 0) return False;
2828 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2829 struct pack_desc* desc)
2832 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2833 buf[sizeof(buf)-1] = 0;
2836 PACKS(desc,"B9",buf); /* szName */
2838 PACKS(desc,"B21",""); /* szUserName */
2839 PACKI(desc,"W",0); /* uJobId */
2840 PACKI(desc,"W",0); /* fsStatus */
2841 PACKS(desc,"z",""); /* pszStatus */
2842 PACKI(desc,"W",0); /* time */
2845 if (uLevel == 2 || uLevel == 3) {
2846 PACKS(desc,"z",buf); /* pszPrinterName */
2848 PACKS(desc,"z",""); /* pszUserName */
2849 PACKS(desc,"z",""); /* pszLogAddr */
2850 PACKI(desc,"W",0); /* uJobId */
2851 PACKI(desc,"W",0); /* fsStatus */
2852 PACKS(desc,"z",""); /* pszStatus */
2853 PACKS(desc,"z",""); /* pszComment */
2854 PACKS(desc,"z","NULL"); /* pszDrivers */
2855 PACKI(desc,"W",0); /* time */
2856 PACKI(desc,"W",0); /* pad1 */
2861 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2862 int mdrcnt,int mprcnt,
2863 char **rdata,char **rparam,
2864 int *rdata_len,int *rparam_len)
2866 char *str1 = param+2;
2867 char *str2 = skip_string(str1,1);
2868 char *p = skip_string(str2,1);
2869 char* PrinterName = p;
2871 struct pack_desc desc;
2874 bzero(&desc,sizeof(desc));
2876 p = skip_string(p,1);
2880 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2882 /* check it's a supported varient */
2883 if (strcmp(str1,"zWrLh") != 0) return False;
2884 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2886 snum = lp_servicenumber(PrinterName);
2887 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2888 int pnum = lp_servicenumber(PRINTERS_NAME);
2890 lp_add_printer(PrinterName,pnum);
2891 snum = lp_servicenumber(PrinterName);
2897 desc.errcode = NERR_DestNotFound;
2901 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2903 desc.buflen = mdrcnt;
2904 if (init_package(&desc,1,0)) {
2905 fill_printdest_info(conn,snum,uLevel,&desc);
2907 *rdata_len = desc.usedlen;
2911 *rparam = REALLOC(*rparam,*rparam_len);
2912 SSVALS(*rparam,0,desc.errcode);
2914 SSVAL(*rparam,4,desc.neededlen);
2916 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2920 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2921 int mdrcnt,int mprcnt,
2922 char **rdata,char **rparam,
2923 int *rdata_len,int *rparam_len)
2925 char *str1 = param+2;
2926 char *str2 = skip_string(str1,1);
2927 char *p = skip_string(str2,1);
2931 struct pack_desc desc;
2932 int services = lp_numservices();
2934 bzero(&desc,sizeof(desc));
2939 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2941 /* check it's a supported varient */
2942 if (strcmp(str1,"WrLeh") != 0) return False;
2943 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2946 for (i = 0; i < services; i++)
2947 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2950 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2952 desc.buflen = mdrcnt;
2953 if (init_package(&desc,queuecnt,0)) {
2956 for (i = 0; i < services; i++) {
2957 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2958 fill_printdest_info(conn,i,uLevel,&desc);
2960 if (desc.errcode == NERR_Success) succnt = n;
2965 *rdata_len = desc.usedlen;
2968 *rparam = REALLOC(*rparam,*rparam_len);
2969 SSVALS(*rparam,0,desc.errcode);
2971 SSVAL(*rparam,4,succnt);
2972 SSVAL(*rparam,6,queuecnt);
2974 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2978 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2979 int mdrcnt,int mprcnt,
2980 char **rdata,char **rparam,
2981 int *rdata_len,int *rparam_len)
2983 char *str1 = param+2;
2984 char *str2 = skip_string(str1,1);
2985 char *p = skip_string(str2,1);
2988 struct pack_desc desc;
2990 bzero(&desc,sizeof(desc));
2995 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2997 /* check it's a supported varient */
2998 if (strcmp(str1,"WrLeh") != 0) return False;
2999 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3001 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3003 desc.buflen = mdrcnt;
3004 if (init_package(&desc,1,0)) {
3005 PACKS(&desc,"B41","NULL");
3008 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3010 *rdata_len = desc.usedlen;
3013 *rparam = REALLOC(*rparam,*rparam_len);
3014 SSVALS(*rparam,0,desc.errcode);
3016 SSVAL(*rparam,4,succnt);
3019 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3023 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3024 int mdrcnt,int mprcnt,
3025 char **rdata,char **rparam,
3026 int *rdata_len,int *rparam_len)
3028 char *str1 = param+2;
3029 char *str2 = skip_string(str1,1);
3030 char *p = skip_string(str2,1);
3033 struct pack_desc desc;
3035 bzero(&desc,sizeof(desc));
3040 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3042 /* check it's a supported varient */
3043 if (strcmp(str1,"WrLeh") != 0) return False;
3044 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3046 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3048 desc.buflen = mdrcnt;
3050 if (init_package(&desc,1,0)) {
3051 PACKS(&desc,"B13","lpd");
3054 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3056 *rdata_len = desc.usedlen;
3059 *rparam = REALLOC(*rparam,*rparam_len);
3060 SSVALS(*rparam,0,desc.errcode);
3062 SSVAL(*rparam,4,succnt);
3065 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3069 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3070 int mdrcnt,int mprcnt,
3071 char **rdata,char **rparam,
3072 int *rdata_len,int *rparam_len)
3074 char *str1 = param+2;
3075 char *str2 = skip_string(str1,1);
3076 char *p = skip_string(str2,1);
3079 struct pack_desc desc;
3081 bzero(&desc,sizeof(desc));
3086 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3088 /* check it's a supported varient */
3089 if (strcmp(str1,"WrLeh") != 0) return False;
3090 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3092 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3093 bzero(&desc,sizeof(desc));
3095 desc.buflen = mdrcnt;
3097 if (init_package(&desc,1,0)) {
3098 PACKS(&desc,"B13","lp0");
3101 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3103 *rdata_len = desc.usedlen;
3106 *rparam = REALLOC(*rparam,*rparam_len);
3107 SSVALS(*rparam,0,desc.errcode);
3109 SSVAL(*rparam,4,succnt);
3112 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3118 char * pipe_clnt_name;
3119 char * pipe_srv_name;
3120 BOOL (*fn) (pipes_struct *, prs_struct *);
3123 static struct api_cmd api_fd_commands[] =
3125 { "lsarpc", "lsass", api_ntlsa_rpc },
3126 { "samr", "lsass", api_samr_rpc },
3127 { "srvsvc", "ntsvcs", api_srvsvc_rpc },
3128 { "wkssvc", "ntsvcs", api_wkssvc_rpc },
3129 { "NETLOGON", "lsass", api_netlog_rpc },
3130 { "winreg", "winreg", api_reg_rpc },
3131 { NULL, NULL, NULL }
3134 static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
3136 BOOL ntlmssp_auth = False;
3137 fstring ack_pipe_name;
3140 DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
3142 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3144 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3145 api_fd_commands[i].fn != NULL)
3147 DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
3148 api_fd_commands[i].pipe_clnt_name,
3149 api_fd_commands[i].pipe_srv_name));
3150 fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
3155 if (api_fd_commands[i].fn == NULL) return False;
3157 /* decode the bind request */
3158 smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
3160 if (pd->offset == 0) return False;
3162 if (p->hdr.auth_len != 0)
3164 /* decode the authentication verifier */
3165 smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
3167 if (pd->offset == 0) return False;
3169 /* ignore the version number for now */
3170 ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
3173 /* name has to be \PIPE\xxxxx */
3174 fstrcpy(ack_pipe_name, "\\PIPE\\");
3175 fstrcat(ack_pipe_name, p->pipe_srv_name);
3177 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
3179 prs_init(&(p->rdata), 1024, 4, 0, False);
3180 prs_init(&(p->rhdr ), 0x10, 4, 0, False);
3181 prs_init(&(p->rauth), 1024, 4, 0, False);
3184 /*** do the bind ack first ***/
3187 make_rpc_hdr_ba(&p->hdr_ba,
3188 p->hdr_rb.bba.max_tsize,
3189 p->hdr_rb.bba.max_rsize,
3190 p->hdr_rb.bba.assoc_gid,
3193 &(p->hdr_rb.transfer));
3195 smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
3196 mem_realloc_data(p->rdata.data, p->rdata.offset);
3199 /*** now the authentication ***/
3205 bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
3207 make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
3210 0x00000000, 0x0000b2b3, 0x000082b1,
3212 smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
3213 mem_realloc_data(p->rauth.data, p->rauth.offset);
3217 /*** then do the header, now we know the length ***/
3220 make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
3222 p->rdata.offset + p->rauth.offset,
3225 smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
3226 mem_realloc_data(p->rhdr.data, p->rdata.offset);
3229 /*** link rpc header, bind acknowledgment and authentication responses ***/
3232 p->rhdr.data->offset.start = 0;
3233 p->rhdr.data->offset.end = p->rhdr.offset;
3234 p->rhdr.data->next = p->rdata.data;
3238 p->rdata.data->offset.start = p->rhdr.offset;
3239 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3240 p->rdata.data->next = p->rauth.data;
3242 p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
3243 p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
3244 p->rauth.data->next = NULL;
3248 p->rdata.data->offset.start = p->rhdr.offset;
3249 p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
3250 p->rdata.data->next = NULL;
3256 static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
3260 for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
3262 if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
3263 api_fd_commands[i].fn != NULL)
3265 DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
3266 return api_fd_commands[i].fn(p, pd);
3272 static BOOL api_dce_rpc_command(char *outbuf,
3277 if (pd->data == NULL) return False;
3279 /* process the rpc header */
3280 smb_io_rpc_hdr("", &p->hdr, pd, 0);
3282 if (pd->offset == 0) return False;
3284 switch (p->hdr.pkt_type)
3288 reply = api_pipe_bind_req(p, pd);
3293 reply = api_pipe_request (p, pd);
3300 /* now send the reply */
3301 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3303 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3305 /* all of data was sent: no need to wait for SMBreadX calls */
3306 mem_free_data(p->rhdr .data);
3307 mem_free_data(p->rdata.data);
3314 /****************************************************************************
3315 SetNamedPipeHandleState
3316 ****************************************************************************/
3317 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3321 if (!param) return False;
3323 id = param[0] + (param[1] << 8);
3324 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
3326 if (set_rpc_pipe_hnd_state(p, id))
3328 /* now send the reply */
3329 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3337 /****************************************************************************
3338 when no reply is generated, indicate unsupported.
3339 ****************************************************************************/
3340 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3342 struct mem_buf rparam;
3344 mem_init(&rparam, 0);
3345 mem_alloc_data(&rparam, 4);
3347 rparam.offset.start = 0;
3348 rparam.offset.end = 4;
3351 SSVAL(rparam.data,0,NERR_notsupported);
3352 SSVAL(rparam.data,2,0); /* converter word */
3354 DEBUG(3,("Unsupported API fd command\n"));
3356 /* now send the reply */
3357 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3359 mem_free_data(&rparam);
3364 /****************************************************************************
3365 handle remote api calls delivered to a named pipe already opened.
3366 ****************************************************************************/
3367 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3368 uint16 *setup,char *data,char *params,
3369 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3375 pipes_struct *p = NULL;
3377 struct mem_buf data_buf;
3379 DEBUG(5,("api_fd_reply\n"));
3381 /* fake up a data buffer from the api_fd_reply data parameters */
3382 mem_create(&data_buf, data, tdscnt, 0, False);
3383 data_buf.offset.start = 0;
3384 data_buf.offset.end = tdscnt;
3386 /* fake up a parsing structure */
3387 pd.data = &data_buf;
3392 /* First find out the name of this file. */
3395 DEBUG(0,("Unexpected named pipe transaction.\n"));
3399 /* Get the file handle and hence the file name. */
3401 subcommand = setup[0];
3402 get_rpc_pipe(pnum, &p);
3406 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3407 subcommand, p->name, pnum));
3409 /* record maximum data length that can be transmitted in an SMBtrans */
3410 p->file_offset = mdrcnt;
3412 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3413 p, p->file_offset));
3419 /* dce/rpc command */
3420 reply = api_dce_rpc_command(outbuf, p, &pd);
3425 /* Set Named Pipe Handle state */
3426 reply = api_SNPHS(outbuf, p, params);
3433 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3438 return api_no_reply(outbuf, mdrcnt);
3443 /****************************************************************************
3444 the buffer was too small
3445 ****************************************************************************/
3446 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3447 int mdrcnt,int mprcnt,
3448 char **rdata,char **rparam,
3449 int *rdata_len,int *rparam_len)
3451 *rparam_len = MIN(*rparam_len,mprcnt);
3452 *rparam = REALLOC(*rparam,*rparam_len);
3456 SSVAL(*rparam,0,NERR_BufTooSmall);
3458 DEBUG(3,("Supplied buffer too small in API command\n"));
3464 /****************************************************************************
3465 the request is not supported
3466 ****************************************************************************/
3467 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3468 int mdrcnt,int mprcnt,
3469 char **rdata,char **rparam,
3470 int *rdata_len,int *rparam_len)
3473 *rparam = REALLOC(*rparam,*rparam_len);
3477 SSVAL(*rparam,0,NERR_notsupported);
3478 SSVAL(*rparam,2,0); /* converter word */
3480 DEBUG(3,("Unsupported API command\n"));
3492 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3493 int,int,char **,char **,int *,int *);
3495 } api_commands[] = {
3496 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3497 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3498 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3499 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3500 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3501 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3502 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3503 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3504 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3505 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3506 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3507 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3508 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3509 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3510 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3511 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3512 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3513 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3514 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3515 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3516 {"NetServerEnum", 104, api_RNetServerEnum,0},
3517 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3518 {"SetUserPassword", 115, api_SetUserPassword,0},
3519 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3520 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3521 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3522 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3523 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3524 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3525 {NULL, -1, api_Unsupported,0}};
3528 /****************************************************************************
3529 handle remote api calls
3530 ****************************************************************************/
3531 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3532 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3534 int api_command = SVAL(params,0);
3535 struct mem_buf rdata_buf;
3536 struct mem_buf rparam_buf;
3538 char *rparam = NULL;
3544 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3545 api_command,params+2,skip_string(params+2,1),
3546 tdscnt,tpscnt,mdrcnt,mprcnt));
3548 for (i=0;api_commands[i].name;i++)
3549 if (api_commands[i].id == api_command && api_commands[i].fn)
3551 DEBUG(3,("Doing %s\n",api_commands[i].name));
3555 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3556 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3558 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3559 &rdata,&rparam,&rdata_len,&rparam_len);
3562 if (rdata_len > mdrcnt ||
3563 rparam_len > mprcnt)
3565 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3566 &rdata,&rparam,&rdata_len,&rparam_len);
3570 /* if we get False back then it's actually unsupported */
3572 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3573 &rdata,&rparam,&rdata_len,&rparam_len);
3576 mem_create(&rdata_buf , rdata , rdata_len , 0, False);
3577 mem_create(&rparam_buf, rparam, rparam_len, 0, False);
3579 rdata_buf.offset.start = 0;
3580 rdata_buf.offset.end = rdata_len;
3582 rparam_buf.offset.start = 0;
3583 rparam_buf.offset.end = rparam_len;
3585 /* now send the reply */
3586 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3588 if (rdata ) free(rdata);
3589 if (rparam) free(rparam);
3594 /****************************************************************************
3595 handle named pipe commands
3596 ****************************************************************************/
3597 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3598 uint16 *setup,char *data,char *params,
3599 int suwcnt,int tdscnt,int tpscnt,
3600 int msrcnt,int mdrcnt,int mprcnt)
3602 DEBUG(3,("named pipe command on <%s> name\n", name));
3604 if (strequal(name,"LANMAN"))
3606 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3609 if (strlen(name) < 1)
3611 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3616 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3623 /****************************************************************************
3625 ****************************************************************************/
3626 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3630 char *data=NULL,*params=NULL;
3633 uint16 vuid = SVAL(inbuf,smb_uid);
3634 int tpscnt = SVAL(inbuf,smb_vwv0);
3635 int tdscnt = SVAL(inbuf,smb_vwv1);
3636 int mprcnt = SVAL(inbuf,smb_vwv2);
3637 int mdrcnt = SVAL(inbuf,smb_vwv3);
3638 int msrcnt = CVAL(inbuf,smb_vwv4);
3639 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3640 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3641 int pscnt = SVAL(inbuf,smb_vwv9);
3642 int psoff = SVAL(inbuf,smb_vwv10);
3643 int dscnt = SVAL(inbuf,smb_vwv11);
3644 int dsoff = SVAL(inbuf,smb_vwv12);
3645 int suwcnt = CVAL(inbuf,smb_vwv13);
3647 bzero(name, sizeof(name));
3648 fstrcpy(name,smb_buf(inbuf));
3650 if (dscnt > tdscnt || pscnt > tpscnt) {
3651 exit_server("invalid trans parameters\n");
3655 data = (char *)malloc(tdscnt);
3656 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3660 params = (char *)malloc(tpscnt);
3661 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3666 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3667 for (i=0;i<suwcnt;i++)
3668 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3672 if (pscnt < tpscnt || dscnt < tdscnt) {
3673 /* We need to send an interim response then receive the rest
3674 of the parameter/data bytes */
3675 outsize = set_message(outbuf,0,0,True);
3677 send_smb(Client,outbuf);
3680 /* receive the rest of the trans packet */
3681 while (pscnt < tpscnt || dscnt < tdscnt) {
3683 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3685 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3687 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3689 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3691 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3692 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3694 if (params) free(params);
3695 if (data) free(data);
3696 if (setup) free(setup);
3697 return(ERROR(ERRSRV,ERRerror));
3702 tpscnt = SVAL(inbuf,smb_vwv0);
3703 tdscnt = SVAL(inbuf,smb_vwv1);
3705 pcnt = SVAL(inbuf,smb_vwv2);
3706 poff = SVAL(inbuf,smb_vwv3);
3707 pdisp = SVAL(inbuf,smb_vwv4);
3709 dcnt = SVAL(inbuf,smb_vwv5);
3710 doff = SVAL(inbuf,smb_vwv6);
3711 ddisp = SVAL(inbuf,smb_vwv7);
3716 if (dscnt > tdscnt || pscnt > tpscnt) {
3717 exit_server("invalid trans parameters\n");
3721 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3723 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3727 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3728 name,tdscnt,tpscnt,suwcnt));
3730 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3731 DEBUG(5,("calling named_pipe\n"));
3732 outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3733 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3735 DEBUG(3,("invalid pipe name\n"));
3740 if (data) free(data);
3741 if (params) free(params);
3742 if (setup) free(setup);
3744 if (close_on_completion)
3745 close_cnum(conn,vuid);
3751 return(ERROR(ERRSRV,ERRnosupport));