blob: 6637b2fb10982221c0ed4bd56d31f143c7d5b543 [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller95def091999-11-25 00:26:21 +11002 * radix.c
3 *
4 * base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
5 * Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
6 * and placed in the public domain.
7 *
8 * Dug Song <dugsong@UMICH.EDU>
9 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100010
Damien Millerd4a8b7e1999-10-27 13:42:43 +100011#include "includes.h"
12
13#ifdef AFS
14#include <krb.h>
15
16char six2pr[64] = {
Damien Miller95def091999-11-25 00:26:21 +110017 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
18 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
19 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
20 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
21 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
Damien Millerd4a8b7e1999-10-27 13:42:43 +100022};
23
24unsigned char pr2six[256];
25
Damien Miller95def091999-11-25 00:26:21 +110026int
27uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100028{
Damien Miller95def091999-11-25 00:26:21 +110029 /* ENC is the basic 1 character encoding function to make a char printing */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100030#define ENC(c) six2pr[c]
Damien Miller95def091999-11-25 00:26:21 +110031
32 register char *outptr = bufcoded;
33 unsigned int i;
34
35 for (i = 0; i < nbytes; i += 3) {
36 *(outptr++) = ENC(*bufin >> 2); /* c1 */
37 *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /* c2 */
38 *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); /* c3 */
39 *(outptr++) = ENC(bufin[2] & 077); /* c4 */
40 bufin += 3;
41 }
42 if (i == nbytes + 1) {
43 outptr[-1] = '=';
44 } else if (i == nbytes + 2) {
45 outptr[-1] = '=';
46 outptr[-2] = '=';
47 }
48 *outptr = '\0';
49 return (outptr - bufcoded);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100050}
51
Damien Miller95def091999-11-25 00:26:21 +110052int
53uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100054{
Damien Miller95def091999-11-25 00:26:21 +110055 /* single character decode */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100056#define DEC(c) pr2six[(unsigned char)c]
57#define MAXVAL 63
Damien Miller95def091999-11-25 00:26:21 +110058
59 static int first = 1;
60 int nbytesdecoded, j;
61 const char *bufin = bufcoded;
62 register unsigned char *bufout = bufplain;
63 register int nprbytes;
64
65 /* If this is the first call, initialize the mapping table. */
66 if (first) {
67 first = 0;
68 for (j = 0; j < 256; j++)
69 pr2six[j] = MAXVAL + 1;
70 for (j = 0; j < 64; j++)
71 pr2six[(unsigned char) six2pr[j]] = (unsigned char) j;
72 }
73 /* Strip leading whitespace. */
74 while (*bufcoded == ' ' || *bufcoded == '\t')
75 bufcoded++;
76
77 /* Figure out how many characters are in the input buffer. If this
78 would decode into more bytes than would fit into the output
79 buffer, adjust the number of input bytes downwards. */
80 bufin = bufcoded;
81 while (DEC(*(bufin++)) <= MAXVAL);
82 nprbytes = bufin - bufcoded - 1;
83 nbytesdecoded = ((nprbytes + 3) / 4) * 3;
84 if (nbytesdecoded > outbufsize)
85 nprbytes = (outbufsize * 4) / 3;
86
87 bufin = bufcoded;
88
89 while (nprbytes > 0) {
90 *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
91 *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
92 *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
93 bufin += 4;
94 nprbytes -= 4;
95 }
96 if (nprbytes & 03) {
97 if (DEC(bufin[-2]) > MAXVAL)
98 nbytesdecoded -= 2;
99 else
100 nbytesdecoded -= 1;
101 }
102 return (nbytesdecoded);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000103}
104
105typedef unsigned char my_u_char;
106typedef unsigned int my_u_int32_t;
107typedef unsigned short my_u_short;
108
109/* Nasty macros from BIND-4.9.2 */
110
111#define GETSHORT(s, cp) { \
112 register my_u_char *t_cp = (my_u_char*)(cp); \
113 (s) = (((my_u_short)t_cp[0]) << 8) \
114 | (((my_u_short)t_cp[1])) \
115 ; \
116 (cp) += 2; \
117}
118
119#define GETLONG(l, cp) { \
120 register my_u_char *t_cp = (my_u_char*)(cp); \
121 (l) = (((my_u_int32_t)t_cp[0]) << 24) \
122 | (((my_u_int32_t)t_cp[1]) << 16) \
123 | (((my_u_int32_t)t_cp[2]) << 8) \
124 | (((my_u_int32_t)t_cp[3])) \
125 ; \
126 (cp) += 4; \
127}
128
129#define PUTSHORT(s, cp) { \
130 register my_u_short t_s = (my_u_short)(s); \
131 register my_u_char *t_cp = (my_u_char*)(cp); \
132 *t_cp++ = t_s >> 8; \
133 *t_cp = t_s; \
134 (cp) += 2; \
135}
136
137#define PUTLONG(l, cp) { \
138 register my_u_int32_t t_l = (my_u_int32_t)(l); \
139 register my_u_char *t_cp = (my_u_char*)(cp); \
140 *t_cp++ = t_l >> 24; \
141 *t_cp++ = t_l >> 16; \
142 *t_cp++ = t_l >> 8; \
143 *t_cp = t_l; \
144 (cp) += 4; \
145}
146
147#define GETSTRING(s, p, p_l) { \
148 register char* p_targ = (p) + p_l; \
149 register char* s_c = (s); \
150 register char* p_c = (p); \
151 while (*p_c && (p_c < p_targ)) { \
152 *s_c++ = *p_c++; \
153 } \
154 if (p_c == p_targ) { \
155 return 1; \
156 } \
157 *s_c = *p_c++; \
158 (p_l) = (p_l) - (p_c - (p)); \
159 (p) = p_c; \
160}
161
162
Damien Miller95def091999-11-25 00:26:21 +1100163int
164creds_to_radix(CREDENTIALS *creds, unsigned char *buf)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000165{
Damien Miller95def091999-11-25 00:26:21 +1100166 char *p, *s;
167 int len;
168 char temp[2048];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000169
Damien Miller95def091999-11-25 00:26:21 +1100170 p = temp;
171 *p++ = 1; /* version */
172 s = creds->service;
173 while (*s)
174 *p++ = *s++;
175 *p++ = *s;
176 s = creds->instance;
177 while (*s)
178 *p++ = *s++;
179 *p++ = *s;
180 s = creds->realm;
181 while (*s)
182 *p++ = *s++;
183 *p++ = *s;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000184
Damien Miller95def091999-11-25 00:26:21 +1100185 s = creds->pname;
186 while (*s)
187 *p++ = *s++;
188 *p++ = *s;
189 s = creds->pinst;
190 while (*s)
191 *p++ = *s++;
192 *p++ = *s;
193 /* Null string to repeat the realm. */
194 *p++ = '\0';
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000195
Damien Miller95def091999-11-25 00:26:21 +1100196 PUTLONG(creds->issue_date, p);
197 {
198 unsigned int endTime;
199 endTime = (unsigned int) krb_life_to_time(creds->issue_date,
200 creds->lifetime);
201 PUTLONG(endTime, p);
202 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000203
Damien Miller95def091999-11-25 00:26:21 +1100204 memcpy(p, &creds->session, sizeof(creds->session));
205 p += sizeof(creds->session);
206
207 PUTSHORT(creds->kvno, p);
208 PUTLONG(creds->ticket_st.length, p);
209
210 memcpy(p, creds->ticket_st.dat, creds->ticket_st.length);
211 p += creds->ticket_st.length;
212 len = p - temp;
213
214 return (uuencode(temp, len, buf));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000215}
216
Damien Miller95def091999-11-25 00:26:21 +1100217int
218radix_to_creds(const char *buf, CREDENTIALS *creds)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000219{
220
Damien Miller95def091999-11-25 00:26:21 +1100221 char *p;
222 int len, tl;
223 char version;
224 char temp[2048];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000225
Damien Miller95def091999-11-25 00:26:21 +1100226 if (!(len = uudecode(buf, temp, sizeof(temp))))
227 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000228
Damien Miller95def091999-11-25 00:26:21 +1100229 p = temp;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000230
Damien Miller95def091999-11-25 00:26:21 +1100231 /* check version and length! */
232 if (len < 1)
233 return 0;
234 version = *p;
235 p++;
236 len--;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000237
Damien Miller95def091999-11-25 00:26:21 +1100238 GETSTRING(creds->service, p, len);
239 GETSTRING(creds->instance, p, len);
240 GETSTRING(creds->realm, p, len);
241
242 GETSTRING(creds->pname, p, len);
243 GETSTRING(creds->pinst, p, len);
244 /* Ignore possibly different realm. */
245 while (*p && len)
246 p++, len--;
247 if (len == 0)
248 return 0;
249 p++, len--;
250
251 /* Enough space for remaining fixed-length parts? */
252 if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
253 return 0;
254
255 GETLONG(creds->issue_date, p);
256 len -= 4;
257 {
258 unsigned int endTime;
259 GETLONG(endTime, p);
260 len -= 4;
261 creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
262 }
263
264 memcpy(&creds->session, p, sizeof(creds->session));
265 p += sizeof(creds->session);
266 len -= sizeof(creds->session);
267
268 GETSHORT(creds->kvno, p);
269 len -= 2;
270 GETLONG(creds->ticket_st.length, p);
271 len -= 4;
272
273 tl = creds->ticket_st.length;
274 if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
275 return 0;
276
277 memcpy(creds->ticket_st.dat, p, tl);
278 p += tl;
279 len -= tl;
280
281 return 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000282}
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000283#endif /* AFS */