[BACK]Return to s_server.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Diff for /src/usr.bin/openssl/s_server.c between version 1.41 and 1.42

version 1.41, 2020/07/27 12:29:51 version 1.42, 2020/07/27 13:06:13
Line 177 
Line 177 
 #include "s_apps.h"  #include "s_apps.h"
 #include "timeouts.h"  #include "timeouts.h"
   
   static void s_server_init(void);
   static void sv_usage(void);
   static void print_stats(BIO *bp, SSL_CTX *ctx);
 static int sv_body(char *hostname, int s, unsigned char *context);  static int sv_body(char *hostname, int s, unsigned char *context);
 static int www_body(char *hostname, int s, unsigned char *context);  
 static void close_accept_socket(void);  static void close_accept_socket(void);
 static void sv_usage(void);  
 static int init_ssl_connection(SSL *s);  static int init_ssl_connection(SSL *s);
 static void print_stats(BIO *bp, SSL_CTX *ctx);  
 static int  
 generate_session_id(const SSL *ssl, unsigned char *id,  
     unsigned int *id_len);  
 #ifndef OPENSSL_NO_DH  #ifndef OPENSSL_NO_DH
 static DH *load_dh_param(const char *dhfile);  static DH *load_dh_param(const char *dhfile);
 #endif  #endif
   static int www_body(char *hostname, int s, unsigned char *context);
 static void s_server_init(void);  static int generate_session_id(const SSL *ssl, unsigned char *id,
       unsigned int *id_len);
   static int ssl_servername_cb(SSL *s, int *ad, void *arg);
   static int cert_status_cb(SSL * s, void *arg);
   static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
       const unsigned char *in, unsigned int inlen, void *arg);
 /* static int load_CA(SSL_CTX *ctx, char *file);*/  /* static int load_CA(SSL_CTX *ctx, char *file);*/
   
 #define BUFSIZZ 16*1024  #define BUFSIZZ 16*1024
Line 205 
Line 206 
 static SSL_CTX *ctx = NULL;  static SSL_CTX *ctx = NULL;
 static SSL_CTX *ctx2 = NULL;  static SSL_CTX *ctx2 = NULL;
 static BIO *bio_s_out = NULL;  static BIO *bio_s_out = NULL;
 static int cert_status_cb(SSL * s, void *arg);  
   
   static int local_argc = 0;
   static char **local_argv;
   
 /* This is a context that we pass to callbacks */  /* This is a context that we pass to callbacks */
 typedef struct tlsextctx_st {  typedef struct tlsextctx_st {
         char *servername;          char *servername;
Line 224 
Line 227 
         int verbose;          int verbose;
 } tlsextstatusctx;  } tlsextstatusctx;
   
   /* This the context that we pass to alpn_cb */
   typedef struct tlsextalpnctx_st {
           unsigned char *data;
           unsigned short len;
   } tlsextalpnctx;
   
 static struct {  static struct {
         char *alpn_in;          char *alpn_in;
         char *npn_in; /* Ignored. */          char *npn_in; /* Ignored. */
Line 1002 
Line 1011 
         fprintf(stderr, "\n");          fprintf(stderr, "\n");
 }  }
   
 static int local_argc = 0;  
 static char **local_argv;  
   
 static int  
 ssl_servername_cb(SSL *s, int *ad, void *arg)  
 {  
         tlsextctx *p = (tlsextctx *) arg;  
         const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);  
         if (servername && p->biodebug)  
                 BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n", servername);  
   
         if (!p->servername)  
                 return SSL_TLSEXT_ERR_NOACK;  
   
         if (servername) {  
                 if (strcmp(servername, p->servername))  
                         return p->extension_error;  
                 if (ctx2) {  
                         BIO_printf(p->biodebug, "Switching server context.\n");  
                         SSL_set_SSL_CTX(s, ctx2);  
                 }  
         }  
         return SSL_TLSEXT_ERR_OK;  
 }  
   
 /* Certificate Status callback. This is called when a client includes a  
  * certificate status request extension.  
  *  
  * This is a simplified version. It examines certificates each time and  
  * makes one OCSP responder query for each request.  
  *  
  * A full version would store details such as the OCSP certificate IDs and  
  * minimise the number of OCSP responses by caching them until they were  
  * considered "expired".  
  */  
   
 static int  
 cert_status_cb(SSL *s, void *arg)  
 {  
         tlsextstatusctx *srctx = arg;  
         BIO *err = srctx->err;  
         char *host = NULL, *port = NULL, *path = NULL;  
         int use_ssl;  
         unsigned char *rspder = NULL;  
         int rspderlen;  
         STACK_OF(OPENSSL_STRING) *aia = NULL;  
         X509 *x = NULL;  
         X509_STORE_CTX inctx;  
         X509_OBJECT obj;  
         OCSP_REQUEST *req = NULL;  
         OCSP_RESPONSE *resp = NULL;  
         OCSP_CERTID *id = NULL;  
         STACK_OF(X509_EXTENSION) *exts;  
         int ret = SSL_TLSEXT_ERR_NOACK;  
         int i;  
   
         if (srctx->verbose)  
                 BIO_puts(err, "cert_status: callback called\n");  
         /* Build up OCSP query from server certificate */  
         x = SSL_get_certificate(s);  
         aia = X509_get1_ocsp(x);  
         if (aia) {  
                 if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),  
                         &host, &port, &path, &use_ssl)) {  
                         BIO_puts(err, "cert_status: can't parse AIA URL\n");  
                         goto err;  
                 }  
                 if (srctx->verbose)  
                         BIO_printf(err, "cert_status: AIA URL: %s\n",  
                             sk_OPENSSL_STRING_value(aia, 0));  
         } else {  
                 if (!srctx->host) {  
                         BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n");  
                         goto done;  
                 }  
                 host = srctx->host;  
                 path = srctx->path;  
                 port = srctx->port;  
                 use_ssl = srctx->use_ssl;  
         }  
   
         if (!X509_STORE_CTX_init(&inctx,  
                 SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),  
                 NULL, NULL))  
                 goto err;  
         if (X509_STORE_get_by_subject(&inctx, X509_LU_X509,  
                 X509_get_issuer_name(x), &obj) <= 0) {  
                 BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n");  
                 X509_STORE_CTX_cleanup(&inctx);  
                 goto done;  
         }  
         req = OCSP_REQUEST_new();  
         if (!req)  
                 goto err;  
         id = OCSP_cert_to_id(NULL, x, obj.data.x509);  
         X509_free(obj.data.x509);  
         X509_STORE_CTX_cleanup(&inctx);  
         if (!id)  
                 goto err;  
         if (!OCSP_request_add0_id(req, id))  
                 goto err;  
         id = NULL;  
         /* Add any extensions to the request */  
         SSL_get_tlsext_status_exts(s, &exts);  
         for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {  
                 X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);  
                 if (!OCSP_REQUEST_add_ext(req, ext, -1))  
                         goto err;  
         }  
         resp = process_responder(err, req, host, path, port, use_ssl, NULL,  
             srctx->timeout);  
         if (!resp) {  
                 BIO_puts(err, "cert_status: error querying responder\n");  
                 goto done;  
         }  
         rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);  
         if (rspderlen <= 0)  
                 goto err;  
         SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);  
         if (srctx->verbose) {  
                 BIO_puts(err, "cert_status: ocsp response sent:\n");  
                 OCSP_RESPONSE_print(err, resp, 2);  
         }  
         ret = SSL_TLSEXT_ERR_OK;  
  done:  
         if (ret != SSL_TLSEXT_ERR_OK)  
                 ERR_print_errors(err);  
         if (aia) {  
                 free(host);  
                 free(path);  
                 free(port);  
                 X509_email_free(aia);  
         }  
         if (id)  
                 OCSP_CERTID_free(id);  
         if (req)  
                 OCSP_REQUEST_free(req);  
         if (resp)  
                 OCSP_RESPONSE_free(resp);  
         return ret;  
  err:  
         ret = SSL_TLSEXT_ERR_ALERT_FATAL;  
         goto done;  
 }  
   
 /* This the context that we pass to alpn_cb */  
 typedef struct tlsextalpnctx_st {  
         unsigned char *data;  
         unsigned short len;  
 } tlsextalpnctx;  
   
 static int  
 alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,  
     const unsigned char *in, unsigned int inlen, void *arg)  
 {  
         tlsextalpnctx *alpn_ctx = arg;  
   
         if (!s_server_config.quiet) {  
                 /* We can assume that in is syntactically valid. */  
                 unsigned i;  
   
                 BIO_printf(bio_s_out,  
                     "ALPN protocols advertised by the client: ");  
                 for (i = 0; i < inlen; ) {  
                         if (i)  
                                 BIO_write(bio_s_out, ", ", 2);  
                         BIO_write(bio_s_out, &in[i + 1], in[i]);  
                         i += in[i] + 1;  
                 }  
                 BIO_write(bio_s_out, "\n", 1);  
         }  
   
         if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data,  
             alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED)  
                 return (SSL_TLSEXT_ERR_NOACK);  
   
         if (!s_server_config.quiet) {  
                 BIO_printf(bio_s_out, "ALPN protocols selected: ");  
                 BIO_write(bio_s_out, *out, *outlen);  
                 BIO_write(bio_s_out, "\n", 1);  
         }  
   
         return (SSL_TLSEXT_ERR_OK);  
 }  
   
 int  int
 s_server_main(int argc, char *argv[])  s_server_main(int argc, char *argv[])
 {  {
Line 2343 
Line 2167 
   
 #define MAX_SESSION_ID_ATTEMPTS 10  #define MAX_SESSION_ID_ATTEMPTS 10
 static int  static int
 generate_session_id(const SSL *ssl, unsigned char *id,  generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len)
     unsigned int *id_len)  
 {  {
         unsigned int count = 0;          unsigned int count = 0;
         do {          do {
Line 2365 
Line 2188 
         if (count >= MAX_SESSION_ID_ATTEMPTS)          if (count >= MAX_SESSION_ID_ATTEMPTS)
                 return 0;                  return 0;
         return 1;          return 1;
   }
   
   static int
   ssl_servername_cb(SSL *s, int *ad, void *arg)
   {
           tlsextctx *p = (tlsextctx *) arg;
           const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
           if (servername && p->biodebug)
                   BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n", servername);
   
           if (!p->servername)
                   return SSL_TLSEXT_ERR_NOACK;
   
           if (servername) {
                   if (strcmp(servername, p->servername))
                           return p->extension_error;
                   if (ctx2) {
                           BIO_printf(p->biodebug, "Switching server context.\n");
                           SSL_set_SSL_CTX(s, ctx2);
                   }
           }
           return SSL_TLSEXT_ERR_OK;
   }
   
   /* Certificate Status callback. This is called when a client includes a
    * certificate status request extension.
    *
    * This is a simplified version. It examines certificates each time and
    * makes one OCSP responder query for each request.
    *
    * A full version would store details such as the OCSP certificate IDs and
    * minimise the number of OCSP responses by caching them until they were
    * considered "expired".
    */
   
   static int
   cert_status_cb(SSL *s, void *arg)
   {
           tlsextstatusctx *srctx = arg;
           BIO *err = srctx->err;
           char *host = NULL, *port = NULL, *path = NULL;
           int use_ssl;
           unsigned char *rspder = NULL;
           int rspderlen;
           STACK_OF(OPENSSL_STRING) *aia = NULL;
           X509 *x = NULL;
           X509_STORE_CTX inctx;
           X509_OBJECT obj;
           OCSP_REQUEST *req = NULL;
           OCSP_RESPONSE *resp = NULL;
           OCSP_CERTID *id = NULL;
           STACK_OF(X509_EXTENSION) *exts;
           int ret = SSL_TLSEXT_ERR_NOACK;
           int i;
   
           if (srctx->verbose)
                   BIO_puts(err, "cert_status: callback called\n");
           /* Build up OCSP query from server certificate */
           x = SSL_get_certificate(s);
           aia = X509_get1_ocsp(x);
           if (aia) {
                   if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
                           &host, &port, &path, &use_ssl)) {
                           BIO_puts(err, "cert_status: can't parse AIA URL\n");
                           goto err;
                   }
                   if (srctx->verbose)
                           BIO_printf(err, "cert_status: AIA URL: %s\n",
                               sk_OPENSSL_STRING_value(aia, 0));
           } else {
                   if (!srctx->host) {
                           BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n");
                           goto done;
                   }
                   host = srctx->host;
                   path = srctx->path;
                   port = srctx->port;
                   use_ssl = srctx->use_ssl;
           }
   
           if (!X509_STORE_CTX_init(&inctx,
                   SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
                   NULL, NULL))
                   goto err;
           if (X509_STORE_get_by_subject(&inctx, X509_LU_X509,
                   X509_get_issuer_name(x), &obj) <= 0) {
                   BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n");
                   X509_STORE_CTX_cleanup(&inctx);
                   goto done;
           }
           req = OCSP_REQUEST_new();
           if (!req)
                   goto err;
           id = OCSP_cert_to_id(NULL, x, obj.data.x509);
           X509_free(obj.data.x509);
           X509_STORE_CTX_cleanup(&inctx);
           if (!id)
                   goto err;
           if (!OCSP_request_add0_id(req, id))
                   goto err;
           id = NULL;
           /* Add any extensions to the request */
           SSL_get_tlsext_status_exts(s, &exts);
           for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
                   X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
                   if (!OCSP_REQUEST_add_ext(req, ext, -1))
                           goto err;
           }
           resp = process_responder(err, req, host, path, port, use_ssl, NULL,
               srctx->timeout);
           if (!resp) {
                   BIO_puts(err, "cert_status: error querying responder\n");
                   goto done;
           }
           rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
           if (rspderlen <= 0)
                   goto err;
           SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
           if (srctx->verbose) {
                   BIO_puts(err, "cert_status: ocsp response sent:\n");
                   OCSP_RESPONSE_print(err, resp, 2);
           }
           ret = SSL_TLSEXT_ERR_OK;
    done:
           if (ret != SSL_TLSEXT_ERR_OK)
                   ERR_print_errors(err);
           if (aia) {
                   free(host);
                   free(path);
                   free(port);
                   X509_email_free(aia);
           }
           if (id)
                   OCSP_CERTID_free(id);
           if (req)
                   OCSP_REQUEST_free(req);
           if (resp)
                   OCSP_RESPONSE_free(resp);
           return ret;
    err:
           ret = SSL_TLSEXT_ERR_ALERT_FATAL;
           goto done;
   }
   
   static int
   alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
       const unsigned char *in, unsigned int inlen, void *arg)
   {
           tlsextalpnctx *alpn_ctx = arg;
   
           if (!s_server_config.quiet) {
                   /* We can assume that in is syntactically valid. */
                   unsigned i;
   
                   BIO_printf(bio_s_out,
                       "ALPN protocols advertised by the client: ");
                   for (i = 0; i < inlen; ) {
                           if (i)
                                   BIO_write(bio_s_out, ", ", 2);
                           BIO_write(bio_s_out, &in[i + 1], in[i]);
                           i += in[i] + 1;
                   }
                   BIO_write(bio_s_out, "\n", 1);
           }
   
           if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data,
               alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED)
                   return (SSL_TLSEXT_ERR_NOACK);
   
           if (!s_server_config.quiet) {
                   BIO_printf(bio_s_out, "ALPN protocols selected: ");
                   BIO_write(bio_s_out, *out, *outlen);
                   BIO_write(bio_s_out, "\n", 1);
           }
   
           return (SSL_TLSEXT_ERR_OK);
 }  }

Legend:
Removed from v.1.41  
changed lines
  Added in v.1.42