openldap: hand it a dup'd socket, not curl's own
No binary (build failed)
—
(log yok)
| @@ -100,6 +100,7 @@ struct ldapconninfo { | |
| Curl_send *send; | |
| struct berval *servercred; /* SASL data from server. */ | |
| ldapstate state; /* Current machine state. */ | |
| + | curl_socket_t dupfd; /* duplicated socket */ |
| int proto; /* LDAP_PROTO_TCP/LDAP_PROTO_UDP/LDAP_PROTO_IPC */ | |
| int msgid; /* Current message id. */ | |
| }; | |
| @@ -425,10 +426,21 @@ static int ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) | |
| return 0; | |
| } | |
| - | /* We do not need to do anything because libcurl does it already */ |
| + | /* if there is a duplicated socket to close, close it */ |
| static int ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) | |
| { | |
| - | (void)sbiod; |
| + | struct Curl_easy *data = sbiod->sbiod_pvt; |
| + | if(data) { |
| + | struct connectdata *conn = data->conn; |
| + | if(conn) { |
| + | struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN); |
| + | if(li && (li->dupfd != CURL_SOCKET_BAD)) { |
| + | sclose(li->dupfd); |
| + | li->dupfd = CURL_SOCKET_BAD; |
| + | } |
| + | } |
| + | } |
| + | |
| return 0; | |
| } | |
| @@ -607,6 +619,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) | |
| result = CURLE_OUT_OF_MEMORY; | |
| goto out; | |
| } | |
| + | li->dupfd = CURL_SOCKET_BAD; |
| result = Curl_conn_meta_set(conn, CURL_META_LDAP_CONN, li, oldap_conn_dtor); | |
| if(result) | |
| @@ -632,7 +645,43 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) | |
| goto out; | |
| } | |
| - | rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); |
| + | { |
| + | #ifdef _WIN32 |
| + | SOCKET dupfd = INVALID_SOCKET; |
| + | WSAPROTOCOL_INFO pi; |
| + | if(WSADuplicateSocket(conn->sock[FIRSTSOCKET], GetCurrentProcessId(), |
| + | &pi)) |
| + | ; /* error */ |
| + | else |
| + | dupfd = CURL_SOCKET(pi.iAddressFamily, pi.iSocketType, pi.iProtocol); |
| + | #else |
| + | #ifdef F_DUPFD_CLOEXEC |
| + | int dupfd = fcntl(conn->sock[FIRSTSOCKET], F_DUPFD_CLOEXEC, 0); |
| + | #else |
| + | int dupfd = dup(conn->sock[FIRSTSOCKET]); |
| + | #ifdef HAVE_FCNTL |
| + | if((dupfd != CURL_SOCKET_BAD) && |
| + | (fcntl(dupfd, F_SETFD, FD_CLOEXEC) < 0)) { |
| + | sclose(dupfd); |
| + | dupfd = CURL_SOCKET_BAD; |
| + | } |
| + | #endif /* HAVE_FCNTL */ |
| + | #endif /* F_DUPFD_CLOEXEC */ |
| + | #endif /* _WIN32 */ |
| + | |
| + | if(dupfd == CURL_SOCKET_BAD) { |
| + | result = CURLE_COULDNT_CONNECT; |
| + | goto out; |
| + | } |
| + | rc = ldap_init_fd((ber_socket_t)dupfd, li->proto, hosturl, &li->ld); |
| + | if(rc) |
| + | sclose(dupfd); |
| + | else |
| + | /* store the socket, as when this is used by TLS we close this ourselves |
| + | and at this point the code does not yet know if this will use TLS or |
| + | not */ |
| + | li->dupfd = dupfd; |
| + | } |
| if(rc) { | |
| failf(data, "LDAP local: Cannot connect to %s, %s", | |
| hosturl, ldap_err2string(rc)); | |