1 /* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
2 * Copyright (c) 2009-2019 by Daniel Stenberg
3 * Copyright (c) 2010 Simon Josefsson
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms,
7 * with or without modification, are permitted provided
8 * that the following conditions are met:
9 *
10 * Redistributions of source code must retain the above
11 * copyright notice, this list of conditions and the
12 * following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials
17 * provided with the distribution.
18 *
19 * Neither the name of the copyright holder nor the names
20 * of any other contributors may be used to endorse or
21 * promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37 * OF SUCH DAMAGE.
38 */
39
40 #include "libssh2_priv.h"
41 #include "misc.h"
42 #include "blf.h"
43
44 #ifdef HAVE_STDLIB_H
45 #include <stdlib.h>
46 #endif
47
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #ifdef HAVE_SYS_TIME_H
53 #include <sys/time.h>
54 #endif
55
56 #if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
57 #ifdef HAVE_WINDOWS_H
58 #include <windows.h>
59 #endif
60 #endif
61
62 #include <stdio.h>
63 #include <errno.h>
64
_libssh2_error_flags(LIBSSH2_SESSION * session,int errcode,const char * errmsg,int errflags)65 int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
66 const char *errmsg, int errflags)
67 {
68 if(session->err_flags & LIBSSH2_ERR_FLAG_DUP)
69 LIBSSH2_FREE(session, (char *)session->err_msg);
70
71 session->err_code = errcode;
72 session->err_flags = 0;
73
74 if((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
75 size_t len = strlen(errmsg);
76 char *copy = LIBSSH2_ALLOC(session, len + 1);
77 if(copy) {
78 memcpy(copy, errmsg, len + 1);
79 session->err_flags = LIBSSH2_ERR_FLAG_DUP;
80 session->err_msg = copy;
81 }
82 else
83 /* Out of memory: this code path is very unlikely */
84 session->err_msg = "former error forgotten (OOM)";
85 }
86 else
87 session->err_msg = errmsg;
88
89 #ifdef LIBSSH2DEBUG
90 if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode)
91 /* if this is EAGAIN and we're in non-blocking mode, don't generate
92 a debug output for this */
93 return errcode;
94 _libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
95 session->err_msg);
96 #endif
97
98 return errcode;
99 }
100
_libssh2_error(LIBSSH2_SESSION * session,int errcode,const char * errmsg)101 int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg)
102 {
103 return _libssh2_error_flags(session, errcode, errmsg, 0);
104 }
105
106 #ifdef WIN32
wsa2errno(void)107 static int wsa2errno(void)
108 {
109 switch(WSAGetLastError()) {
110 case WSAEWOULDBLOCK:
111 return EAGAIN;
112
113 case WSAENOTSOCK:
114 return EBADF;
115
116 case WSAEINTR:
117 return EINTR;
118
119 default:
120 /* It is most important to ensure errno does not stay at EAGAIN
121 * when a different error occurs so just set errno to a generic
122 * error */
123 return EIO;
124 }
125 }
126 #endif
127
128 /* _libssh2_recv
129 *
130 * Replacement for the standard recv, return -errno on failure.
131 */
132 ssize_t
_libssh2_recv(libssh2_socket_t sock,void * buffer,size_t length,int flags,void ** abstract)133 _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length,
134 int flags, void **abstract)
135 {
136 ssize_t rc;
137
138 (void) abstract;
139
140 rc = recv(sock, buffer, length, flags);
141 #ifdef WIN32
142 if(rc < 0)
143 return -wsa2errno();
144 #else
145 if(rc < 0) {
146 /* Sometimes the first recv() function call sets errno to ENOENT on
147 Solaris and HP-UX */
148 if(errno == ENOENT)
149 return -EAGAIN;
150 #ifdef EWOULDBLOCK /* For VMS and other special unixes */
151 else if(errno == EWOULDBLOCK)
152 return -EAGAIN;
153 #endif
154 else
155 return -errno;
156 }
157 #endif
158 return rc;
159 }
160
161 /* _libssh2_send
162 *
163 * Replacement for the standard send, return -errno on failure.
164 */
165 ssize_t
_libssh2_send(libssh2_socket_t sock,const void * buffer,size_t length,int flags,void ** abstract)166 _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
167 int flags, void **abstract)
168 {
169 ssize_t rc;
170
171 (void) abstract;
172
173 rc = send(sock, buffer, length, flags);
174 #ifdef WIN32
175 if(rc < 0)
176 return -wsa2errno();
177 #else
178 if(rc < 0) {
179 #ifdef EWOULDBLOCK /* For VMS and other special unixes */
180 if(errno == EWOULDBLOCK)
181 return -EAGAIN;
182 #endif
183 return -errno;
184 }
185 #endif
186 return rc;
187 }
188
189 /* libssh2_ntohu32
190 */
191 unsigned int
_libssh2_ntohu32(const unsigned char * buf)192 _libssh2_ntohu32(const unsigned char *buf)
193 {
194 return (((unsigned int)buf[0] << 24)
195 | ((unsigned int)buf[1] << 16)
196 | ((unsigned int)buf[2] << 8)
197 | ((unsigned int)buf[3]));
198 }
199
200
201 /* _libssh2_ntohu64
202 */
203 libssh2_uint64_t
_libssh2_ntohu64(const unsigned char * buf)204 _libssh2_ntohu64(const unsigned char *buf)
205 {
206 unsigned long msl, lsl;
207
208 msl = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16)
209 | ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3];
210 lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16)
211 | ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7];
212
213 return ((libssh2_uint64_t)msl <<32) | lsl;
214 }
215
216 /* _libssh2_htonu32
217 */
218 void
_libssh2_htonu32(unsigned char * buf,uint32_t value)219 _libssh2_htonu32(unsigned char *buf, uint32_t value)
220 {
221 buf[0] = (value >> 24) & 0xFF;
222 buf[1] = (value >> 16) & 0xFF;
223 buf[2] = (value >> 8) & 0xFF;
224 buf[3] = value & 0xFF;
225 }
226
227 /* _libssh2_store_u32
228 */
_libssh2_store_u32(unsigned char ** buf,uint32_t value)229 void _libssh2_store_u32(unsigned char **buf, uint32_t value)
230 {
231 _libssh2_htonu32(*buf, value);
232 *buf += sizeof(uint32_t);
233 }
234
235 /* _libssh2_store_str
236 */
_libssh2_store_str(unsigned char ** buf,const char * str,size_t len)237 void _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
238 {
239 _libssh2_store_u32(buf, (uint32_t)len);
240 if(len) {
241 memcpy(*buf, str, len);
242 *buf += len;
243 }
244 }
245
246 /* Base64 Conversion */
247
248 static const short base64_reverse_table[256] = {
249 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
250 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
251 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
252 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
253 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
254 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
255 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
256 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
257 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
258 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
259 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
260 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
261 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
262 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
263 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
264 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
265 };
266
267 /* libssh2_base64_decode
268 *
269 * Decode a base64 chunk and store it into a newly alloc'd buffer
270 */
271 LIBSSH2_API int
libssh2_base64_decode(LIBSSH2_SESSION * session,char ** data,unsigned int * datalen,const char * src,unsigned int src_len)272 libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
273 unsigned int *datalen, const char *src,
274 unsigned int src_len)
275 {
276 unsigned char *s, *d;
277 short v;
278 int i = 0, len = 0;
279
280 *data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
281 d = (unsigned char *) *data;
282 if(!d) {
283 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
284 "Unable to allocate memory for base64 decoding");
285 }
286
287 for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
288 v = base64_reverse_table[*s];
289 if(v < 0)
290 continue;
291 switch(i % 4) {
292 case 0:
293 d[len] = (unsigned char)(v << 2);
294 break;
295 case 1:
296 d[len++] |= v >> 4;
297 d[len] = (unsigned char)(v << 4);
298 break;
299 case 2:
300 d[len++] |= v >> 2;
301 d[len] = (unsigned char)(v << 6);
302 break;
303 case 3:
304 d[len++] |= v;
305 break;
306 }
307 i++;
308 }
309 if((i % 4) == 1) {
310 /* Invalid -- We have a byte which belongs exclusively to a partial
311 octet */
312 LIBSSH2_FREE(session, *data);
313 *data = NULL;
314 return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
315 }
316
317 *datalen = len;
318 return 0;
319 }
320
321 /* ---- Base64 Encoding/Decoding Table --- */
322 static const char table64[]=
323 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
324
325 /*
326 * _libssh2_base64_encode()
327 *
328 * Returns the length of the newly created base64 string. The third argument
329 * is a pointer to an allocated area holding the base64 data. If something
330 * went wrong, 0 is returned.
331 *
332 */
_libssh2_base64_encode(LIBSSH2_SESSION * session,const char * inp,size_t insize,char ** outptr)333 size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
334 const char *inp, size_t insize, char **outptr)
335 {
336 unsigned char ibuf[3];
337 unsigned char obuf[4];
338 int i;
339 int inputparts;
340 char *output;
341 char *base64data;
342 const char *indata = inp;
343
344 *outptr = NULL; /* set to NULL in case of failure before we reach the
345 end */
346
347 if(0 == insize)
348 insize = strlen(indata);
349
350 base64data = output = LIBSSH2_ALLOC(session, insize * 4 / 3 + 4);
351 if(NULL == output)
352 return 0;
353
354 while(insize > 0) {
355 for(i = inputparts = 0; i < 3; i++) {
356 if(insize > 0) {
357 inputparts++;
358 ibuf[i] = *indata;
359 indata++;
360 insize--;
361 }
362 else
363 ibuf[i] = 0;
364 }
365
366 obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
367 obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
368 ((ibuf[1] & 0xF0) >> 4));
369 obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
370 ((ibuf[2] & 0xC0) >> 6));
371 obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
372
373 switch(inputparts) {
374 case 1: /* only one byte read */
375 snprintf(output, 5, "%c%c==",
376 table64[obuf[0]],
377 table64[obuf[1]]);
378 break;
379 case 2: /* two bytes read */
380 snprintf(output, 5, "%c%c%c=",
381 table64[obuf[0]],
382 table64[obuf[1]],
383 table64[obuf[2]]);
384 break;
385 default:
386 snprintf(output, 5, "%c%c%c%c",
387 table64[obuf[0]],
388 table64[obuf[1]],
389 table64[obuf[2]],
390 table64[obuf[3]]);
391 break;
392 }
393 output += 4;
394 }
395 *output = 0;
396 *outptr = base64data; /* make it return the actual data memory */
397
398 return strlen(base64data); /* return the length of the new data */
399 }
400 /* ---- End of Base64 Encoding ---- */
401
402 LIBSSH2_API void
libssh2_free(LIBSSH2_SESSION * session,void * ptr)403 libssh2_free(LIBSSH2_SESSION *session, void *ptr)
404 {
405 LIBSSH2_FREE(session, ptr);
406 }
407
408 #ifdef LIBSSH2DEBUG
409 #include <stdarg.h>
410
411 LIBSSH2_API int
libssh2_trace(LIBSSH2_SESSION * session,int bitmask)412 libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
413 {
414 session->showmask = bitmask;
415 return 0;
416 }
417
418 LIBSSH2_API int
libssh2_trace_sethandler(LIBSSH2_SESSION * session,void * handler_context,libssh2_trace_handler_func callback)419 libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
420 libssh2_trace_handler_func callback)
421 {
422 session->tracehandler = callback;
423 session->tracehandler_context = handler_context;
424 return 0;
425 }
426
427 void
_libssh2_debug(LIBSSH2_SESSION * session,int context,const char * format,...)428 _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
429 {
430 char buffer[1536];
431 int len, msglen, buflen = sizeof(buffer);
432 va_list vargs;
433 struct timeval now;
434 static int firstsec;
435 static const char *const contexts[] = {
436 "Unknown",
437 "Transport",
438 "Key Ex",
439 "Userauth",
440 "Conn",
441 "SCP",
442 "SFTP",
443 "Failure Event",
444 "Publickey",
445 "Socket",
446 };
447 const char *contexttext = contexts[0];
448 unsigned int contextindex;
449
450 if(!(session->showmask & context)) {
451 /* no such output asked for */
452 return;
453 }
454
455 /* Find the first matching context string for this message */
456 for(contextindex = 0; contextindex < ARRAY_SIZE(contexts);
457 contextindex++) {
458 if((context & (1 << contextindex)) != 0) {
459 contexttext = contexts[contextindex];
460 break;
461 }
462 }
463
464 _libssh2_gettimeofday(&now, NULL);
465 if(!firstsec) {
466 firstsec = now.tv_sec;
467 }
468 now.tv_sec -= firstsec;
469
470 len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
471 (int)now.tv_sec, (int)now.tv_usec, contexttext);
472
473 if(len >= buflen)
474 msglen = buflen - 1;
475 else {
476 buflen -= len;
477 msglen = len;
478 va_start(vargs, format);
479 len = vsnprintf(buffer + msglen, buflen, format, vargs);
480 va_end(vargs);
481 msglen += len < buflen ? len : buflen - 1;
482 }
483
484 if(session->tracehandler)
485 (session->tracehandler)(session, session->tracehandler_context, buffer,
486 msglen);
487 else
488 fprintf(stderr, "%s\n", buffer);
489 }
490
491 #else
492 LIBSSH2_API int
libssh2_trace(LIBSSH2_SESSION * session,int bitmask)493 libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
494 {
495 (void) session;
496 (void) bitmask;
497 return 0;
498 }
499
500 LIBSSH2_API int
libssh2_trace_sethandler(LIBSSH2_SESSION * session,void * handler_context,libssh2_trace_handler_func callback)501 libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
502 libssh2_trace_handler_func callback)
503 {
504 (void) session;
505 (void) handler_context;
506 (void) callback;
507 return 0;
508 }
509 #endif
510
511 /* init the list head */
_libssh2_list_init(struct list_head * head)512 void _libssh2_list_init(struct list_head *head)
513 {
514 head->first = head->last = NULL;
515 }
516
517 /* add a node to the list */
_libssh2_list_add(struct list_head * head,struct list_node * entry)518 void _libssh2_list_add(struct list_head *head,
519 struct list_node *entry)
520 {
521 /* store a pointer to the head */
522 entry->head = head;
523
524 /* we add this entry at the "top" so it has no next */
525 entry->next = NULL;
526
527 /* make our prev point to what the head thinks is last */
528 entry->prev = head->last;
529
530 /* and make head's last be us now */
531 head->last = entry;
532
533 /* make sure our 'prev' node points to us next */
534 if(entry->prev)
535 entry->prev->next = entry;
536 else
537 head->first = entry;
538 }
539
540 /* return the "first" node in the list this head points to */
_libssh2_list_first(struct list_head * head)541 void *_libssh2_list_first(struct list_head *head)
542 {
543 return head->first;
544 }
545
546 /* return the next node in the list */
_libssh2_list_next(struct list_node * node)547 void *_libssh2_list_next(struct list_node *node)
548 {
549 return node->next;
550 }
551
552 /* return the prev node in the list */
_libssh2_list_prev(struct list_node * node)553 void *_libssh2_list_prev(struct list_node *node)
554 {
555 return node->prev;
556 }
557
558 /* remove this node from the list */
_libssh2_list_remove(struct list_node * entry)559 void _libssh2_list_remove(struct list_node *entry)
560 {
561 if(entry->prev)
562 entry->prev->next = entry->next;
563 else
564 entry->head->first = entry->next;
565
566 if(entry->next)
567 entry->next->prev = entry->prev;
568 else
569 entry->head->last = entry->prev;
570 }
571
572 #if 0
573 /* insert a node before the given 'after' entry */
574 void _libssh2_list_insert(struct list_node *after, /* insert before this */
575 struct list_node *entry)
576 {
577 /* 'after' is next to 'entry' */
578 bentry->next = after;
579
580 /* entry's prev is then made to be the prev after current has */
581 entry->prev = after->prev;
582
583 /* the node that is now before 'entry' was previously before 'after'
584 and must be made to point to 'entry' correctly */
585 if(entry->prev)
586 entry->prev->next = entry;
587 else
588 /* there was no node before this, so we make sure we point the head
589 pointer to this node */
590 after->head->first = entry;
591
592 /* after's prev entry points back to entry */
593 after->prev = entry;
594
595 /* after's next entry is still the same as before */
596
597 /* entry's head is the same as after's */
598 entry->head = after->head;
599 }
600
601 #endif
602
603 /* this define is defined in misc.h for the correct platforms */
604 #ifdef LIBSSH2_GETTIMEOFDAY_WIN32
605 /*
606 * gettimeofday
607 * Implementation according to:
608 * The Open Group Base Specifications Issue 6
609 * IEEE Std 1003.1, 2004 Edition
610 */
611
612 /*
613 * THIS SOFTWARE IS NOT COPYRIGHTED
614 *
615 * This source code is offered for use in the public domain. You may
616 * use, modify or distribute it freely.
617 *
618 * This code is distributed in the hope that it will be useful but
619 * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
620 * DISCLAIMED. This includes but is not limited to warranties of
621 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
622 *
623 * Contributed by:
624 * Danny Smith <dannysmith@users.sourceforge.net>
625 */
626
627 /* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
628 #define _W32_FT_OFFSET (116444736000000000)
629
_libssh2_gettimeofday(struct timeval * tp,void * tzp)630 int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp)
631 {
632 union {
633 unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
634 FILETIME ft;
635 } _now;
636 (void)tzp;
637 if(tp) {
638 GetSystemTimeAsFileTime(&_now.ft);
639 tp->tv_usec = (long)((_now.ns100 / 10) % 1000000);
640 tp->tv_sec = (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
641 }
642 /* Always return 0 as per Open Group Base Specifications Issue 6.
643 Do not set errno on error. */
644 return 0;
645 }
646
647
648 #endif
649
_libssh2_calloc(LIBSSH2_SESSION * session,size_t size)650 void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size)
651 {
652 void *p = LIBSSH2_ALLOC(session, size);
653 if(p) {
654 memset(p, 0, size);
655 }
656 return p;
657 }
658
659 /* XOR operation on buffers input1 and input2, result in output.
660 It is safe to use an input buffer as the output buffer. */
_libssh2_xor_data(unsigned char * output,const unsigned char * input1,const unsigned char * input2,size_t length)661 void _libssh2_xor_data(unsigned char *output,
662 const unsigned char *input1,
663 const unsigned char *input2,
664 size_t length)
665 {
666 size_t i;
667
668 for(i = 0; i < length; i++)
669 *output++ = *input1++ ^ *input2++;
670 }
671
672 /* Increments an AES CTR buffer to prepare it for use with the
673 next AES block. */
_libssh2_aes_ctr_increment(unsigned char * ctr,size_t length)674 void _libssh2_aes_ctr_increment(unsigned char *ctr,
675 size_t length)
676 {
677 unsigned char *pc;
678 unsigned int val, carry;
679
680 pc = ctr + length - 1;
681 carry = 1;
682
683 while(pc >= ctr) {
684 val = (unsigned int)*pc + carry;
685 *pc-- = val & 0xFF;
686 carry = val >> 8;
687 }
688 }
689
690 #ifdef WIN32
691 static void * (__cdecl * const volatile memset_libssh)(void *, int, size_t) =
692 memset;
693 #else
694 static void * (* const volatile memset_libssh)(void *, int, size_t) = memset;
695 #endif
696
_libssh2_explicit_zero(void * buf,size_t size)697 void _libssh2_explicit_zero(void *buf, size_t size)
698 {
699 #if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
700 SecureZeroMemory(buf, size);
701 (void)memset_libssh; /* Silence unused variable warning */
702 #elif defined(HAVE_MEMSET_S)
703 (void)memset_s(buf, size, 0, size);
704 (void)memset_libssh; /* Silence unused variable warning */
705 #else
706 memset_libssh(buf, 0, size);
707 #endif
708 }
709
710 /* String buffer */
711
_libssh2_string_buf_new(LIBSSH2_SESSION * session)712 struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session)
713 {
714 struct string_buf *ret;
715
716 ret = _libssh2_calloc(session, sizeof(*ret));
717 if(ret == NULL)
718 return NULL;
719
720 return ret;
721 }
722
_libssh2_string_buf_free(LIBSSH2_SESSION * session,struct string_buf * buf)723 void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf)
724 {
725 if(buf == NULL)
726 return;
727
728 if(buf->data != NULL)
729 LIBSSH2_FREE(session, buf->data);
730
731 LIBSSH2_FREE(session, buf);
732 buf = NULL;
733 }
734
_libssh2_get_u32(struct string_buf * buf,uint32_t * out)735 int _libssh2_get_u32(struct string_buf *buf, uint32_t *out)
736 {
737 if(!_libssh2_check_length(buf, 4)) {
738 return -1;
739 }
740
741 *out = _libssh2_ntohu32(buf->dataptr);
742 buf->dataptr += 4;
743 return 0;
744 }
745
_libssh2_get_u64(struct string_buf * buf,libssh2_uint64_t * out)746 int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out)
747 {
748 if(!_libssh2_check_length(buf, 8)) {
749 return -1;
750 }
751
752 *out = _libssh2_ntohu64(buf->dataptr);
753 buf->dataptr += 8;
754 return 0;
755 }
756
_libssh2_match_string(struct string_buf * buf,const char * match)757 int _libssh2_match_string(struct string_buf *buf, const char *match)
758 {
759 unsigned char *out;
760 size_t len = 0;
761 if(_libssh2_get_string(buf, &out, &len) || len != strlen(match) ||
762 strncmp((char *)out, match, strlen(match)) != 0) {
763 return -1;
764 }
765 return 0;
766 }
767
_libssh2_get_string(struct string_buf * buf,unsigned char ** outbuf,size_t * outlen)768 int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
769 size_t *outlen)
770 {
771 uint32_t data_len;
772 if(_libssh2_get_u32(buf, &data_len) != 0) {
773 return -1;
774 }
775 if(!_libssh2_check_length(buf, data_len)) {
776 return -1;
777 }
778 *outbuf = buf->dataptr;
779 buf->dataptr += data_len;
780
781 if(outlen)
782 *outlen = (size_t)data_len;
783
784 return 0;
785 }
786
_libssh2_copy_string(LIBSSH2_SESSION * session,struct string_buf * buf,unsigned char ** outbuf,size_t * outlen)787 int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf,
788 unsigned char **outbuf, size_t *outlen)
789 {
790 size_t str_len;
791 unsigned char *str;
792
793 if(_libssh2_get_string(buf, &str, &str_len)) {
794 return -1;
795 }
796
797 *outbuf = LIBSSH2_ALLOC(session, str_len);
798 if(*outbuf) {
799 memcpy(*outbuf, str, str_len);
800 }
801 else {
802 return -1;
803 }
804
805 if(outlen)
806 *outlen = str_len;
807
808 return 0;
809 }
810
_libssh2_get_bignum_bytes(struct string_buf * buf,unsigned char ** outbuf,size_t * outlen)811 int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
812 size_t *outlen)
813 {
814 uint32_t data_len;
815 uint32_t bn_len;
816 unsigned char *bnptr;
817
818 if(_libssh2_get_u32(buf, &data_len)) {
819 return -1;
820 }
821 if(!_libssh2_check_length(buf, data_len)) {
822 return -1;
823 }
824
825 bn_len = data_len;
826 bnptr = buf->dataptr;
827
828 /* trim leading zeros */
829 while(bn_len > 0 && *bnptr == 0x00) {
830 bn_len--;
831 bnptr++;
832 }
833
834 *outbuf = bnptr;
835 buf->dataptr += data_len;
836
837 if(outlen)
838 *outlen = (size_t)bn_len;
839
840 return 0;
841 }
842
843 /* Given the current location in buf, _libssh2_check_length ensures
844 callers can read the next len number of bytes out of the buffer
845 before reading the buffer content */
846
_libssh2_check_length(struct string_buf * buf,size_t len)847 int _libssh2_check_length(struct string_buf *buf, size_t len)
848 {
849 unsigned char *endp = &buf->data[buf->len];
850 size_t left = endp - buf->dataptr;
851 return ((len <= left) && (left <= buf->len));
852 }
853
854 /* Wrappers */
855
_libssh2_bcrypt_pbkdf(const char * pass,size_t passlen,const uint8_t * salt,size_t saltlen,uint8_t * key,size_t keylen,unsigned int rounds)856 int _libssh2_bcrypt_pbkdf(const char *pass,
857 size_t passlen,
858 const uint8_t *salt,
859 size_t saltlen,
860 uint8_t *key,
861 size_t keylen,
862 unsigned int rounds)
863 {
864 /* defined in bcrypt_pbkdf.c */
865 return bcrypt_pbkdf(pass,
866 passlen,
867 salt,
868 saltlen,
869 key,
870 keylen,
871 rounds);
872 }
873