X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Ftcpip.c;h=dcfec86cebd6ca82e67665b3924bbcd4efae6689;hp=e0128a694268c09855f5e2a0b99978c82999dde9;hb=4b0e4f2ebac2519c2e8a2034cb200dcd5bf0e532;hpb=5242cb5a8634bfa38b9333ff7f903e718ac6e292 diff --git a/src/tcpip.c b/src/tcpip.c index e0128a6..dcfec86 100644 --- a/src/tcpip.c +++ b/src/tcpip.c @@ -1,5 +1,5 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2012 Index Data + * Copyright (C) 1995-2013 Index Data * See the file LICENSE for details. */ /** @@ -338,7 +338,8 @@ static int ssl_check_error(COMSTACK h, tcpip_state *sp, int res) #if HAVE_GETADDRINFO /* resolve using getaddrinfo */ -struct addrinfo *tcpip_getaddrinfo(const char *str, const char *port) +struct addrinfo *tcpip_getaddrinfo(const char *str, const char *port, + int *ipv6_only) { struct addrinfo hints, *res; int error; @@ -366,18 +367,28 @@ struct addrinfo *tcpip_getaddrinfo(const char *str, const char *port) if (!strcmp("@", host)) { hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_INET6; + error = getaddrinfo(0, port, &hints, &res); + *ipv6_only = 0; + } + else if (!strcmp("@4", host)) + { + hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; error = getaddrinfo(0, port, &hints, &res); + *ipv6_only = -1; } else if (!strcmp("@6", host)) { hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; error = getaddrinfo(0, port, &hints, &res); + *ipv6_only = 1; } else { error = getaddrinfo(host, port, &hints, &res); + *ipv6_only = -1; } if (error) return 0; @@ -433,6 +444,7 @@ void *tcpip_straddr(COMSTACK h, const char *str) tcpip_state *sp = (tcpip_state *)h->cprivate; const char *port = "210"; struct addrinfo *ai = 0; + int ipv6_only = 0; if (h->protocol == PROTO_HTTP) { if (h->type == ssl_type) @@ -445,7 +457,7 @@ void *tcpip_straddr(COMSTACK h, const char *str) if (sp->ai) freeaddrinfo(sp->ai); - sp->ai = tcpip_getaddrinfo(str, port); + sp->ai = tcpip_getaddrinfo(str, port, &ipv6_only); if (sp->ai && h->state == CS_ST_UNBND) { int s = -1; @@ -459,7 +471,11 @@ void *tcpip_straddr(COMSTACK h, const char *str) return 0; assert(ai); h->iofile = s; - + if (ipv6_only >= 0 && + setsockopt(h->iofile, + IPPROTO_IPV6, + IPV6_V6ONLY, &ipv6_only, sizeof(ipv6_only))) + return 0; if (!tcpip_set_blocking(h, h->flags)) return 0; } @@ -580,21 +596,20 @@ int tcpip_rcvconnect(COMSTACK h) #if HAVE_GNUTLS_H if (h->type == ssl_type && !sp->session) { - int res; gnutls_global_init(); - tcpip_create_cred(h); - gnutls_init(&sp->session, GNUTLS_CLIENT); gnutls_set_default_priority(sp->session); gnutls_credentials_set (sp->session, GNUTLS_CRD_CERTIFICATE, sp->cred_ptr->xcred); - /* cast to intermediate size_t to avoid GCC warning. */ gnutls_transport_set_ptr(sp->session, (gnutls_transport_ptr_t) (size_t) h->iofile); - res = gnutls_handshake(sp->session); + } + if (sp->session) + { + int res = gnutls_handshake(sp->session); if (res < 0) { if (ssl_check_error(h, sp, res)) @@ -1351,7 +1366,7 @@ void tcpip_close(COMSTACK h) { #if HAVE_GNUTLS_H if (sp->session) - gnutls_bye(sp->session, GNUTLS_SHUT_RDWR); + gnutls_bye(sp->session, GNUTLS_SHUT_WR); #elif HAVE_OPENSSL_SSL_H if (sp->ssl) { @@ -1498,39 +1513,140 @@ static int tcpip_set_blocking(COMSTACK p, int flags) return 1; } + +#if HAVE_GNUTLS_H +/* gnutls_x509_crt_print appeared in 1.7.6. Memory leaks were fixed in 1.7.9. + GNUTLS_CRT_PRINT_FULL appeared in 2.4.0. */ +#if GNUTLS_VERSION_NUMBER >= 0x020400 +#define USE_GNUTLS_X509_CRT_PRINT 1 +#else +#define USE_GNUTLS_X509_CRT_PRINT 0 +#endif + + +#if USE_GNUTLS_X509_CRT_PRINT +#else +static const char *bin2hex(const void *bin, size_t bin_size) +{ + static char printable[110]; + const unsigned char *_bin = bin; + char *print; + size_t i; + if (bin_size > 50) + bin_size = 50; + print = printable; + for (i = 0; i < bin_size; i++) + { + sprintf(print, "%.2x ", _bin[i]); + print += 2; + } + return printable; +} + +static void x509_crt_print(gnutls_x509_crt_t cert) +{ + time_t expiration_time, activation_time; + size_t size; + char serial[40]; + char dn[256]; + unsigned int algo, bits; + + expiration_time = gnutls_x509_crt_get_expiration_time(cert); + activation_time = gnutls_x509_crt_get_activation_time(cert); + + printf("\tCertificate is valid since: %s", ctime(&activation_time)); + printf("\tCertificate expires: %s", ctime(&expiration_time)); + + /* Print the serial number of the certificate. */ + size = sizeof(serial); + gnutls_x509_crt_get_serial(cert, serial, &size); + + printf("\tCertificate serial number: %s\n", bin2hex(serial, size)); + + /* Extract some of the public key algorithm's parameters + */ + algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits); + + printf("Certificate public key: %s", gnutls_pk_algorithm_get_name(algo)); + + /* Print the version of the X.509 certificate. */ + printf("\tCertificate version: #%d\n", gnutls_x509_crt_get_version(cert)); + + size = sizeof(dn); + gnutls_x509_crt_get_dn(cert, dn, &size); + printf("\tDN: %s\n", dn); + + size = sizeof(dn); + gnutls_x509_crt_get_issuer_dn(cert, dn, &size); + printf("\tIssuer's DN: %s\n", dn); +} +#endif +#endif + void cs_print_session_info(COMSTACK cs) { #if HAVE_GNUTLS_H struct tcpip_state *sp = (struct tcpip_state *) cs->cprivate; - if (sp->session) + if (cs->type == ssl_type && sp->session) { + const gnutls_datum_t *cert_list; + unsigned i, cert_list_size; if (gnutls_certificate_type_get(sp->session) != GNUTLS_CRT_X509) return; printf("X509 certificate\n"); + cert_list = gnutls_certificate_get_peers(sp->session, + &cert_list_size); + printf("Peer provided %u certificates\n", cert_list_size); + for (i = 0; i < cert_list_size; i++) + { + gnutls_x509_crt_t cert; +#if USE_GNUTLS_X509_CRT_PRINT + int ret; + gnutls_datum_t cinfo; +#endif + gnutls_x509_crt_init(&cert); + gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER); + printf("Certificate info %d:\n", i + 1); +#if USE_GNUTLS_X509_CRT_PRINT + ret = gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, + &cinfo); + if (ret == 0) + { + printf("\t%s\n", cinfo.data); + gnutls_free(cinfo.data); + } +#else + x509_crt_print(cert); +#endif + gnutls_x509_crt_deinit(cert); + + } } #elif HAVE_OPENSSL_SSL_H - struct tcpip_state *sp = (struct tcpip_state *) cs->cprivate; - SSL *ssl = (SSL *) sp->ssl; - if (ssl) + if (cs->type == ssl_type) { - X509 *server_cert = SSL_get_peer_certificate(ssl); - - if (server_cert) + struct tcpip_state *sp = (struct tcpip_state *) cs->cprivate; + SSL *ssl = (SSL *) sp->ssl; + if (ssl) { - char *pem_buf; - int pem_len; - BIO *bio = BIO_new(BIO_s_mem()); + X509 *server_cert = SSL_get_peer_certificate(ssl); + if (server_cert) + { + char *pem_buf; + int pem_len; + BIO *bio = BIO_new(BIO_s_mem()); - /* get PEM buffer in memory */ - PEM_write_bio_X509(bio, server_cert); - pem_len = BIO_get_mem_data(bio, &pem_buf); - fwrite(pem_buf, pem_len, 1, stdout); + /* get PEM buffer in memory */ + PEM_write_bio_X509(bio, server_cert); + pem_len = BIO_get_mem_data(bio, &pem_buf); + fwrite(pem_buf, pem_len, 1, stdout); - /* print all info on screen .. */ - X509_print_fp(stdout, server_cert); - BIO_free(bio); + /* print all info on screen .. */ + X509_print_fp(stdout, server_cert); + BIO_free(bio); - X509_free(server_cert); + X509_free(server_cert); + } } } #endif