Annotation of embedaddon/strongswan/src/libstrongswan/plugins/constraints/constraints_validator.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2010 Martin Willi
        !             3:  * Copyright (C) 2010 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "constraints_validator.h"
        !            17: 
        !            18: #include <utils/debug.h>
        !            19: #include <asn1/asn1.h>
        !            20: #include <collections/linked_list.h>
        !            21: #include <credentials/certificates/x509.h>
        !            22: 
        !            23: typedef struct private_constraints_validator_t private_constraints_validator_t;
        !            24: 
        !            25: /**
        !            26:  * Private data of an constraints_validator_t object.
        !            27:  */
        !            28: struct private_constraints_validator_t {
        !            29: 
        !            30:        /**
        !            31:         * Public constraints_validator_t interface.
        !            32:         */
        !            33:        constraints_validator_t public;
        !            34: };
        !            35: 
        !            36: /**
        !            37:  * Check pathlen constraint of issuer certificate
        !            38:  */
        !            39: static bool check_pathlen(x509_t *issuer, int pathlen)
        !            40: {
        !            41:        u_int pathlen_constraint;
        !            42: 
        !            43:        pathlen_constraint = issuer->get_constraint(issuer, X509_PATH_LEN);
        !            44:        if (pathlen_constraint != X509_NO_CONSTRAINT &&
        !            45:                pathlen > pathlen_constraint)
        !            46:        {
        !            47:                DBG1(DBG_CFG, "path length of %d violates constraint of %d",
        !            48:                         pathlen, pathlen_constraint);
        !            49:                return FALSE;
        !            50:        }
        !            51:        return TRUE;
        !            52: }
        !            53: 
        !            54: /**
        !            55:  * Check if a FQDN constraint matches
        !            56:  */
        !            57: static bool fqdn_matches(identification_t *constraint, identification_t *id)
        !            58: {
        !            59:        chunk_t c, i, diff;
        !            60: 
        !            61:        c = constraint->get_encoding(constraint);
        !            62:        i = id->get_encoding(id);
        !            63: 
        !            64:        if (!c.len || i.len < c.len)
        !            65:        {
        !            66:                return FALSE;
        !            67:        }
        !            68:        diff = chunk_create(i.ptr, i.len - c.len);
        !            69:        if (!chunk_equals(c, chunk_skip(i, diff.len)))
        !            70:        {
        !            71:                return FALSE;
        !            72:        }
        !            73:        if (!diff.len)
        !            74:        {
        !            75:                return TRUE;
        !            76:        }
        !            77:        if (c.ptr[0] == '.' || diff.ptr[diff.len - 1] == '.')
        !            78:        {
        !            79:                return TRUE;
        !            80:        }
        !            81:        return FALSE;
        !            82: }
        !            83: 
        !            84: /**
        !            85:  * Check if a RFC822 constraint matches
        !            86:  */
        !            87: static bool email_matches(identification_t *constraint, identification_t *id)
        !            88: {
        !            89:        chunk_t c, i, diff;
        !            90: 
        !            91:        c = constraint->get_encoding(constraint);
        !            92:        i = id->get_encoding(id);
        !            93: 
        !            94:        if (!c.len || i.len < c.len)
        !            95:        {
        !            96:                return FALSE;
        !            97:        }
        !            98:        if (memchr(c.ptr, '@', c.len))
        !            99:        {       /* constraint is a full email address */
        !           100:                return chunk_equals(c, i);
        !           101:        }
        !           102:        diff = chunk_create(i.ptr, i.len - c.len);
        !           103:        if (!diff.len || !chunk_equals(c, chunk_skip(i, diff.len)))
        !           104:        {
        !           105:                return FALSE;
        !           106:        }
        !           107:        if (c.ptr[0] == '.')
        !           108:        {       /* constraint is domain, suffix match */
        !           109:                return TRUE;
        !           110:        }
        !           111:        if (diff.ptr[diff.len - 1] == '@')
        !           112:        {       /* constraint is host specific, only username can be appended */
        !           113:                return TRUE;
        !           114:        }
        !           115:        return FALSE;
        !           116: }
        !           117: 
        !           118: /**
        !           119:  * Check if a DN constraint matches (RDN prefix match)
        !           120:  */
        !           121: static bool dn_matches(identification_t *constraint, identification_t *id)
        !           122: {
        !           123:        enumerator_t *ec, *ei;
        !           124:        id_part_t pc, pi;
        !           125:        chunk_t cc, ci;
        !           126:        bool match = TRUE;
        !           127: 
        !           128:        ec = constraint->create_part_enumerator(constraint);
        !           129:        ei = id->create_part_enumerator(id);
        !           130:        while (ec->enumerate(ec, &pc, &cc))
        !           131:        {
        !           132:                if (!ei->enumerate(ei, &pi, &ci) ||
        !           133:                        pi != pc || !chunk_equals(cc, ci))
        !           134:                {
        !           135:                        match = FALSE;
        !           136:                        break;
        !           137:                }
        !           138:        }
        !           139:        ec->destroy(ec);
        !           140:        ei->destroy(ei);
        !           141: 
        !           142:        return match;
        !           143: }
        !           144: 
        !           145: /**
        !           146:  * Check if a certificate matches to a NameConstraint
        !           147:  */
        !           148: static bool name_constraint_matches(identification_t *constraint,
        !           149:                                                                        certificate_t *cert, bool permitted)
        !           150: {
        !           151:        x509_t *x509 = (x509_t*)cert;
        !           152:        enumerator_t *enumerator;
        !           153:        identification_t *id;
        !           154:        id_type_t type;
        !           155:        bool matches = permitted;
        !           156: 
        !           157:        type = constraint->get_type(constraint);
        !           158:        if (type == ID_DER_ASN1_DN)
        !           159:        {
        !           160:                matches = dn_matches(constraint, cert->get_subject(cert));
        !           161:                if (matches != permitted)
        !           162:                {
        !           163:                        return matches;
        !           164:                }
        !           165:        }
        !           166: 
        !           167:        enumerator = x509->create_subjectAltName_enumerator(x509);
        !           168:        while (enumerator->enumerate(enumerator, &id))
        !           169:        {
        !           170:                if (id->get_type(id) == type)
        !           171:                {
        !           172:                        switch (type)
        !           173:                        {
        !           174:                                case ID_FQDN:
        !           175:                                        matches = fqdn_matches(constraint, id);
        !           176:                                        break;
        !           177:                                case ID_RFC822_ADDR:
        !           178:                                        matches = email_matches(constraint, id);
        !           179:                                        break;
        !           180:                                case ID_DER_ASN1_DN:
        !           181:                                        matches = dn_matches(constraint, id);
        !           182:                                        break;
        !           183:                                default:
        !           184:                                        DBG1(DBG_CFG, "%N NameConstraint matching not implemented",
        !           185:                                                 id_type_names, type);
        !           186:                                        matches = FALSE;
        !           187:                                        break;
        !           188:                        }
        !           189:                }
        !           190:                if (matches != permitted)
        !           191:                {
        !           192:                        break;
        !           193:                }
        !           194:        }
        !           195:        enumerator->destroy(enumerator);
        !           196: 
        !           197:        return matches;
        !           198: }
        !           199: 
        !           200: /**
        !           201:  * Check if a permitted or excluded NameConstraint has been inherited to sub-CA
        !           202:  */
        !           203: static bool name_constraint_inherited(identification_t *constraint,
        !           204:                                                                          x509_t *x509, bool permitted)
        !           205: {
        !           206:        enumerator_t *enumerator;
        !           207:        identification_t *id, *a, *b;
        !           208:        bool inherited = FALSE;
        !           209:        id_type_t type;
        !           210: 
        !           211:        if (!(x509->get_flags(x509) & X509_CA))
        !           212:        {       /* not a sub-CA, not required */
        !           213:                return TRUE;
        !           214:        }
        !           215: 
        !           216:        type = constraint->get_type(constraint);
        !           217:        enumerator = x509->create_name_constraint_enumerator(x509, permitted);
        !           218:        while (enumerator->enumerate(enumerator, &id))
        !           219:        {
        !           220:                if (id->get_type(id) == type)
        !           221:                {
        !           222:                        if (permitted)
        !           223:                        {       /* permitted constraint can be narrowed */
        !           224:                                a = constraint;
        !           225:                                b = id;
        !           226:                        }
        !           227:                        else
        !           228:                        {       /* excluded constraint can be widened */
        !           229:                                a = id;
        !           230:                                b = constraint;
        !           231:                        }
        !           232:                        switch (type)
        !           233:                        {
        !           234:                                case ID_FQDN:
        !           235:                                        inherited = fqdn_matches(a, b);
        !           236:                                        break;
        !           237:                                case ID_RFC822_ADDR:
        !           238:                                        inherited = email_matches(a, b);
        !           239:                                        break;
        !           240:                                case ID_DER_ASN1_DN:
        !           241:                                        inherited = dn_matches(a, b);
        !           242:                                        break;
        !           243:                                default:
        !           244:                                        DBG1(DBG_CFG, "%N NameConstraint matching not implemented",
        !           245:                                                 id_type_names, type);
        !           246:                                        inherited = FALSE;
        !           247:                                        break;
        !           248:                        }
        !           249:                }
        !           250:                if (inherited)
        !           251:                {
        !           252:                        break;
        !           253:                }
        !           254:        }
        !           255:        enumerator->destroy(enumerator);
        !           256:        return inherited;
        !           257: }
        !           258: 
        !           259: /**
        !           260:  * Check name constraints
        !           261:  */
        !           262: static bool check_name_constraints(certificate_t *subject, x509_t *issuer)
        !           263: {
        !           264:        enumerator_t *enumerator;
        !           265:        identification_t *constraint;
        !           266: 
        !           267:        enumerator = issuer->create_name_constraint_enumerator(issuer, TRUE);
        !           268:        while (enumerator->enumerate(enumerator, &constraint))
        !           269:        {
        !           270:                if (!name_constraint_matches(constraint, subject, TRUE))
        !           271:                {
        !           272:                        DBG1(DBG_CFG, "certificate '%Y' does not match permitted name "
        !           273:                                 "constraint '%Y'", subject->get_subject(subject), constraint);
        !           274:                        enumerator->destroy(enumerator);
        !           275:                        return FALSE;
        !           276:                }
        !           277:                if (!name_constraint_inherited(constraint, (x509_t*)subject, TRUE))
        !           278:                {
        !           279:                        DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit permitted name "
        !           280:                                 "constraint '%Y'", subject->get_subject(subject), constraint);
        !           281:                        enumerator->destroy(enumerator);
        !           282:                        return FALSE;
        !           283:                }
        !           284:        }
        !           285:        enumerator->destroy(enumerator);
        !           286: 
        !           287:        enumerator = issuer->create_name_constraint_enumerator(issuer, FALSE);
        !           288:        while (enumerator->enumerate(enumerator, &constraint))
        !           289:        {
        !           290:                if (name_constraint_matches(constraint, subject, FALSE))
        !           291:                {
        !           292:                        DBG1(DBG_CFG, "certificate '%Y' matches excluded name "
        !           293:                                 "constraint '%Y'", subject->get_subject(subject), constraint);
        !           294:                        enumerator->destroy(enumerator);
        !           295:                        return FALSE;
        !           296:                }
        !           297:                if (!name_constraint_inherited(constraint, (x509_t*)subject, FALSE))
        !           298:                {
        !           299:                        DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit excluded name "
        !           300:                                 "constraint '%Y'", subject->get_subject(subject), constraint);
        !           301:                        enumerator->destroy(enumerator);
        !           302:                        return FALSE;
        !           303:                }
        !           304:        }
        !           305:        enumerator->destroy(enumerator);
        !           306:        return TRUE;
        !           307: }
        !           308: 
        !           309: /**
        !           310:  * Special OID for anyPolicy
        !           311:  */
        !           312: static chunk_t any_policy = chunk_from_chars(0x55,0x1d,0x20,0x00);
        !           313: 
        !           314: /**
        !           315:  * Check if an issuer certificate has a given policy OID
        !           316:  */
        !           317: static bool has_policy(x509_t *issuer, chunk_t oid)
        !           318: {
        !           319:        x509_policy_mapping_t *mapping;
        !           320:        x509_cert_policy_t *policy;
        !           321:        enumerator_t *enumerator;
        !           322: 
        !           323:        enumerator = issuer->create_cert_policy_enumerator(issuer);
        !           324:        while (enumerator->enumerate(enumerator, &policy))
        !           325:        {
        !           326:                if (chunk_equals(oid, policy->oid) ||
        !           327:                        chunk_equals(any_policy, policy->oid))
        !           328:                {
        !           329:                        enumerator->destroy(enumerator);
        !           330:                        return TRUE;
        !           331:                }
        !           332:        }
        !           333:        enumerator->destroy(enumerator);
        !           334: 
        !           335:        /* fall back to a mapped policy */
        !           336:        enumerator = issuer->create_policy_mapping_enumerator(issuer);
        !           337:        while (enumerator->enumerate(enumerator, &mapping))
        !           338:        {
        !           339:                if (chunk_equals(mapping->subject, oid))
        !           340:                {
        !           341:                        enumerator->destroy(enumerator);
        !           342:                        return TRUE;
        !           343:                }
        !           344:        }
        !           345:        enumerator->destroy(enumerator);
        !           346:        return FALSE;
        !           347: }
        !           348: 
        !           349: /**
        !           350:  * Check certificatePolicies.
        !           351:  */
        !           352: static bool check_policy(x509_t *subject, x509_t *issuer)
        !           353: {
        !           354:        certificate_t *cert = (certificate_t*)subject;
        !           355:        x509_policy_mapping_t *mapping;
        !           356:        x509_cert_policy_t *policy;
        !           357:        enumerator_t *enumerator;
        !           358:        char *oid;
        !           359: 
        !           360:        /* verify if policyMappings in subject are valid */
        !           361:        enumerator = subject->create_policy_mapping_enumerator(subject);
        !           362:        while (enumerator->enumerate(enumerator, &mapping))
        !           363:        {
        !           364:                if (!has_policy(issuer, mapping->issuer))
        !           365:                {
        !           366:                        oid = asn1_oid_to_string(mapping->issuer);
        !           367:                        DBG1(DBG_CFG, "certificate '%Y' maps policy from %s, but issuer "
        !           368:                                 "misses it", cert->get_subject(cert), oid);
        !           369:                        free(oid);
        !           370:                        enumerator->destroy(enumerator);
        !           371:                        return FALSE;
        !           372:                }
        !           373:        }
        !           374:        enumerator->destroy(enumerator);
        !           375: 
        !           376:        enumerator = subject->create_cert_policy_enumerator(subject);
        !           377:        while (enumerator->enumerate(enumerator, &policy))
        !           378:        {
        !           379:                if (!has_policy(issuer, policy->oid))
        !           380:                {
        !           381:                        oid = asn1_oid_to_string(policy->oid);
        !           382:                        DBG1(DBG_CFG, "policy %s missing in issuing certificate '%Y'",
        !           383:                                 oid, cert->get_issuer(cert));
        !           384:                        free(oid);
        !           385:                        enumerator->destroy(enumerator);
        !           386:                        return FALSE;
        !           387:                }
        !           388:        }
        !           389:        enumerator->destroy(enumerator);
        !           390: 
        !           391:        return TRUE;
        !           392: }
        !           393: 
        !           394: /**
        !           395:  * Check if a given policy is valid under a trustchain
        !           396:  */
        !           397: static bool is_policy_valid(linked_list_t *chain, chunk_t oid)
        !           398: {
        !           399:        x509_policy_mapping_t *mapping;
        !           400:        x509_cert_policy_t *policy;
        !           401:        x509_t *issuer;
        !           402:        enumerator_t *issuers, *policies, *mappings;
        !           403:        bool found = TRUE;
        !           404: 
        !           405:        issuers = chain->create_enumerator(chain);
        !           406:        while (issuers->enumerate(issuers, &issuer))
        !           407:        {
        !           408:                int maxmap = 8;
        !           409: 
        !           410:                while (found)
        !           411:                {
        !           412:                        found = FALSE;
        !           413: 
        !           414:                        policies = issuer->create_cert_policy_enumerator(issuer);
        !           415:                        while (policies->enumerate(policies, &policy))
        !           416:                        {
        !           417:                                if (chunk_equals(oid, policy->oid) ||
        !           418:                                        chunk_equals(any_policy, policy->oid))
        !           419:                                {
        !           420:                                        found = TRUE;
        !           421:                                        break;
        !           422:                                }
        !           423:                        }
        !           424:                        policies->destroy(policies);
        !           425:                        if (found)
        !           426:                        {
        !           427:                                break;
        !           428:                        }
        !           429:                        /* fall back to a mapped policy */
        !           430:                        mappings = issuer->create_policy_mapping_enumerator(issuer);
        !           431:                        while (mappings->enumerate(mappings, &mapping))
        !           432:                        {
        !           433:                                if (chunk_equals(mapping->subject, oid))
        !           434:                                {
        !           435:                                        oid = mapping->issuer;
        !           436:                                        found = TRUE;
        !           437:                                        break;
        !           438:                                }
        !           439:                        }
        !           440:                        mappings->destroy(mappings);
        !           441:                        if (--maxmap == 0)
        !           442:                        {
        !           443:                                found = FALSE;
        !           444:                                break;
        !           445:                        }
        !           446:                }
        !           447:                if (!found)
        !           448:                {
        !           449:                        break;
        !           450:                }
        !           451:        }
        !           452:        issuers->destroy(issuers);
        !           453: 
        !           454:        return found;
        !           455: }
        !           456: 
        !           457: /**
        !           458:  * Check len certificates in trustchain for inherited policies
        !           459:  */
        !           460: static bool has_policy_chain(linked_list_t *chain, x509_t *subject, int len)
        !           461: {
        !           462:        enumerator_t *enumerator;
        !           463:        x509_t *issuer;
        !           464:        bool valid = TRUE;
        !           465: 
        !           466:        enumerator = chain->create_enumerator(chain);
        !           467:        while (len-- > 0 && enumerator->enumerate(enumerator, &issuer))
        !           468:        {
        !           469:                if (!check_policy(subject, issuer))
        !           470:                {
        !           471:                        valid = FALSE;
        !           472:                        break;
        !           473:                }
        !           474:                subject = issuer;
        !           475:        }
        !           476:        enumerator->destroy(enumerator);
        !           477:        return valid;
        !           478: }
        !           479: 
        !           480: /**
        !           481:  * Check len certificates in trustchain to have no policyMappings
        !           482:  */
        !           483: static bool has_no_policy_mapping(linked_list_t *chain, int len)
        !           484: {
        !           485:        enumerator_t *enumerator, *mappings;
        !           486:        x509_policy_mapping_t *mapping;
        !           487:        certificate_t *cert;
        !           488:        x509_t *x509;
        !           489:        bool valid = TRUE;
        !           490: 
        !           491:        enumerator = chain->create_enumerator(chain);
        !           492:        while (len-- > 0 && enumerator->enumerate(enumerator, &x509))
        !           493:        {
        !           494:                mappings = x509->create_policy_mapping_enumerator(x509);
        !           495:                valid = !mappings->enumerate(mappings, &mapping);
        !           496:                mappings->destroy(mappings);
        !           497:                if (!valid)
        !           498:                {
        !           499:                        cert = (certificate_t*)x509;
        !           500:                        DBG1(DBG_CFG, "found policyMapping in certificate '%Y', but "
        !           501:                                 "inhibitPolicyMapping in effect", cert->get_subject(cert));
        !           502:                        break;
        !           503:                }
        !           504:        }
        !           505:        enumerator->destroy(enumerator);
        !           506:        return valid;
        !           507: }
        !           508: 
        !           509: /**
        !           510:  * Check len certificates in trustchain to have no anyPolicies
        !           511:  */
        !           512: static bool has_no_any_policy(linked_list_t *chain, int len)
        !           513: {
        !           514:        enumerator_t *enumerator, *policies;
        !           515:        x509_cert_policy_t *policy;
        !           516:        certificate_t *cert;
        !           517:        x509_t *x509;
        !           518:        bool valid = TRUE;
        !           519: 
        !           520:        enumerator = chain->create_enumerator(chain);
        !           521:        while (len-- > 0 && enumerator->enumerate(enumerator, &x509))
        !           522:        {
        !           523:                policies = x509->create_cert_policy_enumerator(x509);
        !           524:                while (policies->enumerate(policies, &policy))
        !           525:                {
        !           526:                        if (chunk_equals(policy->oid, any_policy))
        !           527:                        {
        !           528:                                cert = (certificate_t*)x509;
        !           529:                                DBG1(DBG_CFG, "found anyPolicy in certificate '%Y', but "
        !           530:                                         "inhibitAnyPolicy in effect", cert->get_subject(cert));
        !           531:                                valid = FALSE;
        !           532:                                break;
        !           533:                        }
        !           534:                }
        !           535:                policies->destroy(policies);
        !           536:        }
        !           537:        enumerator->destroy(enumerator);
        !           538:        return valid;
        !           539: }
        !           540: 
        !           541: /**
        !           542:  * Check requireExplicitPolicy and inhibitPolicyMapping constraints
        !           543:  */
        !           544: static bool check_policy_constraints(x509_t *issuer, u_int pathlen,
        !           545:                                                                         auth_cfg_t *auth)
        !           546: {
        !           547:        certificate_t *subject;
        !           548:        bool valid = TRUE;
        !           549: 
        !           550:        subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
        !           551:        if (subject)
        !           552:        {
        !           553:                if (subject->get_type(subject) == CERT_X509)
        !           554:                {
        !           555:                        x509_cert_policy_t *policy;
        !           556:                        enumerator_t *enumerator;
        !           557:                        linked_list_t *chain;
        !           558:                        certificate_t *cert;
        !           559:                        auth_rule_t rule;
        !           560:                        x509_t *x509;
        !           561:                        int len = 0;
        !           562:                        u_int expl, inh;
        !           563:                        char *oid;
        !           564: 
        !           565:                        /* prepare trustchain to validate */
        !           566:                        chain = linked_list_create();
        !           567:                        enumerator = auth->create_enumerator(auth);
        !           568:                        while (enumerator->enumerate(enumerator, &rule, &cert))
        !           569:                        {
        !           570:                                if (rule == AUTH_RULE_IM_CERT &&
        !           571:                                        cert->get_type(cert) == CERT_X509)
        !           572:                                {
        !           573:                                        chain->insert_last(chain, cert);
        !           574:                                }
        !           575:                        }
        !           576:                        enumerator->destroy(enumerator);
        !           577:                        chain->insert_last(chain, issuer);
        !           578: 
        !           579:                        /* search for requireExplicitPolicy constraints */
        !           580:                        enumerator = chain->create_enumerator(chain);
        !           581:                        while (enumerator->enumerate(enumerator, &x509))
        !           582:                        {
        !           583:                                expl = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
        !           584:                                if (expl != X509_NO_CONSTRAINT)
        !           585:                                {
        !           586:                                        if (!has_policy_chain(chain, (x509_t*)subject, len - expl))
        !           587:                                        {
        !           588:                                                valid = FALSE;
        !           589:                                                break;
        !           590:                                        }
        !           591:                                }
        !           592:                                len++;
        !           593:                        }
        !           594:                        enumerator->destroy(enumerator);
        !           595: 
        !           596:                        /* search for inhibitPolicyMapping/inhibitAnyPolicy constraints */
        !           597:                        len = 0;
        !           598:                        chain->insert_first(chain, subject);
        !           599:                        enumerator = chain->create_enumerator(chain);
        !           600:                        while (enumerator->enumerate(enumerator, &x509))
        !           601:                        {
        !           602:                                inh = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
        !           603:                                if (inh != X509_NO_CONSTRAINT)
        !           604:                                {
        !           605:                                        if (!has_no_policy_mapping(chain, len - inh))
        !           606:                                        {
        !           607:                                                valid = FALSE;
        !           608:                                                break;
        !           609:                                        }
        !           610:                                }
        !           611:                                inh = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
        !           612:                                if (inh != X509_NO_CONSTRAINT)
        !           613:                                {
        !           614:                                        if (!has_no_any_policy(chain, len - inh))
        !           615:                                        {
        !           616:                                                valid = FALSE;
        !           617:                                                break;
        !           618:                                        }
        !           619:                                }
        !           620:                                len++;
        !           621:                        }
        !           622:                        enumerator->destroy(enumerator);
        !           623: 
        !           624:                        if (valid)
        !           625:                        {
        !           626:                                x509 = (x509_t*)subject;
        !           627: 
        !           628:                                enumerator = x509->create_cert_policy_enumerator(x509);
        !           629:                                while (enumerator->enumerate(enumerator, &policy))
        !           630:                                {
        !           631:                                        oid = asn1_oid_to_string(policy->oid);
        !           632:                                        if (oid)
        !           633:                                        {
        !           634:                                                if (is_policy_valid(chain, policy->oid))
        !           635:                                                {
        !           636:                                                        auth->add(auth, AUTH_RULE_CERT_POLICY, oid);
        !           637:                                                }
        !           638:                                                else
        !           639:                                                {
        !           640:                                                        DBG1(DBG_CFG, "certificate policy %s for '%Y' "
        !           641:                                                                 "not allowed by trustchain, ignored",
        !           642:                                                                 oid, subject->get_subject(subject));
        !           643:                                                        free(oid);
        !           644:                                                }
        !           645:                                        }
        !           646:                                }
        !           647:                                enumerator->destroy(enumerator);
        !           648:                        }
        !           649:                        chain->destroy(chain);
        !           650:                }
        !           651:        }
        !           652:        return valid;
        !           653: }
        !           654: 
        !           655: METHOD(cert_validator_t, validate, bool,
        !           656:        private_constraints_validator_t *this, certificate_t *subject,
        !           657:        certificate_t *issuer, bool online, u_int pathlen, bool anchor,
        !           658:        auth_cfg_t *auth)
        !           659: {
        !           660:        if (issuer->get_type(issuer) == CERT_X509 &&
        !           661:                subject->get_type(subject) == CERT_X509)
        !           662:        {
        !           663:                if (!check_pathlen((x509_t*)issuer, pathlen))
        !           664:                {
        !           665:                        lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_EXCEEDED_PATH_LEN,
        !           666:                                                                        subject);
        !           667:                        return FALSE;
        !           668:                }
        !           669:                if (!check_name_constraints(subject, (x509_t*)issuer))
        !           670:                {
        !           671:                        lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_POLICY_VIOLATION,
        !           672:                                                                        subject);
        !           673:                        return FALSE;
        !           674:                }
        !           675:                if (anchor)
        !           676:                {
        !           677:                        if (!check_policy_constraints((x509_t*)issuer, pathlen, auth))
        !           678:                        {
        !           679:                                lib->credmgr->call_hook(lib->credmgr,
        !           680:                                                                                CRED_HOOK_POLICY_VIOLATION, issuer);
        !           681:                                return FALSE;
        !           682:                        }
        !           683:                }
        !           684:        }
        !           685:        return TRUE;
        !           686: }
        !           687: 
        !           688: METHOD(constraints_validator_t, destroy, void,
        !           689:        private_constraints_validator_t *this)
        !           690: {
        !           691:        free(this);
        !           692: }
        !           693: 
        !           694: /**
        !           695:  * See header
        !           696:  */
        !           697: constraints_validator_t *constraints_validator_create()
        !           698: {
        !           699:        private_constraints_validator_t *this;
        !           700: 
        !           701:        INIT(this,
        !           702:                .public = {
        !           703:                        .validator.validate = _validate,
        !           704:                        .destroy = _destroy,
        !           705:                },
        !           706:        );
        !           707: 
        !           708:        return &this->public;
        !           709: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>