/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
SMB messaging
- Copyright (C) Andrew Tridgell 1992-1995
+ 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,
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
#include "includes.h"
+#include "smbd/globals.h"
-/* look in server.c for some explanation of these variables */
-extern int DEBUGLEVEL;
+extern userdom_struct current_user_info;
-
-static char msgbuf[1600];
-static int msgpos=0;
-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 s;
- fstring name;
- FILE *f;
- int i;
-
- if (! (*lp_msg_command()))
- {
- DEBUG(1,("no messaging command specified\n"));
- msgpos = 0;
- return;
- }
-
- /* put it in a temporary file */
- sprintf(s,"/tmp/msg.XXXXXX");
- strcpy(name,(char *)mktemp(s));
-
- f = fopen(name,"w");
- if (!f)
- {
- DEBUG(1,("can't open message file %s\n",name));
- return;
- }
-
- for (i=0;i<msgpos;)
- {
- if (msgbuf[i]=='\r' && i<(msgpos-1) && msgbuf[i+1]=='\n')
- i++;
- fputc(msgbuf[i++],f);
- }
-
- fclose(f);
-
-
- /* run the command */
- if (*lp_msg_command())
- {
- strcpy(s,lp_msg_command());
- string_sub(s,"%s",name);
- string_sub(s,"%f",msgfrom);
- string_sub(s,"%t",msgto);
- standard_sub(-1,s);
- 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, true)) {
+ 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(char *inbuf,char *outbuf)
+
+void reply_sends(struct smb_request *req)
{
- int len;
- char *orig,*dest,*msg;
- int outsize = 0;
+ struct msg_state *state;
+ int len;
+ const char *msg;
+ const char *p;
- msgpos = 0;
+ START_PROFILE(SMBsends);
+ if (!(*lp_msg_command())) {
+ reply_doserror(req, ERRSRV, ERRmsgoff);
+ END_PROFILE(SMBsends);
+ return;
+ }
- if (! (*lp_msg_command()))
- return(ERROR(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;
- orig = smb_buf(inbuf)+1;
- dest = skip_string(orig,1)+1;
- msg = skip_string(dest,1)+1;
+ msg = p;
- strcpy(msgfrom,orig);
- strcpy(msgto,dest);
+ len = SVAL(msg,0);
+ len = MIN(len, smbreq_bufrem(req, msg+2));
- len = SVAL(msg,0);
- len = MIN(len,1600-msgpos);
+ state->msg = talloc_array(state, char, len);
- memcpy(&msgbuf[msgpos],msg+2,len);
- msgpos += len;
+ if (state->msg == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsends);
+ return;
+ }
- DEBUG(3,("%s SMBsends (from %s to %s)\n",timestring(),orig,dest));
+ memcpy(state->msg, msg+2, len);
- msg_deliver();
+ msg_deliver(state);
- 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(char *inbuf,char *outbuf)
+
+void reply_sendstrt(struct smb_request *req)
{
- char *orig,*dest;
- int outsize = 0;
+ const char *p;
- if (! (*lp_msg_command()))
- return(ERROR(ERRSRV,ERRmsgoff));
+ START_PROFILE(SMBsendstrt);
- outsize = set_message(outbuf,1,0,True);
+ if (!(*lp_msg_command())) {
+ reply_doserror(req, ERRSRV, ERRmsgoff);
+ END_PROFILE(SMBsendstrt);
+ return;
+ }
- msgpos = 0;
+ TALLOC_FREE(smbd_msg_state);
- orig = smb_buf(inbuf)+1;
- dest = skip_string(orig,1)+1;
+ smbd_msg_state = TALLOC_ZERO_P(NULL, struct msg_state);
- strcpy(msgfrom,orig);
- strcpy(msgto,dest);
+ if (smbd_msg_state == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsendstrt);
+ return;
+ }
- DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),orig,dest));
+ 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;
- 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(char *inbuf,char *outbuf)
+
+void reply_sendtxt(struct smb_request *req)
{
- int len;
- int outsize = 0;
- char *msg;
+ int len;
+ const char *msg;
+ char *tmp;
+ size_t old_len;
- if (! (*lp_msg_command()))
- return(ERROR(ERRSRV,ERRmsgoff));
+ START_PROFILE(SMBsendtxt);
- outsize = set_message(outbuf,0,0,True);
+ if (! (*lp_msg_command())) {
+ reply_doserror(req, ERRSRV, ERRmsgoff);
+ END_PROFILE(SMBsendtxt);
+ return;
+ }
- msg = smb_buf(inbuf) + 1;
+ if (smbd_msg_state == NULL) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ END_PROFILE(SMBsendtxt);
+ return;
+ }
- len = SVAL(msg,0);
- len = MIN(len,1600-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,("%s SMBsendtxt\n",timestring()));
+ len = MIN(SVAL(msg, 0), smbreq_bufrem(req, msg+2));
- return(outsize);
-}
+ tmp = TALLOC_REALLOC_ARRAY(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(char *inbuf,char *outbuf)
+
+void reply_sendend(struct smb_request *req)
{
- int outsize = 0;
+ START_PROFILE(SMBsendend);
- if (! (*lp_msg_command()))
- return(ERROR(ERRSRV,ERRmsgoff));
+ if (! (*lp_msg_command())) {
+ reply_doserror(req, ERRSRV, ERRmsgoff);
+ END_PROFILE(SMBsendend);
+ return;
+ }
- outsize = set_message(outbuf,0,0,True);
+ DEBUG(3,("SMBsendend\n"));
- DEBUG(3,("%s SMBsendend\n",timestring()));
+ msg_deliver(smbd_msg_state);
- msg_deliver();
+ TALLOC_FREE(smbd_msg_state);
- return(outsize);
-}
+ reply_outbuf(req, 0, 0);
+ END_PROFILE(SMBsendend);
+ return;
+}