From 3ea76877dee954361110aa0f48922a4d07dd237b Mon Sep 17 00:00:00 2001 From: Jianhui Zhao Date: Thu, 9 May 2019 16:05:54 +0800 Subject: [PATCH] b64_encode: Refactoring Signed-off-by: Jianhui Zhao --- src/CMakeLists.txt | 2 +- src/base64.c | 155 --------------------------------------------- src/base64.h | 33 ---------- src/utils.c | 47 ++++++++++++++ src/utils.h | 2 + src/uwsc.c | 1 - 6 files changed, 50 insertions(+), 190 deletions(-) delete mode 100644 src/base64.c delete mode 100644 src/base64.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54f53a7..9b2c464 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(Libev REQUIRED) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/buffer ${CMAKE_CURRENT_BINARY_DIR} ${LIBEV_INCLUDE_DIR}) set(EXTRA_LIBS ${LIBEV_LIBRARY} dl) -set(SOURCE_FILES uwsc.c log.c utils.c buffer/buffer.c sha1.c base64.c ssl.c) +set(SOURCE_FILES uwsc.c log.c utils.c buffer/buffer.c sha1.c ssl.c) set(UWSC_SSL_SUPPORT_CONFIG 1) option(UWSC_SSL_SUPPORT "SSL support" ON) diff --git a/src/base64.c b/src/base64.c deleted file mode 100644 index 01e1427..0000000 --- a/src/base64.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2019 Jianhui Zhao - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include - - -static const char Pad64 = '='; - -/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) - The following encoding technique is taken from RFC 1521 by Borenstein - and Freed. It is reproduced here in a slightly edited form for - convenience. - - A 65-character subset of US-ASCII is used, enabling 6 bits to be - represented per printable character. (The extra 65th character, "=", - is used to signify a special processing function.) - - The encoding process represents 24-bit groups of input bits as output - strings of 4 encoded characters. Proceeding from left to right, a - 24-bit input group is formed by concatenating 3 8-bit input groups. - These 24 bits are then treated as 4 concatenated 6-bit groups, each - of which is translated into a single digit in the base64 alphabet. - - Each 6-bit group is used as an index into an array of 64 printable - characters. The character referenced by the index is placed in the - output string. - - Table 1: The Base64 Alphabet - - Value Encoding Value Encoding Value Encoding Value Encoding - 0 A 17 R 34 i 51 z - 1 B 18 S 35 j 52 0 - 2 C 19 T 36 k 53 1 - 3 D 20 U 37 l 54 2 - 4 E 21 V 38 m 55 3 - 5 F 22 W 39 n 56 4 - 6 G 23 X 40 o 57 5 - 7 H 24 Y 41 p 58 6 - 8 I 25 Z 42 q 59 7 - 9 J 26 a 43 r 60 8 - 10 K 27 b 44 s 61 9 - 11 L 28 c 45 t 62 + - 12 M 29 d 46 u 63 / - 13 N 30 e 47 v - 14 O 31 f 48 w (pad) = - 15 P 32 g 49 x - 16 Q 33 h 50 y - - Special processing is performed if fewer than 24 bits are available - at the end of the data being encoded. A full encoding quantum is - always completed at the end of a quantity. When fewer than 24 input - bits are available in an input group, zero bits are added (on the - right) to form an integral number of 6-bit groups. Padding at the - end of the data is performed using the '=' character. - - Since all base64 input is an integral number of octets, only the - ------------------------------------------------- - following cases can arise: - - (1) the final quantum of encoding input is an integral - multiple of 24 bits; here, the final unit of encoded - output will be an integral multiple of 4 characters - with no "=" padding, - (2) the final quantum of encoding input is exactly 8 bits; - here, the final unit of encoded output will be two - characters followed by two "=" padding characters, or - (3) the final quantum of encoding input is exactly 16 bits; - here, the final unit of encoded output will be three - characters followed by one "=" padding character. - */ - -int b64_encode(const void *_src, size_t srclength, - void *dest, size_t targsize) -{ - char Base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - const unsigned char *src = _src; - char *target = dest; - size_t datalength = 0; - uint8_t input[3] = {0}; - uint8_t output[4]; - int i; - - while (2 < srclength) { - input[0] = *src++; - input[1] = *src++; - input[2] = *src++; - srclength -= 3; - - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - output[3] = input[2] & 0x3f; - - if (datalength + 4 > targsize) - return (-1); - target[datalength++] = Base64[output[0]]; - target[datalength++] = Base64[output[1]]; - target[datalength++] = Base64[output[2]]; - target[datalength++] = Base64[output[3]]; - } - - /* Now we worry about padding. */ - if (0 != srclength) { - /* Get what's left. */ - input[0] = input[1] = input[2] = '\0'; - for (i = 0; i < srclength; i++) - input[i] = *src++; - - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - - if (datalength + 4 > targsize) - return (-1); - target[datalength++] = Base64[output[0]]; - target[datalength++] = Base64[output[1]]; - if (srclength == 1) - target[datalength++] = Pad64; - else - target[datalength++] = Base64[output[2]]; - target[datalength++] = Pad64; - } - if (datalength >= targsize) - return (-1); - target[datalength] = '\0'; /* Returned value doesn't count \0. */ - return (datalength); -} - diff --git a/src/base64.h b/src/base64.h deleted file mode 100644 index 7338f63..0000000 --- a/src/base64.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2019 Jianhui Zhao - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _BASE64_H -#define _BASE64_H - -#include - -int b64_encode(const void *_src, size_t srclength, - void *dest, size_t targsize); - -#endif diff --git a/src/utils.c b/src/utils.c index a156262..26799e0 100644 --- a/src/utils.c +++ b/src/utils.c @@ -161,3 +161,50 @@ int tcp_connect(const char *host, int port, int flags, bool *inprogress, int *ea freeaddrinfo(result); return sock; } + +/* reference from https://tools.ietf.org/html/rfc4648#section-4 */ +int b64_encode(const void *src, size_t srclen, void *dest, size_t destsize) +{ + char *Base64 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const uint8_t *input = src; + char *output = dest; + + while (srclen > 0) { + int i0 = input[0] >> 2; + int skip = 1; + + if (destsize < 5) + return -1; + + *output++ = Base64[i0]; + + if (srclen > 1) { + int i1 = ((input[0] & 0x3) << 4) + (input[1] >> 4); + *output++ = Base64[i1]; + if (srclen > 2) { + int i2 = ((input[1] & 0xF) << 2) + (input[2] >> 6); + int i3 = input[2] & 0x3F; + *output++ = Base64[i2]; + *output++ = Base64[i3]; + skip = 3; + } else { + *output++ = Base64[i1]; + *output++ = '='; + skip = 2; + } + } else { + int i1 = (input[0] & 0x3) << 4; + *output++ = Base64[i1]; + *output++ = '='; + *output++ = '='; + } + + input += skip; + srclen -= skip; + destsize -= 4; + } + + *output++ = 0; + return output - (char *)dest - 1; +} diff --git a/src/utils.h b/src/utils.h index e37d1b4..9f4a144 100644 --- a/src/utils.h +++ b/src/utils.h @@ -45,4 +45,6 @@ int parse_url(const char *url, char *host, int host_len, int tcp_connect(const char *host, int port, int flags, bool *inprogress, int *eai); +int b64_encode(const void *src, size_t srclen, void *dest, size_t destsize); + #endif diff --git a/src/uwsc.c b/src/uwsc.c index fb2d908..28785b0 100644 --- a/src/uwsc.c +++ b/src/uwsc.c @@ -35,7 +35,6 @@ #include "uwsc.h" #include "sha1.h" #include "utils.h" -#include "base64.h" static void uwsc_free(struct uwsc_client *cl) {