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