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