home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / ipc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  15.4 KB  |  604 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Andrew Tridgell 1992,1993,1994
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. /*
  21.    This file handles the named pipe and mailslot calls
  22.    in the SMBtrans protocol
  23. */
  24.  
  25.  
  26. #include "includes.h"
  27. #include "loadparm.h"
  28. #include "pcap.h"
  29.  
  30. extern int DEBUGLEVEL;
  31. extern int maxxmit;
  32.  
  33. #define NERR_Success 0
  34. #define NERR_badpass 86
  35. #define NERR_notsupported 50
  36.  
  37. /****************************************************************************
  38. send a trans reply
  39. ****************************************************************************/
  40. void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
  41.               int ldata,int lparam,int lsetup)
  42. {
  43.   int i;
  44.   int this_ldata,this_lparam;
  45.   int tot_data=0,tot_param=0;
  46.  
  47.   this_lparam = MIN(lparam,maxxmit - (500+lsetup*sizeof(WORD))); /* hack */
  48.   this_ldata = MIN(ldata,maxxmit - (500+lsetup*sizeof(WORD)+this_lparam));
  49.  
  50.   set_message(outbuf,10+lsetup,this_ldata+this_lparam,True);
  51.   if (this_lparam)
  52.     memcpy(smb_buf(outbuf),param,this_lparam);
  53.   if (this_ldata)
  54.     memcpy(smb_buf(outbuf)+this_lparam,data,this_ldata);
  55.  
  56.   SSVAL(outbuf,smb_vwv0,lparam);
  57.   SSVAL(outbuf,smb_vwv1,ldata);
  58.   SSVAL(outbuf,smb_vwv3,this_lparam);
  59.   SSVAL(outbuf,smb_vwv4,smb_buf_ofs(outbuf)-4);
  60.   SSVAL(outbuf,smb_vwv5,0);
  61.   SSVAL(outbuf,smb_vwv6,this_ldata);
  62.   SSVAL(outbuf,smb_vwv7,smb_buf_ofs(outbuf)+this_lparam-4);
  63.   SSVAL(outbuf,smb_vwv8,0);
  64.   SSVAL(outbuf,smb_vwv9,lsetup);
  65.   for (i=0;i<lsetup;i++)
  66.     SSVAL(outbuf,smb_vwv10+i*sizeof(WORD),setup[i]);
  67.  
  68.   show_msg(outbuf);
  69.   send_smb(outbuf);
  70.  
  71.   tot_data = this_ldata;
  72.   tot_param = this_lparam;
  73.  
  74.   while (tot_data < ldata || tot_param < lparam)
  75.     {
  76.       this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
  77.       this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
  78.  
  79.       set_message(outbuf,10,this_ldata+this_lparam,False);
  80.       if (this_lparam)
  81.     memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
  82.       if (this_ldata)
  83.     memcpy(smb_buf(outbuf)+this_lparam,data+tot_data,this_ldata);
  84.  
  85.       SSVAL(outbuf,smb_vwv3,this_lparam);
  86.       SSVAL(outbuf,smb_vwv4,smb_buf_ofs(outbuf)-4);
  87.       SSVAL(outbuf,smb_vwv5,tot_param);
  88.       SSVAL(outbuf,smb_vwv6,this_ldata);
  89.       SSVAL(outbuf,smb_vwv7,smb_buf_ofs(outbuf)+this_lparam-4);
  90.       SSVAL(outbuf,smb_vwv8,tot_data);
  91.       SSVAL(outbuf,smb_vwv9,0);
  92.  
  93.       show_msg(outbuf);
  94.       send_smb(outbuf);
  95.  
  96.       tot_data += this_ldata;
  97.       tot_param += this_lparam;
  98.     }
  99. }
  100.  
  101. /****************************************************************************
  102. get a print queue
  103. ****************************************************************************/
  104. BOOL api_DosPrintQGetInfo(int cnum,char *param,char *data,
  105.                   int mdrcnt,int mprcnt,
  106.                   char **rdata,char **rparam,
  107.                   int *rdata_len,int *rparam_len)
  108. {
  109.   char *p = skip_string(param+2,2);
  110.   char *QueueName = p;
  111.   int uLevel,cbBuf;
  112.   int count=0,i;
  113.   print_queue_struct *queue=NULL;
  114.   char *p2;
  115.   int snum;
  116.  
  117.   p = skip_string(p,1);
  118.   uLevel = SVAL(p,0);
  119.   cbBuf = SVAL(p,2);
  120.  
  121.   if (uLevel == 0)
  122.     return(True);
  123.  
  124.   snum = lp_servicenumber(QueueName);
  125.   if (snum < 0 && pcap_printername_ok(QueueName,NULL))
  126.     {
  127.       int pnum = lp_servicenumber(PRINTERS_NAME);
  128.       if (pnum >= 0)
  129.     {
  130.       lp_add_printer(QueueName,pnum);
  131.       snum = lp_servicenumber(QueueName);
  132.     }
  133.     }
  134.       
  135.   if (snum >= 0)
  136.     {
  137.       unbecome_user();
  138.       count = get_printqueue(lp_servicenumber(QueueName),&queue);
  139.       become_user(cnum);
  140.     }
  141.  
  142.   *rparam_len = 6;
  143.   *rparam = Realloc(*rparam,*rparam_len);
  144.  
  145.   *rdata_len = 13 + 1 + 30; 
  146.   *rdata = Realloc(*rdata,*rdata_len + 100 + count*(74+200));
  147.  
  148.   p2 = (*rdata) + 44 + count*74; /* auxillery data (strings) will go here */
  149.  
  150.   SSVAL(*rparam,0,NERR_Success);
  151.   SSVAL(*rparam,2,0); /* converter word */
  152.   SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
  153.  
  154.   p = *rdata;
  155.  
  156.   StrnCpy(p,QueueName,13);
  157.   p += 13 + 1;
  158.   SSVAL(p,0,0); /* priority */
  159.   SSVAL(p,2,0); /* start time */
  160.   SSVAL(p,4,0); /* until time */
  161.   SIVAL(p,6,0); /* pSepFile */
  162.   SIVAL(p,10,0); /* pPrProc */
  163.   SIVAL(p,14,0); /* pDestinations */
  164.   SIVAL(p,18,0); /* pParms */
  165.  
  166.   SIVAL(p,22,PTR_DIFF(p2,*rdata)); /* pComment */
  167.   {
  168.     extern pstring myhostname;
  169.     pstring comment="";
  170.     strcpy(comment,lp_serverstring());
  171.     string_sub(comment,"%v",VERSION);
  172.     string_sub(comment,"%h",myhostname);
  173.     strcpy(p2,comment);
  174.   }
  175.   p2 = skip_string(p2,1);
  176.  
  177.   SSVAL(p,26,0); /* status */
  178.   SSVAL(p,28,count); /* num jobs */
  179.   p += 30;
  180.  
  181.   for (i=0;i<count;i++)
  182.     {
  183.       SSVAL(p,0,queue[i].job);
  184.       StrnCpy(p+2,queue[i].user,21);
  185.       StrnCpy(p+24,"",16); /* notify name */
  186.       StrnCpy(p+40,"",10); /* data type */
  187.       SIVAL(p,50,0); /* pParams */
  188.       SSVAL(p,54,i); /* position */
  189.       SSVAL(p,56,queue[i].status); /* status */
  190.       SIVAL(p,58,0); /* pStatus string */
  191.       SIVAL(p,62,queue[i].time); /* submit time */
  192.       SIVAL(p,66,queue[i].size); /* job size */
  193.  
  194.       SIVAL(p,70,PTR_DIFF(p2,*rdata));
  195.       strcpy(p2,queue[i].file);
  196.       p2 = skip_string(p2,1);      
  197.  
  198.       p += 74;
  199.     }
  200.  
  201.   *rdata_len = PTR_DIFF(p2,*rdata);
  202.  
  203.   if (queue) free(queue);
  204.  
  205.   DEBUG(3,("DosPrintQGetInfo on <%s> gave %d entries\n",QueueName,count));
  206.   return(True);
  207. }
  208.  
  209.  
  210. /****************************************************************************
  211. view list of shares available
  212. ****************************************************************************/
  213. BOOL api_RNetShareEnum(int cnum,char *param,char *data,
  214.          int mdrcnt,int mprcnt,
  215.          char **rdata,char **rparam,
  216.          int *rdata_len,int *rparam_len)
  217. {
  218.   char *p = skip_string(param+2,2);
  219.   int level = SVAL(p,0);
  220.   int buf_len = SVAL(p,2);
  221.   char *p2;
  222.   int count=lp_numservices();
  223.   int total=0,counted=0;
  224.   int comment_len=0;
  225.   int i;
  226.   BOOL squeezed = False;
  227.  
  228.   for (i=0;i<count;i++)
  229.     if (lp_browseable(i))
  230.       {
  231.     total++;
  232.     comment_len += strlen(lp_comment(i)) + 1;
  233.       }
  234.  
  235.   *rparam_len = 8;
  236.   *rparam = Realloc(*rparam,*rparam_len);
  237.  
  238.   *rdata_len = total*20 + comment_len;
  239.   *rdata = Realloc(*rdata,*rdata_len);
  240.   memset(*rdata,0,*rdata_len);
  241.  
  242.   total = MIN(total,buf_len/25);
  243.  
  244.   p2 = (*rdata) + total*20; /* auxillery data (strings) will go here */
  245.  
  246.   p = *rdata;
  247.  
  248.   for (i=0;i<count && counted<total;i++)
  249.     if (lp_browseable(i))
  250.       {
  251.     int type = 0;
  252.     
  253.     if (lp_print_ok(i)) type = 1;
  254.     if (strequal("IPC$",lp_servicename(i))) type = 3;
  255.  
  256.     StrnCpy(p,lp_servicename(i),13);      
  257.     CVAL(p,13) = 0; /* pad */
  258.     SSVAL(p,14,type); /* device type */
  259.     SIVAL(p,16,PTR_DIFF(p2,(*rdata)));
  260.     strcpy(p2,lp_comment(i));
  261.     
  262.     if (!squeezed &&
  263.         PTR_DIFF(skip_string(p2,1),*rdata) < (buf_len-2))
  264.       p2 = skip_string(p2,1);
  265.     else
  266.       squeezed = True;
  267.  
  268.     p += 20;
  269.     counted++;
  270.       }
  271.  
  272.  
  273.   if (squeezed)
  274.     {
  275.       strcpy(p2,"-");
  276.       p2 += 2;
  277.     }
  278.  
  279.   if (counted < total)
  280.     {
  281.       safe_memcpy((*rdata) + counted*20,(*rdata) + total*20,
  282.           PTR_DIFF(p2,(*rdata) + total*20)+2);
  283.       p2 -= (total-counted)*20;      
  284.     }
  285.  
  286.   *rdata_len = PTR_DIFF(p2,(*rdata));
  287.  
  288.   SSVAL(*rparam,0,NERR_Success);
  289.   SSVAL(*rparam,2,(total-counted)*20); /* converter word */
  290.   SSVAL(*rparam,4,counted);
  291.   SSVAL(*rparam,6,total);
  292.  
  293.   DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
  294.        counted,total,level,
  295.        buf_len,*rdata_len,mdrcnt));
  296.   return(True);
  297. }
  298.  
  299.  
  300.  
  301. /****************************************************************************
  302. get the time of day info
  303. ****************************************************************************/
  304. BOOL api_NetRemoteTOD(int cnum,char *param,char *data,
  305.               int mdrcnt,int mprcnt,
  306.               char **rdata,char **rparam,
  307.               int *rdata_len,int *rparam_len)
  308. {
  309.   char *p;
  310.   *rparam_len = 6;
  311.   *rparam = Realloc(*rparam,*rparam_len);
  312.  
  313.   *rdata_len = 21;
  314.   *rdata = Realloc(*rdata,*rdata_len);
  315.  
  316.   SSVAL(*rparam,0,NERR_Success);
  317.   SSVAL(*rparam,2,0); /* converter word */
  318.   SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
  319.  
  320.   p = *rdata;
  321.  
  322.   {
  323.     struct tm *t;
  324.     time_t unixdate = time(NULL);
  325.  
  326.     t = LocalTime(&unixdate,GMT_TO_LOCAL);
  327.  
  328.     SIVAL(p,0,unixdate + GMT_TO_LOCAL*TimeDiff()); /* elapsedt 
  329.                               since 1-1-1970 in 
  330.                               seconds */
  331.     SIVAL(p,4,0); /* msecs ? */
  332.     CVAL(p,8) = t->tm_hour;
  333.     CVAL(p,9) = t->tm_min;
  334.     CVAL(p,10) = t->tm_sec;
  335.     CVAL(p,11) = 0; /* hundredths of seconds */
  336.     SSVAL(p,12,TimeDiff()/60); /* timezone in minutes from GMT */
  337.     SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
  338.     CVAL(p,16) = t->tm_mday;
  339.     CVAL(p,17) = t->tm_mon + 1;
  340.     SSVAL(p,18,t->tm_year);
  341.     CVAL(p,20) = t->tm_wday;
  342.   }
  343.  
  344.  
  345.   return(True);
  346. }
  347.  
  348. /****************************************************************************
  349. set the user password
  350. ****************************************************************************/
  351. BOOL api_SetUserPassword(int cnum,char *param,char *data,
  352.              int mdrcnt,int mprcnt,
  353.              char **rdata,char **rparam,
  354.              int *rdata_len,int *rparam_len)
  355. {
  356.   char *p = skip_string(param+2,2);
  357.   char *user = p;
  358.   fstring pass1,pass2;
  359.  
  360.   p = skip_string(p,1);
  361.  
  362.   StrnCpy(pass1,p,16);
  363.   StrnCpy(pass2,p+16,16);
  364.  
  365.   *rparam_len = 6;
  366.   *rparam = Realloc(*rparam,*rparam_len);
  367.  
  368.   *rdata_len = 0;
  369.  
  370.   SSVAL(*rparam,0,NERR_Success);
  371.   SSVAL(*rparam,2,0); /* converter word */
  372.   SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
  373.  
  374.   DEBUG(3,("Set password for <%s>\n",user));
  375.  
  376.   if (!password_ok(user,pass1,NULL) || !set_user_password(user,pass1,pass2))
  377.     SSVAL(*rparam,0,NERR_badpass);
  378.  
  379.   memset(pass1,0,sizeof(fstring));
  380.   memset(pass2,0,sizeof(fstring));     
  381.      
  382.   return(True);
  383. }
  384.  
  385.  
  386. /****************************************************************************
  387. the request is not supported
  388. ****************************************************************************/
  389. BOOL api_Unsupported(int cnum,char *param,char *data,
  390.              int mdrcnt,int mprcnt,
  391.              char **rdata,char **rparam,
  392.              int *rdata_len,int *rparam_len)
  393. {
  394.   *rparam_len = 6;
  395.   *rparam = Realloc(*rparam,*rparam_len);
  396.  
  397.   *rdata_len = 0;
  398.  
  399.   SSVAL(*rparam,0,NERR_notsupported);
  400.   SSVAL(*rparam,2,0); /* converter word */
  401.   SSVAL(*rparam,4,*rdata_len); /* length of rdata struct */
  402.      
  403.   DEBUG(3,("Unsupported API command\n"));
  404.  
  405.   return(True);
  406. }
  407.  
  408.  
  409.  
  410.  
  411. struct
  412. {
  413.   char *name;
  414.   int id;
  415.   BOOL (*fn)();
  416.   int flags;
  417. } api_commands[] = {
  418.   {"DosPrintQGetInfo",70,api_DosPrintQGetInfo,0},
  419.   {"NetRemoteTOD",91,api_NetRemoteTOD,0},
  420.   {"SetUserPassword",115,api_SetUserPassword,0},
  421.   {"RNetShareEnum",0,api_RNetShareEnum,0},
  422.   {NULL,-1,api_Unsupported,0}};
  423.  
  424.  
  425. /****************************************************************************
  426. handle remote api calls
  427. ****************************************************************************/
  428. int api_reply(int cnum,char *outbuf,char *data,char *params,
  429.            int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
  430. {
  431.   int api_command = SVAL(params,0);
  432.   char *rdata = NULL;
  433.   char *rparam = NULL;
  434.   int rdata_len = 0;
  435.   int rparam_len = 0;
  436.   BOOL reply=False;
  437.   int i;
  438.  
  439.   DEBUG(5,("Got API command %d of form <%s> <%s> \n",
  440.        api_command,params+2,skip_string(params+2,1)));
  441.  
  442.   for (i=0;api_commands[i].name;i++)
  443.     if (api_commands[i].id == api_command && api_commands[i].fn)
  444.       {
  445.     DEBUG(3,("Doing %s\n",api_commands[i].name));
  446.     break;
  447.       }
  448.  
  449.   reply = api_commands[i].fn(cnum,params,data,mdrcnt,mprcnt,
  450.                  &rdata,&rparam,&rdata_len,&rparam_len);
  451.  
  452.   /* now send the reply - assuming there is one */
  453.   if (reply)
  454.     send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
  455.  
  456.   if (rdata)
  457.     free(rdata);
  458.   if (rparam)
  459.     free(rparam);
  460.   
  461.   return(reply?-1:0);
  462. }
  463.  
  464. /****************************************************************************
  465. handle named pipe commands
  466. ****************************************************************************/
  467. int named_pipe(int cnum,char *outbuf,char *name,
  468.            uint16 *setup,char *data,char *params,
  469.            int suwcnt,int tdscnt,int tpscnt,
  470.            int msrcnt,int mdrcnt,int mprcnt)
  471. {
  472.  
  473.   if (strequal(name,"LANMAN"))
  474.     return(api_reply(cnum,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
  475.  
  476.   DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
  477.        name,(int)setup[0],(int)setup[1]));
  478.   
  479.   return(0);
  480. }
  481.  
  482.  
  483. /****************************************************************************
  484.   reply to a SMBtrans
  485. ****************************************************************************/
  486. int reply_trans(char *inbuf,char *outbuf)
  487. {
  488.   fstring name;
  489.  
  490.   char *data=NULL,*params=NULL;
  491.   uint16 *setup=NULL;
  492.  
  493.   int outsize = 0;
  494.   int cnum = SVAL(inbuf,smb_tid);
  495.  
  496.   int tpscnt = SVAL(inbuf,smb_vwv0);
  497.   int tdscnt = SVAL(inbuf,smb_vwv1);
  498.   int mprcnt = SVAL(inbuf,smb_vwv2);
  499.   int mdrcnt = SVAL(inbuf,smb_vwv3);
  500.   int msrcnt = CVAL(inbuf,smb_vwv4);
  501.   BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
  502.   BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
  503.   int pscnt = SVAL(inbuf,smb_vwv9);
  504.   int psoff = SVAL(inbuf,smb_vwv10);
  505.   int dscnt = SVAL(inbuf,smb_vwv11);
  506.   int dsoff = SVAL(inbuf,smb_vwv12);
  507.   int suwcnt = CVAL(inbuf,smb_vwv13);
  508.  
  509.   StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
  510.   
  511.   if (tdscnt)
  512.     {
  513.       data = (char *)malloc(tdscnt);
  514.       memcpy(data,inbuf+4+dsoff,dscnt);
  515.     }
  516.   if (tpscnt)
  517.     {
  518.       params = (char *)malloc(tpscnt);
  519.       memcpy(params,inbuf+4+psoff,pscnt);
  520.     }
  521.  
  522.   if (suwcnt)
  523.     {
  524.       int i;
  525.       setup = (uint16 *)malloc(suwcnt*sizeof(uint16));
  526.       for (i=0;i<suwcnt;i++)
  527.     setup[i] = SVAL(inbuf,smb_vwv14+i*sizeof(WORD));
  528.     }
  529.  
  530.  
  531.   if (pscnt < tpscnt || dscnt < tdscnt)
  532.     {
  533.       /* We need to send an interim response then receive the rest
  534.      of the parameter/data bytes */
  535.       outsize = set_message(outbuf,0,0,True);
  536.       show_msg(outbuf);
  537.       send_smb(outbuf);
  538.     }
  539.  
  540.   /* receive the rest of the trans packet */
  541.   while (pscnt < tpscnt || dscnt < tdscnt)
  542.     {
  543.       int pcnt,poff,dcnt,doff,pdisp,ddisp;
  544.  
  545.       receive_smb(inbuf, 0);
  546.       show_msg(inbuf);
  547.       
  548.       /* Ensure this is still a trans packet (sanity check) */
  549.       if(CVAL(inbuf, smb_com) != SMBtrans)
  550.     {
  551.       DEBUG(0,("Invalid secondary trans2 packet\n"));
  552.       if (params) free(params);
  553.       if (data) free(data);
  554.       if (setup) free(setup);
  555.       return(ERROR(ERRSRV,ERRerror));
  556.     }
  557.       
  558.       tpscnt = SVAL(inbuf,smb_vwv0);
  559.       tdscnt = SVAL(inbuf,smb_vwv1);
  560.  
  561.       pcnt = SVAL(inbuf,smb_vwv2);
  562.       poff = SVAL(inbuf,smb_vwv3);
  563.       pdisp = SVAL(inbuf,smb_vwv4);
  564.       
  565.       dcnt = SVAL(inbuf,smb_vwv5);
  566.       doff = SVAL(inbuf,smb_vwv6);
  567.       ddisp = SVAL(inbuf,smb_vwv7);
  568.       
  569.       pscnt += pcnt;
  570.       dscnt += dcnt;
  571.  
  572.       if (pcnt)
  573.     memcpy(params+pdisp,inbuf+4+poff,pcnt);
  574.       if (dcnt)
  575.     memcpy(data+ddisp,inbuf+4+doff,dcnt);      
  576.     }
  577.  
  578.  
  579.   DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
  580.   
  581.  
  582.   if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
  583.     outsize = named_pipe(cnum,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
  584.              suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
  585.  
  586.  
  587.   if (data) free(data);
  588.   if (params) free(params);
  589.   if (setup) free(setup);
  590.  
  591.   if (close_on_completion)
  592.     close_cnum(cnum);
  593.  
  594.   if (one_way)
  595.     return(-1);
  596.   
  597.   if (outsize == 0)
  598.     return(ERROR(ERRSRV,ERRnosupport));
  599.  
  600.   return(outsize);
  601. }
  602.  
  603.  
  604.