1 1.1 elric /* $NetBSD: common.c,v 1.2 2017/01/28 21:31:49 christos 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.2 christos int aret; 355 1.2 christos 356 1.2 christos aret = asprintf(&str, "%s tried afs%s%s@%s -> %s (%d)", 357 1.2 christos data->name, cell ? "/" : "", 358 1.2 christos cell ? cell : "", realm, estr ? estr : "unknown", ret); 359 1.2 christos if (aret != -1) { 360 1.2 christos (*kafs_verbose)(kafs_verbose_ctx, str); 361 1.2 christos free(str); 362 1.2 christos } else { 363 1.2 christos (*kafs_verbose)(kafs_verbose_ctx, "out of memory"); 364 1.2 christos } 365 1.1 elric if (estr) 366 1.1 elric (*data->free_error)(data, estr); 367 1.1 elric } 368 1.1 elric 369 1.1 elric return ret; 370 1.1 elric } 371 1.1 elric 372 1.1 elric 373 1.1 elric int 374 1.1 elric _kafs_get_cred(struct kafs_data *data, 375 1.1 elric const char *cell, 376 1.1 elric const char *realm_hint, 377 1.1 elric const char *realm, 378 1.1 elric uid_t uid, 379 1.1 elric struct kafs_token *kt) 380 1.1 elric { 381 1.1 elric int ret = -1; 382 1.1 elric char *vl_realm; 383 1.1 elric char CELL[64]; 384 1.1 elric 385 1.1 elric /* We're about to find the realm that holds the key for afs in 386 1.1 elric * the specified cell. The problem is that null-instance 387 1.1 elric * afs-principals are common and that hitting the wrong realm might 388 1.1 elric * yield the wrong afs key. The following assumptions were made. 389 1.1 elric * 390 1.1 elric * Any realm passed to us is preferred. 391 1.1 elric * 392 1.1 elric * If there is a realm with the same name as the cell, it is most 393 1.1 elric * likely the correct realm to talk to. 394 1.1 elric * 395 1.1 elric * In most (maybe even all) cases the database servers of the cell 396 1.1 elric * will live in the realm we are looking for. 397 1.1 elric * 398 1.1 elric * Try the local realm, but if the previous cases fail, this is 399 1.1 elric * really a long shot. 400 1.1 elric * 401 1.1 elric */ 402 1.1 elric 403 1.1 elric /* comments on the ordering of these tests */ 404 1.1 elric 405 1.1 elric /* If the user passes a realm, she probably knows something we don't 406 1.1 elric * know and we should try afs@realm_hint. 407 1.1 elric */ 408 1.1 elric 409 1.1 elric if (realm_hint) { 410 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 411 1.1 elric cell, realm_hint, uid, kt); 412 1.1 elric if (ret == 0) return 0; 413 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 414 1.1 elric NULL, realm_hint, uid, kt); 415 1.1 elric if (ret == 0) return 0; 416 1.1 elric } 417 1.1 elric 418 1.1 elric _kafs_foldup(CELL, cell); 419 1.1 elric 420 1.1 elric /* 421 1.1 elric * If the AFS servers have a file /usr/afs/etc/krb.conf containing 422 1.1 elric * REALM we still don't have to resort to cross-cell authentication. 423 1.1 elric * Try afs.cell@REALM. 424 1.1 elric */ 425 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 426 1.1 elric cell, realm, uid, kt); 427 1.1 elric if (ret == 0) return 0; 428 1.1 elric 429 1.1 elric /* 430 1.1 elric * If cell == realm we don't need no cross-cell authentication. 431 1.1 elric * Try afs@REALM. 432 1.1 elric */ 433 1.1 elric if (strcmp(CELL, realm) == 0) { 434 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 435 1.1 elric NULL, realm, uid, kt); 436 1.1 elric if (ret == 0) return 0; 437 1.1 elric } 438 1.1 elric 439 1.1 elric /* 440 1.1 elric * We failed to get ``first class tickets'' for afs, 441 1.1 elric * fall back to cross-cell authentication. 442 1.1 elric * Try afs@CELL. 443 1.1 elric * Try afs.cell@CELL. 444 1.1 elric */ 445 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 446 1.1 elric NULL, CELL, uid, kt); 447 1.1 elric if (ret == 0) return 0; 448 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 449 1.1 elric cell, CELL, uid, kt); 450 1.1 elric if (ret == 0) return 0; 451 1.1 elric 452 1.1 elric /* 453 1.1 elric * Perhaps the cell doesn't correspond to any realm? 454 1.1 elric * Use realm of first volume location DB server. 455 1.1 elric * Try afs.cell@VL_REALM. 456 1.1 elric * Try afs@VL_REALM??? 457 1.1 elric */ 458 1.1 elric if (_kafs_realm_of_cell(data, cell, &vl_realm) == 0 459 1.1 elric && strcmp(vl_realm, realm) != 0 460 1.1 elric && strcmp(vl_realm, CELL) != 0) { 461 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 462 1.1 elric cell, vl_realm, uid, kt); 463 1.1 elric if (ret) 464 1.1 elric ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 465 1.1 elric NULL, vl_realm, uid, kt); 466 1.1 elric free(vl_realm); 467 1.1 elric if (ret == 0) return 0; 468 1.1 elric } 469 1.1 elric 470 1.1 elric return ret; 471 1.1 elric } 472