static int targetDistance ( NameConstraintsExtension constraints , X509Certificate cert , GeneralNameInterface target ) throws IOException { /* ensure that certificate satisfies existing name constraints */ if ( constraints != null && ! constraints . verify ( cert ) ) { throw new IOException ( "certificate does not satisfy existing name " + "constraints" ) ; } X509CertImpl certImpl ; try { certImpl = X509CertImpl . toImpl ( cert ) ; } catch ( CertificateException e ) { throw new IOException ( "Invalid certificate" , e ) ; } /* see if certificate subject matches target */ X500Name subject = X500Name . asX500Name ( certImpl . getSubjectX500Principal ( ) ) ; if ( subject . equals ( target ) ) { /* match! */ return 0 ; } SubjectAlternativeNameExtension altNameExt = certImpl . getSubjectAlternativeNameExtension ( ) ; if ( altNameExt != null ) { GeneralNames altNames = altNameExt . get ( SubjectAlternativeNameExtension . SUBJECT_NAME ) ; /* see if any alternative name matches target */ if ( altNames != null ) { for ( int j = 0 , n = altNames . size ( ) ; j < n ; j ++ ) { GeneralNameInterface altName = altNames . get ( j ) . getName ( ) ; if ( altName . equals ( target ) ) { return 0 ; } } } } /* no exact match; see if certificate can get us to target */ /* first, get NameConstraints out of certificate */ NameConstraintsExtension ncExt = certImpl . getNameConstraintsExtension ( ) ; if ( ncExt == null ) { return - 1 ; } /* merge certificate's NameConstraints with current NameConstraints */ if ( constraints != null ) { constraints . merge ( ncExt ) ; } else { // Make sure we do a clone here, because we're probably // going to modify this object later and we don't want to // be sharing it with a Certificate object! constraints = ( NameConstraintsExtension ) ncExt . clone ( ) ; } if ( debug != null ) { debug . println ( "Builder.targetDistance() merged constraints: " + String . valueOf ( constraints ) ) ; } /* reduce permitted by excluded */ GeneralSubtrees permitted = constraints . get ( NameConstraintsExtension . PERMITTED_SUBTREES ) ; GeneralSubtrees excluded = constraints . get ( NameConstraintsExtension . EXCLUDED_SUBTREES ) ; if ( permitted != null ) { permitted . reduce ( excluded ) ; } if ( debug != null ) { debug . println ( "Builder.targetDistance() reduced constraints: " + permitted ) ; } /* see if new merged constraints allow target */ if ( ! constraints . verify ( target ) ) { throw new IOException ( "New certificate not allowed to sign " + "certificate for target" ) ; } /* find distance to target, if any, in permitted */ if ( permitted == null ) { /* certificate is unconstrained; could sign for anything */ return - 1 ; } for ( int i = 0 , n = permitted . size ( ) ; i < n ; i ++ ) { GeneralNameInterface perName = permitted . get ( i ) . getName ( ) . getName ( ) ; int distance = distance ( perName , target , - 1 ) ; if ( distance >= 0 ) { return ( distance + 1 ) ; } } /* no matching type in permitted; cert holder could certify target */ return - 1 ; }
Determine how close a given certificate gets you toward a given target .