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