Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/smbd/smb1_message.c
Line
Count
Source
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
static void msg_deliver(struct msg_state *state)
43
0
{
44
0
  TALLOC_CTX *frame = talloc_stackframe();
45
0
  const struct loadparm_substitution *lp_sub =
46
0
    loadparm_s3_global_substitution();
47
0
  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
0
  if (! (*lp_message_command(frame, lp_sub))) {
58
0
    DEBUG(1,("no messaging command specified\n"));
59
0
    goto done;
60
0
  }
61
62
  /* put it in a temporary file */
63
0
  name = talloc_asprintf(talloc_tos(), "%s/msg.XXXXXX", tmpdir());
64
0
  if (!name) {
65
0
    goto done;
66
0
  }
67
0
  mask = umask(S_IRWXO | S_IRWXG);
68
0
  fd = mkstemp(name);
69
0
  umask(mask);
70
71
0
  if (fd == -1) {
72
0
    DEBUG(1, ("can't open message file %s: %s\n", name,
73
0
        strerror(errno)));
74
0
    goto done;
75
0
  }
76
77
  /*
78
   * Incoming message is in DOS codepage format. Convert to UNIX.
79
   */
80
81
0
  if (!convert_string_talloc(talloc_tos(), CH_DOS, CH_UNIX, state->msg,
82
0
           talloc_get_size(state->msg), (void *)&msg,
83
0
           &len)) {
84
0
    DEBUG(3, ("Conversion failed, delivering message in DOS "
85
0
        "codepage format\n"));
86
0
    msg = state->msg;
87
0
  }
88
89
0
  for (i = 0; i < len; i++) {
90
0
    if ((msg[i] == '\r') &&
91
0
        (i < (len-1)) && (msg[i+1] == '\n')) {
92
0
      continue;
93
0
    }
94
0
    sz = write(fd, &msg[i], 1);
95
0
    if ( sz != 1 ) {
96
0
      DEBUG(0, ("Write error to fd %d: %ld(%s)\n", fd,
97
0
          (long)sz, strerror(errno)));
98
0
    }
99
0
  }
100
101
0
  close(fd);
102
103
  /* run the command */
104
0
  s = lp_message_command(frame, lp_sub);
105
0
  if (s == NULL) {
106
0
    goto done;
107
0
  }
108
109
0
  alpha_strcpy(alpha_buf, state->from, NULL, sizeof(alpha_buf));
110
111
0
  s = talloc_string_sub(talloc_tos(), s, "%f", alpha_buf);
112
0
  if (s == NULL) {
113
0
    goto done;
114
0
  }
115
116
0
  alpha_strcpy(alpha_buf, state->to, NULL, sizeof(alpha_buf));
117
118
0
  s = talloc_string_sub(talloc_tos(), s, "%t", alpha_buf);
119
0
  if (s == NULL) {
120
0
    goto done;
121
0
  }
122
123
0
  s = talloc_sub_basic(talloc_tos(), get_current_username(),
124
0
           get_current_user_info_domain(), s);
125
0
  if (s == NULL) {
126
0
    goto done;
127
0
  }
128
129
0
  s = talloc_string_sub(talloc_tos(), s, "%s", name);
130
0
  if (s == NULL) {
131
0
    goto done;
132
0
  }
133
0
  smbrun(s, NULL, NULL);
134
135
0
 done:
136
0
  TALLOC_FREE(frame);
137
0
  return;
138
0
}
139
140
/****************************************************************************
141
 Reply to a sends.
142
 conn POINTER CAN BE NULL HERE !
143
****************************************************************************/
144
145
void reply_sends(struct smb_request *req)
146
0
{
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
0
  }
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
0
  }
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
0
}
192
193
/****************************************************************************
194
 Reply to a sendstrt.
195
 conn POINTER CAN BE NULL HERE !
196
****************************************************************************/
197
198
void reply_sendstrt(struct smb_request *req)
199
0
{
200
0
  const struct loadparm_substitution *lp_sub =
201
0
    loadparm_s3_global_substitution();
202
0
  struct smbXsrv_connection *xconn = req->xconn;
203
0
  const uint8_t *p;
204
205
0
  START_PROFILE(SMBsendstrt);
206
207
0
  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
0
  }
212
213
0
  TALLOC_FREE(xconn->smb1.msg_state);
214
215
0
  xconn->smb1.msg_state = talloc_zero(xconn, struct msg_state);
216
217
0
  if (xconn->smb1.msg_state == NULL) {
218
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
219
0
    END_PROFILE(SMBsendstrt);
220
0
    return;
221
0
  }
222
223
0
  p = req->buf+1;
224
0
  p += srvstr_pull_req_talloc(
225
0
    xconn->smb1.msg_state, req,
226
0
    &xconn->smb1.msg_state->from, p,
227
0
    STR_ASCII|STR_TERMINATE) + 1;
228
0
  p += srvstr_pull_req_talloc(
229
0
    xconn->smb1.msg_state, req,
230
0
    &xconn->smb1.msg_state->to, p,
231
0
    STR_ASCII|STR_TERMINATE) + 1;
232
233
0
  DEBUG(3, ("SMBsendstrt (from %s to %s)\n",
234
0
      xconn->smb1.msg_state->from,
235
0
      xconn->smb1.msg_state->to));
236
237
0
  reply_smb1_outbuf(req, 0, 0);
238
239
0
  END_PROFILE(SMBsendstrt);
240
0
  return;
241
0
}
242
243
/****************************************************************************
244
 Reply to a sendtxt.
245
 conn POINTER CAN BE NULL HERE !
246
****************************************************************************/
247
248
void reply_sendtxt(struct smb_request *req)
249
0
{
250
0
  const struct loadparm_substitution *lp_sub =
251
0
    loadparm_s3_global_substitution();
252
0
  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
0
  START_PROFILE(SMBsendtxt);
259
260
0
  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
0
  }
265
266
0
  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
0
  }
271
272
0
  msg = (const char *)req->buf + 1;
273
274
0
  old_len = talloc_get_size(xconn->smb1.msg_state->msg);
275
276
0
  len = MIN(SVAL(msg, 0), smbreq_bufrem(req, msg+2));
277
278
0
  tmp = talloc_realloc(xconn->smb1.msg_state,
279
0
           xconn->smb1.msg_state->msg,
280
0
           char, old_len + len);
281
282
0
  if (tmp == NULL) {
283
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
284
0
    END_PROFILE(SMBsendtxt);
285
0
    return;
286
0
  }
287
288
0
  xconn->smb1.msg_state->msg = tmp;
289
290
0
  memcpy(&xconn->smb1.msg_state->msg[old_len], msg+2, len);
291
292
0
  DEBUG( 3, ( "SMBsendtxt\n" ) );
293
294
0
  reply_smb1_outbuf(req, 0, 0);
295
296
0
  END_PROFILE(SMBsendtxt);
297
0
  return;
298
0
}
299
300
/****************************************************************************
301
 Reply to a sendend.
302
 conn POINTER CAN BE NULL HERE !
303
****************************************************************************/
304
305
void reply_sendend(struct smb_request *req)
306
0
{
307
0
  const struct loadparm_substitution *lp_sub =
308
0
    loadparm_s3_global_substitution();
309
0
  struct smbXsrv_connection *xconn = req->xconn;
310
0
  START_PROFILE(SMBsendend);
311
312
0
  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
0
  }
317
318
0
  if (xconn->smb1.msg_state == NULL) {
319
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
320
0
    END_PROFILE(SMBsendend);
321
0
    return;
322
0
  }
323
324
0
  DEBUG(3,("SMBsendend\n"));
325
326
0
  msg_deliver(xconn->smb1.msg_state);
327
328
0
  TALLOC_FREE(xconn->smb1.msg_state);
329
330
0
  reply_smb1_outbuf(req, 0, 0);
331
332
0
  END_PROFILE(SMBsendend);
333
0
  return;
334
0
}