Converting crypto/bio/b_sock.c and ssl/ssl-cert.c to call gethostbyname_r(),
getservbyname_r(), and readdir_r() instead of the non-reentrant functions when
threads are enabled turns out to be ugly.  The reentrant function semantics
aren't standard across popular platforms that support threads (Solaris 2.X,
HPUX 10.X, etc.).  Apparently those functions were added to the platforms
before POSIX standardized them.  Also the xxx_r() functions require large
buffers that complicate life on limited memory systems (Win 3.1).

Here are patches that instead use locks to serialize access to the non-reentrant
functions.  The purpose of the existing lock CRYPTO_LOCK_BIO_GETHOSTBYNAME is
slightly changed and it's name is changed to CRYPTO_LOCK_GETHOSTBYNAME, and
there are 2 new locks CRYPTO_LOCK_GETSERVBYNAME and CRYPTO_LOCK_READDIR.

There's a new define BIO_F_BIO_GETHOSTBYNAME in bio.h.  Does anything else need
to be done to add it, or is the define in bio.h enough?

These patches also fix some bugs in b_sock.c where it didn't correctly handle
Malloc() returning NULL and didn't report an error when it happened, and it
sometimes didn't unlock.

With these changes threaded apps will need to wrap calls they make to the non-
reentrant C library functions that are used within openssl with CRYPTO_w_lock()
/ CRYPTO_w_unlock().  Openssl provides BIO_gethostbyname() and BIO_get_port()
to perform gethostbyname() and getservbyname() safely.  Apps should not wrap
them with more locks.

Index: crypto/cryptlib.c
===================================================================
RCS file: /e/openssl/cvs/openssl/crypto/cryptlib.c,v
retrieving revision 1.6
diff -u -r1.6 cryptlib.c
--- cryptlib.c  1999/04/26 22:20:02     1.6
+++ cryptlib.c  1999/05/06 17:11:42
@@ -88,8 +88,10 @@
        "rand",
        "debug_malloc",
        "BIO",
-       "bio_gethostbyname",
+       "gethostbyname",
        "RSA_blinding",
+       "getservbyname",
+       "readdir",
        };
 
 static STACK *app_locks=NULL;

Index: crypto/crypto.h
===================================================================
RCS file: /e/openssl/cvs/openssl/crypto/crypto.h,v
retrieving revision 1.12
diff -u -r1.12 crypto.h
--- crypto.h    1999/04/26 16:40:15     1.12
+++ crypto.h    1999/05/06 17:12:19
@@ -102,9 +102,11 @@
 #define        CRYPTO_LOCK_RAND                16
 #define        CRYPTO_LOCK_MALLOC              17
 #define        CRYPTO_LOCK_BIO                 18
-#define        CRYPTO_LOCK_BIO_GETHOSTBYNAME   19
+#define        CRYPTO_LOCK_GETHOSTBYNAME       19
 #define CRYPTO_LOCK_RSA_BLINDING       20
-#define        CRYPTO_NUM_LOCKS                21
+#define        CRYPTO_LOCK_GETSERVBYNAME       21
+#define        CRYPTO_LOCK_READDIR             22
+#define        CRYPTO_NUM_LOCKS                23
 
 #define CRYPTO_LOCK            1
 #define CRYPTO_UNLOCK          2

Index: crypto/bio/b_sock.c
===================================================================
RCS file: /e/openssl/cvs/openssl/crypto/bio/b_sock.c,v
retrieving revision 1.10
diff -u -r1.10 b_sock.c
--- b_sock.c    1999/04/26 16:40:58     1.10
+++ b_sock.c    1999/05/06 16:31:16
@@ -139,6 +139,7 @@
        {
        int i;
        struct servent *s;
+       unsigned short s_port;
 
        if (str == NULL)
                {
@@ -150,26 +151,30 @@
                *port_ptr=(unsigned short)i;
        else
                {
+               CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
                s=getservbyname(str,"tcp");
+               if(s != NULL)
+                       s_port=s->s_port;
+               CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
                if (s == NULL)
                        {
                        if (strcmp(str,"http") == 0)
-                               *port_ptr=80;
+                               s_port=80;
                        else if (strcmp(str,"telnet") == 0)
-                               *port_ptr=23;
+                               s_port=23;
                        else if (strcmp(str,"socks") == 0)
-                               *port_ptr=1080;
+                               s_port=1080;
                        else if (strcmp(str,"https") == 0)
-                               *port_ptr=443;
+                               s_port=443;
                        else if (strcmp(str,"ssl") == 0)
-                               *port_ptr=443;
+                               s_port=443;
                        else if (strcmp(str,"ftp") == 0)
-                               *port_ptr=21;
+                               s_port=21;
                        else if (strcmp(str,"gopher") == 0)
-                               *port_ptr=70;
+                               s_port=70;
 #if 0
                        else if (strcmp(str,"wais") == 0)
-                               *port_ptr=21;
+                               s_port=21;
 #endif
                        else
                                {
@@ -177,9 +182,8 @@
                                ERR_add_error_data(3,"service='",str,"'");
                                return(0);
                                }
-                       return(1);
                        }
-               *port_ptr=htons((unsigned short)s->s_port);
+               *port_ptr=htons(s_port);
                }
        return(1);
        }
@@ -253,16 +257,16 @@
        for (i=0; a->h_aliases[i] != NULL; i++)
                ;
        i++;
-       ret->h_aliases=(char **)Malloc(sizeof(char *)*i);
+       if((ret->h_aliases=(char **)Malloc(sizeof(char *)*i)) == NULL)
+               goto err;
        memset(ret->h_aliases,0,sizeof(char *)*i);
-       if (ret == NULL) goto err;
 
        for (i=0; a->h_addr_list[i] != NULL; i++)
                ;
        i++;
-       ret->h_addr_list=(char **)Malloc(sizeof(char *)*i);
+       if((ret->h_addr_list=(char **)Malloc(sizeof(char *)*i)) == NULL)
+               goto err;
        memset(ret->h_addr_list,0,sizeof(char *)*i);
-       if (ret->h_addr_list == NULL) goto err;
 
        j=strlen(a->h_name)+1;
        if ((ret->h_name=Malloc(j)) == NULL) goto err;
@@ -323,7 +327,7 @@
 
 /*     return(gethostbyname(name)); */
 
-       CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
+       CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
        j=strlen(name);
        if (j < 128)
                {
@@ -349,15 +353,22 @@
                BIO_ghbn_miss++;
                ret=gethostbyname(name);
 
-               if (ret == NULL) return(NULL);
-               if (j > 128) return(ret); /* too big to cache */
+               if (ret == NULL)
+                       goto end;
+               if (j > 128) /* too big to cache */
+                       goto end;
 
                /* else add to cache */
                if (ghbn_cache[lowi].ent != NULL)
                        ghbn_free(ghbn_cache[lowi].ent);
+               ghbn_cache[lowi].name[0] = '\0';
 
+               if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL)
+                       {
+                       BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE);
+                       goto end;
+                       }
                strncpy(ghbn_cache[lowi].name,name,128);
-               ghbn_cache[lowi].ent=ghbn_dup(ret);
                ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
                }
        else
@@ -366,7 +377,8 @@
                ret= ghbn_cache[i].ent;
                ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
                }
-       CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
+end:
+       CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
        return(ret);
        }
 
Index: crypto/bio/bio.h
===================================================================
RCS file: /e/openssl/cvs/openssl/crypto/bio/bio.h,v
retrieving revision 1.15
diff -u -r1.15 bio.h
--- bio.h       1999/05/05 12:35:19     1.15
+++ bio.h       1999/05/06 14:50:42
@@ -562,6 +562,7 @@
 #define BIO_F_MEM_WRITE                                         117
 #define BIO_F_SSL_NEW                                   118
 #define BIO_F_WSASTARTUP                                119
+#define BIO_F_BIO_GETHOSTBYNAME                                 120
 
 /* Reason codes. */
 #define BIO_R_ACCEPT_ERROR                              100

Index: ssl/ssl_cert.c
===================================================================
RCS file: /e/openssl/cvs/openssl/ssl/ssl_cert.c,v
retrieving revision 1.14
diff -u -r1.14 ssl_cert.c
--- ssl_cert.c  1999/05/03 19:55:00     1.14
+++ ssl_cert.c  1999/05/06 16:28:26
@@ -448,18 +448,20 @@
        SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,ERR_R_MALLOC_FAILURE);
        return 0;
        }
-
+    CRYPTO_w_lock(CRYPTO_LOCK_READDIR);
     while((dstruct=readdir(d)))
        {
        char buf[1024];
 
        if(strlen(dir)+strlen(dstruct->d_name)+2 > sizeof buf)
            {
+           CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
            SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG);
            return 0;
            }
        
        sprintf(buf,"%s/%s",dir,dstruct->d_name);
+       CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
        if(!SSL_add_file_cert_subjects_to_stack(stack,buf))
            return 0;
        }
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to