File stunnel-CVE-2015-3644.patch of Package stunnel.6450

diff -u -r stunnel-5.00-orig/src/client.c stunnel-5.00-patched/src/client.c
--- stunnel-5.00-orig/src/client.c	2014-03-06 00:25:00.000000000 +0100
+++ stunnel-5.00-patched/src/client.c	2015-05-26 10:44:03.219628792 +0200
@@ -75,6 +75,7 @@
     c->opt=opt;
     c->local_rfd.fd=rfd;
     c->local_wfd.fd=wfd;
+    c->redirect=REDIRECT_OFF;
     return c;
 }
 
@@ -142,9 +143,17 @@
     c->fd=-1;
     c->ssl=NULL;
     c->sock_bytes=c->ssl_bytes=0;
+    if(c->opt->option.client) {
+        c->sock_rfd=&(c->local_rfd);
+        c->sock_wfd=&(c->local_wfd);
+        c->ssl_rfd=c->ssl_wfd=&(c->remote_fd);
+    } else {
+        c->sock_rfd=c->sock_wfd=&(c->remote_fd);
+        c->ssl_rfd=&(c->local_rfd);
+        c->ssl_wfd=&(c->local_wfd);
+    }
     c->fds=s_poll_alloc();
-    c->connect_addr.num=0;
-    c->connect_addr.addr=NULL;
+    addrlist_init(&c->connect_addr, 1);
 
     err=setjmp(c->err);
     if(!err)
@@ -207,9 +216,9 @@
         c->opt->servname, num_clients_copy);
 #endif
 
-        /* free remaining memory structures */
-    if(c->connect_addr.addr)
-        str_free(c->connect_addr.addr);
+        /* free the client context */
+         str_free(c->connect_addr.addr);
+
     s_poll_free(c->fds);
     c->fds=NULL;
 }
@@ -365,17 +374,6 @@
         SSL_set_accept_state(c->ssl);
     }
 
-    /* setup some values for transfer() function */
-    if(c->opt->option.client) {
-        c->sock_rfd=&(c->local_rfd);
-        c->sock_wfd=&(c->local_wfd);
-        c->ssl_rfd=c->ssl_wfd=&(c->remote_fd);
-    } else {
-        c->sock_rfd=c->sock_wfd=&(c->remote_fd);
-        c->ssl_rfd=&(c->local_rfd);
-        c->ssl_wfd=&(c->local_wfd);
-    }
-
     unsafe_openssl=SSLeay()<0x0090810fL ||
         (SSLeay()>=0x10000000L && SSLeay()<0x1000002fL);
     while(1) {
@@ -435,21 +433,31 @@
             sslerror("SSL_accept");
         longjmp(c->err, 1);
     }
+    s_log(LOG_INFO, "SSL %s: %s",
+        c->opt->option.client ? "connected" : "accepted",
+        SSL_session_reused(c->ssl) ?
+            "previous session reused" : "new session negotiated");
     if(SSL_session_reused(c->ssl)) {
-        s_log(LOG_INFO, "SSL %s: previous session reused",
-            c->opt->option.client ? "connected" : "accepted");
+        c->redirect=(uintptr_t)SSL_SESSION_get_ex_data(SSL_get_session(c->ssl),
+            redirect_index);
+        if(c->opt->redirect_addr.names && !c->redirect) {
+            s_log(LOG_ERR, "No application data found in the reused session");
+            longjmp(c->err, 1);
+        }
     } else { /* a new session was negotiated */
         new_chain(c);
+        SSL_SESSION_set_ex_data(SSL_get_session(c->ssl),
+            redirect_index, (void *)c->redirect);
         if(c->opt->option.client) {
-            s_log(LOG_INFO, "SSL connected: new session negotiated");
             enter_critical_section(CRIT_SESSION);
             old_session=c->opt->session;
             c->opt->session=SSL_get1_session(c->ssl); /* store it */
             if(old_session)
                 SSL_SESSION_free(old_session); /* release the old one */
             leave_critical_section(CRIT_SESSION);
-        } else
-            s_log(LOG_INFO, "SSL accepted: new session negotiated");
+        } else { /* SSL server */
+            SSL_CTX_add_session(c->opt->ctx, SSL_get_session(c->ssl));
+        }
         print_cipher(c);
     }
 }
@@ -679,6 +687,24 @@
             }
         }
 
+        /****************************** write to socket */
+        if(sock_open_wr && sock_can_wr) {
+            num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr);
+            switch(num) {
+            case -1: /* error */
+                if(parse_socket_error(c, "writesocket"))
+                    break; /* a non-critical error: retry */
+                sock_open_rd=sock_open_wr=0;
+                break;
+            default:
+                memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num);
+                c->ssl_ptr-=num;
+                memset(c->ssl_buff+c->ssl_ptr, 0, num); /* paranoia */
+                c->sock_bytes+=num;
+                watchdog=0; /* reset watchdog */
+            }
+        }
+
         /****************************** read from socket */
         if(sock_open_rd && sock_can_rd) {
             num=readsocket(c->sock_rfd->fd,
@@ -699,23 +725,6 @@
             }
         }
 
-        /****************************** write to socket */
-        if(sock_open_wr && sock_can_wr) {
-            num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr);
-            switch(num) {
-            case -1: /* error */
-                if(parse_socket_error(c, "writesocket"))
-                    break; /* a non-critical error: retry */
-                sock_open_rd=sock_open_wr=0;
-                break;
-            default:
-                memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num);
-                c->ssl_ptr-=num;
-                c->sock_bytes+=num;
-                watchdog=0; /* reset watchdog */
-            }
-        }
-
         /****************************** update *_wants_* based on new *_ptr */
         /* this update is also required for SSL_pending() to be used */
         read_wants_read=!(SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN)
@@ -1153,6 +1162,10 @@
     int fd, ind_start, ind_try, ind_cur;
 
     setup_connect_addr(c);
+    if(!c->connect_addr.num) {
+        s_log(LOG_ERR, "No host resolved");
+        longjmp(c->err, 1);
+    }
     ind_start=c->connect_addr.cur;
     /* the race condition here can be safely ignored */
     if(c->opt->failover==FAILOVER_RR)
@@ -1188,13 +1201,21 @@
     socklen_t addrlen=sizeof(SOCKADDR_UNION);
 #endif /* SO_ORIGINAL_DST */
 
-    /* check if the address was already set by the verify callback,
-     * or a dynamic protocol
-     * implemented protocols: CONNECT
-     * protocols to be implemented: SOCKS4 */
+    /* process "redirect" first */
+    if(c->redirect==REDIRECT_ON) {
+        s_log(LOG_NOTICE, "Redirecting connection");
+        if(c->connect_addr.addr) /* allocated in protocol negotiations */
+            str_free(c->connect_addr.addr);
+        addrlist_dup(&c->connect_addr, &c->opt->redirect_addr);
+        return;
+    }
+
+    /* check if the address was already set in protocol negotiations */
+    /* used by the following protocols: CONNECT */
     if(c->connect_addr.num)
         return;
 
+    /* transparent destination */
 #ifdef SO_ORIGINAL_DST
     if(c->opt->option.transparent_dst) {
         c->connect_addr.num=1;
@@ -1207,19 +1228,8 @@
         return;
     }
 #endif /* SO_ORIGINAL_DST */
-
-    if(c->opt->connect_addr.num) { /* pre-resolved addresses */
-        addrlist_dup(&c->connect_addr, &c->opt->connect_addr);
-        return;
-    }
-
-    /* delayed lookup */
-    if(namelist2addrlist(&c->connect_addr,
-            c->opt->connect_list, DEFAULT_LOOPBACK))
-        return;
-
-    s_log(LOG_ERR, "No host resolved");
-    longjmp(c->err, 1);
+    /* default "connect" target */
+    addrlist_dup(&c->connect_addr, &c->opt->connect_addr);
 }
 
 NOEXPORT void local_bind(CLI *c) {
diff -u -r stunnel-5.00-orig/src/options.c stunnel-5.00-patched/src/options.c
--- stunnel-5.00-orig/src/options.c	2015-05-26 10:42:20.431950948 +0200
+++ stunnel-5.00-patched/src/options.c	2015-05-26 10:42:55.651896451 +0200
@@ -85,6 +85,8 @@
 #endif
 
 NOEXPORT void print_syntax(void);
+
+NOEXPORT void name_list_append(NAME_LIST **, char *);
 #ifndef USE_WIN32
 NOEXPORT char **argalloc(char *);
 #endif
@@ -805,7 +807,6 @@
         char *opt, char *arg) {
     char *tmpstr;
     int tmpnum, endpoints=0;
-    NAME_LIST *tmplist;
 
     if(cmd==CMD_DEFAULT || cmd==CMD_HELP) {
         s_log(LOG_NOTICE, " ");
@@ -991,23 +992,18 @@
     switch(cmd) {
     case CMD_BEGIN:
         section->option.remote=0;
-        section->connect_list=NULL;
-        section->connect_addr.num=0;
+        addrlist_init(&section->connect_addr, 1);
         break;
     case CMD_EXEC:
         if(strcasecmp(opt, "connect"))
             break;
         section->option.remote=1;
-        tmplist=str_alloc(sizeof(NAME_LIST));
-        tmplist->name=str_dup(arg);
-        tmplist->next=section->connect_list;
-        section->connect_list=tmplist;
+        name_list_append(&section->connect_addr.names, arg);
         return NULL; /* OK */
     case CMD_END:
         if(!section->option.delayed_lookup &&
-                section->connect_list &&
-                !namelist2addrlist(&section->connect_addr,
-                    section->connect_list, DEFAULT_LOOPBACK)) {
+                section->connect_addr.names &&
+                !addrlist_resolve(&section->connect_addr)) {
             s_log(LOG_INFO,
                 "Cannot resolve connect target - delaying DNS lookup");
             section->option.delayed_lookup=1;
@@ -1382,6 +1378,10 @@
     case CMD_HELP:
         s_log(LOG_NOTICE, "%-15s = defines the maximum length the queue of pending connections may grow to (max SOMAXCONN)", "listenqueue");
         break;
+	case CMD_END:
+		break;
+	case CMD_FREE:
+		break;
     }
 
 #ifdef HAVE_OSSL_OCSP_H
@@ -1606,23 +1606,20 @@
     /* redirect */
     switch(cmd) {
     case CMD_BEGIN:
-        section->redirect_list=NULL;
-        section->redirect_addr.num=0;
+        addrlist_init(&section->redirect_addr, 1);
         break;
     case CMD_EXEC:
         if(strcasecmp(opt, "redirect"))
             break;
-        tmplist=str_alloc(sizeof(NAME_LIST));
-        tmplist->name=str_dup(arg);
-        tmplist->next=section->redirect_list;
-        section->redirect_list=tmplist;
+        name_list_append(&section->redirect_addr.names, arg);
         return NULL; /* OK */
     case CMD_END:
-        if(section->redirect_list &&
-                !namelist2addrlist(&section->redirect_addr,
-                    section->redirect_list, DEFAULT_LOOPBACK)) {
+        if(!section->option.delayed_lookup &&
+                section->redirect_addr.names &&
+                !addrlist_resolve(&section->redirect_addr)) {
             s_log(LOG_INFO,
                 "Cannot resolve redirect target - delaying DNS lookup");
+            section->option.delayed_lookup=1;
         }
         break;
     case CMD_FREE:
@@ -2373,8 +2370,8 @@
         /* setup host_name for SNI, prefer SNI and protocolHost if specified */
         if(section->protocol_host) /* 'protocolHost' option */
             section->sni=str_dup(section->protocol_host);
-        else if(section->connect_list) /* 'connect' option */
-            section->sni=str_dup(section->connect_list->name); /* first hostname */
+        else if(section->connect_addr.names) /* 'connect' option */
+            section->sni=str_dup(section->connect_addr.names->name); /* first hostname */
         if(section->sni) { /* either 'protocolHost' or 'connect' specified */
             tmpstr=strrchr(section->sni, ':');
             if(tmpstr) { /* 'host:port' -> drop ':port' */
@@ -2976,6 +2973,14 @@
 
 /**************************************** various supporting functions */
 
+NOEXPORT void name_list_append(NAME_LIST **ptr, char *name) {
+    while(*ptr) /* find the null pointer */
+        ptr=&(*ptr)->next;
+    *ptr=str_alloc(sizeof(NAME_LIST));
+    (*ptr)->name=str_dup(name);
+    (*ptr)->next=NULL;
+}
+
 #ifndef USE_WIN32
 
 NOEXPORT char **argalloc(char *str) { /* allocate 'exec' argumets */
diff -u -r stunnel-5.00-orig/src/protocol.c stunnel-5.00-patched/src/protocol.c
--- stunnel-5.00-orig/src/protocol.c	2014-03-06 00:25:58.000000000 +0100
+++ stunnel-5.00-patched/src/protocol.c	2015-05-26 10:42:55.651896451 +0200
@@ -546,7 +546,7 @@
 
     host_list.name=request+8;
     host_list.next=NULL;
-    if(!namelist2addrlist(&c->connect_addr, &host_list, DEFAULT_LOOPBACK)) {
+    if(!name2addrlist(&c->connect_addr, &host_list, DEFAULT_LOOPBACK)) {
         fd_putline(c, c->local_wfd.fd, "HTTP/1.0 404 Not Found");
         fd_putline(c, c->local_wfd.fd, "Server: stunnel/" STUNNEL_VERSION);
         fd_putline(c, c->local_wfd.fd, "");
diff -u -r stunnel-5.00-orig/src/prototypes.h stunnel-5.00-patched/src/prototypes.h
--- stunnel-5.00-orig/src/prototypes.h	2015-05-26 10:42:20.431950948 +0200
+++ stunnel-5.00-patched/src/prototypes.h	2015-05-26 10:42:55.652896506 +0200
@@ -42,6 +42,10 @@
 
 /**************************************** data structures */
 
+/* non-zero constants for the "redirect" option */
+#define REDIRECT_ON         1
+#define REDIRECT_OFF        2
+
 #if defined (USE_WIN32)
 #define ICON_IMAGE HICON
 #elif defined(__APPLE__)
@@ -86,8 +90,10 @@
 
 typedef struct sockaddr_list {                          /* list of addresses */
     SOCKADDR_UNION *addr;                           /* the list of addresses */
+    unsigned *rr_ptr, rr_val;             /* current address for round-robin */
     u16 cur;                              /* current address for round-robin */
     u16 num;                                  /* how many addresses are used */
+    NAME_LIST *names;
 } SOCKADDR_LIST;
 
 #ifndef OPENSSL_NO_COMP
@@ -202,7 +208,6 @@
 #endif
     SOCKADDR_UNION local_addr, source_addr;
     SOCKADDR_LIST connect_addr, redirect_addr;
-    NAME_LIST *connect_list, *redirect_list;
     int timeout_busy;                       /* maximum waiting for data time */
     int timeout_close;                          /* maximum close_notify time */
     int timeout_connect;                           /* maximum connect() time */
@@ -380,7 +385,7 @@
 
 /**************************************** prototypes for ssl.c */
 
-extern int cli_index, opt_index;
+extern int cli_index, opt_index, redirect_index;
 
 int ssl_init(void);
 int ssl_configure(GLOBAL_OPTIONS *);
@@ -464,6 +469,7 @@
     FD *ssl_rfd, *ssl_wfd; /* read and write SSL descriptors */
     int sock_bytes, ssl_bytes; /* bytes written to socket and SSL */
     s_poll_set *fds; /* file descriptors */
+    uintptr_t redirect; /* redirect to another destination after failed auth */
 } CLI;
 
 CLI *alloc_client_session(SERVICE_OPTIONS *, int, int);
@@ -484,6 +490,9 @@
 #else
     ;
 #endif
+void s_ssl_write(CLI *, const void *, int);
+void s_ssl_read(CLI *, void *, int);
+char *ssl_getstring(CLI *c);
 
 /**************************************** prototype for protocol.c */
 
@@ -500,10 +509,15 @@
 /**************************************** prototypes for resolver.c */
 
 void resolver_init();
+
 int name2addr(SOCKADDR_UNION *, char *, char *);
 int hostport2addr(SOCKADDR_UNION *, char *, char *);
-int namelist2addrlist(SOCKADDR_LIST *, NAME_LIST *, char *);
-void addrlist_dup(SOCKADDR_LIST *, const SOCKADDR_LIST *);
+unsigned name2addrlist(SOCKADDR_LIST *, char *, char *);
+int hostport2addrlist(SOCKADDR_LIST *, char *, char *);
+void addrlist_init(SOCKADDR_LIST *, int);
+unsigned addrlist_dup(SOCKADDR_LIST *, const SOCKADDR_LIST *);
+unsigned addrlist_resolve(SOCKADDR_LIST *);
+
 char *s_ntop(SOCKADDR_UNION *, socklen_t);
 socklen_t addr_len(const SOCKADDR_UNION *);
 const char *s_gai_strerror(int);
diff -u -r stunnel-5.00-orig/src/resolver.c stunnel-5.00-patched/src/resolver.c
--- stunnel-5.00-orig/src/resolver.c	2014-03-06 00:26:04.000000000 +0100
+++ stunnel-5.00-patched/src/resolver.c	2015-05-26 10:42:55.652896506 +0200
@@ -40,8 +40,8 @@
 
 /**************************************** prototypes */
 
-NOEXPORT int name2addrlist(SOCKADDR_LIST *, char *, char *);
 NOEXPORT int hostport2addrlist(SOCKADDR_LIST *, char *, char *);
+NOEXPORT void addrlist2addr(SOCKADDR_UNION *, SOCKADDR_LIST *);
 
 #ifndef HAVE_GETADDRINFO
 
@@ -119,46 +119,60 @@
 /**************************************** stunnel resolver API */
 
 int name2addr(SOCKADDR_UNION *addr, char *name, char *default_host) {
-    SOCKADDR_LIST addr_list;
+    SOCKADDR_LIST *addr_list;
     int retval;
 
-    addr_list.num=0;
-    addr_list.addr=NULL;
-    retval=name2addrlist(&addr_list, name, default_host);
-    if(retval>0)
-        memcpy(addr, &addr_list.addr[0], sizeof *addr);
-    if(addr_list.addr)
-        str_free(addr_list.addr);
+    addr_list=str_alloc(sizeof(SOCKADDR_LIST));
+    addrlist_init(addr_list, 1);
+    retval=name2addrlist(addr_list, name, default_host);
+    if(retval)
+        addrlist2addr(addr, addr_list);
+    if(addr_list->addr)
+        str_free(addr_list->addr);
+    str_free(addr_list);
     return retval;
 }
 
-int hostport2addr(SOCKADDR_UNION *addr, char *hostname, char *portname) {
-    SOCKADDR_LIST addr_list;
+int hostport2addr(SOCKADDR_UNION *addr, char *host_name, char *port_name) {
+    SOCKADDR_LIST *addr_list;
     int retval;
 
-    addr_list.num=0;
-    addr_list.addr=NULL;
-    retval=hostport2addrlist(&addr_list, hostname, portname);
-    if(retval>0)
-        memcpy(addr, &addr_list.addr[0], sizeof *addr);
-    if(addr_list.addr)
-        str_free(addr_list.addr);
+    addr_list=str_alloc(sizeof(SOCKADDR_LIST));
+    addrlist_init(addr_list, 1);
+    retval=hostport2addrlist(addr_list, host_name, port_name);
+    if(retval)
+        addrlist2addr(addr, addr_list);
+    if(addr_list->addr)
+        str_free(addr_list->addr);
+    str_free(addr_list);
     return retval;
 }
 
-int namelist2addrlist(SOCKADDR_LIST *addr_list, NAME_LIST *name_list, char *default_host) {
-    /* recursive implementation to reverse the list */
-    if(!name_list)
-        return 0;
-    return namelist2addrlist(addr_list, name_list->next, default_host) +
-        name2addrlist(addr_list, name_list->name, default_host);
-}
+NOEXPORT void addrlist2addr(SOCKADDR_UNION *addr, SOCKADDR_LIST *addr_list) {
+    int i;
 
-NOEXPORT int name2addrlist(SOCKADDR_LIST *addr_list, char *name, char *default_host) {
-    char *tmp, *hostname, *portname;
-    int retval;
+    for(i=0; i<addr_list->num; ++i) { /* find the first IPv4 address */
+        if(addr_list->addr[i].in.sin_family==AF_INET) {
+            memcpy(addr, &addr_list->addr[i], sizeof(SOCKADDR_UNION));
+            return;
+        }
+    }
+#ifdef USE_IPv6
+    for(i=0; i<addr_list->num; ++i) { /* find the first IPv6 address */
+        if(addr_list->addr[i].in.sin_family==AF_INET6) {
+            memcpy(addr, &addr_list->addr[i], sizeof(SOCKADDR_UNION));
+            return;
+        }
+    }
+#endif
+    /* copy the first address resolved (curently AF_UNIX) */
+    memcpy(addr, &addr_list->addr[0], sizeof(SOCKADDR_UNION));
+}
 
-    addr_list->cur=0; /* reset round-robin counter */
+unsigned name2addrlist(SOCKADDR_LIST *addr_list, char *name, char *default_host)
+{
+    char *tmp, *host_name, *port_name;
+    unsigned retval;
 
     /* first check if this is a UNIX socket */
 #ifdef HAVE_STRUCT_SOCKADDR_UN
@@ -176,25 +190,25 @@
     }
 #endif
 
-    /* set hostname and portname */
+    /* set host_name and port_name */
     tmp=str_dup(name);
-    portname=strrchr(tmp, ':');
-    if(portname) {
-        hostname=tmp;
-        *portname++='\0';
+    port_name=strrchr(tmp, ':');
+    if(port_name) {
+        host_name=tmp;
+        *port_name++='\0';
     } else { /* no ':' - use default host IP */
-        hostname=default_host;
-        portname=tmp;
+        host_name=default_host;
+        port_name=tmp;
     }
 
     /* fill addr_list structure */
-    retval=hostport2addrlist(addr_list, hostname, portname);
+    retval=hostport2addrlist(addr_list, host_name, port_name);
     str_free(tmp);
     return retval;
 }
 
 NOEXPORT int hostport2addrlist(SOCKADDR_LIST *addr_list,
-        char *hostname, char *portname) {
+        char *host_name, char *port_name) {
     struct addrinfo hints, *res=NULL, *cur;
     int err, retries=0;
 
@@ -207,7 +221,7 @@
     hints.ai_socktype=SOCK_STREAM;
     hints.ai_protocol=IPPROTO_TCP;
     for(;;) {
-        err=getaddrinfo(hostname, portname, &hints, &res);
+        err=getaddrinfo(host_name, port_name, &hints, &res);
         if(err && res)
             freeaddrinfo(res);
         if(err!=EAI_AGAIN || ++retries>=3)
@@ -219,11 +233,11 @@
     case 0:
         break; /* success */
     case EAI_SERVICE:
-        s_log(LOG_ERR, "Unknown TCP service '%s'", portname);
+        s_log(LOG_ERR, "Unknown TCP service '%s'", port_name);
         return 0; /* error */
     default:
         s_log(LOG_ERR, "Error resolving '%s': %s",
-            hostname, s_gai_strerror(err));
+            host_name, s_gai_strerror(err));
         return 0; /* error */
     }
 
@@ -243,12 +257,38 @@
     return addr_list->num; /* ok - return the number of addresses */
 }
 
-void addrlist_dup(SOCKADDR_LIST *dst, const SOCKADDR_LIST *src) {
+void addrlist_init(SOCKADDR_LIST *addr_list, int clear_names) {
+    addr_list->num=0;
+    if(addr_list->addr)
+        str_free(addr_list->addr);
+    addr_list->addr=NULL;
+    addr_list->rr_val=0; /* reset round-robin counter */
+    /* allow structures created with sockaddr_dup() to modify
+     * the original rr_val rather than its local copy */
+    addr_list->rr_ptr=&addr_list->rr_val;
+    if(clear_names)
+        addr_list->names=NULL;
+}
+
+unsigned addrlist_dup(SOCKADDR_LIST *dst, const SOCKADDR_LIST *src) {
     memcpy(dst, src, sizeof(SOCKADDR_LIST));
-    if(src->addr) {
+    if(src->num) {
         dst->addr=str_alloc(src->num*sizeof(SOCKADDR_UNION));
         memcpy(dst->addr, src->addr, src->num*sizeof(SOCKADDR_UNION));
+    } else { /* delayed resolver */
+        addrlist_resolve(dst);
     }
+	return dst->num;
+}
+
+unsigned addrlist_resolve(SOCKADDR_LIST *addr_list) {
+    unsigned num=0;
+    NAME_LIST *host;
+
+    addrlist_init(addr_list, 0);
+    for(host=addr_list->names; host; host=host->next)
+        num+=name2addrlist(addr_list, host->name, DEFAULT_LOOPBACK);
+    return num;
 }
 
 char *s_ntop(SOCKADDR_UNION *addr, socklen_t addrlen) {
diff -u -r stunnel-5.00-orig/src/ssl.c stunnel-5.00-patched/src/ssl.c
--- stunnel-5.00-orig/src/ssl.c	2014-03-06 00:26:08.000000000 +0100
+++ stunnel-5.00-patched/src/ssl.c	2015-05-26 10:42:55.652896506 +0200
@@ -43,15 +43,21 @@
 NOEXPORT int init_prng(GLOBAL_OPTIONS *);
 NOEXPORT int add_rand_file(GLOBAL_OPTIONS *, const char *);
 
-int cli_index, opt_index; /* to keep structure for callbacks */
+int cli_index, opt_index, redirect_index; /* to keep structure for callbacks */
 
 int ssl_init(void) { /* init SSL before parsing configuration file */
     SSL_load_error_strings();
     SSL_library_init();
-    cli_index=SSL_get_ex_new_index(0, "cli index", NULL, NULL, NULL);
-    opt_index=SSL_CTX_get_ex_new_index(0, "opt index", NULL, NULL, NULL);
-    if(cli_index<0 || opt_index<0)
+    cli_index=SSL_get_ex_new_index(0, "cli pointer index",
+        NULL, NULL, NULL);
+    opt_index=SSL_CTX_get_ex_new_index(0, "opt pointer index",
+        NULL, NULL, NULL);
+    redirect_index=SSL_SESSION_get_ex_new_index(0, "redirect value index",
+        NULL, NULL, NULL);
+    if(cli_index<0 || opt_index<0 || redirect_index<0) {
+        s_log(LOG_ERR, "Application specific data initialization failed");
         return 1;
+    }
 #ifdef HAVE_OSSL_ENGINE_H
     ENGINE_load_builtin_engines();
 #endif
diff -u -r stunnel-5.00-orig/src/verify.c stunnel-5.00-patched/src/verify.c
--- stunnel-5.00-orig/src/verify.c	2014-03-06 00:26:39.000000000 +0100
+++ stunnel-5.00-patched/src/verify.c	2015-05-26 10:42:55.652896506 +0200
@@ -188,15 +188,8 @@
         return 1; /* accept */
     if(c->opt->option.client || c->opt->protocol>=0)
         return 0; /* reject */
-    if(c->opt->redirect_addr.num) { /* pre-resolved addresses */
-        addrlist_dup(&c->connect_addr, &c->opt->redirect_addr);
-        s_log(LOG_INFO, "Redirecting connection");
-        return 1; /* accept */
-    }
-    /* delayed lookup */
-    if(namelist2addrlist(&c->connect_addr,
-            c->opt->redirect_list, DEFAULT_LOOPBACK)) {
-        s_log(LOG_INFO, "Redirecting connection");
+    if(c->opt->redirect_addr.names) {
+        c->redirect=REDIRECT_ON;
         return 1; /* accept */
     }
     return 0; /* reject */
openSUSE Build Service is sponsored by