blob: 84e390fd1d61bf4fac9de79d3e29b200b5a0878b [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller95def091999-11-25 00:26:21 +11002 * radix.c
Damien Miller4af51302000-04-16 11:18:38 +10003 *
Damien Miller95def091999-11-25 00:26:21 +11004 * 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.
Damien Miller4af51302000-04-16 11:18:38 +10007 *
Damien Miller95def091999-11-25 00:26:21 +11008 * 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 Miller4af51302000-04-16 11:18:38 +100026int
Damien Miller95def091999-11-25 00:26:21 +110027uuencode(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 Miller4af51302000-04-16 11:18:38 +100052int
Damien Miller95def091999-11-25 00:26:21 +110053uudecode(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
Damien Miller5428f641999-11-25 11:54:57 +110077 /*
78 * Figure out how many characters are in the input buffer. If this
79 * would decode into more bytes than would fit into the output
80 * buffer, adjust the number of input bytes downwards.
81 */
Damien Miller95def091999-11-25 00:26:21 +110082 bufin = bufcoded;
83 while (DEC(*(bufin++)) <= MAXVAL);
84 nprbytes = bufin - bufcoded - 1;
85 nbytesdecoded = ((nprbytes + 3) / 4) * 3;
86 if (nbytesdecoded > outbufsize)
87 nprbytes = (outbufsize * 4) / 3;
88
89 bufin = bufcoded;
90
91 while (nprbytes > 0) {
92 *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
93 *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
94 *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
95 bufin += 4;
96 nprbytes -= 4;
97 }
98 if (nprbytes & 03) {
99 if (DEC(bufin[-2]) > MAXVAL)
100 nbytesdecoded -= 2;
101 else
102 nbytesdecoded -= 1;
103 }
104 return (nbytesdecoded);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000105}
106
107typedef unsigned char my_u_char;
108typedef unsigned int my_u_int32_t;
109typedef unsigned short my_u_short;
110
111/* Nasty macros from BIND-4.9.2 */
112
113#define GETSHORT(s, cp) { \
114 register my_u_char *t_cp = (my_u_char*)(cp); \
115 (s) = (((my_u_short)t_cp[0]) << 8) \
116 | (((my_u_short)t_cp[1])) \
117 ; \
118 (cp) += 2; \
119}
120
121#define GETLONG(l, cp) { \
122 register my_u_char *t_cp = (my_u_char*)(cp); \
123 (l) = (((my_u_int32_t)t_cp[0]) << 24) \
124 | (((my_u_int32_t)t_cp[1]) << 16) \
125 | (((my_u_int32_t)t_cp[2]) << 8) \
126 | (((my_u_int32_t)t_cp[3])) \
127 ; \
128 (cp) += 4; \
129}
130
131#define PUTSHORT(s, cp) { \
132 register my_u_short t_s = (my_u_short)(s); \
133 register my_u_char *t_cp = (my_u_char*)(cp); \
134 *t_cp++ = t_s >> 8; \
135 *t_cp = t_s; \
136 (cp) += 2; \
137}
138
139#define PUTLONG(l, cp) { \
140 register my_u_int32_t t_l = (my_u_int32_t)(l); \
141 register my_u_char *t_cp = (my_u_char*)(cp); \
142 *t_cp++ = t_l >> 24; \
143 *t_cp++ = t_l >> 16; \
144 *t_cp++ = t_l >> 8; \
145 *t_cp = t_l; \
146 (cp) += 4; \
147}
148
149#define GETSTRING(s, p, p_l) { \
150 register char* p_targ = (p) + p_l; \
151 register char* s_c = (s); \
152 register char* p_c = (p); \
153 while (*p_c && (p_c < p_targ)) { \
154 *s_c++ = *p_c++; \
155 } \
156 if (p_c == p_targ) { \
157 return 1; \
158 } \
159 *s_c = *p_c++; \
160 (p_l) = (p_l) - (p_c - (p)); \
161 (p) = p_c; \
162}
163
164
Damien Miller4af51302000-04-16 11:18:38 +1000165int
Damien Miller95def091999-11-25 00:26:21 +1100166creds_to_radix(CREDENTIALS *creds, unsigned char *buf)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000167{
Damien Miller95def091999-11-25 00:26:21 +1100168 char *p, *s;
169 int len;
170 char temp[2048];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000171
Damien Miller95def091999-11-25 00:26:21 +1100172 p = temp;
173 *p++ = 1; /* version */
174 s = creds->service;
175 while (*s)
176 *p++ = *s++;
177 *p++ = *s;
178 s = creds->instance;
179 while (*s)
180 *p++ = *s++;
181 *p++ = *s;
182 s = creds->realm;
183 while (*s)
184 *p++ = *s++;
185 *p++ = *s;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000186
Damien Miller95def091999-11-25 00:26:21 +1100187 s = creds->pname;
188 while (*s)
189 *p++ = *s++;
190 *p++ = *s;
191 s = creds->pinst;
192 while (*s)
193 *p++ = *s++;
194 *p++ = *s;
195 /* Null string to repeat the realm. */
196 *p++ = '\0';
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000197
Damien Miller95def091999-11-25 00:26:21 +1100198 PUTLONG(creds->issue_date, p);
199 {
200 unsigned int endTime;
201 endTime = (unsigned int) krb_life_to_time(creds->issue_date,
202 creds->lifetime);
203 PUTLONG(endTime, p);
204 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000205
Damien Miller95def091999-11-25 00:26:21 +1100206 memcpy(p, &creds->session, sizeof(creds->session));
207 p += sizeof(creds->session);
208
209 PUTSHORT(creds->kvno, p);
210 PUTLONG(creds->ticket_st.length, p);
211
212 memcpy(p, creds->ticket_st.dat, creds->ticket_st.length);
213 p += creds->ticket_st.length;
214 len = p - temp;
215
Damien Miller7684ee12000-03-17 23:40:15 +1100216 return (uuencode((unsigned char *)temp, len, (char *)buf));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000217}
218
Damien Miller4af51302000-04-16 11:18:38 +1000219int
Damien Miller95def091999-11-25 00:26:21 +1100220radix_to_creds(const char *buf, CREDENTIALS *creds)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000221{
222
Damien Miller95def091999-11-25 00:26:21 +1100223 char *p;
224 int len, tl;
225 char version;
226 char temp[2048];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000227
Damien Miller7684ee12000-03-17 23:40:15 +1100228 if (!(len = uudecode(buf, (unsigned char *)temp, sizeof(temp))))
Damien Miller95def091999-11-25 00:26:21 +1100229 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000230
Damien Miller95def091999-11-25 00:26:21 +1100231 p = temp;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000232
Damien Miller95def091999-11-25 00:26:21 +1100233 /* check version and length! */
234 if (len < 1)
235 return 0;
236 version = *p;
237 p++;
238 len--;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000239
Damien Miller95def091999-11-25 00:26:21 +1100240 GETSTRING(creds->service, p, len);
241 GETSTRING(creds->instance, p, len);
242 GETSTRING(creds->realm, p, len);
243
244 GETSTRING(creds->pname, p, len);
245 GETSTRING(creds->pinst, p, len);
246 /* Ignore possibly different realm. */
247 while (*p && len)
248 p++, len--;
249 if (len == 0)
250 return 0;
251 p++, len--;
252
253 /* Enough space for remaining fixed-length parts? */
254 if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
255 return 0;
256
257 GETLONG(creds->issue_date, p);
258 len -= 4;
259 {
260 unsigned int endTime;
261 GETLONG(endTime, p);
262 len -= 4;
263 creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
264 }
265
266 memcpy(&creds->session, p, sizeof(creds->session));
267 p += sizeof(creds->session);
268 len -= sizeof(creds->session);
269
270 GETSHORT(creds->kvno, p);
271 len -= 2;
272 GETLONG(creds->ticket_st.length, p);
273 len -= 4;
274
275 tl = creds->ticket_st.length;
276 if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
277 return 0;
278
279 memcpy(creds->ticket_st.dat, p, tl);
280 p += tl;
281 len -= tl;
282
283 return 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000284}
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000285#endif /* AFS */