Matthew Rodriguez DSD staff wrote:

Richard Levitte - VMS Whacker wrote:

In message <[EMAIL PROTECTED]> on Tue, 15 Mar 2005 14:36:57 -0800, Matt Rodriguez <[EMAIL PROTECTED]> said:

MKRodriguez> I've looking at the tests in the snapshots for 0.9.8. I
MKRodriguez> am trying to figure out what functionality regarding
MKRodriguez> proxy certificates has been implemented.

Most importantly:

- verification, as a change in the functions used by
  X509_verify_cert()
- parsing of proxy certificate extensions in a configuration file.
- implementation of internal ASN.1 structures for
  ProxyCertInfoExtensions and ProxyPolicy.

MKRodriguez> Here are 2 things that I am looking for:
MKRodriguez> MKRodriguez> 1) I need to be able to do a handshake using proxy
MKRodriguez> certificates for client and server authentication.


If you don't care about the rights assigned with the policy
extensions, you can do it by just setting the certificate to use and
the whole chain properly.  A "catch" is the the whole chain, CA root
cert, CA intermediate certs, EE cert and intermediate proxy certs are
view as the issuing chain, and should be part of whatever you use as
your CA certificate bundle.



Reflecting on the problem a little more, I think I see what you mean by the catch.
My EE cert does not have the ability to sign certificates like my one
of my CA certs is able to do. But openssl is treating my EE like it is a CA.


Here is the KeyUsage on my EE cert
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment


Here is the KeyUsage on one of my CA certs
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, Certificate Sign, CRL Sign



I think this is where the error is coming from in X509_check_issued. This is why this call is returning true ku_reject(issuer, KU_KEY_CERT_SIGN).

Is my thinking correct on this matter?

Matt

This is what I need to do. I've been able to do it with a certificate
chain that consists of my EE, an intermediate CA cert, self signed CA cert.
But I have not been able to do it with this certificate chain
Proxy certificate, EE, intermediate CA cert, self signed CA cert.


I've been using gdb to trace through the X509_verify_cert function,
The problem seems to be the it cannot find the issuer of my proxy
certificate. This call happens on line 158 in x509_vfy.c. Since it can't find
the issuer it can't build the cert_chain, and later a check for NULL on chain_ss
is true so the X509_verify_cert functions exits with an error.


Ok, so I stepped through the find_issuer code path where it was calling check_issued
on the proxy certificate and the EE cert, which should return true, because the EE cert was the
issuer for my proxy cert. I found that it was returning an error at the end of the check_issued
function in this code block.


Specifically else if condition was true. ku_reject(issuer, KU_KEY_CERT_SIGN)
I think this means that my EE cert is not allowed to sign for other certs. Is that
correct?


   if(subject->ex_flags & EXFLAG_PROXY)
       {
       if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
           return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
       }
   else if(ku_reject(issuer, KU_KEY_CERT_SIGN))
       return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;

I've attached 2 programs, one is a server who presents a certificate chain. I'm using the
SSL_CTX_use_certificate_chain_file to parse in the cert chain. The client calls
SSL_CTX_load_verify_locations which points at a directory where the CA certs are kept.
The client verifies the server, and has its own verify_cb, the server does not verify the client.


One final note, to create the proxy the certificate I've used a globus program called grid-proxy-init.
I'm not sure if you are familiar with that or not.


Thanks for your help, I'm looking over the your proxy_certificates.txt documentation, if I see anything
that could be clarified I'll let you know.


Thanks for you help,
Matt Rodriguez


Here's my stack, which may help
#0 X509_check_issued (issuer=0x8068840, subject=0x8067b58) at v3_purp.c:640
#1 0xb7f81c04 in check_issued (ctx=0xbfffe5f0, x=0x8067b58, issuer=0x8068840)
at x509_vfy.c:351
#2 0xb7f81bbe in find_issuer (ctx=0xbfffe5f0, sk=0x806a3d8, x=0x8067b58)
at x509_vfy.c:340
#3 0xb7f81681 in X509_verify_cert (ctx=0xbfffe5f0) at x509_vfy.c:158
#4 0xb7e986d7 in ssl_verify_cert_chain (s=0x8056aa0, sk=0x8067b28)
at ssl_cert.c:515
#5 0xb7e871b9 in ssl3_get_server_certificate (s=0x8056aa0) at s3_clnt.c:862
#6 0xb7e86040 in ssl3_connect (s=0x8056aa0) at s3_clnt.c:296
#7 0xb7e94cf1 in SSL_connect (s=0x8056aa0) at ssl_lib.c:841
#8 0x08049034 in main (argc=1, argv=0xbfffe824) at client.c:38


If you need to care about the proxy policy rights and you're using
SSL, you should read docs/HOWTO/proxy_certificates.txt, which explains
how you should set up SSL verification callbacks to do that properly,
with an example and all.

MKRodriguez> 2) I need to be able to verify a proxy certificate, given
MKRodriguez>    the certificate and certificate chain.

X509_verify_cert()

MKRodriguez> It looks like the testsslproxy does the tests the first
MKRodriguez> requirement, but not the second.

Maybe I misunderstand you, but I'm quite sure it does both.

MKRodriguez> Does anybody know if the functionality I want has been
MKRodriguez> implemented? What function calls will I have to make
MKRodriguez> to do this, or what files should I be looking in?

I know, since I implemented the stuff.  I hope what I said above is
satisfactory.  If not, I'm up for talking about it.  Maybe I need to
document yet a bit better?

Cheers,
Richard




------------------------------------------------------------------------

#include "common.h"

int
main(int argc, char **argv){
int fd, ret = 1, filetype = SSL_FILETYPE_PEM; SSL_CTX* ctx = NULL;
SSL *ssl = NULL;
OpenSSL_add_all_ciphers();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();


RAND_seed(SEED, strlen(SEED)); ctx = SSL_CTX_new(TLSv1_client_method()); if (ctx == NULL) {
ERR_print_errors_fp(stderr);
goto bad;
} SSL_CTX_set_info_callback(ctx, (void (*)(const SSL*, int, int)) trace); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); /*SSL_CTX_set_verify_depth(ctx, 4);*/ /*ret = SSL_CTX_load_verify_locations(ctx, "/home/u5/mateo/.globus/usercert.pem",NULL);*/
ret = SSL_CTX_load_verify_locations(ctx, NULL,"/home/u5/mateo/.globus/certificates");
if (!ret) {
ERR_print_errors_fp(stderr);
goto bad;
} fd = doConnect();


 if (fd == -1) {
  printf("UNABLE TO CONNECT TO SERVER %s at port %d\n", HOST, PORT);
  goto bad;
 }

ssl = SSL_new(ctx); SSL_set_fd(ssl, fd);

if (SSL_connect(ssl) <= 0) {
ERR_print_errors_fp(stderr);
goto bad;
}


if (SSL_shutdown(ssl) <= 0) {
ERR_print_errors_fp(stderr);
goto bad;
} ret = 0;


bad:
 if (ssl) {
   SSL_free(ssl);
 }

 if (fd != -1) {
   close(fd);
 }

 if (ctx) {
   SSL_CTX_free(ctx);
 }

exit(ret);
}


------------------------------------------------------------------------

#include "common.h"

int main() {
int fd, sd, ret, filetype = SSL_FILETYPE_PEM;
SSL_CTX* ctx; /*char * keyfile = "/home/mateo/.globus/userkey.pem";
char * certchainfile = "/tmp/cert_chain2.tmp"; char * keyfile = "./client.pkey";
char * certfile = "./client.cert";
char * cafile = "./CA.cert"; */
char * keyfile = "/tmp/proxykey.tmp"; char * certchainfile = "/tmp/proxycertchain.tmp";


OpenSSL_add_all_ciphers();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
RAND_seed(SEED,strlen(SEED));



ctx = SSL_CTX_new(TLSv1_server_method());

 if (ctx == NULL) {
   ERR_print_errors_fp(stderr);
   exit(1);
 }

SSL_CTX_set_info_callback(ctx, (void (*)(const SSL*, int, int)) trace); SSL_CTX_set_verify_depth(ctx, 4);
ret = SSL_CTX_use_PrivateKey_file(ctx, keyfile, filetype);
if (!ret) {
ERR_print_errors_fp(stderr);
exit(1);
}
ret = SSL_CTX_use_certificate_chain_file(ctx, certchainfile); if (!ret) { ERR_print_errors_fp(stderr);
exit(1);
}


 printf("CONFIGURING SSL SERVER CONTEXT DONE\n");

 fd = doBind();

 if (fd == -1) {
   printf("bind failed for port %d\n", PORT);
   exit(1);
 }

 if (doListen(fd) == -1) {
   printf("listen failed");
   exit(1);
 }

while (1) { SSL* ssl;

   sd = doAccept(fd);

   if (sd == -1) {
     break;
   }

   printf("SERVER ACCEPTED TCP CONNECTION: %d\n", sd);

ssl = SSL_new(ctx);
if (!ssl) {
close(sd);
ERR_print_errors_fp(stderr);
}


   SSL_set_fd(ssl,sd);

if (SSL_accept(ssl) <= 0) {
ERR_print_errors_fp(stderr);
} else { SSL_free(ssl);
close(sd);
}
}
return 0;
}


------------------------------------------------------------------------

#include "common.h"

int
verify_cb(int ok, X509_STORE_CTX *x509_ctx){
int errnum, errdepth;
X509 *err_cert;
char subject_buf[256];
char issuer_buf[256];
printf("in verify cb\n");
errnum = X509_STORE_CTX_get_error(x509_ctx);
errdepth = X509_STORE_CTX_get_error_depth(x509_ctx);
err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
X509_NAME_oneline(X509_get_subject_name(err_cert), subject_buf, 256);
X509_NAME_oneline(X509_get_issuer_name(err_cert), issuer_buf, 256);
printf("subject is %s\n", subject_buf);
printf("issuer is %s\n", issuer_buf);
if (errnum){
ERR_print_errors_fp(stderr); }
printf("errnum %d\n", errnum);
printf("errdepth %d\n", errdepth);
printf("ok %d\n", ok);
return ok;
}


void trace(SSL* s, int where, int ret) {
char* str;
int w;


 w = where & ~SSL_ST_MASK;

 if (w & SSL_ST_CONNECT) str = "SSL_connect";
 else if (w & SSL_ST_ACCEPT) str = "SSL_accept";
 else str = "undefined";

 if (where & SSL_CB_LOOP) {
   switch(SSL_state((SSL*) s)) {
     default:
       break;
   }

   printf("%s:%s\n", str, SSL_state_string_long(s));
 } else if (where & SSL_CB_ALERT) {
   str=(char*) ((where & SSL_CB_READ)? "read":"write");
   printf("SSL3 alert %s:%s:%s\n",
          str,
          SSL_alert_type_string_long(ret),
          SSL_alert_desc_string_long(ret));
 } else if (where & SSL_CB_EXIT) {
   if (ret == 0) {
     printf("%s:failed in %s\n", str,SSL_state_string_long(s));
   } else if (ret < 0) {
     printf("%s:error in %s\n", str,SSL_state_string_long(s));
   }
 }
}

int
doListen(int fd) {
 if (listen(fd, 5) < 0) {
   return -1;
 }

 return fd;
}

int doBind() {
struct sockaddr_in address;
int sock_fd;
int on=1;


 if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
   return -1;
 }


if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char*) &on,sizeof(on)) < 0) { return -1; }

 address.sin_family = AF_INET;
 address.sin_port = htons(PORT);
 address.sin_addr.s_addr = htonl(INADDR_ANY);

 if (bind(sock_fd, (struct sockaddr*) &address, sizeof(address)) < 0) {
   return -1;
 }

 return sock_fd;
}

int
doAccept(int fd) { struct sockaddr_in address;
socklen_t len = sizeof(address);
int sd = accept(fd, (struct sockaddr*) &address,&len);


 if (sd < 0) {
   return -1;
 }

 return sd;
}

int
doConnect() {
 struct sockaddr_in address;
 struct hostent* hp;
 int sock_fd;

 if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
   return -1;
 }

 hp = gethostbyname(HOST);

 if (!hp) {
   return -1;
 }

 address.sin_family=AF_INET;
 address.sin_port=htons((unsigned short) PORT);
 memcpy(&address.sin_addr, *hp->h_addr_list, hp->h_length);

 if (connect(sock_fd, (struct sockaddr *) &address, sizeof(address))  < 0) {
   return -1;
 }

return sock_fd;
}



______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]

Reply via email to