X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fssltest.c;h=6949f9696bccc5594d6ef4909036bbe03f590cc0;hp=e384599fb17b35b71e91497529f7dfc621b29b1b;hb=3eeaab4bed46e3320947d0f609b82007b65b5a46;hpb=e9224c717711eefb30038c9b37c69795dda93c9a diff --git a/ssl/ssltest.c b/ssl/ssltest.c index e384599fb1..6949f9696b 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -116,9 +116,6 @@ #define _BSD_SOURCE 1 /* Or gethostname won't be declared properly on Linux and GNU platforms. */ -#define _XOPEN_SOURCE_EXTENDED 1 /* Or gethostname won't be declared properly - on Compaq platforms (at least with DEC C). - */ #include #include @@ -131,17 +128,40 @@ #define USE_SOCKETS #include "e_os.h" +#define _XOPEN_SOURCE 500 /* Or isascii won't be declared properly on + VMS (at least with DECompHP C). */ +#include + #include #include #include #include +#include #include +#ifndef OPENSSL_NO_ENGINE #include +#endif #include #include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif +#include + +#define _XOPEN_SOURCE_EXTENDED 1 /* Or gethostname won't be declared properly + on Compaq platforms (at least with DEC C). + Do not try to put it earlier, or IPv6 includes + get screwed... + */ + #ifdef OPENSSL_SYS_WINDOWS #include -#include "../crypto/bio/bss_file.c" #else #include OPENSSL_UNISTD #endif @@ -152,6 +172,9 @@ #elif defined(OPENSSL_SYS_WINCE) # define TEST_SERVER_CERT "\\OpenSSL\\server.pem" # define TEST_CLIENT_CERT "\\OpenSSL\\client.pem" +#elif defined(OPENSSL_SYS_NETWARE) +# define TEST_SERVER_CERT "\\openssl\\apps\\server.pem" +# define TEST_CLIENT_CERT "\\openssl\\apps\\client.pem" #else # define TEST_SERVER_CERT "../apps/server.pem" # define TEST_CLIENT_CERT "../apps/client.pem" @@ -159,8 +182,8 @@ /* There is really no standard for this, so let's assign some tentative numbers. In any case, these numbers are only for this test */ -#define COMP_RLE 1 -#define COMP_ZLIB 2 +#define COMP_RLE 255 +#define COMP_ZLIB 1 static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx); #ifndef OPENSSL_NO_RSA @@ -168,8 +191,15 @@ static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export,int keylength); static void free_tmp_rsa(void); #endif static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg); -#define APP_CALLBACK "Test Callback Argument" -static char *app_verify_arg = APP_CALLBACK; +#define APP_CALLBACK_STRING "Test Callback Argument" +struct app_verify_arg + { + char *string; + int app_verify; + int allow_proxy_certs; + char *proxy_auth; + char *proxy_cond; + }; #ifndef OPENSSL_NO_DH static DH *get_dh512(void); @@ -200,6 +230,9 @@ static void sv_usage(void) fprintf(stderr,"\n"); fprintf(stderr," -server_auth - check server certificate\n"); fprintf(stderr," -client_auth - do client authentication\n"); + fprintf(stderr," -proxy - allow proxy certificates\n"); + fprintf(stderr," -proxy_auth - set proxy policy rights\n"); + fprintf(stderr," -proxy_cond - experssion to test proxy policy rights\n"); fprintf(stderr," -v - more output\n"); fprintf(stderr," -d - debug output\n"); fprintf(stderr," -reuse - use session-id reuse\n"); @@ -298,7 +331,7 @@ static void lock_dbg_cb(int mode, int type, const char *file, int line) goto err; } - if (type < 0 || type > CRYPTO_NUM_LOCKS) + if (type < 0 || type >= CRYPTO_NUM_LOCKS) { errstr = "type out of bounds"; goto err; @@ -357,18 +390,21 @@ int main(int argc, char *argv[]) int tls1=0,ssl2=0,ssl3=0,ret=1; int client_auth=0; int server_auth=0,i; - int app_verify=0; + struct app_verify_arg app_verify_arg = + { APP_CALLBACK_STRING, 0, 0, NULL, NULL }; char *server_cert=TEST_SERVER_CERT; char *server_key=NULL; char *client_cert=TEST_CLIENT_CERT; char *client_key=NULL; +#ifndef OPENSSL_NO_ECDH char *named_curve = NULL; +#endif SSL_CTX *s_ctx=NULL; SSL_CTX *c_ctx=NULL; SSL_METHOD *meth=NULL; SSL *c_ssl,*s_ssl; int number=1,reuse=0; - long bytes=1L; + long bytes=256L; #ifndef OPENSSL_NO_DH DH *dh; int dhe1024 = 0, dhe1024dsa = 0; @@ -382,6 +418,7 @@ int main(int argc, char *argv[]) clock_t s_time = 0, c_time = 0; int comp = 0; COMP_METHOD *cm = NULL; + STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; verbose = 0; debug = 0; @@ -417,6 +454,16 @@ int main(int argc, char *argv[]) server_auth=1; else if (strcmp(*argv,"-client_auth") == 0) client_auth=1; + else if (strcmp(*argv,"-proxy_auth") == 0) + { + if (--argc < 1) goto bad; + app_verify_arg.proxy_auth= *(++argv); + } + else if (strcmp(*argv,"-proxy_cond") == 0) + { + if (--argc < 1) goto bad; + app_verify_arg.proxy_cond= *(++argv); + } else if (strcmp(*argv,"-v") == 0) verbose=1; else if (strcmp(*argv,"-d") == 0) @@ -541,7 +588,11 @@ int main(int argc, char *argv[]) } else if (strcmp(*argv,"-app_verify") == 0) { - app_verify = 1; + app_verify_arg.app_verify = 1; + } + else if (strcmp(*argv,"-proxy") == 0) + { + app_verify_arg.allow_proxy_certs = 1; } else { @@ -589,7 +640,14 @@ bad: if (cm != NULL) { if (cm->type != NID_undef) - SSL_COMP_add_compression_method(comp, cm); + { + if (SSL_COMP_add_compression_method(comp, cm) != 0) + { + fprintf(stderr, + "Failed to add compression method\n"); + ERR_print_errors_fp(stderr); + } + } else { fprintf(stderr, @@ -600,6 +658,19 @@ bad: ERR_print_errors_fp(stderr); } } + ssl_comp_methods = SSL_COMP_get_compression_methods(); + fprintf(stderr, "Available compression methods:\n"); + { + int j, n = sk_SSL_COMP_num(ssl_comp_methods); + if (n == 0) + fprintf(stderr, " NONE\n"); + else + for (j = 0; j < n; j++) + { + SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j); + fprintf(stderr, " %d: %s\n", c->id, c->name); + } + } #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) if (ssl2) @@ -657,36 +728,30 @@ bad: #ifndef OPENSSL_NO_ECDH if (!no_ecdhe) { - ecdh = EC_KEY_new(); - if (ecdh != NULL) - { - if (named_curve) - { - int nid = OBJ_sn2nid(named_curve); + int nid; - if (nid == 0) - { - BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); - EC_KEY_free(ecdh); - goto end; - } - - ecdh->group = EC_GROUP_new_by_nid(nid); - if (ecdh->group == NULL) - { - BIO_printf(bio_err, "unable to create curve (%s)\n", named_curve); - EC_KEY_free(ecdh); - goto end; - } + if (named_curve != NULL) + { + nid = OBJ_sn2nid(named_curve); + if (nid == 0) + { + BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); + goto end; } - - if (ecdh->group == NULL) - ecdh->group=EC_GROUP_new_by_nid(NID_sect163r2); + } + else + nid = NID_sect163r2; - SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); - SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE); - EC_KEY_free(ecdh); + ecdh = EC_KEY_new_by_curve_name(nid); + if (ecdh == NULL) + { + BIO_printf(bio_err, "unable to create curve\n"); + goto end; } + + SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); + SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE); + EC_KEY_free(ecdh); } #else (void)no_ecdhe; @@ -732,20 +797,14 @@ bad: SSL_CTX_set_verify(s_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); - if (app_verify) - { - SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); - } + SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, &app_verify_arg); } if (server_auth) { BIO_printf(bio_err,"server authentication\n"); SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, verify_callback); - if (app_verify) - { - SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); - } + SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback, &app_verify_arg); } { @@ -824,7 +883,9 @@ end: #ifndef OPENSSL_NO_RSA free_tmp_rsa(); #endif +#ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); +#endif CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); ERR_remove_state(0); @@ -1322,8 +1383,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) { if (c_write) { - j=(cw_num > (long)sizeof(cbuf)) - ?sizeof(cbuf):(int)cw_num; + j = (cw_num > (long)sizeof(cbuf)) ? + (int)sizeof(cbuf) : (int)cw_num; i=BIO_write(c_bio,cbuf,j); if (i < 0) { @@ -1453,8 +1514,8 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count) } else { - j=(sw_num > (long)sizeof(sbuf))? - sizeof(sbuf):(int)sw_num; + j = (sw_num > (long)sizeof(sbuf)) ? + (int)sizeof(sbuf) : (int)sw_num; i=BIO_write(s_bio,sbuf,j); if (i < 0) { @@ -1525,6 +1586,22 @@ err: return(ret); } +static int get_proxy_auth_ex_data_idx(void) + { + static volatile int idx = -1; + if (idx < 0) + { + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + if (idx < 0) + { + idx = X509_STORE_CTX_get_ex_new_index(0, + "SSLtest for verify callback", NULL,NULL,NULL); + } + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + } + return idx; + } + static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) { char *s,buf[256]; @@ -1534,42 +1611,467 @@ static int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) if (s != NULL) { if (ok) - fprintf(stderr,"depth=%d %s\n",ctx->error_depth,buf); + fprintf(stderr,"depth=%d %s\n", + ctx->error_depth,buf); else + { fprintf(stderr,"depth=%d error=%d %s\n", ctx->error_depth,ctx->error,buf); + } } if (ok == 0) { + fprintf(stderr,"Error string: %s\n", + X509_verify_cert_error_string(ctx->error)); switch (ctx->error) { case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + fprintf(stderr," ... ignored.\n"); ok=1; } } + if (ok == 1) + { + X509 *xs = ctx->current_cert; +#if 0 + X509 *xi = ctx->current_issuer; +#endif + + if (xs->ex_flags & EXFLAG_PROXY) + { + unsigned int *letters = + X509_STORE_CTX_get_ex_data(ctx, + get_proxy_auth_ex_data_idx()); + + if (letters) + { + int found_any = 0; + int i; + PROXY_CERT_INFO_EXTENSION *pci = + X509_get_ext_d2i(xs, NID_proxyCertInfo, + NULL, NULL); + + switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage)) + { + case NID_Independent: + /* Completely meaningless in this + program, as there's no way to + grant explicit rights to a + specific PrC. Basically, using + id-ppl-Independent is the perfect + way to grant no rights at all. */ + fprintf(stderr, " Independent proxy certificate"); + for (i = 0; i < 26; i++) + letters[i] = 0; + break; + case NID_id_ppl_inheritAll: + /* This is basically a NOP, we + simply let the current rights + stand as they are. */ + fprintf(stderr, " Proxy certificate inherits all"); + break; + default: + s = (char *) + pci->proxyPolicy->policy->data; + i = pci->proxyPolicy->policy->length; + + /* The algorithm works as follows: + it is assumed that previous + iterations or the initial granted + rights has already set some elements + of `letters'. What we need to do is + to clear those that weren't granted + by the current PrC as well. The + easiest way to do this is to add 1 + to all the elements whose letters + are given with the current policy. + That way, all elements that are set + by the current policy and were + already set by earlier policies and + through the original grant of rights + will get the value 2 or higher. + The last thing to do is to sweep + through `letters' and keep the + elements having the value 2 as set, + and clear all the others. */ + + fprintf(stderr, " Certificate proxy rights = %*.*s", i, i, s); + while(i-- > 0) + { + int c = *s++; + if (isascii(c) && isalpha(c)) + { + if (islower(c)) + c = toupper(c); + letters[c - 'A']++; + } + } + for (i = 0; i < 26; i++) + if (letters[i] < 2) + letters[i] = 0; + else + letters[i] = 1; + } + + found_any = 0; + fprintf(stderr, + ", resulting proxy rights = "); + for(i = 0; i < 26; i++) + if (letters[i]) + { + fprintf(stderr, "%c", i + 'A'); + found_any = 1; + } + if (!found_any) + fprintf(stderr, "none"); + fprintf(stderr, "\n"); + + PROXY_CERT_INFO_EXTENSION_free(pci); + } + } + } + return(ok); } +static void process_proxy_debug(int indent, const char *format, ...) + { + static const char indentation[] = + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"; /* That's 80 > */ + char my_format[256]; + va_list args; + + BIO_snprintf(my_format, sizeof(my_format), "%*.*s %s", + indent, indent, indentation, format); + + va_start(args, format); + vfprintf(stderr, my_format, args); + va_end(args); + } +/* Priority levels: + 0 [!]var, () + 1 & ^ + 2 | +*/ +static int process_proxy_cond_adders(unsigned int letters[26], + const char *cond, const char **cond_end, int *pos, int indent); +static int process_proxy_cond_val(unsigned int letters[26], + const char *cond, const char **cond_end, int *pos, int indent) + { + int c; + int ok = 1; + int negate = 0; + + while(isspace((int)*cond)) + { + cond++; (*pos)++; + } + c = *cond; + + if (debug) + process_proxy_debug(indent, + "Start process_proxy_cond_val at position %d: %s\n", + *pos, cond); + + while(c == '!') + { + negate = !negate; + cond++; (*pos)++; + while(isspace((int)*cond)) + { + cond++; (*pos)++; + } + c = *cond; + } + + if (c == '(') + { + cond++; (*pos)++; + ok = process_proxy_cond_adders(letters, cond, cond_end, pos, + indent + 1); + cond = *cond_end; + if (ok < 0) + goto end; + while(isspace((int)*cond)) + { + cond++; (*pos)++; + } + c = *cond; + if (c != ')') + { + fprintf(stderr, + "Weird condition character in position %d: " + "%c\n", *pos, c); + ok = -1; + goto end; + } + cond++; (*pos)++; + } + else if (isascii(c) && isalpha(c)) + { + if (islower(c)) + c = toupper(c); + ok = letters[c - 'A']; + cond++; (*pos)++; + } + else + { + fprintf(stderr, + "Weird condition character in position %d: " + "%c\n", *pos, c); + ok = -1; + goto end; + } + end: + *cond_end = cond; + if (ok >= 0 && negate) + ok = !ok; + + if (debug) + process_proxy_debug(indent, + "End process_proxy_cond_val at position %d: %s, returning %d\n", + *pos, cond, ok); + + return ok; + } +static int process_proxy_cond_multipliers(unsigned int letters[26], + const char *cond, const char **cond_end, int *pos, int indent) + { + int ok; + char c; + + if (debug) + process_proxy_debug(indent, + "Start process_proxy_cond_multipliers at position %d: %s\n", + *pos, cond); + + ok = process_proxy_cond_val(letters, cond, cond_end, pos, indent + 1); + cond = *cond_end; + if (ok < 0) + goto end; + + while(ok >= 0) + { + while(isspace((int)*cond)) + { + cond++; (*pos)++; + } + c = *cond; + + switch(c) + { + case '&': + case '^': + { + int save_ok = ok; + + cond++; (*pos)++; + ok = process_proxy_cond_val(letters, + cond, cond_end, pos, indent + 1); + cond = *cond_end; + if (ok < 0) + break; + + switch(c) + { + case '&': + ok &= save_ok; + break; + case '^': + ok ^= save_ok; + break; + default: + fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!" + " STOPPING\n"); + EXIT(1); + } + } + break; + default: + goto end; + } + } + end: + if (debug) + process_proxy_debug(indent, + "End process_proxy_cond_multipliers at position %d: %s, returning %d\n", + *pos, cond, ok); + + *cond_end = cond; + return ok; + } +static int process_proxy_cond_adders(unsigned int letters[26], + const char *cond, const char **cond_end, int *pos, int indent) + { + int ok; + char c; + + if (debug) + process_proxy_debug(indent, + "Start process_proxy_cond_adders at position %d: %s\n", + *pos, cond); + + ok = process_proxy_cond_multipliers(letters, cond, cond_end, pos, + indent + 1); + cond = *cond_end; + if (ok < 0) + goto end; + + while(ok >= 0) + { + while(isspace((int)*cond)) + { + cond++; (*pos)++; + } + c = *cond; + + switch(c) + { + case '|': + { + int save_ok = ok; + + cond++; (*pos)++; + ok = process_proxy_cond_multipliers(letters, + cond, cond_end, pos, indent + 1); + cond = *cond_end; + if (ok < 0) + break; + + switch(c) + { + case '|': + ok |= save_ok; + break; + default: + fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!" + " STOPPING\n"); + EXIT(1); + } + } + break; + default: + goto end; + } + } + end: + if (debug) + process_proxy_debug(indent, + "End process_proxy_cond_adders at position %d: %s, returning %d\n", + *pos, cond, ok); + + *cond_end = cond; + return ok; + } + +static int process_proxy_cond(unsigned int letters[26], + const char *cond, const char **cond_end) + { + int pos = 1; + return process_proxy_cond_adders(letters, cond, cond_end, &pos, 1); + } + static int MS_CALLBACK app_verify_callback(X509_STORE_CTX *ctx, void *arg) { - char *s = NULL,buf[256]; int ok=1; + struct app_verify_arg *cb_arg = arg; + unsigned int letters[26]; /* only used with proxy_auth */ - fprintf(stderr, "In app_verify_callback, allowing cert. "); - fprintf(stderr, "Arg is: %s\n", (char *)arg); - fprintf(stderr, "Finished printing do we have a context? 0x%x a cert? 0x%x\n", - (unsigned int)ctx, (unsigned int)ctx->cert); - if (ctx->cert) - s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256); - if (s != NULL) + if (cb_arg->app_verify) { + char *s = NULL,buf[256]; + + fprintf(stderr, "In app_verify_callback, allowing cert. "); + fprintf(stderr, "Arg is: %s\n", cb_arg->string); + fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n", + (void *)ctx, (void *)ctx->cert); + if (ctx->cert) + s=X509_NAME_oneline(X509_get_subject_name(ctx->cert),buf,256); + if (s != NULL) + { fprintf(stderr,"cert depth=%d %s\n",ctx->error_depth,buf); + } + return(1); + } + if (cb_arg->proxy_auth) + { + int found_any = 0, i; + char *sp; + + for(i = 0; i < 26; i++) + letters[i] = 0; + for(sp = cb_arg->proxy_auth; *sp; sp++) + { + int c = *sp; + if (isascii(c) && isalpha(c)) + { + if (islower(c)) + c = toupper(c); + letters[c - 'A'] = 1; + } + } + + fprintf(stderr, + " Initial proxy rights = "); + for(i = 0; i < 26; i++) + if (letters[i]) + { + fprintf(stderr, "%c", i + 'A'); + found_any = 1; + } + if (!found_any) + fprintf(stderr, "none"); + fprintf(stderr, "\n"); + + X509_STORE_CTX_set_ex_data(ctx, + get_proxy_auth_ex_data_idx(),letters); + } + if (cb_arg->allow_proxy_certs) + { + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS); } +#ifndef OPENSSL_NO_X509_VERIFY +# ifdef OPENSSL_FIPS + if(s->version == TLS1_VERSION) + FIPS_allow_md5(1); +# endif + ok = X509_verify_cert(ctx); +# ifdef OPENSSL_FIPS + if(s->version == TLS1_VERSION) + FIPS_allow_md5(0); +# endif +#endif + + if (cb_arg->proxy_auth) + { + if (ok) + { + const char *cond_end = NULL; + + ok = process_proxy_cond(letters, + cb_arg->proxy_cond, &cond_end); + + if (ok < 0) + EXIT(3); + if (*cond_end) + { + fprintf(stderr, "Stopped processing condition before it's end.\n"); + ok = 0; + } + if (!ok) + fprintf(stderr, "Proxy rights check with condition '%s' proved invalid\n", + cb_arg->proxy_cond); + else + fprintf(stderr, "Proxy rights check with condition '%s' proved valid\n", + cb_arg->proxy_cond); + } + } return(ok); } @@ -1578,19 +2080,21 @@ static RSA *rsa_tmp=NULL; static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength) { + BIGNUM *bn = NULL; if (rsa_tmp == NULL) { + bn = BN_new(); rsa_tmp = RSA_new(); - if(!rsa_tmp) + if(!bn || !rsa_tmp || !BN_set_word(bn, RSA_F4)) { BIO_printf(bio_err, "Memory error..."); goto end; } BIO_printf(bio_err,"Generating temp (%d bit) RSA key...",keylength); (void)BIO_flush(bio_err); - if(!RSA_generate_key_ex(rsa_tmp,keylength,RSA_F4,NULL)) + if(!RSA_generate_key_ex(rsa_tmp,keylength,bn,NULL)) { - BIO_printf(bio_err, "Error generating key.", keylength); + BIO_printf(bio_err, "Error generating key."); RSA_free(rsa_tmp); rsa_tmp = NULL; } @@ -1598,6 +2102,7 @@ end: BIO_printf(bio_err,"\n"); (void)BIO_flush(bio_err); } + if(bn) BN_free(bn); return(rsa_tmp); }