/*
- 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
- 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 "system/filesys.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "smbprofile.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;
-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(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;
+ mode_t mask;
+
+ if (! (*lp_message_command(frame))) {
+ 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;
+ }
+ mask = umask(S_IRWXO | S_IRWXG);
+ fd = mkstemp(name);
+ umask(mask);
+
+ 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 = lp_message_command(frame);
+ 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, 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 uint8_t *msg;
+ const uint8_t *p;
- START_PROFILE(SMBsends);
+ START_PROFILE(SMBsends);
- msgpos = 0;
+ if (!(*lp_message_command(talloc_tos()))) {
+ 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 = 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;
+ struct smbXsrv_connection *xconn = req->xconn;
+ const uint8_t *p;
- START_PROFILE(SMBsendstrt);
+ START_PROFILE(SMBsendstrt);
- if (! (*lp_msg_command())) {
- END_PROFILE(SMBsendstrt);
- return(ERROR_DOS(ERRSRV,ERRmsgoff));
- }
+ if (!(*lp_message_command(talloc_tos()))) {
+ reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ END_PROFILE(SMBsendstrt);
+ return;
+ }
- outsize = set_message(outbuf,1,0,True);
+ TALLOC_FREE(xconn->smb1.msg_state);
- memset(msgbuf,'\0',sizeof(msgbuf));
- msgpos = 0;
+ xconn->smb1.msg_state = talloc_zero(xconn, 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 (xconn->smb1.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 = req->buf+1;
+ p += srvstr_pull_req_talloc(
+ xconn->smb1.msg_state, req,
+ &xconn->smb1.msg_state->from, p,
+ STR_ASCII|STR_TERMINATE) + 1;
+ p += srvstr_pull_req_talloc(
+ xconn->smb1.msg_state, req,
+ &xconn->smb1.msg_state->to, p,
+ STR_ASCII|STR_TERMINATE) + 1;
- END_PROFILE(SMBsendstrt);
- return(outsize);
-}
+ DEBUG(3, ("SMBsendstrt (from %s to %s)\n",
+ xconn->smb1.msg_state->from,
+ xconn->smb1.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);
+ struct smbXsrv_connection *xconn = req->xconn;
+ 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_message_command(talloc_tos()))) {
+ reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ END_PROFILE(SMBsendtxt);
+ return;
+ }
- msg = smb_buf(inbuf) + 1;
+ if ((xconn->smb1.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(xconn->smb1.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(xconn->smb1.msg_state,
+ xconn->smb1.msg_state->msg,
+ char, old_len + len);
+
+ if (tmp == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsendtxt);
+ return;
+ }
+
+ xconn->smb1.msg_state->msg = tmp;
+
+ memcpy(&xconn->smb1.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);
+ struct smbXsrv_connection *xconn = req->xconn;
+ START_PROFILE(SMBsendend);
+
+ if (! (*lp_message_command(talloc_tos()))) {
+ 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(xconn->smb1.msg_state);
- DEBUG(3,("SMBsendend\n"));
+ TALLOC_FREE(xconn->smb1.msg_state);
- msg_deliver();
+ reply_outbuf(req, 0, 0);
- END_PROFILE(SMBsendend);
- return(outsize);
+ END_PROFILE(SMBsendend);
+ return;
}