Patrick Powell wrote:
> 
> Ah... an expert.
> 
> OK. Welcome to the joys of "certificate revocation" and 'accept
> users with certs signed only by this 'signer' cert'
> 
> Certificate revocation is ugly.
> I looked at the way that mod_ssl in Apache did it and was taken
> aback.
> You need to:
> a)  set up a 'certificate revocation list/directory MIT Hash Files Yet'
> b)  Do magic to read the certs in the CRL/CRL Dir
> c)  Write/add a callback so that on connection/ssl authentication
>     you check to see if the user/signer is in the revocation list.
>     (... and there are all sorts of nasty things...)
> 
> Don't forget to use the 'cca' script to 'revoke' the cert,
> put the cert into a revocation directory, and create the hash
> to it OR append it to a file of revoked certs.
> 
> So...  I can go through the pain and agony of handling this a la mod_ssl
> in Apache,  or I can ... cheat.
> 
> Now I just know that you will say 'write your own authentication callback'.
> Nope.  I looked at that code in the SSL distribution and it was... ugly.
> And that is coming from me who has written some code that was so ugly
> that monitors died before they would display it.
> 
> But If I could simply EXTRACT the cert information, then I could
> do something more audatious:
> 
> Idea:  use the LPRng lpd.perms and add a new option: AUTH_CHAIN
> 
> This would have a value of all subject name and all of the signers
> of a cert:
> 
> h110: {33} % openssl x509 -noout -subject -issuer -in signer1.crt
> subject= /C=US/ST=California/L=San 
>[EMAIL PROTECTED]
> issuer= /C=US/ST=California/L=San Diego/O=Astart/OU=Certificate Authority/CN=Astart 
>[EMAIL PROTECTED]
> h110: {34} % openssl x509 -noout -subject -issuer -in user1.crt
> issuer= /C=US/ST=California/L=San 
>[EMAIL PROTECTED]
> subject= /C=US/ST=California/L=San 
>[EMAIL PROTECTED]
> 
> AUTH_CHAIN=
> /C=US/ST=California/L=San [EMAIL PROTECTED]
> /C=US/ST=California/L=San 
>[EMAIL PROTECTED]
> /C=US/ST=California/L=San Diego/O=Astart/OU=Certificate Authority/CN=Astart 
>[EMAIL PROTECTED]
> 
> (line folded to fit)
> 
> This would represent the signature chain starting from the
> bottom of the certificate and going to the top.
> 
> Now you could 'cancel' a user with subject: '/.../ON=jsmith/...' using:
> REJECT AUTHTYPE=SSL AUTH_CHAIN=*/ON=jsmith/*
> 
> You probably would put these into a file, say /etc/lpd/ssl/revoke.list
> 
> REJECT AUTHTYPE=SSL AUTH_CHAIN=</etc/lpd/ssl/revoke.list
> 
> You can only accept certs signed by ON=jsmith using:
> 
> REJECT AUTHTYPE=SSL NOT AUTH_CHAIN=*/ON=jsmith/*
> 
> Now, I know that the SSL/OpenSSL community is having the dry
> heaves at this method (I feel kinda queasy myself).  But this
> does have the benefit of allowing you to require a cert to have
> a specific signer... and instead of enumerating all of the
> allowed certs, to delegate this.
> 
> Patrick Powell                 Astart Technologies,
> [EMAIL PROTECTED]            9475 Chesapeake Drive, Suite D,
> Network and System             San Diego, CA 92123
>   Consulting                   858-874-6543 FAX 858-279-8424
> LPRng - Print Spooler (http://www.lprng.com)
> 
....

If I understand your way to do the certificate checking, it's completely failing, 
because you don't use any of the mechanism along the
certificate infrastructure; so checking only a textual part of the certificate, as the 
subject or the issuer, can lead anyone to forge a
certificate for the connection.
The best way to do the job is:

1) A directory with an hashed list of accepted CAs
2) A directory with an hashed list of CRL (ideally one for every CA)

then check every certificate with a "standard" callback function, you don't need to 
change at all (I've attached a cbf as a full sample,
grabbed an adjusted from apps/s_cb.c on openssl distribution)

Then if the ssl connection is ok, you have certainly a "legal" certificate passed by 
the client (as the relative ca chain is legal...).
You can now add every check in the code based on the subject or the issuer, as you 
need.

The issuer can be catched with these lines (grabbed from apps/s_server.c on openssl 
distribution)

   peer=SSL_get_peer_certificate(con);
   X509_NAME_oneline(X509_get_issuer_name(peer),buf,BUFSIZ);

where con is the SSL connection handler (SSL*) and buf is a buffer BUFSIZ bytes long, 
sufficient to hold the issuer string.

Hope this help.

where peer is an X509 certi

Dott. Sergio Rabellino 

 Technical Staff
 Department of Computer Science
 University of Torino (Italy)
 Member of the Internet Society

http://www.di.unito.it/~rabser
Tel. +39-0116706701
Fax. +39-011751603
#include <stdio.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>

int verify_depth=0;
int verify_error=X509_V_OK;

int verify_callback(int ok, X509_STORE_CTX *ctx)
        {
        char buf[256];
        X509 *err_cert;
        int err,depth;

        err_cert=X509_STORE_CTX_get_current_cert(ctx);
        err=    X509_STORE_CTX_get_error(ctx);
        depth=  X509_STORE_CTX_get_error_depth(ctx);

        X509_NAME_oneline(X509_get_subject_name(err_cert),buf,256);
        if (!ok)
                {
                if (verify_depth >= depth)
                        {
                        ok=1;
                        verify_error=X509_V_OK;
                        }
                else
                        {
                        ok=0;
                        verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG;
                        }
                }
        switch (ctx->error)
                {
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
                X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
                break;
        case X509_V_ERR_CERT_NOT_YET_VALID:
        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
                break;
        case X509_V_ERR_CERT_HAS_EXPIRED:
        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
                break;
                }
        return(ok);
        }

Reply via email to