create_identifiers_from_stack(STACK_OF(X509) *sk,
                              krb5_external_principal_identifier *** ids)
{
    int i = 0, sk_size = sk_X509_num(sk);
    krb5_external_principal_identifier **krb5_cas = NULL;
    X509 *x = NULL;
    X509_NAME *xn = NULL;
    unsigned char *p = NULL;
    int len = 0;
    PKCS7_ISSUER_AND_SERIAL *is = NULL;
    char buf[DN_BUF_LEN];

    *ids = NULL;

    krb5_cas = calloc(sk_size + 1, sizeof(*krb5_cas));
    if (krb5_cas == NULL)
        return ENOMEM;

    for (i = 0; i < sk_size; i++) {
        krb5_cas[i] = malloc(sizeof(krb5_external_principal_identifier));

        x = sk_X509_value(sk, i);

        X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
        pkiDebug("#%d cert= %s\n", i, buf);

        /* fill-in subjectName */
        krb5_cas[i]->subjectName.magic = 0;
        krb5_cas[i]->subjectName.length = 0;
        krb5_cas[i]->subjectName.data = NULL;

        xn = X509_get_subject_name(x);
        len = i2d_X509_NAME(xn, NULL);
        if ((p = malloc((size_t) len)) == NULL)
            goto oom;
        krb5_cas[i]->subjectName.data = (char *)p;
        i2d_X509_NAME(xn, &p);
        krb5_cas[i]->subjectName.length = len;

        /* fill-in issuerAndSerialNumber */
        krb5_cas[i]->issuerAndSerialNumber.length = 0;
        krb5_cas[i]->issuerAndSerialNumber.magic = 0;
        krb5_cas[i]->issuerAndSerialNumber.data = NULL;

        is = PKCS7_ISSUER_AND_SERIAL_new();
        if (is == NULL)
            goto oom;
        X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
        ASN1_INTEGER_free(is->serial);
        is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
        if (is->serial == NULL)
            goto oom;
        len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
        p = malloc(len);
        if (p == NULL)
            goto oom;
        krb5_cas[i]->issuerAndSerialNumber.data = (char *)p;
        i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
        krb5_cas[i]->issuerAndSerialNumber.length = len;

        /* fill-in subjectKeyIdentifier */
        krb5_cas[i]->subjectKeyIdentifier.length = 0;
        krb5_cas[i]->subjectKeyIdentifier.magic = 0;
        krb5_cas[i]->subjectKeyIdentifier.data = NULL;

        if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
            ASN1_OCTET_STRING *ikeyid;

            ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
                                      NULL);
            if (ikeyid != NULL) {
                len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
                p = malloc(len);
                if (p == NULL)
                    goto oom;
                krb5_cas[i]->subjectKeyIdentifier.data = (char *)p;
                i2d_ASN1_OCTET_STRING(ikeyid, &p);
                krb5_cas[i]->subjectKeyIdentifier.length = len;
                ASN1_OCTET_STRING_free(ikeyid);
            }
        }
        PKCS7_ISSUER_AND_SERIAL_free(is);
        is = NULL;
    }

    *ids = krb5_cas;
    return 0;

oom:
    free_krb5_external_principal_identifier(&krb5_cas);
    PKCS7_ISSUER_AND_SERIAL_free(is);
    return ENOMEM;
}
create_identifiers_from_stack(STACK_OF(X509) *sk,
                              krb5_external_principal_identifier *** ids)
{
    int i = 0, sk_size = sk_X509_num(sk);
    krb5_external_principal_identifier **krb5_cas = NULL;
    X509 *x = NULL;
    X509_NAME *xn = NULL;
    unsigned char *p = NULL;
    int len = 0;
    PKCS7_ISSUER_AND_SERIAL *is = NULL;
    char buf[DN_BUF_LEN];

    *ids = NULL;

    krb5_cas = calloc(sk_size + 1, sizeof(*krb5_cas));
    if (krb5_cas == NULL)
        return ENOMEM;

    for (i = 0; i < sk_size; i++) {
        krb5_cas[i] = malloc(sizeof(krb5_external_principal_identifier));

        x = sk_X509_value(sk, i);

        X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
        pkiDebug("#%d cert= %s\n", i, buf);

         
        krb5_cas[i]->subjectName.magic = 0;
        krb5_cas[i]->subjectName.length = 0;
        krb5_cas[i]->subjectName.data = NULL;

        xn = X509_get_subject_name(x);
        len = i2d_X509_NAME(xn, NULL);
        if ((p = malloc((size_t) len)) == NULL)
            goto oom;
        krb5_cas[i]->subjectName.data = (char *)p;
        i2d_X509_NAME(xn, &p);
        krb5_cas[i]->subjectName.length = len;

         
        krb5_cas[i]->issuerAndSerialNumber.length = 0;
        krb5_cas[i]->issuerAndSerialNumber.magic = 0;
        krb5_cas[i]->issuerAndSerialNumber.data = NULL;

        is = PKCS7_ISSUER_AND_SERIAL_new();
        if (is == NULL)
            goto oom;
        X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
        ASN1_INTEGER_free(is->serial);
        is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x));
        if (is->serial == NULL)
            goto oom;
        len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
        p = malloc(len);
        if (p == NULL)
            goto oom;
        krb5_cas[i]->issuerAndSerialNumber.data = (char *)p;
        i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
        krb5_cas[i]->issuerAndSerialNumber.length = len;

         
        krb5_cas[i]->subjectKeyIdentifier.length = 0;
        krb5_cas[i]->subjectKeyIdentifier.magic = 0;
        krb5_cas[i]->subjectKeyIdentifier.data = NULL;

        if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
            ASN1_OCTET_STRING *ikeyid;

            ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
                                      NULL);
            if (ikeyid != NULL) {
                len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
                p = malloc(len);
                if (p == NULL)
                    goto oom;
                krb5_cas[i]->subjectKeyIdentifier.data = (char *)p;
                i2d_ASN1_OCTET_STRING(ikeyid, &p);
                krb5_cas[i]->subjectKeyIdentifier.length = len;
                ASN1_OCTET_STRING_free(ikeyid);
            }
        }
        PKCS7_ISSUER_AND_SERIAL_free(is);
        is = NULL;
    }

    *ids = krb5_cas;
    return 0;

oom:
    free_krb5_external_principal_identifier(&krb5_cas);
    PKCS7_ISSUER_AND_SERIAL_free(is);
    return ENOMEM;
}