source: src/router/proftpd/contrib/mod_sftp/msg.c @ 14677

Last change on this file since 14677 was 14677, checked in by BrainSlayer, 3 years ago

missing files

File size: 8.7 KB
Line 
1/*
2 * ProFTPD - mod_sftp message format
3 * Copyright (c) 2008-2009 TJ Saunders
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
18 *
19 * As a special exemption, TJ Saunders and other respective copyright holders
20 * give permission to link this program with OpenSSL, and distribute the
21 * resulting executable, without including the source code for OpenSSL in the
22 * source distribution.
23 *
24 * $Id: msg.c,v 1.2 2009/02/13 23:41:19 castaglia Exp $
25 */
26
27#include "mod_sftp.h"
28#include "ssh2.h"
29#include "msg.h"
30#include "crypto.h"
31#include "disconnect.h"
32
33/* The scratch buffer used by getbuf() is a constant 8KB.  If the caller
34 * requests a larger size than that, the request is fulfilled using the
35 * caller-provided pool.
36 */
37static char msg_buf[8 * 1024];
38
39char *sftp_msg_getbuf(pool *p, size_t sz) {
40  if (sz <= sizeof(msg_buf)) {
41    return msg_buf;
42  }
43
44  return palloc(p, sz);
45}
46
47char sftp_msg_read_byte(pool *p, char **buf, uint32_t *buflen) {
48  char byte;
49
50  (void) p;
51
52  if (*buflen < sizeof(char)) {
53    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
54      "message format error: unable to read byte (buflen = %lu)",
55      (unsigned long) *buflen);
56    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
57  }
58
59  memcpy(&byte, *buf, sizeof(char));
60  (*buf) += sizeof(char);
61  (*buflen) -= sizeof(char);
62
63  return byte;
64}
65
66int sftp_msg_read_bool(pool *p, char **buf, uint32_t *buflen) {
67  char bool;
68
69  (void) p;
70
71  bool = sftp_msg_read_byte(p, buf, buflen);
72  if (bool == 0)
73    return 0;
74
75  return 1;
76}
77
78char *sftp_msg_read_data(pool *p, char **buf, uint32_t *buflen,
79    size_t datalen) {
80  char *data;
81
82  if (*buflen < datalen) {
83    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
84      "message format error: unable to read %u bytes of raw data "
85      "(buflen = %lu)", (unsigned int) datalen, (unsigned long) *buflen);
86    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
87  }
88
89  data = palloc(p, datalen);
90
91  memcpy(data, *buf, datalen);
92  (*buf) += datalen;
93  (*buflen) -= datalen;
94
95  return data;
96}
97
98uint32_t sftp_msg_read_int(pool *p, char **buf, uint32_t *buflen) {
99  uint32_t val;
100
101  (void) p;
102
103  if (*buflen < sizeof(uint32_t)) {
104    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
105      "message format error: unable to read int (buflen = %lu)",
106      (unsigned long) *buflen);
107    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
108  }
109
110  memcpy(&val, *buf, sizeof(uint32_t));
111  (*buf) += sizeof(uint32_t);
112  (*buflen) -= sizeof(uint32_t);
113
114  val = ntohl(val);
115  return val;
116}
117
118BIGNUM *sftp_msg_read_mpint(pool *p, char **buf, uint32_t *buflen) {
119  BIGNUM *mpint = NULL;
120  const unsigned char *data = NULL;
121  uint32_t datalen;
122
123  datalen = sftp_msg_read_int(p, buf, buflen);
124
125  if (*buflen < datalen) {
126    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
127      "message format error: unable to read %lu bytes of mpint (buflen = %lu)",
128      (unsigned long) datalen, (unsigned long) *buflen);
129    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
130  }
131
132  if (datalen > (1024 * 16)) {
133    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
134      "message format error: unable to handle mpint of %lu bytes",
135      (unsigned long) datalen);
136    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
137  }
138
139  data = (const unsigned char *) sftp_msg_read_data(p, buf, buflen, datalen);
140  if (data == NULL) {
141    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
142      "message format error: unable to read %lu bytes of mpint data",
143      (unsigned long) datalen);
144    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
145  }
146
147  if (data[0] & 0x80) {
148    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
149      "message format error: negative mpint numbers not supported");
150    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
151  }
152
153  mpint = BN_bin2bn(data, (int) datalen, NULL);
154  if (mpint == NULL) {
155    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
156      "message format error: unable to convert binary mpint: %s",
157      sftp_crypto_get_errors());
158    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
159  }
160
161  return mpint;
162}
163
164char *sftp_msg_read_string(pool *p, char **buf, uint32_t *buflen) {
165  uint32_t len;
166  char *str;
167
168  len = sftp_msg_read_int(p, buf, buflen);
169
170  /* We can't use sftp_msg_read_data() here, since we need to allocate and
171   * populate a buffer that is one byte longer than the len just read in,
172   * for the terminating NUL.
173   */
174
175  if (*buflen < len) {
176    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
177      "message format error: unable to read %lu bytes of string data "
178      "(buflen = %lu)", (unsigned long) len, (unsigned long) *buflen);
179    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
180  }
181
182  str = palloc(p, len + 1);
183
184  memcpy(str, *buf, len);
185  (*buf) += len;
186  (*buflen) -= len;
187  str[len] = '\0';
188
189  return str;
190}
191
192void sftp_msg_write_byte(char **buf, uint32_t *buflen, char byte) {
193  if (*buflen < sizeof(char)) {
194    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
195      "message format error: unable to write byte (buflen = %lu)",
196      (unsigned long) *buflen);
197    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
198  }
199
200  memcpy(*buf, &byte, sizeof(char));
201  (*buf) += sizeof(char);
202  (*buflen) -= sizeof(char);
203}
204
205void sftp_msg_write_bool(char **buf, uint32_t *buflen, char bool) {
206  sftp_msg_write_byte(buf, buflen, bool == 0 ? 0 : 1);
207}
208
209void sftp_msg_write_data(char **buf, uint32_t *buflen, const char *data,
210   size_t datalen, int write_len) {
211
212  if (write_len)
213    sftp_msg_write_int(buf, buflen, datalen);
214
215  if (*buflen < datalen) {
216    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
217      "message format error: unable to write %u bytes of raw data "
218      "(buflen = %lu)", (unsigned int) datalen, (unsigned long) *buflen);
219    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
220  }
221
222  if (datalen > 0) {
223    memcpy(*buf, data, datalen);
224    (*buf) += datalen;
225    (*buflen) -= datalen;
226  }
227}
228
229void sftp_msg_write_int(char **buf, uint32_t *buflen, uint32_t val) {
230  if (*buflen < sizeof(uint32_t)) {
231    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
232      "message format error: unable to write int (buflen = %lu)",
233      (unsigned long) *buflen);
234    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
235  }
236
237  val = htonl(val);
238  memcpy(*buf, &val, sizeof(uint32_t));
239  (*buf) += sizeof(uint32_t);
240  (*buflen) -= sizeof(uint32_t);
241}
242
243void sftp_msg_write_mpint(char **buf, uint32_t *buflen,
244    const BIGNUM *mpint) {
245  unsigned char *data;
246  size_t datalen;
247  int res;
248
249  if (BN_is_zero(mpint)) {
250    sftp_msg_write_int(buf, buflen, 0);
251    return;
252  }
253
254  if (mpint->neg) {
255    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
256      "message format error: unable to write mpint (negative numbers not "
257      "supported)");
258    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
259  }
260
261  datalen = BN_num_bytes(mpint) + 1;
262
263  if (*buflen < datalen) {
264    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
265      "message format error: unable to write %u bytes of mpint (buflen = %lu)",
266      (unsigned int) datalen, (unsigned long) *buflen);
267    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
268  }
269
270  data = malloc(datalen);
271  if (data == NULL) {
272    pr_log_pri(PR_LOG_CRIT, MOD_SFTP_VERSION ": Out of memory!");
273    _exit(1);
274  }
275
276  data[0] = 0;
277
278  res = BN_bn2bin(mpint, data + 1);
279  if (res < 0 ||
280      res != (datalen - 1)) {
281    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
282      "message format error: BN_bn2bin() failed: expected %lu bytes, got %d",
283      (unsigned long) (datalen - 1), res);
284    pr_memscrub(data, datalen);
285    free(data);
286
287    SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
288  }
289
290  if (data[1] & 0x80) {
291    sftp_msg_write_data(buf, buflen, (char *) data, datalen, TRUE);
292
293  } else {
294    sftp_msg_write_data(buf, buflen, (char *) data + 1, datalen - 1, TRUE);
295  }
296
297  pr_memscrub(data, datalen);
298  free(data);
299}
300
301void sftp_msg_write_string(char **buf, uint32_t *buflen, const char *str) {
302  uint32_t len;
303
304  len = strlen(str);
305  sftp_msg_write_data(buf, buflen, str, len, TRUE);
306}
Note: See TracBrowser for help on using the repository browser.