X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fgen_sslfunc.c;h=d9f1ceccbb1bd4a5f0e35aa9dfabba4ea8f99510;hb=5f0a2b3f0846dd4c2f72fc62e7171200d1fd6e06;hp=f03f9c56a50e21b89c9a1b85f316acaff04bf73c;hpb=9f2cc079246d21f98bb7b73f1bdce9be6606c8c0;p=wget diff --git a/src/gen_sslfunc.c b/src/gen_sslfunc.c index f03f9c56..d9f1cecc 100644 --- a/src/gen_sslfunc.c +++ b/src/gen_sslfunc.c @@ -16,7 +16,17 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wget; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +In addition, as a special exception, the Free Software Foundation +gives permission to link the code of its release of Wget with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. */ #include @@ -50,8 +60,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ extern int errno; #endif -static int verify_callback PARAMS ((int, X509_STORE_CTX *)); - void ssl_init_prng (void) { @@ -112,35 +120,152 @@ ssl_init_prng (void) #endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */ } +int +verify_callback (int ok, X509_STORE_CTX *ctx) +{ + char *s, buf[256]; + s = X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), buf, 256); + if (ok == 0) { + switch (ctx->error) { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + /* This mean the CERT is not valid !!! */ + ok = 0; + break; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + /* Unsure if we should handle that this way */ + ok = 1; + break; + } + } + return ok; +} + +/* pass all ssl errors to DEBUGP + returns the number of printed errors */ +int +ssl_printerrors (void) +{ + int ocerr = 0; + unsigned long curerr = 0; + char errbuff[1024]; + xzero (errbuff); + while ((curerr = ERR_get_error ()) != 0) + { + DEBUGP (("OpenSSL: %s\n", ERR_error_string (curerr, errbuff))); + ++ocerr; + } + return ocerr; +} + /* Creates a SSL Context and sets some defaults for it */ uerr_t init_ssl (SSL_CTX **ctx) { SSL_METHOD *meth = NULL; - int verify = SSL_VERIFY_NONE; + int verify; + int can_validate; SSL_library_init (); SSL_load_error_strings (); SSLeay_add_all_algorithms (); SSLeay_add_ssl_algorithms (); - meth = SSLv23_client_method (); + switch (opt.sslprotocol) + { + default: + meth = SSLv23_client_method (); + break; + case 1 : + meth = SSLv2_client_method (); + break; + case 2 : + meth = SSLv3_client_method (); + break; + case 3 : + meth = TLSv1_client_method (); + break; + } + if (meth == NULL) + { + ssl_printerrors (); + return SSLERRCTXCREATE; + } + *ctx = SSL_CTX_new (meth); + if (meth == NULL) + { + ssl_printerrors (); + return SSLERRCTXCREATE; + } + /* Can we validate the server Cert ? */ + if (opt.sslcadir != NULL || opt.sslcafile != NULL) + { + SSL_CTX_load_verify_locations (*ctx, opt.sslcafile, opt.sslcadir); + can_validate = 1; + } + else + { + can_validate = 0; + } + + if (!opt.sslcheckcert) + { + /* check cert but ignore error, do not break handshake on error */ + verify = SSL_VERIFY_NONE; + } + else + { + if (!can_validate) + { + logprintf (LOG_NOTQUIET, "Warrining validation of Server Cert not possible!\n"); + verify = SSL_VERIFY_NONE; + } + else + { + /* break handshake if server cert is not valid but allow NO-Cert mode */ + verify = SSL_VERIFY_PEER; + } + } + SSL_CTX_set_verify (*ctx, verify, verify_callback); - if (*ctx == NULL) - return SSLERRCTXCREATE; - if (opt.sslcertfile) + + if (opt.sslcertfile != NULL || opt.sslcertkey != NULL) { - if (SSL_CTX_use_certificate_file (*ctx, opt.sslcertfile, - SSL_FILETYPE_PEM) <= 0) - return SSLERRCERTFILE; + int ssl_cert_type; + if (!opt.sslcerttype) + ssl_cert_type = SSL_FILETYPE_PEM; + else + ssl_cert_type = SSL_FILETYPE_ASN1; + if (opt.sslcertkey == NULL) - opt.sslcertkey=opt.sslcertfile; - if (SSL_CTX_use_PrivateKey_file (*ctx, opt.sslcertkey, - SSL_FILETYPE_PEM) <= 0) - return SSLERRCERTKEY; - } + opt.sslcertkey = opt.sslcertfile; + if (opt.sslcertfile == NULL) + opt.sslcertfile = opt.sslcertkey; + + if (SSL_CTX_use_certificate_file (*ctx, opt.sslcertfile, ssl_cert_type) <= 0) + { + ssl_printerrors (); + return SSLERRCERTFILE; + } + if (SSL_CTX_use_PrivateKey_file (*ctx, opt.sslcertkey , ssl_cert_type) <= 0) + { + ssl_printerrors (); + return SSLERRCERTKEY; + } + } + return 0; /* Succeded */ } +void +shutdown_ssl (SSL* con) +{ + if (con == NULL) + return; + if (0==SSL_shutdown (con)) + SSL_shutdown (con); + SSL_free (con); +} + /* Sets up a SSL structure and performs the handshake on fd Returns 0 if everything went right Returns 1 if something went wrong ----- TODO: More exit codes @@ -148,65 +273,41 @@ init_ssl (SSL_CTX **ctx) int connect_ssl (SSL **con, SSL_CTX *ctx, int fd) { - *con = (SSL *)SSL_new (ctx); - SSL_set_fd (*con, fd); - SSL_set_connect_state (*con); - SSL_connect (*con); - if ((*con)->state != SSL_ST_OK) - return 1; - /*while((SSLerror=ERR_get_error())!=0) - printf("%s\n", ERR_error_string(SSLerror,NULL));*/ - + if (NULL == (*con = SSL_new (ctx))) + { + ssl_printerrors (); + return 1; + } + if (!SSL_set_fd (*con, fd)) + { + ssl_printerrors (); + return 1; + } + SSL_set_connect_state (*con); + switch (SSL_connect (*con)) + { + case 1 : + return (*con)->state != SSL_ST_OK; + default: + ssl_printerrors (); + shutdown_ssl (*con); + *con = NULL; + return 1; + case 0 : + ssl_printerrors (); + SSL_free (*con); + *con = NULL; + return 1; + } return 0; } -void -shutdown_ssl (SSL* con) -{ - SSL_shutdown (con); - if (con != NULL) - SSL_free (con); -} - void free_ssl_ctx (SSL_CTX * ctx) { SSL_CTX_free (ctx); } -int -verify_callback (int ok, X509_STORE_CTX *ctx) -{ - char *s, buf[256]; - s = X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), buf, 256); - if (ok == 0) { - 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: - ok = 1; - } - } - return ok; -} - -/* pass all ssl errors to DEBUGP - returns the number of printed errors */ -int -ssl_printerrors (void) -{ - int ocerr = 0; - unsigned long curerr = 0; - char errbuff[1024]; - memset(errbuff, 0, sizeof(errbuff)); - for (curerr = ERR_get_error (); curerr; curerr = ERR_get_error ()) - { - DEBUGP (("OpenSSL: %s\n", ERR_error_string (curerr, errbuff))); - ++ocerr; - } - return ocerr; -} - /* SSL version of iread. Only exchanged read for SSL_read Read at most LEN bytes from FD, storing them to BUF. */ @@ -216,8 +317,8 @@ ssl_iread (SSL *con, char *buf, int len) int res, fd; BIO_get_fd (con->rbio, &fd); #ifdef HAVE_SELECT - if (opt.timeout && !SSL_pending (con)) - if (select_fd (fd, opt.timeout, 0) <= 0) + if (opt.read_timeout && !SSL_pending (con)) + if (select_fd (fd, opt.read_timeout, 0) <= 0) return -1; #endif do @@ -242,8 +343,8 @@ ssl_iwrite (SSL *con, char *buf, int len) while (len > 0) { #ifdef HAVE_SELECT - if (opt.timeout) - if (select_fd (fd, opt.timeout, 1) <= 0) + if (opt.read_timeout) + if (select_fd (fd, opt.read_timeout, 1) <= 0) return -1; #endif do