diff -Naur socat-1.7.1.3/VERSION socat-1.7.1.3g/VERSION --- socat-1.7.1.3/VERSION 2010-07-06 07:28:25.000000000 +0200 +++ socat-1.7.1.3g/VERSION 2010-10-05 15:47:06.000000000 +0200 @@ -1 +1 @@ -"1.7.1.3" +"1.7.1.3/g" diff -Naur socat-1.7.1.3/sslcls.c socat-1.7.1.3g/sslcls.c --- socat-1.7.1.3/sslcls.c 2008-09-22 21:59:28.000000000 +0200 +++ socat-1.7.1.3g/sslcls.c 2010-10-05 15:45:09.000000000 +0200 @@ -281,8 +281,7 @@ DH *sycPEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) { DH *result; - Debug4("PEM_read_bio_DHparams(%p, %p, %p, %p)", - bp, x, cb, u); + Debug4("PEM_read_bio_DHparams(%p, %p, %p, %p)", bp, x, cb, u); result = PEM_read_bio_DHparams(bp, x, cb, u); if (result) { /*Debug2("PEM_read_bio_DHparams(, {%p},,) -> %p", *x, result);*/ @@ -293,6 +292,22 @@ return result; } +long sycSSLeay(void) { + long result; + Debug("SSLeay()"); + result = SSLeay(); + Debug1("SSLeay() -> %#X", result); + return result; +} + +const char *sycSSLeay_version(int t) { + const char *result; + Debug1("SSLeay_version(%d)", t); + result = SSLeay_version(t); + Debug1("SSLeay_version() -> \"%s\"", result); + return result; +} + BIO *sycBIO_new_file(const char *filename, const char *mode) { BIO *result; Debug2("BIO_new_file(\"%s\", \"%s\")", filename, mode); @@ -305,6 +320,346 @@ return result; } +int sycBIO_read_filename(BIO *bio, const char *filename) { + int result; + Debug2("BIO_read_filename(%p, \"%s\")", bio, filename); + result = BIO_read_filename(bio, filename); + Debug1("BIO_read_filename() -> %d", result); + return result; +} + +BIO *sycBIO_new(BIO_METHOD *method) { + BIO *result; + Debug1("BIO_new(%p)", method); + result = BIO_new(method); + if (result) { + Debug1("BIO_new() -> %p", result); + } else { + Debug("BIO_new() -> NULL"); + } + return result; +} + +int sycBIO_free(BIO *bio) { + int result; + Debug1("BIO_free(%p)", bio); + result = BIO_free(bio); + Debug1("BIO_free() -> %d", result); + return result; +} + +BIO_METHOD *sycBIO_s_file(void) { + BIO_METHOD *result; + Debug("BIO_s_file()"); + result = BIO_s_file(); + if (result) { + Debug1("BIO_s_file() -> %p", result); + } else { + Debug("BIO_s_file() -> NULL"); + } + return result; +} + +STACK_OF(X509_INFO) *sycPEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u) { + STACK_OF(X509_INFO) *result; + Debug4("PEM_X509_INFO_read_bio(%p, %p, %p, %p)", bp, sk, cb, u); + result = PEM_X509_INFO_read_bio(bp, sk, cb, u); + if (result) { + Debug1("PEM_X509_INFO_read_bio() -> %p", result); + } else { + Debug("PEM_X509_INFO_read_bio() -> NULL"); + } + return result; +} + +int sycX509_verify_cert(X509_STORE_CTX *ctx) { + int result; + Debug1("X509_verify_cert(%p)", ctx); + result = X509_verify_cert(ctx); + Debug1("X509_verify_cert()-> %d", result); + return result; +} + +const char *sycX509_verify_cert_error_string(long n) { + const char *result; + Debug1("X509_verify_cert_error_string(%d)", n); + result = X509_verify_cert_error_string(n); + Debug1("X509_verify_cert_error_string() -> \"%s\"", result); + return result; +} + +int sycX509_check_issued(X509 *issuer, X509 *subject) { + int result; + Debug2("X509_check_issued(%p, %p)", issuer, subject); + result = X509_check_issued(issuer, subject); + Debug1("X509_check_issued() -> %d", result); + return result; +} + +int sycX509_check_purpose(X509 *x, int id, int ca) { + int result; + Debug3("X509_check_purpose(%p, %d, %d)", x, id, ca); + result = X509_check_purpose(x, id, ca); + Debug1("X509_check_purpose() -> %d", result); + return result; +} + +X509_EXTENSION *sycX509_get_ext(X509 *x, int loc) { + X509_EXTENSION *result; + Debug2("X509_get_ext(%p, %d)", x, loc); + result = X509_get_ext(x, loc); + if (result) { + Debug1("X509_get_ext() -> %p", result); + } else { + Debug("X509_get_ext() -> NULL"); + } + return result; +} + +int sycX509_get_ext_count(X509 *x) { + int result; + Debug1("X509_get_ext_count(%p)", x); + result = X509_get_ext_count(x); + Debug1("X509_get_ext_count() -> %d", result); + return result; +} + +X509_NAME *sycX509_get_issuer_name(X509 *a) { + X509_NAME *result; + Debug1("X509_get_issuer_name(%p)", a); + result = X509_get_issuer_name(a); + if (result) { + Debug1("X509_get_issuer_name() -> %p", result); + } else { + Debug("X509_get_issuer_name() -> NULL"); + } + return result; +} + +X509_NAME *sycX509_get_subject_name(X509 *a) { + X509_NAME *result; + Debug1("X509_get_subject_name(%p)", a); + result = X509_get_subject_name(a); + if (result) { + Debug1("X509_get_subject_name() -> %p", result); + } else { + Debug("X509_get_subject_name() -> NULL"); + } + return result; +} + +int sycX509_subject_name_cmp(const X509 *a, const X509 *b) { + int result; + Debug2("X509_subject_name_cmp(%p, %p)", a, b); + result = X509_subject_name_cmp(a, b); + Debug1("X509_subject_name_cmp() -> %d", result); + return result; +} + +int sycX509_supported_extension(X509_EXTENSION *ex) { + int result; + Debug1("X509_supported_extension(%p)", ex); + result = X509_supported_extension(ex); + Debug1("X509_supported_extension() -> %d", result); + return result; +} + +int sycX509_EXTENSION_get_critical(X509_EXTENSION *ex) { + int result; + Debug1("X509_EXTENSION_get_critical(%p)", ex); + result = X509_EXTENSION_get_critical(ex); + Debug1("X509_EXTENSION_get_critical() -> %d", result); + return result; +} + +ASN1_OBJECT *sycX509_EXTENSION_get_object(X509_EXTENSION *ex) { + ASN1_OBJECT *result; + Debug1("X509_EXTENSION_get_object(%p)", ex); + result = X509_EXTENSION_get_object(ex); + if (result) { + Debug1("X509_EXTENSION_get_object() -> %p", result); + } else { + Debug("X509_EXTENSION_get_object() -> NULL"); + } + return result; +} + +void sycX509_INFO_free(X509_INFO *xi) { + Debug1("X509_INFO_free(%p)", xi); + X509_INFO_free(xi); + Debug("X509_INFO_free() -> void"); +} + +int sycX509_LOOKUP_add_dir(X509_LOOKUP *x, const char *dir, long type) { + int result; + Debug3("X509_LOOKUP_add_dir(%p, \"%s\", %d)", x, dir, type); + result = X509_LOOKUP_add_dir(x, dir, type); + Debug1("X509_LOOKUP_add_dir() -> %d", result); + return result; +} + +X509_LOOKUP_METHOD *sycX509_LOOKUP_hash_dir(void) { + X509_LOOKUP_METHOD *result; + Debug("X509_LOOKUP_hash_dir()"); + result = X509_LOOKUP_hash_dir(); + if (result) { + Debug1("X509_LOOKUP_hash_dir() -> %p", result); + } else { + Debug("X509_LOOKUP_hash_dir() -> NULL"); + } + return result; +} + +int sycX509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { + int result; + Debug2("X509_NAME_cmp(%p, %p)", a, b); + result = X509_NAME_cmp(a, b); + Debug1("X509_NAME_cmp() -> %d", result); + return result; +} + +char *sycX509_NAME_oneline(X509_NAME *a, char *buf, int size) { + char *result; + Debug3("X509_NAME_oneline(%p, %p, %d)", a, buf, size); + result = X509_NAME_oneline(a, buf, size); + if (result) { + Debug1("X509_NAME_oneline() -> \"%s\"", result); + } else { + Debug("X509_NAME_oneline() -> NULL"); + } + return result; +} + +X509_LOOKUP *sycX509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) { + X509_LOOKUP *result; + Debug2("X509_STORE_add_lookup(%p, %p)", v, m); + result = X509_STORE_add_lookup(v, m); + if (result) { + Debug1("X509_STORE_add_lookup() -> %p", result); + } else { + Debug("X509_STORE_add_lookup() -> NULL"); + } + return result; +} + +X509_STORE *sycX509_STORE_new(void ) { + X509_STORE *result; + Debug("X509_STORE_new()"); + result = X509_STORE_new(); + if (result) { + Debug1("X509_STORE_new() -> %p", result); + } else { + Debug("X509_STORE_new() -> NULL"); + } + return result; +} + +void sycX509_STORE_free(X509_STORE *v) { + Debug1("X509_STORE_free(%p)", v); + X509_STORE_free(v); + Debug("X509_STORE_free() -> void"); +} + +int sycX509_STORE_load_locations(X509_STORE *ctx, const char *file, const char *dir) { + int result; + Debug3("X509_STORE_load_locations(%p, \"%s\", \"%s\")", ctx, file, dir); + result = X509_STORE_load_locations(ctx, file, dir); + Debug1("X509_STORE_load_locations() -> %d", result); + return result; +} + + +int sycX509_STORE_set_default_paths(X509_STORE *ctx) { + int result; + Debug1("X509_STORE_set_default_paths(%p)", ctx); + result = X509_STORE_set_default_paths(ctx); + Debug1("X509_STORE_set_default_paths() -> %d", result); + return result; +} + +void sycX509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) { + Debug2("X509_STORE_set_flags(%p, %d)", ctx, flags); + X509_STORE_set_flags(ctx, flags); + Debug("X509_STORE_set_flags() -> void"); +} + +void sycX509_STORE_CTX_free(X509_STORE_CTX *ctx) { + Debug1("X509_STORE_CTX_free(%p)", ctx); + X509_STORE_CTX_free(ctx); + Debug("X509_STORE_CTX_free() -> void"); +} + +STACK_OF(X509) *sycX509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) { + STACK_OF(X509) *result; + Debug1("X509_STORE_CTX_get_chain(%p)", ctx); + result = X509_STORE_CTX_get_chain(ctx); + if (result) { + Debug1("X509_STORE_CTX_get_chain() -> %p", result); + } else { + Debug("X509_STORE_CTX_get_chain() -> NULL"); + } + return result; +} + +X509 *sycX509_STORE_CTX_get_current_cert (X509_STORE_CTX *ctx) { + X509 *result; + Debug1("X509_STORE_CTX_get_current_cert(%p)", ctx); + result = X509_STORE_CTX_get_current_cert(ctx); + if (result) { + Debug1("X509_STORE_CTX_get_current_cert() -> %p", result); + } else { + Debug("X509_STORE_CTX_get_current_cert() -> NULL"); + } + return result; +} + +int sycX509_STORE_CTX_get_error(X509_STORE_CTX *ctx) { + int result; + Debug1("X509_STORE_CTX_get_error(%p)", ctx); + result = X509_STORE_CTX_get_error(ctx); + Debug1("X509_STORE_CTX_get_error() -> %d", result); + return result; +} + +int sycX509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) { + int result; + Debug1("X509_STORE_CTX_get_error_depth(%p)", ctx); + result = X509_STORE_CTX_get_error_depth(ctx); + Debug1("X509_STORE_CTX_get_error_depth() -> %d", result); + return result; +} + +int sycX509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain) +{ + int result; + Debug4("X509_STORE_CTX_init(%p, %p, %p, %p", ctx, store, x509, chain); + result = X509_STORE_CTX_init(ctx, store, x509, chain); + Debug1("X509_STORE_CTX_init() -> %d", result); + return result; +} + +X509_STORE_CTX *sycX509_STORE_CTX_new(void) { + X509_STORE_CTX *result; + Debug("X509_STORE_CTX_new()"); + result = X509_STORE_CTX_new(); + if (result) { + Debug1("X509_STORE_CTX_new() -> %p", result); + } else { + Debug("X509_STORE_CTX_new() -> NULL"); + } + return result; +} + +int sycX509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) { + int result; + Debug2("X509_STORE_CTX_set_purpose(%p, %d)", ctx, purpose); + result = X509_STORE_CTX_set_purpose(ctx, purpose); + Debug1("X509_STORE_CTX_set_purpose() -> %d", result); + return result; +} + #if WITH_FIPS int sycFIPS_mode_set(int onoff) { int result; diff -Naur socat-1.7.1.3/sslcls.h socat-1.7.1.3g/sslcls.h --- socat-1.7.1.3/sslcls.h 2008-09-22 21:59:28.000000000 +0200 +++ socat-1.7.1.3g/sslcls.h 2010-10-05 15:45:09.000000000 +0200 @@ -45,9 +45,55 @@ DH *sycPEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u); -BIO *sycBIO_new_file(const char *filename, const char *mode); +long sycSSLeay(void); +const char *sycSSLeay_version(int t); +BIO *sycBIO_new_file(const char *filename, const char *mode); +int sycBIO_read_filename(BIO *bio, const char *filename); +BIO *sycBIO_new(BIO_METHOD *method); +int sycBIO_free(BIO *bio); +BIO_METHOD *sycBIO_s_file(void); +STACK_OF(X509_INFO) *sycPEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); + +int sycX509_check_issued(X509 *issuer, X509 *subject); +int sycX509_check_purpose(X509 *x, int id, int ca); +X509_EXTENSION *sycX509_get_ext(X509 *x, int loc); +int sycX509_get_ext_count(X509 *x); +X509_NAME *sycX509_get_issuer_name(X509 *a); +X509_NAME *sycX509_get_subject_name(X509 *a); +int sycX509_subject_name_cmp(const X509 *a, const X509 *b); +int sycX509_supported_extension(X509_EXTENSION *ex); +int sycX509_verify_cert(X509_STORE_CTX *ctx); +const char *sycX509_verify_cert_error_string(long n); +int sycX509_EXTENSION_get_critical(X509_EXTENSION *ex); +ASN1_OBJECT *sycX509_EXTENSION_get_object(X509_EXTENSION *ex); +void sycX509_INFO_free(X509_INFO *xi); +int sycX509_LOOKUP_add_dir(X509_LOOKUP *x, const char *dir, long type); +X509_LOOKUP_METHOD *sycX509_LOOKUP_hash_dir(void); +int sycX509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); +char *sycX509_NAME_oneline(X509_NAME *a, char *buf, int size); +X509_LOOKUP *sycX509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); +void sycX509_STORE_free(X509_STORE *v); +X509_STORE *sycX509_STORE_new(void ); +int sycX509_STORE_load_locations (X509_STORE *ctx, + const char *file, + const char *dir); +int sycX509_STORE_set_default_paths(X509_STORE *ctx); +void sycX509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +void sycX509_STORE_CTX_free(X509_STORE_CTX *ctx); +STACK_OF(X509) *sycX509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); +X509 *sycX509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +int sycX509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +int sycX509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +int sycX509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +X509_STORE_CTX *sycX509_STORE_CTX_new(void); +int sycX509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); + +#if WITH_FIPS int sycFIPS_mode_set(int onoff); +#endif /* WITH_FIPS */ #endif /* WITH_OPENSSL */ @@ -90,11 +136,54 @@ #define sycPEM_read_bio_DHparams(b,x,p,u) PEM_read_bio_DHparams(b,x,p,u) +#define sycSSLeay() SSLeay() +#define sycSSLeay_version(t) SSLeay_version(t) #define sycBIO_new_file(f,m) BIO_new_file(f,m) +#define sycBIO_read_filename(b,f) BIO_read_filename(b,f) +#define sycBIO_new(m) BIO_new(m) +#define sycBIO_free(b) BIO_free(b) +#define sycBIO_s_file() BIO_s_file() + +#define sycPEM_X509_INFO_read_bio(bp,sk,cb,u) PEM_X509_INFO_read_bio(bp,sk,cb,u) + +#define sycX509_check_issued(i,s) X509_check_issued(i,s) +#define sycX509_check_purpose(x,i,c) X509_check_purpose(x,i,c) +#define sycX509_get_ext(x) X509_get_ext(x) +#define sycX509_get_ext_count(x) X509_get_ext_count(x) +#define sycX509_get_issuer_name(a) X509_get_issuer_name(a) +#define sycX509_get_subject_name(a) X509_get_subject_name(a) +#define sycX509_subject_name_cmp(a,b) X509_subject_name_cmp(a,b) +#define sycX509_supported_extension(ex) X509_supported_extension(ex) +#define sycX509_verify_cert(v) X509_verify_cert(v) +#define sycX509_verify_cert_error_string(n) X509_verify_cert_error_string(n) +#define sycX509_EXTENSION_get_critical(ex) X509_EXTENSION_get_critical(ex) +#define sycX509_EXTENSION_get_object(ex) X509_EXTENSION_get_object(ex) +#define sycX509_INFO_free(v) X509_INFO_free(v) +#define sycX509_LOOKUP_add_dir(x,d,t) X509_LOOKUP_add_dir(x,d,t) +#define sycX509_LOOKUP_hash_dir() X509_LOOKUP_hash_dir() +#define sycX509_NAME_cmp(a,b) X509_NAME_cmp(a,b) +#define sycX509_NAME_oneline(a,b,s) X509_NAME_oneline(a,b,s) +#define sycX509_STORE_add_lookup(v,m) X509_STORE_add_lookup(v,m) +#define sycX509_STORE_free(v) X509_STORE_free(v) +#define sycX509_STORE_new() X509_STORE_new() +#define sycX509_STORE_load_locations(c,f,d) X509_STORE_load_locations(c,f,d) +#define sycX509_STORE_set_default_paths(c) X509_STORE_set_default_paths(c) +#define sycX509_STORE_set_flags(c,f) X509_STORE_set_flags(c,f) +#define sycX509_STORE_CTX_free(c) X509_STORE_CTX_free(c) +#define sycX509_STORE_CTX_get_chain(c) X509_STORE_CTX_get_chain(c) +#define sycX509_STORE_CTX_get_current_cert(c) X509_STORE_CTX_get_current_cert(c) +#define sycX509_STORE_CTX_get_error(c) X509_STORE_CTX_get_error(c) +#define sycX509_STORE_CTX_get_error_depth(c) X509_STORE_CTX_get_error_depth(c) +#define sycX509_STORE_CTX_init(ctx,s,x,chain) X509_STORE_CTX_init(ctx,s,x,chain) +#define sycX509_STORE_CTX_new() X509_STORE_CTX_new() +#define sycX509_STORE_CTX_set_purpose(c,p) X509_STORE_CTX_set_purpose(c,p) -#endif /* WITH_OPENSSL */ +#if WITH_FIPS #define sycFIPS_mode_set(o) FIPS_mode_set(o) +#endif /* WITH_FIPS */ + +#endif /* WITH_OPENSSL */ #endif /* !WITH_SYCLS */ diff -Naur socat-1.7.1.3/sysincludes.h socat-1.7.1.3g/sysincludes.h --- socat-1.7.1.3/sysincludes.h 2009-12-26 09:07:50.000000000 +0100 +++ socat-1.7.1.3g/sysincludes.h 2010-10-05 15:45:09.000000000 +0200 @@ -173,6 +173,9 @@ #include #include #include +#include +#include +#include #endif #endif /* !defined(__sysincludes_h_included) */ diff -Naur socat-1.7.1.3/xio-openssl.c socat-1.7.1.3g/xio-openssl.c --- socat-1.7.1.3/xio-openssl.c 2010-05-22 19:09:17.000000000 +0200 +++ socat-1.7.1.3g/xio-openssl.c 2010-10-05 15:45:09.000000000 +0200 @@ -46,7 +46,7 @@ int dummy1, int dummy2, int dummy3); static int openssl_SSL_ERROR_SSL(int level, const char *funcname); static int openssl_handle_peer_certificate(struct single *xfd, bool opt_ver, - int level); + int level); static int xioSSL_set_fd(struct single *xfd, int level); static int xioSSL_connect(struct single *xfd, bool opt_ver, int level); @@ -99,6 +99,8 @@ const struct optdesc opt_openssl_verify = { "openssl-verify", "verify", OPT_OPENSSL_VERIFY, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_openssl_certificate = { "openssl-certificate", "cert", OPT_OPENSSL_CERTIFICATE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC }; const struct optdesc opt_openssl_key = { "openssl-key", "key", OPT_OPENSSL_KEY, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC }; +const struct optdesc opt_openssl_proxy = { "openssl-proxy", "proxy", OPT_OPENSSL_PROXY, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC }; +const struct optdesc opt_openssl_allowproxy = { "openssl-allow-proxy", "allow-proxy", OPT_OPENSSL_ALLOWPROXY, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC }; const struct optdesc opt_openssl_dhparam = { "openssl-dhparam", "dh", OPT_OPENSSL_DHPARAM, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC }; const struct optdesc opt_openssl_cafile = { "openssl-cafile", "cafile", OPT_OPENSSL_CAFILE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC }; const struct optdesc opt_openssl_capath = { "openssl-capath", "capath", OPT_OPENSSL_CAPATH, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC }; @@ -167,7 +169,6 @@ int level; SSL_CTX* ctx; bool opt_ver = true; /* verify peer certificate */ - char *opt_cert = NULL; /* file name of client certificate */ int result; if (!(xioflags & XIO_MAYCONVERT)) { @@ -189,10 +190,8 @@ retropt_bool(opts, OPT_FORK, &dofork); - retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert); - result = - _xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx); + _xioopen_openssl_prepare(opts, xfd, false, &opt_ver, &ctx); if (result != STAT_OK) return STAT_NORETRY; result = @@ -389,7 +388,6 @@ int level; SSL_CTX* ctx; bool opt_ver = true; /* verify peer certificate - changed with 1.6.0 */ - char *opt_cert = NULL; /* file name of server certificate */ int result; if (!(xioflags & XIO_MAYCONVERT)) { @@ -410,22 +408,17 @@ #else pf = PF_INET; #endif - + portname = argv[1]; xfd->howtoend = END_SHUTDOWN; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; applyopts(-1, opts, PH_INIT); - retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert); - if (opt_cert == NULL) { - Warn("no certificate given; consider option \"cert\""); - } - applyopts(-1, opts, PH_EARLY); result = - _xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert, &ctx); + _xioopen_openssl_prepare(opts, xfd, true, &opt_ver, &ctx); if (result != STAT_OK) return STAT_NORETRY; if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto, @@ -606,6 +599,583 @@ #endif /* WITH_LISTEN */ +/// ASN1 time string (in a char *) to time_t +/** + * (Use ASN1_STRING_data() to convert ASN1_GENERALIZEDTIME to char * if + * necessary) + */ + +time_t grid_asn1TimeToTimeT(char *asn1time, size_t len) +{ + char zone; + struct tm time_tm; + + if (len == 0) len = strlen(asn1time); + + if ((len != 13) && (len != 15)) return 0; /* dont understand */ + + if ((len == 13) && + ((sscanf(asn1time, "%02d%02d%02d%02d%02d%02d%c", + &(time_tm.tm_year), + &(time_tm.tm_mon), + &(time_tm.tm_mday), + &(time_tm.tm_hour), + &(time_tm.tm_min), + &(time_tm.tm_sec), + &zone) != 7) || (zone != 'Z'))) return 0; /* dont understand */ + + if ((len == 15) && + ((sscanf(asn1time, "20%02d%02d%02d%02d%02d%02d%c", + &(time_tm.tm_year), + &(time_tm.tm_mon), + &(time_tm.tm_mday), + &(time_tm.tm_hour), + &(time_tm.tm_min), + &(time_tm.tm_sec), + &zone) != 7) || (zone != 'Z'))) return 0; /* dont understand */ + + /* time format fixups */ + + if (time_tm.tm_year < 90) time_tm.tm_year += 100; + --(time_tm.tm_mon); + + return timegm(&time_tm); +} + + +/// Check if certificate can be used as a CA to sign standard X509 certs +/* + * Return 1 if true; 0 if not. + */ + +int grid_IsCA(X509 *cert) +{ + int idret; + + /* final argument to X509_check_purpose() is whether to check for CAness */ + idret = sycX509_check_purpose(cert, X509_PURPOSE_SSL_CLIENT, 1); + if (idret == 1) + return 1; + else if (idret == 0) + return 0; + else + { + Warn1( "Purpose warning code = %d\n", idret ); + return 0; + } +} + + +#define PROXYCERTINFO_OID "1.3.6.1.5.5.7.1.14" +#define OLD_PROXYCERTINFO_OID "1.3.6.1.4.1.3536.1.222" + +unsigned long grid_knownCriticalExts(X509 *cert) +{ + int i; + char s[80]; + X509_EXTENSION *ex; + + Debug( "grid_knownCriticalExts" ); + + for (i = 0; i < sycX509_get_ext_count(cert); ++i) + { + ex = sycX509_get_ext(cert, i); + + if ( sycX509_EXTENSION_get_critical(ex) && + !sycX509_supported_extension(ex)) + { + OBJ_obj2txt(s, sizeof(s), sycX509_EXTENSION_get_object(ex), 1); + + Debug1( " Critical extension found: %s", s ); + + if (strcmp(s, PROXYCERTINFO_OID) == 0) return X509_V_OK; + if (strcmp(s, OLD_PROXYCERTINFO_OID) == 0) return X509_V_OK; + + return X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; + } + } + + return X509_V_OK; +} + + +unsigned long grid_readProxy( char *filename, STACK_OF(X509) **certstack ) +{ + STACK_OF(X509_INFO) *sk = NULL; + BIO *certbio = NULL; + X509_INFO *xi; + unsigned long err; + + Debug( "--- grid_readProxy() start"); + + *certstack = sk_X509_new_null(); + if (*certstack == NULL) return ERR_get_error(); + + if ( (certbio = sycBIO_new(sycBIO_s_file())) == NULL ) return ERR_get_error(); + + Notice1( "Reading file %s", filename ); + if ( sycBIO_read_filename(certbio, filename) <= 0 ) return ERR_get_error(); + + Debug( "Reading X509_INFO records" ); + if ( !(sk=sycPEM_X509_INFO_read_bio(certbio, NULL, NULL, NULL)) ) + { + err = ERR_get_error(); + Error( "Reading proxy: No X509 records found" ); + sycBIO_free(certbio); + sk_X509_INFO_free(sk); + sk_X509_free(*certstack); + return err; + } + + while (sk_X509_INFO_num(sk)) + { + xi=sk_X509_INFO_shift(sk); + if (xi->x509 != NULL) + { + sk_X509_push(*certstack, xi->x509); + xi->x509=NULL; + } + X509_INFO_free(xi); + } + + if (!sk_X509_num(*certstack)) + { + err = ERR_get_error(); + Error( "Reading proxy: No certificates found" ); + sycBIO_free(certbio); + sk_X509_INFO_free(sk); + sk_X509_free(*certstack); + return err; + } + + sycBIO_free(certbio); + sk_X509_INFO_free(sk); + + return X509_V_OK; +} + + +int grid_check_issued_wrapper(X509_STORE_CTX *ctx,X509 *x,X509 *issuer) +/* We change the default callback to use our wrapper and discard errors + due to GSI proxy chains (ie where users certs act as CAs) */ +{ + int ret; + ret = sycX509_check_issued(issuer, x); + if (ret == X509_V_OK) return 1; + + Debug( "grid_check_issued_wrapper" ); + Debug1( " check_issued returned: %s", sycX509_verify_cert_error_string (ret)); + + /* Non self-signed certs without signing are ok if they passed + the other checks inside X509_check_issued. Is this enough? */ + if ((ret == X509_V_ERR_KEYUSAGE_NO_CERTSIGN) && + (sycX509_subject_name_cmp(issuer, x) != 0)) return 1; + +#if OPENSSL_VERSION_NUMBER < 0x00908000L + /* If we haven't asked for issuer errors don't set ctx */ + if (!(ctx->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0; +#else + if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0; +#endif + + ctx->error = ret; + ctx->current_cert = x; + ctx->current_issuer = issuer; + Debug( "grid_check_issued_wrapper: calling ctx->verify_cb" ); + return ctx->verify_cb(0, ctx); +} + + +/****************************************************************************** +Function: grid_verifyProxy +Description: + Tries to verify the proxies in the certstack +******************************************************************************/ +unsigned long grid_verifyProxy( STACK_OF(X509) *certstack ) +{ + int i = 0; + int serialLen, j = 0; + X509 *cert = NULL; + time_t now = time((time_t *)NULL); + size_t len = 0; /* Lengths of issuer and cert DN */ + size_t len2 = 0; /* Lengths of issuer and cert DN */ + int prevIsLimited = 0; /* previous cert was proxy and limited */ + char *cert_DN = NULL; /* Pointer to current-certificate-in-certstack's DN */ + char *issuer_DN = NULL; /* Pointer to issuer-of-current-cert-in-certstack's DN */ + char *proxy_part_DN = NULL; + int depth = sk_X509_num (certstack); + int amount_of_CAs = 0; + int is_old_style_proxy = 0; + int is_limited_proxy = 0; + ASN1_INTEGER *cert_Serial = NULL; + ASN1_INTEGER *issuer_Serial = NULL; + unsigned char serialNumberDER[127]; + unsigned char serialStr[255]; + unsigned char *temp; + + Debug( "--- grid_verifyProxy() start"); + + // And there was (current) time... + time(&now); + + // How many CA certs are there in the certstack? + for (i = 0; i < depth; i++) + { + if (grid_IsCA(sk_X509_value(certstack, i))) + amount_of_CAs++; + } + + Debug2( "#CA's = %d , depth = %d", amount_of_CAs, depth ); + + if ((amount_of_CAs + 2) > depth) + { + if ((depth - amount_of_CAs) > 0) + { + Warn( "No proxy certificate in certificate stack to check." ); + return X509_V_OK; + } + else + { + Error( "Verifying proxy: No personal certificate (neither proxy or user certificate) found in the certficiate stack." ); + return X509_V_ERR_APPLICATION_VERIFICATION; + } + } + + + /* Changed this value to start checking the proxy and such and + to skip the CA and the user_cert + */ + for (i = depth - (amount_of_CAs + 2); i >= 0; i--) + { + /* Check for X509 certificate and point to it with 'cert' */ + if ( (cert = sk_X509_value(certstack, i)) != NULL ) + { + cert_DN = sycX509_NAME_oneline( sycX509_get_subject_name( cert ), NULL, 0); + issuer_DN = sycX509_NAME_oneline( sycX509_get_issuer_name( cert ), NULL, 0); + len = strlen( cert_DN ); + len2 = strlen( issuer_DN ); + + Notice( "Proxy to verify:" ); + Notice1( " DN: %s", cert_DN ); + Notice1( " Issuer DN: %s", issuer_DN ); + + if (now < grid_asn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0)) + { + Error( "Verifying proxy: Proxy certificate is not yet valid." ); + return X509_V_ERR_CERT_NOT_YET_VALID; + } + + if (now > grid_asn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0)) + { + Error( "Verifying proxy: Proxy certificate expired." ); + return X509_V_ERR_CERT_HAS_EXPIRED; + } + + /* User not allowed to sign shortened DN */ + if (len2 > len) + { + Error( "Verifying proxy: It is not allowed to sign a shorthened DN."); + return X509_V_ERR_APPLICATION_VERIFICATION; + } + + /* Proxy subject must begin with issuer. */ + if (strncmp(cert_DN, issuer_DN, len2) != 0) + { + Error( "Verifying proxy: Proxy subject must begin with the issuer."); + return X509_V_ERR_APPLICATION_VERIFICATION; + } + + /* Set pointer to end of base DN in cert_DN */ + proxy_part_DN = &cert_DN[len2]; + + /* First attempt at support for Old and New style GSI + proxies: /CN=anything is ok for now */ + if (strncmp(proxy_part_DN, "/CN=", 4) != 0) + { + Error( "Verifying proxy: Could not find a /CN= structure in the DN, thus it is not a proxy."); + return X509_V_ERR_APPLICATION_VERIFICATION; + } + + if (strncmp(proxy_part_DN, "/CN=proxy", 9) == 0) + { + Info( "Current certificate is an old style proxy." ); + is_old_style_proxy = 1; + is_limited_proxy = 0; + } + else if (strncmp(proxy_part_DN, "/CN=limited proxy", 17) == 0) + { + Info( "Current certificate is an old limited style proxy." ); + is_old_style_proxy = 1; + is_limited_proxy = 1; + } + else + { + Info( "Current certificate is a GSI/RFC3820 proxy." ); + } + + if ( is_old_style_proxy ) + { + cert_Serial = X509_get_serialNumber( cert ); + temp = serialNumberDER; + serialLen = i2c_ASN1_INTEGER( cert_Serial, &temp ); + bzero( serialStr, sizeof( serialStr) ); + temp = serialStr; + for (j = 0; j < serialLen; j++) + { + sprintf( (char *)temp, "%02X", serialNumberDER[j] ); + temp = temp + 2; + } + Debug1( "Serial number: %s", serialStr ); + + issuer_Serial = X509_get_serialNumber( sk_X509_value(certstack, i+1)); + temp = serialNumberDER; + serialLen = i2c_ASN1_INTEGER( issuer_Serial, &temp ); + bzero( serialStr, sizeof( serialStr) ); + temp = serialStr; + for (j = 0; j < serialLen; j++) + { + sprintf( (char *)temp, "%02X", serialNumberDER[j] ); + temp = temp + 2; + } + Debug1( "Issuer serial number: %s", serialStr ); + + if (cert_Serial && issuer_Serial) + { + if ( ASN1_INTEGER_cmp( cert_Serial, issuer_Serial ) ) + { + Warn( "Serial numbers do not match." ); + } + } + } + + if ( is_limited_proxy ) + { + prevIsLimited = 1; + if (i > 0) Warn( "Found limited proxy." ); + } + else + { + if (prevIsLimited) + { + Error( "Proxy chain integrity error. Previous proxy in chain was limited, but this one is a regular proxy." ); + return X509_V_ERR_APPLICATION_VERIFICATION; + } + } + + if (cert_DN) free(cert_DN); + if (issuer_DN) free(issuer_DN); + } + } + + return X509_V_OK; +} + + +/****************************************************************************** +Function: grid_verify_callback +Description: + Callback function for OpenSSL to put the errors +Parameters: + ok, X509_STORE_CTX +Returns: +******************************************************************************/ +static int grid_verify_callback(int ok, X509_STORE_CTX *ctx) +{ + unsigned long errnum = sycX509_STORE_CTX_get_error(ctx); + int errdepth = sycX509_STORE_CTX_get_error_depth(ctx); + X509 *cert = sycX509_STORE_CTX_get_current_cert(ctx); + STACK_OF(X509) *certstack; + + Debug( "grid_verify_callback" ); + char *cert_DN = sycX509_NAME_oneline( sycX509_get_subject_name( cert ), NULL, 0 ); + char *issuer_DN = sycX509_NAME_oneline( sycX509_get_issuer_name( cert ), NULL, 0 ); + Debug1( " DN: %s", cert_DN ); + Debug1( " Issuer DN: %s", issuer_DN ); + + if (ok != 1) + { + if (errnum == X509_V_ERR_INVALID_CA) ok=1; + if (errnum == X509_V_ERR_UNABLE_TO_GET_CRL) ok=1; +#if OPENSSL_VERSION_NUMBER >= 0x00908000L + /* I don't want to do this, really, but I have yet to figure out + how to get openssl 0.9.8 to accept proxy certificates when + opening a new SSL connection... + */ + if (errnum == X509_V_ERR_INVALID_PURPOSE) ok=1; +#endif + if (errnum == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) + { + errnum = grid_knownCriticalExts( cert ); + ctx->error = errnum; + if (errnum == X509_V_OK) ok=1; + } + } + + /* + * We've now got the last certificate - the identity being used for + * this connection. At this point we check the whole chain for valid + * CAs or, failing that, GSI-proxy validity using grid_verifyProxy + */ + if ( (errdepth == 0) && (ok == 1) ) + { + certstack = (STACK_OF(X509) *) sycX509_STORE_CTX_get_chain( ctx ); + + errnum = grid_verifyProxy( certstack ); + ctx->error = errnum; + if (errnum == X509_V_OK) ok=1; + } + + if (ok != 1) + { + Notice1( "grid_verify_callback: error message=%s", + sycX509_verify_cert_error_string (errnum)); + } + +// ok=1; + + return ok; +} + + +/****************************************************************************** +Function: grid_verifyCert +Description: + Validates a certificate with the CRL list and the signing CA +******************************************************************************/ +unsigned long grid_verifyCert( char * CA_DIR, STACK_OF(X509) *certstack ) +{ + X509_STORE *store = NULL; + X509_LOOKUP *lookup = NULL; + X509_STORE_CTX *verify_ctx = NULL; + X509 *cert = NULL; + int i = 0; + int depth = sk_X509_num( certstack ); + + Debug( "--- grid_verifyCert() start"); + + // Initials must be good + if ( CA_DIR == NULL ) + { + Error( "Verifying certificate chain: No CA certificate directory specified." ); + return X509_V_ERR_APPLICATION_VERIFICATION; + } + if ( certstack == NULL ) + { + Error( "Verifying certificate chain: Certificate stack is empty." ); + return X509_V_ERR_APPLICATION_VERIFICATION; + } + + Notice1( "Using CA Directory: %s", CA_DIR); + + if (!(store = sycX509_STORE_new())) + { + Error( "Verifying certificate chain: Could not create a X509 STORE." ); + return ERR_get_error(); + } + + // this is a macro, so we don't create a 'syc' version + X509_STORE_set_verify_cb_func (store, grid_verify_callback); + + // Executing the lookups to the CA and CRL files + if (sycX509_STORE_load_locations (store, NULL, CA_DIR) != 1) + { + Error( "Verifying certificate chain: Could not load the CA directory."); + return ERR_get_error(); + } + if (sycX509_STORE_set_default_paths(store) != 1) + { + Error( "Verifying certificate chain: Could not load the system wide CA certificates."); + return ERR_get_error(); + } + + if (!(lookup = sycX509_STORE_add_lookup (store, sycX509_LOOKUP_hash_dir()))) + { + Error( "Verifying certificate chain: Could not create X509_LOOKUP object."); + return ERR_get_error(); + } + + if (!(sycX509_LOOKUP_add_dir (lookup, CA_DIR, X509_FILETYPE_PEM))) + { + Error( "Verifying certificate chain: Could not add CA_DIR."); + return ERR_get_error(); + } + + store->check_issued = grid_check_issued_wrapper; +#if OPENSSL_VERSION_NUMBER < 0x00908000L + sycX509_STORE_set_flags( store, X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL ); +#else + sycX509_STORE_set_flags( store, X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL | + X509_V_FLAG_ALLOW_PROXY_CERTS ); +#endif + + // Creating a verification context and init it + if (!(verify_ctx = sycX509_STORE_CTX_new())) + { + Error( "Verifying certificate chain: Could not create a X509 STORE CTX (context)."); + return ERR_get_error(); + } + + for (i=depth-1; i >= 0; --i) + { + if ((cert = sk_X509_value(certstack, i))) + { + char *cert_DN = sycX509_NAME_oneline( + sycX509_get_subject_name( cert ), NULL, 0 ); + char *issuer_DN = sycX509_NAME_oneline( + sycX509_get_issuer_name( cert ), NULL, 0 ); + + Debug2( "DN[%d]: %s", i, cert_DN ); + Debug2( "Issuer DN[%d]: %s", i, issuer_DN); + + if (grid_IsCA(cert)) + { + Debug( "This certificate is a CA certificate" ); + Debug( "continue search for user certificate..." ); + } + else + { + break; + } + } + } + + cert = sk_X509_value( certstack, 0 ); + char *cert_DN = sycX509_NAME_oneline( sycX509_get_subject_name( cert ) , NULL, 0 ); + char *issuer_DN = sycX509_NAME_oneline( sycX509_get_issuer_name( cert ) , NULL, 0 ); + + Debug( "Certificate to verify:" ); + Debug1( " DN: %s", cert_DN ); + Debug1( " Issuer DN: %s", issuer_DN ); + + if ( sycX509_STORE_CTX_init( verify_ctx, store, cert, certstack) != 1 ) + { + Error( "Verifying certificate chain: Could not initialize verification context."); + return ERR_get_error(); + } + + sycX509_STORE_CTX_set_purpose( verify_ctx, X509_PURPOSE_SSL_CLIENT ); +#if OPENSSL_VERSION_NUMBER >= 0x00908000L + cert->ex_flags |= EXFLAG_PROXY; +#endif + + if ( ( sycX509_verify_cert( verify_ctx ) ) != 1 ) + { + return verify_ctx->error; + } + else + { + Notice( "The verification of the certicate has succeeded."); + } + + if ( verify_ctx ) sycX509_STORE_CTX_free( verify_ctx ); + if ( store ) sycX509_STORE_free( store ); + + return X509_V_OK; +} + + int _xioopen_openssl_prepare(struct opt *opts, struct single *xfd,/* a xio file descriptor @@ -613,20 +1183,24 @@ */ bool server, /* SSL client: false */ bool *opt_ver, - const char *opt_cert, SSL_CTX **ctx) { bool opt_fips = false; SSL_METHOD *method; char *me_str = NULL; /* method string */ char *ci_str = NULL; /* cipher string */ - char *opt_key = NULL; /* file name of client private key */ + char *opt_key = NULL; /* file name of client private key */ + bool opt_allowproxy = false; /* allow connections using GSI proxies */ + char *opt_proxy = NULL; /* file name of GSI proxy */ char *opt_dhparam = NULL; /* file name of DH params */ char *opt_cafile = NULL; /* certificate authority file */ char *opt_capath = NULL; /* certificate authority directory */ + char *opt_cert = NULL; /* public key */ char *opt_egd = NULL; /* entropy gathering daemon socket path */ bool opt_pseudo = false; /* use pseudo entropy if nothing else */ - unsigned long err; + BIO *bio; + DH *dh; + unsigned long err = 0; int result; xfd->addr = &addr_openssl; @@ -638,11 +1212,25 @@ retropt_bool(opts, OPT_OPENSSL_VERIFY, opt_ver); retropt_string(opts, OPT_OPENSSL_CAFILE, &opt_cafile); retropt_string(opts, OPT_OPENSSL_CAPATH, &opt_capath); + retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert); retropt_string(opts, OPT_OPENSSL_KEY, &opt_key); + retropt_string(opts, OPT_OPENSSL_PROXY, &opt_proxy); + retropt_bool(opts, OPT_OPENSSL_ALLOWPROXY, &opt_allowproxy); retropt_string(opts, OPT_OPENSSL_DHPARAM, &opt_dhparam); retropt_string(opts, OPT_OPENSSL_EGD, &opt_egd); retropt_bool(opts,OPT_OPENSSL_PSEUDO, &opt_pseudo); + if (server && (opt_cert == NULL) && (opt_proxy == NULL)) { + Warn("no certificate given; consider option \"cert\" or \"proxy\""); + } + + Notice1( "Using %s", sycSSLeay_version( SSLEAY_VERSION ) ); + if ((sycSSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) + { + Error2( "OpenSSL version mismatch. Built against %lx, " + "you have %lx", OPENSSL_VERSION_NUMBER, SSLeay() ); + } + #if WITH_FIPS if (opt_fips) { if (!sycFIPS_mode_set(1)) { @@ -662,7 +1250,7 @@ /* OpenSSL preparation */ sycSSL_library_init(); - + /*! actions_to_seed_PRNG();*/ if (!server) { @@ -778,6 +1366,7 @@ if (opt_dhparam == NULL) { opt_dhparam = (char *)opt_cert; } + Debug1( "opt_dhparam = %s", opt_dhparam ); if ((bio = sycBIO_new_file(opt_dhparam, "r")) == NULL) { Warn2("BIO_new_file(\"%s\", \"r\"): %s", opt_dhparam, strerror(errno)); @@ -792,6 +1381,78 @@ } } } + else if (opt_proxy) + { + STACK_OF(X509) *certStack; + + *opt_ver = true; + opt_allowproxy = true; /* when using a proxy, always allow connections + from the other end using proxies */ + + /* read the file and build the certificate stack */ + err = grid_readProxy( opt_proxy, &certStack ); + if ( err == X509_V_OK ) + { + /* first, verify the certificate chain */ + err = grid_verifyCert( opt_capath, certStack ); + if ( err == X509_V_OK ) + { + err = sycSSL_CTX_use_certificate_chain_file( *ctx, opt_proxy ); + if ( err <= 0 ) + { + Error( "Cannot add certificate stack to SSL_CTX" ); + while ( err = ERR_get_error() ) + { + Error1( "SSL_CTX_use_certificate(): %s", + ERR_error_string( err, NULL ) ); + } + + return STAT_RETRYLATER; + } + err = sycSSL_CTX_use_PrivateKey_file( *ctx, opt_proxy, SSL_FILETYPE_PEM ); + if ( err <= 0 ) + { + Error( "Cannot add certificate stack to SSL_CTX" ); + while ( err = ERR_get_error() ) + { + Error1( "SSL_CTX_use_certificate(): %s", + ERR_error_string( err, NULL ) ); + } + + return STAT_RETRYLATER; + } + } + else + Error1( "Verifying certificate chain: %s", + X509_verify_cert_error_string( err ) ); + } + else + Error1( "Reading proxy: %s", + ERR_reason_error_string( err ) ); + + if (opt_dhparam == NULL) opt_dhparam = (char *)opt_proxy; + + if ((bio = sycBIO_new_file(opt_dhparam, "r")) == NULL) + { + Warn2("BIO_new_file(\"%s\", \"r\"): %s", + opt_dhparam, strerror(errno)); + } + else + { + if ((dh = sycPEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL) + { + Info1("PEM_read_bio_DHparams(%p, NULL, NULL, NULL): error", bio); + } + else + { + BIO_free(bio); + if (sycSSL_CTX_set_tmp_dh(*ctx, dh) == 0) + { + Error2("SSL_CTX_set_tmp_dh(%p, %p): error", ctx, dh); + } + } + } + } /* set pre ssl-connect options */ /* SSL_CIPHERS */ @@ -808,7 +1469,16 @@ } } - if (*opt_ver) { + if (opt_allowproxy) { + (*ctx)->cert_store->check_issued = grid_check_issued_wrapper; + } + + if (opt_allowproxy) { + sycSSL_CTX_set_verify(*ctx, + SSL_VERIFY_PEER| SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + grid_verify_callback); + } + else if (*opt_ver) { sycSSL_CTX_set_verify(*ctx, SSL_VERIFY_PEER| SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); @@ -901,7 +1571,7 @@ bool opt_ver, int level) { X509 *peer_cert; char *str; - char buff[2048]; /* hold peer certificate */ + char buff[32768]; /* hold peer certificate */ int status; /* SSL_CTX_add_extra_chain_cert diff -Naur socat-1.7.1.3/xio-openssl.h socat-1.7.1.3g/xio-openssl.h --- socat-1.7.1.3/xio-openssl.h 2008-09-22 21:59:28.000000000 +0200 +++ socat-1.7.1.3g/xio-openssl.h 2010-10-05 15:45:09.000000000 +0200 @@ -22,6 +22,8 @@ extern const struct optdesc opt_openssl_cafile; extern const struct optdesc opt_openssl_capath; extern const struct optdesc opt_openssl_egd; +extern const struct optdesc opt_openssl_allowproxy; +extern const struct optdesc opt_openssl_proxy; extern const struct optdesc opt_openssl_pseudo; #if WITH_FIPS extern const struct optdesc opt_openssl_fips; @@ -29,8 +31,7 @@ extern int _xioopen_openssl_prepare(struct opt *opts, struct single *xfd, - bool server, bool *opt_ver, const char *opt_cert, - SSL_CTX **ctx); + bool server, bool *opt_ver, SSL_CTX **ctx); extern int _xioopen_openssl_connect(struct single *xfd, bool opt_ver, SSL_CTX *ctx, int level); diff -Naur socat-1.7.1.3/xioopts.c socat-1.7.1.3g/xioopts.c --- socat-1.7.1.3/xioopts.c 2010-06-09 12:04:33.000000000 +0200 +++ socat-1.7.1.3g/xioopts.c 2010-10-05 15:45:09.000000000 +0200 @@ -157,6 +157,7 @@ IF_IP ("add-membership", &opt_ip_add_membership) #endif IF_TUN ("allmulti", &opt_iff_allmulti) + IF_OPENSSL("allow-proxy", &opt_openssl_allowproxy) #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE) IF_IPAPP ("allow-table", &opt_tcpwrap_hosts_allow_table) #endif @@ -1063,6 +1064,7 @@ #if HAVE_OPENPTY IF_EXEC ("openpty", &opt_openpty) #endif /* HAVE_OPENPTY */ + IF_OPENSSL("openssl-allow-proxy", &opt_openssl_allowproxy) IF_OPENSSL("openssl-cafile", &opt_openssl_cafile) IF_OPENSSL("openssl-capath", &opt_openssl_capath) IF_OPENSSL("openssl-certificate", &opt_openssl_certificate) @@ -1074,6 +1076,7 @@ #endif IF_OPENSSL("openssl-key", &opt_openssl_key) IF_OPENSSL("openssl-method", &opt_openssl_method) + IF_OPENSSL("openssl-proxy", &opt_openssl_proxy) IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo) IF_OPENSSL("openssl-verify", &opt_openssl_verify) IF_TERMIOS("opost", &opt_opost) @@ -1134,6 +1137,7 @@ #ifdef SO_PROTOTYPE IF_SOCKET ("prototype", &opt_so_prototype) #endif + IF_OPENSSL("proxy", &opt_openssl_proxy) IF_PROXY ("proxy-auth", &opt_proxy_authorization) IF_PROXY ("proxy-authorization", &opt_proxy_authorization) IF_PROXY ("proxy-resolve", &opt_proxy_resolve) diff -Naur socat-1.7.1.3/xioopts.h socat-1.7.1.3g/xioopts.h --- socat-1.7.1.3/xioopts.h 2010-05-22 19:09:17.000000000 +0200 +++ socat-1.7.1.3g/xioopts.h 2010-10-05 15:45:09.000000000 +0200 @@ -468,6 +468,7 @@ #if HAVE_OPENPTY OPT_OPENPTY, #endif + OPT_OPENSSL_ALLOWPROXY, OPT_OPENSSL_CAFILE, OPT_OPENSSL_CAPATH, OPT_OPENSSL_CERTIFICATE, @@ -477,6 +478,7 @@ OPT_OPENSSL_FIPS, OPT_OPENSSL_KEY, OPT_OPENSSL_METHOD, + OPT_OPENSSL_PROXY, OPT_OPENSSL_PSEUDO, OPT_OPENSSL_VERIFY, OPT_OPOST, /* termios.c_oflag */