Annotation of embedaddon/strongswan/src/libstrongswan/credentials/auth_cfg.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2008-2017 Tobias Brunner
! 3: * Copyright (C) 2007-2009 Martin Willi
! 4: * Copyright (C) 2016 Andreas Steffen
! 5: * HSR Hochschule fuer Technik Rapperswil
! 6: *
! 7: * This program is free software; you can redistribute it and/or modify it
! 8: * under the terms of the GNU General Public License as published by the
! 9: * Free Software Foundation; either version 2 of the License, or (at your
! 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 11: *
! 12: * This program is distributed in the hope that it will be useful, but
! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 15: * for more details.
! 16: */
! 17:
! 18: #include "auth_cfg.h"
! 19:
! 20: #include <library.h>
! 21: #include <utils/debug.h>
! 22: #include <collections/array.h>
! 23: #include <utils/identification.h>
! 24: #include <eap/eap.h>
! 25: #include <credentials/certificates/certificate.h>
! 26:
! 27: ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_XAUTH,
! 28: "any",
! 29: "public key",
! 30: "pre-shared key",
! 31: "EAP",
! 32: "XAuth",
! 33: );
! 34:
! 35: ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT,
! 36: "RULE_IDENTITY",
! 37: "RULE_IDENTITY_LOOSE",
! 38: "RULE_AUTH_CLASS",
! 39: "RULE_AAA_IDENTITY",
! 40: "RULE_EAP_IDENTITY",
! 41: "RULE_EAP_TYPE",
! 42: "RULE_EAP_VENDOR",
! 43: "RULE_XAUTH_BACKEND",
! 44: "RULE_XAUTH_IDENTITY",
! 45: "AUTH_RULE_CA_IDENTITY",
! 46: "RULE_CA_CERT",
! 47: "RULE_IM_CERT",
! 48: "RULE_SUBJECT_CERT",
! 49: "RULE_CRL_VALIDATION",
! 50: "RULE_OCSP_VALIDATION",
! 51: "RULE_CERT_VALIDATION_SUSPENDED",
! 52: "RULE_GROUP",
! 53: "RULE_RSA_STRENGTH",
! 54: "RULE_ECDSA_STRENGTH",
! 55: "RULE_BLISS_STRENGTH",
! 56: "RULE_SIGNATURE_SCHEME",
! 57: "RULE_IKE_SIGNATURE_SCHEME",
! 58: "RULE_CERT_POLICY",
! 59: "HELPER_IM_CERT",
! 60: "HELPER_SUBJECT_CERT",
! 61: "HELPER_IM_HASH_URL",
! 62: "HELPER_SUBJECT_HASH_URL",
! 63: "HELPER_REVOCATION_CERT",
! 64: "HELPER_AC_CERT",
! 65: );
! 66:
! 67: /**
! 68: * Check if the given rule is a rule for which there may be multiple values.
! 69: */
! 70: static inline bool is_multi_value_rule(auth_rule_t type)
! 71: {
! 72: switch (type)
! 73: {
! 74: case AUTH_RULE_AUTH_CLASS:
! 75: case AUTH_RULE_EAP_TYPE:
! 76: case AUTH_RULE_EAP_VENDOR:
! 77: case AUTH_RULE_IDENTITY:
! 78: case AUTH_RULE_IDENTITY_LOOSE:
! 79: case AUTH_RULE_EAP_IDENTITY:
! 80: case AUTH_RULE_AAA_IDENTITY:
! 81: case AUTH_RULE_XAUTH_IDENTITY:
! 82: case AUTH_RULE_XAUTH_BACKEND:
! 83: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 84: case AUTH_HELPER_SUBJECT_CERT:
! 85: case AUTH_HELPER_SUBJECT_HASH_URL:
! 86: case AUTH_RULE_MAX:
! 87: return FALSE;
! 88: case AUTH_RULE_OCSP_VALIDATION:
! 89: case AUTH_RULE_CRL_VALIDATION:
! 90: case AUTH_RULE_GROUP:
! 91: case AUTH_RULE_SUBJECT_CERT:
! 92: case AUTH_RULE_CA_IDENTITY:
! 93: case AUTH_RULE_CA_CERT:
! 94: case AUTH_RULE_IM_CERT:
! 95: case AUTH_RULE_CERT_POLICY:
! 96: case AUTH_RULE_RSA_STRENGTH:
! 97: case AUTH_RULE_ECDSA_STRENGTH:
! 98: case AUTH_RULE_BLISS_STRENGTH:
! 99: case AUTH_RULE_SIGNATURE_SCHEME:
! 100: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 101: case AUTH_HELPER_IM_CERT:
! 102: case AUTH_HELPER_IM_HASH_URL:
! 103: case AUTH_HELPER_REVOCATION_CERT:
! 104: case AUTH_HELPER_AC_CERT:
! 105: return TRUE;
! 106: }
! 107: return FALSE;
! 108: }
! 109:
! 110: typedef struct private_auth_cfg_t private_auth_cfg_t;
! 111:
! 112: /**
! 113: * private data of item_set
! 114: */
! 115: struct private_auth_cfg_t {
! 116:
! 117: /**
! 118: * public functions
! 119: */
! 120: auth_cfg_t public;
! 121:
! 122: /**
! 123: * Array of entry_t
! 124: */
! 125: array_t *entries;
! 126: };
! 127:
! 128: typedef struct entry_t entry_t;
! 129:
! 130: struct entry_t {
! 131: /** rule type */
! 132: auth_rule_t type;
! 133: /** associated value */
! 134: void *value;
! 135: };
! 136:
! 137: /**
! 138: * enumerator for auth_cfg_t.create_enumerator()
! 139: */
! 140: typedef struct {
! 141: /** implements enumerator_t */
! 142: enumerator_t public;
! 143: /** inner enumerator from linked_list_t */
! 144: enumerator_t *inner;
! 145: /** current entry */
! 146: entry_t *current;
! 147: /** types we have already enumerated */
! 148: bool enumerated[AUTH_RULE_MAX];
! 149: } entry_enumerator_t;
! 150:
! 151: METHOD(enumerator_t, enumerate, bool,
! 152: entry_enumerator_t *this, va_list args)
! 153: {
! 154: auth_rule_t *type;
! 155: entry_t *entry;
! 156: void **value;
! 157:
! 158: VA_ARGS_VGET(args, type, value);
! 159:
! 160: while (this->inner->enumerate(this->inner, &entry))
! 161: {
! 162: if (!is_multi_value_rule(entry->type) && this->enumerated[entry->type])
! 163: {
! 164: continue;
! 165: }
! 166: this->enumerated[entry->type] = TRUE;
! 167: this->current = entry;
! 168: if (type)
! 169: {
! 170: *type = entry->type;
! 171: }
! 172: if (value)
! 173: {
! 174: *value = entry->value;
! 175: }
! 176: return TRUE;
! 177: }
! 178: return FALSE;
! 179: }
! 180:
! 181: METHOD(enumerator_t, entry_enumerator_destroy, void,
! 182: entry_enumerator_t *this)
! 183: {
! 184: this->inner->destroy(this->inner);
! 185: free(this);
! 186: }
! 187:
! 188: METHOD(auth_cfg_t, create_enumerator, enumerator_t*,
! 189: private_auth_cfg_t *this)
! 190: {
! 191: entry_enumerator_t *enumerator;
! 192:
! 193: INIT(enumerator,
! 194: .public = {
! 195: .enumerate = enumerator_enumerate_default,
! 196: .venumerate = _enumerate,
! 197: .destroy = _entry_enumerator_destroy,
! 198: },
! 199: .inner = array_create_enumerator(this->entries),
! 200: );
! 201: return &enumerator->public;
! 202: }
! 203:
! 204: /**
! 205: * Initialize an entry.
! 206: */
! 207: static void init_entry(entry_t *this, auth_rule_t type, va_list args)
! 208: {
! 209: this->type = type;
! 210: switch (type)
! 211: {
! 212: case AUTH_RULE_IDENTITY_LOOSE:
! 213: case AUTH_RULE_AUTH_CLASS:
! 214: case AUTH_RULE_EAP_TYPE:
! 215: case AUTH_RULE_EAP_VENDOR:
! 216: case AUTH_RULE_CRL_VALIDATION:
! 217: case AUTH_RULE_OCSP_VALIDATION:
! 218: case AUTH_RULE_RSA_STRENGTH:
! 219: case AUTH_RULE_ECDSA_STRENGTH:
! 220: case AUTH_RULE_BLISS_STRENGTH:
! 221: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 222: /* integer type */
! 223: this->value = (void*)(uintptr_t)va_arg(args, u_int);
! 224: break;
! 225: case AUTH_RULE_IDENTITY:
! 226: case AUTH_RULE_EAP_IDENTITY:
! 227: case AUTH_RULE_AAA_IDENTITY:
! 228: case AUTH_RULE_XAUTH_BACKEND:
! 229: case AUTH_RULE_XAUTH_IDENTITY:
! 230: case AUTH_RULE_GROUP:
! 231: case AUTH_RULE_CA_IDENTITY:
! 232: case AUTH_RULE_CA_CERT:
! 233: case AUTH_RULE_IM_CERT:
! 234: case AUTH_RULE_SUBJECT_CERT:
! 235: case AUTH_RULE_CERT_POLICY:
! 236: case AUTH_RULE_SIGNATURE_SCHEME:
! 237: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 238: case AUTH_HELPER_IM_CERT:
! 239: case AUTH_HELPER_SUBJECT_CERT:
! 240: case AUTH_HELPER_IM_HASH_URL:
! 241: case AUTH_HELPER_SUBJECT_HASH_URL:
! 242: case AUTH_HELPER_REVOCATION_CERT:
! 243: case AUTH_HELPER_AC_CERT:
! 244: /* pointer type */
! 245: this->value = va_arg(args, void*);
! 246: break;
! 247: case AUTH_RULE_MAX:
! 248: this->value = NULL;
! 249: break;
! 250: }
! 251: }
! 252:
! 253: /**
! 254: * Compare two entries for equality.
! 255: */
! 256: static bool entry_equals(entry_t *e1, entry_t *e2)
! 257: {
! 258: if (e1->type != e2->type)
! 259: {
! 260: return FALSE;
! 261: }
! 262: switch (e1->type)
! 263: {
! 264: case AUTH_RULE_IDENTITY_LOOSE:
! 265: case AUTH_RULE_AUTH_CLASS:
! 266: case AUTH_RULE_EAP_TYPE:
! 267: case AUTH_RULE_EAP_VENDOR:
! 268: case AUTH_RULE_CRL_VALIDATION:
! 269: case AUTH_RULE_OCSP_VALIDATION:
! 270: case AUTH_RULE_RSA_STRENGTH:
! 271: case AUTH_RULE_ECDSA_STRENGTH:
! 272: case AUTH_RULE_BLISS_STRENGTH:
! 273: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 274: {
! 275: return e1->value == e2->value;
! 276: }
! 277: case AUTH_RULE_CA_CERT:
! 278: case AUTH_RULE_IM_CERT:
! 279: case AUTH_RULE_SUBJECT_CERT:
! 280: case AUTH_HELPER_IM_CERT:
! 281: case AUTH_HELPER_SUBJECT_CERT:
! 282: case AUTH_HELPER_REVOCATION_CERT:
! 283: case AUTH_HELPER_AC_CERT:
! 284: {
! 285: certificate_t *c1, *c2;
! 286:
! 287: c1 = (certificate_t*)e1->value;
! 288: c2 = (certificate_t*)e2->value;
! 289:
! 290: return c1->equals(c1, c2);
! 291: }
! 292: case AUTH_RULE_IDENTITY:
! 293: case AUTH_RULE_CA_IDENTITY:
! 294: case AUTH_RULE_EAP_IDENTITY:
! 295: case AUTH_RULE_AAA_IDENTITY:
! 296: case AUTH_RULE_XAUTH_IDENTITY:
! 297: case AUTH_RULE_GROUP:
! 298: {
! 299: identification_t *id1, *id2;
! 300:
! 301: id1 = (identification_t*)e1->value;
! 302: id2 = (identification_t*)e2->value;
! 303:
! 304: return id1->equals(id1, id2);
! 305: }
! 306: case AUTH_RULE_SIGNATURE_SCHEME:
! 307: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 308: {
! 309: return signature_params_equal(e1->value, e2->value);
! 310: }
! 311: case AUTH_RULE_CERT_POLICY:
! 312: case AUTH_RULE_XAUTH_BACKEND:
! 313: case AUTH_HELPER_IM_HASH_URL:
! 314: case AUTH_HELPER_SUBJECT_HASH_URL:
! 315: {
! 316: return streq(e1->value, e2->value);
! 317: }
! 318: case AUTH_RULE_MAX:
! 319: break;
! 320: }
! 321: return FALSE;
! 322: }
! 323:
! 324: /**
! 325: * Destroy the value associated with an entry
! 326: */
! 327: static void destroy_entry_value(entry_t *entry)
! 328: {
! 329: switch (entry->type)
! 330: {
! 331: case AUTH_RULE_IDENTITY:
! 332: case AUTH_RULE_CA_IDENTITY:
! 333: case AUTH_RULE_EAP_IDENTITY:
! 334: case AUTH_RULE_AAA_IDENTITY:
! 335: case AUTH_RULE_GROUP:
! 336: case AUTH_RULE_XAUTH_IDENTITY:
! 337: {
! 338: identification_t *id = (identification_t*)entry->value;
! 339: id->destroy(id);
! 340: break;
! 341: }
! 342: case AUTH_RULE_CA_CERT:
! 343: case AUTH_RULE_IM_CERT:
! 344: case AUTH_RULE_SUBJECT_CERT:
! 345: case AUTH_HELPER_IM_CERT:
! 346: case AUTH_HELPER_SUBJECT_CERT:
! 347: case AUTH_HELPER_REVOCATION_CERT:
! 348: case AUTH_HELPER_AC_CERT:
! 349: {
! 350: certificate_t *cert = (certificate_t*)entry->value;
! 351: cert->destroy(cert);
! 352: break;
! 353: }
! 354: case AUTH_RULE_CERT_POLICY:
! 355: case AUTH_RULE_XAUTH_BACKEND:
! 356: case AUTH_HELPER_IM_HASH_URL:
! 357: case AUTH_HELPER_SUBJECT_HASH_URL:
! 358: {
! 359: free(entry->value);
! 360: break;
! 361: }
! 362: case AUTH_RULE_SIGNATURE_SCHEME:
! 363: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 364: {
! 365: signature_params_destroy(entry->value);
! 366: break;
! 367: }
! 368: case AUTH_RULE_IDENTITY_LOOSE:
! 369: case AUTH_RULE_AUTH_CLASS:
! 370: case AUTH_RULE_EAP_TYPE:
! 371: case AUTH_RULE_EAP_VENDOR:
! 372: case AUTH_RULE_CRL_VALIDATION:
! 373: case AUTH_RULE_OCSP_VALIDATION:
! 374: case AUTH_RULE_RSA_STRENGTH:
! 375: case AUTH_RULE_ECDSA_STRENGTH:
! 376: case AUTH_RULE_BLISS_STRENGTH:
! 377: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 378: case AUTH_RULE_MAX:
! 379: break;
! 380: }
! 381: }
! 382:
! 383: /**
! 384: * Implementation of auth_cfg_t.replace.
! 385: */
! 386: static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
! 387: auth_rule_t type, ...)
! 388: {
! 389: if (enumerator->current)
! 390: {
! 391: entry_t *entry;
! 392: va_list args;
! 393:
! 394: va_start(args, type);
! 395: entry = enumerator->current;
! 396: destroy_entry_value(entry);
! 397: entry->type = type;
! 398: switch (type)
! 399: {
! 400: case AUTH_RULE_IDENTITY_LOOSE:
! 401: case AUTH_RULE_AUTH_CLASS:
! 402: case AUTH_RULE_EAP_TYPE:
! 403: case AUTH_RULE_EAP_VENDOR:
! 404: case AUTH_RULE_CRL_VALIDATION:
! 405: case AUTH_RULE_OCSP_VALIDATION:
! 406: case AUTH_RULE_RSA_STRENGTH:
! 407: case AUTH_RULE_ECDSA_STRENGTH:
! 408: case AUTH_RULE_BLISS_STRENGTH:
! 409: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 410: /* integer type */
! 411: entry->value = (void*)(uintptr_t)va_arg(args, u_int);
! 412: break;
! 413: case AUTH_RULE_IDENTITY:
! 414: case AUTH_RULE_CA_IDENTITY:
! 415: case AUTH_RULE_EAP_IDENTITY:
! 416: case AUTH_RULE_AAA_IDENTITY:
! 417: case AUTH_RULE_XAUTH_BACKEND:
! 418: case AUTH_RULE_XAUTH_IDENTITY:
! 419: case AUTH_RULE_GROUP:
! 420: case AUTH_RULE_CA_CERT:
! 421: case AUTH_RULE_IM_CERT:
! 422: case AUTH_RULE_SUBJECT_CERT:
! 423: case AUTH_RULE_CERT_POLICY:
! 424: case AUTH_RULE_SIGNATURE_SCHEME:
! 425: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 426: case AUTH_HELPER_IM_CERT:
! 427: case AUTH_HELPER_SUBJECT_CERT:
! 428: case AUTH_HELPER_IM_HASH_URL:
! 429: case AUTH_HELPER_SUBJECT_HASH_URL:
! 430: case AUTH_HELPER_REVOCATION_CERT:
! 431: case AUTH_HELPER_AC_CERT:
! 432: /* pointer type */
! 433: entry->value = va_arg(args, void*);
! 434: break;
! 435: case AUTH_RULE_MAX:
! 436: entry->value = NULL;
! 437: break;
! 438: }
! 439: va_end(args);
! 440: }
! 441: }
! 442:
! 443: METHOD(auth_cfg_t, get, void*,
! 444: private_auth_cfg_t *this, auth_rule_t type)
! 445: {
! 446: enumerator_t *enumerator;
! 447: void *current_value, *best_value = NULL;
! 448: auth_rule_t current_type;
! 449: bool found = FALSE;
! 450:
! 451: enumerator = create_enumerator(this);
! 452: while (enumerator->enumerate(enumerator, ¤t_type, ¤t_value))
! 453: {
! 454: if (type == current_type)
! 455: {
! 456: if (type == AUTH_RULE_CRL_VALIDATION ||
! 457: type == AUTH_RULE_OCSP_VALIDATION)
! 458: { /* for CRL/OCSP validation, always get() the highest value */
! 459: if (!found || current_value > best_value)
! 460: {
! 461: best_value = current_value;
! 462: }
! 463: found = TRUE;
! 464: continue;
! 465: }
! 466: best_value = current_value;
! 467: found = TRUE;
! 468: break;
! 469: }
! 470: }
! 471: enumerator->destroy(enumerator);
! 472: if (found)
! 473: {
! 474: return best_value;
! 475: }
! 476: switch (type)
! 477: {
! 478: /* use some sane defaults if we don't find an entry */
! 479: case AUTH_RULE_AUTH_CLASS:
! 480: return (void*)AUTH_CLASS_ANY;
! 481: case AUTH_RULE_EAP_TYPE:
! 482: return (void*)EAP_NAK;
! 483: case AUTH_RULE_EAP_VENDOR:
! 484: case AUTH_RULE_RSA_STRENGTH:
! 485: case AUTH_RULE_ECDSA_STRENGTH:
! 486: case AUTH_RULE_BLISS_STRENGTH:
! 487: return (void*)0;
! 488: case AUTH_RULE_CRL_VALIDATION:
! 489: case AUTH_RULE_OCSP_VALIDATION:
! 490: return (void*)VALIDATION_FAILED;
! 491: case AUTH_RULE_IDENTITY_LOOSE:
! 492: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 493: return (void*)FALSE;
! 494: case AUTH_RULE_IDENTITY:
! 495: case AUTH_RULE_CA_IDENTITY:
! 496: case AUTH_RULE_EAP_IDENTITY:
! 497: case AUTH_RULE_AAA_IDENTITY:
! 498: case AUTH_RULE_XAUTH_BACKEND:
! 499: case AUTH_RULE_XAUTH_IDENTITY:
! 500: case AUTH_RULE_GROUP:
! 501: case AUTH_RULE_CA_CERT:
! 502: case AUTH_RULE_IM_CERT:
! 503: case AUTH_RULE_SUBJECT_CERT:
! 504: case AUTH_RULE_CERT_POLICY:
! 505: case AUTH_RULE_SIGNATURE_SCHEME:
! 506: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 507: case AUTH_HELPER_IM_CERT:
! 508: case AUTH_HELPER_SUBJECT_CERT:
! 509: case AUTH_HELPER_IM_HASH_URL:
! 510: case AUTH_HELPER_SUBJECT_HASH_URL:
! 511: case AUTH_HELPER_REVOCATION_CERT:
! 512: case AUTH_HELPER_AC_CERT:
! 513: case AUTH_RULE_MAX:
! 514: break;
! 515: }
! 516: return NULL;
! 517: }
! 518:
! 519: /**
! 520: * Implementation of auth_cfg_t.add.
! 521: */
! 522: static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
! 523: {
! 524: entry_t entry;
! 525: va_list args;
! 526:
! 527: va_start(args, type);
! 528: init_entry(&entry, type, args);
! 529: va_end(args);
! 530:
! 531: if (is_multi_value_rule(type))
! 532: { /* insert rules that may occur multiple times at the end */
! 533: array_insert(this->entries, ARRAY_TAIL, &entry);
! 534: }
! 535: else
! 536: { /* insert rules we expect only once at the front (get() will return
! 537: * the latest value) */
! 538: array_insert(this->entries, ARRAY_HEAD, &entry);
! 539: }
! 540: }
! 541:
! 542: /**
! 543: * Create a constraint for RSA/PSS signatures
! 544: */
! 545: static signature_params_t *create_rsa_pss_constraint(char *token)
! 546: {
! 547: signature_params_t *params = NULL;
! 548: hash_algorithm_t hash;
! 549:
! 550: if (enum_from_name(hash_algorithm_short_names, token, &hash))
! 551: {
! 552: rsa_pss_params_t pss = {
! 553: .hash = hash,
! 554: .mgf1_hash = hash,
! 555: .salt_len = RSA_PSS_SALT_LEN_DEFAULT,
! 556: };
! 557: signature_params_t pss_params = {
! 558: .scheme = SIGN_RSA_EMSA_PSS,
! 559: .params = &pss,
! 560: };
! 561: rsa_pss_params_set_salt_len(&pss, 0);
! 562: params = signature_params_clone(&pss_params);
! 563: }
! 564: return params;
! 565: }
! 566:
! 567: METHOD(auth_cfg_t, add_pubkey_constraints, void,
! 568: private_auth_cfg_t *this, char* constraints, bool ike)
! 569: {
! 570: enumerator_t *enumerator;
! 571: bool ike_added = FALSE, rsa_pss;
! 572: key_type_t expected_type = -1;
! 573: auth_rule_t expected_strength = AUTH_RULE_MAX;
! 574: signature_params_t *params;
! 575: int strength;
! 576: char *token, *key_token = NULL;
! 577: auth_rule_t type;
! 578: void *value;
! 579:
! 580: rsa_pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE,
! 581: lib->ns);
! 582:
! 583: enumerator = enumerator_create_token(constraints, "-", "");
! 584: while (enumerator->enumerate(enumerator, &token))
! 585: {
! 586: bool found = FALSE;
! 587: int i;
! 588: struct {
! 589: char *name;
! 590: signature_scheme_t scheme;
! 591: key_type_t key;
! 592: } schemes[] = {
! 593: { "md5", SIGN_RSA_EMSA_PKCS1_MD5, KEY_RSA, },
! 594: { "sha1", SIGN_RSA_EMSA_PKCS1_SHA1, KEY_RSA, },
! 595: { "sha224", SIGN_RSA_EMSA_PKCS1_SHA2_224, KEY_RSA, },
! 596: { "sha256", SIGN_RSA_EMSA_PKCS1_SHA2_256, KEY_RSA, },
! 597: { "sha384", SIGN_RSA_EMSA_PKCS1_SHA2_384, KEY_RSA, },
! 598: { "sha512", SIGN_RSA_EMSA_PKCS1_SHA2_512, KEY_RSA, },
! 599: { "sha1", SIGN_ECDSA_WITH_SHA1_DER, KEY_ECDSA, },
! 600: { "sha256", SIGN_ECDSA_WITH_SHA256_DER, KEY_ECDSA, },
! 601: { "sha384", SIGN_ECDSA_WITH_SHA384_DER, KEY_ECDSA, },
! 602: { "sha512", SIGN_ECDSA_WITH_SHA512_DER, KEY_ECDSA, },
! 603: { "sha256", SIGN_ECDSA_256, KEY_ECDSA, },
! 604: { "sha384", SIGN_ECDSA_384, KEY_ECDSA, },
! 605: { "sha512", SIGN_ECDSA_521, KEY_ECDSA, },
! 606: { "sha256", SIGN_BLISS_WITH_SHA2_256, KEY_BLISS, },
! 607: { "sha384", SIGN_BLISS_WITH_SHA2_384, KEY_BLISS, },
! 608: { "sha512", SIGN_BLISS_WITH_SHA2_512, KEY_BLISS, },
! 609: { "identity", SIGN_ED25519, KEY_ED25519, },
! 610: { "identity", SIGN_ED448, KEY_ED448, },
! 611: };
! 612:
! 613: if (expected_strength != AUTH_RULE_MAX)
! 614: { /* expecting a key strength token */
! 615: strength = atoi(token);
! 616: if (strength)
! 617: {
! 618: add(this, expected_strength, (uintptr_t)strength);
! 619: }
! 620: expected_strength = AUTH_RULE_MAX;
! 621: if (strength)
! 622: {
! 623: continue;
! 624: }
! 625: }
! 626: if (streq(token, "rsa") || streq(token, "ike:rsa"))
! 627: {
! 628: key_token = token;
! 629: expected_type = KEY_RSA;
! 630: expected_strength = AUTH_RULE_RSA_STRENGTH;
! 631: continue;
! 632: }
! 633: if (streq(token, "rsa/pss") || streq(token, "ike:rsa/pss"))
! 634: {
! 635: key_token = token;
! 636: expected_type = KEY_RSA;
! 637: expected_strength = AUTH_RULE_RSA_STRENGTH;
! 638: continue;
! 639: }
! 640: if (streq(token, "ecdsa") || streq(token, "ike:ecdsa"))
! 641: {
! 642: key_token = token;
! 643: expected_type = KEY_ECDSA;
! 644: expected_strength = AUTH_RULE_ECDSA_STRENGTH;
! 645: continue;
! 646: }
! 647: if (streq(token, "ed25519") || streq(token, "ike:ed25519"))
! 648: {
! 649: key_token = token;
! 650: expected_type = KEY_ED25519;
! 651: continue;
! 652: }
! 653: if (streq(token, "ed448") || streq(token, "ike:ed448"))
! 654: {
! 655: key_token = token;
! 656: expected_type = KEY_ED448;
! 657: continue;
! 658: }
! 659: if (streq(token, "bliss") || streq(token, "ike:bliss"))
! 660: {
! 661: key_token = token;
! 662: expected_type = KEY_BLISS;
! 663: expected_strength = AUTH_RULE_BLISS_STRENGTH;
! 664: continue;
! 665: }
! 666: if (streq(token, "pubkey") || streq(token, "ike:pubkey"))
! 667: {
! 668: key_token = token;
! 669: expected_type = KEY_ANY;
! 670: continue;
! 671: }
! 672: if (key_token && strpfx(key_token, "ike:") && !ike)
! 673: {
! 674: continue;
! 675: }
! 676:
! 677: if (key_token && streq(key_token + strlen(key_token) - 3, "pss"))
! 678: {
! 679: params = create_rsa_pss_constraint(token);
! 680: if (params)
! 681: {
! 682: if (strpfx(key_token, "ike:"))
! 683: {
! 684: add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, params);
! 685: ike_added = TRUE;
! 686: }
! 687: else
! 688: {
! 689: add(this, AUTH_RULE_SIGNATURE_SCHEME, params);
! 690: }
! 691: found = TRUE;
! 692: }
! 693: }
! 694: else
! 695: {
! 696: if (rsa_pss)
! 697: {
! 698: if (expected_type == KEY_ANY ||
! 699: expected_type == KEY_RSA)
! 700: {
! 701: params = create_rsa_pss_constraint(token);
! 702: if (params)
! 703: {
! 704: if (strpfx(key_token, "ike:"))
! 705: {
! 706: add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, params);
! 707: ike_added = TRUE;
! 708: }
! 709: else
! 710: {
! 711: add(this, AUTH_RULE_SIGNATURE_SCHEME, params);
! 712: }
! 713: found = TRUE;
! 714: }
! 715: }
! 716: }
! 717: for (i = 0; i < countof(schemes); i++)
! 718: {
! 719: if (streq(schemes[i].name, token))
! 720: {
! 721: if (expected_type == KEY_ANY ||
! 722: expected_type == schemes[i].key)
! 723: {
! 724: INIT(params,
! 725: .scheme = schemes[i].scheme,
! 726: );
! 727: if (strpfx(key_token, "ike:"))
! 728: {
! 729: add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, params);
! 730: ike_added = TRUE;
! 731: }
! 732: else
! 733: {
! 734: add(this, AUTH_RULE_SIGNATURE_SCHEME, params);
! 735: }
! 736: }
! 737: found = TRUE;
! 738: }
! 739: }
! 740: }
! 741: if (!found)
! 742: {
! 743: DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token);
! 744: }
! 745: }
! 746: enumerator->destroy(enumerator);
! 747:
! 748: /* if no explicit IKE signature constraints were added we add them for all
! 749: * configured signature constraints */
! 750: if (ike && !ike_added &&
! 751: lib->settings->get_bool(lib->settings,
! 752: "%s.signature_authentication_constraints", TRUE,
! 753: lib->ns))
! 754: {
! 755: enumerator = create_enumerator(this);
! 756: while (enumerator->enumerate(enumerator, &type, &value))
! 757: {
! 758: if (type == AUTH_RULE_SIGNATURE_SCHEME)
! 759: {
! 760: add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME,
! 761: signature_params_clone(value));
! 762: }
! 763: }
! 764: enumerator->destroy(enumerator);
! 765: }
! 766: }
! 767:
! 768: /**
! 769: * Check if signature schemes of a specific type are compliant
! 770: */
! 771: static bool complies_scheme(private_auth_cfg_t *this, auth_cfg_t *constraints,
! 772: auth_rule_t type, bool log_error)
! 773: {
! 774: enumerator_t *e1, *e2;
! 775: auth_rule_t t1, t2;
! 776: signature_params_t *params, *constraint;
! 777: bool success = TRUE;
! 778:
! 779: e2 = create_enumerator(this);
! 780: while (e2->enumerate(e2, &t2, ¶ms))
! 781: {
! 782: if (t2 == type)
! 783: {
! 784: success = FALSE;
! 785: e1 = constraints->create_enumerator(constraints);
! 786: while (e1->enumerate(e1, &t1, &constraint))
! 787: {
! 788: if (t1 == type &&
! 789: signature_params_comply(constraint, params))
! 790: {
! 791: success = TRUE;
! 792: break;
! 793: }
! 794: }
! 795: e1->destroy(e1);
! 796: if (!success)
! 797: {
! 798: if (log_error)
! 799: {
! 800: DBG1(DBG_CFG, "%s signature scheme %N not acceptable",
! 801: AUTH_RULE_SIGNATURE_SCHEME == type ? "X.509" : "IKE",
! 802: signature_scheme_names, params->scheme);
! 803: }
! 804: break;
! 805: }
! 806: }
! 807: }
! 808: e2->destroy(e2);
! 809: return success;
! 810: }
! 811:
! 812: METHOD(auth_cfg_t, complies, bool,
! 813: private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error)
! 814: {
! 815: enumerator_t *e1, *e2;
! 816: bool success = TRUE, group_match = FALSE;
! 817: bool ca_match = FALSE, cert_match = FALSE;
! 818: identification_t *require_group = NULL, *require_ca = NULL;
! 819: certificate_t *require_cert = NULL;
! 820: signature_params_t *ike_scheme = NULL, *scheme = NULL;
! 821: u_int strength = 0;
! 822: auth_rule_t t1, t2;
! 823: char *key_type;
! 824: void *value;
! 825:
! 826: e1 = constraints->create_enumerator(constraints);
! 827: while (e1->enumerate(e1, &t1, &value))
! 828: {
! 829: switch (t1)
! 830: {
! 831: case AUTH_RULE_CA_CERT:
! 832: case AUTH_RULE_IM_CERT:
! 833: {
! 834: certificate_t *cert, *ca;
! 835:
! 836: /* for CA certs, a match of a single cert is sufficient */
! 837: ca = (certificate_t*)value;
! 838: require_ca = ca->get_subject(ca);
! 839:
! 840: e2 = create_enumerator(this);
! 841: while (e2->enumerate(e2, &t2, &cert))
! 842: {
! 843: if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
! 844: cert->equals(cert, ca))
! 845: {
! 846: ca_match = TRUE;
! 847: }
! 848: }
! 849: e2->destroy(e2);
! 850: break;
! 851: }
! 852: case AUTH_RULE_CA_IDENTITY:
! 853: {
! 854: certificate_t *cert;
! 855:
! 856: require_ca = (identification_t*)value;
! 857:
! 858: e2 = create_enumerator(this);
! 859: while (e2->enumerate(e2, &t2, &cert))
! 860: {
! 861: if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
! 862: cert->has_subject(cert, require_ca))
! 863: {
! 864: ca_match = TRUE;
! 865: }
! 866: }
! 867: e2->destroy(e2);
! 868: break;
! 869: }
! 870: case AUTH_RULE_SUBJECT_CERT:
! 871: {
! 872: certificate_t *cert;
! 873:
! 874: /* for certs, a match of a single cert is sufficient */
! 875: require_cert = (certificate_t*)value;
! 876:
! 877: e2 = create_enumerator(this);
! 878: while (e2->enumerate(e2, &t2, &cert))
! 879: {
! 880: if (t2 == AUTH_RULE_SUBJECT_CERT &&
! 881: cert->equals(cert, require_cert))
! 882: {
! 883: cert_match = TRUE;
! 884: }
! 885: }
! 886: e2->destroy(e2);
! 887: break;
! 888: }
! 889: case AUTH_RULE_CRL_VALIDATION:
! 890: case AUTH_RULE_OCSP_VALIDATION:
! 891: {
! 892: uintptr_t validated;
! 893:
! 894: if (get(this, AUTH_RULE_CERT_VALIDATION_SUSPENDED))
! 895: { /* skip validation, may happen later */
! 896: break;
! 897: }
! 898:
! 899: e2 = create_enumerator(this);
! 900: while (e2->enumerate(e2, &t2, &validated))
! 901: {
! 902: if (t2 == t1)
! 903: {
! 904: switch ((uintptr_t)value)
! 905: {
! 906: case VALIDATION_FAILED:
! 907: /* no constraint */
! 908: break;
! 909: case VALIDATION_SKIPPED:
! 910: if (validated == VALIDATION_SKIPPED)
! 911: {
! 912: break;
! 913: }
! 914: /* FALL */
! 915: case VALIDATION_GOOD:
! 916: if (validated == VALIDATION_GOOD)
! 917: {
! 918: break;
! 919: }
! 920: /* FALL */
! 921: default:
! 922: success = FALSE;
! 923: if (log_error)
! 924: {
! 925: DBG1(DBG_CFG, "constraint check failed: "
! 926: "%N is %N, but requires at least %N",
! 927: auth_rule_names, t1,
! 928: cert_validation_names, validated,
! 929: cert_validation_names, (uintptr_t)value);
! 930: }
! 931: break;
! 932: }
! 933: }
! 934: }
! 935: e2->destroy(e2);
! 936: break;
! 937: }
! 938: case AUTH_RULE_IDENTITY:
! 939: case AUTH_RULE_EAP_IDENTITY:
! 940: case AUTH_RULE_AAA_IDENTITY:
! 941: case AUTH_RULE_XAUTH_IDENTITY:
! 942: {
! 943: identification_t *id1, *id2;
! 944:
! 945: id1 = (identification_t*)value;
! 946: id2 = get(this, t1);
! 947: if (!id2 || !id2->matches(id2, id1))
! 948: {
! 949: if (t1 == AUTH_RULE_IDENTITY &&
! 950: constraints->get(constraints, AUTH_RULE_IDENTITY_LOOSE))
! 951: { /* also verify identity against subjectAltNames */
! 952: certificate_t *cert;
! 953:
! 954: cert = get(this, AUTH_RULE_SUBJECT_CERT);
! 955: if (cert && cert->has_subject(cert, id1))
! 956: {
! 957: break;
! 958: }
! 959: }
! 960: success = FALSE;
! 961: if (log_error)
! 962: {
! 963: DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
! 964: " required ", t1 == AUTH_RULE_IDENTITY ? "" :
! 965: "EAP ", id1);
! 966: }
! 967: }
! 968: break;
! 969: }
! 970: case AUTH_RULE_AUTH_CLASS:
! 971: {
! 972: if ((uintptr_t)value != AUTH_CLASS_ANY &&
! 973: (uintptr_t)value != (uintptr_t)get(this, t1))
! 974: {
! 975: success = FALSE;
! 976: if (log_error)
! 977: {
! 978: DBG1(DBG_CFG, "constraint requires %N authentication, "
! 979: "but %N was used", auth_class_names, (uintptr_t)value,
! 980: auth_class_names, (uintptr_t)get(this, t1));
! 981: }
! 982: }
! 983: break;
! 984: }
! 985: case AUTH_RULE_EAP_TYPE:
! 986: {
! 987: if ((uintptr_t)value != (uintptr_t)get(this, t1) &&
! 988: (uintptr_t)value != EAP_DYNAMIC &&
! 989: (uintptr_t)value != EAP_RADIUS)
! 990: {
! 991: success = FALSE;
! 992: if (log_error)
! 993: {
! 994: DBG1(DBG_CFG, "constraint requires %N, "
! 995: "but %N was used", eap_type_names, (uintptr_t)value,
! 996: eap_type_names, (uintptr_t)get(this, t1));
! 997: }
! 998: }
! 999: break;
! 1000: }
! 1001: case AUTH_RULE_EAP_VENDOR:
! 1002: {
! 1003: if ((uintptr_t)value != (uintptr_t)get(this, t1))
! 1004: {
! 1005: success = FALSE;
! 1006: if (log_error)
! 1007: {
! 1008: DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
! 1009: "but %d was used", (uintptr_t)value,
! 1010: (uintptr_t)get(this, t1));
! 1011: }
! 1012: }
! 1013: break;
! 1014: }
! 1015: case AUTH_RULE_GROUP:
! 1016: {
! 1017: identification_t *group;
! 1018:
! 1019: /* for groups, a match of a single group is sufficient */
! 1020: require_group = (identification_t*)value;
! 1021: e2 = create_enumerator(this);
! 1022: while (e2->enumerate(e2, &t2, &group))
! 1023: {
! 1024: if (t2 == AUTH_RULE_GROUP &&
! 1025: group->matches(group, require_group))
! 1026: {
! 1027: group_match = TRUE;
! 1028: }
! 1029: }
! 1030: e2->destroy(e2);
! 1031: break;
! 1032: }
! 1033: case AUTH_RULE_RSA_STRENGTH:
! 1034: case AUTH_RULE_ECDSA_STRENGTH:
! 1035: case AUTH_RULE_BLISS_STRENGTH:
! 1036: {
! 1037: strength = (uintptr_t)value;
! 1038: break;
! 1039: }
! 1040: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 1041: {
! 1042: ike_scheme = value;
! 1043: break;
! 1044: }
! 1045: case AUTH_RULE_SIGNATURE_SCHEME:
! 1046: {
! 1047: scheme = value;
! 1048: break;
! 1049: }
! 1050: case AUTH_RULE_CERT_POLICY:
! 1051: {
! 1052: char *oid1, *oid2;
! 1053:
! 1054: oid1 = (char*)value;
! 1055: success = FALSE;
! 1056: e2 = create_enumerator(this);
! 1057: while (e2->enumerate(e2, &t2, &oid2))
! 1058: {
! 1059: if (t2 == t1 && streq(oid1, oid2))
! 1060: {
! 1061: success = TRUE;
! 1062: break;
! 1063: }
! 1064: }
! 1065: e2->destroy(e2);
! 1066: if (!success && log_error)
! 1067: {
! 1068: DBG1(DBG_CFG, "constraint requires cert policy %s", oid1);
! 1069: }
! 1070: break;
! 1071: }
! 1072: case AUTH_RULE_IDENTITY_LOOSE:
! 1073: /* just an indication when verifying AUTH_RULE_IDENTITY */
! 1074: case AUTH_RULE_XAUTH_BACKEND:
! 1075: /* not enforced, just a hint for local authentication */
! 1076: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 1077: /* not a constraint */
! 1078: case AUTH_HELPER_IM_CERT:
! 1079: case AUTH_HELPER_SUBJECT_CERT:
! 1080: case AUTH_HELPER_IM_HASH_URL:
! 1081: case AUTH_HELPER_SUBJECT_HASH_URL:
! 1082: case AUTH_HELPER_REVOCATION_CERT:
! 1083: case AUTH_HELPER_AC_CERT:
! 1084: case AUTH_RULE_MAX:
! 1085: /* skip helpers */
! 1086: continue;
! 1087: }
! 1088: if (!success)
! 1089: {
! 1090: break;
! 1091: }
! 1092: }
! 1093: e1->destroy(e1);
! 1094:
! 1095: /* Check if we have a matching constraint (or none at all) for used
! 1096: * signature schemes. */
! 1097: if (success && scheme)
! 1098: {
! 1099: success = complies_scheme(this, constraints,
! 1100: AUTH_RULE_SIGNATURE_SCHEME, log_error);
! 1101: }
! 1102: if (success && ike_scheme)
! 1103: {
! 1104: success = complies_scheme(this, constraints,
! 1105: AUTH_RULE_IKE_SIGNATURE_SCHEME, log_error);
! 1106: }
! 1107:
! 1108: /* Check if we have a matching constraint (or none at all) for used
! 1109: * public key strength */
! 1110: if (success && strength)
! 1111: {
! 1112: e2 = create_enumerator(this);
! 1113: while (e2->enumerate(e2, &t2, &strength))
! 1114: {
! 1115: switch (t2)
! 1116: {
! 1117: default:
! 1118: continue;
! 1119: case AUTH_RULE_RSA_STRENGTH:
! 1120: key_type = "RSA";
! 1121: break;
! 1122: case AUTH_RULE_ECDSA_STRENGTH:
! 1123: key_type = "ECDSA";
! 1124: break;
! 1125: case AUTH_RULE_BLISS_STRENGTH:
! 1126: key_type = "BLISS";
! 1127: break;
! 1128: }
! 1129: success = FALSE;
! 1130: e1 = constraints->create_enumerator(constraints);
! 1131: while (e1->enumerate(e1, &t1, &value))
! 1132: {
! 1133: if (t1 == t2 && (uintptr_t)value <= strength)
! 1134: {
! 1135: success = TRUE;
! 1136: break;
! 1137: }
! 1138: }
! 1139: e1->destroy(e1);
! 1140: if (!success)
! 1141: {
! 1142: if (log_error)
! 1143: {
! 1144: DBG1(DBG_CFG, "%s-%d signatures not acceptable",
! 1145: key_type, strength);
! 1146: }
! 1147: break;
! 1148: }
! 1149: }
! 1150: e2->destroy(e2);
! 1151: }
! 1152:
! 1153: if (require_group && !group_match)
! 1154: {
! 1155: if (log_error)
! 1156: {
! 1157: DBG1(DBG_CFG, "constraint check failed: group membership to "
! 1158: "'%Y' required", require_group);
! 1159: }
! 1160: return FALSE;
! 1161: }
! 1162: if (require_ca && !ca_match)
! 1163: {
! 1164: if (log_error)
! 1165: {
! 1166: DBG1(DBG_CFG, "constraint check failed: peer not "
! 1167: "authenticated by CA '%Y'", require_ca);
! 1168: }
! 1169: return FALSE;
! 1170: }
! 1171: if (require_cert && !cert_match)
! 1172: {
! 1173: if (log_error)
! 1174: {
! 1175: DBG1(DBG_CFG, "constraint check failed: peer not "
! 1176: "authenticated with peer cert '%Y'",
! 1177: require_cert->get_subject(require_cert));
! 1178: }
! 1179: return FALSE;
! 1180: }
! 1181: return success;
! 1182: }
! 1183:
! 1184: /**
! 1185: * Implementation of auth_cfg_t.merge.
! 1186: */
! 1187: static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
! 1188: {
! 1189: if (!other)
! 1190: { /* nothing to merge */
! 1191: return;
! 1192: }
! 1193: if (copy)
! 1194: {
! 1195: enumerator_t *enumerator;
! 1196: auth_rule_t type;
! 1197: void *value;
! 1198:
! 1199: /* this enumerator skips duplicates for rules we expect only once */
! 1200: enumerator = create_enumerator(other);
! 1201: while (enumerator->enumerate(enumerator, &type, &value))
! 1202: {
! 1203: switch (type)
! 1204: {
! 1205: case AUTH_RULE_CA_CERT:
! 1206: case AUTH_RULE_IM_CERT:
! 1207: case AUTH_RULE_SUBJECT_CERT:
! 1208: case AUTH_HELPER_IM_CERT:
! 1209: case AUTH_HELPER_SUBJECT_CERT:
! 1210: case AUTH_HELPER_REVOCATION_CERT:
! 1211: case AUTH_HELPER_AC_CERT:
! 1212: {
! 1213: certificate_t *cert = (certificate_t*)value;
! 1214:
! 1215: add(this, type, cert->get_ref(cert));
! 1216: break;
! 1217: }
! 1218: case AUTH_RULE_IDENTITY_LOOSE:
! 1219: case AUTH_RULE_CRL_VALIDATION:
! 1220: case AUTH_RULE_OCSP_VALIDATION:
! 1221: case AUTH_RULE_AUTH_CLASS:
! 1222: case AUTH_RULE_EAP_TYPE:
! 1223: case AUTH_RULE_EAP_VENDOR:
! 1224: case AUTH_RULE_RSA_STRENGTH:
! 1225: case AUTH_RULE_ECDSA_STRENGTH:
! 1226: case AUTH_RULE_BLISS_STRENGTH:
! 1227: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 1228: {
! 1229: add(this, type, (uintptr_t)value);
! 1230: break;
! 1231: }
! 1232: case AUTH_RULE_IDENTITY:
! 1233: case AUTH_RULE_CA_IDENTITY:
! 1234: case AUTH_RULE_EAP_IDENTITY:
! 1235: case AUTH_RULE_AAA_IDENTITY:
! 1236: case AUTH_RULE_GROUP:
! 1237: case AUTH_RULE_XAUTH_IDENTITY:
! 1238: {
! 1239: identification_t *id = (identification_t*)value;
! 1240:
! 1241: add(this, type, id->clone(id));
! 1242: break;
! 1243: }
! 1244: case AUTH_RULE_SIGNATURE_SCHEME:
! 1245: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 1246: {
! 1247: add(this, type, signature_params_clone(value));
! 1248: break;
! 1249: }
! 1250: case AUTH_RULE_XAUTH_BACKEND:
! 1251: case AUTH_RULE_CERT_POLICY:
! 1252: case AUTH_HELPER_IM_HASH_URL:
! 1253: case AUTH_HELPER_SUBJECT_HASH_URL:
! 1254: {
! 1255: add(this, type, strdup((char*)value));
! 1256: break;
! 1257: }
! 1258: case AUTH_RULE_MAX:
! 1259: break;
! 1260: }
! 1261: }
! 1262: enumerator->destroy(enumerator);
! 1263: }
! 1264: else
! 1265: {
! 1266: entry_t entry;
! 1267:
! 1268: while (array_remove(other->entries, ARRAY_TAIL, &entry))
! 1269: { /* keep order but prefer new values (esp. for single valued ones) */
! 1270: array_insert(this->entries, ARRAY_HEAD, &entry);
! 1271: }
! 1272: array_compress(other->entries);
! 1273: }
! 1274: }
! 1275:
! 1276: /**
! 1277: * Compare two auth_cfg_t objects for equality.
! 1278: */
! 1279: static bool auth_cfg_equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
! 1280: {
! 1281: enumerator_t *e1, *e2;
! 1282: entry_t *i1, *i2;
! 1283: bool equal = TRUE, found;
! 1284:
! 1285: /* the rule count does not have to be equal for the two, as we only compare
! 1286: * the first value found for some rules */
! 1287: e1 = array_create_enumerator(this->entries);
! 1288: while (e1->enumerate(e1, &i1))
! 1289: {
! 1290: found = FALSE;
! 1291:
! 1292: e2 = array_create_enumerator(other->entries);
! 1293: while (e2->enumerate(e2, &i2))
! 1294: {
! 1295: if (entry_equals(i1, i2))
! 1296: {
! 1297: found = TRUE;
! 1298: break;
! 1299: }
! 1300: else if (i1->type == i2->type && !is_multi_value_rule(i1->type))
! 1301: { /* we continue our search, only for multi valued rules */
! 1302: break;
! 1303: }
! 1304: }
! 1305: e2->destroy(e2);
! 1306: if (!found)
! 1307: {
! 1308: equal = FALSE;
! 1309: break;
! 1310: }
! 1311: }
! 1312: e1->destroy(e1);
! 1313: return equal;
! 1314: }
! 1315:
! 1316: /**
! 1317: * Implementation of auth_cfg_t.equals.
! 1318: */
! 1319: static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
! 1320: {
! 1321: if (auth_cfg_equals(this, other))
! 1322: {
! 1323: /* as 'other' might contain entries that 'this' doesn't we also check
! 1324: * the other way around */
! 1325: return auth_cfg_equals(other, this);
! 1326: }
! 1327: return FALSE;
! 1328: }
! 1329:
! 1330: METHOD(auth_cfg_t, purge, void,
! 1331: private_auth_cfg_t *this, bool keep_ca)
! 1332: {
! 1333: enumerator_t *enumerator;
! 1334: entry_t *entry;
! 1335:
! 1336: enumerator = array_create_enumerator(this->entries);
! 1337: while (enumerator->enumerate(enumerator, &entry))
! 1338: {
! 1339: if (!keep_ca || entry->type != AUTH_RULE_CA_CERT)
! 1340: {
! 1341: destroy_entry_value(entry);
! 1342: array_remove_at(this->entries, enumerator);
! 1343: }
! 1344: }
! 1345: enumerator->destroy(enumerator);
! 1346:
! 1347: array_compress(this->entries);
! 1348: }
! 1349:
! 1350: METHOD(auth_cfg_t, clone_, auth_cfg_t*,
! 1351: private_auth_cfg_t *this)
! 1352: {
! 1353: enumerator_t *enumerator;
! 1354: auth_cfg_t *clone;
! 1355: auth_rule_t type;
! 1356: void *value;
! 1357:
! 1358: clone = auth_cfg_create();
! 1359: /* this enumerator skips duplicates for rules we expect only once */
! 1360: enumerator = create_enumerator(this);
! 1361: while (enumerator->enumerate(enumerator, &type, &value))
! 1362: {
! 1363: switch (type)
! 1364: {
! 1365: case AUTH_RULE_IDENTITY:
! 1366: case AUTH_RULE_CA_IDENTITY:
! 1367: case AUTH_RULE_EAP_IDENTITY:
! 1368: case AUTH_RULE_AAA_IDENTITY:
! 1369: case AUTH_RULE_GROUP:
! 1370: case AUTH_RULE_XAUTH_IDENTITY:
! 1371: {
! 1372: identification_t *id = (identification_t*)value;
! 1373: clone->add(clone, type, id->clone(id));
! 1374: break;
! 1375: }
! 1376: case AUTH_RULE_CA_CERT:
! 1377: case AUTH_RULE_IM_CERT:
! 1378: case AUTH_RULE_SUBJECT_CERT:
! 1379: case AUTH_HELPER_IM_CERT:
! 1380: case AUTH_HELPER_SUBJECT_CERT:
! 1381: case AUTH_HELPER_REVOCATION_CERT:
! 1382: case AUTH_HELPER_AC_CERT:
! 1383: {
! 1384: certificate_t *cert = (certificate_t*)value;
! 1385: clone->add(clone, type, cert->get_ref(cert));
! 1386: break;
! 1387: }
! 1388: case AUTH_RULE_XAUTH_BACKEND:
! 1389: case AUTH_RULE_CERT_POLICY:
! 1390: case AUTH_HELPER_IM_HASH_URL:
! 1391: case AUTH_HELPER_SUBJECT_HASH_URL:
! 1392: {
! 1393: clone->add(clone, type, strdup(value));
! 1394: break;
! 1395: }
! 1396: case AUTH_RULE_IDENTITY_LOOSE:
! 1397: case AUTH_RULE_AUTH_CLASS:
! 1398: case AUTH_RULE_EAP_TYPE:
! 1399: case AUTH_RULE_EAP_VENDOR:
! 1400: case AUTH_RULE_CRL_VALIDATION:
! 1401: case AUTH_RULE_OCSP_VALIDATION:
! 1402: case AUTH_RULE_RSA_STRENGTH:
! 1403: case AUTH_RULE_ECDSA_STRENGTH:
! 1404: case AUTH_RULE_BLISS_STRENGTH:
! 1405: case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
! 1406: clone->add(clone, type, (uintptr_t)value);
! 1407: break;
! 1408: case AUTH_RULE_SIGNATURE_SCHEME:
! 1409: case AUTH_RULE_IKE_SIGNATURE_SCHEME:
! 1410: {
! 1411: clone->add(clone, type, signature_params_clone(value));
! 1412: break;
! 1413: }
! 1414: case AUTH_RULE_MAX:
! 1415: break;
! 1416: }
! 1417: }
! 1418: enumerator->destroy(enumerator);
! 1419: return clone;
! 1420: }
! 1421:
! 1422: METHOD(auth_cfg_t, destroy, void,
! 1423: private_auth_cfg_t *this)
! 1424: {
! 1425: purge(this, FALSE);
! 1426: array_destroy(this->entries);
! 1427: free(this);
! 1428: }
! 1429:
! 1430: /*
! 1431: * see header file
! 1432: */
! 1433: auth_cfg_t *auth_cfg_create()
! 1434: {
! 1435: private_auth_cfg_t *this;
! 1436:
! 1437: INIT(this,
! 1438: .public = {
! 1439: .add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add,
! 1440: .add_pubkey_constraints = _add_pubkey_constraints,
! 1441: .get = _get,
! 1442: .create_enumerator = _create_enumerator,
! 1443: .replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace,
! 1444: .complies = _complies,
! 1445: .merge = (void(*)(auth_cfg_t*,auth_cfg_t*,bool))merge,
! 1446: .purge = _purge,
! 1447: .equals = (bool(*)(auth_cfg_t*,auth_cfg_t*))equals,
! 1448: .clone = _clone_,
! 1449: .destroy = _destroy,
! 1450: },
! 1451: .entries = array_create(sizeof(entry_t), 0),
! 1452: );
! 1453:
! 1454: return &this->public;
! 1455: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>