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 smb_read_error;
64 extern uint32 global_client_caps;
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)+1;
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 align = ((this_lparam)%4);
187 set_message(outbuf,10+lsetup,1+align+this_ldata+this_lparam,True);
189 if (buffer_too_large)
191 if (global_client_caps & CAP_STATUS32)
193 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
194 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
195 SIVAL(outbuf, smb_rcls, 0x80000005); /* STATUS_BUFFER_OVERFLOW */
197 SCVAL(outbuf, smb_rcls, ERRDOS);
198 SSVAL(outbuf, smb_err, ERRmoredata);
202 copy_trans_params_and_data(outbuf, align,
204 tot_param , tot_data,
205 this_lparam, this_ldata);
207 SSVAL(outbuf,smb_vwv0,lparam);
208 SSVAL(outbuf,smb_vwv1,ldata);
209 SSVAL(outbuf,smb_vwv3,this_lparam);
210 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
211 SSVAL(outbuf,smb_vwv5,0);
212 SSVAL(outbuf,smb_vwv6,this_ldata);
213 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
214 SSVAL(outbuf,smb_vwv8,0);
215 SSVAL(outbuf,smb_vwv9,lsetup);
217 for (i=0;i<lsetup;i++)
219 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
223 send_smb(Client,outbuf);
225 tot_data = this_ldata;
226 tot_param = this_lparam;
228 while (tot_data < ldata || tot_param < lparam)
230 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
231 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
233 align = (this_lparam%4);
235 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
237 copy_trans_params_and_data(outbuf, align,
239 tot_param , tot_data,
240 this_lparam, this_ldata);
242 SSVAL(outbuf,smb_vwv3,this_lparam);
243 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
244 SSVAL(outbuf,smb_vwv5,tot_param);
245 SSVAL(outbuf,smb_vwv6,this_ldata);
246 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
247 SSVAL(outbuf,smb_vwv8,tot_data);
248 SSVAL(outbuf,smb_vwv9,0);
251 send_smb(Client,outbuf);
253 tot_data += this_ldata;
254 tot_param += this_lparam;
259 char* format; /* formatstring for structure */
260 char* subformat; /* subformat for structure */
261 char* base; /* baseaddress of buffer */
262 int buflen; /* remaining size for fixed part; on init: length of base */
263 int subcount; /* count of substructures */
264 char* structbuf; /* pointer into buffer for remaining fixed part */
265 int stringlen; /* remaining size for variable part */
266 char* stringbuf; /* pointer into buffer for remaining variable part */
267 int neededlen; /* total needed size */
268 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
269 char* curpos; /* current position; pointer into format or subformat */
273 static int get_counter(char** p)
276 if (!p || !(*p)) return(1);
277 if (!isdigit((int)**p)) return 1;
281 n = 10 * n + (i - '0');
288 static int getlen(char* p)
294 case 'W': /* word (2 byte) */
297 case 'N': /* count of substructures (word) at end */
300 case 'D': /* double word (4 byte) */
301 case 'z': /* offset to zero terminated string (4 byte) */
302 case 'l': /* offset to user data (4 byte) */
305 case 'b': /* offset to data (with counter) (4 byte) */
309 case 'B': /* byte (with optional counter) */
310 n += get_counter(&p);
317 static BOOL init_package(struct pack_desc* p, int count, int subcount)
322 if (!p->format || !p->base) return(False);
324 i = count * getlen(p->format);
325 if (p->subformat) i += subcount * getlen(p->subformat);
326 p->structbuf = p->base;
330 p->curpos = p->format;
334 p->errcode = ERRmoredata;
337 p->errcode = NERR_Success;
340 p->stringbuf = p->base + i;
342 return(p->errcode == NERR_Success);
346 static int package(struct pack_desc* p, ...)
349 static int package(va_alist)
355 int needed=0, stringneeded;
357 int is_string=0, stringused;
364 p = va_arg(args,struct pack_desc *);
369 p->curpos = p->format;
371 p->curpos = p->subformat;
376 str = va_arg(args,char*);
377 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
381 if (!p->curpos) return(0);
383 switch( *p->curpos++ ) {
384 case 'W': /* word (2 byte) */
386 temp = va_arg(args,int);
387 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
389 case 'N': /* count of substructures (word) at end */
391 p->subcount = va_arg(args,int);
392 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
394 case 'D': /* double word (4 byte) */
396 temp = va_arg(args,int);
397 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
399 case 'B': /* byte (with optional counter) */
400 needed = get_counter(&p->curpos);
402 char *s = va_arg(args,char*);
403 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
406 case 'z': /* offset to zero terminated string (4 byte) */
407 str = va_arg(args,char*);
408 stringneeded = (str ? strlen(str)+1 : 0);
411 case 'l': /* offset to user data (4 byte) */
412 str = va_arg(args,char*);
413 stringneeded = va_arg(args,int);
416 case 'b': /* offset to data (with counter) (4 byte) */
417 str = va_arg(args,char*);
418 stringneeded = get_counter(&p->curpos);
423 if (stringneeded >= 0) {
425 if (p->buflen >= needed) {
426 stringused = stringneeded;
427 if (stringused > p->stringlen) {
428 stringused = (is_string ? p->stringlen : 0);
429 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
432 SIVAL(p->structbuf,0,0);
434 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
435 memcpy(p->stringbuf,str?str:"",stringused);
436 if (is_string) p->stringbuf[stringused-1] = '\0';
437 p->stringbuf += stringused;
438 p->stringlen -= stringused;
439 p->usedlen += stringused;
442 p->neededlen += stringneeded;
444 p->neededlen += needed;
445 if (p->buflen >= needed) {
446 p->structbuf += needed;
448 p->usedlen += needed;
451 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
457 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
458 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
460 #define PACK(desc,t,v) package(desc,v)
461 #define PACKl(desc,t,v,l) package(desc,v,l)
464 static void PACKI(struct pack_desc* desc,char *t,int v)
469 static void PACKS(struct pack_desc* desc,char *t,char *v)
475 /****************************************************************************
477 ****************************************************************************/
479 static void PackDriverData(struct pack_desc* desc)
481 char drivdata[4+4+32];
482 SIVAL(drivdata,0,sizeof drivdata); /* cb */
483 SIVAL(drivdata,4,1000); /* lVersion */
484 memset(drivdata+8,0,32); /* szDeviceName */
485 pstrcpy(drivdata+8,"NULL");
486 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
489 static int check_printq_info(struct pack_desc* desc,
490 int uLevel, char *id1, char *id2)
492 desc->subformat = NULL;
495 desc->format = "B13";
498 desc->format = "B13BWWWzzzzzWW";
501 desc->format = "B13BWWWzzzzzWN";
502 desc->subformat = "WB21BB16B10zWWzDDz";
505 desc->format = "zWWWWzzzzWWzzl";
508 desc->format = "zWWWWzzzzWNzzl";
509 desc->subformat = "WWzWWDDzz";
515 desc->format = "WzzzzzzzzN";
516 desc->subformat = "z";
518 default: return False;
520 if (strcmp(desc->format,id1) != 0) return False;
521 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
525 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
526 struct pack_desc* desc,
527 print_queue_struct* queue, int n)
529 time_t t = queue->time;
531 /* the client expects localtime */
534 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
536 PACKS(desc,"B21",queue->user); /* szUserName */
537 PACKS(desc,"B",""); /* pad */
538 PACKS(desc,"B16",""); /* szNotifyName */
539 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
540 PACKS(desc,"z",""); /* pszParms */
541 PACKI(desc,"W",n+1); /* uPosition */
542 PACKI(desc,"W",queue->status); /* fsStatus */
543 PACKS(desc,"z",""); /* pszStatus */
544 PACKI(desc,"D",t); /* ulSubmitted */
545 PACKI(desc,"D",queue->size); /* ulSize */
546 PACKS(desc,"z",queue->file); /* pszComment */
548 if (uLevel == 2 || uLevel == 3) {
549 PACKI(desc,"W",queue->priority); /* uPriority */
550 PACKS(desc,"z",queue->user); /* pszUserName */
551 PACKI(desc,"W",n+1); /* uPosition */
552 PACKI(desc,"W",queue->status); /* fsStatus */
553 PACKI(desc,"D",t); /* ulSubmitted */
554 PACKI(desc,"D",queue->size); /* ulSize */
555 PACKS(desc,"z","Samba"); /* pszComment */
556 PACKS(desc,"z",queue->file); /* pszDocument */
558 PACKS(desc,"z",""); /* pszNotifyName */
559 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
560 PACKS(desc,"z",""); /* pszParms */
561 PACKS(desc,"z",""); /* pszStatus */
562 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
563 PACKS(desc,"z","lpd"); /* pszQProcName */
564 PACKS(desc,"z",""); /* pszQProcParms */
565 PACKS(desc,"z","NULL"); /* pszDriverName */
566 PackDriverData(desc); /* pDriverData */
567 PACKS(desc,"z",""); /* pszPrinterName */
572 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
573 struct pack_desc* desc,
574 int count, print_queue_struct* queue,
575 print_status_struct* status)
580 PACKS(desc,"B13",SERVICE(snum));
585 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
589 if (uLevel == 1 || uLevel == 2) {
590 PACKS(desc,"B",""); /* alignment */
591 PACKI(desc,"W",5); /* priority */
592 PACKI(desc,"W",0); /* start time */
593 PACKI(desc,"W",0); /* until time */
594 PACKS(desc,"z",""); /* pSepFile */
595 PACKS(desc,"z","lpd"); /* pPrProc */
596 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
597 PACKS(desc,"z",""); /* pParms */
599 PACKS(desc,"z","UNKNOWN PRINTER");
600 PACKI(desc,"W",LPSTAT_ERROR);
602 else if (!status || !status->message[0]) {
603 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
604 PACKI(desc,"W",LPSTAT_OK); /* status */
606 PACKS(desc,"z",status->message);
607 PACKI(desc,"W",status->status); /* status */
609 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
611 if (uLevel == 3 || uLevel == 4) {
612 PACKI(desc,"W",5); /* uPriority */
613 PACKI(desc,"W",0); /* uStarttime */
614 PACKI(desc,"W",0); /* uUntiltime */
615 PACKI(desc,"W",5); /* pad1 */
616 PACKS(desc,"z",""); /* pszSepFile */
617 PACKS(desc,"z","WinPrint"); /* pszPrProc */
618 PACKS(desc,"z",""); /* pszParms */
619 if (!status || !status->message[0]) {
620 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
621 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
623 PACKS(desc,"z",status->message); /* pszComment */
624 PACKI(desc,"W",status->status); /* fsStatus */
626 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
627 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
628 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
629 PackDriverData(desc); /* pDriverData */
631 if (uLevel == 2 || uLevel == 4) {
633 for (i=0;i<count;i++)
634 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
639 pstring tok,driver,datafile,langmon,helpfile,datatype;
644 pstrcpy(fname,lp_driverfile());
645 f=sys_fopen(fname,"r");
647 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
648 desc->errcode=NERR_notsupported;
652 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
653 DEBUG(0,("fill_printq_info: malloc fail !\n"));
654 desc->errcode=NERR_notsupported;
659 bzero(p, 8192*sizeof(char));
662 /* lookup the long printer driver name in the file description */
663 while (f && !feof(f) && !ok)
665 p = q; /* reset string pointer */
668 if (next_token(&p,tok,":",sizeof(tok)) &&
669 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
670 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
675 /* driver file name */
676 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
678 if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
680 * for the next tokens - which may be empty - I have to check for empty
681 * tokens first because the next_token function will skip all empty
689 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
693 /* language monitor */
697 } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0;
700 /* default data type */
701 if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0;
704 PACKI(desc,"W",0x0400); /* don't know */
705 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
706 PACKS(desc,"z",driver); /* Driverfile Name */
707 PACKS(desc,"z",datafile); /* Datafile name */
708 PACKS(desc,"z",langmon); /* language monitor */
709 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
710 PACKS(desc,"z",datatype); /* default data type */
711 PACKS(desc,"z",helpfile); /* helpfile name */
712 PACKS(desc,"z",driver); /* driver name */
713 DEBUG(3,("Driver:%s:\n",driver));
714 DEBUG(3,("Data File:%s:\n",datafile));
715 DEBUG(3,("Language Monitor:%s:\n",langmon));
716 DEBUG(3,("Data Type:%s:\n",datatype));
717 DEBUG(3,("Help File:%s:\n",helpfile));
718 PACKI(desc,"N",count); /* number of files to copy */
719 for (i=0;i<count;i++)
721 /* no need to check return value here - it was already tested in
722 * get_printerdrivernumber
724 next_token(&p,tok,",",sizeof(tok));
725 PACKS(desc,"z",tok); /* driver files to copy */
726 DEBUG(3,("file:%s:\n",tok));
729 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
730 SERVICE(snum),count));
732 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
733 desc->errcode=NERR_notsupported;
739 /* This function returns the number of files for a given driver */
740 static int get_printerdrivernumber(int snum)
748 pstrcpy(fname,lp_driverfile());
750 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
751 f=sys_fopen(fname,"r");
753 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
757 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
758 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
763 q=p; /* need it to free memory because p change ! */
765 /* lookup the long printer driver name in the file description */
766 while (!feof(f) && !ok)
768 p = q; /* reset string pointer */
770 if (next_token(&p,tok,":",sizeof(tok)) &&
771 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
780 if (*p++ == ':') i--;
785 /* count the number of files */
786 while (next_token(&p,tok,",",sizeof(tok)))
794 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
795 uint16 vuid, char *param,char *data,
796 int mdrcnt,int mprcnt,
797 char **rdata,char **rparam,
798 int *rdata_len,int *rparam_len)
800 char *str1 = param+2;
801 char *str2 = skip_string(str1,1);
802 char *p = skip_string(str2,1);
808 struct pack_desc desc;
809 print_queue_struct *queue=NULL;
810 print_status_struct status;
812 bzero(&status,sizeof(status));
813 bzero(&desc,sizeof(desc));
815 p = skip_string(p,1);
819 /* remove any trailing username */
820 if ((p = strchr(QueueName,'%'))) *p = 0;
822 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
824 /* check it's a supported varient */
825 if (!prefix_ok(str1,"zWrLh")) return False;
826 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
828 snum = lp_servicenumber(QueueName);
829 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
830 int pnum = lp_servicenumber(PRINTERS_NAME);
832 lp_add_printer(QueueName,pnum);
833 snum = lp_servicenumber(QueueName);
837 if (snum < 0 || !VALID_SNUM(snum)) return(False);
840 count = get_printerdrivernumber(snum);
841 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
843 count = get_printqueue(snum, conn,&queue,&status);
846 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
848 desc.buflen = mdrcnt;
849 if (init_package(&desc,1,count)) {
850 desc.subcount = count;
851 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
852 } else if(uLevel == 0) {
854 * This is a *disgusting* hack.
855 * This is *so* bad that even I'm embarrassed (and I
856 * have no shame). Here's the deal :
857 * Until we get the correct SPOOLSS code into smbd
858 * then when we're running with NT SMB support then
859 * NT makes this call with a level of zero, and then
860 * immediately follows it with an open request to
861 * the \\SRVSVC pipe. If we allow that open to
862 * succeed then NT barfs when it cannot open the
863 * \\SPOOLSS pipe immediately after and continually
864 * whines saying "Printer name is invalid" forever
865 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
866 * to fail, then NT downgrades to using the downlevel code
867 * and everything works as well as before. I hate
868 * myself for adding this code.... JRA.
871 fail_next_srvsvc_open();
874 *rdata_len = desc.usedlen;
877 *rparam = REALLOC(*rparam,*rparam_len);
878 SSVALS(*rparam,0,desc.errcode);
880 SSVAL(*rparam,4,desc.neededlen);
882 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
884 if (queue) free(queue);
890 /****************************************************************************
891 view list of all print jobs on all queues
892 ****************************************************************************/
893 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
894 int mdrcnt, int mprcnt,
895 char **rdata, char** rparam,
896 int *rdata_len, int *rparam_len)
898 char *param_format = param+2;
899 char *output_format1 = skip_string(param_format,1);
900 char *p = skip_string(output_format1,1);
901 int uLevel = SVAL(p,0);
902 char *output_format2 = p + 4;
903 int services = lp_numservices();
905 struct pack_desc desc;
906 print_queue_struct **queue = NULL;
907 print_status_struct *status = NULL;
908 int* subcntarr = NULL;
909 int queuecnt, subcnt=0, succnt=0;
911 bzero(&desc,sizeof(desc));
913 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
915 if (!prefix_ok(param_format,"WrLeh")) return False;
916 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
919 for (i = 0; i < services; i++)
920 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
923 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
924 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
927 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
928 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
929 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
932 memset(status,0,queuecnt*sizeof(print_status_struct));
933 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
934 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
939 for (i = 0; i < services; i++)
940 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
941 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
942 subcnt += subcntarr[n];
946 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
948 desc.buflen = mdrcnt;
950 if (init_package(&desc,queuecnt,subcnt)) {
953 for (i = 0; i < services; i++)
954 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
955 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
957 if (desc.errcode == NERR_Success) succnt = n;
961 if (subcntarr) free(subcntarr);
963 *rdata_len = desc.usedlen;
965 *rparam = REALLOC(*rparam,*rparam_len);
966 SSVALS(*rparam,0,desc.errcode);
968 SSVAL(*rparam,4,succnt);
969 SSVAL(*rparam,6,queuecnt);
971 for (i = 0; i < queuecnt; i++) {
972 if (queue && queue[i]) free(queue[i]);
975 if (queue) free(queue);
976 if (status) free(status);
981 /****************************************************************************
982 get info level for a server list query
983 ****************************************************************************/
984 static BOOL check_server_info(int uLevel, char* id)
988 if (strcmp(id,"B16") != 0) return False;
991 if (strcmp(id,"B16BBDz") != 0) return False;
999 struct srv_info_struct
1009 /*******************************************************************
1010 get server info lists from the files saved by nmbd. Return the
1012 ******************************************************************/
1013 static int get_server_info(uint32 servertype,
1014 struct srv_info_struct **servers,
1022 BOOL local_list_only;
1024 pstrcpy(fname,lp_lockdir());
1025 trim_string(fname,NULL,"/");
1027 pstrcat(fname,SERVER_LIST);
1029 f = sys_fopen(fname,"r");
1032 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1036 /* request for everything is code for request all servers */
1037 if (servertype == SV_TYPE_ALL)
1038 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1040 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1042 DEBUG(4,("Servertype search: %8x\n",servertype));
1047 struct srv_info_struct *s;
1052 fgets(line,sizeof(line)-1,f);
1053 if (!*line) continue;
1055 if (count == alloced) {
1057 (*servers) = (struct srv_info_struct *)
1058 Realloc(*servers,sizeof(**servers)*alloced);
1059 if (!(*servers)) return(0);
1060 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1062 s = &(*servers)[count];
1064 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1065 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1066 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1067 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1068 /* this allows us to cope with an old nmbd */
1069 pstrcpy(s->domain,global_myworkgroup);
1072 if (sscanf(stype,"%X",&s->type) != 1) {
1073 DEBUG(4,("r:host file "));
1077 /* Filter the servers/domains we return based on what was asked for. */
1079 /* Check to see if we are being asked for a local list only. */
1080 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1081 DEBUG(4,("r: local list only"));
1085 /* doesn't match up: don't want it */
1086 if (!(servertype & s->type)) {
1087 DEBUG(4,("r:serv type "));
1091 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1092 (s->type & SV_TYPE_DOMAIN_ENUM))
1094 DEBUG(4,("s: dom mismatch "));
1098 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1103 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1104 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1108 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1109 s->name, s->type, s->comment, s->domain));
1111 s->server_added = True;
1116 DEBUG(4,("%20s %8x %25s %15s\n",
1117 s->name, s->type, s->comment, s->domain));
1126 /*******************************************************************
1127 fill in a server info structure
1128 ******************************************************************/
1129 static int fill_srv_info(struct srv_info_struct *service,
1130 int uLevel, char **buf, int *buflen,
1131 char **stringbuf, int *stringspace, char *baseaddr)
1140 case 0: struct_len = 16; break;
1141 case 1: struct_len = 26; break;
1151 len = strlen(service->comment)+1;
1155 if (buflen) *buflen = struct_len;
1156 if (stringspace) *stringspace = len;
1157 return struct_len + len;
1162 if (*buflen < struct_len) return -1;
1170 p2 = p + struct_len;
1171 l2 = *buflen - struct_len;
1173 if (!baseaddr) baseaddr = p;
1178 StrnCpy(p,service->name,15);
1182 StrnCpy(p,service->name,15);
1183 SIVAL(p,18,service->type);
1184 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1185 len += CopyAndAdvance(&p2,service->comment,&l2);
1191 *buf = p + struct_len;
1192 *buflen -= struct_len;
1205 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1207 return(strcmp(s1->name,s2->name));
1210 /****************************************************************************
1211 view list of servers available (or possibly domains). The info is
1212 extracted from lists saved by nmbd on the local host
1213 ****************************************************************************/
1214 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1215 int mdrcnt, int mprcnt, char **rdata,
1216 char **rparam, int *rdata_len, int *rparam_len)
1218 char *str1 = param+2;
1219 char *str2 = skip_string(str1,1);
1220 char *p = skip_string(str2,1);
1221 int uLevel = SVAL(p,0);
1222 int buf_len = SVAL(p,2);
1223 uint32 servertype = IVAL(p,4);
1225 int data_len, fixed_len, string_len;
1226 int f_len = 0, s_len = 0;
1227 struct srv_info_struct *servers=NULL;
1228 int counted=0,total=0;
1231 BOOL domain_request;
1234 /* If someone sets all the bits they don't really mean to set
1235 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1238 if (servertype == SV_TYPE_ALL)
1239 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1241 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1242 any other bit (they may just set this bit on it's own) they
1243 want all the locally seen servers. However this bit can be
1244 set on its own so set the requested servers to be
1245 ALL - DOMAIN_ENUM. */
1247 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1248 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1250 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1251 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1255 if (!prefix_ok(str1,"WrLehD")) return False;
1256 if (!check_server_info(uLevel,str2)) return False;
1258 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1259 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1260 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1262 if (strcmp(str1, "WrLehDz") == 0) {
1263 StrnCpy(domain, p, sizeof(fstring)-1);
1265 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1268 if (lp_browse_list())
1269 total = get_server_info(servertype,&servers,domain);
1271 data_len = fixed_len = string_len = 0;
1274 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1277 char *lastname=NULL;
1279 for (i=0;i<total;i++)
1281 struct srv_info_struct *s = &servers[i];
1282 if (lastname && strequal(lastname,s->name)) continue;
1284 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1285 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1286 s->name, s->type, s->comment, s->domain));
1288 if (data_len <= buf_len) {
1291 string_len += s_len;
1298 *rdata_len = fixed_len + string_len;
1299 *rdata = REALLOC(*rdata,*rdata_len);
1300 bzero(*rdata,*rdata_len);
1302 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1308 char *lastname=NULL;
1309 int count2 = counted;
1310 for (i = 0; i < total && count2;i++)
1312 struct srv_info_struct *s = &servers[i];
1313 if (lastname && strequal(lastname,s->name)) continue;
1315 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1316 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1317 s->name, s->type, s->comment, s->domain));
1323 *rparam = REALLOC(*rparam,*rparam_len);
1324 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1326 SSVAL(*rparam,4,counted);
1327 SSVAL(*rparam,6,counted+missed);
1329 if (servers) free(servers);
1331 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1332 domain,uLevel,counted,counted+missed));
1337 /****************************************************************************
1338 command 0x34 - suspected of being a "Lookup Names" stub api
1339 ****************************************************************************/
1340 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1341 int mdrcnt, int mprcnt, char **rdata,
1342 char **rparam, int *rdata_len, int *rparam_len)
1344 char *str1 = param+2;
1345 char *str2 = skip_string(str1,1);
1346 char *p = skip_string(str2,1);
1347 int uLevel = SVAL(p,0);
1348 int buf_len = SVAL(p,2);
1352 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1353 str1, str2, p, uLevel, buf_len));
1355 if (!prefix_ok(str1,"zWrLeh")) return False;
1361 *rparam = REALLOC(*rparam,*rparam_len);
1363 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1365 SSVAL(*rparam,4,counted);
1366 SSVAL(*rparam,6,counted+missed);
1371 /****************************************************************************
1372 get info about a share
1373 ****************************************************************************/
1374 static BOOL check_share_info(int uLevel, char* id)
1378 if (strcmp(id,"B13") != 0) return False;
1381 if (strcmp(id,"B13BWz") != 0) return False;
1384 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1387 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1389 default: return False;
1394 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1395 char** buf, int* buflen,
1396 char** stringbuf, int* stringspace, char* baseaddr)
1405 case 0: struct_len = 13; break;
1406 case 1: struct_len = 20; break;
1407 case 2: struct_len = 40; break;
1408 case 91: struct_len = 68; break;
1416 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1417 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1418 if (buflen) *buflen = struct_len;
1419 if (stringspace) *stringspace = len;
1420 return struct_len + len;
1425 if ((*buflen) < struct_len) return -1;
1433 p2 = p + struct_len;
1434 l2 = (*buflen) - struct_len;
1436 if (!baseaddr) baseaddr = p;
1438 StrnCpy(p,lp_servicename(snum),13);
1444 type = STYPE_DISKTREE;
1445 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1446 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1447 SSVAL(p,14,type); /* device type */
1448 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1449 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1454 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1455 SSVALS(p,22,-1); /* max uses */
1456 SSVAL(p,24,1); /* current uses */
1457 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1458 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1459 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1464 memset(p+40,0,SHPWLEN+2);
1476 (*buf) = p + struct_len;
1477 (*buflen) -= struct_len;
1479 (*stringspace) = l2;
1489 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1490 int mdrcnt,int mprcnt,
1491 char **rdata,char **rparam,
1492 int *rdata_len,int *rparam_len)
1494 char *str1 = param+2;
1495 char *str2 = skip_string(str1,1);
1496 char *netname = skip_string(str2,1);
1497 char *p = skip_string(netname,1);
1498 int uLevel = SVAL(p,0);
1499 int snum = find_service(netname);
1501 if (snum < 0) return False;
1503 /* check it's a supported varient */
1504 if (!prefix_ok(str1,"zWrLh")) return False;
1505 if (!check_share_info(uLevel,str2)) return False;
1507 *rdata = REALLOC(*rdata,mdrcnt);
1509 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1510 if (*rdata_len < 0) return False;
1513 *rparam = REALLOC(*rparam,*rparam_len);
1514 SSVAL(*rparam,0,NERR_Success);
1515 SSVAL(*rparam,2,0); /* converter word */
1516 SSVAL(*rparam,4,*rdata_len);
1521 /****************************************************************************
1522 view list of shares available
1523 ****************************************************************************/
1524 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1525 int mdrcnt,int mprcnt,
1526 char **rdata,char **rparam,
1527 int *rdata_len,int *rparam_len)
1529 char *str1 = param+2;
1530 char *str2 = skip_string(str1,1);
1531 char *p = skip_string(str2,1);
1532 int uLevel = SVAL(p,0);
1533 int buf_len = SVAL(p,2);
1535 int count=lp_numservices();
1536 int total=0,counted=0;
1537 BOOL missed = False;
1539 int data_len, fixed_len, string_len;
1540 int f_len = 0, s_len = 0;
1542 if (!prefix_ok(str1,"WrLeh")) return False;
1543 if (!check_share_info(uLevel,str2)) return False;
1545 data_len = fixed_len = string_len = 0;
1546 for (i=0;i<count;i++)
1547 if (lp_browseable(i) && lp_snum_ok(i))
1550 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1551 if (data_len <= buf_len)
1555 string_len += s_len;
1560 *rdata_len = fixed_len + string_len;
1561 *rdata = REALLOC(*rdata,*rdata_len);
1562 memset(*rdata,0,*rdata_len);
1564 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1568 for (i = 0; i < count;i++)
1569 if (lp_browseable(i) && lp_snum_ok(i))
1570 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1574 *rparam = REALLOC(*rparam,*rparam_len);
1575 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1577 SSVAL(*rparam,4,counted);
1578 SSVAL(*rparam,6,total);
1580 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1581 counted,total,uLevel,
1582 buf_len,*rdata_len,mdrcnt));
1588 /****************************************************************************
1589 get the time of day info
1590 ****************************************************************************/
1591 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1592 int mdrcnt,int mprcnt,
1593 char **rdata,char **rparam,
1594 int *rdata_len,int *rparam_len)
1598 *rparam = REALLOC(*rparam,*rparam_len);
1601 *rdata = REALLOC(*rdata,*rdata_len);
1603 SSVAL(*rparam,0,NERR_Success);
1604 SSVAL(*rparam,2,0); /* converter word */
1610 time_t unixdate = time(NULL);
1612 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1613 by NT in a "net time" operation,
1614 it seems to ignore the one below */
1616 /* the client expects to get localtime, not GMT, in this bit
1617 (I think, this needs testing) */
1618 t = LocalTime(&unixdate);
1620 SIVAL(p,4,0); /* msecs ? */
1621 CVAL(p,8) = t->tm_hour;
1622 CVAL(p,9) = t->tm_min;
1623 CVAL(p,10) = t->tm_sec;
1624 CVAL(p,11) = 0; /* hundredths of seconds */
1625 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1626 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1627 CVAL(p,16) = t->tm_mday;
1628 CVAL(p,17) = t->tm_mon + 1;
1629 SSVAL(p,18,1900+t->tm_year);
1630 CVAL(p,20) = t->tm_wday;
1637 /****************************************************************************
1638 set the user password
1639 ****************************************************************************/
1640 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1641 int mdrcnt,int mprcnt,
1642 char **rdata,char **rparam,
1643 int *rdata_len,int *rparam_len)
1645 char *p = skip_string(param+2,2);
1647 fstring pass1,pass2;
1651 p = skip_string(p,1);
1654 memcpy(pass2,p+16,16);
1657 *rparam = REALLOC(*rparam,*rparam_len);
1661 SSVAL(*rparam,0,NERR_badpass);
1662 SSVAL(*rparam,2,0); /* converter word */
1664 DEBUG(3,("Set password for <%s>\n",user));
1667 * Pass the user through the NT -> unix user mapping
1671 (void)map_username(user);
1674 * Do any UNIX username case mangling.
1676 (void)Get_Pwnam( user, True);
1679 * Attempt the plaintext password change first.
1680 * Older versions of Windows seem to do this.
1683 if (password_ok(user, pass1,strlen(pass1),NULL, NULL) &&
1684 chgpasswd(user,pass1,pass2,False))
1686 SSVAL(*rparam,0,NERR_Success);
1690 * If the plaintext change failed, attempt
1691 * the encrypted. NT will generate this
1692 * after trying the samr method.
1695 if(SVAL(*rparam,0) != NERR_Success)
1697 struct smb_passwd *sampw = NULL;
1699 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1700 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1702 SSVAL(*rparam,0,NERR_Success);
1706 bzero(pass1,sizeof(fstring));
1707 bzero(pass2,sizeof(fstring));
1712 /****************************************************************************
1713 Set the user password (SamOEM version - gets plaintext).
1714 ****************************************************************************/
1716 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1717 int mdrcnt,int mprcnt,
1718 char **rdata,char **rparam,
1719 int *rdata_len,int *rparam_len)
1722 char *p = param + 2;
1724 *rparam = REALLOC(*rparam,*rparam_len);
1728 SSVAL(*rparam,0,NERR_badpass);
1731 * Check the parameter definition is correct.
1733 if(!strequal(param + 2, "zsT")) {
1734 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1737 p = skip_string(p, 1);
1739 if(!strequal(p, "B516B16")) {
1740 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1743 p = skip_string(p,1);
1746 p = skip_string(p,1);
1748 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1751 * Pass the user through the NT -> unix user mapping
1755 (void)map_username(user);
1758 * Do any UNIX username case mangling.
1760 (void)Get_Pwnam( user, True);
1762 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1764 SSVAL(*rparam,0,NERR_Success);
1770 /****************************************************************************
1773 ****************************************************************************/
1774 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1775 int mdrcnt,int mprcnt,
1776 char **rdata,char **rparam,
1777 int *rdata_len,int *rparam_len)
1779 int function = SVAL(param,0);
1780 char *str1 = param+2;
1781 char *str2 = skip_string(str1,1);
1782 char *p = skip_string(str2,1);
1786 printjob_decode(SVAL(p,0), &snum, &jobid);
1788 /* check it's a supported varient */
1789 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1793 *rparam = REALLOC(*rparam,*rparam_len);
1797 SSVAL(*rparam,0,NERR_Success);
1799 if (snum >= 0 && VALID_SNUM(snum))
1801 print_queue_struct *queue=NULL;
1803 count = get_printqueue(snum,conn,&queue,NULL);
1805 for (i=0;i<count;i++)
1806 if ((queue[i].job&0xFF) == jobid)
1809 case 81: /* delete */
1810 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1811 del_printqueue(conn,snum,queue[i].job);
1813 case 82: /* pause */
1814 case 83: /* resume */
1815 DEBUG(3,("%s queue entry %d\n",
1816 (function==82?"pausing":"resuming"),queue[i].job));
1817 status_printjob(conn,snum,queue[i].job,
1818 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1825 SSVAL(*rparam,0,NERR_JobNotFound);
1827 if (queue) free(queue);
1830 SSVAL(*rparam,2,0); /* converter word */
1835 /****************************************************************************
1836 Purge a print queue - or pause or resume it.
1837 ****************************************************************************/
1838 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1839 int mdrcnt,int mprcnt,
1840 char **rdata,char **rparam,
1841 int *rdata_len,int *rparam_len)
1843 int function = SVAL(param,0);
1844 char *str1 = param+2;
1845 char *str2 = skip_string(str1,1);
1846 char *QueueName = skip_string(str2,1);
1849 /* check it's a supported varient */
1850 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1854 *rparam = REALLOC(*rparam,*rparam_len);
1858 SSVAL(*rparam,0,NERR_Success);
1859 SSVAL(*rparam,2,0); /* converter word */
1861 snum = lp_servicenumber(QueueName);
1862 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1863 int pnum = lp_servicenumber(PRINTERS_NAME);
1865 lp_add_printer(QueueName,pnum);
1866 snum = lp_servicenumber(QueueName);
1870 if (snum >= 0 && VALID_SNUM(snum)) {
1874 case 74: /* Pause queue */
1875 case 75: /* Resume queue */
1876 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1877 DEBUG(3,("Print queue %s, queue=%s\n",
1878 (function==74?"pause":"resume"),QueueName));
1880 case 103: /* Purge */
1882 print_queue_struct *queue=NULL;
1884 count = get_printqueue(snum,conn,&queue,NULL);
1885 for (i = 0; i < count; i++)
1886 del_printqueue(conn,snum,queue[i].job);
1888 if (queue) free(queue);
1889 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1899 /****************************************************************************
1900 set the property of a print job (undocumented?)
1901 ? function = 0xb -> set name of print job
1902 ? function = 0x6 -> move print job up/down
1903 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1904 or <WWsTP> <WB21BB16B10zWWzDDz>
1905 ****************************************************************************/
1906 static int check_printjob_info(struct pack_desc* desc,
1907 int uLevel, char* id)
1909 desc->subformat = NULL;
1911 case 0: desc->format = "W"; break;
1912 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1913 case 2: desc->format = "WWzWWDDzz"; break;
1914 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1915 default: return False;
1917 if (strcmp(desc->format,id) != 0) return False;
1921 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1922 int mdrcnt,int mprcnt,
1923 char **rdata,char **rparam,
1924 int *rdata_len,int *rparam_len)
1926 struct pack_desc desc;
1927 char *str1 = param+2;
1928 char *str2 = skip_string(str1,1);
1929 char *p = skip_string(str2,1);
1931 int uLevel = SVAL(p,2);
1932 int function = SVAL(p,4); /* what is this ?? */
1937 printjob_decode(SVAL(p,0), &snum, &jobid);
1940 *rparam = REALLOC(*rparam,*rparam_len);
1944 /* check it's a supported varient */
1945 if ((strcmp(str1,"WWsTP")) ||
1946 (!check_printjob_info(&desc,uLevel,str2)))
1950 case 0x6: /* change job place in the queue,
1951 data gives the new place */
1952 if (snum >= 0 && VALID_SNUM(snum)) {
1953 print_queue_struct *queue=NULL;
1957 count = get_printqueue(snum,conn,&queue,NULL);
1958 for (i=0;i<count;i++) /* find job */
1959 if ((queue[i].job&0xFF) == jobid) break;
1962 desc.errcode=NERR_JobNotFound;
1963 if (queue) free(queue);
1965 desc.errcode=NERR_Success;
1969 int place= SVAL(data,0);
1970 /* we currently have no way of
1971 doing this. Can any unix do it? */
1972 if (i < place) /* move down */;
1973 else if (i > place ) /* move up */;
1976 desc.errcode=NERR_notsupported; /* not yet
1978 if (queue) free(queue);
1981 desc.errcode=NERR_JobNotFound;
1985 case 0xb: /* change print job name, data gives the name */
1986 /* jobid, snum should be zero */
1987 if (isalpha((int)*s)) {
1990 while (l<64 && *s) {
1991 if (issafe(*s)) name[l++] = *s;
1996 DEBUG(3,("Setting print name to %s\n",name));
1998 fsp = file_find_print();
2001 connection_struct *fconn = fsp->conn;
2004 if (!become_user(fconn,vuid) ||
2005 !become_service(fconn,True))
2008 if (conn->vfs_ops.rename(dos_to_unix(fsp->fsp_name,False),name) == 0) {
2009 string_set(&fsp->fsp_name,name);
2014 desc.errcode=NERR_Success;
2017 default: /* not implemented */
2021 SSVALS(*rparam,0,desc.errcode);
2022 SSVAL(*rparam,2,0); /* converter word */
2028 /****************************************************************************
2029 get info about the server
2030 ****************************************************************************/
2031 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2032 int mdrcnt,int mprcnt,
2033 char **rdata,char **rparam,
2034 int *rdata_len,int *rparam_len)
2036 char *str1 = param+2;
2037 char *str2 = skip_string(str1,1);
2038 char *p = skip_string(str2,1);
2039 int uLevel = SVAL(p,0);
2043 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2045 /* check it's a supported varient */
2046 if (!prefix_ok(str1,"WrLh")) return False;
2049 if (strcmp(str2,"B16") != 0) return False;
2053 if (strcmp(str2,"B16BBDz") != 0) return False;
2057 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2062 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2067 if (strcmp(str2,"DN") != 0) return False;
2071 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2074 default: return False;
2077 *rdata_len = mdrcnt;
2078 *rdata = REALLOC(*rdata,*rdata_len);
2081 p2 = p + struct_len;
2083 StrnCpy(p,local_machine,16);
2089 struct srv_info_struct *servers=NULL;
2092 uint32 servertype= lp_default_server_announce();
2094 pstrcpy(comment,lp_serverstring());
2096 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2097 for (i=0;i<count;i++)
2098 if (strequal(servers[i].name,local_machine))
2100 servertype = servers[i].type;
2101 pstrcpy(comment,servers[i].comment);
2104 if (servers) free(servers);
2106 SCVAL(p,0,lp_major_announce_version());
2107 SCVAL(p,1,lp_minor_announce_version());
2108 SIVAL(p,2,servertype);
2110 if (mdrcnt == struct_len) {
2113 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2114 standard_sub(conn,comment);
2115 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2116 p2 = skip_string(p2,1);
2121 return False; /* not yet implemented */
2124 *rdata_len = PTR_DIFF(p2,*rdata);
2127 *rparam = REALLOC(*rparam,*rparam_len);
2128 SSVAL(*rparam,0,NERR_Success);
2129 SSVAL(*rparam,2,0); /* converter word */
2130 SSVAL(*rparam,4,*rdata_len);
2136 /****************************************************************************
2137 get info about the server
2138 ****************************************************************************/
2139 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2140 int mdrcnt,int mprcnt,
2141 char **rdata,char **rparam,
2142 int *rdata_len,int *rparam_len)
2144 char *str1 = param+2;
2145 char *str2 = skip_string(str1,1);
2146 char *p = skip_string(str2,1);
2148 extern pstring sesssetup_user;
2149 int level = SVAL(p,0);
2151 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2154 *rparam = REALLOC(*rparam,*rparam_len);
2156 /* check it's a supported varient */
2157 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2160 *rdata_len = mdrcnt + 1024;
2161 *rdata = REALLOC(*rdata,*rdata_len);
2163 SSVAL(*rparam,0,NERR_Success);
2164 SSVAL(*rparam,2,0); /* converter word */
2170 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2171 pstrcpy(p2,local_machine);
2173 p2 = skip_string(p2,1);
2176 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2177 pstrcpy(p2,sesssetup_user);
2178 p2 = skip_string(p2,1);
2181 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2182 pstrcpy(p2,global_myworkgroup);
2184 p2 = skip_string(p2,1);
2187 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2188 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2191 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2192 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2193 p2 = skip_string(p2,1);
2196 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2198 p2 = skip_string(p2,1);
2201 *rdata_len = PTR_DIFF(p2,*rdata);
2203 SSVAL(*rparam,4,*rdata_len);
2208 /****************************************************************************
2209 get info about a user
2211 struct user_info_11 {
2212 char usri11_name[21]; 0-20
2214 char *usri11_comment; 22-25
2215 char *usri11_usr_comment; 26-29
2216 unsigned short usri11_priv; 30-31
2217 unsigned long usri11_auth_flags; 32-35
2218 long usri11_password_age; 36-39
2219 char *usri11_homedir; 40-43
2220 char *usri11_parms; 44-47
2221 long usri11_last_logon; 48-51
2222 long usri11_last_logoff; 52-55
2223 unsigned short usri11_bad_pw_count; 56-57
2224 unsigned short usri11_num_logons; 58-59
2225 char *usri11_logon_server; 60-63
2226 unsigned short usri11_country_code; 64-65
2227 char *usri11_workstations; 66-69
2228 unsigned long usri11_max_storage; 70-73
2229 unsigned short usri11_units_per_week; 74-75
2230 unsigned char *usri11_logon_hours; 76-79
2231 unsigned short usri11_code_page; 80-81
2236 usri11_name specifies the user name for which information is retireved
2238 usri11_pad aligns the next data structure element to a word boundary
2240 usri11_comment is a null terminated ASCII comment
2242 usri11_user_comment is a null terminated ASCII comment about the user
2244 usri11_priv specifies the level of the privilege assigned to the user.
2245 The possible values are:
2247 Name Value Description
2248 USER_PRIV_GUEST 0 Guest privilege
2249 USER_PRIV_USER 1 User privilege
2250 USER_PRV_ADMIN 2 Administrator privilege
2252 usri11_auth_flags specifies the account operator privileges. The
2253 possible values are:
2255 Name Value Description
2256 AF_OP_PRINT 0 Print operator
2259 Leach, Naik [Page 28]
\r\f
2262 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2265 AF_OP_COMM 1 Communications operator
2266 AF_OP_SERVER 2 Server operator
2267 AF_OP_ACCOUNTS 3 Accounts operator
2270 usri11_password_age specifies how many seconds have elapsed since the
2271 password was last changed.
2273 usri11_home_dir points to a null terminated ASCII string that contains
2274 the path name of the user's home directory.
2276 usri11_parms points to a null terminated ASCII string that is set
2277 aside for use by applications.
2279 usri11_last_logon specifies the time when the user last logged on.
2280 This value is stored as the number of seconds elapsed since
2281 00:00:00, January 1, 1970.
2283 usri11_last_logoff specifies the time when the user last logged off.
2284 This value is stored as the number of seconds elapsed since
2285 00:00:00, January 1, 1970. A value of 0 means the last logoff
2288 usri11_bad_pw_count specifies the number of incorrect passwords
2289 entered since the last successful logon.
2291 usri11_log1_num_logons specifies the number of times this user has
2292 logged on. A value of -1 means the number of logons is unknown.
2294 usri11_logon_server points to a null terminated ASCII string that
2295 contains the name of the server to which logon requests are sent.
2296 A null string indicates logon requests should be sent to the
2299 usri11_country_code specifies the country code for the user's language
2302 usri11_workstations points to a null terminated ASCII string that
2303 contains the names of workstations the user may log on from.
2304 There may be up to 8 workstations, with the names separated by
2305 commas. A null strings indicates there are no restrictions.
2307 usri11_max_storage specifies the maximum amount of disk space the user
2308 can occupy. A value of 0xffffffff indicates there are no
2311 usri11_units_per_week specifies the equal number of time units into
2312 which a week is divided. This value must be equal to 168.
2314 usri11_logon_hours points to a 21 byte (168 bits) string that
2315 specifies the time during which the user can log on. Each bit
2316 represents one unique hour in a week. The first bit (bit 0, word
2317 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2321 Leach, Naik [Page 29]
\r\f
2324 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2327 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2328 are no restrictions.
2330 usri11_code_page specifies the code page for the user's language of
2333 All of the pointers in this data structure need to be treated
2334 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2335 to be ignored. The converter word returned in the parameters section
2336 needs to be subtracted from the lower 16 bits to calculate an offset
2337 into the return buffer where this ASCII string resides.
2339 There is no auxiliary data in the response.
2341 ****************************************************************************/
2343 #define usri11_name 0
2344 #define usri11_pad 21
2345 #define usri11_comment 22
2346 #define usri11_usr_comment 26
2347 #define usri11_full_name 30
2348 #define usri11_priv 34
2349 #define usri11_auth_flags 36
2350 #define usri11_password_age 40
2351 #define usri11_homedir 44
2352 #define usri11_parms 48
2353 #define usri11_last_logon 52
2354 #define usri11_last_logoff 56
2355 #define usri11_bad_pw_count 60
2356 #define usri11_num_logons 62
2357 #define usri11_logon_server 64
2358 #define usri11_country_code 68
2359 #define usri11_workstations 70
2360 #define usri11_max_storage 74
2361 #define usri11_units_per_week 78
2362 #define usri11_logon_hours 80
2363 #define usri11_code_page 84
2364 #define usri11_end 86
2366 #define USER_PRIV_GUEST 0
2367 #define USER_PRIV_USER 1
2368 #define USER_PRIV_ADMIN 2
2370 #define AF_OP_PRINT 0
2371 #define AF_OP_COMM 1
2372 #define AF_OP_SERVER 2
2373 #define AF_OP_ACCOUNTS 3
2376 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2377 int mdrcnt,int mprcnt,
2378 char **rdata,char **rparam,
2379 int *rdata_len,int *rparam_len)
2381 char *str1 = param+2;
2382 char *str2 = skip_string(str1,1);
2383 char *UserName = skip_string(str2,1);
2384 char *p = skip_string(UserName,1);
2385 int uLevel = SVAL(p,0);
2388 /* get NIS home of a previously validated user - simeon */
2389 /* With share level security vuid will always be zero.
2390 Don't depend on vuser being non-null !!. JRA */
2391 user_struct *vuser = get_valid_user_struct(vuid);
2393 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2396 *rparam = REALLOC(*rparam,*rparam_len);
2398 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2400 /* check it's a supported variant */
2401 if (strcmp(str1,"zWrLh") != 0) return False;
2404 case 0: p2 = "B21"; break;
2405 case 1: p2 = "B21BB16DWzzWz"; break;
2406 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2407 case 10: p2 = "B21Bzzz"; break;
2408 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2409 default: return False;
2412 if (strcmp(p2,str2) != 0) return False;
2414 *rdata_len = mdrcnt + 1024;
2415 *rdata = REALLOC(*rdata,*rdata_len);
2417 SSVAL(*rparam,0,NERR_Success);
2418 SSVAL(*rparam,2,0); /* converter word */
2421 p2 = p + usri11_end;
2424 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2428 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2433 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2434 pstrcpy(p2,"Comment");
2435 p2 = skip_string(p2,1);
2437 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2438 pstrcpy(p2,"UserComment");
2439 p2 = skip_string(p2,1);
2441 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2442 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2443 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2444 p2 = skip_string(p2,1);
2447 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2449 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2450 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2451 SIVALS(p,usri11_password_age,-1); /* password age */
2452 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2453 pstrcpy(p2, lp_logon_path());
2454 p2 = skip_string(p2,1);
2455 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2457 p2 = skip_string(p2,1);
2458 SIVAL(p,usri11_last_logon,0); /* last logon */
2459 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2460 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2461 SSVALS(p,usri11_num_logons,-1); /* num logons */
2462 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2463 pstrcpy(p2,"\\\\*");
2464 p2 = skip_string(p2,1);
2465 SSVAL(p,usri11_country_code,0); /* country code */
2467 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2469 p2 = skip_string(p2,1);
2471 SIVALS(p,usri11_max_storage,-1); /* max storage */
2472 SSVAL(p,usri11_units_per_week,168); /* units per week */
2473 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2475 /* a simple way to get logon hours at all times. */
2477 SCVAL(p2,21,0); /* fix zero termination */
2478 p2 = skip_string(p2,1);
2480 SSVAL(p,usri11_code_page,0); /* code page */
2482 if (uLevel == 1 || uLevel == 2)
2484 memset(p+22,' ',16); /* password */
2485 SIVALS(p,38,-1); /* password age */
2487 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2488 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2489 pstrcpy(p2,lp_logon_path());
2490 p2 = skip_string(p2,1);
2491 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2493 SSVAL(p,52,0); /* flags */
2494 SIVAL(p,54,0); /* script_path */
2497 SIVAL(p,60,0); /* auth_flags */
2498 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2499 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2500 p2 = skip_string(p2,1);
2501 SIVAL(p,68,0); /* urs_comment */
2502 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2504 p2 = skip_string(p2,1);
2505 SIVAL(p,76,0); /* workstations */
2506 SIVAL(p,80,0); /* last_logon */
2507 SIVAL(p,84,0); /* last_logoff */
2508 SIVALS(p,88,-1); /* acct_expires */
2509 SIVALS(p,92,-1); /* max_storage */
2510 SSVAL(p,96,168); /* units_per_week */
2511 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2514 SSVALS(p,102,-1); /* bad_pw_count */
2515 SSVALS(p,104,-1); /* num_logons */
2516 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2517 pstrcpy(p2,"\\\\%L");
2518 standard_sub_basic(p2);
2519 p2 = skip_string(p2,1);
2520 SSVAL(p,110,49); /* country_code */
2521 SSVAL(p,112,860); /* code page */
2525 *rdata_len = PTR_DIFF(p2,*rdata);
2527 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2532 /*******************************************************************
2533 get groups that a user is a member of
2534 ******************************************************************/
2535 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2536 int mdrcnt,int mprcnt,
2537 char **rdata,char **rparam,
2538 int *rdata_len,int *rparam_len)
2540 char *str1 = param+2;
2541 char *str2 = skip_string(str1,1);
2542 char *UserName = skip_string(str2,1);
2543 char *p = skip_string(UserName,1);
2544 int uLevel = SVAL(p,0);
2549 *rparam = REALLOC(*rparam,*rparam_len);
2551 /* check it's a supported varient */
2552 if (strcmp(str1,"zWrLeh") != 0) return False;
2554 case 0: p2 = "B21"; break;
2555 default: return False;
2557 if (strcmp(p2,str2) != 0) return False;
2559 *rdata_len = mdrcnt + 1024;
2560 *rdata = REALLOC(*rdata,*rdata_len);
2562 SSVAL(*rparam,0,NERR_Success);
2563 SSVAL(*rparam,2,0); /* converter word */
2567 /* XXXX we need a real SAM database some day */
2568 pstrcpy(p,"Users"); p += 21; count++;
2569 pstrcpy(p,"Domain Users"); p += 21; count++;
2570 pstrcpy(p,"Guests"); p += 21; count++;
2571 pstrcpy(p,"Domain Guests"); p += 21; count++;
2573 *rdata_len = PTR_DIFF(p,*rdata);
2575 SSVAL(*rparam,4,count); /* is this right?? */
2576 SSVAL(*rparam,6,count); /* is this right?? */
2582 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2583 int mdrcnt,int mprcnt,
2584 char **rdata,char **rparam,
2585 int *rdata_len,int *rparam_len)
2587 char *str1 = param+2;
2588 char *str2 = skip_string(str1,1);
2589 char *p = skip_string(str2,1);
2591 struct pack_desc desc;
2598 bzero(&desc,sizeof(desc));
2600 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2602 /* check it's a supported varient */
2603 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2604 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2605 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2607 desc.buflen = mdrcnt;
2608 desc.subformat = NULL;
2611 if (init_package(&desc,1,0))
2613 PACKI(&desc,"W",0); /* code */
2614 PACKS(&desc,"B21",name); /* eff. name */
2615 PACKS(&desc,"B",""); /* pad */
2617 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2618 PACKI(&desc,"D",0); /* auth flags XXX */
2619 PACKI(&desc,"W",0); /* num logons */
2620 PACKI(&desc,"W",0); /* bad pw count */
2621 PACKI(&desc,"D",0); /* last logon */
2622 PACKI(&desc,"D",-1); /* last logoff */
2623 PACKI(&desc,"D",-1); /* logoff time */
2624 PACKI(&desc,"D",-1); /* kickoff time */
2625 PACKI(&desc,"D",0); /* password age */
2626 PACKI(&desc,"D",0); /* password can change */
2627 PACKI(&desc,"D",-1); /* password must change */
2630 fstrcpy(mypath,"\\\\");
2631 fstrcat(mypath,local_machine);
2633 PACKS(&desc,"z",mypath); /* computer */
2635 PACKS(&desc,"z",global_myworkgroup);/* domain */
2637 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2638 /* made sure all macros are fully substituted and available */
2639 logon_script = lp_logon_script();
2640 standard_sub( conn, logon_script );
2641 PACKS(&desc,"z", logon_script); /* script path */
2642 /* End of JHT mods */
2644 PACKI(&desc,"D",0x00000000); /* reserved */
2647 *rdata_len = desc.usedlen;
2649 *rparam = REALLOC(*rparam,*rparam_len);
2650 SSVALS(*rparam,0,desc.errcode);
2652 SSVAL(*rparam,4,desc.neededlen);
2654 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2659 /****************************************************************************
2660 api_WAccessGetUserPerms
2661 ****************************************************************************/
2662 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2663 int mdrcnt,int mprcnt,
2664 char **rdata,char **rparam,
2665 int *rdata_len,int *rparam_len)
2667 char *str1 = param+2;
2668 char *str2 = skip_string(str1,1);
2669 char *user = skip_string(str2,1);
2670 char *resource = skip_string(user,1);
2672 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2674 /* check it's a supported varient */
2675 if (strcmp(str1,"zzh") != 0) return False;
2676 if (strcmp(str2,"") != 0) return False;
2679 *rparam = REALLOC(*rparam,*rparam_len);
2680 SSVALS(*rparam,0,0); /* errorcode */
2681 SSVAL(*rparam,2,0); /* converter word */
2682 SSVAL(*rparam,4,0x7f); /* permission flags */
2687 /****************************************************************************
2688 api_WPrintJobEnumerate
2689 ****************************************************************************/
2690 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2691 int mdrcnt,int mprcnt,
2692 char **rdata,char **rparam,
2693 int *rdata_len,int *rparam_len)
2695 char *str1 = param+2;
2696 char *str2 = skip_string(str1,1);
2697 char *p = skip_string(str2,1);
2703 struct pack_desc desc;
2704 print_queue_struct *queue=NULL;
2705 print_status_struct status;
2709 bzero(&desc,sizeof(desc));
2710 bzero(&status,sizeof(status));
2712 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2714 /* check it's a supported varient */
2715 if (strcmp(str1,"WWrLh") != 0) return False;
2716 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2718 printjob_decode(SVAL(p,0), &snum, &job);
2720 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2722 count = get_printqueue(snum,conn,&queue,&status);
2723 for (i = 0; i < count; i++) {
2724 if ((queue[i].job & 0xFF) == job) break;
2726 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2728 desc.buflen = mdrcnt;
2730 if (init_package(&desc,1,0)) {
2732 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2733 *rdata_len = desc.usedlen;
2736 desc.errcode = NERR_JobNotFound;
2742 *rparam = REALLOC(*rparam,*rparam_len);
2743 SSVALS(*rparam,0,desc.errcode);
2745 SSVAL(*rparam,4,desc.neededlen);
2747 if (queue) free(queue);
2749 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2753 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2754 int mdrcnt,int mprcnt,
2755 char **rdata,char **rparam,
2756 int *rdata_len,int *rparam_len)
2758 char *str1 = param+2;
2759 char *str2 = skip_string(str1,1);
2760 char *p = skip_string(str2,1);
2766 struct pack_desc desc;
2767 print_queue_struct *queue=NULL;
2768 print_status_struct status;
2770 bzero(&desc,sizeof(desc));
2771 bzero(&status,sizeof(status));
2773 p = skip_string(p,1);
2776 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2778 /* check it's a supported varient */
2779 if (strcmp(str1,"zWrLeh") != 0) return False;
2780 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2781 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2783 snum = lp_servicenumber(name);
2784 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2785 int pnum = lp_servicenumber(PRINTERS_NAME);
2787 lp_add_printer(name,pnum);
2788 snum = lp_servicenumber(name);
2792 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2794 count = get_printqueue(snum,conn,&queue,&status);
2795 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2797 desc.buflen = mdrcnt;
2799 if (init_package(&desc,count,0)) {
2801 for (i = 0; i < count; i++) {
2802 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2803 if (desc.errcode == NERR_Success) succnt = i+1;
2807 *rdata_len = desc.usedlen;
2810 *rparam = REALLOC(*rparam,*rparam_len);
2811 SSVALS(*rparam,0,desc.errcode);
2813 SSVAL(*rparam,4,succnt);
2814 SSVAL(*rparam,6,count);
2816 if (queue) free(queue);
2818 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2822 static int check_printdest_info(struct pack_desc* desc,
2823 int uLevel, char* id)
2825 desc->subformat = NULL;
2827 case 0: desc->format = "B9"; break;
2828 case 1: desc->format = "B9B21WWzW"; break;
2829 case 2: desc->format = "z"; break;
2830 case 3: desc->format = "zzzWWzzzWW"; break;
2831 default: return False;
2833 if (strcmp(desc->format,id) != 0) return False;
2837 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2838 struct pack_desc* desc)
2841 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2842 buf[sizeof(buf)-1] = 0;
2845 PACKS(desc,"B9",buf); /* szName */
2847 PACKS(desc,"B21",""); /* szUserName */
2848 PACKI(desc,"W",0); /* uJobId */
2849 PACKI(desc,"W",0); /* fsStatus */
2850 PACKS(desc,"z",""); /* pszStatus */
2851 PACKI(desc,"W",0); /* time */
2854 if (uLevel == 2 || uLevel == 3) {
2855 PACKS(desc,"z",buf); /* pszPrinterName */
2857 PACKS(desc,"z",""); /* pszUserName */
2858 PACKS(desc,"z",""); /* pszLogAddr */
2859 PACKI(desc,"W",0); /* uJobId */
2860 PACKI(desc,"W",0); /* fsStatus */
2861 PACKS(desc,"z",""); /* pszStatus */
2862 PACKS(desc,"z",""); /* pszComment */
2863 PACKS(desc,"z","NULL"); /* pszDrivers */
2864 PACKI(desc,"W",0); /* time */
2865 PACKI(desc,"W",0); /* pad1 */
2870 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2871 int mdrcnt,int mprcnt,
2872 char **rdata,char **rparam,
2873 int *rdata_len,int *rparam_len)
2875 char *str1 = param+2;
2876 char *str2 = skip_string(str1,1);
2877 char *p = skip_string(str2,1);
2878 char* PrinterName = p;
2880 struct pack_desc desc;
2883 bzero(&desc,sizeof(desc));
2885 p = skip_string(p,1);
2888 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2890 /* check it's a supported varient */
2891 if (strcmp(str1,"zWrLh") != 0) return False;
2892 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2894 snum = lp_servicenumber(PrinterName);
2895 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2896 int pnum = lp_servicenumber(PRINTERS_NAME);
2898 lp_add_printer(PrinterName,pnum);
2899 snum = lp_servicenumber(PrinterName);
2905 desc.errcode = NERR_DestNotFound;
2909 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2911 desc.buflen = mdrcnt;
2912 if (init_package(&desc,1,0)) {
2913 fill_printdest_info(conn,snum,uLevel,&desc);
2915 *rdata_len = desc.usedlen;
2919 *rparam = REALLOC(*rparam,*rparam_len);
2920 SSVALS(*rparam,0,desc.errcode);
2922 SSVAL(*rparam,4,desc.neededlen);
2924 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2928 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2929 int mdrcnt,int mprcnt,
2930 char **rdata,char **rparam,
2931 int *rdata_len,int *rparam_len)
2933 char *str1 = param+2;
2934 char *str2 = skip_string(str1,1);
2935 char *p = skip_string(str2,1);
2939 struct pack_desc desc;
2940 int services = lp_numservices();
2942 bzero(&desc,sizeof(desc));
2946 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2948 /* check it's a supported varient */
2949 if (strcmp(str1,"WrLeh") != 0) return False;
2950 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2953 for (i = 0; i < services; i++)
2954 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2957 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2959 desc.buflen = mdrcnt;
2960 if (init_package(&desc,queuecnt,0)) {
2963 for (i = 0; i < services; i++) {
2964 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2965 fill_printdest_info(conn,i,uLevel,&desc);
2967 if (desc.errcode == NERR_Success) succnt = n;
2972 *rdata_len = desc.usedlen;
2975 *rparam = REALLOC(*rparam,*rparam_len);
2976 SSVALS(*rparam,0,desc.errcode);
2978 SSVAL(*rparam,4,succnt);
2979 SSVAL(*rparam,6,queuecnt);
2981 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2985 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2986 int mdrcnt,int mprcnt,
2987 char **rdata,char **rparam,
2988 int *rdata_len,int *rparam_len)
2990 char *str1 = param+2;
2991 char *str2 = skip_string(str1,1);
2992 char *p = skip_string(str2,1);
2995 struct pack_desc desc;
2997 bzero(&desc,sizeof(desc));
3001 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3003 /* check it's a supported varient */
3004 if (strcmp(str1,"WrLeh") != 0) return False;
3005 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3007 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3009 desc.buflen = mdrcnt;
3010 if (init_package(&desc,1,0)) {
3011 PACKS(&desc,"B41","NULL");
3014 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3016 *rdata_len = desc.usedlen;
3019 *rparam = REALLOC(*rparam,*rparam_len);
3020 SSVALS(*rparam,0,desc.errcode);
3022 SSVAL(*rparam,4,succnt);
3025 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3029 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3030 int mdrcnt,int mprcnt,
3031 char **rdata,char **rparam,
3032 int *rdata_len,int *rparam_len)
3034 char *str1 = param+2;
3035 char *str2 = skip_string(str1,1);
3036 char *p = skip_string(str2,1);
3039 struct pack_desc desc;
3041 bzero(&desc,sizeof(desc));
3045 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3047 /* check it's a supported varient */
3048 if (strcmp(str1,"WrLeh") != 0) return False;
3049 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3051 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3053 desc.buflen = mdrcnt;
3055 if (init_package(&desc,1,0)) {
3056 PACKS(&desc,"B13","lpd");
3059 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3061 *rdata_len = desc.usedlen;
3064 *rparam = REALLOC(*rparam,*rparam_len);
3065 SSVALS(*rparam,0,desc.errcode);
3067 SSVAL(*rparam,4,succnt);
3070 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3074 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3075 int mdrcnt,int mprcnt,
3076 char **rdata,char **rparam,
3077 int *rdata_len,int *rparam_len)
3079 char *str1 = param+2;
3080 char *str2 = skip_string(str1,1);
3081 char *p = skip_string(str2,1);
3084 struct pack_desc desc;
3086 bzero(&desc,sizeof(desc));
3090 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3092 /* check it's a supported varient */
3093 if (strcmp(str1,"WrLeh") != 0) return False;
3094 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3096 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3097 bzero(&desc,sizeof(desc));
3099 desc.buflen = mdrcnt;
3101 if (init_package(&desc,1,0)) {
3102 PACKS(&desc,"B13","lp0");
3105 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3107 *rdata_len = desc.usedlen;
3110 *rparam = REALLOC(*rparam,*rparam_len);
3111 SSVALS(*rparam,0,desc.errcode);
3113 SSVAL(*rparam,4,succnt);
3116 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3120 static void api_rpc_trans_reply(char *outbuf,
3123 send_trans_reply(outbuf, p->rsmb_pdu.data, NULL, NULL, 0, p->file_offset);
3125 if (mem_buf_len(p->rsmb_pdu.data) <= p->file_offset)
3127 /* all of data was sent: no need to wait for SMBreadX calls */
3128 mem_free_data(p->rsmb_pdu.data);
3132 /****************************************************************************
3133 WaitNamedPipeHandleState
3134 ****************************************************************************/
3135 static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param)
3139 if (!param) return False;
3141 priority = param[0] + (param[1] << 8);
3142 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
3144 if (wait_rpc_pipe_hnd_state(p, priority))
3146 /* now send the reply */
3147 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3155 /****************************************************************************
3156 SetNamedPipeHandleState
3157 ****************************************************************************/
3158 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3162 if (!param) return False;
3164 id = param[0] + (param[1] << 8);
3165 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
3167 if (set_rpc_pipe_hnd_state(p, id))
3169 /* now send the reply */
3170 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3178 /****************************************************************************
3179 when no reply is generated, indicate unsupported.
3180 ****************************************************************************/
3181 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3183 struct mem_buf rparam;
3185 mem_init(&rparam, 0);
3186 mem_alloc_data(&rparam, 4);
3188 rparam.offset.start = 0;
3189 rparam.offset.end = 4;
3192 SSVAL(rparam.data,0,NERR_notsupported);
3193 SSVAL(rparam.data,2,0); /* converter word */
3195 DEBUG(3,("Unsupported API fd command\n"));
3197 /* now send the reply */
3198 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3200 mem_free_data(&rparam);
3205 /****************************************************************************
3206 handle remote api calls delivered to a named pipe already opened.
3207 ****************************************************************************/
3208 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3209 uint16 *setup,char *data,char *params,
3210 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3216 pipes_struct *p = NULL;
3218 DEBUG(5,("api_fd_reply\n"));
3220 /* First find out the name of this file. */
3223 DEBUG(0,("Unexpected named pipe transaction.\n"));
3227 /* Get the file handle and hence the file name. */
3229 subcommand = setup[0];
3230 p = get_rpc_pipe(pnum);
3234 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3235 subcommand, p->name, pnum));
3237 /* record maximum data length that can be transmitted in an SMBtrans */
3238 p->file_offset = mdrcnt;
3239 p->prev_pdu_file_offset = 0;
3241 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3242 p, p->file_offset));
3248 reply = rpc_to_smb(p, data, tdscnt);
3251 api_rpc_trans_reply(outbuf, p);
3257 /* Wait Named Pipe Handle state */
3258 reply = api_WNPHS(outbuf, p, params);
3263 /* Set Named Pipe Handle state */
3264 reply = api_SNPHS(outbuf, p, params);
3271 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3276 return api_no_reply(outbuf, mdrcnt);
3281 /****************************************************************************
3282 the buffer was too small
3283 ****************************************************************************/
3284 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3285 int mdrcnt,int mprcnt,
3286 char **rdata,char **rparam,
3287 int *rdata_len,int *rparam_len)
3289 *rparam_len = MIN(*rparam_len,mprcnt);
3290 *rparam = REALLOC(*rparam,*rparam_len);
3294 SSVAL(*rparam,0,NERR_BufTooSmall);
3296 DEBUG(3,("Supplied buffer too small in API command\n"));
3302 /****************************************************************************
3303 the request is not supported
3304 ****************************************************************************/
3305 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3306 int mdrcnt,int mprcnt,
3307 char **rdata,char **rparam,
3308 int *rdata_len,int *rparam_len)
3311 *rparam = REALLOC(*rparam,*rparam_len);
3315 SSVAL(*rparam,0,NERR_notsupported);
3316 SSVAL(*rparam,2,0); /* converter word */
3318 DEBUG(3,("Unsupported API command\n"));
3330 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3331 int,int,char **,char **,int *,int *);
3333 } api_commands[] = {
3334 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3335 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3336 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3337 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3338 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3339 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3340 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3341 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3342 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3343 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3344 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3345 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3346 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3347 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3348 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3349 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3350 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3351 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3352 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3353 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3354 {"NetServerEnum", 104, api_RNetServerEnum,0},
3355 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3356 {"SetUserPassword", 115, api_SetUserPassword,0},
3357 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3358 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3359 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3360 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3361 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3362 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3363 {NULL, -1, api_Unsupported,0}};
3366 /****************************************************************************
3367 handle remote api calls
3368 ****************************************************************************/
3369 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3370 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3373 struct mem_buf rdata_buf;
3374 struct mem_buf rparam_buf;
3376 char *rparam = NULL;
3382 SMB_ASSERT(params != 0);
3384 api_command = SVAL(params,0);
3386 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3389 skip_string(params+2,1),
3390 tdscnt,tpscnt,mdrcnt,mprcnt));
3392 for (i=0;api_commands[i].name;i++)
3393 if (api_commands[i].id == api_command && api_commands[i].fn)
3395 DEBUG(3,("Doing %s\n",api_commands[i].name));
3399 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3400 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3402 if(!rdata || !rparam) {
3403 DEBUG(0,("api_reply: malloc fail !\n"));
3407 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3408 &rdata,&rparam,&rdata_len,&rparam_len);
3411 if (rdata_len > mdrcnt ||
3412 rparam_len > mprcnt)
3414 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3415 &rdata,&rparam,&rdata_len,&rparam_len);
3419 /* if we get False back then it's actually unsupported */
3421 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3422 &rdata,&rparam,&rdata_len,&rparam_len);
3425 mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False);
3426 mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False);
3428 /* now send the reply */
3429 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3431 if (rdata ) free(rdata);
3432 if (rparam) free(rparam);
3437 /****************************************************************************
3438 handle named pipe commands
3439 ****************************************************************************/
3440 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3441 uint16 *setup,char *data,char *params,
3442 int suwcnt,int tdscnt,int tpscnt,
3443 int msrcnt,int mdrcnt,int mprcnt)
3445 DEBUG(3,("named pipe command on <%s> name\n", name));
3447 if (strequal(name,"LANMAN"))
3449 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3452 if (strequal(name,"WKSSVC") ||
3453 strequal(name,"SRVSVC") ||
3454 strequal(name,"WINREG") ||
3455 strequal(name,"SAMR") ||
3456 strequal(name,"LSARPC"))
3458 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3459 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3462 if (strlen(name) < 1)
3464 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3469 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3476 /****************************************************************************
3478 ****************************************************************************/
3479 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3482 int name_offset = 0;
3483 char *data=NULL,*params=NULL;
3486 uint16 vuid = SVAL(inbuf,smb_uid);
3487 int tpscnt = SVAL(inbuf,smb_vwv0);
3488 int tdscnt = SVAL(inbuf,smb_vwv1);
3489 int mprcnt = SVAL(inbuf,smb_vwv2);
3490 int mdrcnt = SVAL(inbuf,smb_vwv3);
3491 int msrcnt = CVAL(inbuf,smb_vwv4);
3492 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3493 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3494 int pscnt = SVAL(inbuf,smb_vwv9);
3495 int psoff = SVAL(inbuf,smb_vwv10);
3496 int dscnt = SVAL(inbuf,smb_vwv11);
3497 int dsoff = SVAL(inbuf,smb_vwv12);
3498 int suwcnt = CVAL(inbuf,smb_vwv13);
3500 bzero(name, sizeof(name));
3501 fstrcpy(name,smb_buf(inbuf));
3503 if (dscnt > tdscnt || pscnt > tpscnt) {
3504 exit_server("invalid trans parameters\n");
3508 if((data = (char *)malloc(tdscnt)) == NULL) {
3509 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
3510 return(ERROR(ERRDOS,ERRnomem));
3512 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3516 if((params = (char *)malloc(tpscnt)) == NULL) {
3517 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
3518 return(ERROR(ERRDOS,ERRnomem));
3520 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3525 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
3526 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16)));
3527 return(ERROR(ERRDOS,ERRnomem));
3529 for (i=0;i<suwcnt;i++)
3530 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3534 if (pscnt < tpscnt || dscnt < tdscnt) {
3535 /* We need to send an interim response then receive the rest
3536 of the parameter/data bytes */
3537 outsize = set_message(outbuf,0,0,True);
3539 send_smb(Client,outbuf);
3542 /* receive the rest of the trans packet */
3543 while (pscnt < tpscnt || dscnt < tdscnt) {
3545 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3547 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3549 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3551 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3553 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3554 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3556 if (params) free(params);
3557 if (data) free(data);
3558 if (setup) free(setup);
3559 return(ERROR(ERRSRV,ERRerror));
3564 tpscnt = SVAL(inbuf,smb_vwv0);
3565 tdscnt = SVAL(inbuf,smb_vwv1);
3567 pcnt = SVAL(inbuf,smb_vwv2);
3568 poff = SVAL(inbuf,smb_vwv3);
3569 pdisp = SVAL(inbuf,smb_vwv4);
3571 dcnt = SVAL(inbuf,smb_vwv5);
3572 doff = SVAL(inbuf,smb_vwv6);
3573 ddisp = SVAL(inbuf,smb_vwv7);
3578 if (dscnt > tdscnt || pscnt > tpscnt) {
3579 exit_server("invalid trans parameters\n");
3583 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3585 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3589 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3590 name,tdscnt,tpscnt,suwcnt));
3593 * WinCE wierdness....
3596 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine,
3597 strlen(local_machine)) == 0)) {
3598 name_offset = strlen(local_machine)+1;
3601 if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3602 DEBUG(5,("calling named_pipe\n"));
3603 outsize = named_pipe(conn,vuid,outbuf,
3604 name+name_offset+strlen("\\PIPE\\"),setup,data,params,
3605 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3607 DEBUG(3,("invalid pipe name\n"));
3612 if (data) free(data);
3613 if (params) free(params);
3614 if (setup) free(setup);
3616 if (close_on_completion)
3617 close_cnum(conn,vuid);
3623 return(ERROR(ERRSRV,ERRnosupport));