summaryrefslogtreecommitdiffstats
path: root/source3/smbd/smb1_message.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/smb1_message.c')
-rw-r--r--source3/smbd/smb1_message.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/source3/smbd/smb1_message.c b/source3/smbd/smb1_message.c
new file mode 100644
index 0000000..edce398
--- /dev/null
+++ b/source3/smbd/smb1_message.c
@@ -0,0 +1,336 @@
+/*
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+/*
+ This file handles the messaging system calls for winpopup style
+ messages
+*/
+
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "smbprofile.h"
+#include "source3/lib/substitute.h"
+
+extern userdom_struct current_user_info;
+
+struct msg_state {
+ char *from;
+ char *to;
+ char *msg;
+};
+
+/****************************************************************************
+ Deliver the message.
+****************************************************************************/
+
+static void msg_deliver(struct msg_state *state)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ 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, lp_sub))) {
+ 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, lp_sub);
+ 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.
+ conn POINTER CAN BE NULL HERE !
+****************************************************************************/
+
+void reply_sends(struct smb_request *req)
+{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ struct msg_state *state;
+ int len;
+ const uint8_t *msg;
+ const uint8_t *p;
+
+ START_PROFILE(SMBsends);
+
+ if (!(*lp_message_command(talloc_tos(), lp_sub))) {
+ reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ END_PROFILE(SMBsends);
+ return;
+ }
+
+ state = talloc_zero(talloc_tos(), struct msg_state);
+
+ 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;
+
+ msg = p;
+
+ len = SVAL(msg,0);
+ len = MIN(len, smbreq_bufrem(req, msg+2));
+
+ state->msg = talloc_array(state, char, len);
+
+ if (state->msg == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsends);
+ return;
+ }
+
+ memcpy(state->msg, msg+2, len);
+
+ msg_deliver(state);
+
+ reply_smb1_outbuf(req, 0, 0);
+
+ END_PROFILE(SMBsends);
+ return;
+}
+
+/****************************************************************************
+ Reply to a sendstrt.
+ conn POINTER CAN BE NULL HERE !
+****************************************************************************/
+
+void reply_sendstrt(struct smb_request *req)
+{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ struct smbXsrv_connection *xconn = req->xconn;
+ const uint8_t *p;
+
+ START_PROFILE(SMBsendstrt);
+
+ if (!(*lp_message_command(talloc_tos(), lp_sub))) {
+ reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ END_PROFILE(SMBsendstrt);
+ return;
+ }
+
+ TALLOC_FREE(xconn->smb1.msg_state);
+
+ xconn->smb1.msg_state = talloc_zero(xconn, struct msg_state);
+
+ if (xconn->smb1.msg_state == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsendstrt);
+ return;
+ }
+
+ 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;
+
+ DEBUG(3, ("SMBsendstrt (from %s to %s)\n",
+ xconn->smb1.msg_state->from,
+ xconn->smb1.msg_state->to));
+
+ reply_smb1_outbuf(req, 0, 0);
+
+ END_PROFILE(SMBsendstrt);
+ return;
+}
+
+/****************************************************************************
+ Reply to a sendtxt.
+ conn POINTER CAN BE NULL HERE !
+****************************************************************************/
+
+void reply_sendtxt(struct smb_request *req)
+{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ struct smbXsrv_connection *xconn = req->xconn;
+ int len;
+ const char *msg;
+ char *tmp;
+ size_t old_len;
+
+ START_PROFILE(SMBsendtxt);
+
+ if (! (*lp_message_command(talloc_tos(), lp_sub))) {
+ reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ END_PROFILE(SMBsendtxt);
+ return;
+ }
+
+ if ((xconn->smb1.msg_state == NULL) || (req->buflen < 3)) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ END_PROFILE(SMBsendtxt);
+ return;
+ }
+
+ msg = (const char *)req->buf + 1;
+
+ old_len = talloc_get_size(xconn->smb1.msg_state->msg);
+
+ len = MIN(SVAL(msg, 0), smbreq_bufrem(req, msg+2));
+
+ 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_smb1_outbuf(req, 0, 0);
+
+ END_PROFILE(SMBsendtxt);
+ return;
+}
+
+/****************************************************************************
+ Reply to a sendend.
+ conn POINTER CAN BE NULL HERE !
+****************************************************************************/
+
+void reply_sendend(struct smb_request *req)
+{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ struct smbXsrv_connection *xconn = req->xconn;
+ START_PROFILE(SMBsendend);
+
+ if (! (*lp_message_command(talloc_tos(), lp_sub))) {
+ reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ END_PROFILE(SMBsendend);
+ return;
+ }
+
+ if (xconn->smb1.msg_state == NULL) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ END_PROFILE(SMBsendend);
+ return;
+ }
+
+ DEBUG(3,("SMBsendend\n"));
+
+ msg_deliver(xconn->smb1.msg_state);
+
+ TALLOC_FREE(xconn->smb1.msg_state);
+
+ reply_smb1_outbuf(req, 0, 0);
+
+ END_PROFILE(SMBsendend);
+ return;
+}