1 /*
2 **
3 ** Copyright (C) 1994 Swedish University Network (SUNET)
4 ** Modified by Rami Lehti (C) 1999
5 **
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITTNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 **
21 **
22 **                                        Martin.Wendel@udac.uu.se
23 **                                        Torbjorn.Wictorin@udac.uu.se
24 **
25 **                                        UDAC
26 **                                        P.O. Box 174
27 **                                        S-751 04 Uppsala
28 **                                        Sweden
29 **
30 */
31 
32 #include "aide.h"
33 #include <string.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include "base64.h"
37 #include "util.h"
38 #include "log.h"
39 /*for locale support*/
40 #include "locale-aide.h"
41 /*for locale support*/
42 
43 char tob64[] =
44 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
45 
46 
47 
48 int fromb64[] = {
49 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
50 FAIL, SKIP, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
51 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
52 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
53 
54 SKIP, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
55 FAIL, FAIL, FAIL, 0x3e, FAIL, FAIL, FAIL, 0x3f,
56 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
57 0x3c, 0x3d, FAIL, FAIL, FAIL, SKIP, FAIL, FAIL,
58 
59 FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
60 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
61 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
62 0x17, 0x18, 0x19, FAIL, FAIL, FAIL, FAIL, FAIL,
63 
64 FAIL, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
65 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
66 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
67 0x31, 0x32, 0x33, FAIL, FAIL, FAIL, FAIL, FAIL,
68 
69 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
70 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
71 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
72 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
73 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
74 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
75 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
76 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
77 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
78 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
79 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
80 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
81 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
82 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
83 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
84 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL
85 };
86 
87 /* Returns NULL on error */
encode_base64(byte * src,size_t ssize)88 char* encode_base64(byte* src,size_t ssize)
89 {
90   char* outbuf;
91   int pos;
92   int i, l, left;
93   unsigned long triple;
94   byte *inb;
95 
96   /* Exit on empty input */
97   if (!ssize||src==NULL){
98     log_msg(LOG_LEVEL_DEBUG,"encode base64: empty string");
99     return NULL;
100   }
101 
102   /* length of encoded base64 string (padded) */
103   size_t length = sizeof(char)* ((ssize + 2) / 3) * 4;
104   outbuf = (char *)checked_malloc(length + 1);
105 
106   /* Initialize working pointers */
107   inb = src;
108   i = 0;
109   triple = 0;
110   pos = 0;
111   left = ssize;
112   log_msg(LOG_LEVEL_TRACE, "encode base64:, data length: %d", left);
113   /*
114    * Process entire inbuf.
115    */
116   while (left != 0)
117     {
118       i++;
119       left--;
120 
121       triple = (triple <<8) | *inb;
122       if (i == 3 || left == 0)
123 	{
124 	  switch (i)
125 	    {
126 	    case 1:
127 	      triple = triple<<4;
128 	      break;
129 	    case 2:
130 	      triple = triple<<2;
131 	      break;
132 	    default:
133 	      break;
134 	    }
135 	  for (l = i; l >= 0; l--){
136 	    /* register */
137 	    int rr;
138 	    rr = 0x3f & (triple>>(6*l));
139 	    assert (rr < 64);
140 	    outbuf[pos]=tob64[rr];
141 	    pos++;
142 	      }
143 	  if (left == 0)
144 	    switch(i)
145 	      {
146 	      case 2:
147 		outbuf[pos]='=';
148 		pos++;
149 		break;
150 	      case 1:
151 		outbuf[pos]='=';
152 		pos++;
153 		outbuf[pos]='=';
154 		pos++;
155 		break;
156 	      default:
157 		break;
158 	      }
159 	  triple = 0;
160 	  i = 0;
161 	  }
162       inb++;
163   }
164 
165   outbuf[pos]='\0';
166 
167   return outbuf;
168 }
169 
decode_base64(char * src,size_t ssize,size_t * ret_len)170 byte* decode_base64(char* src,size_t ssize, size_t *ret_len)
171 {
172   byte* outbuf;
173   char* inb;
174   int i;
175   int l;
176   int left;
177   int pos;
178   unsigned long triple;
179 
180   /* Exit on empty input */
181   if (!ssize||src==NULL) {
182     log_msg(LOG_LEVEL_DEBUG, "decode base64: empty string");
183     return NULL;
184   }
185 
186   /* exit on unpadded input */
187   if (ssize % 4) {
188     log_msg(LOG_LEVEL_WARNING, "decode_base64: '%s' has invalid length (missing padding characters?)", src);
189     return NULL;
190   }
191 
192   /* calculate length of decoded string, substract padding chars if any (ssize is >= 4) */
193   size_t length = sizeof(byte) * ((ssize / 4) * 3)- (src[ssize-1] == '=') - (src[ssize-2] == '=');
194 
195   /* Initialize working pointers */
196   inb = src;
197   outbuf = (byte *)checked_malloc(length + 1);
198 
199   l = 0;
200   triple = 0;
201   pos=0;
202   left = ssize;
203   /*
204    * Process entire inbuf.
205    */
206   while (left != 0)
207     {
208       left--;
209       i = fromb64[(unsigned char)*inb];
210       switch(i)
211 	{
212 	case FAIL:
213 	  log_msg(LOG_LEVEL_WARNING, "decode_base64: illegal character: '%c' in '%s'", *inb, src);
214 	  free(outbuf);
215 	  return NULL;
216 	  break;
217 	case SKIP:
218 	  break;
219 	default:
220 	  triple = triple<<6 | (0x3f & i);
221 	  l++;
222 	  break;
223 	}
224       if (l == 4 || left == 0)
225 	{
226 	  switch(l)
227 	    {
228 	    case 2:
229 	      triple = triple>>4;
230 	      break;
231 	    case 3:
232 	      triple = triple>>2;
233 	      break;
234 	    default:
235 	      break;
236 	    }
237 	  for (l  -= 2; l >= 0; l--)
238 	    {
239 	      outbuf[pos]=( 0xff & (triple>>(l*8)));
240 	      pos++;
241 	    }
242 	  triple = 0;
243 	  l = 0;
244 	}
245       inb++;
246     }
247 
248   outbuf[pos]='\0';
249 
250   if (ret_len) *ret_len = pos;
251 
252   return outbuf;
253 }
254 
length_base64(char * src,size_t ssize)255 size_t length_base64(char* src,size_t ssize)
256 {
257   char* inb;
258   int i;
259   int l;
260   int left;
261   size_t pos;
262   unsigned long triple;
263 
264   /* Exit on empty input */
265   if (!ssize||src==NULL) {
266     log_msg(LOG_LEVEL_DEBUG,"length_base64: empty string");
267     return 0;
268   }
269 
270 
271 
272   /* Initialize working pointers */
273   inb = src;
274 
275   l = 0;
276   triple = 0;
277   pos=0;
278   left = ssize;
279   /*
280    * Process entire inbuf.
281    */
282   while (left != 0)
283     {
284       left--;
285       i = fromb64[(unsigned char)*inb];
286       switch(i)
287 	{
288 	case FAIL:
289 	  log_msg(LOG_LEVEL_DEBUG, "length_base64: illegal string: '%s'", src);
290 	  return 0;
291 	  break;
292 	case SKIP:
293 	  break;
294 	default:
295 	  triple = triple<<6 | (0x3f & i);
296 	  l++;
297 	  break;
298 	}
299       if (l == 4 || left == 0)
300 	{
301 	  switch(l)
302 	    {
303 	    case 2:
304 	      triple = triple>>4;
305 	      break;
306 	    case 3:
307 	      triple = triple>>2;
308 	      break;
309 	    default:
310 	      break;
311 	    }
312 	  for (l  -= 2; l >= 0; l--)
313 	    {
314 	      pos++;
315 	    }
316 	  triple = 0;
317 	  l = 0;
318 	}
319       inb++;
320     }
321 
322   return pos;
323 }
324 
325