PR: 1794
authorDr. Stephen Henson <steve@openssl.org>
Tue, 27 Dec 2011 14:23:22 +0000 (14:23 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 27 Dec 2011 14:23:22 +0000 (14:23 +0000)
Submitted by: Peter Sylvester <peter.sylvester@edelweb.fr>
Reviewed by: steve

- remove some unncessary SSL_err and permit
an srp user callback to allow a worker to obtain
a user verifier.

- cleanup and comments in s_server and demonstration
for asynchronous srp user lookup

apps/s_server.c
ssl/s3_srvr.c

index e89b888888bf6bfc8dd642d1d03212e36cebc485..2c02fc7d0ccda388667ba72b6ce59aca2f4f7a94 100644 (file)
@@ -380,31 +380,43 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity,
 /* This is a context that we pass to callbacks */
 typedef struct srpsrvparm_st
        {
-       int verbose;
        char *login;
        SRP_VBASE *vb;
+       SRP_user_pwd *user;
        } srpsrvparm;
 
+/* This callback pretends to require some asynchronous logic in order to obtain
+   a verifier. When the callback is called for a new connection we return
+   with a negative value. This will provoke the accept etc to return with
+   an LOOKUP_X509. The main logic of the reinvokes the suspended call 
+   (which would normally occur after a worker has finished) and we
+   set the user parameters. 
+*/
 static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
        {
-       srpsrvparm *p = (srpsrvparm *) arg;
-       SRP_user_pwd *user;
-
-       p->login = BUF_strdup(SSL_get_srp_username(s));
-       BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
+       srpsrvparm *p = (srpsrvparm *)arg;
+       if (p->login == NULL && p->user == NULL )
+               {
+               p->login = SSL_get_srp_username(s);
+               BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
+               return (-1) ;
+               }
 
-       user = SRP_VBASE_get_by_user(p->vb, p->login);
-       if (user == NULL)
+       if (p->user == NULL)
                {
                BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
                return SSL3_AL_FATAL;
                }
-       if (SSL_set_srp_server_param(s, user->N, user->g, user->s, user->v,
-                                    user->info) < 0)
+       if (SSL_set_srp_server_param(s, p->user->N, p->user->g, p->user->s, p->user->v,
+                                    p->user->info) < 0)
                {
                *ad = SSL_AD_INTERNAL_ERROR;
                return SSL3_AL_FATAL;
                }
+       BIO_printf(bio_err, "SRP parameters set: username = \"%s\" info=\"%s\" \n", p->login,p->user->info);
+       /* need to check whether there are memory leaks */
+       p->user = NULL;
+       p->login = NULL;
        return SSL_ERROR_NONE;
        }
 
@@ -908,6 +920,9 @@ int MAIN(int, char **);
 #ifndef OPENSSL_NO_JPAKE
 static char *jpake_secret = NULL;
 #endif
+#ifndef OPENSSL_NO_SRP
+       static srpsrvparm srp_callback_parm;
+#endif
 static char *srtp_profiles = NULL;
 
 int MAIN(int argc, char *argv[])
@@ -953,7 +968,6 @@ int MAIN(int argc, char *argv[])
 #ifndef OPENSSL_NO_SRP
        char *srpuserseed = NULL;
        char *srp_verifier_file = NULL;
-       srpsrvparm p;
 #endif
 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
        meth=SSLv23_server_method();
@@ -1842,8 +1856,10 @@ bad:
 #ifndef OPENSSL_NO_SRP
        if (srp_verifier_file != NULL)
                {
-               p.vb = SRP_VBASE_new(srpuserseed);
-               if ((ret = SRP_VBASE_init(p.vb, srp_verifier_file)) != SRP_NO_ERROR)
+               srp_callback_parm.vb = SRP_VBASE_new(srpuserseed);
+               srp_callback_parm.user = NULL;
+               srp_callback_parm.login = NULL;
+               if ((ret = SRP_VBASE_init(srp_callback_parm.vb, srp_verifier_file)) != SRP_NO_ERROR)
                        {
                        BIO_printf(bio_err,
                                   "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
@@ -1851,7 +1867,7 @@ bad:
                                goto end;
                        }
                SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE,verify_callback);
-               SSL_CTX_set_srp_cb_arg(ctx, &p);                        
+               SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);                        
                SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
                }
        else
@@ -2219,6 +2235,16 @@ static int sv_body(char *hostname, int s, unsigned char *context)
 { static count=0; if (++count == 100) { count=0; SSL_renegotiate(con); } }
 #endif
                                k=SSL_write(con,&(buf[l]),(unsigned int)i);
+                               while (SSL_get_error(con,k) == SSL_ERROR_WANT_X509_LOOKUP)
+                                       {
+                                       BIO_printf(bio_s_out,"LOOKUP renego during write\n");
+                                       srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); 
+                                       if (srp_callback_parm.user) 
+                                               BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info);
+                                       else 
+                                               BIO_printf(bio_s_out,"LOOKUP not successful\n");
+                                               k=SSL_write(con,&(buf[l]),(unsigned int)i);
+                                       }
                                switch (SSL_get_error(con,k))
                                        {
                                case SSL_ERROR_NONE:
@@ -2266,6 +2292,16 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                                {
 again: 
                                i=SSL_read(con,(char *)buf,bufsize);
+                               while (SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP)
+                                       {
+                                       BIO_printf(bio_s_out,"LOOKUP renego during read\n");
+                                       srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); 
+                                       if (srp_callback_parm.user) 
+                                               BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info);
+                                       else 
+                                               BIO_printf(bio_s_out,"LOOKUP not successful\n");
+                                       i=SSL_read(con,(char *)buf,bufsize);
+                                       }
                                switch (SSL_get_error(con,i))
                                        {
                                case SSL_ERROR_NONE:
@@ -2278,7 +2314,6 @@ again:
                                        break;
                                case SSL_ERROR_WANT_WRITE:
                                case SSL_ERROR_WANT_READ:
-                               case SSL_ERROR_WANT_X509_LOOKUP:
                                        BIO_printf(bio_s_out,"Read BLOCK\n");
                                        break;
                                case SSL_ERROR_SYSCALL:
@@ -2343,7 +2378,18 @@ static int init_ssl_connection(SSL *con)
        unsigned char *exportedkeymat;
 
 
-       if ((i=SSL_accept(con)) <= 0)
+       i=SSL_accept(con);
+       while (i <= 0 &&  SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP) 
+               {
+                       BIO_printf(bio_s_out,"LOOKUP during accept %s\n",srp_callback_parm.login);
+                       srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); 
+                       if (srp_callback_parm.user) 
+                               BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info);
+                       else 
+                               BIO_printf(bio_s_out,"LOOKUP not successful\n");
+                       i=SSL_accept(con);
+               }
+       if (i <= 0)
                {
                if (BIO_sock_should_retry(i))
                        {
@@ -2567,6 +2613,16 @@ static int www_body(char *hostname, int s, unsigned char *context)
                if (hack)
                        {
                        i=SSL_accept(con);
+                       while (i <= 0 &&  SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP) 
+               {
+                       BIO_printf(bio_s_out,"LOOKUP during accept %s\n",srp_callback_parm.login);
+                       srp_callback_parm.user = SRP_VBASE_get_by_user(srp_callback_parm.vb, srp_callback_parm.login); 
+                       if (srp_callback_parm.user) 
+                               BIO_printf(bio_s_out,"LOOKUP done %s\n",srp_callback_parm.user->info);
+                       else 
+                               BIO_printf(bio_s_out,"LOOKUP not successful\n");
+                       i=SSL_accept(con);
+               }
 
                        switch (SSL_get_error(con,i))
                                {
index bae14c17e59ceb8921f12922e006dcad3c8bc777..3609aba5f29953b7d0c38f94dd6b1cbabdab2ad5 100644 (file)
@@ -338,16 +338,27 @@ int ssl3_accept(SSL *s)
                case SSL3_ST_SR_CLNT_HELLO_C:
 
                        s->shutdown=0;
-
-                       ret=ssl3_get_client_hello(s);
-                       if (ret <= 0) goto end;
+                       if (s->rwstate != SSL_X509_LOOKUP)
+                       {
+                               ret=ssl3_get_client_hello(s);
+                               if (ret <= 0) goto end;
+                       }
 #ifndef OPENSSL_NO_SRP
                        {
                        int al;
-                       if ((ret = ssl_check_srp_ext_ClientHello(s,&al)) != SSL_ERROR_NONE)
+                       if ((ret = ssl_check_srp_ext_ClientHello(s,&al))  < 0)
+                                       {
+                                       /* callback indicates firther work to be done */
+                                       s->rwstate=SSL_X509_LOOKUP;
+                                       goto end;
+                                       }
+                       if (ret != SSL_ERROR_NONE)
                                {
-                               ssl3_send_alert(s,SSL3_AL_FATAL,al);                            
-                               SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT);                     
+                               ssl3_send_alert(s,SSL3_AL_FATAL,al);    
+                               /* This is not really an error but the only means to
+                                   for a client to detect whether srp is supported. */
+                                  if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)      
+                                       SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT);                     
                                ret = SSL_TLSEXT_ERR_ALERT_FATAL;                       
                                ret= -1;
                                goto end;