Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : Samba utility functions 4 : 5 : Copyright (C) Andrew Tridgell 1992-2001 6 : Copyright (C) Simo Sorce 2001-2002 7 : Copyright (C) Martin Pool 2003 8 : Copyright (C) James Peach 2006 9 : Copyright (C) Jeremy Allison 1992-2007 10 : 11 : This program is free software; you can redistribute it and/or modify 12 : it under the terms of the GNU General Public License as published by 13 : the Free Software Foundation; either version 3 of the License, or 14 : (at your option) any later version. 15 : 16 : This program is distributed in the hope that it will be useful, 17 : but WITHOUT ANY WARRANTY; without even the implied warranty of 18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 : GNU General Public License for more details. 20 : 21 : You should have received a copy of the GNU General Public License 22 : along with this program. If not, see <http://www.gnu.org/licenses/>. 23 : */ 24 : 25 : #include "replace.h" 26 : #include "lib/util/base64.h" 27 : 28 : static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 29 : 30 : /** 31 : * Decode a base64 string into a DATA_BLOB - simple and slow algorithm. 32 : * 33 : * A DATA_BLOB like {.data = NULL, length = 0} indicates memory error. 34 : * 35 : * Decoding stops at the first invalid character. 36 : **/ 37 24068 : _PUBLIC_ DATA_BLOB base64_decode_data_blob_talloc(TALLOC_CTX *mem_ctx, const char *s) 38 : { 39 3227 : int bit_offset, byte_offset, idx, i, n; 40 24068 : DATA_BLOB decoded = data_blob_talloc(mem_ctx, s, strlen(s)+1); 41 24068 : unsigned char *d = decoded.data; 42 3227 : char *p; 43 : 44 24068 : if (decoded.data == NULL) { 45 0 : decoded.length = 0; 46 0 : return decoded; 47 : } 48 : 49 20841 : n=i=0; 50 : 51 39418171 : while (*s && (p=strchr(b64,*s))) { 52 39394103 : idx = (int)(p - b64); 53 39394103 : byte_offset = (i*6)/8; 54 39394103 : bit_offset = (i*6)%8; 55 39394103 : d[byte_offset] &= ~((1<<(8-bit_offset))-1); 56 39394103 : if (bit_offset < 3) { 57 19691903 : d[byte_offset] |= (idx << (2-bit_offset)); 58 19691903 : n = byte_offset+1; 59 : } else { 60 19702200 : d[byte_offset] |= (idx >> (bit_offset-2)); 61 19702200 : d[byte_offset+1] = (idx << (8-(bit_offset-2))) & 0xFF; 62 19702200 : n = byte_offset+2; 63 : } 64 39394103 : s++; i++; 65 : } 66 : 67 24068 : if ((n > 0) && (*s == '=')) { 68 20551 : n -= 1; 69 : } 70 : 71 : /* fix up length */ 72 24068 : decoded.length = n; 73 24068 : decoded.data = talloc_realloc(mem_ctx, decoded.data, uint8_t, n); 74 24068 : return decoded; 75 : } 76 : 77 : /** 78 : * Decode a base64 string into a DATA_BLOB - simple and slow algorithm 79 : **/ 80 2415 : _PUBLIC_ DATA_BLOB base64_decode_data_blob(const char *s) 81 : { 82 2415 : return base64_decode_data_blob_talloc(NULL, s); 83 : } 84 : 85 : /** 86 : * Decode a base64 string in-place - wrapper for the above 87 : **/ 88 0 : _PUBLIC_ void base64_decode_inplace(char *s) 89 : { 90 0 : DATA_BLOB decoded = base64_decode_data_blob(s); 91 : 92 0 : if ( decoded.length != 0 ) { 93 0 : memcpy(s, decoded.data, decoded.length); 94 : 95 : /* null terminate */ 96 0 : s[decoded.length] = '\0'; 97 : } else { 98 0 : *s = '\0'; 99 : } 100 : 101 0 : data_blob_free(&decoded); 102 0 : } 103 : 104 : /** 105 : * Encode a base64 string into a talloc()ed string caller to free. 106 : * 107 : * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c 108 : * with adjustments 109 : **/ 110 : 111 2555 : _PUBLIC_ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data) 112 : { 113 2555 : int bits = 0; 114 2555 : int char_count = 0; 115 1999 : size_t out_cnt, len, output_len; 116 1999 : char *result; 117 : 118 : /* 119 : * Note: we return NULL for a zero-length blob, even though it can be 120 : * encoded as a zero length string in base64. 121 : * 122 : * FIXME, perhaps, but we need to check carefully before changing 123 : * this. 124 : */ 125 2555 : if (data.length == 0 || data.data == NULL) { 126 0 : return NULL; 127 : } 128 : 129 2555 : out_cnt = 0; 130 2555 : len = data.length; 131 2555 : output_len = data.length * 2 + 4; /* Account for closing bytes. 4 is 132 : * random but should be enough for 133 : * the = and \0 */ 134 2555 : result = talloc_array(mem_ctx, char, output_len); /* get us plenty of space */ 135 2555 : if (result == NULL) { 136 0 : return NULL; 137 : } 138 : 139 2139849 : while (len--) { 140 2137294 : int c = (unsigned char) *(data.data++); 141 2137294 : bits += c; 142 2137294 : char_count++; 143 2137294 : if (char_count == 3) { 144 711564 : result[out_cnt++] = b64[bits >> 18]; 145 711564 : result[out_cnt++] = b64[(bits >> 12) & 0x3f]; 146 711564 : result[out_cnt++] = b64[(bits >> 6) & 0x3f]; 147 711564 : result[out_cnt++] = b64[bits & 0x3f]; 148 711564 : bits = 0; 149 711564 : char_count = 0; 150 : } else { 151 1425730 : bits <<= 8; 152 : } 153 : } 154 2555 : if (char_count != 0) { 155 1750 : bits <<= 16 - (8 * char_count); 156 1750 : result[out_cnt++] = b64[bits >> 18]; 157 1750 : result[out_cnt++] = b64[(bits >> 12) & 0x3f]; 158 1750 : if (char_count == 1) { 159 898 : result[out_cnt++] = '='; 160 898 : result[out_cnt++] = '='; 161 : } else { 162 852 : result[out_cnt++] = b64[(bits >> 6) & 0x3f]; 163 852 : result[out_cnt++] = '='; 164 : } 165 : } 166 2555 : result[out_cnt] = '\0'; /* terminate */ 167 2555 : return result; 168 : } 169 :