home *** CD-ROM | disk | FTP | other *** search
- /*
- Unix SMB/Netbios implementation.
- Version 1.8.
- Copyright (C) Andrew Tridgell 1992,1993,1994
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /*
- This file handles the named pipe and mailslot calls
- in the SMBtrans protocol
- */
-
-
- #include "includes.h"
- #include "loadparm.h"
- #include "pcap.h"
-
- extern int DEBUGLEVEL;
- extern int maxxmit;
-
- #define NERR_Success 0
- #define NERR_badpass 86
- #define NERR_notsupported 50
-
- /****************************************************************************
- send a trans reply
- ****************************************************************************/
- void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
- int ldata,int lparam,int lsetup)
- {
- int i;
- int this_ldata,this_lparam;
- int tot_data=0,tot_param=0;
-
- this_lparam = MIN(lparam,maxxmit - (500+lsetup*sizeof(WORD))); /* hack */
- this_ldata = MIN(ldata,maxxmit - (500+lsetup*sizeof(WORD)+this_lparam));
-
- set_message(outbuf,10+lsetup,this_ldata+this_lparam,True);
- if (this_lparam)
- memcpy(smb_buf(outbuf),param,this_lparam);
- if (this_ldata)
- memcpy(smb_buf(outbuf)+this_lparam,data,this_ldata);
-
- SSVAL(outbuf,smb_vwv0,lparam);
- SSVAL(outbuf,smb_vwv1,ldata);
- SSVAL(outbuf,smb_vwv3,this_lparam);
- SSVAL(outbuf,smb_vwv4,smb_buf_ofs(outbuf)-4);
- SSVAL(outbuf,smb_vwv5,0);
- SSVAL(outbuf,smb_vwv6,this_ldata);
- SSVAL(outbuf,smb_vwv7,smb_buf_ofs(outbuf)+this_lparam-4);
- SSVAL(outbuf,smb_vwv8,0);
- SSVAL(outbuf,smb_vwv9,lsetup);
- for (i=0;i<lsetup;i++)
- SSVAL(outbuf,smb_vwv10+i*sizeof(WORD),setup[i]);
-
- show_msg(outbuf);
- send_smb(outbuf);
-
- tot_data = this_ldata;
- tot_param = this_lparam;
-
- while (tot_data < ldata || tot_param < lparam)
- {
- this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
- this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
-
- set_message(outbuf,10,this_ldata+this_lparam,False);
- if (this_lparam)
- memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
- if (this_ldata)
- memcpy(smb_buf(outbuf)+this_lparam,data+tot_data,this_ldata);
-
- SSVAL(outbuf,smb_vwv3,this_lparam);
- SSVAL(outbuf,smb_vwv4,smb_buf_ofs(outbuf)-4);
- SSVAL(outbuf,smb_vwv5,tot_param);
- SSVAL(outbuf,smb_vwv6,this_ldata);
- SSVAL(outbuf,smb_vwv7,smb_buf_ofs(outbuf)+this_lparam-4);
- SSVAL(outbuf,smb_vwv8,tot_data);
- SSVAL(outbuf,smb_vwv9,0);
-
- show_msg(outbuf);
- send_smb(outbuf);
-
- tot_data += this_ldata;
- tot_param += this_lparam;
- }
- }
-
- /****************************************************************************
- get a print queue
- ****************************************************************************/
- BOOL api_DosPrintQGetInfo(int cnum,char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
- {
- char *p = skip_string(param+2,2);
- char *QueueName = p;
- int uLevel,cbBuf;
- int count=0,i;
- print_queue_struct *queue=NULL;
- char *p2;
- int snum;
-
- p = skip_string(p,1);
- uLevel = SVAL(p,0);
- cbBuf = SVAL(p,2);
-
- if (uLevel == 0)
- return(True);
-
- snum = lp_servicenumber(QueueName);
- if (snum < 0 && pcap_printername_ok(QueueName,NULL))
- {
- int pnum = lp_servicenumber(PRINTERS_NAME);
- if (pnum >= 0)
- {
- lp_add_printer(QueueName,pnum);
- snum = lp_servicenumber(QueueName);
- }
- }
-
- if (snum >= 0)
- {
- unbecome_user();
- count = get_printqueue(lp_servicenumber(QueueName),&queue);
- become_user(cnum);
- }
-
- *rparam_len = 6;
- *rparam = Realloc(*rparam,*rparam_len);
-
- *rdata_len = 13 + 1 + 30;
- *rdata = Realloc(*rdata,*rdata_len + 100 + count*(74+200));
-
- p2 = (*rdata) + 44 + count*74; /* auxillery data (strings) will go here */
-
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
-
- p = *rdata;
-
- StrnCpy(p,QueueName,13);
- p += 13 + 1;
- SSVAL(p,0,0); /* priority */
- SSVAL(p,2,0); /* start time */
- SSVAL(p,4,0); /* until time */
- SIVAL(p,6,0); /* pSepFile */
- SIVAL(p,10,0); /* pPrProc */
- SIVAL(p,14,0); /* pDestinations */
- SIVAL(p,18,0); /* pParms */
-
- SIVAL(p,22,PTR_DIFF(p2,*rdata)); /* pComment */
- {
- extern pstring myhostname;
- pstring comment="";
- strcpy(comment,lp_serverstring());
- string_sub(comment,"%v",VERSION);
- string_sub(comment,"%h",myhostname);
- strcpy(p2,comment);
- }
- p2 = skip_string(p2,1);
-
- SSVAL(p,26,0); /* status */
- SSVAL(p,28,count); /* num jobs */
- p += 30;
-
- for (i=0;i<count;i++)
- {
- SSVAL(p,0,queue[i].job);
- StrnCpy(p+2,queue[i].user,21);
- StrnCpy(p+24,"",16); /* notify name */
- StrnCpy(p+40,"",10); /* data type */
- SIVAL(p,50,0); /* pParams */
- SSVAL(p,54,i); /* position */
- SSVAL(p,56,queue[i].status); /* status */
- SIVAL(p,58,0); /* pStatus string */
- SIVAL(p,62,queue[i].time); /* submit time */
- SIVAL(p,66,queue[i].size); /* job size */
-
- SIVAL(p,70,PTR_DIFF(p2,*rdata));
- strcpy(p2,queue[i].file);
- p2 = skip_string(p2,1);
-
- p += 74;
- }
-
- *rdata_len = PTR_DIFF(p2,*rdata);
-
- if (queue) free(queue);
-
- DEBUG(3,("DosPrintQGetInfo on <%s> gave %d entries\n",QueueName,count));
- return(True);
- }
-
-
- /****************************************************************************
- view list of shares available
- ****************************************************************************/
- BOOL api_RNetShareEnum(int cnum,char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
- {
- char *p = skip_string(param+2,2);
- int level = SVAL(p,0);
- int buf_len = SVAL(p,2);
- char *p2;
- int count=lp_numservices();
- int total=0,counted=0;
- int comment_len=0;
- int i;
- BOOL squeezed = False;
-
- for (i=0;i<count;i++)
- if (lp_browseable(i))
- {
- total++;
- comment_len += strlen(lp_comment(i)) + 1;
- }
-
- *rparam_len = 8;
- *rparam = Realloc(*rparam,*rparam_len);
-
- *rdata_len = total*20 + comment_len;
- *rdata = Realloc(*rdata,*rdata_len);
- memset(*rdata,0,*rdata_len);
-
- total = MIN(total,buf_len/25);
-
- p2 = (*rdata) + total*20; /* auxillery data (strings) will go here */
-
- p = *rdata;
-
- for (i=0;i<count && counted<total;i++)
- if (lp_browseable(i))
- {
- int type = 0;
-
- if (lp_print_ok(i)) type = 1;
- if (strequal("IPC$",lp_servicename(i))) type = 3;
-
- StrnCpy(p,lp_servicename(i),13);
- CVAL(p,13) = 0; /* pad */
- SSVAL(p,14,type); /* device type */
- SIVAL(p,16,PTR_DIFF(p2,(*rdata)));
- strcpy(p2,lp_comment(i));
-
- if (!squeezed &&
- PTR_DIFF(skip_string(p2,1),*rdata) < (buf_len-2))
- p2 = skip_string(p2,1);
- else
- squeezed = True;
-
- p += 20;
- counted++;
- }
-
-
- if (squeezed)
- {
- strcpy(p2,"-");
- p2 += 2;
- }
-
- if (counted < total)
- {
- safe_memcpy((*rdata) + counted*20,(*rdata) + total*20,
- PTR_DIFF(p2,(*rdata) + total*20)+2);
- p2 -= (total-counted)*20;
- }
-
- *rdata_len = PTR_DIFF(p2,(*rdata));
-
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,(total-counted)*20); /* converter word */
- SSVAL(*rparam,4,counted);
- SSVAL(*rparam,6,total);
-
- DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
- counted,total,level,
- buf_len,*rdata_len,mdrcnt));
- return(True);
- }
-
-
-
- /****************************************************************************
- get the time of day info
- ****************************************************************************/
- BOOL api_NetRemoteTOD(int cnum,char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
- {
- char *p;
- *rparam_len = 6;
- *rparam = Realloc(*rparam,*rparam_len);
-
- *rdata_len = 21;
- *rdata = Realloc(*rdata,*rdata_len);
-
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
-
- p = *rdata;
-
- {
- struct tm *t;
- time_t unixdate = time(NULL);
-
- t = LocalTime(&unixdate,GMT_TO_LOCAL);
-
- SIVAL(p,0,unixdate + GMT_TO_LOCAL*TimeDiff()); /* elapsedt
- since 1-1-1970 in
- seconds */
- SIVAL(p,4,0); /* msecs ? */
- CVAL(p,8) = t->tm_hour;
- CVAL(p,9) = t->tm_min;
- CVAL(p,10) = t->tm_sec;
- CVAL(p,11) = 0; /* hundredths of seconds */
- SSVAL(p,12,TimeDiff()/60); /* timezone in minutes from GMT */
- SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
- CVAL(p,16) = t->tm_mday;
- CVAL(p,17) = t->tm_mon + 1;
- SSVAL(p,18,t->tm_year);
- CVAL(p,20) = t->tm_wday;
- }
-
-
- return(True);
- }
-
- /****************************************************************************
- set the user password
- ****************************************************************************/
- BOOL api_SetUserPassword(int cnum,char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
- {
- char *p = skip_string(param+2,2);
- char *user = p;
- fstring pass1,pass2;
-
- p = skip_string(p,1);
-
- StrnCpy(pass1,p,16);
- StrnCpy(pass2,p+16,16);
-
- *rparam_len = 6;
- *rparam = Realloc(*rparam,*rparam_len);
-
- *rdata_len = 0;
-
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
-
- DEBUG(3,("Set password for <%s>\n",user));
-
- if (!password_ok(user,pass1,NULL) || !set_user_password(user,pass1,pass2))
- SSVAL(*rparam,0,NERR_badpass);
-
- memset(pass1,0,sizeof(fstring));
- memset(pass2,0,sizeof(fstring));
-
- return(True);
- }
-
-
- /****************************************************************************
- the request is not supported
- ****************************************************************************/
- BOOL api_Unsupported(int cnum,char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
- {
- *rparam_len = 6;
- *rparam = Realloc(*rparam,*rparam_len);
-
- *rdata_len = 0;
-
- SSVAL(*rparam,0,NERR_notsupported);
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
-
- DEBUG(3,("Unsupported API command\n"));
-
- return(True);
- }
-
-
-
-
- struct
- {
- char *name;
- int id;
- BOOL (*fn)();
- int flags;
- } api_commands[] = {
- {"DosPrintQGetInfo",70,api_DosPrintQGetInfo,0},
- {"NetRemoteTOD",91,api_NetRemoteTOD,0},
- {"SetUserPassword",115,api_SetUserPassword,0},
- {"RNetShareEnum",0,api_RNetShareEnum,0},
- {NULL,-1,api_Unsupported,0}};
-
-
- /****************************************************************************
- handle remote api calls
- ****************************************************************************/
- int api_reply(int cnum,char *outbuf,char *data,char *params,
- int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
- {
- int api_command = SVAL(params,0);
- char *rdata = NULL;
- char *rparam = NULL;
- int rdata_len = 0;
- int rparam_len = 0;
- BOOL reply=False;
- int i;
-
- DEBUG(5,("Got API command %d of form <%s> <%s> \n",
- api_command,params+2,skip_string(params+2,1)));
-
- for (i=0;api_commands[i].name;i++)
- if (api_commands[i].id == api_command && api_commands[i].fn)
- {
- DEBUG(3,("Doing %s\n",api_commands[i].name));
- break;
- }
-
- reply = api_commands[i].fn(cnum,params,data,mdrcnt,mprcnt,
- &rdata,&rparam,&rdata_len,&rparam_len);
-
- /* now send the reply - assuming there is one */
- if (reply)
- send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
-
- if (rdata)
- free(rdata);
- if (rparam)
- free(rparam);
-
- return(reply?-1:0);
- }
-
- /****************************************************************************
- handle named pipe commands
- ****************************************************************************/
- int named_pipe(int cnum,char *outbuf,char *name,
- uint16 *setup,char *data,char *params,
- int suwcnt,int tdscnt,int tpscnt,
- int msrcnt,int mdrcnt,int mprcnt)
- {
-
- if (strequal(name,"LANMAN"))
- return(api_reply(cnum,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
-
- DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
- name,(int)setup[0],(int)setup[1]));
-
- return(0);
- }
-
-
- /****************************************************************************
- reply to a SMBtrans
- ****************************************************************************/
- int reply_trans(char *inbuf,char *outbuf)
- {
- fstring name;
-
- char *data=NULL,*params=NULL;
- uint16 *setup=NULL;
-
- int outsize = 0;
- int cnum = SVAL(inbuf,smb_tid);
-
- int tpscnt = SVAL(inbuf,smb_vwv0);
- int tdscnt = SVAL(inbuf,smb_vwv1);
- int mprcnt = SVAL(inbuf,smb_vwv2);
- int mdrcnt = SVAL(inbuf,smb_vwv3);
- int msrcnt = CVAL(inbuf,smb_vwv4);
- BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
- BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
- int pscnt = SVAL(inbuf,smb_vwv9);
- int psoff = SVAL(inbuf,smb_vwv10);
- int dscnt = SVAL(inbuf,smb_vwv11);
- int dsoff = SVAL(inbuf,smb_vwv12);
- int suwcnt = CVAL(inbuf,smb_vwv13);
-
- StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
-
- if (tdscnt)
- {
- data = (char *)malloc(tdscnt);
- memcpy(data,inbuf+4+dsoff,dscnt);
- }
- if (tpscnt)
- {
- params = (char *)malloc(tpscnt);
- memcpy(params,inbuf+4+psoff,pscnt);
- }
-
- if (suwcnt)
- {
- int i;
- setup = (uint16 *)malloc(suwcnt*sizeof(uint16));
- for (i=0;i<suwcnt;i++)
- setup[i] = SVAL(inbuf,smb_vwv14+i*sizeof(WORD));
- }
-
-
- if (pscnt < tpscnt || dscnt < tdscnt)
- {
- /* We need to send an interim response then receive the rest
- of the parameter/data bytes */
- outsize = set_message(outbuf,0,0,True);
- show_msg(outbuf);
- send_smb(outbuf);
- }
-
- /* receive the rest of the trans packet */
- while (pscnt < tpscnt || dscnt < tdscnt)
- {
- int pcnt,poff,dcnt,doff,pdisp,ddisp;
-
- receive_smb(inbuf, 0);
- show_msg(inbuf);
-
- /* Ensure this is still a trans packet (sanity check) */
- if(CVAL(inbuf, smb_com) != SMBtrans)
- {
- DEBUG(0,("Invalid secondary trans2 packet\n"));
- if (params) free(params);
- if (data) free(data);
- if (setup) free(setup);
- return(ERROR(ERRSRV,ERRerror));
- }
-
- tpscnt = SVAL(inbuf,smb_vwv0);
- tdscnt = SVAL(inbuf,smb_vwv1);
-
- pcnt = SVAL(inbuf,smb_vwv2);
- poff = SVAL(inbuf,smb_vwv3);
- pdisp = SVAL(inbuf,smb_vwv4);
-
- dcnt = SVAL(inbuf,smb_vwv5);
- doff = SVAL(inbuf,smb_vwv6);
- ddisp = SVAL(inbuf,smb_vwv7);
-
- pscnt += pcnt;
- dscnt += dcnt;
-
- if (pcnt)
- memcpy(params+pdisp,inbuf+4+poff,pcnt);
- if (dcnt)
- memcpy(data+ddisp,inbuf+4+doff,dcnt);
- }
-
-
- DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
-
-
- if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
- outsize = named_pipe(cnum,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
- suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
-
-
- if (data) free(data);
- if (params) free(params);
- if (setup) free(setup);
-
- if (close_on_completion)
- close_cnum(cnum);
-
- if (one_way)
- return(-1);
-
- if (outsize == 0)
- return(ERROR(ERRSRV,ERRnosupport));
-
- return(outsize);
- }
-
-
-