aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/vtls/gskit.c98
1 files changed, 3 insertions, 95 deletions
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 296362e52..32153dd07 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -26,6 +26,8 @@
#include <gskssl.h>
#include <qsoasync.h>
+#undef HAVE_SOCKETPAIR /* because the native one isn't good enough */
+#include "socketpair.h"
/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
@@ -511,100 +513,6 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
BACKEND->iocport = -1;
}
-/* SSL over SSL
- * Problems:
- * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
- * pipe an SSL stream into another, it is therefore needed to have a pair
- * of such communicating sockets and handle the pipelining explicitly.
- * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
- * be used to produce the pipeline.
- * The solution is to simulate socketpair() for AF_INET with low-level API
- * listen(), bind() and connect().
- */
-
-static int
-inetsocketpair(int sv[2])
-{
- int lfd; /* Listening socket. */
- int sfd; /* Server socket. */
- int cfd; /* Client socket. */
- int len;
- struct sockaddr_in addr1;
- struct sockaddr_in addr2;
-
- /* Create listening socket on a local dynamic port. */
- lfd = socket(AF_INET, SOCK_STREAM, 0);
- if(lfd < 0)
- return -1;
- memset((char *) &addr1, 0, sizeof(addr1));
- addr1.sin_family = AF_INET;
- addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr1.sin_port = 0;
- if(bind(lfd, (struct sockaddr *) &addr1, sizeof(addr1)) ||
- listen(lfd, 2) < 0) {
- close(lfd);
- return -1;
- }
-
- /* Get the allocated port. */
- len = sizeof(addr1);
- if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
- close(lfd);
- return -1;
- }
-
- /* Create the client socket. */
- cfd = socket(AF_INET, SOCK_STREAM, 0);
- if(cfd < 0) {
- close(lfd);
- return -1;
- }
-
- /* Request unblocking connection to the listening socket. */
- curlx_nonblock(cfd, TRUE);
- if(connect(cfd, (struct sockaddr *) &addr1, sizeof(addr1)) < 0 &&
- errno != EINPROGRESS) {
- close(lfd);
- close(cfd);
- return -1;
- }
-
- /* Get the client dynamic port for intrusion check below. */
- len = sizeof(addr2);
- if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
- close(lfd);
- close(cfd);
- return -1;
- }
-
- /* Accept the incoming connection and get the server socket. */
- curlx_nonblock(lfd, TRUE);
- for(;;) {
- len = sizeof(addr1);
- sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
- if(sfd < 0) {
- close(lfd);
- close(cfd);
- return -1;
- }
-
- /* Check for possible intrusion from an external process. */
- if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
- addr1.sin_port == addr2.sin_port)
- break;
-
- /* Intrusion: reject incoming connection. */
- close(sfd);
- }
-
- /* Done, return sockets and succeed. */
- close(lfd);
- curlx_nonblock(cfd, FALSE);
- sv[0] = cfd;
- sv[1] = sfd;
- return 0;
-}
-
static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
int directions)
{
@@ -855,7 +763,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Establish a pipelining socket pair for SSL over SSL. */
if(conn->proxy_ssl[sockindex].use) {
- if(inetsocketpair(sockpair))
+ if(Curl_socketpair(0, 0, 0, sockpair))
return CURLE_SSL_CONNECT_ERROR;
BACKEND->localfd = sockpair[0];
BACKEND->remotefd = sockpair[1];