1 /*
2    Unix SMB/CIFS implementation.
3    SMB messaging
4    Copyright (C) Andrew Tridgell 1992-1998
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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19 /*
20    This file handles the messaging system calls for winpopup style
21    messages
22 */
23 
24 
25 #include "includes.h"
26 #include "system/filesys.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "smbprofile.h"
30 
31 extern userdom_struct current_user_info;
32 
33 struct msg_state {
34 	char *from;
35 	char *to;
36 	char *msg;
37 };
38 
39 /****************************************************************************
40  Deliver the message.
get_base_model(GtkTreeModel * top_model,GtkTreeIter * top_iter,GtkTreeModel ** model,GtkTreeIter * iter)41 ****************************************************************************/
42 
43 static void msg_deliver(struct msg_state *state)
44 {
45 	TALLOC_CTX *frame = talloc_stackframe();
46 	const struct loadparm_substitution *lp_sub =
47 		loadparm_s3_global_substitution();
48 	char *name = NULL;
49 	int i;
50 	int fd;
51 	char *msg;
52 	size_t len;
53 	ssize_t sz;
54 	fstring alpha_buf;
55 	char *s;
56 	mode_t mask;
57 
58 	if (! (*lp_message_command(frame, lp_sub))) {
59 		DEBUG(1,("no messaging command specified\n"));
60 		goto done;
61 	}
62 
63 	/* put it in a temporary file */
64 	name = talloc_asprintf(talloc_tos(), "%s/msg.XXXXXX", tmpdir());
65 	if (!name) {
66 		goto done;
67 	}
68 	mask = umask(S_IRWXO | S_IRWXG);
69 	fd = mkstemp(name);
70 	umask(mask);
71 
72 	if (fd == -1) {
73 		DEBUG(1, ("can't open message file %s: %s\n", name,
74 			  strerror(errno)));
75 		goto done;
76 	}
77 
78 	/*
79 	 * Incoming message is in DOS codepage format. Convert to UNIX.
80 	 */
81 
82 	if (!convert_string_talloc(talloc_tos(), CH_DOS, CH_UNIX, state->msg,
83 				   talloc_get_size(state->msg), (void *)&msg,
84 				   &len)) {
85 		DEBUG(3, ("Conversion failed, delivering message in DOS "
86 			  "codepage format\n"));
87 		msg = state->msg;
88 	}
89 
90 	for (i = 0; i < len; i++) {
91 		if ((msg[i] == '\r') &&
92 		    (i < (len-1)) && (msg[i+1] == '\n')) {
93 			continue;
94 		}
95 		sz = write(fd, &msg[i], 1);
96 		if ( sz != 1 ) {
97 			DEBUG(0, ("Write error to fd %d: %ld(%s)\n", fd,
98 				  (long)sz, strerror(errno)));
99 		}
100 	}
101 
102 	close(fd);
103 
104 	/* run the command */
105 	s = lp_message_command(frame, lp_sub);
106 	if (s == NULL) {
107 		goto done;
108 	}
109 
110 	alpha_strcpy(alpha_buf, state->from, NULL, sizeof(alpha_buf));
111 
112 	s = talloc_string_sub(talloc_tos(), s, "%f", alpha_buf);
113 	if (s == NULL) {
114 		goto done;
115 	}
116 
117 	alpha_strcpy(alpha_buf, state->to, NULL, sizeof(alpha_buf));
118 
119 	s = talloc_string_sub(talloc_tos(), s, "%t", alpha_buf);
120 	if (s == NULL) {
121 		goto done;
122 	}
123 
124 	s = talloc_sub_basic(talloc_tos(), current_user_info.smb_name,
125 			     current_user_info.domain, s);
126 	if (s == NULL) {
127 		goto done;
128 	}
129 
130 	s = talloc_string_sub(talloc_tos(), s, "%s", name);
131 	if (s == NULL) {
132 		goto done;
133 	}
134 	smbrun(s, NULL, NULL);
135 
136  done:
137 	TALLOC_FREE(frame);
138 	return;
139 }
140 
141 /****************************************************************************
142  Reply to a sends.
insert_source_row_into_tree_view(GtkTreeIter iter,GtkWidget * dest,GtkTreeModel * model,gpointer data)143  conn POINTER CAN BE NULL HERE !
144 ****************************************************************************/
145 
146 void reply_sends(struct smb_request *req)
147 {
148 	const struct loadparm_substitution *lp_sub =
149 		loadparm_s3_global_substitution();
150 	struct msg_state *state;
151 	int len;
152 	const uint8_t *msg;
153 	const uint8_t *p;
154 
155 	START_PROFILE(SMBsends);
156 
157 	if (!(*lp_message_command(talloc_tos(), lp_sub))) {
158 		reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
159 		END_PROFILE(SMBsends);
160 		return;
161 	}
162 
163 	state = talloc(talloc_tos(), struct msg_state);
164 
165 	p = req->buf + 1;
166 	p += srvstr_pull_req_talloc(
167 		state, req, &state->from, p, STR_ASCII|STR_TERMINATE) + 1;
168 	p += srvstr_pull_req_talloc(
169 		state, req, &state->to, p, STR_ASCII|STR_TERMINATE) + 1;
170 
171 	msg = p;
172 
173 	len = SVAL(msg,0);
174 	len = MIN(len, smbreq_bufrem(req, msg+2));
175 
176 	state->msg = talloc_array(state, char, len);
177 
178 	if (state->msg == NULL) {
179 		reply_nterror(req, NT_STATUS_NO_MEMORY);
180 		END_PROFILE(SMBsends);
181 		return;
182 	}
183 
184 	memcpy(state->msg, msg+2, len);
185 
186 	msg_deliver(state);
187 
188 	reply_outbuf(req, 0, 0);
189 
190 	END_PROFILE(SMBsends);
191 	return;
192 }
193 
194 /****************************************************************************
195  Reply to a sendstrt.
196  conn POINTER CAN BE NULL HERE !
197 ****************************************************************************/
198 
199 void reply_sendstrt(struct smb_request *req)
200 {
201 	const struct loadparm_substitution *lp_sub =
202 		loadparm_s3_global_substitution();
203 	struct smbXsrv_connection *xconn = req->xconn;
204 	const uint8_t *p;
205 
is_currently_in_varview(GtkTreeModel * model,GtkTreeIter * iter,PsppireSelector * sel)206 	START_PROFILE(SMBsendstrt);
207 
208 	if (!(*lp_message_command(talloc_tos(), lp_sub))) {
209 		reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
210 		END_PROFILE(SMBsendstrt);
211 		return;
212 	}
213 
214 	TALLOC_FREE(xconn->smb1.msg_state);
215 
216 	xconn->smb1.msg_state = talloc_zero(xconn, struct msg_state);
217 
218 	if (xconn->smb1.msg_state == NULL) {
219 		reply_nterror(req, NT_STATUS_NO_MEMORY);
220 		END_PROFILE(SMBsendstrt);
221 		return;
222 	}
223 
224 	p = req->buf+1;
225 	p += srvstr_pull_req_talloc(
226 		xconn->smb1.msg_state, req,
227 		&xconn->smb1.msg_state->from, p,
228 		STR_ASCII|STR_TERMINATE) + 1;
229 	p += srvstr_pull_req_talloc(
230 		xconn->smb1.msg_state, req,
231 		&xconn->smb1.msg_state->to, p,
232 		STR_ASCII|STR_TERMINATE) + 1;
233 
234 	DEBUG(3, ("SMBsendstrt (from %s to %s)\n",
235 		  xconn->smb1.msg_state->from,
236 		  xconn->smb1.msg_state->to));
237 
238 	reply_outbuf(req, 0, 0);
239 
240 	END_PROFILE(SMBsendstrt);
241 	return;
242 }
243 
244 /****************************************************************************
245  Reply to a sendtxt.
246  conn POINTER CAN BE NULL HERE !
247 ****************************************************************************/
248 
249 void reply_sendtxt(struct smb_request *req)
250 {
251 	const struct loadparm_substitution *lp_sub =
252 		loadparm_s3_global_substitution();
253 	struct smbXsrv_connection *xconn = req->xconn;
254 	int len;
255 	const char *msg;
256 	char *tmp;
257 	size_t old_len;
258 
259 	START_PROFILE(SMBsendtxt);
260 
261 	if (! (*lp_message_command(talloc_tos(), lp_sub))) {
262 		reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
263 		END_PROFILE(SMBsendtxt);
264 		return;
265 	}
266 
267 	if ((xconn->smb1.msg_state == NULL) || (req->buflen < 3)) {
268 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
269 		END_PROFILE(SMBsendtxt);
270 		return;
271 	}
272 
273 	msg = (const char *)req->buf + 1;
274 
275 	old_len = talloc_get_size(xconn->smb1.msg_state->msg);
276 
277 	len = MIN(SVAL(msg, 0), smbreq_bufrem(req, msg+2));
278 
279 	tmp = talloc_realloc(xconn->smb1.msg_state,
280 			     xconn->smb1.msg_state->msg,
281 			     char, old_len + len);
282 
283 	if (tmp == NULL) {
284 		reply_nterror(req, NT_STATUS_NO_MEMORY);
285 		END_PROFILE(SMBsendtxt);
286 		return;
287 	}
288 
289 	xconn->smb1.msg_state->msg = tmp;
290 
291 	memcpy(&xconn->smb1.msg_state->msg[old_len], msg+2, len);
292 
293 	DEBUG( 3, ( "SMBsendtxt\n" ) );
294 
295 	reply_outbuf(req, 0, 0);
296 
297 	END_PROFILE(SMBsendtxt);
298 	return;
299 }
300 
301 /****************************************************************************
302  Reply to a sendend.
303  conn POINTER CAN BE NULL HERE !
304 ****************************************************************************/
305 
306 void reply_sendend(struct smb_request *req)
307 {
308 	const struct loadparm_substitution *lp_sub =
309 		loadparm_s3_global_substitution();
310 	struct smbXsrv_connection *xconn = req->xconn;
311 	START_PROFILE(SMBsendend);
312 
313 	if (! (*lp_message_command(talloc_tos(), lp_sub))) {
314 		reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
315 		END_PROFILE(SMBsendend);
316 		return;
317 	}
318 
319 	if (xconn->smb1.msg_state == NULL) {
320 		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
321 		END_PROFILE(SMBsendend);
322 		return;
323 	}
324 
325 	DEBUG(3,("SMBsendend\n"));
326 
327 	msg_deliver(xconn->smb1.msg_state);
328 
329 	TALLOC_FREE(xconn->smb1.msg_state);
330 
331 	reply_outbuf(req, 0, 0);
332 
333 	END_PROFILE(SMBsendend);
334 	return;
335 }
336