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