new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / addagent / b64.c
1 /*
2  * Copyright (C), 2000-2004 by the monit project group.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19
20 /* base64 encoding/decoding
21  * Author: Jan-Henrik Haukeland <hauk@tildeslash.com>
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #define TRUE    1
29 #define FALSE   0
30
31 /* Prototypes */
32 static int is_base64(char c);
33 static char encode(unsigned char u);
34 static unsigned char decode(char c);
35
36 /* Global variables */
37 char *decode_base64(const char *src);
38 char *encode_base64(int size, char *src);
39
40
41 /* Base64 encode and return size data in 'src'. The caller must free the
42  * returned string.
43  * Returns encoded string otherwise NULL
44  */
45 char *encode_base64(int size, char *src)
46 {
47     int i;
48     char *out, *p;
49
50     if (!src) {
51         return NULL;
52     }
53
54     if (!size) {
55         size = strlen((char *)src);
56     }
57
58     out = (char *)calloc(sizeof(char), size * 4 / 3 + 4);
59     if (!out) {
60         return NULL;
61     }
62
63     p = out;
64
65     for (i = 0; i < size; i += 3) {
66         unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0;
67
68         b1 = src[i];
69
70         if (i + 1 < size) {
71             b2 = src[i + 1];
72         }
73
74         if (i + 2 < size) {
75             b3 = src[i + 2];
76         }
77
78         b4 = b1 >> 2;
79         b5 = ((b1 & 0x3) << 4) | (b2 >> 4);
80         b6 = ((b2 & 0xf) << 2) | (b3 >> 6);
81         b7 = b3 & 0x3f;
82
83         *p++ = encode(b4);
84         *p++ = encode(b5);
85
86         if (i + 1 < size) {
87             *p++ = encode(b6);
88         } else {
89             *p++ = '=';
90         }
91
92         if (i + 2 < size) {
93             *p++ = encode(b7);
94         } else {
95             *p++ = '=';
96         }
97     }
98
99     return out;
100 }
101
102 /* Decode the base64 encoded string 'src' into the memory pointed to by
103  * 'dest'. The dest buffer is NUL terminated.
104  * Returns NULL in case of error
105  */
106 char *decode_base64(const char *src)
107 {
108     if (src && *src) {
109         char *dest;
110         unsigned char *p;
111         int k, l = strlen(src) + 1;
112         unsigned char *buf;
113
114         /* The size of the dest will always be less than the source */
115         dest = (char *)calloc(sizeof(char), l + 13);
116         if (!dest) {
117             return (NULL);
118         }
119
120         p = (unsigned char *)dest;
121
122         buf = (unsigned char *) malloc(l);
123         if (!buf) {
124             free(dest);
125             return (NULL);
126         }
127
128         /* Ignore non base64 chars as per the POSIX standard */
129         for (k = 0, l = 0; src[k]; k++) {
130             if (is_base64(src[k])) {
131                 buf[l++] = src[k];
132             }
133         }
134
135         for (k = 0; k < l; k += 4) {
136             char c1 = 'A', c2 = 'A', c3 = 'A', c4 = 'A';
137             unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0;
138
139             c1 = buf[k];
140
141             if (k + 1 < l) {
142                 c2 = buf[k + 1];
143             }
144
145             if (k + 2 < l) {
146                 c3 = buf[k + 2];
147             }
148
149             if (k + 3 < l) {
150                 c4 = buf[k + 3];
151             }
152
153             b1 = decode(c1);
154             b2 = decode(c2);
155             b3 = decode(c3);
156             b4 = decode(c4);
157
158             *p++ = ((b1 << 2) | (b2 >> 4) );
159
160             if (c3 != '=') {
161                 *p++ = (((b2 & 0xf) << 4) | (b3 >> 2) );
162             }
163
164             if (c4 != '=') {
165                 *p++ = (((b3 & 0x3) << 6) | b4 );
166             }
167
168         }
169
170         free(buf);
171
172         return (dest);
173     }
174     return (NULL);
175 }
176
177 static char encode(unsigned char u)
178 {
179     if (u < 26) {
180         return 'A' + u;
181     }
182     if (u < 52) {
183         return 'a' + (u - 26);
184     }
185     if (u < 62) {
186         return '0' + (u - 52);
187     }
188     if (u == 62) {
189         return '+';
190     }
191
192     return '/';
193 }
194
195 /* Decode a base64 character */
196 static unsigned char decode(char c)
197 {
198     if (c >= 'A' && c <= 'Z') {
199         return (c - 'A');
200     }
201     if (c >= 'a' && c <= 'z') {
202         return (c - 'a' + 26);
203     }
204     if (c >= '0' && c <= '9') {
205         return (c - '0' + 52);
206     }
207     if (c == '+') {
208         return 62;
209     }
210
211     return 63;
212 }
213
214 /* Returns TRUE if 'c' is a valid base64 character, otherwise FALSE */
215 static int is_base64(char c)
216 {
217     if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
218         (c >= '0' && c <= '9') || (c == '+')             ||
219         (c == '/')             || (c == '=')) {
220
221         return TRUE;
222     }
223     return FALSE;
224 }
225