/* 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.
*/
/**
sp->altbuf = 0;
sp->altsize = sp->altlen = 0;
sp->towrite = sp->written = -1;
- if (protocol == PROTO_WAIS)
- sp->complete = completeWAIS;
- else
- sp->complete = cs_complete_auto;
+ sp->complete = cs_complete_auto;
sp->connect_request_buf = 0;
sp->connect_request_len = 0;
sp->connect_response_buf = 0;
sp->connect_response_len = 0;
- p->timeout = COMSTACK_DEFAULT_TIMEOUT;
- TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
+ TRC(fprintf(stderr, "Created new TCPIP comstack h=%p\n", p));
return p;
}
#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;
if (!strcmp("@", host))
{
hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_UNSPEC;
+ 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;
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)
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;
for (ai = sp->ai; ai; ai = ai->ai_next)
{
- s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (s != -1)
- break;
+ if (ai->ai_family == AF_INET6)
+ {
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s != -1)
+ break;
+ }
+ }
+ if (s == -1)
+ {
+ for (ai = sp->ai; ai; ai = ai->ai_next)
+ {
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s != -1)
+ break;
+ }
}
if (s == -1)
return 0;
assert(ai);
h->iofile = s;
-
+ if (ai->ai_family == AF_INET6 && 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;
}
struct sockaddr_in *add = (struct sockaddr_in *) address;
#endif
int r;
- TRC(fprintf(stderr, "tcpip_connect\n"));
+ TRC(fprintf(stderr, "tcpip_connect h=%p\n", h));
h->io_pending = 0;
if (h->state != CS_ST_UNBND)
{
#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))
int tmpi, berlen, rest, req, tomove;
int hasread = 0, res;
- TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize));
+ TRC(fprintf(stderr, "tcpip_get: h=%p bufsize=%d\n", h, *bufsize));
if (sp->altlen) /* switch buffers */
{
TRC(fprintf(stderr, " %d bytes in altbuf (%p)\n", sp->altlen,
int res;
struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
- TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
+ TRC(fprintf(stderr, "tcpip_put: h=%p size=%d\n", h, size));
h->io_pending = 0;
h->event = CS_DATA;
if (state->towrite < 0)
{
tcpip_state *sp = (struct tcpip_state *)h->cprivate;
- TRC(fprintf(stderr, "tcpip_close h=%p pid=%d\n", h, getpid()));
+ TRC(fprintf(stderr, "tcpip_close: h=%p pid=%d\n", h, getpid()));
if (h->iofile != -1)
{
#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)
{
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];
}
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
- if (cs->type == ssl_type)
- {
- struct tcpip_state *sp = (struct tcpip_state *) cs->cprivate;
- if (sp->session)
+ struct tcpip_state *sp = (struct tcpip_state *) cs->cprivate;
+ 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++)
{
- 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)
{
- gnutls_x509_crt_t cert;
- gnutls_datum_t cinfo;
- int ret;
- time_t expiration_time, activation_time;
- size_t size;
- char serial[40];
- char dn[256];
- unsigned int algo, bits;
-
- /* we only print information about the first certificate. */
- gnutls_x509_crt_init(&cert);
- gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER);
- printf("Certificate info %d:\n", i + 1);
- /* This is the preferred way of printing short information about
- a certificate. */
- ret = gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo);
- if (ret == 0)
- {
- printf("\t%s\n", cinfo.data);
- gnutls_free(cinfo.data);
- }
-
- /* If you want to extract fields manually for some other reason,
- below are popular example calls. */
-
- 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);
-
- gnutls_x509_crt_deinit(cert);
-
+ 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