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