]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Add cancellable_accept(), make cancellable_send() take a const buffer
authorDavid Woodhouse <dwmw2@infradead.org>
Sat, 9 Apr 2022 21:45:49 +0000 (22:45 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Mon, 11 Apr 2022 13:50:18 +0000 (14:50 +0100)
These will be needed for AnyConnect 'external browser' SAML mode.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
openconnect-internal.h
ssl.c

index f066246aa091dce32bf53a262bf9b5b87b708a07..a14a825275de76282750be135b47421fa9058647 100644 (file)
@@ -1372,9 +1372,10 @@ int cancellable_gets(struct openconnect_info *vpninfo, int fd,
                     char *buf, size_t len);
 
 int cancellable_send(struct openconnect_info *vpninfo, int fd,
-                    char *buf, size_t len);
+                    const char *buf, size_t len);
 int cancellable_recv(struct openconnect_info *vpninfo, int fd,
                     char *buf, size_t len);
+int cancellable_accept(struct openconnect_info *vpninfo, int fd);
 
 #if defined(OPENCONNECT_OPENSSL)
 /* openssl-pkcs11.c */
diff --git a/ssl.c b/ssl.c
index e77abba25c7dc27537a1ba4fe01ebb82a17d24b6..aa706f79df26dfec3b7dadb7cbfd805187dd62e3 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -156,6 +156,62 @@ static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
        return err;
 }
 
+
+static inline int accept_pending(void)
+{
+#ifdef _WIN32
+       return WSAGetLastError() == WSAEWOULDBLOCK;
+#else
+       return errno == EAGAIN || errno == EWOULDBLOCK;
+#endif
+}
+
+int cancellable_accept(struct openconnect_info *vpninfo, int sockfd)
+{
+       fd_set wr_set, rd_set, ex_set;
+       int accept_fd, maxfd = sockfd;
+       char *errstr;
+
+       do {
+               accept_fd = accept(sockfd, NULL, NULL);
+               if (accept_fd >= 0)
+                       return accept_fd;
+
+               if (!accept_pending())
+                       break;
+
+               FD_ZERO(&wr_set);
+               FD_ZERO(&rd_set);
+               FD_ZERO(&ex_set);
+               FD_SET(sockfd, &rd_set);
+
+               cmd_fd_set(vpninfo, &rd_set, &maxfd);
+               if (select(maxfd + 1, &rd_set, &wr_set, &ex_set, NULL) < 0 &&
+                   errno != EINTR) {
+                       vpn_perror(vpninfo, _("Failed select() for socket accept"));
+                       return -EIO;
+               }
+
+               if (is_cancel_pending(vpninfo, &rd_set)) {
+                       vpn_progress(vpninfo, PRG_ERR, _("Socket accept cancelled\n"));
+                       return -EINTR;
+               }
+       } while (!FD_ISSET(sockfd, &ex_set) && !vpninfo->got_pause_cmd);
+
+#ifdef _WIN32
+       errstr = openconnect__win32_strerror(WSAGetLastError());
+#else
+       errstr = strerror(errno);
+#endif
+       vpn_progress(vpninfo, PRG_ERR,
+                    _("Failed to accept local connection: %s\n"),
+                    errstr);
+#ifdef _WIN32
+       free(errstr);
+#endif
+       return -1;
+}
+
 /* checks whether the provided string is an IP or a hostname.
  */
 unsigned string_is_hostname(const char *str)
@@ -1212,7 +1268,7 @@ int cancellable_gets(struct openconnect_info *vpninfo, int fd,
 }
 
 int cancellable_send(struct openconnect_info *vpninfo, int fd,
-                    char *buf, size_t len)
+                    const char *buf, size_t len)
 {
        size_t count;