From df31d067844d7fa46c0658652eca49f9a447676f Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 15 Mar 2021 10:56:46 +0100
Subject: [PATCH 3/5] src: avoid file descriptor leak in socket_open2

Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
 src/socket.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/socket.c b/src/socket.c
index 9ba784fa3a..39f18dbe18 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -517,10 +517,11 @@ socket_open2(socket_st * hd, const char *hostname, const char *service,
 		     getnameinfo(ptr->ai_addr, ptr->ai_addrlen, buffer,
 				 MAX_BUF, portname, sizeof(portname),
 				 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
 			fprintf(stderr, "getnameinfo(): %s\n",
 				gai_strerror(err));
+			close(sd);
 			continue;
 		}
 
 		if (hints.ai_socktype == SOCK_DGRAM) {
 #if defined(IP_DONTFRAG)
@@ -548,12 +549,14 @@ socket_open2(socket_st * hd, const char *hostname, const char *service,
 
 		} else {
 			if (msg)
 				log_msg(stdout, "%s '%s:%s'...\n", msg, buffer, portname);
 
-			if ((err = connect(sd, ptr->ai_addr, ptr->ai_addrlen)) < 0)
+			if ((err = connect(sd, ptr->ai_addr, ptr->ai_addrlen)) < 0) {
+				close(sd);
 				continue;
+			}
 		}
 
 		hd->fd = sd;
 		if (flags & SOCKET_FLAG_STARTTLS) {
 			hd->app_proto = app_proto;
@@ -563,19 +566,21 @@ socket_open2(socket_st * hd, const char *hostname, const char *service,
 
 		if (!(flags & SOCKET_FLAG_SKIP_INIT)) {
 			hd->session = init_tls_session(hostname);
 			if (hd->session == NULL) {
 				fprintf(stderr, "error initializing session\n");
+				close(sd);
 				exit(1);
 			}
 		}
 
 		if (hd->session) {
 			if (hd->edata.data) {
 				ret = gnutls_record_send_early_data(hd->session, hd->edata.data, hd->edata.size);
 				if (ret < 0) {
 					fprintf(stderr, "error sending early data\n");
+					close(sd);
 					exit(1);
 				}
 			}
 			if (hd->rdata.data) {
 				gnutls_session_set_data(hd->session, hd->rdata.data, hd->rdata.size);
@@ -596,15 +601,17 @@ socket_open2(socket_st * hd, const char *hostname, const char *service,
 		if (!(flags & SOCKET_FLAG_RAW) && !(flags & SOCKET_FLAG_SKIP_INIT)) {
 			err = do_handshake(hd);
 			if (err == GNUTLS_E_PUSH_ERROR) { /* failed connecting */
 				gnutls_deinit(hd->session);
 				hd->session = NULL;
+				close(sd);
 				continue;
 			}
 			else if (err < 0) {
 				if (!(flags & SOCKET_FLAG_DONT_PRINT_ERRORS))
 					fprintf(stderr, "*** handshake has failed: %s\n", gnutls_strerror(err));
+				close(sd);
 				exit(1);
 			}
 		}
 
 		break;
-- 
2.30.2

