diff --git a/httpd/proc.c b/httpd/proc.c index 30a2ee21c..3c897c98b 100644 --- a/httpd/proc.c +++ b/httpd/proc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Cameron Rich + * Copyright (c) 2007-2008, Cameron Rich * * All rights reserved. * @@ -137,6 +137,11 @@ static int procheadelem(struct connstruct *cn, char *buf) { cn->if_modified_since = tdate_parse(value); } + else if (strcmp(buf, "Expect:") == 0) + { + send_error(cn, 417); /* expectation failed */ + return 0; + } #ifdef CONFIG_HTTP_HAS_AUTHORIZATION else if (strcmp(buf, "Authorization:") == 0 && strncmp(value, "Basic ", 6) == 0) diff --git a/ssl/test/ssltest.c b/ssl/test/ssltest.c index f441f4038..d525e1a68 100644 --- a/ssl/test/ssltest.c +++ b/ssl/test/ssltest.c @@ -770,7 +770,7 @@ static int SSL_server_test( const char *private_key, const char *ca_cert, const char *password, - int axolotls_option) + int axtls_option) { int server_fd, ret = 0; SSL_CTX *ssl_ctx = NULL; @@ -791,10 +791,10 @@ static int SSL_server_test( if (private_key) { - axolotls_option |= SSL_NO_DEFAULT_KEY; + axtls_option |= SSL_NO_DEFAULT_KEY; } - if ((ssl_ctx = ssl_ctx_new(axolotls_option, SSL_DEFAULT_SVR_SESS)) == NULL) + if ((ssl_ctx = ssl_ctx_new(axtls_option, SSL_DEFAULT_SVR_SESS)) == NULL) { ret = SSL_ERROR_INVALID_KEY; goto error; @@ -1012,7 +1012,7 @@ int SSL_server_tests(void) /* this test should fail */ if (stat("../ssl/test/axTLS.x509_bad_before.pem", &stat_buf) >= 0) { - if ((ret = SSL_server_test("Bad Before Cert", + if ((ret = SSL_server_test("Error: Bad Before Cert", "-cipher RC4-SHA -tls1 " "-cert ../ssl/test/axTLS.x509_bad_before.pem " "-key ../ssl/test/axTLS.key_512.pem ", @@ -1028,7 +1028,7 @@ int SSL_server_tests(void) } /* this test should fail */ - if ((ret = SSL_server_test("Bad After Cert", + if ((ret = SSL_server_test("Error: Bad After Cert", "-cipher RC4-SHA -tls1 " "-cert ../ssl/test/axTLS.x509_bad_after.pem " "-key ../ssl/test/axTLS.key_512.pem ", @@ -1041,6 +1041,53 @@ int SSL_server_tests(void) printf("SSL server test \"%s\" passed\n", "Bad After Cert"); TTY_FLUSH(); + /* + * No trusted cert + */ + if ((ret = SSL_server_test("Error: No trusted certificate", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_512.pem " + "-key ../ssl/test/axTLS.key_512.pem ", + NULL, NULL, NULL, + NULL, NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) != + SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT)) + goto cleanup; + + printf("SSL server test \"%s\" passed\n", "No trusted certificate"); + TTY_FLUSH(); + + /* + * Self-signed (from the server) + */ + if ((ret = SSL_server_test("Error: Self-signed certificate (from server)", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_512.pem " + "-key ../ssl/test/axTLS.key_512.pem " + "-CAfile ../ssl/test/axTLS.ca_x509.pem ", + NULL, NULL, NULL, + NULL, NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) != + SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED)) + goto cleanup; + + printf("SSL server test \"%s\" passed\n", + "Self-signed certificate (from server)"); + TTY_FLUSH(); + + /* + * Self-signed (from the client) + */ + if ((ret = SSL_server_test("Self-signed certificate (from client)", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_512.pem " + "-key ../ssl/test/axTLS.key_512.pem ", + NULL, NULL, NULL, + "../ssl/test/axTLS.ca_x509.cer", + NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION))) + goto cleanup; + /* * Key in PEM format */ @@ -1434,13 +1481,12 @@ int SSL_client_tests(void) "-CAfile ../ssl/test/axTLS.ca_x509.pem " "-verify 1 ", NULL, DEFAULT_CLNT_OPTION, "../ssl/test/axTLS.key_1024", NULL, - "../ssl/test/axTLS.x509_1024.cer")) - != SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED)) + "../ssl/test/axTLS.x509_1024.cer"))) goto cleanup; /* Should get an "ERROR" from openssl (as the handshake fails as soon as * the certificate verification fails) */ - if ((ret = SSL_client_test("Expired cert (verify now) should fail!", + if ((ret = SSL_client_test("Error: Expired cert (verify now)", &ssl_ctx, "-cert ../ssl/test/axTLS.x509_bad_after.pem " "-key ../ssl/test/axTLS.key_512.pem", NULL, @@ -1452,10 +1498,9 @@ int SSL_client_tests(void) } printf("SSL client test \"Expired cert (verify now)\" passed\n"); - ret = 0; /* There is no "ERROR" from openssl */ - if ((ret = SSL_client_test("Expired cert (verify later) should fail!", + if ((ret = SSL_client_test("Error: Expired cert (verify later)", &ssl_ctx, "-cert ../ssl/test/axTLS.x509_bad_after.pem " "-key ../ssl/test/axTLS.key_512.pem", NULL, @@ -1467,7 +1512,6 @@ int SSL_client_tests(void) } printf("SSL client test \"Expired cert (verify later)\" passed\n"); - ret = 0; cleanup: diff --git a/ssl/tls1.c b/ssl/tls1.c index c98cd7a5f..24710b923 100755 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -386,7 +386,6 @@ int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len) int ret = SSL_ERROR_NO_CERT_DEFINED; int i = 0; int offset; - X509_CTX *cert = NULL; CA_CERT_CTX *ca_cert_ctx; if (ssl_ctx->ca_cert_ctx == NULL) @@ -409,22 +408,6 @@ int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len) if ((ret = x509_new(buf, &offset, &ca_cert_ctx->cert[i]))) goto error; - /* make sure the cert is valid */ - cert = ca_cert_ctx->cert[i]; - SSL_CTX_LOCK(ssl_ctx->mutex); - - if ((ret = x509_verify(ca_cert_ctx, cert)) != X509_VFY_ERROR_SELF_SIGNED) - { - SSL_CTX_UNLOCK(ssl_ctx->mutex); - x509_free(cert); /* get rid of it */ - ca_cert_ctx->cert[i] = NULL; -#ifdef CONFIG_SSL_FULL_MODE - printf("Error: %s\n", x509_display_error(ret)); TTY_FLUSH(); -#endif - goto error; - } - - SSL_CTX_UNLOCK(ssl_ctx->mutex); len -= offset; ret = SSL_OK; /* ok so far */ @@ -1751,6 +1734,7 @@ int process_certificate(SSL *ssl, X509_CTX **x509_ctx) goto error; } + DISPLAY_CERT(ssl, *chain); chain = &((*chain)->next); offset += cert_size; } @@ -1763,7 +1747,6 @@ int process_certificate(SSL *ssl, X509_CTX **x509_ctx) ret = ssl_verify_cert(ssl); } - DISPLAY_CERT(ssl, *x509_ctx); ssl->next_state = is_client ? HS_SERVER_HELLO_DONE : HS_CLIENT_KEY_XCHG; ssl->dc->bm_proc_index += offset; error: diff --git a/ssl/tls1_svr.c b/ssl/tls1_svr.c index 3a79c31c9..6f5dedddf 100644 --- a/ssl/tls1_svr.c +++ b/ssl/tls1_svr.c @@ -378,6 +378,12 @@ static int process_client_key_xchg(SSL *ssl) int offset = 4; int ret = SSL_OK; + if (rsa_ctx == NULL) + { + ret = SSL_ERROR_NO_CERT_DEFINED; + goto error; + } + DISPLAY_RSA(ssl, rsa_ctx); /* is there an extra size field? */ diff --git a/ssl/x509.c b/ssl/x509.c index bd25da61c..db8fda6c4 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -251,11 +251,11 @@ static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, * Do some basic checks on the certificate chain. * * Certificate verification consists of a number of checks: - * - A root certificate exists in the certificate store. * - The date of the certificate is after the start date. * - The date of the certificate is before the finish date. - * - The certificate chain is valid. + * - A root certificate exists in the certificate store. * - That the certificate(s) are not self-signed. + * - The certificate chain is valid. * - The signature of the certificate is valid. */ int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) @@ -263,44 +263,26 @@ int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) int ret = X509_OK, i = 0; bigint *cert_sig; X509_CTX *next_cert = NULL; - BI_CTX *ctx; + BI_CTX *ctx = NULL; bigint *mod = NULL, *expn = NULL; - struct timeval tv; int match_ca_cert = 0; + struct timeval tv; uint8_t is_self_signed = 0; - if (cert == NULL || ca_cert_ctx == NULL) + if (cert == NULL) { ret = X509_VFY_ERROR_NO_TRUSTED_CERT; goto end_verify; } - /* last cert in the chain - look for a trusted cert */ - if (cert->next == NULL && ca_cert_ctx) + /* a self-signed certificate that is not in the CA store - use this + to check the signature */ + if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0) { - while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i]) - { - if (asn1_compare_dn(cert->ca_cert_dn, - ca_cert_ctx->cert[i]->cert_dn) == 0) - { - match_ca_cert = 1; - next_cert = ca_cert_ctx->cert[i]; - break; - } - - i++; - } - - /* trusted cert not found */ - if (match_ca_cert == 0) - { - ret = X509_VFY_ERROR_NO_TRUSTED_CERT; - goto end_verify; - } - } - else - { - next_cert = cert->next; + is_self_signed = 1; + ctx = cert->rsa_ctx->bi_ctx; + mod = cert->rsa_ctx->m; + expn = cert->rsa_ctx->e; } gettimeofday(&tv, NULL); @@ -319,61 +301,76 @@ int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) goto end_verify; } - ctx = cert->rsa_ctx->bi_ctx; + next_cert = cert->next; - /* check for self-signing */ - if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0) + /* last cert in the chain - look for a trusted cert */ + if (next_cert == NULL) { - is_self_signed = 1; - mod = cert->rsa_ctx->m; - expn = cert->rsa_ctx->e; + if (ca_cert_ctx != NULL) + { + /* go thu the CA store */ + while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i]) + { + if (asn1_compare_dn(cert->ca_cert_dn, + ca_cert_ctx->cert[i]->cert_dn) == 0) + { + /* use this CA certificate for signature verification */ + match_ca_cert = 1; + ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx; + mod = ca_cert_ctx->cert[i]->rsa_ctx->m; + expn = ca_cert_ctx->cert[i]->rsa_ctx->e; + break; + } + + i++; + } + } + + /* couldn't find a trusted cert (& let self-signed errors be returned) */ + if (!match_ca_cert && !is_self_signed) + { + ret = X509_VFY_ERROR_NO_TRUSTED_CERT; + goto end_verify; + } } - else if (next_cert != NULL) + else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0) { + /* check the chain */ + ret = X509_VFY_ERROR_INVALID_CHAIN; + goto end_verify; + } + else /* use the next certificate in the chain for signature verify */ + { + ctx = next_cert->rsa_ctx->bi_ctx; mod = next_cert->rsa_ctx->m; expn = next_cert->rsa_ctx->e; - - /* check the chain integrity */ - if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0) - { - ret = X509_VFY_ERROR_INVALID_CHAIN; - goto end_verify; - } } - /* check the signature */ - if (mod != NULL) - { - cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, - bi_clone(ctx, mod), bi_clone(ctx, expn)); - - if (cert_sig && cert->digest) - { - if (bi_compare(cert_sig, cert->digest)) - { - ret = X509_VFY_ERROR_BAD_SIGNATURE; - } - - bi_free(ctx, cert_sig); - - if (ret) - goto end_verify; - } - else - { - ret = X509_VFY_ERROR_BAD_SIGNATURE; - goto end_verify; - } - } - - if (is_self_signed) + /* cert is self signed */ + if (!match_ca_cert && is_self_signed) { ret = X509_VFY_ERROR_SELF_SIGNED; goto end_verify; } + /* check the signature */ + cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, + bi_clone(ctx, mod), bi_clone(ctx, expn)); + + if (cert_sig && cert->digest) + { + if (bi_compare(cert_sig, cert->digest) != 0) + ret = X509_VFY_ERROR_BAD_SIGNATURE; + + + bi_free(ctx, cert_sig); + } + + if (ret) + goto end_verify; + /* go down the certificate chain using recursion. */ - if (ret == 0 && cert->next) + if (next_cert != NULL) { ret = x509_verify(ca_cert_ctx, next_cert); } @@ -441,7 +438,7 @@ void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx) if (ca_cert_ctx) { - printf("Verify:\t\t\t%s\n", + printf("Verify:\t\t\t\t%s\n", x509_display_error(x509_verify(ca_cert_ctx, cert))); } @@ -463,6 +460,9 @@ const char * x509_display_error(int error) { switch (error) { + case X509_OK: + return "Certificate verify successful"; + case X509_NOT_OK: return "X509 not ok"; diff --git a/www/index.html b/www/index.html index 1b9c8790f..aef66de8f 100755 --- a/www/index.html +++ b/www/index.html @@ -7087,7 +7087,7 @@ if (useJavaSaver)