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