1 /*
2 * ProFTPD - mod_sftp message format
3 * Copyright (c) 2008-2019 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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
25 #include "mod_sftp.h"
26 #include "ssh2.h"
27 #include "msg.h"
28 #include "crypto.h"
29 #include "disconnect.h"
30
31 #ifdef PR_USE_OPENSSL_ECC
32 /* Max GFp field length = 528 bits. SEC1 uncompressed encoding uses 2
33 * bitstring points. SEC1 specifies a 1 byte point type header.
34 */
35 # define MAX_ECPOINT_LEN ((528*2 / 8) + 1)
36 #endif /* PR_USE_OPENSSL_ECC */
37
38 /* The scratch buffer used by getbuf() is a constant 8KB. If the caller
39 * requests a larger size than that, the request is fulfilled using the
40 * caller-provided pool.
41 */
42 static unsigned char msg_buf[8 * 1024];
43
44 static const char *trace_channel = "ssh2";
45
sftp_msg_getbuf(pool * p,size_t sz)46 unsigned char *sftp_msg_getbuf(pool *p, size_t sz) {
47 if (sz <= sizeof(msg_buf)) {
48 return msg_buf;
49 }
50
51 return palloc(p, sz);
52 }
53
sftp_msg_read_byte2(pool * p,unsigned char ** buf,uint32_t * buflen,char * byte)54 uint32_t sftp_msg_read_byte2(pool *p, unsigned char **buf, uint32_t *buflen,
55 char *byte) {
56 (void) p;
57
58 if (*buflen < sizeof(char)) {
59 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
60 "message format error: unable to read byte (buflen = %lu)",
61 (unsigned long) *buflen);
62 return 0;
63 }
64
65 memcpy(byte, *buf, sizeof(char));
66 (*buf) += sizeof(char);
67 (*buflen) -= sizeof(char);
68
69 return sizeof(char);
70 }
71
sftp_msg_read_byte(pool * p,unsigned char ** buf,uint32_t * buflen)72 char sftp_msg_read_byte(pool *p, unsigned char **buf, uint32_t *buflen) {
73 char byte = 0;
74 uint32_t len;
75
76 len = sftp_msg_read_byte2(p, buf, buflen, &byte);
77 if (len == 0) {
78 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
79 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
80 }
81
82 return byte;
83 }
84
sftp_msg_read_bool2(pool * p,unsigned char ** buf,uint32_t * buflen,int * bool)85 uint32_t sftp_msg_read_bool2(pool *p, unsigned char **buf, uint32_t *buflen,
86 int *bool) {
87 char byte = 0;
88 uint32_t len;
89
90 (void) p;
91
92 len = sftp_msg_read_byte2(p, buf, buflen, &byte);
93 if (len == 0) {
94 return 0;
95 }
96
97 *bool = byte;
98 return len;
99 }
100
sftp_msg_read_bool(pool * p,unsigned char ** buf,uint32_t * buflen)101 int sftp_msg_read_bool(pool *p, unsigned char **buf, uint32_t *buflen) {
102 int bool = 0;
103 uint32_t len;
104
105 len = sftp_msg_read_bool2(p, buf, buflen, &bool);
106 if (len == 0) {
107 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
108 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
109 }
110
111 if (bool == 0) {
112 return FALSE;
113 }
114
115 return TRUE;
116 }
117
sftp_msg_read_data2(pool * p,unsigned char ** buf,uint32_t * buflen,size_t datalen,unsigned char ** data)118 uint32_t sftp_msg_read_data2(pool *p, unsigned char **buf,
119 uint32_t *buflen, size_t datalen, unsigned char **data) {
120 if (datalen == 0) {
121 return 0;
122 }
123
124 if (*buflen < datalen) {
125 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
126 "message format error: unable to read %lu bytes of raw data "
127 "(buflen = %lu)", (unsigned long) datalen, (unsigned long) *buflen);
128 return 0;
129 }
130
131 *data = palloc(p, datalen);
132
133 memcpy(*data, *buf, datalen);
134 (*buf) += datalen;
135 (*buflen) -= datalen;
136
137 return datalen;
138 }
139
sftp_msg_read_data(pool * p,unsigned char ** buf,uint32_t * buflen,size_t datalen)140 unsigned char *sftp_msg_read_data(pool *p, unsigned char **buf,
141 uint32_t *buflen, size_t datalen) {
142 unsigned char *data = NULL;
143 uint32_t len;
144
145 if (datalen == 0) {
146 errno = EINVAL;
147 return NULL;
148 }
149
150 len = sftp_msg_read_data2(p, buf, buflen, datalen, &data);
151 if (len == 0) {
152 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
153 "message format error: unable to read %lu bytes of raw data "
154 "(buflen = %lu)", (unsigned long) datalen, (unsigned long) *buflen);
155 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
156 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
157 }
158
159 return data;
160 }
161
sftp_msg_read_int2(pool * p,unsigned char ** buf,uint32_t * buflen,uint32_t * val)162 uint32_t sftp_msg_read_int2(pool *p, unsigned char **buf, uint32_t *buflen,
163 uint32_t *val) {
164
165 (void) p;
166
167 if (*buflen < sizeof(uint32_t)) {
168 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
169 "message format error: unable to read int (buflen = %lu)",
170 (unsigned long) *buflen);
171 return 0;
172 }
173
174 memcpy(val, *buf, sizeof(uint32_t));
175 (*buf) += sizeof(uint32_t);
176 (*buflen) -= sizeof(uint32_t);
177
178 *val = ntohl(*val);
179 return sizeof(uint32_t);
180 }
181
sftp_msg_read_int(pool * p,unsigned char ** buf,uint32_t * buflen)182 uint32_t sftp_msg_read_int(pool *p, unsigned char **buf, uint32_t *buflen) {
183 uint32_t val = 0;
184 uint32_t len;
185
186 len = sftp_msg_read_int2(p, buf, buflen, &val);
187 if (len == 0) {
188 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
189 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
190 }
191
192 return val;
193 }
194
sftp_msg_read_long2(pool * p,unsigned char ** buf,uint32_t * buflen,uint64_t * val)195 uint32_t sftp_msg_read_long2(pool *p, unsigned char **buf, uint32_t *buflen,
196 uint64_t *val) {
197 unsigned char data[8];
198
199 if (*buflen < sizeof(data)) {
200 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
201 "message format error: unable to read long (buflen = %lu)",
202 (unsigned long) *buflen);
203 return 0;
204 }
205
206 memcpy(data, *buf, sizeof(data));
207 (*buf) += sizeof(data);
208 (*buflen) -= sizeof(data);
209
210 (*val) = (uint64_t) data[0] << 56;
211 (*val) |= (uint64_t) data[1] << 48;
212 (*val) |= (uint64_t) data[2] << 40;
213 (*val) |= (uint64_t) data[3] << 32;
214 (*val) |= (uint64_t) data[4] << 24;
215 (*val) |= (uint64_t) data[5] << 16;
216 (*val) |= (uint64_t) data[6] << 8;
217 (*val) |= (uint64_t) data[7];
218
219 return sizeof(data);
220 }
221
sftp_msg_read_long(pool * p,unsigned char ** buf,uint32_t * buflen)222 uint64_t sftp_msg_read_long(pool *p, unsigned char **buf, uint32_t *buflen) {
223 uint64_t val = 0;
224 uint32_t len;
225
226 len = sftp_msg_read_long2(p, buf, buflen, &val);
227 if (len == 0) {
228 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
229 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
230 }
231
232 return val;
233 }
234
sftp_msg_read_mpint2(pool * p,unsigned char ** buf,uint32_t * buflen,BIGNUM ** mpint)235 uint32_t sftp_msg_read_mpint2(pool *p, unsigned char **buf, uint32_t *buflen,
236 BIGNUM **mpint) {
237 unsigned char *mpint_data = NULL;
238 const unsigned char *data = NULL, *ptr = NULL;
239 uint32_t datalen = 0, mpint_len = 0, len = 0, total_len = 0;
240
241 len = sftp_msg_read_int2(p, buf, buflen, &mpint_len);
242 if (len == 0) {
243 return 0;
244 }
245
246 if (*buflen < mpint_len) {
247 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
248 "message format error: unable to read %lu bytes of mpint (buflen = %lu)",
249 (unsigned long) len, (unsigned long) *buflen);
250 return 0;
251 }
252
253 if (len > (1024 * 16)) {
254 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
255 "message format error: unable to handle mpint of %lu bytes",
256 (unsigned long) len);
257 return 0;
258 }
259
260 total_len += len;
261
262 len = sftp_msg_read_data2(p, buf, buflen, mpint_len, &mpint_data);
263 if (len == 0) {
264 return 0;
265 }
266
267 total_len += len;
268
269 ptr = (const unsigned char *) mpint_data;
270 if ((ptr[0] & 0x80) != 0) {
271 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
272 "message format error: negative mpint numbers not supported");
273 return 0;
274 }
275
276 /* Trim any leading zeros. */
277 data = ptr;
278 datalen = mpint_len;
279 while (datalen > 0 &&
280 *data == 0x00) {
281 pr_signals_handle();
282 data++;
283 datalen--;
284 }
285
286 *mpint = BN_bin2bn(data, (int) datalen, NULL);
287 if (*mpint == NULL) {
288 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
289 "message format error: unable to convert binary mpint: %s",
290 sftp_crypto_get_errors());
291 return 0;
292 }
293
294 return total_len;
295 }
296
sftp_msg_read_mpint(pool * p,unsigned char ** buf,uint32_t * buflen)297 BIGNUM *sftp_msg_read_mpint(pool *p, unsigned char **buf, uint32_t *buflen) {
298 BIGNUM *mpint = NULL;
299 uint32_t len;
300
301 len = sftp_msg_read_mpint2(p, buf, buflen, &mpint);
302 if (len == 0) {
303 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
304 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
305 }
306
307 return mpint;
308 }
309
sftp_msg_read_string2(pool * p,unsigned char ** buf,uint32_t * buflen,char ** str)310 uint32_t sftp_msg_read_string2(pool *p, unsigned char **buf, uint32_t *buflen,
311 char **str) {
312 uint32_t data_len = 0, len = 0;
313
314 /* If there is no data remaining, treat this as if the string is empty
315 * (see Bug#4093).
316 */
317 if (*buflen == 0) {
318 pr_trace_msg(trace_channel, 9,
319 "malformed message format (buflen = %lu) for reading string, using \"\"",
320 (unsigned long) *buflen);
321 *str = pstrdup(p, "");
322 return 1;
323 }
324
325 len = sftp_msg_read_int2(p, buf, buflen, &data_len);
326 if (len == 0) {
327 return 0;
328 }
329
330 /* We can't use sftp_msg_read_data() here, since we need to allocate and
331 * populate a buffer that is one byte longer than the len just read in,
332 * for the terminating NUL.
333 */
334
335 if (*buflen < data_len) {
336 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
337 "message format error: unable to read %lu bytes of string data "
338 "(buflen = %lu)", (unsigned long) data_len, (unsigned long) *buflen);
339 return 0;
340 }
341
342 *str = palloc(p, data_len + 1);
343
344 if (data_len > 0) {
345 memcpy(*str, *buf, data_len);
346 (*buf) += data_len;
347 (*buflen) -= data_len;
348 }
349 (*str)[data_len] = '\0';
350
351 return len + data_len;
352 }
353
sftp_msg_read_string(pool * p,unsigned char ** buf,uint32_t * buflen)354 char *sftp_msg_read_string(pool *p, unsigned char **buf, uint32_t *buflen) {
355 char *str = NULL;
356 uint32_t len;
357
358 len = sftp_msg_read_string2(p, buf, buflen, &str);
359 if (len == 0) {
360 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
361 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
362 }
363
364 return str;
365 }
366
367 #ifdef PR_USE_OPENSSL_ECC
sftp_msg_read_ecpoint2(pool * p,unsigned char ** buf,uint32_t * buflen,const EC_GROUP * curve,EC_POINT ** point)368 uint32_t sftp_msg_read_ecpoint2(pool *p, unsigned char **buf, uint32_t *buflen,
369 const EC_GROUP *curve, EC_POINT **point) {
370 BN_CTX *bn_ctx;
371 unsigned char *data = NULL;
372 uint32_t datalen = 0, len = 0, total_len = 0;
373
374 len = sftp_msg_read_int2(p, buf, buflen, &datalen);
375 if (len == 0) {
376 return 0;
377 }
378
379 if (*buflen < datalen) {
380 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
381 "message format error: unable to read %lu bytes of EC point"
382 " (buflen = %lu)", (unsigned long) datalen, (unsigned long) *buflen);
383 return 0;
384 }
385
386 if (datalen > MAX_ECPOINT_LEN) {
387 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
388 "message format error: EC point length too long (%lu > max %lu)",
389 (unsigned long) datalen, (unsigned long) MAX_ECPOINT_LEN);
390 return 0;
391 }
392
393 total_len += len;
394
395 len = sftp_msg_read_data2(p, buf, buflen, datalen, &data);
396 if (len == 0) {
397 return 0;
398 }
399
400 if (data == NULL) {
401 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
402 "message format error: unable to read %lu bytes of EC point data",
403 (unsigned long) datalen);
404 return 0;
405 }
406
407 total_len += len;
408
409 if (data[0] != POINT_CONVERSION_UNCOMPRESSED) {
410 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
411 "message format error: EC point data formatted incorrectly "
412 "(leading byte 0x%02x should be 0x%02x)", data[0],
413 POINT_CONVERSION_UNCOMPRESSED);
414 return 0;
415 }
416
417 bn_ctx = BN_CTX_new();
418 if (bn_ctx == NULL) {
419 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
420 "error allocating new BN_CTX: %s", sftp_crypto_get_errors());
421 return 0;
422 }
423
424 if (EC_POINT_oct2point(curve, *point, data, datalen, bn_ctx) != 1) {
425 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
426 "message format error: unable to convert binary EC point data: %s",
427 sftp_crypto_get_errors());
428 BN_CTX_free(bn_ctx);
429 return 0;
430 }
431
432 BN_CTX_free(bn_ctx);
433 pr_memscrub(data, datalen);
434
435 return total_len;
436 }
437
sftp_msg_read_ecpoint(pool * p,unsigned char ** buf,uint32_t * buflen,const EC_GROUP * curve,EC_POINT * point)438 EC_POINT *sftp_msg_read_ecpoint(pool *p, unsigned char **buf, uint32_t *buflen,
439 const EC_GROUP *curve, EC_POINT *point) {
440 uint32_t len;
441
442 len = sftp_msg_read_ecpoint2(p, buf, buflen, curve, &point);
443 if (len == 0) {
444 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
445 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
446 }
447
448 return point;
449 }
450 #endif /* PR_USE_OPENSSL_ECC */
451
sftp_msg_write_byte(unsigned char ** buf,uint32_t * buflen,char byte)452 uint32_t sftp_msg_write_byte(unsigned char **buf, uint32_t *buflen, char byte) {
453 uint32_t len = 0;
454
455 if (*buflen < sizeof(char)) {
456 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
457 "message format error: unable to write byte (buflen = %lu)",
458 (unsigned long) *buflen);
459 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
460 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
461 }
462
463 len = sizeof(char);
464
465 memcpy(*buf, &byte, len);
466 (*buf) += len;
467 (*buflen) -= len;
468
469 return len;
470 }
471
sftp_msg_write_bool(unsigned char ** buf,uint32_t * buflen,char bool)472 uint32_t sftp_msg_write_bool(unsigned char **buf, uint32_t *buflen, char bool) {
473 return sftp_msg_write_byte(buf, buflen, bool == 0 ? 0 : 1);
474 }
475
sftp_msg_write_data(unsigned char ** buf,uint32_t * buflen,const unsigned char * data,size_t datalen,int write_len)476 uint32_t sftp_msg_write_data(unsigned char **buf, uint32_t *buflen,
477 const unsigned char *data, size_t datalen, int write_len) {
478 uint32_t len = 0;
479
480 if (write_len) {
481 len += sftp_msg_write_int(buf, buflen, datalen);
482 }
483
484 if (*buflen < datalen) {
485 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
486 "message format error: unable to write %lu bytes of raw data "
487 "(buflen = %lu)", (unsigned long) datalen, (unsigned long) *buflen);
488 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
489 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
490 }
491
492 if (datalen > 0) {
493 memcpy(*buf, data, datalen);
494 (*buf) += datalen;
495 (*buflen) -= datalen;
496
497 len += datalen;
498 }
499
500 return len;
501 }
502
sftp_msg_write_int(unsigned char ** buf,uint32_t * buflen,uint32_t val)503 uint32_t sftp_msg_write_int(unsigned char **buf, uint32_t *buflen,
504 uint32_t val) {
505 uint32_t len;
506
507 if (*buflen < sizeof(uint32_t)) {
508 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
509 "message format error: unable to write int (buflen = %lu)",
510 (unsigned long) *buflen);
511 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
512 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
513 }
514
515 len = sizeof(uint32_t);
516
517 val = htonl(val);
518 memcpy(*buf, &val, len);
519 (*buf) += len;
520 (*buflen) -= len;
521
522 return len;
523 }
524
sftp_msg_write_long(unsigned char ** buf,uint32_t * buflen,uint64_t val)525 uint32_t sftp_msg_write_long(unsigned char **buf, uint32_t *buflen,
526 uint64_t val) {
527 unsigned char data[8];
528
529 if (*buflen < sizeof(uint64_t)) {
530 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
531 "message format error: unable to write long (buflen = %lu)",
532 (unsigned long) *buflen);
533 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
534 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
535 }
536
537 data[0] = (unsigned char) (val >> 56) & 0xFF;
538 data[1] = (unsigned char) (val >> 48) & 0xFF;
539 data[2] = (unsigned char) (val >> 40) & 0xFF;
540 data[3] = (unsigned char) (val >> 32) & 0xFF;
541 data[4] = (unsigned char) (val >> 24) & 0xFF;
542 data[5] = (unsigned char) (val >> 16) & 0xFF;
543 data[6] = (unsigned char) (val >> 8) & 0xFF;
544 data[7] = (unsigned char) val & 0xFF;
545
546 return sftp_msg_write_data(buf, buflen, data, sizeof(data), FALSE);
547 }
548
sftp_msg_write_mpint(unsigned char ** buf,uint32_t * buflen,const BIGNUM * mpint)549 uint32_t sftp_msg_write_mpint(unsigned char **buf, uint32_t *buflen,
550 const BIGNUM *mpint) {
551 unsigned char *data = NULL;
552 size_t datalen = 0;
553 int res = 0;
554 uint32_t len = 0;
555
556 if (BN_is_zero(mpint)) {
557 return sftp_msg_write_int(buf, buflen, 0);
558 }
559
560 #if OPENSSL_VERSION_NUMBER >= 0x0090801fL
561 if (BN_is_negative(mpint)) {
562 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
563 "message format error: unable to write mpint (negative numbers not "
564 "supported)");
565 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
566 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
567 }
568 #endif /* OpenSSL-0.9.8a or later */
569
570 datalen = BN_num_bytes(mpint) + 1;
571
572 if (*buflen < datalen) {
573 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
574 "message format error: unable to write %lu bytes of mpint (buflen = %lu)",
575 (unsigned long) datalen, (unsigned long) *buflen);
576 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
577 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
578 }
579
580 data = malloc(datalen);
581 if (data == NULL) {
582 pr_log_pri(PR_LOG_ALERT, MOD_SFTP_VERSION ": Out of memory!");
583 _exit(1);
584 }
585
586 data[0] = 0;
587
588 res = BN_bn2bin(mpint, data + 1);
589 if (res < 0 ||
590 res != (int) (datalen - 1)) {
591 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
592 "message format error: BN_bn2bin() failed: expected %lu bytes, got %d",
593 (unsigned long) (datalen - 1), res);
594 pr_memscrub(data, datalen);
595 free(data);
596
597 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
598
599 /* Needed to avoid compiler (and static code analysis) complaints. */
600 return 0;
601 }
602
603 if (data[1] & 0x80) {
604 len += sftp_msg_write_data(buf, buflen, data, datalen, TRUE);
605
606 } else {
607 len += sftp_msg_write_data(buf, buflen, data + 1, datalen - 1,
608 TRUE);
609 }
610
611 pr_memscrub(data, datalen);
612 free(data);
613
614 return len;
615 }
616
sftp_msg_write_string(unsigned char ** buf,uint32_t * buflen,const char * str)617 uint32_t sftp_msg_write_string(unsigned char **buf, uint32_t *buflen,
618 const char *str) {
619 uint32_t len = 0;
620
621 len = strlen(str);
622 return sftp_msg_write_data(buf, buflen, (const unsigned char *) str, len,
623 TRUE);
624 }
625
626 #ifdef PR_USE_OPENSSL_ECC
sftp_msg_write_ecpoint(unsigned char ** buf,uint32_t * buflen,const EC_GROUP * curve,const EC_POINT * point)627 uint32_t sftp_msg_write_ecpoint(unsigned char **buf, uint32_t *buflen,
628 const EC_GROUP *curve, const EC_POINT *point) {
629 unsigned char *data = NULL;
630 size_t datalen = 0;
631 uint32_t len = 0;
632 BN_CTX *bn_ctx;
633
634 bn_ctx = BN_CTX_new();
635 if (bn_ctx == NULL) {
636 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
637 "error allocating new BN_CTX: %s", sftp_crypto_get_errors());
638 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
639 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
640 }
641
642 datalen = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
643 NULL, 0, bn_ctx);
644 if (datalen > MAX_ECPOINT_LEN) {
645 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
646 "message format error: EC point length too long (%lu > max %lu)",
647 (unsigned long) datalen, (unsigned long) MAX_ECPOINT_LEN);
648 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
649 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
650 }
651
652 if (*buflen < datalen) {
653 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
654 "message format error: unable to write %lu bytes of EC point "
655 "(buflen = %lu)", (unsigned long) datalen, (unsigned long) *buflen);
656 pr_log_stacktrace(sftp_logfd, MOD_SFTP_VERSION);
657 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
658 }
659
660 data = malloc(datalen);
661 if (data == NULL) {
662 pr_log_pri(PR_LOG_ALERT, MOD_SFTP_VERSION ": Out of memory!");
663 _exit(1);
664 }
665
666 if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, data,
667 datalen, bn_ctx) != datalen) {
668 (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
669 "error writing EC point data: Length mismatch");
670 pr_memscrub(data, datalen);
671 free(data);
672 BN_CTX_free(bn_ctx);
673
674 SFTP_DISCONNECT_CONN(SFTP_SSH2_DISCONNECT_BY_APPLICATION, NULL);
675
676 /* Needed to avoid compiler (and static code analysis) complaints. */
677 return 0;
678 }
679
680 len = sftp_msg_write_data(buf, buflen, (const unsigned char *) data, datalen,
681 TRUE);
682
683 pr_memscrub(data, datalen);
684 free(data);
685 BN_CTX_free(bn_ctx);
686
687 return len;
688 }
689 #endif /* PR_USE_OPENSSL_ECC */
690
691