s3-talloc Change TALLOC_ZERO_P() to talloc_zero()
[nivanova/samba-autobuild/.git] / source3 / smbd / message.c
index a3625e37168a631f10dc309e880648d6a5cddfd1..63b08e126203148718bd3552f9a82b797ba26566 100644 (file)
@@ -1,12 +1,11 @@
 /* 
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    SMB messaging
    Copyright (C) Andrew Tridgell 1992-1998
    
    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
    SMB messaging
    Copyright (C) Andrew Tridgell 1992-1998
    
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -15,8 +14,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 /*
    This file handles the messaging system calls for winpopup style
 */
 /*
    This file handles the messaging system calls for winpopup style
 
 
 #include "includes.h"
 
 
 #include "includes.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "smbprofile.h"
 
 extern userdom_struct current_user_info;
 
 
 extern userdom_struct current_user_info;
 
-/* look in server.c for some explanation of these variables */
-static char msgbuf[1600];
-static int msgpos;
-static fstring msgfrom;
-static fstring msgto;
+struct msg_state {
+       char *from;
+       char *to;
+       char *msg;
+};
 
 /****************************************************************************
 
 /****************************************************************************
-deliver the message
+ Deliver the message.
 ****************************************************************************/
 ****************************************************************************/
-static void msg_deliver(void)
+
+static void msg_deliver(struct msg_state *state)
 {
 {
-  pstring name;
-  int i;
-  int fd;
-
-  if (! (*lp_msg_command()))
-    {
-      DEBUG(1,("no messaging command specified\n"));
-      msgpos = 0;
-      return;
-    }
-
-  /* put it in a temporary file */
-  slprintf(name,sizeof(name)-1, "%s/msg.XXXXXX",tmpdir());
-  fd = smb_mkstemp(name);
-
-  if (fd == -1) {
-    DEBUG(1,("can't open message file %s\n",name));
-    return;
-  }
-
-  /*
-   * Incoming message is in DOS codepage format. Convert to UNIX.
-   */
-
-  if(msgpos > 0) {
-    msgbuf[msgpos] = '\0'; /* Ensure null terminated. */
-  }
-
-  for (i=0;i<msgpos;) {
-    if (msgbuf[i]=='\r' && i<(msgpos-1) && msgbuf[i+1]=='\n') {
-      i++; continue;      
-    }
-    write(fd,&msgbuf[i++],1);
-  }
-  close(fd);
-
-
-  /* run the command */
-  if (*lp_msg_command())
-    {
-      fstring alpha_msgfrom;
-      fstring alpha_msgto;
-      pstring s;
-
-      pstrcpy(s,lp_msg_command());
-      pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom)));
-      pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto)));
-      standard_sub_basic(current_user_info.smb_name, s);
-      pstring_sub(s,"%s",name);
-      smbrun(s,NULL);
-    }
-
-  msgpos = 0;
+       TALLOC_CTX *frame = talloc_stackframe();
+       char *name = NULL;
+       int i;
+       int fd;
+       char *msg;
+       size_t len;
+       ssize_t sz;
+       fstring alpha_buf;
+       char *s;
+
+       if (! (*lp_msg_command())) {
+               DEBUG(1,("no messaging command specified\n"));
+               goto done;
+       }
+
+       /* put it in a temporary file */
+       name = talloc_asprintf(talloc_tos(), "%s/msg.XXXXXX", tmpdir());
+       if (!name) {
+               goto done;
+       }
+       fd = mkstemp(name);
+
+       if (fd == -1) {
+               DEBUG(1, ("can't open message file %s: %s\n", name,
+                         strerror(errno)));
+               goto done;
+       }
+
+       /*
+        * Incoming message is in DOS codepage format. Convert to UNIX.
+        */
+
+       if (!convert_string_talloc(talloc_tos(), CH_DOS, CH_UNIX, state->msg,
+                                  talloc_get_size(state->msg), (void *)&msg,
+                                  &len)) {
+               DEBUG(3, ("Conversion failed, delivering message in DOS "
+                         "codepage format\n"));
+               msg = state->msg;
+       }
+
+       for (i = 0; i < len; i++) {
+               if ((msg[i] == '\r') &&
+                   (i < (len-1)) && (msg[i+1] == '\n')) {
+                       continue;
+               }
+               sz = write(fd, &msg[i], 1);
+               if ( sz != 1 ) {
+                       DEBUG(0, ("Write error to fd %d: %ld(%s)\n", fd,
+                                 (long)sz, strerror(errno)));
+               }
+       }
+
+       close(fd);
+
+       /* run the command */
+       s = talloc_strdup(talloc_tos(), lp_msg_command());
+       if (s == NULL) {
+               goto done;
+       }
+
+       alpha_strcpy(alpha_buf, state->from, NULL, sizeof(alpha_buf));
+
+       s = talloc_string_sub(talloc_tos(), s, "%f", alpha_buf);
+       if (s == NULL) {
+               goto done;
+       }
+
+       alpha_strcpy(alpha_buf, state->to, NULL, sizeof(alpha_buf));
+
+       s = talloc_string_sub(talloc_tos(), s, "%t", alpha_buf);
+       if (s == NULL) {
+               goto done;
+       }
+
+       s = talloc_sub_basic(talloc_tos(), current_user_info.smb_name,
+                            current_user_info.domain, s);
+       if (s == NULL) {
+               goto done;
+       }
+
+       s = talloc_string_sub(talloc_tos(), s, "%s", name);
+       if (s == NULL) {
+               goto done;
+       }
+       smbrun(s,NULL);
+
+ done:
+       TALLOC_FREE(frame);
+       return;
 }
 
 }
 
-
-
 /****************************************************************************
 /****************************************************************************
-  reply to a sends
+ Reply to a sends.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 ****************************************************************************/
-int reply_sends(connection_struct *conn,
-               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+
+void reply_sends(struct smb_request *req)
 {
 {
-  int len;
-  char *msg;
-  int outsize = 0;
-  char *p;
+       struct msg_state *state;
+       int len;
+       const char *msg;
+       const char *p;
 
 
-  START_PROFILE(SMBsends);
+       START_PROFILE(SMBsends);
 
 
-  msgpos = 0;
+       if (!(*lp_msg_command())) {
+               reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+               END_PROFILE(SMBsends);
+               return;
+       }
 
 
-  if (! (*lp_msg_command())) {
-    END_PROFILE(SMBsends);
-    return(ERROR_DOS(ERRSRV,ERRmsgoff));
-  }
+       state = talloc(talloc_tos(), struct msg_state);
 
 
-  outsize = set_message(outbuf,0,0,True);
+       p = (const char *)req->buf + 1;
+       p += srvstr_pull_req_talloc(
+               state, req, &state->from, p, STR_ASCII|STR_TERMINATE) + 1;
+       p += srvstr_pull_req_talloc(
+               state, req, &state->to, p, STR_ASCII|STR_TERMINATE) + 1;
 
 
-  p = smb_buf(inbuf)+1;
-  p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE) + 1;
-  p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE) + 1;
+       msg = p;
 
 
-  msg = p;
+       len = SVAL(msg,0);
+       len = MIN(len, smbreq_bufrem(req, msg+2));
 
 
-  len = SVAL(msg,0);
-  len = MIN(len,sizeof(msgbuf)-msgpos);
+       state->msg = talloc_array(state, char, len);
 
 
-  memset(msgbuf,'\0',sizeof(msgbuf));
+       if (state->msg == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               END_PROFILE(SMBsends);
+               return;
+       }
 
 
-  memcpy(&msgbuf[msgpos],msg+2,len);
-  msgpos += len;
+       memcpy(state->msg, msg+2, len);
 
 
-  msg_deliver();
+       msg_deliver(state);
 
 
-  END_PROFILE(SMBsends);
-  return(outsize);
-}
+       reply_outbuf(req, 0, 0);
 
 
+       END_PROFILE(SMBsends);
+       return;
+}
 
 /****************************************************************************
 
 /****************************************************************************
-  reply to a sendstrt
+ Reply to a sendstrt.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 ****************************************************************************/
-int reply_sendstrt(connection_struct *conn,
-                  char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+
+void reply_sendstrt(struct smb_request *req)
 {
 {
-  int outsize = 0;
-  char *p;
+       const char *p;
 
 
-  START_PROFILE(SMBsendstrt);
+       START_PROFILE(SMBsendstrt);
 
 
-  if (! (*lp_msg_command())) {
-    END_PROFILE(SMBsendstrt);
-    return(ERROR_DOS(ERRSRV,ERRmsgoff));
-  }
+       if (!(*lp_msg_command())) {
+               reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+               END_PROFILE(SMBsendstrt);
+               return;
+       }
 
 
-  outsize = set_message(outbuf,1,0,True);
+       TALLOC_FREE(smbd_msg_state);
 
 
-  memset(msgbuf,'\0',sizeof(msgbuf));
-  msgpos = 0;
+       smbd_msg_state = talloc_zero(NULL, struct msg_state);
 
 
-  p = smb_buf(inbuf)+1;
-  p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE) + 1;
-  p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE) + 1;
+       if (smbd_msg_state == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               END_PROFILE(SMBsendstrt);
+               return;
+       }
 
 
-  DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) );
+       p = (const char *)req->buf+1;
+       p += srvstr_pull_req_talloc(
+               smbd_msg_state, req, &smbd_msg_state->from, p,
+               STR_ASCII|STR_TERMINATE) + 1;
+       p += srvstr_pull_req_talloc(
+               smbd_msg_state, req, &smbd_msg_state->to, p,
+               STR_ASCII|STR_TERMINATE) + 1;
 
 
-  END_PROFILE(SMBsendstrt);
-  return(outsize);
-}
+       DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", smbd_msg_state->from,
+                   smbd_msg_state->to ) );
 
 
+       reply_outbuf(req, 0, 0);
+
+       END_PROFILE(SMBsendstrt);
+       return;
+}
 
 /****************************************************************************
 
 /****************************************************************************
-  reply to a sendtxt
+ Reply to a sendtxt.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 ****************************************************************************/
-int reply_sendtxt(connection_struct *conn,
-                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+
+void reply_sendtxt(struct smb_request *req)
 {
 {
-  int len;
-  int outsize = 0;
-  char *msg;
-  START_PROFILE(SMBsendtxt);
+       int len;
+       const char *msg;
+       char *tmp;
+       size_t old_len;
 
 
-  if (! (*lp_msg_command())) {
-    END_PROFILE(SMBsendtxt);
-    return(ERROR_DOS(ERRSRV,ERRmsgoff));
-  }
+       START_PROFILE(SMBsendtxt);
 
 
-  outsize = set_message(outbuf,0,0,True);
+       if (! (*lp_msg_command())) {
+               reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+               END_PROFILE(SMBsendtxt);
+               return;
+       }
 
 
-  msg = smb_buf(inbuf) + 1;
+       if ((smbd_msg_state == NULL) || (req->buflen < 3)) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsendtxt);
+               return;
+       }
 
 
-  len = SVAL(msg,0);
-  len = MIN(len,sizeof(msgbuf)-msgpos);
+       msg = (const char *)req->buf + 1;
 
 
-  memcpy(&msgbuf[msgpos],msg+2,len);
-  msgpos += len;
+       old_len = talloc_get_size(smbd_msg_state->msg);
 
 
-  DEBUG( 3, ( "SMBsendtxt\n" ) );
+       len = MIN(SVAL(msg, 0), smbreq_bufrem(req, msg+2));
 
 
-  END_PROFILE(SMBsendtxt);
-  return(outsize);
-}
+       tmp = talloc_realloc(smbd_msg_state, smbd_msg_state->msg,
+                                  char, old_len + len);
+
+       if (tmp == NULL) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               END_PROFILE(SMBsendtxt);
+               return;
+       }
+
+       smbd_msg_state->msg = tmp;
+
+       memcpy(&smbd_msg_state->msg[old_len], msg+2, len);
 
 
+       DEBUG( 3, ( "SMBsendtxt\n" ) );
+
+       reply_outbuf(req, 0, 0);
+
+       END_PROFILE(SMBsendtxt);
+       return;
+}
 
 /****************************************************************************
 
 /****************************************************************************
-  reply to a sendend
+ Reply to a sendend.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 ****************************************************************************/
-int reply_sendend(connection_struct *conn,
-                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+
+void reply_sendend(struct smb_request *req)
 {
 {
-  int outsize = 0;
-  START_PROFILE(SMBsendend);
+       START_PROFILE(SMBsendend);
+
+       if (! (*lp_msg_command())) {
+               reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+               END_PROFILE(SMBsendend);
+               return;
+       }
 
 
-  if (! (*lp_msg_command())) {
-    END_PROFILE(SMBsendend);
-    return(ERROR_DOS(ERRSRV,ERRmsgoff));
-  }
+       DEBUG(3,("SMBsendend\n"));
 
 
-  outsize = set_message(outbuf,0,0,True);
+       msg_deliver(smbd_msg_state);
 
 
-  DEBUG(3,("SMBsendend\n"));
+       TALLOC_FREE(smbd_msg_state);
 
 
-  msg_deliver();
+       reply_outbuf(req, 0, 0);
 
 
-  END_PROFILE(SMBsendend);
-  return(outsize);
+       END_PROFILE(SMBsendend);
+       return;
 }
 }