diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-26 10:33:24 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-26 14:23:55 +0200 |
commit | 7e051ae28c288c218584f75dbc6c097a3b2564c9 (patch) | |
tree | 9456e41b15aac3333770d58715c7487607318af3 /src/socket.c | |
parent | e9b7e84870bc1bfea4969a57d15e523133b46ecb (diff) | |
download | gnutls-7e051ae28c288c218584f75dbc6c097a3b2564c9.tar.gz |
tools: TLS handling has been incorporated into socket_open()
This is of particular usage to the server IP address loop, since
we can detect fast open errors and retry handshake to the next IP
address.
Diffstat (limited to 'src/socket.c')
-rw-r--r-- | src/socket.c | 88 |
1 files changed, 55 insertions, 33 deletions
diff --git a/src/socket.c b/src/socket.c index 35fd61534e..aae9ee7403 100644 --- a/src/socket.c +++ b/src/socket.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * Copyright (C) 2000-2016 Free Software Foundation, Inc. + * Copyright (C) 2015-2016 Red Hat, Inc. * * This file is part of GnuTLS. * @@ -201,18 +202,18 @@ ssize_t wait_for_text(socket_st * socket, const char *txt, unsigned txt_size) return ret; } -void -socket_starttls(socket_st * socket, const char *app_proto) +static void +socket_starttls(socket_st * socket) { char buf[512]; if (socket->secure) return; - if (app_proto == NULL || strcasecmp(app_proto, "https") == 0) + if (socket->app_proto == NULL || strcasecmp(socket->app_proto, "https") == 0) return; - if (strcasecmp(app_proto, "smtp") == 0 || strcasecmp(app_proto, "submission") == 0) { + if (strcasecmp(socket->app_proto, "smtp") == 0 || strcasecmp(socket->app_proto, "submission") == 0) { if (socket->verbose) printf("Negotiating SMTP STARTTLS\n"); @@ -222,7 +223,7 @@ socket_starttls(socket_st * socket, const char *app_proto) wait_for_text(socket, "250 ", 4); send_line(socket, "STARTTLS\n"); wait_for_text(socket, "220 ", 4); - } else if (strcasecmp(app_proto, "imap") == 0 || strcasecmp(app_proto, "imap2") == 0) { + } else if (strcasecmp(socket->app_proto, "imap") == 0 || strcasecmp(socket->app_proto, "imap2") == 0) { if (socket->verbose) printf("Negotiating IMAP STARTTLS\n"); @@ -230,7 +231,7 @@ socket_starttls(socket_st * socket, const char *app_proto) wait_for_text(socket, "a OK", 4); send_line(socket, "a STARTTLS\r\n"); wait_for_text(socket, "a OK", 4); - } else if (strcasecmp(app_proto, "xmpp") == 0) { + } else if (strcasecmp(socket->app_proto, "xmpp") == 0) { if (socket->verbose) printf("Negotiating XMPP STARTTLS\n"); @@ -239,13 +240,13 @@ socket_starttls(socket_st * socket, const char *app_proto) wait_for_text(socket, "<?", 2); send_line(socket, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); wait_for_text(socket, "<proceed", 8); - } else if (strcasecmp(app_proto, "ldap") == 0) { + } else if (strcasecmp(socket->app_proto, "ldap") == 0) { if (socket->verbose) printf("Negotiating LDAP STARTTLS\n"); #define LDAP_STR "\x30\x1d\x02\x01\x01\x77\x18\x80\x16\x31\x2e\x33\x2e\x36\x2e\x31\x2e\x34\x2e\x31\x2e\x31\x34\x36\x36\x2e\x32\x30\x30\x33\x37" send(socket->fd, LDAP_STR, sizeof(LDAP_STR)-1, 0); wait_for_text(socket, NULL, 0); - } else if (strcasecmp(app_proto, "ftp") == 0 || strcasecmp(app_proto, "ftps") == 0) { + } else if (strcasecmp(socket->app_proto, "ftp") == 0 || strcasecmp(socket->app_proto, "ftps") == 0) { if (socket->verbose) printf("Negotiating FTP STARTTLS\n"); @@ -254,10 +255,10 @@ socket_starttls(socket_st * socket, const char *app_proto) send_line(socket, "AUTH TLS\r\n"); wait_for_text(socket, "234", 3); } else { - if (!c_isdigit(app_proto[0])) { + if (!c_isdigit(socket->app_proto[0])) { static int warned = 0; if (warned == 0) { - fprintf(stderr, "unknown protocol '%s'\n", app_proto); + fprintf(stderr, "unknown protocol '%s'\n", socket->app_proto); warned = 1; } } @@ -309,7 +310,7 @@ void socket_bye(socket_st * socket) ret = gnutls_bye(socket->session, GNUTLS_SHUT_WR); while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); - if (ret < 0) + if (socket->verbose && ret < 0) fprintf(stderr, "*** gnutls_bye() error: %s\n", gnutls_strerror(ret)); gnutls_deinit(socket->session); @@ -352,20 +353,26 @@ void canonicalize_host(char *hostname, char *service, unsigned service_size) snprintf(service, service_size, "%s", p+1); } + void socket_open(socket_st * hd, const char *hostname, const char *service, - int flags, const char *msg) + const char *app_proto, int flags, const char *msg, gnutls_datum_t *rdata) { struct addrinfo hints, *res, *ptr; int sd, err = 0; - int udp = flags & 1; - int fastopen = flags & 2; + int udp = flags & SOCKET_FLAG_UDP; + int fastopen = flags & SOCKET_FLAG_FASTOPEN; char buffer[MAX_BUF + 1]; char portname[16] = { 0 }; char *a_hostname = (char*)hostname; memset(hd, 0, sizeof(*hd)); + if (rdata) { + hd->rdata.data = rdata->data; + hd->rdata.size = rdata->size; + } + #ifdef HAVE_LIBIDN err = idna_to_ascii_8z(hostname, &a_hostname, IDNA_ALLOW_UNASSIGNED); if (err != IDNA_SUCCESS) { @@ -374,6 +381,7 @@ socket_open(socket_st * hd, const char *hostname, const char *service, exit(1); } #endif + hd->hostname = strdup(hostname); if (msg != NULL) printf("Resolving '%s:%s'...\n", a_hostname,service); @@ -426,6 +434,7 @@ socket_open(socket_st * hd, const char *hostname, const char *service, if (msg) printf("%s '%s:%s' (TFO)...\n", msg, buffer, portname); + } else { if (msg) printf("%s '%s:%s'...\n", msg, buffer, portname); @@ -434,6 +443,32 @@ socket_open(socket_st * hd, const char *hostname, const char *service, continue; } + if (!(flags & SOCKET_FLAG_RAW)) { + if (flags & SOCKET_FLAG_STARTTLS) { + socket_starttls(hd); + } + + hd->session = init_tls_session(hostname); + if (hd->rdata.data) { + gnutls_session_set_data(hd->session, hd->rdata.data, hd->rdata.size); + } + + hd->fd = sd; + gnutls_transport_set_int(hd->session, sd); + + err = do_handshake(hd); + if (err == GNUTLS_E_PUSH_ERROR) { /* failed connecting */ + gnutls_deinit(hd->session); + hd->session = NULL; + continue; + } + else if (err < 0) { + fprintf(stderr, "*** handshake has failed: %s\n", gnutls_strerror(err)); + exit(1); + } else if (hd->verbose) + printf("- Handshake was completed\n"); + } + break; } @@ -449,9 +484,12 @@ socket_open(socket_st * hd, const char *hostname, const char *service, exit(1); } - hd->secure = 0; + if (flags & SOCKET_FLAG_RAW) + hd->secure = 0; + else + hd->secure = 1; + hd->fd = sd; - hd->hostname = strdup(hostname); hd->ip = strdup(buffer); hd->service = strdup(portname); hd->ptr = ptr; @@ -463,22 +501,6 @@ socket_open(socket_st * hd, const char *hostname, const char *service, return; } -void sockets_init(void) -{ -#ifdef _WIN32 - WORD wVersionRequested; - WSADATA wsaData; - - wVersionRequested = MAKEWORD(1, 1); - if (WSAStartup(wVersionRequested, &wsaData) != 0) { - perror("WSA_STARTUP_ERROR"); - } -#else - signal(SIGPIPE, SIG_IGN); -#endif - -} - /* converts a textual service or port to * a service. */ |