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