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 8866 : _PUBLIC_ DATA_BLOB base64_decode_data_blob_talloc(TALLOC_CTX *mem_ctx, const char *s) 38 : { 39 : int bit_offset, byte_offset, idx, i, n; 40 8866 : DATA_BLOB decoded = data_blob_talloc(mem_ctx, s, strlen(s)+1); 41 8866 : unsigned char *d = decoded.data; 42 : char *p; 43 : 44 8866 : if (decoded.data == NULL) { 45 0 : decoded.length = 0; 46 0 : return decoded; 47 : } 48 : 49 8866 : n=i=0; 50 : 51 14884938 : while (*s && (p=strchr(b64,*s))) { 52 14876072 : idx = (int)(p - b64); 53 14876072 : byte_offset = (i*6)/8; 54 14876072 : bit_offset = (i*6)%8; 55 14876072 : d[byte_offset] &= ~((1<<(8-bit_offset))-1); 56 14876072 : if (bit_offset < 3) { 57 7436075 : d[byte_offset] |= (idx << (2-bit_offset)); 58 7436075 : n = byte_offset+1; 59 : } else { 60 7439997 : d[byte_offset] |= (idx >> (bit_offset-2)); 61 7439997 : d[byte_offset+1] = (idx << (8-(bit_offset-2))) & 0xFF; 62 7439997 : n = byte_offset+2; 63 : } 64 14876072 : s++; i++; 65 : } 66 : 67 8866 : if ((n > 0) && (*s == '=')) { 68 7845 : n -= 1; 69 : } 70 : 71 : /* fix up length */ 72 8866 : decoded.length = n; 73 8866 : decoded.data = talloc_realloc(mem_ctx, decoded.data, uint8_t, n); 74 8866 : return decoded; 75 : } 76 : 77 : /** 78 : * Decode a base64 string into a DATA_BLOB - simple and slow algorithm 79 : **/ 80 0 : _PUBLIC_ DATA_BLOB base64_decode_data_blob(const char *s) 81 : { 82 0 : 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 216 : _PUBLIC_ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data) 112 : { 113 216 : int bits = 0; 114 216 : int char_count = 0; 115 : size_t out_cnt, len, output_len; 116 : char *result; 117 : 118 216 : if (!data.length || !data.data) 119 0 : return NULL; 120 : 121 216 : out_cnt = 0; 122 216 : len = data.length; 123 216 : output_len = data.length * 2 + 4; /* Account for closing bytes. 4 is 124 : * random but should be enough for 125 : * the = and \0 */ 126 216 : result = talloc_array(mem_ctx, char, output_len); /* get us plenty of space */ 127 216 : if (result == NULL) { 128 0 : return NULL; 129 : } 130 : 131 44332 : while (len--) { 132 44116 : int c = (unsigned char) *(data.data++); 133 44116 : bits += c; 134 44116 : char_count++; 135 44116 : if (char_count == 3) { 136 14631 : result[out_cnt++] = b64[bits >> 18]; 137 14631 : result[out_cnt++] = b64[(bits >> 12) & 0x3f]; 138 14631 : result[out_cnt++] = b64[(bits >> 6) & 0x3f]; 139 14631 : result[out_cnt++] = b64[bits & 0x3f]; 140 14631 : bits = 0; 141 14631 : char_count = 0; 142 : } else { 143 29485 : bits <<= 8; 144 : } 145 : } 146 216 : if (char_count != 0) { 147 161 : bits <<= 16 - (8 * char_count); 148 161 : result[out_cnt++] = b64[bits >> 18]; 149 161 : result[out_cnt++] = b64[(bits >> 12) & 0x3f]; 150 161 : if (char_count == 1) { 151 99 : result[out_cnt++] = '='; 152 99 : result[out_cnt++] = '='; 153 : } else { 154 62 : result[out_cnt++] = b64[(bits >> 6) & 0x3f]; 155 62 : result[out_cnt++] = '='; 156 : } 157 : } 158 216 : result[out_cnt] = '\0'; /* terminate */ 159 216 : return result; 160 : } 161 :