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;
65 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
66 int mdrcnt,int mprcnt,
67 char **rdata,char **rparam,
68 int *rdata_len,int *rparam_len);
69 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
70 int mdrcnt,int mprcnt,
71 char **rdata,char **rparam,
72 int *rdata_len,int *rparam_len);
75 static int CopyExpanded(connection_struct *conn,
76 int snum, char** dst, char* src, int* n)
81 if (!src || !dst || !n || !(*dst)) return(0);
83 StrnCpy(buf,src,sizeof(buf)/2);
84 string_sub(buf,"%S",lp_servicename(snum));
85 standard_sub(conn,buf);
93 static int CopyAndAdvance(char** dst, char* src, int* n)
96 if (!src || !dst || !n || !(*dst)) return(0);
104 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
108 StrnCpy(buf,s,sizeof(buf)/2);
109 string_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(conn,buf);
111 return strlen(buf) + 1;
114 static char* Expand(connection_struct *conn, int snum, char* s)
117 if (!s) return(NULL);
118 StrnCpy(buf,s,sizeof(buf)/2);
119 string_sub(buf,"%S",lp_servicename(snum));
120 standard_sub(conn,buf);
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL prefix_ok(char *str,char *prefix)
129 return(strncmp(str,prefix,strlen(prefix)) == 0);
132 /*******************************************************************
133 copies parameters and data, as needed, into the smb buffer
135 *both* the data and params sections should be aligned. this
136 is fudged in the rpc pipes by
137 at present, only the data section is. this may be a possible
138 cause of some of the ipc problems being experienced. lkcl26dec97
140 ******************************************************************/
141 static void copy_trans_params_and_data(char *outbuf, int align,
142 struct mem_buf *rparam, struct mem_buf *rdata,
143 int param_offset, int data_offset,
144 int param_len, int data_len)
146 char *copy_into = smb_buf(outbuf)+1;
148 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
149 param_offset, param_offset + param_len,
150 data_offset , data_offset + data_len));
152 if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
153 copy_into += param_len + align;
154 if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
157 /****************************************************************************
159 ****************************************************************************/
160 static void send_trans_reply(char *outbuf,
161 struct mem_buf *rdata,
162 struct mem_buf *rparam,
163 uint16 *setup, int lsetup, int max_data_ret)
166 int this_ldata,this_lparam;
167 int tot_data=0,tot_param=0;
170 int ldata = rdata ? mem_buf_len(rdata ) : 0;
171 int lparam = rparam ? mem_buf_len(rparam) : 0;
173 BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
175 if (buffer_too_large)
177 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
178 ldata = max_data_ret;
181 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
182 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
184 align = ((this_lparam)%4);
186 set_message(outbuf,10+lsetup,1+align+this_ldata+this_lparam,True);
188 if (buffer_too_large)
191 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
192 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
193 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
195 SCVAL(outbuf, smb_rcls, ERRDOS);
196 SSVAL(outbuf, smb_err, ERRmoredata);
199 copy_trans_params_and_data(outbuf, align,
201 tot_param , tot_data,
202 this_lparam, this_ldata);
204 SSVAL(outbuf,smb_vwv0,lparam);
205 SSVAL(outbuf,smb_vwv1,ldata);
206 SSVAL(outbuf,smb_vwv3,this_lparam);
207 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
208 SSVAL(outbuf,smb_vwv5,0);
209 SSVAL(outbuf,smb_vwv6,this_ldata);
210 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
211 SSVAL(outbuf,smb_vwv8,0);
212 SSVAL(outbuf,smb_vwv9,lsetup);
214 for (i=0;i<lsetup;i++)
216 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
220 send_smb(Client,outbuf);
222 tot_data = this_ldata;
223 tot_param = this_lparam;
225 while (tot_data < ldata || tot_param < lparam)
227 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
228 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
230 align = (this_lparam%4);
232 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
234 copy_trans_params_and_data(outbuf, align,
236 tot_param , tot_data,
237 this_lparam, this_ldata);
239 SSVAL(outbuf,smb_vwv3,this_lparam);
240 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
241 SSVAL(outbuf,smb_vwv5,tot_param);
242 SSVAL(outbuf,smb_vwv6,this_ldata);
243 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
244 SSVAL(outbuf,smb_vwv8,tot_data);
245 SSVAL(outbuf,smb_vwv9,0);
248 send_smb(Client,outbuf);
250 tot_data += this_ldata;
251 tot_param += this_lparam;
256 char* format; /* formatstring for structure */
257 char* subformat; /* subformat for structure */
258 char* base; /* baseaddress of buffer */
259 int buflen; /* remaining size for fixed part; on init: length of base */
260 int subcount; /* count of substructures */
261 char* structbuf; /* pointer into buffer for remaining fixed part */
262 int stringlen; /* remaining size for variable part */
263 char* stringbuf; /* pointer into buffer for remaining variable part */
264 int neededlen; /* total needed size */
265 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
266 char* curpos; /* current position; pointer into format or subformat */
270 static int get_counter(char** p)
273 if (!p || !(*p)) return(1);
274 if (!isdigit((int)**p)) return 1;
278 n = 10 * n + (i - '0');
285 static int getlen(char* p)
291 case 'W': /* word (2 byte) */
294 case 'N': /* count of substructures (word) at end */
297 case 'D': /* double word (4 byte) */
298 case 'z': /* offset to zero terminated string (4 byte) */
299 case 'l': /* offset to user data (4 byte) */
302 case 'b': /* offset to data (with counter) (4 byte) */
306 case 'B': /* byte (with optional counter) */
307 n += get_counter(&p);
314 static BOOL init_package(struct pack_desc* p, int count, int subcount)
319 if (!p->format || !p->base) return(False);
321 i = count * getlen(p->format);
322 if (p->subformat) i += subcount * getlen(p->subformat);
323 p->structbuf = p->base;
327 p->curpos = p->format;
331 p->errcode = ERRmoredata;
334 p->errcode = NERR_Success;
337 p->stringbuf = p->base + i;
339 return(p->errcode == NERR_Success);
343 static int package(struct pack_desc* p, ...)
346 static int package(va_alist)
352 int needed=0, stringneeded;
354 int is_string=0, stringused;
361 p = va_arg(args,struct pack_desc *);
366 p->curpos = p->format;
368 p->curpos = p->subformat;
373 str = va_arg(args,char*);
374 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
378 if (!p->curpos) return(0);
380 switch( *p->curpos++ ) {
381 case 'W': /* word (2 byte) */
383 temp = va_arg(args,int);
384 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
386 case 'N': /* count of substructures (word) at end */
388 p->subcount = va_arg(args,int);
389 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
391 case 'D': /* double word (4 byte) */
393 temp = va_arg(args,int);
394 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
396 case 'B': /* byte (with optional counter) */
397 needed = get_counter(&p->curpos);
399 char *s = va_arg(args,char*);
400 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
403 case 'z': /* offset to zero terminated string (4 byte) */
404 str = va_arg(args,char*);
405 stringneeded = (str ? strlen(str)+1 : 0);
408 case 'l': /* offset to user data (4 byte) */
409 str = va_arg(args,char*);
410 stringneeded = va_arg(args,int);
413 case 'b': /* offset to data (with counter) (4 byte) */
414 str = va_arg(args,char*);
415 stringneeded = get_counter(&p->curpos);
420 if (stringneeded >= 0) {
422 if (p->buflen >= needed) {
423 stringused = stringneeded;
424 if (stringused > p->stringlen) {
425 stringused = (is_string ? p->stringlen : 0);
426 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
429 SIVAL(p->structbuf,0,0);
431 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
432 memcpy(p->stringbuf,str?str:"",stringused);
433 if (is_string) p->stringbuf[stringused-1] = '\0';
434 p->stringbuf += stringused;
435 p->stringlen -= stringused;
436 p->usedlen += stringused;
439 p->neededlen += stringneeded;
441 p->neededlen += needed;
442 if (p->buflen >= needed) {
443 p->structbuf += needed;
445 p->usedlen += needed;
448 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
454 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
455 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
457 #define PACK(desc,t,v) package(desc,v)
458 #define PACKl(desc,t,v,l) package(desc,v,l)
461 static void PACKI(struct pack_desc* desc,char *t,int v)
466 static void PACKS(struct pack_desc* desc,char *t,char *v)
472 /****************************************************************************
474 ****************************************************************************/
476 static void PackDriverData(struct pack_desc* desc)
478 char drivdata[4+4+32];
479 SIVAL(drivdata,0,sizeof drivdata); /* cb */
480 SIVAL(drivdata,4,1000); /* lVersion */
481 memset(drivdata+8,0,32); /* szDeviceName */
482 pstrcpy(drivdata+8,"NULL");
483 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
486 static int check_printq_info(struct pack_desc* desc,
487 int uLevel, char *id1, char *id2)
489 desc->subformat = NULL;
492 desc->format = "B13";
495 desc->format = "B13BWWWzzzzzWW";
498 desc->format = "B13BWWWzzzzzWN";
499 desc->subformat = "WB21BB16B10zWWzDDz";
502 desc->format = "zWWWWzzzzWWzzl";
505 desc->format = "zWWWWzzzzWNzzl";
506 desc->subformat = "WWzWWDDzz";
512 desc->format = "WzzzzzzzzN";
513 desc->subformat = "z";
515 default: return False;
517 if (strcmp(desc->format,id1) != 0) return False;
518 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
522 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
523 struct pack_desc* desc,
524 print_queue_struct* queue, int n)
526 time_t t = queue->time;
528 /* the client expects localtime */
531 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
533 PACKS(desc,"B21",queue->user); /* szUserName */
534 PACKS(desc,"B",""); /* pad */
535 PACKS(desc,"B16",""); /* szNotifyName */
536 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
537 PACKS(desc,"z",""); /* pszParms */
538 PACKI(desc,"W",n+1); /* uPosition */
539 PACKI(desc,"W",queue->status); /* fsStatus */
540 PACKS(desc,"z",""); /* pszStatus */
541 PACKI(desc,"D",t); /* ulSubmitted */
542 PACKI(desc,"D",queue->size); /* ulSize */
543 PACKS(desc,"z",queue->file); /* pszComment */
545 if (uLevel == 2 || uLevel == 3) {
546 PACKI(desc,"W",queue->priority); /* uPriority */
547 PACKS(desc,"z",queue->user); /* pszUserName */
548 PACKI(desc,"W",n+1); /* uPosition */
549 PACKI(desc,"W",queue->status); /* fsStatus */
550 PACKI(desc,"D",t); /* ulSubmitted */
551 PACKI(desc,"D",queue->size); /* ulSize */
552 PACKS(desc,"z","Samba"); /* pszComment */
553 PACKS(desc,"z",queue->file); /* pszDocument */
555 PACKS(desc,"z",""); /* pszNotifyName */
556 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
557 PACKS(desc,"z",""); /* pszParms */
558 PACKS(desc,"z",""); /* pszStatus */
559 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
560 PACKS(desc,"z","lpd"); /* pszQProcName */
561 PACKS(desc,"z",""); /* pszQProcParms */
562 PACKS(desc,"z","NULL"); /* pszDriverName */
563 PackDriverData(desc); /* pDriverData */
564 PACKS(desc,"z",""); /* pszPrinterName */
569 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
570 struct pack_desc* desc,
571 int count, print_queue_struct* queue,
572 print_status_struct* status)
577 PACKS(desc,"B13",SERVICE(snum));
582 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
586 if (uLevel == 1 || uLevel == 2) {
587 PACKS(desc,"B",""); /* alignment */
588 PACKI(desc,"W",5); /* priority */
589 PACKI(desc,"W",0); /* start time */
590 PACKI(desc,"W",0); /* until time */
591 PACKS(desc,"z",""); /* pSepFile */
592 PACKS(desc,"z","lpd"); /* pPrProc */
593 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
594 PACKS(desc,"z",""); /* pParms */
596 PACKS(desc,"z","UNKNOWN PRINTER");
597 PACKI(desc,"W",LPSTAT_ERROR);
599 else if (!status || !status->message[0]) {
600 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
601 PACKI(desc,"W",LPSTAT_OK); /* status */
603 PACKS(desc,"z",status->message);
604 PACKI(desc,"W",status->status); /* status */
606 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
608 if (uLevel == 3 || uLevel == 4) {
609 PACKI(desc,"W",5); /* uPriority */
610 PACKI(desc,"W",0); /* uStarttime */
611 PACKI(desc,"W",0); /* uUntiltime */
612 PACKI(desc,"W",5); /* pad1 */
613 PACKS(desc,"z",""); /* pszSepFile */
614 PACKS(desc,"z","WinPrint"); /* pszPrProc */
615 PACKS(desc,"z",""); /* pszParms */
616 if (!status || !status->message[0]) {
617 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
618 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
620 PACKS(desc,"z",status->message); /* pszComment */
621 PACKI(desc,"W",status->status); /* fsStatus */
623 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
624 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
625 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
626 PackDriverData(desc); /* pDriverData */
628 if (uLevel == 2 || uLevel == 4) {
630 for (i=0;i<count;i++)
631 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
636 pstring tok,driver,datafile,langmon,helpfile,datatype;
641 pstrcpy(fname,lp_driverfile());
642 f=sys_fopen(fname,"r");
644 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
645 desc->errcode=NERR_notsupported;
649 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
650 DEBUG(0,("fill_printq_info: malloc fail !\n"));
651 desc->errcode=NERR_notsupported;
656 bzero(p, 8192*sizeof(char));
659 /* lookup the long printer driver name in the file description */
660 while (f && !feof(f) && !ok)
662 p = q; /* reset string pointer */
665 if (next_token(&p,tok,":",sizeof(tok)) &&
666 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
667 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
672 /* driver file name */
673 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
675 if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
677 * for the next tokens - which may be empty - I have to check for empty
678 * tokens first because the next_token function will skip all empty
686 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
690 /* language monitor */
694 } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0;
697 /* default data type */
698 if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0;
701 PACKI(desc,"W",0x0400); /* don't know */
702 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
703 PACKS(desc,"z",driver); /* Driverfile Name */
704 PACKS(desc,"z",datafile); /* Datafile name */
705 PACKS(desc,"z",langmon); /* language monitor */
706 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
707 PACKS(desc,"z",datatype); /* default data type */
708 PACKS(desc,"z",helpfile); /* helpfile name */
709 PACKS(desc,"z",driver); /* driver name */
710 DEBUG(3,("Driver:%s:\n",driver));
711 DEBUG(3,("Data File:%s:\n",datafile));
712 DEBUG(3,("Language Monitor:%s:\n",langmon));
713 DEBUG(3,("Data Type:%s:\n",datatype));
714 DEBUG(3,("Help File:%s:\n",helpfile));
715 PACKI(desc,"N",count); /* number of files to copy */
716 for (i=0;i<count;i++)
718 /* no need to check return value here - it was already tested in
719 * get_printerdrivernumber
721 next_token(&p,tok,",",sizeof(tok));
722 PACKS(desc,"z",tok); /* driver files to copy */
723 DEBUG(3,("file:%s:\n",tok));
726 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
727 SERVICE(snum),count));
729 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
730 desc->errcode=NERR_notsupported;
736 /* This function returns the number of files for a given driver */
737 static int get_printerdrivernumber(int snum)
745 pstrcpy(fname,lp_driverfile());
747 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
748 f=sys_fopen(fname,"r");
750 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
754 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
755 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
760 q=p; /* need it to free memory because p change ! */
762 /* lookup the long printer driver name in the file description */
763 while (!feof(f) && !ok)
765 p = q; /* reset string pointer */
767 if (next_token(&p,tok,":",sizeof(tok)) &&
768 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
777 if (*p++ == ':') i--;
782 /* count the number of files */
783 while (next_token(&p,tok,",",sizeof(tok)))
791 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
792 uint16 vuid, char *param,char *data,
793 int mdrcnt,int mprcnt,
794 char **rdata,char **rparam,
795 int *rdata_len,int *rparam_len)
797 char *str1 = param+2;
798 char *str2 = skip_string(str1,1);
799 char *p = skip_string(str2,1);
805 struct pack_desc desc;
806 print_queue_struct *queue=NULL;
807 print_status_struct status;
809 bzero(&status,sizeof(status));
810 bzero(&desc,sizeof(desc));
812 p = skip_string(p,1);
816 /* remove any trailing username */
817 if ((p = strchr(QueueName,'%'))) *p = 0;
819 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
821 /* check it's a supported varient */
822 if (!prefix_ok(str1,"zWrLh")) return False;
823 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
825 snum = lp_servicenumber(QueueName);
826 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
827 int pnum = lp_servicenumber(PRINTERS_NAME);
829 lp_add_printer(QueueName,pnum);
830 snum = lp_servicenumber(QueueName);
834 if (snum < 0 || !VALID_SNUM(snum)) return(False);
837 count = get_printerdrivernumber(snum);
838 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
840 count = get_printqueue(snum, conn,&queue,&status);
843 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
845 desc.buflen = mdrcnt;
846 if (init_package(&desc,1,count)) {
847 desc.subcount = count;
848 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
849 } else if(uLevel == 0) {
851 * This is a *disgusting* hack.
852 * This is *so* bad that even I'm embarrassed (and I
853 * have no shame). Here's the deal :
854 * Until we get the correct SPOOLSS code into smbd
855 * then when we're running with NT SMB support then
856 * NT makes this call with a level of zero, and then
857 * immediately follows it with an open request to
858 * the \\SRVSVC pipe. If we allow that open to
859 * succeed then NT barfs when it cannot open the
860 * \\SPOOLSS pipe immediately after and continually
861 * whines saying "Printer name is invalid" forever
862 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
863 * to fail, then NT downgrades to using the downlevel code
864 * and everything works as well as before. I hate
865 * myself for adding this code.... JRA.
868 fail_next_srvsvc_open();
871 *rdata_len = desc.usedlen;
874 *rparam = REALLOC(*rparam,*rparam_len);
875 SSVALS(*rparam,0,desc.errcode);
877 SSVAL(*rparam,4,desc.neededlen);
879 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
881 if (queue) free(queue);
887 /****************************************************************************
888 view list of all print jobs on all queues
889 ****************************************************************************/
890 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
891 int mdrcnt, int mprcnt,
892 char **rdata, char** rparam,
893 int *rdata_len, int *rparam_len)
895 char *param_format = param+2;
896 char *output_format1 = skip_string(param_format,1);
897 char *p = skip_string(output_format1,1);
898 int uLevel = SVAL(p,0);
899 char *output_format2 = p + 4;
900 int services = lp_numservices();
902 struct pack_desc desc;
903 print_queue_struct **queue = NULL;
904 print_status_struct *status = NULL;
905 int* subcntarr = NULL;
906 int queuecnt, subcnt=0, succnt=0;
908 bzero(&desc,sizeof(desc));
910 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
912 if (!prefix_ok(param_format,"WrLeh")) return False;
913 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
916 for (i = 0; i < services; i++)
917 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
920 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
921 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
924 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
925 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
926 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
929 memset(status,0,queuecnt*sizeof(print_status_struct));
930 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
931 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
936 for (i = 0; i < services; i++)
937 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
938 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
939 subcnt += subcntarr[n];
943 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
945 desc.buflen = mdrcnt;
947 if (init_package(&desc,queuecnt,subcnt)) {
950 for (i = 0; i < services; i++)
951 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
952 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
954 if (desc.errcode == NERR_Success) succnt = n;
958 if (subcntarr) free(subcntarr);
960 *rdata_len = desc.usedlen;
962 *rparam = REALLOC(*rparam,*rparam_len);
963 SSVALS(*rparam,0,desc.errcode);
965 SSVAL(*rparam,4,succnt);
966 SSVAL(*rparam,6,queuecnt);
968 for (i = 0; i < queuecnt; i++) {
969 if (queue && queue[i]) free(queue[i]);
972 if (queue) free(queue);
973 if (status) free(status);
978 /****************************************************************************
979 get info level for a server list query
980 ****************************************************************************/
981 static BOOL check_server_info(int uLevel, char* id)
985 if (strcmp(id,"B16") != 0) return False;
988 if (strcmp(id,"B16BBDz") != 0) return False;
996 struct srv_info_struct
1006 /*******************************************************************
1007 get server info lists from the files saved by nmbd. Return the
1009 ******************************************************************/
1010 static int get_server_info(uint32 servertype,
1011 struct srv_info_struct **servers,
1019 BOOL local_list_only;
1021 pstrcpy(fname,lp_lockdir());
1022 trim_string(fname,NULL,"/");
1024 pstrcat(fname,SERVER_LIST);
1026 f = sys_fopen(fname,"r");
1029 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1033 /* request for everything is code for request all servers */
1034 if (servertype == SV_TYPE_ALL)
1035 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1037 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1039 DEBUG(4,("Servertype search: %8x\n",servertype));
1044 struct srv_info_struct *s;
1049 fgets(line,sizeof(line)-1,f);
1050 if (!*line) continue;
1052 if (count == alloced) {
1054 (*servers) = (struct srv_info_struct *)
1055 Realloc(*servers,sizeof(**servers)*alloced);
1056 if (!(*servers)) return(0);
1057 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1059 s = &(*servers)[count];
1061 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1062 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1063 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1064 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1065 /* this allows us to cope with an old nmbd */
1066 pstrcpy(s->domain,global_myworkgroup);
1069 if (sscanf(stype,"%X",&s->type) != 1) {
1070 DEBUG(4,("r:host file "));
1074 /* Filter the servers/domains we return based on what was asked for. */
1076 /* Check to see if we are being asked for a local list only. */
1077 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1078 DEBUG(4,("r: local list only"));
1082 /* doesn't match up: don't want it */
1083 if (!(servertype & s->type)) {
1084 DEBUG(4,("r:serv type "));
1088 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1089 (s->type & SV_TYPE_DOMAIN_ENUM))
1091 DEBUG(4,("s: dom mismatch "));
1095 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1100 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1101 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1105 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1106 s->name, s->type, s->comment, s->domain));
1108 s->server_added = True;
1113 DEBUG(4,("%20s %8x %25s %15s\n",
1114 s->name, s->type, s->comment, s->domain));
1123 /*******************************************************************
1124 fill in a server info structure
1125 ******************************************************************/
1126 static int fill_srv_info(struct srv_info_struct *service,
1127 int uLevel, char **buf, int *buflen,
1128 char **stringbuf, int *stringspace, char *baseaddr)
1137 case 0: struct_len = 16; break;
1138 case 1: struct_len = 26; break;
1148 len = strlen(service->comment)+1;
1152 if (buflen) *buflen = struct_len;
1153 if (stringspace) *stringspace = len;
1154 return struct_len + len;
1159 if (*buflen < struct_len) return -1;
1167 p2 = p + struct_len;
1168 l2 = *buflen - struct_len;
1170 if (!baseaddr) baseaddr = p;
1175 StrnCpy(p,service->name,15);
1179 StrnCpy(p,service->name,15);
1180 SIVAL(p,18,service->type);
1181 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1182 len += CopyAndAdvance(&p2,service->comment,&l2);
1188 *buf = p + struct_len;
1189 *buflen -= struct_len;
1202 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1204 return(strcmp(s1->name,s2->name));
1207 /****************************************************************************
1208 view list of servers available (or possibly domains). The info is
1209 extracted from lists saved by nmbd on the local host
1210 ****************************************************************************/
1211 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1212 int mdrcnt, int mprcnt, char **rdata,
1213 char **rparam, int *rdata_len, int *rparam_len)
1215 char *str1 = param+2;
1216 char *str2 = skip_string(str1,1);
1217 char *p = skip_string(str2,1);
1218 int uLevel = SVAL(p,0);
1219 int buf_len = SVAL(p,2);
1220 uint32 servertype = IVAL(p,4);
1222 int data_len, fixed_len, string_len;
1223 int f_len = 0, s_len = 0;
1224 struct srv_info_struct *servers=NULL;
1225 int counted=0,total=0;
1228 BOOL domain_request;
1231 /* If someone sets all the bits they don't really mean to set
1232 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1235 if (servertype == SV_TYPE_ALL)
1236 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1238 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1239 any other bit (they may just set this bit on it's own) they
1240 want all the locally seen servers. However this bit can be
1241 set on its own so set the requested servers to be
1242 ALL - DOMAIN_ENUM. */
1244 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1245 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1247 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1248 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1252 if (!prefix_ok(str1,"WrLehD")) return False;
1253 if (!check_server_info(uLevel,str2)) return False;
1255 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1256 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1257 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1259 if (strcmp(str1, "WrLehDz") == 0) {
1260 StrnCpy(domain, p, sizeof(fstring)-1);
1262 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1265 if (lp_browse_list())
1266 total = get_server_info(servertype,&servers,domain);
1268 data_len = fixed_len = string_len = 0;
1271 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1274 char *lastname=NULL;
1276 for (i=0;i<total;i++)
1278 struct srv_info_struct *s = &servers[i];
1279 if (lastname && strequal(lastname,s->name)) continue;
1281 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1282 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1283 s->name, s->type, s->comment, s->domain));
1285 if (data_len <= buf_len) {
1288 string_len += s_len;
1295 *rdata_len = fixed_len + string_len;
1296 *rdata = REALLOC(*rdata,*rdata_len);
1297 bzero(*rdata,*rdata_len);
1299 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1305 char *lastname=NULL;
1306 int count2 = counted;
1307 for (i = 0; i < total && count2;i++)
1309 struct srv_info_struct *s = &servers[i];
1310 if (lastname && strequal(lastname,s->name)) continue;
1312 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1313 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1314 s->name, s->type, s->comment, s->domain));
1320 *rparam = REALLOC(*rparam,*rparam_len);
1321 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1323 SSVAL(*rparam,4,counted);
1324 SSVAL(*rparam,6,counted+missed);
1326 if (servers) free(servers);
1328 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1329 domain,uLevel,counted,counted+missed));
1334 /****************************************************************************
1335 command 0x34 - suspected of being a "Lookup Names" stub api
1336 ****************************************************************************/
1337 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1338 int mdrcnt, int mprcnt, char **rdata,
1339 char **rparam, int *rdata_len, int *rparam_len)
1341 char *str1 = param+2;
1342 char *str2 = skip_string(str1,1);
1343 char *p = skip_string(str2,1);
1344 int uLevel = SVAL(p,0);
1345 int buf_len = SVAL(p,2);
1349 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1350 str1, str2, p, uLevel, buf_len));
1352 if (!prefix_ok(str1,"zWrLeh")) return False;
1358 *rparam = REALLOC(*rparam,*rparam_len);
1360 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1362 SSVAL(*rparam,4,counted);
1363 SSVAL(*rparam,6,counted+missed);
1368 /****************************************************************************
1369 get info about a share
1370 ****************************************************************************/
1371 static BOOL check_share_info(int uLevel, char* id)
1375 if (strcmp(id,"B13") != 0) return False;
1378 if (strcmp(id,"B13BWz") != 0) return False;
1381 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1384 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1386 default: return False;
1391 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1392 char** buf, int* buflen,
1393 char** stringbuf, int* stringspace, char* baseaddr)
1402 case 0: struct_len = 13; break;
1403 case 1: struct_len = 20; break;
1404 case 2: struct_len = 40; break;
1405 case 91: struct_len = 68; break;
1413 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1414 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1415 if (buflen) *buflen = struct_len;
1416 if (stringspace) *stringspace = len;
1417 return struct_len + len;
1422 if ((*buflen) < struct_len) return -1;
1430 p2 = p + struct_len;
1431 l2 = (*buflen) - struct_len;
1433 if (!baseaddr) baseaddr = p;
1435 StrnCpy(p,lp_servicename(snum),13);
1441 type = STYPE_DISKTREE;
1442 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1443 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1444 SSVAL(p,14,type); /* device type */
1445 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1446 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1451 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1452 SSVALS(p,22,-1); /* max uses */
1453 SSVAL(p,24,1); /* current uses */
1454 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1455 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1456 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1461 memset(p+40,0,SHPWLEN+2);
1473 (*buf) = p + struct_len;
1474 (*buflen) -= struct_len;
1476 (*stringspace) = l2;
1486 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1487 int mdrcnt,int mprcnt,
1488 char **rdata,char **rparam,
1489 int *rdata_len,int *rparam_len)
1491 char *str1 = param+2;
1492 char *str2 = skip_string(str1,1);
1493 char *netname = skip_string(str2,1);
1494 char *p = skip_string(netname,1);
1495 int uLevel = SVAL(p,0);
1496 int snum = find_service(netname);
1498 if (snum < 0) return False;
1500 /* check it's a supported varient */
1501 if (!prefix_ok(str1,"zWrLh")) return False;
1502 if (!check_share_info(uLevel,str2)) return False;
1504 *rdata = REALLOC(*rdata,mdrcnt);
1506 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1507 if (*rdata_len < 0) return False;
1510 *rparam = REALLOC(*rparam,*rparam_len);
1511 SSVAL(*rparam,0,NERR_Success);
1512 SSVAL(*rparam,2,0); /* converter word */
1513 SSVAL(*rparam,4,*rdata_len);
1518 /****************************************************************************
1519 view list of shares available
1520 ****************************************************************************/
1521 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1522 int mdrcnt,int mprcnt,
1523 char **rdata,char **rparam,
1524 int *rdata_len,int *rparam_len)
1526 char *str1 = param+2;
1527 char *str2 = skip_string(str1,1);
1528 char *p = skip_string(str2,1);
1529 int uLevel = SVAL(p,0);
1530 int buf_len = SVAL(p,2);
1532 int count=lp_numservices();
1533 int total=0,counted=0;
1534 BOOL missed = False;
1536 int data_len, fixed_len, string_len;
1537 int f_len = 0, s_len = 0;
1539 if (!prefix_ok(str1,"WrLeh")) return False;
1540 if (!check_share_info(uLevel,str2)) return False;
1542 data_len = fixed_len = string_len = 0;
1543 for (i=0;i<count;i++)
1544 if (lp_browseable(i) && lp_snum_ok(i))
1547 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1548 if (data_len <= buf_len)
1552 string_len += s_len;
1557 *rdata_len = fixed_len + string_len;
1558 *rdata = REALLOC(*rdata,*rdata_len);
1559 memset(*rdata,0,*rdata_len);
1561 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1565 for (i = 0; i < count;i++)
1566 if (lp_browseable(i) && lp_snum_ok(i))
1567 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1571 *rparam = REALLOC(*rparam,*rparam_len);
1572 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1574 SSVAL(*rparam,4,counted);
1575 SSVAL(*rparam,6,total);
1577 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1578 counted,total,uLevel,
1579 buf_len,*rdata_len,mdrcnt));
1585 /****************************************************************************
1586 get the time of day info
1587 ****************************************************************************/
1588 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1589 int mdrcnt,int mprcnt,
1590 char **rdata,char **rparam,
1591 int *rdata_len,int *rparam_len)
1595 *rparam = REALLOC(*rparam,*rparam_len);
1598 *rdata = REALLOC(*rdata,*rdata_len);
1600 SSVAL(*rparam,0,NERR_Success);
1601 SSVAL(*rparam,2,0); /* converter word */
1607 time_t unixdate = time(NULL);
1609 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1610 by NT in a "net time" operation,
1611 it seems to ignore the one below */
1613 /* the client expects to get localtime, not GMT, in this bit
1614 (I think, this needs testing) */
1615 t = LocalTime(&unixdate);
1617 SIVAL(p,4,0); /* msecs ? */
1618 CVAL(p,8) = t->tm_hour;
1619 CVAL(p,9) = t->tm_min;
1620 CVAL(p,10) = t->tm_sec;
1621 CVAL(p,11) = 0; /* hundredths of seconds */
1622 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1623 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1624 CVAL(p,16) = t->tm_mday;
1625 CVAL(p,17) = t->tm_mon + 1;
1626 SSVAL(p,18,1900+t->tm_year);
1627 CVAL(p,20) = t->tm_wday;
1634 /****************************************************************************
1635 set the user password
1636 ****************************************************************************/
1637 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1638 int mdrcnt,int mprcnt,
1639 char **rdata,char **rparam,
1640 int *rdata_len,int *rparam_len)
1642 char *p = skip_string(param+2,2);
1644 fstring pass1,pass2;
1648 p = skip_string(p,1);
1651 memcpy(pass2,p+16,16);
1654 *rparam = REALLOC(*rparam,*rparam_len);
1658 SSVAL(*rparam,0,NERR_badpass);
1659 SSVAL(*rparam,2,0); /* converter word */
1661 DEBUG(3,("Set password for <%s>\n",user));
1664 * Pass the user through the NT -> unix user mapping
1668 (void)map_username(user);
1671 * Do any UNIX username case mangling.
1673 (void)Get_Pwnam( user, True);
1676 * Attempt the plaintext password change first.
1677 * Older versions of Windows seem to do this.
1680 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1681 chgpasswd(user,pass1,pass2,False))
1683 SSVAL(*rparam,0,NERR_Success);
1687 * If the plaintext change failed, attempt
1688 * the encrypted. NT will generate this
1689 * after trying the samr method.
1692 if(SVAL(*rparam,0) != NERR_Success)
1694 struct smb_passwd *sampw = NULL;
1696 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1697 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1699 SSVAL(*rparam,0,NERR_Success);
1703 bzero(pass1,sizeof(fstring));
1704 bzero(pass2,sizeof(fstring));
1709 /****************************************************************************
1710 Set the user password (SamOEM version - gets plaintext).
1711 ****************************************************************************/
1713 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1714 int mdrcnt,int mprcnt,
1715 char **rdata,char **rparam,
1716 int *rdata_len,int *rparam_len)
1719 char *p = param + 2;
1721 *rparam = REALLOC(*rparam,*rparam_len);
1725 SSVAL(*rparam,0,NERR_badpass);
1728 * Check the parameter definition is correct.
1730 if(!strequal(param + 2, "zsT")) {
1731 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1734 p = skip_string(p, 1);
1736 if(!strequal(p, "B516B16")) {
1737 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1740 p = skip_string(p,1);
1743 p = skip_string(p,1);
1745 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1748 * Pass the user through the NT -> unix user mapping
1752 (void)map_username(user);
1755 * Do any UNIX username case mangling.
1757 (void)Get_Pwnam( user, True);
1759 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1761 SSVAL(*rparam,0,NERR_Success);
1767 /****************************************************************************
1770 ****************************************************************************/
1771 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1772 int mdrcnt,int mprcnt,
1773 char **rdata,char **rparam,
1774 int *rdata_len,int *rparam_len)
1776 int function = SVAL(param,0);
1777 char *str1 = param+2;
1778 char *str2 = skip_string(str1,1);
1779 char *p = skip_string(str2,1);
1783 printjob_decode(SVAL(p,0), &snum, &jobid);
1785 /* check it's a supported varient */
1786 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1790 *rparam = REALLOC(*rparam,*rparam_len);
1794 SSVAL(*rparam,0,NERR_Success);
1796 if (snum >= 0 && VALID_SNUM(snum))
1798 print_queue_struct *queue=NULL;
1800 count = get_printqueue(snum,conn,&queue,NULL);
1802 for (i=0;i<count;i++)
1803 if ((queue[i].job&0xFF) == jobid)
1806 case 81: /* delete */
1807 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1808 del_printqueue(conn,snum,queue[i].job);
1810 case 82: /* pause */
1811 case 83: /* resume */
1812 DEBUG(3,("%s queue entry %d\n",
1813 (function==82?"pausing":"resuming"),queue[i].job));
1814 status_printjob(conn,snum,queue[i].job,
1815 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1822 SSVAL(*rparam,0,NERR_JobNotFound);
1824 if (queue) free(queue);
1827 SSVAL(*rparam,2,0); /* converter word */
1832 /****************************************************************************
1833 Purge a print queue - or pause or resume it.
1834 ****************************************************************************/
1835 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1836 int mdrcnt,int mprcnt,
1837 char **rdata,char **rparam,
1838 int *rdata_len,int *rparam_len)
1840 int function = SVAL(param,0);
1841 char *str1 = param+2;
1842 char *str2 = skip_string(str1,1);
1843 char *QueueName = skip_string(str2,1);
1846 /* check it's a supported varient */
1847 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1851 *rparam = REALLOC(*rparam,*rparam_len);
1855 SSVAL(*rparam,0,NERR_Success);
1856 SSVAL(*rparam,2,0); /* converter word */
1858 snum = lp_servicenumber(QueueName);
1859 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1860 int pnum = lp_servicenumber(PRINTERS_NAME);
1862 lp_add_printer(QueueName,pnum);
1863 snum = lp_servicenumber(QueueName);
1867 if (snum >= 0 && VALID_SNUM(snum)) {
1871 case 74: /* Pause queue */
1872 case 75: /* Resume queue */
1873 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1874 DEBUG(3,("Print queue %s, queue=%s\n",
1875 (function==74?"pause":"resume"),QueueName));
1877 case 103: /* Purge */
1879 print_queue_struct *queue=NULL;
1881 count = get_printqueue(snum,conn,&queue,NULL);
1882 for (i = 0; i < count; i++)
1883 del_printqueue(conn,snum,queue[i].job);
1885 if (queue) free(queue);
1886 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1896 /****************************************************************************
1897 set the property of a print job (undocumented?)
1898 ? function = 0xb -> set name of print job
1899 ? function = 0x6 -> move print job up/down
1900 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1901 or <WWsTP> <WB21BB16B10zWWzDDz>
1902 ****************************************************************************/
1903 static int check_printjob_info(struct pack_desc* desc,
1904 int uLevel, char* id)
1906 desc->subformat = NULL;
1908 case 0: desc->format = "W"; break;
1909 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1910 case 2: desc->format = "WWzWWDDzz"; break;
1911 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1912 default: return False;
1914 if (strcmp(desc->format,id) != 0) return False;
1918 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1919 int mdrcnt,int mprcnt,
1920 char **rdata,char **rparam,
1921 int *rdata_len,int *rparam_len)
1923 struct pack_desc desc;
1924 char *str1 = param+2;
1925 char *str2 = skip_string(str1,1);
1926 char *p = skip_string(str2,1);
1928 int uLevel = SVAL(p,2);
1929 int function = SVAL(p,4); /* what is this ?? */
1934 printjob_decode(SVAL(p,0), &snum, &jobid);
1937 *rparam = REALLOC(*rparam,*rparam_len);
1941 /* check it's a supported varient */
1942 if ((strcmp(str1,"WWsTP")) ||
1943 (!check_printjob_info(&desc,uLevel,str2)))
1947 case 0x6: /* change job place in the queue,
1948 data gives the new place */
1949 if (snum >= 0 && VALID_SNUM(snum)) {
1950 print_queue_struct *queue=NULL;
1954 count = get_printqueue(snum,conn,&queue,NULL);
1955 for (i=0;i<count;i++) /* find job */
1956 if ((queue[i].job&0xFF) == jobid) break;
1959 desc.errcode=NERR_JobNotFound;
1960 if (queue) free(queue);
1962 desc.errcode=NERR_Success;
1966 int place= SVAL(data,0);
1967 /* we currently have no way of
1968 doing this. Can any unix do it? */
1969 if (i < place) /* move down */;
1970 else if (i > place ) /* move up */;
1973 desc.errcode=NERR_notsupported; /* not yet
1975 if (queue) free(queue);
1978 desc.errcode=NERR_JobNotFound;
1982 case 0xb: /* change print job name, data gives the name */
1983 /* jobid, snum should be zero */
1984 if (isalpha((int)*s)) {
1987 while (l<64 && *s) {
1988 if (issafe(*s)) name[l++] = *s;
1993 DEBUG(3,("Setting print name to %s\n",name));
1995 fsp = file_find_print();
1998 connection_struct *fconn = fsp->conn;
2001 if (!become_user(fconn,vuid) ||
2002 !become_service(fconn,True))
2005 if (dos_rename(fsp->fsp_name,name) == 0) {
2006 string_set(&fsp->fsp_name,name);
2011 desc.errcode=NERR_Success;
2014 default: /* not implemented */
2018 SSVALS(*rparam,0,desc.errcode);
2019 SSVAL(*rparam,2,0); /* converter word */
2025 /****************************************************************************
2026 get info about the server
2027 ****************************************************************************/
2028 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2029 int mdrcnt,int mprcnt,
2030 char **rdata,char **rparam,
2031 int *rdata_len,int *rparam_len)
2033 char *str1 = param+2;
2034 char *str2 = skip_string(str1,1);
2035 char *p = skip_string(str2,1);
2036 int uLevel = SVAL(p,0);
2040 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2042 /* check it's a supported varient */
2043 if (!prefix_ok(str1,"WrLh")) return False;
2046 if (strcmp(str2,"B16") != 0) return False;
2050 if (strcmp(str2,"B16BBDz") != 0) return False;
2054 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2059 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2064 if (strcmp(str2,"DN") != 0) return False;
2068 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2071 default: return False;
2074 *rdata_len = mdrcnt;
2075 *rdata = REALLOC(*rdata,*rdata_len);
2078 p2 = p + struct_len;
2080 StrnCpy(p,local_machine,16);
2086 struct srv_info_struct *servers=NULL;
2089 uint32 servertype= lp_default_server_announce();
2091 pstrcpy(comment,lp_serverstring());
2093 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2094 for (i=0;i<count;i++)
2095 if (strequal(servers[i].name,local_machine))
2097 servertype = servers[i].type;
2098 pstrcpy(comment,servers[i].comment);
2101 if (servers) free(servers);
2103 SCVAL(p,0,lp_major_announce_version());
2104 SCVAL(p,1,lp_minor_announce_version());
2105 SIVAL(p,2,servertype);
2107 if (mdrcnt == struct_len) {
2110 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2111 standard_sub(conn,comment);
2112 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2113 p2 = skip_string(p2,1);
2118 return False; /* not yet implemented */
2121 *rdata_len = PTR_DIFF(p2,*rdata);
2124 *rparam = REALLOC(*rparam,*rparam_len);
2125 SSVAL(*rparam,0,NERR_Success);
2126 SSVAL(*rparam,2,0); /* converter word */
2127 SSVAL(*rparam,4,*rdata_len);
2133 /****************************************************************************
2134 get info about the server
2135 ****************************************************************************/
2136 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2137 int mdrcnt,int mprcnt,
2138 char **rdata,char **rparam,
2139 int *rdata_len,int *rparam_len)
2141 char *str1 = param+2;
2142 char *str2 = skip_string(str1,1);
2143 char *p = skip_string(str2,1);
2145 extern pstring sesssetup_user;
2146 int level = SVAL(p,0);
2148 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2151 *rparam = REALLOC(*rparam,*rparam_len);
2153 /* check it's a supported varient */
2154 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2157 *rdata_len = mdrcnt + 1024;
2158 *rdata = REALLOC(*rdata,*rdata_len);
2160 SSVAL(*rparam,0,NERR_Success);
2161 SSVAL(*rparam,2,0); /* converter word */
2167 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2168 pstrcpy(p2,local_machine);
2170 p2 = skip_string(p2,1);
2173 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2174 pstrcpy(p2,sesssetup_user);
2175 p2 = skip_string(p2,1);
2178 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2179 pstrcpy(p2,global_myworkgroup);
2181 p2 = skip_string(p2,1);
2184 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2185 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2188 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2189 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2190 p2 = skip_string(p2,1);
2193 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2195 p2 = skip_string(p2,1);
2198 *rdata_len = PTR_DIFF(p2,*rdata);
2200 SSVAL(*rparam,4,*rdata_len);
2205 /****************************************************************************
2206 get info about a user
2208 struct user_info_11 {
2209 char usri11_name[21]; 0-20
2211 char *usri11_comment; 22-25
2212 char *usri11_usr_comment; 26-29
2213 unsigned short usri11_priv; 30-31
2214 unsigned long usri11_auth_flags; 32-35
2215 long usri11_password_age; 36-39
2216 char *usri11_homedir; 40-43
2217 char *usri11_parms; 44-47
2218 long usri11_last_logon; 48-51
2219 long usri11_last_logoff; 52-55
2220 unsigned short usri11_bad_pw_count; 56-57
2221 unsigned short usri11_num_logons; 58-59
2222 char *usri11_logon_server; 60-63
2223 unsigned short usri11_country_code; 64-65
2224 char *usri11_workstations; 66-69
2225 unsigned long usri11_max_storage; 70-73
2226 unsigned short usri11_units_per_week; 74-75
2227 unsigned char *usri11_logon_hours; 76-79
2228 unsigned short usri11_code_page; 80-81
2233 usri11_name specifies the user name for which information is retireved
2235 usri11_pad aligns the next data structure element to a word boundary
2237 usri11_comment is a null terminated ASCII comment
2239 usri11_user_comment is a null terminated ASCII comment about the user
2241 usri11_priv specifies the level of the privilege assigned to the user.
2242 The possible values are:
2244 Name Value Description
2245 USER_PRIV_GUEST 0 Guest privilege
2246 USER_PRIV_USER 1 User privilege
2247 USER_PRV_ADMIN 2 Administrator privilege
2249 usri11_auth_flags specifies the account operator privileges. The
2250 possible values are:
2252 Name Value Description
2253 AF_OP_PRINT 0 Print operator
2256 Leach, Naik [Page 28]
\r\f
2259 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2262 AF_OP_COMM 1 Communications operator
2263 AF_OP_SERVER 2 Server operator
2264 AF_OP_ACCOUNTS 3 Accounts operator
2267 usri11_password_age specifies how many seconds have elapsed since the
2268 password was last changed.
2270 usri11_home_dir points to a null terminated ASCII string that contains
2271 the path name of the user's home directory.
2273 usri11_parms points to a null terminated ASCII string that is set
2274 aside for use by applications.
2276 usri11_last_logon specifies the time when the user last logged on.
2277 This value is stored as the number of seconds elapsed since
2278 00:00:00, January 1, 1970.
2280 usri11_last_logoff specifies the time when the user last logged off.
2281 This value is stored as the number of seconds elapsed since
2282 00:00:00, January 1, 1970. A value of 0 means the last logoff
2285 usri11_bad_pw_count specifies the number of incorrect passwords
2286 entered since the last successful logon.
2288 usri11_log1_num_logons specifies the number of times this user has
2289 logged on. A value of -1 means the number of logons is unknown.
2291 usri11_logon_server points to a null terminated ASCII string that
2292 contains the name of the server to which logon requests are sent.
2293 A null string indicates logon requests should be sent to the
2296 usri11_country_code specifies the country code for the user's language
2299 usri11_workstations points to a null terminated ASCII string that
2300 contains the names of workstations the user may log on from.
2301 There may be up to 8 workstations, with the names separated by
2302 commas. A null strings indicates there are no restrictions.
2304 usri11_max_storage specifies the maximum amount of disk space the user
2305 can occupy. A value of 0xffffffff indicates there are no
2308 usri11_units_per_week specifies the equal number of time units into
2309 which a week is divided. This value must be equal to 168.
2311 usri11_logon_hours points to a 21 byte (168 bits) string that
2312 specifies the time during which the user can log on. Each bit
2313 represents one unique hour in a week. The first bit (bit 0, word
2314 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2318 Leach, Naik [Page 29]
\r\f
2321 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2324 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2325 are no restrictions.
2327 usri11_code_page specifies the code page for the user's language of
2330 All of the pointers in this data structure need to be treated
2331 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2332 to be ignored. The converter word returned in the parameters section
2333 needs to be subtracted from the lower 16 bits to calculate an offset
2334 into the return buffer where this ASCII string resides.
2336 There is no auxiliary data in the response.
2338 ****************************************************************************/
2340 #define usri11_name 0
2341 #define usri11_pad 21
2342 #define usri11_comment 22
2343 #define usri11_usr_comment 26
2344 #define usri11_full_name 30
2345 #define usri11_priv 34
2346 #define usri11_auth_flags 36
2347 #define usri11_password_age 40
2348 #define usri11_homedir 44
2349 #define usri11_parms 48
2350 #define usri11_last_logon 52
2351 #define usri11_last_logoff 56
2352 #define usri11_bad_pw_count 60
2353 #define usri11_num_logons 62
2354 #define usri11_logon_server 64
2355 #define usri11_country_code 68
2356 #define usri11_workstations 70
2357 #define usri11_max_storage 74
2358 #define usri11_units_per_week 78
2359 #define usri11_logon_hours 80
2360 #define usri11_code_page 84
2361 #define usri11_end 86
2363 #define USER_PRIV_GUEST 0
2364 #define USER_PRIV_USER 1
2365 #define USER_PRIV_ADMIN 2
2367 #define AF_OP_PRINT 0
2368 #define AF_OP_COMM 1
2369 #define AF_OP_SERVER 2
2370 #define AF_OP_ACCOUNTS 3
2373 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2374 int mdrcnt,int mprcnt,
2375 char **rdata,char **rparam,
2376 int *rdata_len,int *rparam_len)
2378 char *str1 = param+2;
2379 char *str2 = skip_string(str1,1);
2380 char *UserName = skip_string(str2,1);
2381 char *p = skip_string(UserName,1);
2382 int uLevel = SVAL(p,0);
2385 /* get NIS home of a previously validated user - simeon */
2386 /* With share level security vuid will always be zero.
2387 Don't depend on vuser being non-null !!. JRA */
2388 user_struct *vuser = get_valid_user_struct(vuid);
2390 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2393 *rparam = REALLOC(*rparam,*rparam_len);
2395 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2397 /* check it's a supported variant */
2398 if (strcmp(str1,"zWrLh") != 0) return False;
2401 case 0: p2 = "B21"; break;
2402 case 1: p2 = "B21BB16DWzzWz"; break;
2403 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2404 case 10: p2 = "B21Bzzz"; break;
2405 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2406 default: return False;
2409 if (strcmp(p2,str2) != 0) return False;
2411 *rdata_len = mdrcnt + 1024;
2412 *rdata = REALLOC(*rdata,*rdata_len);
2414 SSVAL(*rparam,0,NERR_Success);
2415 SSVAL(*rparam,2,0); /* converter word */
2418 p2 = p + usri11_end;
2421 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2425 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2430 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2431 pstrcpy(p2,"Comment");
2432 p2 = skip_string(p2,1);
2434 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2435 pstrcpy(p2,"UserComment");
2436 p2 = skip_string(p2,1);
2438 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2439 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2440 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2441 p2 = skip_string(p2,1);
2444 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2446 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2447 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2448 SIVALS(p,usri11_password_age,-1); /* password age */
2449 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2450 pstrcpy(p2, lp_logon_path());
2451 p2 = skip_string(p2,1);
2452 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2454 p2 = skip_string(p2,1);
2455 SIVAL(p,usri11_last_logon,0); /* last logon */
2456 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2457 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2458 SSVALS(p,usri11_num_logons,-1); /* num logons */
2459 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2460 pstrcpy(p2,"\\\\*");
2461 p2 = skip_string(p2,1);
2462 SSVAL(p,usri11_country_code,0); /* country code */
2464 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2466 p2 = skip_string(p2,1);
2468 SIVALS(p,usri11_max_storage,-1); /* max storage */
2469 SSVAL(p,usri11_units_per_week,168); /* units per week */
2470 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2472 /* a simple way to get logon hours at all times. */
2474 SCVAL(p2,21,0); /* fix zero termination */
2475 p2 = skip_string(p2,1);
2477 SSVAL(p,usri11_code_page,0); /* code page */
2479 if (uLevel == 1 || uLevel == 2)
2481 memset(p+22,' ',16); /* password */
2482 SIVALS(p,38,-1); /* password age */
2484 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2485 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2486 pstrcpy(p2,lp_logon_path());
2487 p2 = skip_string(p2,1);
2488 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2490 SSVAL(p,52,0); /* flags */
2491 SIVAL(p,54,0); /* script_path */
2494 SIVAL(p,60,0); /* auth_flags */
2495 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2496 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2497 p2 = skip_string(p2,1);
2498 SIVAL(p,68,0); /* urs_comment */
2499 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2501 p2 = skip_string(p2,1);
2502 SIVAL(p,76,0); /* workstations */
2503 SIVAL(p,80,0); /* last_logon */
2504 SIVAL(p,84,0); /* last_logoff */
2505 SIVALS(p,88,-1); /* acct_expires */
2506 SIVALS(p,92,-1); /* max_storage */
2507 SSVAL(p,96,168); /* units_per_week */
2508 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2511 SSVALS(p,102,-1); /* bad_pw_count */
2512 SSVALS(p,104,-1); /* num_logons */
2513 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2514 pstrcpy(p2,"\\\\%L");
2515 standard_sub_basic(p2);
2516 p2 = skip_string(p2,1);
2517 SSVAL(p,110,49); /* country_code */
2518 SSVAL(p,112,860); /* code page */
2522 *rdata_len = PTR_DIFF(p2,*rdata);
2524 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2529 /*******************************************************************
2530 get groups that a user is a member of
2531 ******************************************************************/
2532 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2533 int mdrcnt,int mprcnt,
2534 char **rdata,char **rparam,
2535 int *rdata_len,int *rparam_len)
2537 char *str1 = param+2;
2538 char *str2 = skip_string(str1,1);
2539 char *UserName = skip_string(str2,1);
2540 char *p = skip_string(UserName,1);
2541 int uLevel = SVAL(p,0);
2546 *rparam = REALLOC(*rparam,*rparam_len);
2548 /* check it's a supported varient */
2549 if (strcmp(str1,"zWrLeh") != 0) return False;
2551 case 0: p2 = "B21"; break;
2552 default: return False;
2554 if (strcmp(p2,str2) != 0) return False;
2556 *rdata_len = mdrcnt + 1024;
2557 *rdata = REALLOC(*rdata,*rdata_len);
2559 SSVAL(*rparam,0,NERR_Success);
2560 SSVAL(*rparam,2,0); /* converter word */
2564 /* XXXX we need a real SAM database some day */
2565 pstrcpy(p,"Users"); p += 21; count++;
2566 pstrcpy(p,"Domain Users"); p += 21; count++;
2567 pstrcpy(p,"Guests"); p += 21; count++;
2568 pstrcpy(p,"Domain Guests"); p += 21; count++;
2570 *rdata_len = PTR_DIFF(p,*rdata);
2572 SSVAL(*rparam,4,count); /* is this right?? */
2573 SSVAL(*rparam,6,count); /* is this right?? */
2579 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2580 int mdrcnt,int mprcnt,
2581 char **rdata,char **rparam,
2582 int *rdata_len,int *rparam_len)
2584 char *str1 = param+2;
2585 char *str2 = skip_string(str1,1);
2586 char *p = skip_string(str2,1);
2588 struct pack_desc desc;
2595 bzero(&desc,sizeof(desc));
2597 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2599 /* check it's a supported varient */
2600 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2601 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2602 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2604 desc.buflen = mdrcnt;
2605 desc.subformat = NULL;
2608 if (init_package(&desc,1,0))
2610 PACKI(&desc,"W",0); /* code */
2611 PACKS(&desc,"B21",name); /* eff. name */
2612 PACKS(&desc,"B",""); /* pad */
2614 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2615 PACKI(&desc,"D",0); /* auth flags XXX */
2616 PACKI(&desc,"W",0); /* num logons */
2617 PACKI(&desc,"W",0); /* bad pw count */
2618 PACKI(&desc,"D",0); /* last logon */
2619 PACKI(&desc,"D",-1); /* last logoff */
2620 PACKI(&desc,"D",-1); /* logoff time */
2621 PACKI(&desc,"D",-1); /* kickoff time */
2622 PACKI(&desc,"D",0); /* password age */
2623 PACKI(&desc,"D",0); /* password can change */
2624 PACKI(&desc,"D",-1); /* password must change */
2627 fstrcpy(mypath,"\\\\");
2628 fstrcat(mypath,local_machine);
2630 PACKS(&desc,"z",mypath); /* computer */
2632 PACKS(&desc,"z",global_myworkgroup);/* domain */
2634 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2635 /* made sure all macros are fully substituted and available */
2636 logon_script = lp_logon_script();
2637 standard_sub( conn, logon_script );
2638 PACKS(&desc,"z", logon_script); /* script path */
2639 /* End of JHT mods */
2641 PACKI(&desc,"D",0x00000000); /* reserved */
2644 *rdata_len = desc.usedlen;
2646 *rparam = REALLOC(*rparam,*rparam_len);
2647 SSVALS(*rparam,0,desc.errcode);
2649 SSVAL(*rparam,4,desc.neededlen);
2651 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2656 /****************************************************************************
2657 api_WAccessGetUserPerms
2658 ****************************************************************************/
2659 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2660 int mdrcnt,int mprcnt,
2661 char **rdata,char **rparam,
2662 int *rdata_len,int *rparam_len)
2664 char *str1 = param+2;
2665 char *str2 = skip_string(str1,1);
2666 char *user = skip_string(str2,1);
2667 char *resource = skip_string(user,1);
2669 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2671 /* check it's a supported varient */
2672 if (strcmp(str1,"zzh") != 0) return False;
2673 if (strcmp(str2,"") != 0) return False;
2676 *rparam = REALLOC(*rparam,*rparam_len);
2677 SSVALS(*rparam,0,0); /* errorcode */
2678 SSVAL(*rparam,2,0); /* converter word */
2679 SSVAL(*rparam,4,0x7f); /* permission flags */
2684 /****************************************************************************
2685 api_WPrintJobEnumerate
2686 ****************************************************************************/
2687 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2688 int mdrcnt,int mprcnt,
2689 char **rdata,char **rparam,
2690 int *rdata_len,int *rparam_len)
2692 char *str1 = param+2;
2693 char *str2 = skip_string(str1,1);
2694 char *p = skip_string(str2,1);
2700 struct pack_desc desc;
2701 print_queue_struct *queue=NULL;
2702 print_status_struct status;
2706 bzero(&desc,sizeof(desc));
2707 bzero(&status,sizeof(status));
2709 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2711 /* check it's a supported varient */
2712 if (strcmp(str1,"WWrLh") != 0) return False;
2713 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2715 printjob_decode(SVAL(p,0), &snum, &job);
2717 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2719 count = get_printqueue(snum,conn,&queue,&status);
2720 for (i = 0; i < count; i++) {
2721 if ((queue[i].job & 0xFF) == job) break;
2723 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2725 desc.buflen = mdrcnt;
2727 if (init_package(&desc,1,0)) {
2729 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2730 *rdata_len = desc.usedlen;
2733 desc.errcode = NERR_JobNotFound;
2739 *rparam = REALLOC(*rparam,*rparam_len);
2740 SSVALS(*rparam,0,desc.errcode);
2742 SSVAL(*rparam,4,desc.neededlen);
2744 if (queue) free(queue);
2746 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2750 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2751 int mdrcnt,int mprcnt,
2752 char **rdata,char **rparam,
2753 int *rdata_len,int *rparam_len)
2755 char *str1 = param+2;
2756 char *str2 = skip_string(str1,1);
2757 char *p = skip_string(str2,1);
2763 struct pack_desc desc;
2764 print_queue_struct *queue=NULL;
2765 print_status_struct status;
2767 bzero(&desc,sizeof(desc));
2768 bzero(&status,sizeof(status));
2770 p = skip_string(p,1);
2773 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2775 /* check it's a supported varient */
2776 if (strcmp(str1,"zWrLeh") != 0) return False;
2777 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2778 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2780 snum = lp_servicenumber(name);
2781 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2782 int pnum = lp_servicenumber(PRINTERS_NAME);
2784 lp_add_printer(name,pnum);
2785 snum = lp_servicenumber(name);
2789 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2791 count = get_printqueue(snum,conn,&queue,&status);
2792 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2794 desc.buflen = mdrcnt;
2796 if (init_package(&desc,count,0)) {
2798 for (i = 0; i < count; i++) {
2799 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2800 if (desc.errcode == NERR_Success) succnt = i+1;
2804 *rdata_len = desc.usedlen;
2807 *rparam = REALLOC(*rparam,*rparam_len);
2808 SSVALS(*rparam,0,desc.errcode);
2810 SSVAL(*rparam,4,succnt);
2811 SSVAL(*rparam,6,count);
2813 if (queue) free(queue);
2815 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2819 static int check_printdest_info(struct pack_desc* desc,
2820 int uLevel, char* id)
2822 desc->subformat = NULL;
2824 case 0: desc->format = "B9"; break;
2825 case 1: desc->format = "B9B21WWzW"; break;
2826 case 2: desc->format = "z"; break;
2827 case 3: desc->format = "zzzWWzzzWW"; break;
2828 default: return False;
2830 if (strcmp(desc->format,id) != 0) return False;
2834 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2835 struct pack_desc* desc)
2838 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2839 buf[sizeof(buf)-1] = 0;
2842 PACKS(desc,"B9",buf); /* szName */
2844 PACKS(desc,"B21",""); /* szUserName */
2845 PACKI(desc,"W",0); /* uJobId */
2846 PACKI(desc,"W",0); /* fsStatus */
2847 PACKS(desc,"z",""); /* pszStatus */
2848 PACKI(desc,"W",0); /* time */
2851 if (uLevel == 2 || uLevel == 3) {
2852 PACKS(desc,"z",buf); /* pszPrinterName */
2854 PACKS(desc,"z",""); /* pszUserName */
2855 PACKS(desc,"z",""); /* pszLogAddr */
2856 PACKI(desc,"W",0); /* uJobId */
2857 PACKI(desc,"W",0); /* fsStatus */
2858 PACKS(desc,"z",""); /* pszStatus */
2859 PACKS(desc,"z",""); /* pszComment */
2860 PACKS(desc,"z","NULL"); /* pszDrivers */
2861 PACKI(desc,"W",0); /* time */
2862 PACKI(desc,"W",0); /* pad1 */
2867 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2868 int mdrcnt,int mprcnt,
2869 char **rdata,char **rparam,
2870 int *rdata_len,int *rparam_len)
2872 char *str1 = param+2;
2873 char *str2 = skip_string(str1,1);
2874 char *p = skip_string(str2,1);
2875 char* PrinterName = p;
2877 struct pack_desc desc;
2880 bzero(&desc,sizeof(desc));
2882 p = skip_string(p,1);
2885 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2887 /* check it's a supported varient */
2888 if (strcmp(str1,"zWrLh") != 0) return False;
2889 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2891 snum = lp_servicenumber(PrinterName);
2892 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2893 int pnum = lp_servicenumber(PRINTERS_NAME);
2895 lp_add_printer(PrinterName,pnum);
2896 snum = lp_servicenumber(PrinterName);
2902 desc.errcode = NERR_DestNotFound;
2906 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2908 desc.buflen = mdrcnt;
2909 if (init_package(&desc,1,0)) {
2910 fill_printdest_info(conn,snum,uLevel,&desc);
2912 *rdata_len = desc.usedlen;
2916 *rparam = REALLOC(*rparam,*rparam_len);
2917 SSVALS(*rparam,0,desc.errcode);
2919 SSVAL(*rparam,4,desc.neededlen);
2921 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2925 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2926 int mdrcnt,int mprcnt,
2927 char **rdata,char **rparam,
2928 int *rdata_len,int *rparam_len)
2930 char *str1 = param+2;
2931 char *str2 = skip_string(str1,1);
2932 char *p = skip_string(str2,1);
2936 struct pack_desc desc;
2937 int services = lp_numservices();
2939 bzero(&desc,sizeof(desc));
2943 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2945 /* check it's a supported varient */
2946 if (strcmp(str1,"WrLeh") != 0) return False;
2947 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2950 for (i = 0; i < services; i++)
2951 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2954 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2956 desc.buflen = mdrcnt;
2957 if (init_package(&desc,queuecnt,0)) {
2960 for (i = 0; i < services; i++) {
2961 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2962 fill_printdest_info(conn,i,uLevel,&desc);
2964 if (desc.errcode == NERR_Success) succnt = n;
2969 *rdata_len = desc.usedlen;
2972 *rparam = REALLOC(*rparam,*rparam_len);
2973 SSVALS(*rparam,0,desc.errcode);
2975 SSVAL(*rparam,4,succnt);
2976 SSVAL(*rparam,6,queuecnt);
2978 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2982 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2983 int mdrcnt,int mprcnt,
2984 char **rdata,char **rparam,
2985 int *rdata_len,int *rparam_len)
2987 char *str1 = param+2;
2988 char *str2 = skip_string(str1,1);
2989 char *p = skip_string(str2,1);
2992 struct pack_desc desc;
2994 bzero(&desc,sizeof(desc));
2998 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3000 /* check it's a supported varient */
3001 if (strcmp(str1,"WrLeh") != 0) return False;
3002 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3004 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3006 desc.buflen = mdrcnt;
3007 if (init_package(&desc,1,0)) {
3008 PACKS(&desc,"B41","NULL");
3011 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3013 *rdata_len = desc.usedlen;
3016 *rparam = REALLOC(*rparam,*rparam_len);
3017 SSVALS(*rparam,0,desc.errcode);
3019 SSVAL(*rparam,4,succnt);
3022 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3026 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3027 int mdrcnt,int mprcnt,
3028 char **rdata,char **rparam,
3029 int *rdata_len,int *rparam_len)
3031 char *str1 = param+2;
3032 char *str2 = skip_string(str1,1);
3033 char *p = skip_string(str2,1);
3036 struct pack_desc desc;
3038 bzero(&desc,sizeof(desc));
3042 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3044 /* check it's a supported varient */
3045 if (strcmp(str1,"WrLeh") != 0) return False;
3046 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3048 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3050 desc.buflen = mdrcnt;
3052 if (init_package(&desc,1,0)) {
3053 PACKS(&desc,"B13","lpd");
3056 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3058 *rdata_len = desc.usedlen;
3061 *rparam = REALLOC(*rparam,*rparam_len);
3062 SSVALS(*rparam,0,desc.errcode);
3064 SSVAL(*rparam,4,succnt);
3067 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3071 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3072 int mdrcnt,int mprcnt,
3073 char **rdata,char **rparam,
3074 int *rdata_len,int *rparam_len)
3076 char *str1 = param+2;
3077 char *str2 = skip_string(str1,1);
3078 char *p = skip_string(str2,1);
3081 struct pack_desc desc;
3083 bzero(&desc,sizeof(desc));
3087 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3089 /* check it's a supported varient */
3090 if (strcmp(str1,"WrLeh") != 0) return False;
3091 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3093 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3094 bzero(&desc,sizeof(desc));
3096 desc.buflen = mdrcnt;
3098 if (init_package(&desc,1,0)) {
3099 PACKS(&desc,"B13","lp0");
3102 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3104 *rdata_len = desc.usedlen;
3107 *rparam = REALLOC(*rparam,*rparam_len);
3108 SSVALS(*rparam,0,desc.errcode);
3110 SSVAL(*rparam,4,succnt);
3113 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3117 static void api_rpc_trans_reply(char *outbuf,
3121 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3123 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3125 /* all of data was sent: no need to wait for SMBreadX calls */
3126 mem_free_data(p->rhdr .data);
3127 mem_free_data(p->rdata.data);
3128 mem_free_data(p->rdata_i.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;
3219 DEBUG(5,("api_fd_reply\n"));
3221 /* make a static data parsing structure from the api_fd_reply data */
3222 prs_init(&pd, 0, 4, 0, True);
3223 mem_create(pd.data, data, 0, tdscnt, 0, False);
3225 /* First find out the name of this file. */
3228 DEBUG(0,("Unexpected named pipe transaction.\n"));
3232 /* Get the file handle and hence the file name. */
3234 subcommand = setup[0];
3235 p = get_rpc_pipe(pnum);
3239 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3240 subcommand, p->name, pnum));
3242 /* record maximum data length that can be transmitted in an SMBtrans */
3243 p->file_offset = mdrcnt;
3244 p->prev_pdu_file_offset = 0;
3246 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3247 p, p->file_offset));
3253 /* dce/rpc command */
3254 reply = rpc_command(p, &pd);
3257 api_rpc_trans_reply(outbuf, p, &pd);
3263 /* Wait Named Pipe Handle state */
3264 reply = api_WNPHS(outbuf, p, params);
3269 /* Set Named Pipe Handle state */
3270 reply = api_SNPHS(outbuf, p, params);
3277 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3280 mem_free_data(pd.data);
3284 return api_no_reply(outbuf, mdrcnt);
3289 /****************************************************************************
3290 the buffer was too small
3291 ****************************************************************************/
3292 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3293 int mdrcnt,int mprcnt,
3294 char **rdata,char **rparam,
3295 int *rdata_len,int *rparam_len)
3297 *rparam_len = MIN(*rparam_len,mprcnt);
3298 *rparam = REALLOC(*rparam,*rparam_len);
3302 SSVAL(*rparam,0,NERR_BufTooSmall);
3304 DEBUG(3,("Supplied buffer too small in API command\n"));
3310 /****************************************************************************
3311 the request is not supported
3312 ****************************************************************************/
3313 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3314 int mdrcnt,int mprcnt,
3315 char **rdata,char **rparam,
3316 int *rdata_len,int *rparam_len)
3319 *rparam = REALLOC(*rparam,*rparam_len);
3323 SSVAL(*rparam,0,NERR_notsupported);
3324 SSVAL(*rparam,2,0); /* converter word */
3326 DEBUG(3,("Unsupported API command\n"));
3338 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3339 int,int,char **,char **,int *,int *);
3341 } api_commands[] = {
3342 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3343 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3344 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3345 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3346 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3347 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3348 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3349 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3350 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3351 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3352 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3353 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3354 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3355 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3356 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3357 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3358 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3359 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3360 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3361 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3362 {"NetServerEnum", 104, api_RNetServerEnum,0},
3363 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3364 {"SetUserPassword", 115, api_SetUserPassword,0},
3365 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3366 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3367 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3368 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3369 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3370 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3371 {NULL, -1, api_Unsupported,0}};
3374 /****************************************************************************
3375 handle remote api calls
3376 ****************************************************************************/
3377 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3378 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3381 struct mem_buf rdata_buf;
3382 struct mem_buf rparam_buf;
3384 char *rparam = NULL;
3390 SMB_ASSERT(params != 0);
3392 api_command = SVAL(params,0);
3394 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3397 skip_string(params+2,1),
3398 tdscnt,tpscnt,mdrcnt,mprcnt));
3400 for (i=0;api_commands[i].name;i++)
3401 if (api_commands[i].id == api_command && api_commands[i].fn)
3403 DEBUG(3,("Doing %s\n",api_commands[i].name));
3407 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3408 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3410 if(!rdata || !rparam) {
3411 DEBUG(0,("api_reply: malloc fail !\n"));
3415 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3416 &rdata,&rparam,&rdata_len,&rparam_len);
3419 if (rdata_len > mdrcnt ||
3420 rparam_len > mprcnt)
3422 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3423 &rdata,&rparam,&rdata_len,&rparam_len);
3427 /* if we get False back then it's actually unsupported */
3429 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3430 &rdata,&rparam,&rdata_len,&rparam_len);
3433 mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False);
3434 mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False);
3436 /* now send the reply */
3437 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3439 if (rdata ) free(rdata);
3440 if (rparam) free(rparam);
3445 /****************************************************************************
3446 handle named pipe commands
3447 ****************************************************************************/
3448 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3449 uint16 *setup,char *data,char *params,
3450 int suwcnt,int tdscnt,int tpscnt,
3451 int msrcnt,int mdrcnt,int mprcnt)
3453 DEBUG(3,("named pipe command on <%s> name\n", name));
3455 if (strequal(name,"LANMAN"))
3457 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3460 if (strequal(name,"WKSSVC") ||
3461 strequal(name,"SRVSVC") ||
3462 strequal(name,"WINREG") ||
3463 strequal(name,"SAMR") ||
3464 strequal(name,"LSARPC"))
3466 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3467 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3470 if (strlen(name) < 1)
3472 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3477 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3484 /****************************************************************************
3486 ****************************************************************************/
3487 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3490 int name_offset = 0;
3491 char *data=NULL,*params=NULL;
3494 uint16 vuid = SVAL(inbuf,smb_uid);
3495 int tpscnt = SVAL(inbuf,smb_vwv0);
3496 int tdscnt = SVAL(inbuf,smb_vwv1);
3497 int mprcnt = SVAL(inbuf,smb_vwv2);
3498 int mdrcnt = SVAL(inbuf,smb_vwv3);
3499 int msrcnt = CVAL(inbuf,smb_vwv4);
3500 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3501 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3502 int pscnt = SVAL(inbuf,smb_vwv9);
3503 int psoff = SVAL(inbuf,smb_vwv10);
3504 int dscnt = SVAL(inbuf,smb_vwv11);
3505 int dsoff = SVAL(inbuf,smb_vwv12);
3506 int suwcnt = CVAL(inbuf,smb_vwv13);
3508 bzero(name, sizeof(name));
3509 fstrcpy(name,smb_buf(inbuf));
3511 if (dscnt > tdscnt || pscnt > tpscnt) {
3512 exit_server("invalid trans parameters\n");
3516 if((data = (char *)malloc(tdscnt)) == NULL) {
3517 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
3518 return(ERROR(ERRDOS,ERRnomem));
3520 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3524 if((params = (char *)malloc(tpscnt)) == NULL) {
3525 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
3526 return(ERROR(ERRDOS,ERRnomem));
3528 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3533 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
3534 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16)));
3535 return(ERROR(ERRDOS,ERRnomem));
3537 for (i=0;i<suwcnt;i++)
3538 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3542 if (pscnt < tpscnt || dscnt < tdscnt) {
3543 /* We need to send an interim response then receive the rest
3544 of the parameter/data bytes */
3545 outsize = set_message(outbuf,0,0,True);
3547 send_smb(Client,outbuf);
3550 /* receive the rest of the trans packet */
3551 while (pscnt < tpscnt || dscnt < tdscnt) {
3553 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3555 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3557 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3559 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3561 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3562 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3564 if (params) free(params);
3565 if (data) free(data);
3566 if (setup) free(setup);
3567 return(ERROR(ERRSRV,ERRerror));
3572 tpscnt = SVAL(inbuf,smb_vwv0);
3573 tdscnt = SVAL(inbuf,smb_vwv1);
3575 pcnt = SVAL(inbuf,smb_vwv2);
3576 poff = SVAL(inbuf,smb_vwv3);
3577 pdisp = SVAL(inbuf,smb_vwv4);
3579 dcnt = SVAL(inbuf,smb_vwv5);
3580 doff = SVAL(inbuf,smb_vwv6);
3581 ddisp = SVAL(inbuf,smb_vwv7);
3586 if (dscnt > tdscnt || pscnt > tpscnt) {
3587 exit_server("invalid trans parameters\n");
3591 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3593 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3597 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3598 name,tdscnt,tpscnt,suwcnt));
3601 * WinCE wierdness....
3604 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine,
3605 strlen(local_machine)) == 0)) {
3606 name_offset = strlen(local_machine)+1;
3609 if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3610 DEBUG(5,("calling named_pipe\n"));
3611 outsize = named_pipe(conn,vuid,outbuf,
3612 name+name_offset+strlen("\\PIPE\\"),setup,data,params,
3613 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3615 DEBUG(3,("invalid pipe name\n"));
3620 if (data) free(data);
3621 if (params) free(params);
3622 if (setup) free(setup);
3624 if (close_on_completion)
3625 close_cnum(conn,vuid);
3631 return(ERROR(ERRSRV,ERRnosupport));