common.c revision 1.1 1 1.1 elric /* $NetBSD: common.c,v 1.1 2011/04/13 18:15:30 elric Exp $ */
2 1.1 elric
3 1.1 elric /*
4 1.1 elric * Copyright (c) 1997 - 2005 Kungliga Tekniska Hgskolan
5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden).
6 1.1 elric * All rights reserved.
7 1.1 elric *
8 1.1 elric * Redistribution and use in source and binary forms, with or without
9 1.1 elric * modification, are permitted provided that the following conditions
10 1.1 elric * are met:
11 1.1 elric *
12 1.1 elric * 1. Redistributions of source code must retain the above copyright
13 1.1 elric * notice, this list of conditions and the following disclaimer.
14 1.1 elric *
15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 elric * notice, this list of conditions and the following disclaimer in the
17 1.1 elric * documentation and/or other materials provided with the distribution.
18 1.1 elric *
19 1.1 elric * 3. Neither the name of the Institute nor the names of its contributors
20 1.1 elric * may be used to endorse or promote products derived from this software
21 1.1 elric * without specific prior written permission.
22 1.1 elric *
23 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 1.1 elric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 elric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 1.1 elric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 elric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 elric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 elric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 elric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 elric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 elric * SUCH DAMAGE.
34 1.1 elric */
35 1.1 elric
36 1.1 elric #include "kafs_locl.h"
37 1.1 elric
38 1.1 elric #define AUTH_SUPERUSER "afs"
39 1.1 elric
40 1.1 elric /*
41 1.1 elric * Here only ASCII characters are relevant.
42 1.1 elric */
43 1.1 elric
44 1.1 elric #define IsAsciiLower(c) ('a' <= (c) && (c) <= 'z')
45 1.1 elric
46 1.1 elric #define ToAsciiUpper(c) ((c) - 'a' + 'A')
47 1.1 elric
48 1.1 elric static void (*kafs_verbose)(void *, const char *);
49 1.1 elric static void *kafs_verbose_ctx;
50 1.1 elric
51 1.1 elric void
52 1.1 elric _kafs_foldup(char *a, const char *b)
53 1.1 elric {
54 1.1 elric for (; *b; a++, b++)
55 1.1 elric if (IsAsciiLower(*b))
56 1.1 elric *a = ToAsciiUpper(*b);
57 1.1 elric else
58 1.1 elric *a = *b;
59 1.1 elric *a = '\0';
60 1.1 elric }
61 1.1 elric
62 1.1 elric void
63 1.1 elric kafs_set_verbose(void (*f)(void *, const char *), void *ctx)
64 1.1 elric {
65 1.1 elric if (f) {
66 1.1 elric kafs_verbose = f;
67 1.1 elric kafs_verbose_ctx = ctx;
68 1.1 elric }
69 1.1 elric }
70 1.1 elric
71 1.1 elric int
72 1.1 elric kafs_settoken_rxkad(const char *cell, struct ClearToken *ct,
73 1.1 elric void *ticket, size_t ticket_len)
74 1.1 elric {
75 1.1 elric struct ViceIoctl parms;
76 1.1 elric char buf[2048], *t;
77 1.1 elric int32_t sizeof_x;
78 1.1 elric
79 1.1 elric t = buf;
80 1.1 elric /*
81 1.1 elric * length of secret token followed by secret token
82 1.1 elric */
83 1.1 elric sizeof_x = ticket_len;
84 1.1 elric memcpy(t, &sizeof_x, sizeof(sizeof_x));
85 1.1 elric t += sizeof(sizeof_x);
86 1.1 elric memcpy(t, ticket, sizeof_x);
87 1.1 elric t += sizeof_x;
88 1.1 elric /*
89 1.1 elric * length of clear token followed by clear token
90 1.1 elric */
91 1.1 elric sizeof_x = sizeof(*ct);
92 1.1 elric memcpy(t, &sizeof_x, sizeof(sizeof_x));
93 1.1 elric t += sizeof(sizeof_x);
94 1.1 elric memcpy(t, ct, sizeof_x);
95 1.1 elric t += sizeof_x;
96 1.1 elric
97 1.1 elric /*
98 1.1 elric * do *not* mark as primary cell
99 1.1 elric */
100 1.1 elric sizeof_x = 0;
101 1.1 elric memcpy(t, &sizeof_x, sizeof(sizeof_x));
102 1.1 elric t += sizeof(sizeof_x);
103 1.1 elric /*
104 1.1 elric * follow with cell name
105 1.1 elric */
106 1.1 elric sizeof_x = strlen(cell) + 1;
107 1.1 elric memcpy(t, cell, sizeof_x);
108 1.1 elric t += sizeof_x;
109 1.1 elric
110 1.1 elric /*
111 1.1 elric * Build argument block
112 1.1 elric */
113 1.1 elric parms.in = buf;
114 1.1 elric parms.in_size = t - buf;
115 1.1 elric parms.out = 0;
116 1.1 elric parms.out_size = 0;
117 1.1 elric
118 1.1 elric return k_pioctl(0, VIOCSETTOK, &parms, 0);
119 1.1 elric }
120 1.1 elric
121 1.1 elric void
122 1.1 elric _kafs_fixup_viceid(struct ClearToken *ct, uid_t uid)
123 1.1 elric {
124 1.1 elric #define ODD(x) ((x) & 1)
125 1.1 elric /* According to Transarc conventions ViceId is valid iff
126 1.1 elric * (EndTimestamp - BeginTimestamp) is odd. By decrementing EndTime
127 1.1 elric * the transformations:
128 1.1 elric *
129 1.1 elric * (issue_date, life) -> (StartTime, EndTime) -> (issue_date, life)
130 1.1 elric * preserves the original values.
131 1.1 elric */
132 1.1 elric if (uid != 0) /* valid ViceId */
133 1.1 elric {
134 1.1 elric if (!ODD(ct->EndTimestamp - ct->BeginTimestamp))
135 1.1 elric ct->EndTimestamp--;
136 1.1 elric }
137 1.1 elric else /* not valid ViceId */
138 1.1 elric {
139 1.1 elric if (ODD(ct->EndTimestamp - ct->BeginTimestamp))
140 1.1 elric ct->EndTimestamp--;
141 1.1 elric }
142 1.1 elric }
143 1.1 elric
144 1.1 elric /* Try to get a db-server for an AFS cell from a AFSDB record */
145 1.1 elric
146 1.1 elric static int
147 1.1 elric dns_find_cell(const char *cell, char *dbserver, size_t len)
148 1.1 elric {
149 1.1 elric struct rk_dns_reply *r;
150 1.1 elric int ok = -1;
151 1.1 elric r = rk_dns_lookup(cell, "afsdb");
152 1.1 elric if(r){
153 1.1 elric struct rk_resource_record *rr = r->head;
154 1.1 elric while(rr){
155 1.1 elric if(rr->type == rk_ns_t_afsdb && rr->u.afsdb->preference == 1){
156 1.1 elric strlcpy(dbserver,
157 1.1 elric rr->u.afsdb->domain,
158 1.1 elric len);
159 1.1 elric ok = 0;
160 1.1 elric break;
161 1.1 elric }
162 1.1 elric rr = rr->next;
163 1.1 elric }
164 1.1 elric rk_dns_free_data(r);
165 1.1 elric }
166 1.1 elric return ok;
167 1.1 elric }
168 1.1 elric
169 1.1 elric
170 1.1 elric /*
171 1.1 elric * Try to find the cells we should try to klog to in "file".
172 1.1 elric */
173 1.1 elric static void
174 1.1 elric find_cells(const char *file, char ***cells, int *idx)
175 1.1 elric {
176 1.1 elric FILE *f;
177 1.1 elric char cell[64];
178 1.1 elric int i;
179 1.1 elric int ind = *idx;
180 1.1 elric
181 1.1 elric f = fopen(file, "r");
182 1.1 elric if (f == NULL)
183 1.1 elric return;
184 1.1 elric while (fgets(cell, sizeof(cell), f)) {
185 1.1 elric char *t;
186 1.1 elric t = cell + strlen(cell);
187 1.1 elric for (; t >= cell; t--)
188 1.1 elric if (*t == '\n' || *t == '\t' || *t == ' ')
189 1.1 elric *t = 0;
190 1.1 elric if (cell[0] == '\0' || cell[0] == '#')
191 1.1 elric continue;
192 1.1 elric for(i = 0; i < ind; i++)
193 1.1 elric if(strcmp((*cells)[i], cell) == 0)
194 1.1 elric break;
195 1.1 elric if(i == ind){
196 1.1 elric char **tmp;
197 1.1 elric
198 1.1 elric tmp = realloc(*cells, (ind + 1) * sizeof(**cells));
199 1.1 elric if (tmp == NULL)
200 1.1 elric break;
201 1.1 elric *cells = tmp;
202 1.1 elric (*cells)[ind] = strdup(cell);
203 1.1 elric if ((*cells)[ind] == NULL)
204 1.1 elric break;
205 1.1 elric ++ind;
206 1.1 elric }
207 1.1 elric }
208 1.1 elric fclose(f);
209 1.1 elric *idx = ind;
210 1.1 elric }
211 1.1 elric
212 1.1 elric /*
213 1.1 elric * Get tokens for all cells[]
214 1.1 elric */
215 1.1 elric static int
216 1.1 elric afslog_cells(struct kafs_data *data, char **cells, int max, uid_t uid,
217 1.1 elric const char *homedir)
218 1.1 elric {
219 1.1 elric int ret = 0;
220 1.1 elric int i;
221 1.1 elric for (i = 0; i < max; i++) {
222 1.1 elric int er = (*data->afslog_uid)(data, cells[i], 0, uid, homedir);
223 1.1 elric if (er)
224 1.1 elric ret = er;
225 1.1 elric }
226 1.1 elric return ret;
227 1.1 elric }
228 1.1 elric
229 1.1 elric int
230 1.1 elric _kafs_afslog_all_local_cells(struct kafs_data *data,
231 1.1 elric uid_t uid, const char *homedir)
232 1.1 elric {
233 1.1 elric int ret;
234 1.1 elric char **cells = NULL;
235 1.1 elric int idx = 0;
236 1.1 elric
237 1.1 elric if (homedir == NULL)
238 1.1 elric homedir = getenv("HOME");
239 1.1 elric if (homedir != NULL) {
240 1.1 elric char home[MaxPathLen];
241 1.1 elric snprintf(home, sizeof(home), "%s/.TheseCells", homedir);
242 1.1 elric find_cells(home, &cells, &idx);
243 1.1 elric }
244 1.1 elric find_cells(_PATH_THESECELLS, &cells, &idx);
245 1.1 elric find_cells(_PATH_THISCELL, &cells, &idx);
246 1.1 elric find_cells(_PATH_ARLA_THESECELLS, &cells, &idx);
247 1.1 elric find_cells(_PATH_ARLA_THISCELL, &cells, &idx);
248 1.1 elric find_cells(_PATH_OPENAFS_DEBIAN_THESECELLS, &cells, &idx);
249 1.1 elric find_cells(_PATH_OPENAFS_DEBIAN_THISCELL, &cells, &idx);
250 1.1 elric find_cells(_PATH_OPENAFS_MACOSX_THESECELLS, &cells, &idx);
251 1.1 elric find_cells(_PATH_OPENAFS_MACOSX_THISCELL, &cells, &idx);
252 1.1 elric find_cells(_PATH_ARLA_DEBIAN_THESECELLS, &cells, &idx);
253 1.1 elric find_cells(_PATH_ARLA_DEBIAN_THISCELL, &cells, &idx);
254 1.1 elric find_cells(_PATH_ARLA_OPENBSD_THESECELLS, &cells, &idx);
255 1.1 elric find_cells(_PATH_ARLA_OPENBSD_THISCELL, &cells, &idx);
256 1.1 elric
257 1.1 elric ret = afslog_cells(data, cells, idx, uid, homedir);
258 1.1 elric while(idx > 0)
259 1.1 elric free(cells[--idx]);
260 1.1 elric free(cells);
261 1.1 elric return ret;
262 1.1 elric }
263 1.1 elric
264 1.1 elric
265 1.1 elric static int
266 1.1 elric file_find_cell(struct kafs_data *data,
267 1.1 elric const char *cell, char **realm, int exact)
268 1.1 elric {
269 1.1 elric FILE *F;
270 1.1 elric char buf[1024];
271 1.1 elric char *p;
272 1.1 elric int ret = -1;
273 1.1 elric
274 1.1 elric if ((F = fopen(_PATH_CELLSERVDB, "r"))
275 1.1 elric || (F = fopen(_PATH_ARLA_CELLSERVDB, "r"))
276 1.1 elric || (F = fopen(_PATH_OPENAFS_DEBIAN_CELLSERVDB, "r"))
277 1.1 elric || (F = fopen(_PATH_OPENAFS_MACOSX_CELLSERVDB, "r"))
278 1.1 elric || (F = fopen(_PATH_ARLA_DEBIAN_CELLSERVDB, "r"))) {
279 1.1 elric while (fgets(buf, sizeof(buf), F)) {
280 1.1 elric int cmp;
281 1.1 elric
282 1.1 elric if (buf[0] != '>')
283 1.1 elric continue; /* Not a cell name line, try next line */
284 1.1 elric p = buf;
285 1.1 elric strsep(&p, " \t\n#");
286 1.1 elric
287 1.1 elric if (exact)
288 1.1 elric cmp = strcmp(buf + 1, cell);
289 1.1 elric else
290 1.1 elric cmp = strncmp(buf + 1, cell, strlen(cell));
291 1.1 elric
292 1.1 elric if (cmp == 0) {
293 1.1 elric /*
294 1.1 elric * We found the cell name we're looking for.
295 1.1 elric * Read next line on the form ip-address '#' hostname
296 1.1 elric */
297 1.1 elric if (fgets(buf, sizeof(buf), F) == NULL)
298 1.1 elric break; /* Read failed, give up */
299 1.1 elric p = strchr(buf, '#');
300 1.1 elric if (p == NULL)
301 1.1 elric break; /* No '#', give up */
302 1.1 elric p++;
303 1.1 elric if (buf[strlen(buf) - 1] == '\n')
304 1.1 elric buf[strlen(buf) - 1] = '\0';
305 1.1 elric *realm = (*data->get_realm)(data, p);
306 1.1 elric if (*realm && **realm != '\0')
307 1.1 elric ret = 0;
308 1.1 elric break; /* Won't try any more */
309 1.1 elric }
310 1.1 elric }
311 1.1 elric fclose(F);
312 1.1 elric }
313 1.1 elric return ret;
314 1.1 elric }
315 1.1 elric
316 1.1 elric /* Find the realm associated with cell. Do this by opening CellServDB
317 1.1 elric file and getting the realm-of-host for the first VL-server for the
318 1.1 elric cell.
319 1.1 elric
320 1.1 elric This does not work when the VL-server is living in one realm, but
321 1.1 elric the cell it is serving is living in another realm.
322 1.1 elric
323 1.1 elric Return 0 on success, -1 otherwise.
324 1.1 elric */
325 1.1 elric
326 1.1 elric int
327 1.1 elric _kafs_realm_of_cell(struct kafs_data *data,
328 1.1 elric const char *cell, char **realm)
329 1.1 elric {
330 1.1 elric char buf[1024];
331 1.1 elric int ret;
332 1.1 elric
333 1.1 elric ret = file_find_cell(data, cell, realm, 1);
334 1.1 elric if (ret == 0)
335 1.1 elric return ret;
336 1.1 elric if (dns_find_cell(cell, buf, sizeof(buf)) == 0) {
337 1.1 elric *realm = (*data->get_realm)(data, buf);
338 1.1 elric if(*realm != NULL)
339 1.1 elric return 0;
340 1.1 elric }
341 1.1 elric return file_find_cell(data, cell, realm, 0);
342 1.1 elric }
343 1.1 elric
344 1.1 elric static int
345 1.1 elric _kafs_try_get_cred(struct kafs_data *data, const char *user, const char *cell,
346 1.1 elric const char *realm, uid_t uid, struct kafs_token *kt)
347 1.1 elric {
348 1.1 elric int ret;
349 1.1 elric
350 1.1 elric ret = (*data->get_cred)(data, user, cell, realm, uid, kt);
351 1.1 elric if (kafs_verbose) {
352 1.1 elric const char *estr = (*data->get_error)(data, ret);
353 1.1 elric char *str;
354 1.1 elric asprintf(&str, "%s tried afs%s%s@%s -> %s (%d)",
355 1.1 elric data->name, cell ? "/" : "",
356 1.1 elric cell ? cell : "", realm, estr ? estr : "unknown", ret);
357 1.1 elric (*kafs_verbose)(kafs_verbose_ctx, str);
358 1.1 elric if (estr)
359 1.1 elric (*data->free_error)(data, estr);
360 1.1 elric free(str);
361 1.1 elric }
362 1.1 elric
363 1.1 elric return ret;
364 1.1 elric }
365 1.1 elric
366 1.1 elric
367 1.1 elric int
368 1.1 elric _kafs_get_cred(struct kafs_data *data,
369 1.1 elric const char *cell,
370 1.1 elric const char *realm_hint,
371 1.1 elric const char *realm,
372 1.1 elric uid_t uid,
373 1.1 elric struct kafs_token *kt)
374 1.1 elric {
375 1.1 elric int ret = -1;
376 1.1 elric char *vl_realm;
377 1.1 elric char CELL[64];
378 1.1 elric
379 1.1 elric /* We're about to find the realm that holds the key for afs in
380 1.1 elric * the specified cell. The problem is that null-instance
381 1.1 elric * afs-principals are common and that hitting the wrong realm might
382 1.1 elric * yield the wrong afs key. The following assumptions were made.
383 1.1 elric *
384 1.1 elric * Any realm passed to us is preferred.
385 1.1 elric *
386 1.1 elric * If there is a realm with the same name as the cell, it is most
387 1.1 elric * likely the correct realm to talk to.
388 1.1 elric *
389 1.1 elric * In most (maybe even all) cases the database servers of the cell
390 1.1 elric * will live in the realm we are looking for.
391 1.1 elric *
392 1.1 elric * Try the local realm, but if the previous cases fail, this is
393 1.1 elric * really a long shot.
394 1.1 elric *
395 1.1 elric */
396 1.1 elric
397 1.1 elric /* comments on the ordering of these tests */
398 1.1 elric
399 1.1 elric /* If the user passes a realm, she probably knows something we don't
400 1.1 elric * know and we should try afs@realm_hint.
401 1.1 elric */
402 1.1 elric
403 1.1 elric if (realm_hint) {
404 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
405 1.1 elric cell, realm_hint, uid, kt);
406 1.1 elric if (ret == 0) return 0;
407 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
408 1.1 elric NULL, realm_hint, uid, kt);
409 1.1 elric if (ret == 0) return 0;
410 1.1 elric }
411 1.1 elric
412 1.1 elric _kafs_foldup(CELL, cell);
413 1.1 elric
414 1.1 elric /*
415 1.1 elric * If the AFS servers have a file /usr/afs/etc/krb.conf containing
416 1.1 elric * REALM we still don't have to resort to cross-cell authentication.
417 1.1 elric * Try afs.cell@REALM.
418 1.1 elric */
419 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
420 1.1 elric cell, realm, uid, kt);
421 1.1 elric if (ret == 0) return 0;
422 1.1 elric
423 1.1 elric /*
424 1.1 elric * If cell == realm we don't need no cross-cell authentication.
425 1.1 elric * Try afs@REALM.
426 1.1 elric */
427 1.1 elric if (strcmp(CELL, realm) == 0) {
428 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
429 1.1 elric NULL, realm, uid, kt);
430 1.1 elric if (ret == 0) return 0;
431 1.1 elric }
432 1.1 elric
433 1.1 elric /*
434 1.1 elric * We failed to get ``first class tickets'' for afs,
435 1.1 elric * fall back to cross-cell authentication.
436 1.1 elric * Try afs@CELL.
437 1.1 elric * Try afs.cell@CELL.
438 1.1 elric */
439 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
440 1.1 elric NULL, CELL, uid, kt);
441 1.1 elric if (ret == 0) return 0;
442 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
443 1.1 elric cell, CELL, uid, kt);
444 1.1 elric if (ret == 0) return 0;
445 1.1 elric
446 1.1 elric /*
447 1.1 elric * Perhaps the cell doesn't correspond to any realm?
448 1.1 elric * Use realm of first volume location DB server.
449 1.1 elric * Try afs.cell@VL_REALM.
450 1.1 elric * Try afs@VL_REALM???
451 1.1 elric */
452 1.1 elric if (_kafs_realm_of_cell(data, cell, &vl_realm) == 0
453 1.1 elric && strcmp(vl_realm, realm) != 0
454 1.1 elric && strcmp(vl_realm, CELL) != 0) {
455 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
456 1.1 elric cell, vl_realm, uid, kt);
457 1.1 elric if (ret)
458 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
459 1.1 elric NULL, vl_realm, uid, kt);
460 1.1 elric free(vl_realm);
461 1.1 elric if (ret == 0) return 0;
462 1.1 elric }
463 1.1 elric
464 1.1 elric return ret;
465 1.1 elric }
466