1 /*
2  * atheme-services: A collection of minimalist IRC services
3  * ubase64.c: ircu base64 routines.
4  *
5  * Copyright (c) 2005-2007 Atheme Project (http://www.atheme.org)
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
12  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
15  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
17  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
19  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
20  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21  * POSSIBILITY OF SUCH DAMAGE.
22  */
23 
24 #include "atheme.h"
25 
26 /*
27  * base64touint() written 01/20/06 by jilles, for getting IP addresses.
28  */
29 
30 static const char ub64_alphabet[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]";
31 #define __ '\377'
32 static const char ub64_lookuptab[256] = {
33 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 0-15 */
34 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 16-31 */
35 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 32-47 */
36 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, __, __, __, __, __, __, /* 48-63 */
37 __, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 64-79 */
38 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62, __, 63, __, __, /* 80-95 */
39 __, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 96-111 */
40 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, __, __, __, __, __, /* 112-127 */
41 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
42 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
43 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
44 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
45 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
46 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
47 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
48 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __ };
49 #undef __
50 
uinttobase64(char * buf,uint64_t v,int64_t count)51 const char *uinttobase64(char *buf, uint64_t v, int64_t count)
52 {
53 	buf[count] = '\0';
54 
55 	while (count > 0)
56 	{
57 		buf[--count] = ub64_alphabet[v & 63];
58 		v >>= 6;
59 	}
60 
61 	return buf;
62 }
63 
base64touint(const char * buf)64 unsigned int base64touint(const char *buf)
65 {
66 	int bits;
67 	unsigned int v = 0;
68 	int count = 6;
69 
70 	while (--count >= 0 && (bits = ub64_lookuptab[255 & *buf++]) != '\377')
71 		v = v << 6 | bits;
72 	return v;
73 }
74 
decode_p10_ip(const char * b64,char ipstring[HOSTIPLEN])75 void decode_p10_ip(const char *b64, char ipstring[HOSTIPLEN])
76 {
77 	struct in_addr ip;
78 	char buf[4];
79 	int i, j;
80 	size_t len;
81 
82 	ipstring[0] = '\0';
83 	len = strlen(b64);
84 	if (len == 6)
85 	{
86 		ip.s_addr = ntohl(base64touint(b64));
87 		if (!inet_ntop(AF_INET, &ip, ipstring, HOSTIPLEN))
88 			ipstring[0] = '\0';
89 	}
90 	else if (len == 24 || (len < 24 && strchr(b64, '_')))
91 	{
92 		/* why is this encoded in such a complicated manner? */
93 		i = 0;
94 		j = 0;
95 		while (b64[i] != '\0')
96 		{
97 			if (b64[i] == '_')
98 			{
99 				i++;
100 				if (j >= HOSTIPLEN - 2)
101 					break;
102 				if (j == 0)
103 					ipstring[j++] = '0';
104 				if (b64[i] == '\0')
105 					ipstring[j++] = ':';
106 				ipstring[j++] = ':';
107 			}
108 			else
109 			{
110 				if (j >= HOSTIPLEN - 5)
111 					break;
112 				if (j != 0)
113 					ipstring[j++] = ':';
114 				mowgli_strlcpy(buf, b64 + i, 4);
115 				i += strlen(buf);
116 				j += sprintf(ipstring + j, "%x", (uint16_t)base64touint(buf));
117 			}
118 		}
119 		ipstring[j] = '\0';
120 	}
121 }
122 
123 /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
124  * vim:ts=8
125  * vim:sw=8
126  * vim:noexpandtab
127  */
128