Anope IRC Services  Version 1.8
base64.c
Go to the documentation of this file.
1 /* base64 routines.
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 
14 /*
15  This is borrowed from Unreal
16 */
17 
18 #include "services.h"
19 
20 static char *int_to_base64(long);
21 static long base64_to_int(char *);
22 
23 char *base64enc(long i)
24 {
25  if (i < 0)
26  return ("0");
27  return int_to_base64(i);
28 }
29 
30 long base64dec(char *b64)
31 {
32  if (b64)
33  return base64_to_int(b64);
34  else
35  return 0;
36 }
37 
38 
39 static const char Base64[] =
40  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
41 static const char Pad64 = '=';
42 
43 /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
44  The following encoding technique is taken from RFC 1521 by Borenstein
45  and Freed. It is reproduced here in a slightly edited form for
46  convenience.
47 
48  A 65-character subset of US-ASCII is used, enabling 6 bits to be
49  represented per printable character. (The extra 65th character, "=",
50  is used to signify a special processing function.)
51 
52  The encoding process represents 24-bit groups of input bits as output
53  strings of 4 encoded characters. Proceeding from left to right, a
54  24-bit input group is formed by concatenating 3 8-bit input groups.
55  These 24 bits are then treated as 4 concatenated 6-bit groups, each
56  of which is translated into a single digit in the base64 alphabet.
57 
58  Each 6-bit group is used as an index into an array of 64 printable
59  characters. The character referenced by the index is placed in the
60  output string.
61 
62  Table 1: The Base64 Alphabet
63 
64  Value Encoding Value Encoding Value Encoding Value Encoding
65  0 A 17 R 34 i 51 z
66  1 B 18 S 35 j 52 0
67  2 C 19 T 36 k 53 1
68  3 D 20 U 37 l 54 2
69  4 E 21 V 38 m 55 3
70  5 F 22 W 39 n 56 4
71  6 G 23 X 40 o 57 5
72  7 H 24 Y 41 p 58 6
73  8 I 25 Z 42 q 59 7
74  9 J 26 a 43 r 60 8
75  10 K 27 b 44 s 61 9
76  11 L 28 c 45 t 62 +
77  12 M 29 d 46 u 63 /
78  13 N 30 e 47 v
79  14 O 31 f 48 w (pad) =
80  15 P 32 g 49 x
81  16 Q 33 h 50 y
82 
83  Special processing is performed if fewer than 24 bits are available
84  at the end of the data being encoded. A full encoding quantum is
85  always completed at the end of a quantity. When fewer than 24 input
86  bits are available in an input group, zero bits are added (on the
87  right) to form an integral number of 6-bit groups. Padding at the
88  end of the data is performed using the '=' character.
89 
90  Since all base64 input is an integral number of octets, only the
91  -------------------------------------------------
92  following cases can arise:
93 
94  (1) the final quantum of encoding input is an integral
95  multiple of 24 bits; here, the final unit of encoded
96  output will be an integral multiple of 4 characters
97  with no "=" padding,
98  (2) the final quantum of encoding input is exactly 8 bits;
99  here, the final unit of encoded output will be two
100  characters followed by two "=" padding characters, or
101  (3) the final quantum of encoding input is exactly 16 bits;
102  here, the final unit of encoded output will be three
103  characters followed by one "=" padding character.
104  */
105 
106 int b64_encode(char *src, size_t srclength, char *target, size_t targsize)
107 {
108  size_t datalength = 0;
109  unsigned char input[3];
110  unsigned char output[4];
111  size_t i;
112 
113  while (2 < srclength) {
114  input[0] = *src++;
115  input[1] = *src++;
116  input[2] = *src++;
117  srclength -= 3;
118 
119  output[0] = input[0] >> 2;
120  output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
121  output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
122  output[3] = input[2] & 0x3f;
123 
124  if (datalength + 4 > targsize)
125  return (-1);
126  target[datalength++] = Base64[output[0]];
127  target[datalength++] = Base64[output[1]];
128  target[datalength++] = Base64[output[2]];
129  target[datalength++] = Base64[output[3]];
130  }
131 
132  /* Now we worry about padding. */
133  if (0 != srclength) {
134  /* Get what's left. */
135  input[0] = input[1] = input[2] = '\0';
136  for (i = 0; i < srclength; i++)
137  input[i] = *src++;
138 
139  output[0] = input[0] >> 2;
140  output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
141  output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
142 
143  if (datalength + 4 > targsize)
144  return (-1);
145  target[datalength++] = Base64[output[0]];
146  target[datalength++] = Base64[output[1]];
147  if (srclength == 1)
148  target[datalength++] = Pad64;
149  else
150  target[datalength++] = Base64[output[2]];
151  target[datalength++] = Pad64;
152  }
153  if (datalength >= targsize)
154  return (-1);
155  target[datalength] = '\0'; /* Returned value doesn't count \0. */
156  return (datalength);
157 }
158 
159 /* skips all whitespace anywhere.
160  converts characters, four at a time, starting at (or after)
161  src from base - 64 numbers into three 8 bit bytes in the target area.
162  it returns the number of data bytes stored at the target, or -1 on error.
163  */
164 
165 int b64_decode(char *src, char *target, size_t targsize)
166 {
167  int tarindex, state, ch;
168  char *pos;
169 
170  state = 0;
171  tarindex = 0;
172 
173  while ((ch = *src++) != '\0') {
174  if (isspace(ch)) /* Skip whitespace anywhere. */
175  continue;
176 
177  if (ch == Pad64)
178  break;
179 
180  pos = strchr(Base64, ch);
181  if (pos == 0) /* A non-base64 character. */
182  return (-1);
183 
184  switch (state) {
185  case 0:
186  if (target) {
187  if ((size_t) tarindex >= targsize)
188  return (-1);
189  target[tarindex] = (pos - Base64) << 2;
190  }
191  state = 1;
192  break;
193  case 1:
194  if (target) {
195  if ((size_t) tarindex + 1 >= targsize)
196  return (-1);
197  target[tarindex] |= (pos - Base64) >> 4;
198  target[tarindex + 1] = ((pos - Base64) & 0x0f)
199  << 4;
200  }
201  tarindex++;
202  state = 2;
203  break;
204  case 2:
205  if (target) {
206  if ((size_t) tarindex + 1 >= targsize)
207  return (-1);
208  target[tarindex] |= (pos - Base64) >> 2;
209  target[tarindex + 1] = ((pos - Base64) & 0x03)
210  << 6;
211  }
212  tarindex++;
213  state = 3;
214  break;
215  case 3:
216  if (target) {
217  if ((size_t) tarindex >= targsize)
218  return (-1);
219  target[tarindex] |= (pos - Base64);
220  }
221  tarindex++;
222  state = 0;
223  break;
224  default:
225  abort();
226  }
227  }
228 
229  /*
230  * We are done decoding Base-64 chars. Let's see if we ended
231  * on a byte boundary, and/or with erroneous trailing characters.
232  */
233 
234  if (ch == Pad64) { /* We got a pad char. */
235  ch = *src++; /* Skip it, get next. */
236  switch (state) {
237  case 0: /* Invalid = in first position */
238  case 1: /* Invalid = in second position */
239  return (-1);
240 
241  case 2: /* Valid, means one byte of info */
242  /* Skip any number of spaces. */
243  for ((void) NULL; ch != '\0'; ch = *src++)
244  if (!isspace(ch))
245  break;
246  /* Make sure there is another trailing = sign. */
247  if (ch != Pad64)
248  return (-1);
249  ch = *src++; /* Skip the = */
250  /* Fall through to "single trailing =" case. */
251  /* FALLTHROUGH */
252 
253  case 3: /* Valid, means two bytes of info */
254  /*
255  * We know this char is an =. Is there anything but
256  * whitespace after it?
257  */
258  for ((void) NULL; ch != '\0'; ch = *src++)
259  if (!isspace(ch))
260  return (-1);
261 
262  /*
263  * Now make sure for cases 2 and 3 that the "extra"
264  * bits that slopped past the last full byte were
265  * zeros. If we don't check them, they become a
266  * subliminal channel.
267  */
268  if (target && target[tarindex] != 0)
269  return (-1);
270  }
271  } else {
272  /*
273  * We ended by seeing the end of the string. Make sure we
274  * have no partial bytes lying around.
275  */
276  if (state != 0)
277  return (-1);
278  }
279 
280  return (tarindex);
281 }
282 
283 char *encode_ip(unsigned char *ip)
284 {
285  static char buf[25];
286  unsigned char *cp;
287  struct in_addr ia; /* For IPv4 */
288  char *s_ip; /* Signed ip string */
289 
290  if (!ip)
291  return "*";
292 
293  if (strchr((char *) ip, ':')) {
294  return NULL;
295  } else {
296  s_ip = str_signed(ip);
297  ia.s_addr = inet_addr(s_ip);
298  cp = (unsigned char *) &ia.s_addr;
299  b64_encode((char *) &cp, sizeof(struct in_addr), buf, 25);
300  }
301  return buf;
302 }
303 
304 int decode_ip(char *buf)
305 {
306  int len = strlen(buf);
307  char targ[25];
308  struct in_addr *ia;
309 
310  b64_decode(buf, targ, 25);
311  ia = (struct in_addr *) targ;
312  if (len == 24) { /* IPv6 */
313  return 0;
314  } else if (len == 8) /* IPv4 */
315  return ia->s_addr;
316  else /* Error?? */
317  return 0;
318 }
319 
320 /* ':' and '#' and '&' and '+' and '@' must never be in this table. */
321 /* these tables must NEVER CHANGE! >) */
323  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
324  'E', 'F',
325  'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
326  'U', 'V',
327  'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
328  'k', 'l',
329  'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
330  '{', '}'
331 };
332 
334  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
335  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
336  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
337  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
338  -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
339  25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
340  -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
341  51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, 63, -1, -1,
342  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
343  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
344  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
345  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
346  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
347  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
348  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
349  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
350 };
351 
352 static char *int_to_base64(long val)
353 {
354  /* 32/6 == max 6 bytes for representation,
355  * +1 for the null, +1 for byte boundaries
356  */
357  static char base64buf[8];
358  long i = 7;
359 
360  base64buf[i] = '\0';
361 
362  /* Temporary debugging code.. remove before 2038 ;p.
363  * This might happen in case of 64bit longs (opteron/ia64),
364  * if the value is then too large it can easily lead to
365  * a buffer underflow and thus to a crash. -- Syzop
366  */
367  if (val > 2147483647L) {
368  abort();
369  }
370 
371  do {
372  base64buf[--i] = int6_to_base64_map[val & 63];
373  }
374  while (val >>= 6);
375 
376  return base64buf + i;
377 }
378 
379 static long base64_to_int(char *b64)
380 {
381  int v = base64_to_int6_map[(unsigned char) *b64++];
382 
383  if (!b64)
384  return 0;
385 
386  while (*b64) {
387  v <<= 6;
388  v += base64_to_int6_map[(unsigned char) *b64++];
389  }
390 
391  return v;
392 }
393 
394 long base64dects(char *ts)
395 {
396  char *token;
397  long value;
398 
399  if (!ts) {
400  return 0;
401  }
402  token = myStrGetToken(ts, '!', 1);
403 
404  if (!token) {
405  return strtoul(ts, NULL, 10);
406  }
407  value = base64dec(token);
408  Anope_Free(token);
409  return value;
410 }
#define Anope_Free(x)
Definition: extern.h:1391
char base64_to_int6_map[]
Definition: base64.c:333
static long base64_to_int(char *)
Definition: base64.c:379
static char * int_to_base64(long)
Definition: base64.c:352
long base64dects(char *ts)
Definition: base64.c:394
static const char Pad64
Definition: base64.c:41
char * base64enc(long i)
Definition: base64.c:23
static const char Base64[]
Definition: base64.c:39
long base64dec(char *b64)
Definition: base64.c:30
int b64_encode(char *src, size_t srclength, char *target, size_t targsize)
Definition: base64.c:106
int decode_ip(char *buf)
Definition: base64.c:304
E char * myStrGetToken(const char *str, const char dilim, int token_number)
Definition: misc.c:654
int b64_decode(char *src, char *target, size_t targsize)
Definition: base64.c:165
char * encode_ip(unsigned char *ip)
Definition: base64.c:283
char int6_to_base64_map[]
Definition: base64.c:322
E char * str_signed(unsigned char *str)
Definition: misc.c:1169