long Condor_Auth_SSL :: post_connection_check(SSL *ssl, int /* role */ )
{
	X509      *cert;
		/* These are removed, see below.
    X509_NAME *subj;
    char      data[256];
    int       extcount;
    int       ok = 0;
		*/
    ouch("post_connection_check.\n");
 
    /* Checking the return from SSL_get_peer_certificate here is not
     * strictly necessary.  With our example programs, it is not
     * possible for it to return NULL.  However, it is good form to
     * check the return since it can return NULL if the examples are
     * modified to enable anonymous ciphers or for the server to not
     * require a client certificate.
     * (Comment from book.  -Ian)
     */
    cert = SSL_get_peer_certificate(ssl);
    if( cert == NULL ) {
        dprintf(D_SECURITY,"SSL_get_peer_certificate returned null.\n" );
        goto err_occured;
    }
    dprintf(D_SECURITY,"SSL_get_peer_certificate returned data.\n" );

    /* What follows is working code based on examples from the book
       "Network Programming with OpenSSL."  The point of this code
       is to determine that the certificate is a valid host certificate
       for the server side.  Zach says that this will be done by
       the caller of the authenticate method, so we just ignore it.
       However, since it's more complicated than simply extracting
       the CN and comparing it to the host name, I'm leaving it in
       here so we can refer to it if needed.

       TODO: Does globus do this?  Do we need to do it?

       TODO: The caller is probably going to want the DN, we should
       extract it here.
       
       -Ian
       
    if(role == AUTH_SSL_ROLE_SERVER) {
        X509_free( cert );
        ouch("Server role: returning from post connection check.\n");
        return SSL_get_verify_result( ssl );
    } // else ROLE_CLIENT: check dns (arg 2) against cn
    if ((extcount = X509_get_ext_count(cert)) > 0) {
        int i;
        for (i = 0;  i < extcount;  i++) {
            const char              *extstr;
            X509_EXTENSION    *ext;
            ASN1_OBJECT *foo;

            ext = X509_get_ext(cert, i);
            foo = X509_EXTENSION_get_object(ext);
            int bar = OBJ_obj2nid(foo);
            extstr = OBJ_nid2sn(bar);
            
            if (!strcmp(extstr, "subjectAltName")) {
                int                  j;
                unsigned char        *data;
                STACK_OF(CONF_VALUE) *val;
                CONF_VALUE           *nval;
                X509V3_EXT_METHOD    *meth;
                void                 *ext_str = NULL;
 
                if (!(meth = X509V3_EXT_get(ext)))
                    break;
                data = ext->value->data;
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)

                if (meth->it)
                    ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
                                            ASN1_ITEM_ptr(meth->it));
                else
                    ext_str = meth->d2i(NULL, &data, ext->value->length);
#else
                ext_str = meth->d2i(NULL, &data, ext->value->length);
#endif
                val = meth->i2v(meth, ext_str, NULL);
                for (j = 0;  j < sk_CONF_VALUE_num(val);  j++) {
                    nval = sk_CONF_VALUE_value(val, j);
                    if (!strcmp(nval->name, "DNS")
                        && !strcmp(nval->value, host)) {
                        ok = 1;
                        break;
                    }
                }
            }
            if (ok)
                break;
        }
    }
    
    if (!ok && (subj = X509_get_subject_name(cert)) &&
        X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0)
    {
        data[255] = 0;
        dprintf(D_SECURITY, "Common Name: '%s'; host: '%s'\n", data, host);
        if (strcasecmp(data, host) != 0)
            goto err_occured;
    }
    if( cert != NULL ) {
        dprintf(D_SECURITY,"Client: Got non null cert.\n" );
    }
    */
    ouch("Returning SSL_get_verify_result.\n");
    
    X509_free(cert);
    return SSL_get_verify_result(ssl);
 
err_occured:
    if (cert)
        X509_free(cert);
    return X509_V_ERR_APPLICATION_VERIFICATION;
}

long Condor_Auth_SSL :: post_connection_check(SSL *ssl, int /* role */ )
{
	X509      *cert;
		/* These are removed, see below.
    X509_NAME *subj;
    char      data[256];
    int       extcount;
    int       ok = 0;
		*/
    ouch("post_connection_check.\n");
 
    /* Checking the return from SSL_get_peer_certificate here is not
     * strictly necessary.  With our example programs, it is not
     * possible for it to return NULL.  However, it is good form to
     * check the return since it can return NULL if the examples are
     * modified to enable anonymous ciphers or for the server to not
     * require a client certificate.
     * (Comment from book.  -Ian)
     */
    cert = SSL_get_peer_certificate(ssl);
    if( cert == NULL ) {
        dprintf(D_SECURITY,"SSL_get_peer_certificate returned null.\n" );
        goto err_occured;
    }
    dprintf(D_SECURITY,"SSL_get_peer_certificate returned data.\n" );

    /* What follows is working code based on examples from the book
       "Network Programming with OpenSSL."  The point of this code
       is to determine that the certificate is a valid host certificate
       for the server side.  Zach says that this will be done by
       the caller of the authenticate method, so we just ignore it.
       However, since it's more complicated than simply extracting
       the CN and comparing it to the host name, I'm leaving it in
       here so we can refer to it if needed.

       TODO: Does globus do this?  Do we need to do it?

       TODO: The caller is probably going to want the DN, we should
       extract it here.
       
       -Ian
       
    if(role == AUTH_SSL_ROLE_SERVER) {
        X509_free( cert );
        ouch("Server role: returning from post connection check.\n");
        return SSL_get_verify_result( ssl );
    } // else ROLE_CLIENT: check dns (arg 2) against cn
    if ((extcount = X509_get_ext_count(cert)) > 0) {
        int i;
        for (i = 0;  i < extcount;  i++) {
            const char              *extstr;
            X509_EXTENSION    *ext;
            ASN1_OBJECT *foo;

            ext = X509_get_ext(cert, i);
            foo = X509_EXTENSION_get_object(ext);
            int bar = OBJ_obj2nid(foo);
            extstr = OBJ_nid2sn(bar);
            
            if (!strcmp(extstr, "subjectAltName")) {
                int                  j;
                unsigned char        *data;
                STACK_OF(CONF_VALUE) *val;
                CONF_VALUE           *nval;
                X509V3_EXT_METHOD    *meth;
                void                 *ext_str = NULL;
 
                if (!(meth = X509V3_EXT_get(ext)))
                    break;
                data = ext->value->data;
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)

                if (meth->it)
                    ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
                                            ASN1_ITEM_ptr(meth->it));
                else
                    ext_str = meth->d2i(NULL, &data, ext->value->length);
#else
                ext_str = meth->d2i(NULL, &data, ext->value->length);
#endif
                val = meth->i2v(meth, ext_str, NULL);
                for (j = 0;  j < sk_CONF_VALUE_num(val);  j++) {
                    nval = sk_CONF_VALUE_value(val, j);
                    if (!strcmp(nval->name, "DNS")
                        && !strcmp(nval->value, host)) {
                        ok = 1;
                        break;
                    }
                }
            }
            if (ok)
                break;
        }
    }
    
    if (!ok && (subj = X509_get_subject_name(cert)) &&
        X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0)
    {
        data[255] = 0;
        dprintf(D_SECURITY, "Common Name: '%s'; host: '%s'\n", data, host);
        if (strcasecmp(data, host) != 0)
            goto err_occured;
    }
    if( cert != NULL ) {
        dprintf(D_SECURITY,"Client: Got non null cert.\n" );
    }
    */
    ouch("Returning SSL_get_verify_result.\n");
    
    X509_free(cert);
    return SSL_get_verify_result(ssl);
 
err_occured:
    if (cert)
        X509_free(cert);
    return X509_V_ERR_APPLICATION_VERIFICATION;
}
