1 /* $OpenBSD: auxil.c,v 1.6 2001/02/13 20:30:40 angelos Exp $ */ 2 /* 3 * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu) 4 * 5 * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA, 6 * in April-May 1998 7 * 8 * Copyright (C) 1998, 1999 by Angelos D. Keromytis. 9 * 10 * Permission to use, copy, and modify this software without fee 11 * is hereby granted, provided that this entire notice is included in 12 * all copies of any software which is or includes a copy or 13 * modification of this software. 14 * 15 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 16 * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO 17 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 18 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 19 * PURPOSE. 20 */ 21 22 #if HAVE_CONFIG_H 23 #include "config.h" 24 #endif /* HAVE_CONFIG_H */ 25 26 #include <sys/types.h> 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <ctype.h> 30 31 #if STDC_HEADERS 32 #include <string.h> 33 #endif /* STDC_HEADERS */ 34 35 #if HAVE_LIMITS_H 36 #include <limits.h> 37 #endif /* HAVE_LIMITS_H */ 38 39 #include "header.h" 40 #include "keynote.h" 41 #include "assertion.h" 42 #include "signature.h" 43 44 /* 45 * Get some sort of key-hash for hash table indexing purposes. 46 */ 47 static int 48 keynote_keyhash(void *key, int alg) 49 { 50 struct keynote_binary *bn; 51 unsigned int res = 0, i; 52 #ifdef CRYPTO 53 DSA *dsa; 54 RSA *rsa; 55 #endif /* CRYPTO */ 56 57 if (key == (void *) NULL) 58 return 0; 59 60 switch (alg) 61 { 62 #ifdef CRYPTO 63 case KEYNOTE_ALGORITHM_DSA: 64 dsa = (DSA *) key; 65 res += BN_mod_word(dsa->p, HASHTABLESIZE); 66 res += BN_mod_word(dsa->q, HASHTABLESIZE); 67 res += BN_mod_word(dsa->g, HASHTABLESIZE); 68 res += BN_mod_word(dsa->pub_key, HASHTABLESIZE); 69 return res % HASHTABLESIZE; 70 71 case KEYNOTE_ALGORITHM_RSA: 72 rsa = (RSA *) key; 73 res += BN_mod_word(rsa->n, HASHTABLESIZE); 74 res += BN_mod_word(rsa->e, HASHTABLESIZE); 75 return res % HASHTABLESIZE; 76 77 case KEYNOTE_ALGORITHM_X509: /* RSA-specific */ 78 rsa = (RSA *) key; 79 res += BN_mod_word(rsa->n, HASHTABLESIZE); 80 res += BN_mod_word(rsa->e, HASHTABLESIZE); 81 return res % HASHTABLESIZE; 82 #endif /* CRYPTO */ 83 84 case KEYNOTE_ALGORITHM_BINARY: 85 bn = (struct keynote_binary *) key; 86 for (i = 0; i < bn->bn_len; i++) 87 res = (res + ((unsigned char) bn->bn_key[i])) % HASHTABLESIZE; 88 89 return res; 90 91 case KEYNOTE_ALGORITHM_NONE: 92 return keynote_stringhash(key, HASHTABLESIZE); 93 94 default: 95 return 0; 96 } 97 } 98 99 /* 100 * Return RESULT_TRUE if key appears in the action authorizers. 101 */ 102 int 103 keynote_in_action_authorizers(void *key, int algorithm) 104 { 105 struct keylist *kl, *kl2; 106 void *s; 107 int alg; 108 109 if (algorithm == KEYNOTE_ALGORITHM_UNSPEC) 110 { 111 kl2 = keynote_keylist_find(keynote_current_assertion->as_keylist, key); 112 if (kl2 == (struct keylist *) NULL) 113 return RESULT_FALSE; /* Shouldn't ever happen */ 114 115 s = kl2->key_key; 116 alg = kl2->key_alg; 117 } 118 else 119 { 120 s = key; 121 alg = algorithm; 122 } 123 124 for (kl = keynote_current_session->ks_action_authorizers; 125 kl != (struct keylist *) NULL; 126 kl = kl->key_next) 127 if ((kl->key_alg == alg) || 128 ((kl->key_alg == KEYNOTE_ALGORITHM_RSA) && 129 (alg == KEYNOTE_ALGORITHM_X509)) || 130 ((kl->key_alg == KEYNOTE_ALGORITHM_X509) && 131 (alg == KEYNOTE_ALGORITHM_RSA))) 132 if (kn_keycompare(kl->key_key, s, alg) == RESULT_TRUE) 133 return RESULT_TRUE; 134 135 return RESULT_FALSE; 136 } 137 138 /* 139 * Add a key to the keylist. Return RESULT_TRUE on success, -1 (and set 140 * keynote_errno) otherwise. We are not supposed to make a copy of the 141 * argument. 142 */ 143 int 144 keynote_keylist_add(struct keylist **keylist, char *key) 145 { 146 struct keynote_deckey dc; 147 struct keylist *kl; 148 149 if (keylist == (struct keylist **) NULL) 150 { 151 keynote_errno = ERROR_MEMORY; 152 return -1; 153 } 154 155 kl = (struct keylist *) calloc(1, sizeof(struct keylist)); 156 if (kl == (struct keylist *) NULL) 157 { 158 keynote_errno = ERROR_MEMORY; 159 return -1; 160 } 161 162 if (kn_decode_key(&dc, key, KEYNOTE_PUBLIC_KEY) != 0) 163 { 164 free(kl); 165 return -1; 166 } 167 168 kl->key_key = dc.dec_key; 169 kl->key_alg = dc.dec_algorithm; 170 kl->key_stringkey = key; 171 kl->key_next = *keylist; 172 *keylist = kl; 173 return RESULT_TRUE; 174 } 175 176 /* 177 * Remove an action authorizer. 178 */ 179 int 180 kn_remove_authorizer(int sessid, char *key) 181 { 182 struct keynote_session *ks; 183 struct keylist *kl, *kl2; 184 185 keynote_errno = 0; 186 if ((keynote_current_session == (struct keynote_session *) NULL) || 187 (keynote_current_session->ks_id != sessid)) 188 { 189 keynote_current_session = keynote_find_session(sessid); 190 if (keynote_current_session == (struct keynote_session *) NULL) 191 { 192 keynote_errno = ERROR_NOTFOUND; 193 return -1; 194 } 195 } 196 197 ks = keynote_current_session; 198 199 /* If no action authorizers present */ 200 if ((kl = ks->ks_action_authorizers) == (struct keylist *) NULL) 201 { 202 keynote_errno = ERROR_NOTFOUND; 203 return -1; 204 } 205 206 /* First in list */ 207 if (!strcmp(kl->key_stringkey, key)) 208 { 209 ks->ks_action_authorizers = kl->key_next; 210 kl->key_next = (struct keylist *) NULL; 211 keynote_keylist_free(kl); 212 return 0; 213 } 214 215 for (; kl->key_next != (struct keylist *) NULL; kl = kl->key_next) 216 if (!strcmp(kl->key_next->key_stringkey, key)) 217 { 218 kl2 = kl->key_next; 219 kl->key_next = kl2->key_next; 220 kl2->key_next = (struct keylist *) NULL; 221 keynote_keylist_free(kl2); 222 return 0; 223 } 224 225 keynote_errno = ERROR_NOTFOUND; 226 return -1; 227 } 228 229 /* 230 * Add an action authorizer. 231 */ 232 int 233 kn_add_authorizer(int sessid, char *key) 234 { 235 char *stringkey; 236 237 keynote_errno = 0; 238 if ((keynote_current_session == (struct keynote_session *) NULL) || 239 (keynote_current_session->ks_id != sessid)) 240 { 241 keynote_current_session = keynote_find_session(sessid); 242 if (keynote_current_session == (struct keynote_session *) NULL) 243 { 244 keynote_errno = ERROR_NOTFOUND; 245 return -1; 246 } 247 } 248 249 stringkey = strdup((char *) key); 250 if (stringkey == (char *) NULL) 251 { 252 keynote_errno = ERROR_MEMORY; 253 return -1; 254 } 255 256 if (keynote_keylist_add(&(keynote_current_session->ks_action_authorizers), 257 stringkey) == -1) 258 { 259 free(stringkey); 260 return -1; 261 } 262 263 return 0; 264 } 265 266 /* 267 * Find a keylist entry based on the key_stringkey entry. 268 */ 269 struct keylist * 270 keynote_keylist_find(struct keylist *kl, char *s) 271 { 272 for (; kl != (struct keylist *) NULL; kl = kl->key_next) 273 if (!strcmp(kl->key_stringkey, s)) 274 return kl; 275 276 return kl; 277 } 278 279 /* 280 * Free keylist list. 281 */ 282 void 283 keynote_keylist_free(struct keylist *kl) 284 { 285 struct keylist *kl2; 286 287 while (kl != (struct keylist *) NULL) 288 { 289 kl2 = kl->key_next; 290 free(kl->key_stringkey); 291 keynote_free_key(kl->key_key, kl->key_alg); 292 free(kl); 293 kl = kl2; 294 } 295 } 296 297 /* 298 * Free a key. 299 */ 300 void 301 kn_free_key(struct keynote_deckey *dc) 302 { 303 if (dc) 304 keynote_free_key(dc->dec_key, dc->dec_algorithm); 305 } 306 307 /* 308 * Find the num-th assertion given the authorizer. Return NULL if not found. 309 */ 310 struct assertion * 311 keynote_find_assertion(void *authorizer, int num, int algorithm) 312 { 313 struct assertion *as; 314 unsigned int h; 315 316 if (authorizer == (char *) NULL) 317 return (struct assertion *) NULL; 318 319 h = keynote_keyhash(authorizer, algorithm); 320 for (as = keynote_current_session->ks_assertion_table[h]; 321 as != (struct assertion *) NULL; 322 as = as->as_next) 323 if ((as->as_authorizer != (void *) NULL) && 324 ((as->as_signeralgorithm == algorithm) || 325 ((as->as_signeralgorithm == KEYNOTE_ALGORITHM_RSA) && 326 (algorithm == KEYNOTE_ALGORITHM_X509)) || 327 ((as->as_signeralgorithm == KEYNOTE_ALGORITHM_X509) && 328 (algorithm == KEYNOTE_ALGORITHM_RSA)))) 329 if (kn_keycompare(authorizer, as->as_authorizer, algorithm) == 330 RESULT_TRUE) 331 if (num-- == 0) 332 return as; 333 334 return (struct assertion *) NULL; 335 } 336 337 /* 338 * Add an assertion to the hash table. Return RESULT_TRUE on success, 339 * ERROR_MEMORY for memory failure, ERROR_SYNTAX if some problem with 340 * the assertion is detected. 341 */ 342 int 343 keynote_add_htable(struct assertion *as, int which) 344 { 345 char *hashname; 346 unsigned int i; 347 348 if (as == (struct assertion *) NULL) 349 { 350 keynote_errno = ERROR_MEMORY; 351 return -1; 352 } 353 354 if (!which) 355 hashname = as->as_authorizer_string_s; 356 else 357 hashname = as->as_authorizer; 358 359 if (hashname == (char *) NULL) 360 { 361 keynote_errno = ERROR_SYNTAX; 362 return -1; 363 } 364 365 i = keynote_keyhash(hashname, as->as_signeralgorithm); 366 as->as_next = keynote_current_session->ks_assertion_table[i]; 367 keynote_current_session->ks_assertion_table[i] = as; 368 return RESULT_TRUE; 369 } 370 371 /* 372 * Parse and store an assertion in the internal hash table. 373 * Return the result of the evaluation, if doing early evaluation. 374 * If an error was encountered, set keynote_errno. 375 */ 376 int 377 kn_add_assertion(int sessid, char *asrt, int len, int assertion_flags) 378 { 379 struct assertion *as; 380 381 keynote_errno = 0; 382 if ((keynote_current_session == (struct keynote_session *) NULL) || 383 (keynote_current_session->ks_id != sessid)) 384 { 385 keynote_current_session = keynote_find_session(sessid); 386 if (keynote_current_session == (struct keynote_session *) NULL) 387 { 388 keynote_errno = ERROR_NOTFOUND; 389 return -1; 390 } 391 } 392 393 as = keynote_parse_assertion(asrt, len, assertion_flags); 394 if ((as == (struct assertion *) NULL) || (keynote_errno != 0)) 395 { 396 if (keynote_errno == 0) 397 keynote_errno = ERROR_SYNTAX; 398 399 return -1; 400 } 401 402 as->as_id = keynote_current_session->ks_assertioncounter++; 403 404 /* Check for wrap around...there has to be a better solution to this */ 405 if (keynote_current_session->ks_assertioncounter < 0) 406 { 407 keynote_free_assertion(as); 408 keynote_errno = ERROR_SYNTAX; 409 return -1; 410 } 411 412 if (keynote_add_htable(as, 0) != RESULT_TRUE) 413 { 414 keynote_free_assertion(as); 415 return -1; 416 } 417 418 as->as_internalflags |= ASSERT_IFLAG_NEEDPROC; 419 return as->as_id; 420 } 421 422 /* 423 * Remove an assertion from the hash table. 424 */ 425 static int 426 keynote_remove_assertion(int sessid, int assertid, int deleteflag) 427 { 428 struct assertion *ht, *ht2; 429 int i; 430 431 if ((keynote_current_session == (struct keynote_session *) NULL) || 432 (keynote_current_session->ks_id != sessid)) 433 { 434 keynote_current_session = keynote_find_session(sessid); 435 if (keynote_current_session == (struct keynote_session *) NULL) 436 { 437 keynote_errno = ERROR_NOTFOUND; 438 return -1; 439 } 440 } 441 442 for (i = 0; i < HASHTABLESIZE; i++) 443 { 444 ht = keynote_current_session->ks_assertion_table[i]; 445 if (ht == (struct assertion *) NULL) 446 continue; 447 448 /* If first entry in bucket */ 449 if (ht->as_id == assertid) 450 { 451 keynote_current_session->ks_assertion_table[i] = ht->as_next; 452 if (deleteflag) 453 keynote_free_assertion(ht); 454 return 0; 455 } 456 457 for (; ht->as_next != (struct assertion *) NULL; ht = ht->as_next) 458 if (ht->as_next->as_id == assertid) /* Got it */ 459 { 460 ht2 = ht->as_next; 461 ht->as_next = ht2->as_next; 462 if (deleteflag) 463 keynote_free_assertion(ht2); 464 return 0; 465 } 466 } 467 468 keynote_errno = ERROR_NOTFOUND; 469 return -1; 470 } 471 472 /* 473 * API wrapper for deleting assertions. 474 */ 475 int 476 kn_remove_assertion(int sessid, int assertid) 477 { 478 keynote_errno = 0; 479 return keynote_remove_assertion(sessid, assertid, 1); 480 } 481 482 /* 483 * Internally-used wrapper for removing but not deleting assertions. 484 */ 485 int 486 keynote_sremove_assertion(int sessid, int assertid) 487 { 488 return keynote_remove_assertion(sessid, assertid, 0); 489 } 490 491 /* 492 * Free an assertion structure. 493 */ 494 void 495 keynote_free_assertion(struct assertion *as) 496 { 497 if (as == (struct assertion *) NULL) 498 return; 499 500 if (as->as_buf != (char *) NULL) 501 free(as->as_buf); 502 503 if (as->as_signature != (char *) NULL) 504 free(as->as_signature); 505 506 if (as->as_env != (struct environment *) NULL) 507 keynote_env_cleanup(&(as->as_env), 1); 508 509 if (as->as_keylist != (struct keylist *) NULL) 510 keynote_keylist_free(as->as_keylist); 511 512 if (as->as_authorizer != (void *) NULL) 513 keynote_free_key(as->as_authorizer, as->as_signeralgorithm); 514 515 free(as); 516 } 517 518 unsigned int 519 keynote_stringhash(char *name, unsigned int size) 520 { 521 unsigned int hash_val = 0; 522 unsigned int i; 523 524 if ((size == 0) || (size == 1)) 525 return 0; 526 527 for (; *name; name++) 528 { 529 hash_val = (hash_val << 2) + *name; 530 if ((i = hash_val & 0x3fff) != 0) 531 hash_val = ((hash_val ^ (i >> 12)) & 0x3fff); 532 } 533 534 return hash_val % size; 535 } 536