| /* |
| * Copyright (C) Tildeslash Ltd. All rights reserved. |
| * |
| * This program is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU Affero General Public License version 3. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU Affero General Public License |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| * |
| * In addition, as a special exception, the copyright holders give |
| * permission to link the code of portions of this program with the |
| * OpenSSL library under certain conditions as described in each |
| * individual source file, and distribute linked combinations |
| * including the two. |
| * |
| * You must obey the GNU Affero General Public License in all respects |
| * for all of the code used other than OpenSSL. |
| */ |
| |
| #include "config.h" |
| |
| #ifdef HAVE_STDIO_H |
| #include <stdio.h> |
| #endif |
| |
| #ifdef HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| |
| #ifdef HAVE_STRING_H |
| #include <string.h> |
| #endif |
| |
| #include "monit.h" |
| #include "base64.h" |
| |
| |
| /** |
| * Implementation of base64 encoding/decoding. |
| * |
| * @file |
| */ |
| |
| |
| /* ----------------------------------------------------------------- Private */ |
| |
| |
| /** |
| * Base64 encode one byte |
| */ |
| static char encode(unsigned char u) { |
| |
| if(u < 26) return 'A'+u; |
| if(u < 52) return 'a'+(u-26); |
| if(u < 62) return '0'+(u-52); |
| if(u == 62) return '+'; |
| |
| return '/'; |
| |
| } |
| |
| |
| /** |
| * Decode a base64 character |
| */ |
| static unsigned char decode(char c) { |
| |
| if(c >= 'A' && c <= 'Z') return(c - 'A'); |
| if(c >= 'a' && c <= 'z') return(c - 'a' + 26); |
| if(c >= '0' && c <= '9') return(c - '0' + 52); |
| if(c == '+') return 62; |
| |
| return 63; |
| |
| } |
| |
| |
| /** |
| * Return TRUE if 'c' is a valid base64 character, otherwise FALSE |
| */ |
| static int is_base64(char c) { |
| |
| if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || |
| (c >= '0' && c <= '9') || (c == '+') || |
| (c == '/') || (c == '=')) { |
| |
| return TRUE; |
| |
| } |
| |
| return FALSE; |
| |
| } |
| |
| |
| /* ------------------------------------------------------------------ Public */ |
| |
| |
| /** |
| * Base64 encode and return size data in 'src'. The caller must free the |
| * returned string. |
| * @param size The size of the data in src |
| * @param src The data to be base64 encode |
| * @return encoded string otherwise NULL |
| */ |
| char *encode_base64(size_t size, unsigned char *src) { |
| |
| int i; |
| char *out, *p; |
| |
| if(!src) |
| return NULL; |
| |
| if(!size) |
| size= strlen((char *)src); |
| |
| out= CALLOC(sizeof(char), size*4/3+4); |
| |
| p= out; |
| |
| for(i=0; i<size; i+=3) { |
| |
| unsigned char b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, b7=0; |
| |
| b1 = src[i]; |
| |
| if(i+1<size) |
| b2 = src[i+1]; |
| |
| if(i+2<size) |
| b3 = src[i+2]; |
| |
| b4= b1>>2; |
| b5= ((b1&0x3)<<4)|(b2>>4); |
| b6= ((b2&0xf)<<2)|(b3>>6); |
| b7= b3&0x3f; |
| |
| *p++= encode(b4); |
| *p++= encode(b5); |
| |
| if(i+1<size) { |
| *p++= encode(b6); |
| } else { |
| *p++= '='; |
| } |
| |
| if(i+2<size) { |
| *p++= encode(b7); |
| } else { |
| *p++= '='; |
| } |
| |
| } |
| |
| return out; |
| |
| } |
| |
| |
| /** |
| * Decode the base64 encoded string 'src' into the memory pointed to by |
| * 'dest'. The dest buffer is <b>not</b> NUL terminated. |
| * @param dest Pointer to memory for holding the decoded string. |
| * Must be large enough to recieve the decoded string. |
| * @param src A base64 encoded string. |
| * @return TRUE (the length of the decoded string) if decode |
| * succeeded otherwise FALSE. |
| */ |
| size_t decode_base64(unsigned char *dest, const char *src) { |
| |
| if(src && *src) { |
| |
| unsigned char *p= dest; |
| size_t k, l = strlen(src)+1; |
| unsigned char *buf= CALLOC(1, l); |
| |
| |
| /* Ignore non base64 chars as per the POSIX standard */ |
| for(k=0, l=0; src[k]; k++) { |
| |
| if(is_base64(src[k])) { |
| |
| buf[l++]= src[k]; |
| |
| } |
| |
| } |
| |
| for(k=0; k<l; k+=4) { |
| |
| char c1='A', c2='A', c3='A', c4='A'; |
| unsigned char b1=0, b2=0, b3=0, b4=0; |
| |
| c1= buf[k]; |
| |
| if(k+1<l) { |
| |
| c2= buf[k+1]; |
| |
| } |
| |
| if(k+2<l) { |
| |
| c3= buf[k+2]; |
| |
| } |
| |
| if(k+3<l) { |
| |
| c4= buf[k+3]; |
| |
| } |
| |
| b1= decode(c1); |
| b2= decode(c2); |
| b3= decode(c3); |
| b4= decode(c4); |
| |
| *p++=((b1<<2)|(b2>>4) ); |
| |
| if(c3 != '=') { |
| |
| *p++=(((b2&0xf)<<4)|(b3>>2) ); |
| |
| } |
| |
| if(c4 != '=') { |
| |
| *p++=(((b3&0x3)<<6)|b4 ); |
| |
| } |
| |
| } |
| |
| FREE(buf); |
| |
| return(p-dest); |
| |
| } |
| |
| return FALSE; |
| |
| } |