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