ssl.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:25k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /* ====================================================================
  2.  * Copyright (c) 1995, 1996, 1997 Ben Laurie.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer. 
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by Ben Laurie
  19.  *    for use in the Apache-SSL HTTP server project."
  20.  *
  21.  * 4. The name "Apache-SSL Server" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission.
  24.  *
  25.  * 5. Redistributions of any form whatsoever must retain the following
  26.  *    acknowledgment:
  27.  *    "This product includes software developed by Ben Laurie
  28.  *    for use in the Apache-SSL HTTP server project."
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
  31.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  33.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL BEN LAURIE OR
  34.  * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  41.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  42.  * ====================================================================
  43.  *
  44.  * This software consists of patches to the Apache HTTP server interfacing it
  45.  * to SSLeay.
  46.  * For more information on Apache-SSL, contact Ben Laurie <ben@algroup.co.uk>.
  47.  *
  48.  * For more information on Apache see http://www.apache.org.
  49.  *
  50.  * For more information on SSLeay see http://www.psy.uq.oz.au/~ftp/Crypto/.
  51.  *
  52.  */
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <stdarg.h>
  56. #include <assert.h>
  57. #include <ssl.h>
  58. #include <err.h>
  59. #include <x509.h>
  60. #include <pem.h>
  61. #include <crypto.h>
  62. #include "httpd.h"
  63. #include "http_config.h"
  64. #include "http_log.h"
  65. #if SSLEAY_VERSION_NUMBER < 0x600
  66. #define ERR_print_errors_fp ERR_print_errors
  67. #endif
  68. #if SSLEAY_VERSION_NUMBER < 0x0800
  69. #define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 
  70. VERIFY_ERR_UNABLE_TO_GET_ISSUER
  71. #define X509_V_OK VERIFY_OK
  72. #define SSL_CTX_set_default_verify_paths(ctx) SSL_set_default_verify_paths(ctx)
  73. #define SSL_CTX_load_verify_locations(ctx,cafile,capath) 
  74.  SSL_load_verify_locations(ctx,cafile,capath)
  75. #define X509_verify_cert_error_string(error) X509_cert_verify_error_string(error)
  76. #endif
  77. #if !defined(SSL_TXT_NULL)
  78. /* text strings for the ciphers */
  79. #define SSL_TXT_NULL_WITH_MD5 SSL2_TXT_NULL_WITH_MD5
  80. #define SSL_TXT_RC4_128_WITH_MD5 SSL2_TXT_RC4_128_WITH_MD5
  81. #define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5
  82. #define SSL_TXT_RC2_128_CBC_WITH_MD5 SSL2_TXT_RC2_128_CBC_WITH_MD5
  83. #define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5
  84. #define SSL_TXT_IDEA_128_CBC_WITH_MD5 SSL2_TXT_IDEA_128_CBC_WITH_MD5
  85. #define SSL_TXT_DES_64_CBC_WITH_MD5 SSL2_TXT_DES_64_CBC_WITH_MD5
  86. #define SSL_TXT_DES_64_CBC_WITH_SHA SSL2_TXT_DES_64_CBC_WITH_SHA
  87. #define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5
  88. #define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA
  89. #define SSL_TXT_DES_64_CFB64_WITH_MD5_1 SSL2_TXT_DES_64_CFB64_WITH_MD5_1
  90. #define SSL_TXT_NULL SSL2_TXT_NULL
  91. #endif
  92. #ifndef SSL_TXT_DES_64_CFB64_WITH_MD5_1
  93. /* SSLeay 0.8.0 misses this definition */
  94. #define SSL_TXT_DES_64_CFB64_WITH_MD5_1 SSL2_TXT_DES_64_CFB64_WITH_MD5_1
  95. #endif
  96. typedef enum
  97.     {
  98.     VERIFY_NONE=0,
  99.     VERIFY_OPTIONAL=1,
  100.     VERIFY_REQUIRE=2,
  101.     VERIFY_OPTIONAL_NO_CA=3
  102.     } VerifyType;
  103. typedef struct
  104.     {
  105.     BOOL bDisabled;
  106.     char *szCertificateFile;
  107.     char *szKeyFile;
  108.     char *szCACertificatePath;
  109.     char *szCACertificateFile;
  110.     char *szLogFile;
  111.     char *szReqCiphers;
  112.     FILE *fileLogFile;
  113.     int nVerifyDepth;
  114.     VerifyType nVerifyClient;
  115.     X509 *px509Certificate;
  116.     RSA *prsaKey;
  117.     SSL_CTX *pSSLCtx;
  118.     BOOL bFakeBasicAuth;
  119.     } SSLConfigRec;
  120. typedef struct
  121.     {
  122.     /* 1) If cipher is banned, refuse */
  123.     /* 2) If RequiredCiphers is NULL, accept */
  124.     /* 3) If the cipher isn't required, refuse */
  125.     table *tbRequiredCiphers;
  126.     table *tbBannedCiphers;
  127.     } SSLDirConfigRec;
  128. extern module ssl_module;
  129. static conn_rec *SSLVerifyConn;
  130. static const char *SSLRequireCipher(cmd_parms *cmd,SSLDirConfigRec *rec,char *cipher)
  131.     {
  132.     table_set(rec->tbRequiredCiphers,cipher,"Required");
  133.     return NULL;
  134.     }
  135. static const char *SSLBanCipher(cmd_parms *cmd,SSLDirConfigRec *rec,char *cipher)
  136.     {
  137.     table_set(rec->tbBannedCiphers,cipher,"Banned");
  138.     return NULL;
  139.     }
  140. static int SSLCheckCipher(request_rec *r)
  141.     {
  142.     char *cipher;
  143.     SSLDirConfigRec *rec=(SSLDirConfigRec *)
  144.       get_module_config(r->per_dir_config,&ssl_module);
  145.     SSLConfigRec *pConfig=(SSLConfigRec *)
  146.       get_module_config(r->server->module_config,&ssl_module);
  147.     /* Check to see if SSL is on */
  148.     if(pConfig->bDisabled)
  149. return DECLINED;
  150.     cipher=SSL_get_cipher(r->connection->client->ssl);
  151.     if(table_get(rec->tbBannedCiphers,cipher))
  152. {
  153. char *buf;
  154. buf=pstrcat(r->pool,"Cipher ",cipher," is forbidden",NULL);
  155. log_reason(buf,r->filename,r);
  156. return FORBIDDEN;
  157. }
  158.     if(table_get(rec->tbRequiredCiphers,cipher))
  159. return OK;
  160.     if(rec->tbRequiredCiphers->nelts == 0)
  161. return OK;
  162.     else
  163. {
  164. char *buf;
  165. buf=pstrcat(r->pool,"Cipher ",cipher," is not on the permitted list",
  166.     NULL);
  167. log_reason(buf,r->filename,r);
  168. return FORBIDDEN;
  169. }
  170.     }
  171. int SSLFixups (request_rec *r)
  172.     {
  173.     table *e=r->subprocess_env;
  174.     int keysize=0;
  175.     int secretkeysize=0;
  176.     char buf[MAX_STRING_LEN];
  177.     char *cipher;
  178.     SSLConfigRec *pConfig=(SSLConfigRec *)
  179.       get_module_config(r->server->module_config,&ssl_module);
  180.     /* Check to see if SSL is on */
  181.     if(pConfig->bDisabled)
  182. return DECLINED;
  183.     cipher=SSL_get_cipher(r->connection->client->ssl);
  184.     table_set(e,"HTTPS","on");
  185.     table_set(e,"HTTPS_CIPHER",cipher);
  186.     if(!strcmp(cipher,SSL_TXT_NULL_WITH_MD5))
  187. keysize=secretkeysize=0;
  188.     else if(!strcmp(cipher,SSL_TXT_RC4_128_WITH_MD5))
  189. keysize=secretkeysize=128;
  190.     else if(!strcmp(cipher,SSL_TXT_RC4_128_EXPORT40_WITH_MD5))
  191. { keysize=128; secretkeysize=40; }
  192.     else if(!strcmp(cipher,SSL_TXT_RC2_128_CBC_WITH_MD5))
  193. keysize=secretkeysize=128;
  194.     else if(!strcmp(cipher,SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5))
  195. { keysize=128; secretkeysize=40; }
  196.     else if(!strcmp(cipher,SSL_TXT_IDEA_128_CBC_WITH_MD5))
  197. keysize=secretkeysize=128;
  198.     else if(!strcmp(cipher,SSL_TXT_DES_64_CBC_WITH_MD5))
  199. keysize=secretkeysize=64;
  200.     else if(!strcmp(cipher,SSL_TXT_DES_64_CBC_WITH_SHA))
  201. keysize=secretkeysize=64;
  202.     else if(!strcmp(cipher,SSL_TXT_DES_192_EDE3_CBC_WITH_MD5))
  203. keysize=secretkeysize=192;
  204.     else if(!strcmp(cipher,SSL_TXT_DES_192_EDE3_CBC_WITH_SHA))
  205. keysize=secretkeysize=192;
  206.     else if(!strcmp(cipher,SSL_TXT_DES_64_CFB64_WITH_MD5_1))
  207. keysize=secretkeysize=64;
  208.     else if(!strcmp(cipher,SSL_TXT_NULL))
  209. keysize=secretkeysize=0;
  210.     sprintf(buf,"%d",keysize);
  211.     table_set(e,"HTTPS_KEYSIZE",buf);
  212.     sprintf(buf,"%d",secretkeysize);
  213.     table_set(e,"HTTPS_SECRETKEYSIZE",buf);
  214.     if(r->connection->client->szClientX509)
  215. table_set(e,"SSL_CLIENT_DN",r->connection->client->szClientX509);
  216.     return OK;
  217.     }
  218. static void SSLLogError(server_rec *s)
  219.     {
  220.     unsigned long l;
  221.     char buf[MAX_STRING_LEN];
  222.     /* Print out error messages */
  223.     while((l=ERR_get_error()))
  224.       {
  225. ERR_error_string(l,buf);
  226. log_error(buf,s);
  227.       }
  228.     }
  229. static void *CreateSSLServerConfig(pool *p,server_rec *s)
  230.     {
  231.     SSLConfigRec *rec=pcalloc(p,sizeof(SSLConfigRec));
  232.     
  233.     rec->bDisabled=FALSE;
  234.     rec->szCertificateFile=rec->szKeyFile=rec->szLogFile=NULL;
  235.     rec->nVerifyDepth=0;
  236.     rec->nVerifyClient=VERIFY_NONE;
  237.     rec->px509Certificate=NULL;
  238.     rec->prsaKey=NULL;
  239.     rec->bFakeBasicAuth=FALSE;
  240.     return rec;
  241.     }
  242. static void *CreateSSLDirConfig(pool *p,char *dummy)
  243.     {
  244.     SSLDirConfigRec *rec=pcalloc(p,sizeof(SSLDirConfigRec));
  245.     rec->tbRequiredCiphers=make_table(p,4);
  246.     rec->tbBannedCiphers=make_table(p,4);
  247.     return rec;
  248.     }
  249. static void *MergeSSLDirConfig(pool *p,void *basev,void *addv)
  250.     {
  251.     SSLDirConfigRec *base=(SSLDirConfigRec *)basev;
  252.     SSLDirConfigRec *add=(SSLDirConfigRec *)addv;
  253.     SSLDirConfigRec *new=(SSLDirConfigRec *)palloc(p,sizeof(SSLDirConfigRec));
  254.     new->tbRequiredCiphers=overlay_tables(p,add->tbRequiredCiphers,
  255.     base->tbRequiredCiphers);
  256.     new->tbBannedCiphers=overlay_tables(p,add->tbBannedCiphers,
  257.   base->tbBannedCiphers);
  258.     return new;
  259.     }
  260. static void InitSSL()
  261.     {
  262.     char *CAfile=NULL,*CApath=NULL;
  263.     SSL_load_error_strings();
  264.     ERR_load_crypto_strings();
  265. #if SSLEAY_VERSION_NUMBER >= 0x0800
  266.     SSLeay_add_ssl_algorithms();
  267. #else
  268.     SSL_debug("/tmp/ssldebug");
  269. #endif
  270.     }
  271. #if SSLEAY_VERSION_NUMBER >= 0x0800
  272. /* FIXME: This is an expensive operation which should probably be done before
  273. forking */
  274. static RSA *TmpRSACallback(SSL *pSSL,int nExport)
  275.     {
  276.     static RSA *pRSA=NULL;
  277.     if (pRSA == NULL)
  278. pRSA=RSA_generate_key(512,RSA_F4,NULL);
  279.     return pRSA;
  280.     }
  281. #endif
  282. #if SSLEAY_VERSION_NUMBER >= 0x0800
  283. int ApacheSSLVerifyCallback(int ok,X509_STORE_CTX *ctx)
  284.     {
  285.     X509 *xs=X509_STORE_CTX_get_current_cert(ctx);
  286.     int depth=X509_STORE_CTX_get_error_depth(ctx);
  287.     int error=X509_STORE_CTX_get_error(ctx);
  288. #else
  289. int ApacheSSLVerifyCallback(int ok,X509 *xs,X509 *xi,int depth,int error)
  290.     {
  291. #endif
  292.     char *s;
  293.     SSLConfigRec *pConfig=get_module_config(SSLVerifyConn->server->module_config,&ssl_module);
  294. #if SSLEAY_VERSION_NUMBER < 0x0800
  295.     s=(char *)X509_NAME_oneline(X509_get_subject_name(xs));
  296. #else
  297.     s=(char *)X509_NAME_oneline(X509_get_subject_name(xs),NULL,0);
  298. #endif
  299.     if(s == NULL)
  300. {
  301. ERR_print_errors_fp(pConfig->fileLogFile);
  302. return(0);
  303. }
  304.     if(depth == 0)
  305. SSLVerifyConn->client->szClientX509=pstrdup(SSLVerifyConn->pool,s);
  306.     fprintf(pConfig->fileLogFile,"depth=%d %sn",depth,s);
  307.     free(s);
  308.     if(error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
  309. {
  310. if(pConfig->nVerifyClient == VERIFY_OPTIONAL_NO_CA)
  311.     {
  312.     fprintf(pConfig->fileLogFile,"no issuer, returning OKn");
  313.     return TRUE;
  314.     }
  315. #if SSLEAY_VERSION_NUMBER < 0x0800
  316. s=(char *)X509_NAME_oneline(X509_get_issuer_name(xs));
  317. #else
  318. s=(char *)X509_NAME_oneline(X509_get_issuer_name(xs),NULL,0);
  319. #endif
  320. if(s == NULL)
  321.     {
  322.     fprintf(pConfig->fileLogFile,"verify errorn");
  323.     ERR_print_errors_fp(pConfig->fileLogFile);
  324.     SSLLogError(SSLVerifyConn->server);
  325.     return(0);
  326.     }
  327. fprintf(pConfig->fileLogFile,"issuer= %sn",s);
  328. free(s);
  329. }
  330.     if(!ok)
  331. {
  332. fprintf(pConfig->fileLogFile,"verify error:num=%d:%sn",error,
  333. X509_verify_cert_error_string(error));
  334. SSLLogError(SSLVerifyConn->server);
  335. SSLVerifyConn->client->szClientX509=NULL;
  336. }
  337.     if(depth >= pConfig->nVerifyDepth)
  338. {
  339. fprintf(pConfig->fileLogFile,"Verify depth exceededn");
  340. log_error("Verify depth exceeded",SSLVerifyConn->server);
  341. ok=0;
  342. }
  343.     fprintf(pConfig->fileLogFile,"verify return:%dn",ok);
  344.     return(ok);
  345.     }
  346. static int VerifyFlags(SSLConfigRec *pConfig)
  347.     {
  348.     int nVerify=0;
  349.     switch(pConfig->nVerifyClient)
  350. {
  351.     case VERIFY_REQUIRE:
  352. nVerify|=SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
  353. break;
  354.     case VERIFY_OPTIONAL:
  355.     case VERIFY_OPTIONAL_NO_CA:
  356. nVerify|=SSL_VERIFY_PEER;
  357. break;
  358. }
  359.     return nVerify;
  360.     }
  361. static void GetCertificateAndKey(server_rec *s,SSLConfigRec *pConfig)
  362.     {
  363.     char buf[1024],prompt[1024];
  364.     int n;
  365.     FILE *f;
  366.     char szPath[MAX_STRING_LEN];
  367.     if(pConfig->px509Certificate)
  368. {
  369. fprintf(stderr,"Attempt to reinitialise SSL for server %sn",
  370. s->server_hostname);
  371. return;
  372. }
  373.     fprintf(stderr,"Reading certificate and key for server %s:%dn",
  374.     s->server_hostname,s->port);
  375. #if SSLEAY_VERSION_NUMBER < 0x0800
  376.     pConfig->pSSLCtx=SSL_CTX_new();
  377. #else
  378.     pConfig->pSSLCtx=SSL_CTX_new(SSLv23_server_method());
  379.     SSL_CTX_set_verify(pConfig->pSSLCtx,VerifyFlags(pConfig),ApacheSSLVerifyCallback);
  380. #endif
  381.     if(pConfig->szReqCiphers != NULL)
  382. {
  383. if(!SSL_CTX_set_cipher_list(pConfig->pSSLCtx,pConfig->szReqCiphers))
  384.     {
  385.     fprintf(stderr,"unable to set ciphersn");
  386.     ERR_print_errors_fp(stderr);
  387.     SSLLogError(s);
  388.     }
  389. }
  390.     if(!SSL_CTX_load_verify_locations(pConfig->pSSLCtx,
  391.   pConfig->szCACertificateFile,
  392.   pConfig->szCACertificatePath)
  393.        || !SSL_CTX_set_default_verify_paths(pConfig->pSSLCtx))
  394.        {
  395.        fprintf(stderr,"error seting default verify locationsn");
  396.        ERR_print_errors_fp(stderr);
  397.        exit(1);
  398.        }
  399.     f=fopen(pConfig->szCertificateFile,"r");
  400.     if(!f)
  401. {
  402. sprintf(szPath,"%s/%s",X509_get_default_cert_dir(),
  403. pConfig->szCertificateFile);
  404. f=fopen(szPath,"r");
  405. if(!f)
  406.     {
  407.     fprintf(stderr,"Can't open certificate file %s, nor %sn",
  408.     pConfig->szCertificateFile,szPath);
  409.     exit(1);
  410.     }
  411. }
  412.     else
  413. strcpy(szPath,pConfig->szCertificateFile);  /* in case it also contains the key */
  414.     pConfig->px509Certificate=X509_new();
  415.     if(!PEM_read_X509(f,&pConfig->px509Certificate,NULL))
  416. {
  417. fprintf(stderr,"Error reading server certificate file %s: ",szPath);
  418. ERR_print_errors_fp(stderr);
  419. exit(1);
  420. }
  421.     fclose(f);
  422.     if(pConfig->szKeyFile)
  423. if(*pConfig->szKeyFile == '/')
  424.     strcpy(szPath,pConfig->szKeyFile);
  425. else
  426.     sprintf(szPath,"%s/private/%s",X509_get_default_cert_area(),
  427.     pConfig->szKeyFile);
  428. /* Otherwise the path already contains the name of the certificate file */
  429.     f=fopen(szPath,"r");
  430.     if(!f)
  431. {
  432. fprintf(stderr,"Can't open key file ");
  433. perror(szPath);
  434. exit(1);
  435. }
  436.     pConfig->prsaKey=RSA_new();
  437.     if(!PEM_read_RSAPrivateKey(f,&pConfig->prsaKey,NULL))
  438. {
  439. fprintf(stderr,"Error reading private key file %s: ",szPath);
  440. ERR_print_errors_fp(stderr);
  441. exit(1);
  442. }
  443. #if SSLEAY_VERSION_NUMBER >= 0x0800
  444.     SSL_CTX_set_tmp_rsa_callback(pConfig->pSSLCtx,TmpRSACallback);
  445.     /* Really this should have its own directive and list, but I haven't got
  446.        the time at the moment.
  447.      */
  448.     SSL_CTX_set_client_CA_list(pConfig->pSSLCtx, 
  449.     SSL_load_client_CA_file(pConfig->szCACertificateFile)); 
  450. #endif
  451.     }
  452. static void InitSSLServer(server_rec *s,pool *p)
  453.     {
  454.     InitSSL();
  455.     for ( ; s ; s=s->next)
  456. {
  457. SSLConfigRec *pConfig=get_module_config(s->module_config,&ssl_module);
  458. if(pConfig->bDisabled)
  459.     {
  460.     if(!s->port)
  461. s->port=HTTP_PORT;
  462.     fprintf(stderr,"SSL disabled for server %s:%dn",
  463.     s->server_hostname,s->port);
  464.     continue;
  465.     }
  466. if(!s->port)
  467.     s->port=HTTPS_PORT;
  468. if(!pConfig->szCertificateFile)
  469.     {
  470.     fprintf(stderr,"No SSL Certificate set for server %s:%dn",
  471.     s->server_hostname,s->port);
  472.     exit(1);
  473.     }
  474. if(pConfig->nVerifyClient < 0 || pConfig->nVerifyClient > VERIFY_OPTIONAL_NO_CA)
  475.     {
  476.     fprintf(stderr,"Bad value for SSLVerifyClient (%d)n",pConfig->nVerifyClient);
  477.     exit(1);
  478.     }
  479. if(!pConfig->szLogFile)
  480.     {
  481.     fprintf(stderr,"Required SSLLogFile missingn");
  482.     exit(1);
  483.     }
  484. pConfig->fileLogFile=fopen(pConfig->szLogFile,"a");
  485. if(!pConfig->fileLogFile)
  486.     {
  487.     perror(pConfig->szLogFile);
  488.     exit(1);
  489.     }
  490. setbuf(pConfig->fileLogFile,NULL);
  491.     
  492. GetCertificateAndKey(s,pConfig);
  493. }
  494.     }
  495. static const char *set_server_string_slot (cmd_parms *cmd,char *struct_ptr,char *arg)
  496.     {
  497.     /* This one should be pretty generic... */
  498.     char *pConfig=get_module_config(cmd->server->module_config,&ssl_module);
  499.   
  500.     int offset=(int)cmd->info; 
  501.     *(char **)(pConfig+offset)=arg;
  502.     return NULL;
  503.     }
  504. static const char *set_server_int_slot (cmd_parms *cmd,char *struct_ptr,char *arg)
  505.     {
  506.   /* This one should be pretty generic... */
  507.     char *pConfig=get_module_config(cmd->server->module_config,&ssl_module);
  508.   
  509.     int offset=(int)cmd->info; 
  510.     *(int *)(pConfig+offset)=atoi(arg);
  511.     return NULL;
  512.     }
  513. static const char *set_server_bool_slot (cmd_parms *cmd,char *struct_ptr)
  514.     {
  515.   /* This one should be pretty generic... */
  516.     char *pConfig=get_module_config(cmd->server->module_config,&ssl_module);
  517.   
  518.     int offset=(int)cmd->info; 
  519.     *(BOOL *)(pConfig+offset)=TRUE;
  520.     return NULL;
  521.     }
  522. command_rec ssl_cmds[]=
  523.     {
  524.     { "SSLDisable",set_server_bool_slot,
  525.       (void *)XtOffsetOf(SSLConfigRec,bDisabled),RSRC_CONF,NO_ARGS,
  526.       "Enable SSL" },
  527.     { "SSLCertificateFile",set_server_string_slot,
  528.       (void *)XtOffsetOf(SSLConfigRec,szCertificateFile),RSRC_CONF,TAKE1,
  529.       "PEM certificate file" },
  530.     { "SSLCertificateKeyFile",set_server_string_slot,
  531.       (void *)XtOffsetOf(SSLConfigRec,szKeyFile),RSRC_CONF,TAKE1,
  532.       "Certificate private key file (assumed to be SSLCertificateFile if absent)" },
  533.     { "SSLCACertificatePath",set_server_string_slot,
  534.       (void *)XtOffsetOf(SSLConfigRec,szCACertificatePath),RSRC_CONF,TAKE1,
  535.       "CA Certificate path (taken from SSL_CERT_DIR if absent)" },
  536.     { "SSLCACertificateFile",set_server_string_slot,
  537.       (void *)XtOffsetOf(SSLConfigRec,szCACertificateFile),RSRC_CONF,TAKE1,
  538.       "CA Certificate file (taken from SSL_CERT_FILE if absent)" },
  539.     { "SSLVerifyDepth",set_server_int_slot,
  540.       (void *)XtOffsetOf(SSLConfigRec,nVerifyDepth),RSRC_CONF,TAKE1,
  541.       "Verify depth (default 0)" },
  542.     { "SSLVerifyClient",set_server_int_slot,
  543.       (void *)XtOffsetOf(SSLConfigRec,nVerifyClient),RSRC_CONF,TAKE1,
  544.       "Verify client (0=no,1=optional,2=required" },
  545.     { "SSLFakeBasicAuth",set_server_bool_slot,
  546.       (void *)XtOffsetOf(SSLConfigRec,bFakeBasicAuth),RSRC_CONF,NO_ARGS,
  547.       "Translate client X509 into a user name" },
  548.     { "SSLLogFile",set_server_string_slot,
  549.       (void *)XtOffsetOf(SSLConfigRec,szLogFile),RSRC_CONF,TAKE1,
  550.       "Place to dump all SSL messages that have no better home" },
  551.     { "SSLRequiredCiphers",set_server_string_slot,
  552.       (void *)XtOffsetOf(SSLConfigRec,szReqCiphers),RSRC_CONF,TAKE1,
  553.       "Colon-delimited list of required ciphers" },
  554.     /* Per Directory */
  555.     { "SSLRequireCipher",SSLRequireCipher,NULL,OR_FILEINFO,ITERATE,
  556.       "add a cipher to the per directory list of required ciphers" },
  557.     { "SSLBanCipher",SSLBanCipher,NULL,OR_FILEINFO,ITERATE,
  558.       "add a cipher to the per directory list of banned ciphers" },
  559.     { NULL },
  560.     };
  561. static const char six2pr[64+1]=
  562.   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  563. void uuencode(char *szTo,const char *szFrom)
  564.     {
  565.     const unsigned char *s;
  566.     for(s=(const unsigned char *)szFrom ; *s ; s+=3)
  567. {
  568. *szTo++=six2pr[s[0] >> 2];
  569. *szTo++=six2pr[(s[0] << 4 | s[1] >> 4)&0x3f];
  570. if(!s[0])
  571.     break;
  572. *szTo++=six2pr[(s[1] << 2 | s[2] >> 6)&0x3f];
  573. if(!s[1])
  574.     break;
  575. *szTo++=six2pr[s[2]&0x3f];
  576. if(!s[2])
  577.     break;
  578. }
  579.     *szTo++='';
  580.     }
  581. /*
  582. Fake a Basic authentication from the X509 client certificate.
  583. This must be run fairly early on to prevent a real authentication from
  584. occuring, in particular it must be run before anything else that authenticates
  585. a user.
  586. This means that the Module statement for this module should be LAST in the
  587. Configuration file.
  588. */
  589. static int FakeBasicAuth(request_rec *r)
  590.     {
  591.     SSLConfigRec *pConfig=get_module_config(r->server->module_config,&ssl_module);
  592.     char b1[MAX_STRING_LEN],b2[MAX_STRING_LEN];
  593.   
  594.     if(!pConfig->bFakeBasicAuth)
  595. return DECLINED;
  596.     if(r->connection->user)
  597. return DECLINED;
  598.     if(!r->connection->client->szClientX509)
  599. return DECLINED;
  600.     /*
  601.        Fake a password - which one would be immaterial, as, it seems, an empty
  602.        password in the users file would match ALL incoming passwords, if only we
  603.        were using the standard crypt library routine. Unfortunately, SSLeay
  604.        "fixes" a "bug" in crypt and thus prevents blank passwords from working.
  605.        (IMHO what they really fix is a bug in the users of the code - failing to
  606.        program correctly for shadow passwords).
  607.        We need, therefore, to provide a password. This password can be matched by
  608.        adding the string "xxj31ZMTZzkVA" as the password in the user file.
  609. */
  610.     sprintf(b1,"%s:password",r->connection->client->szClientX509);
  611.     uuencode(b2,b1);
  612.     sprintf(b1,"Basic %s",b2);
  613.     table_set(r->headers_in,"Authorization",b1);
  614.     return DECLINED;
  615.     }
  616. static BOOL ApacheSSLSetCertStuff(conn_rec *conn)
  617.     {
  618.     SSLConfigRec *pConfig=get_module_config(conn->server->module_config,
  619.     &ssl_module);
  620.     SSL *con=conn->client->ssl;
  621.     char *cert_file=pConfig->szCertificateFile;
  622.     char *key_file=pConfig->szKeyFile;
  623. /*  PEM_set_getkey_callback(ApacheSSLKeyCallback); */
  624.     if(cert_file != NULL)
  625. {
  626. if(SSL_use_certificate(con,pConfig->px509Certificate) <= 0)
  627.     {
  628.     fprintf(pConfig->fileLogFile,"unable to set certificaten");
  629.     ERR_print_errors_fp(pConfig->fileLogFile);
  630.     SSLLogError(conn->server);
  631.     return FALSE;
  632.     }
  633. if(SSL_use_RSAPrivateKey(con,pConfig->prsaKey) <= 0)
  634.     {
  635.     fprintf(pConfig->fileLogFile,"unable to set private keyn");
  636.     ERR_print_errors_fp(pConfig->fileLogFile);
  637.     SSLLogError(conn->server);
  638.     return FALSE;
  639.     }
  640. }
  641.     return TRUE;
  642.     }
  643. void ApacheSSLSetupVerify(conn_rec *conn)
  644.     {
  645.     SSLConfigRec *pConfig=get_module_config(conn->server->module_config,&ssl_module);
  646.     int nVerify=VerifyFlags(pConfig);
  647.     conn->client->szClientX509=NULL;
  648.     SSLVerifyConn=conn;
  649.     conn->client->nVerifyError=X509_V_OK;
  650. /* Why call this twice?? Ben */  
  651. #if SSLEAY_VERSION_NUMBER < 0x0800
  652.     SSL_set_verify(conn->client->ssl,nVerify,ApacheSSLVerifyCallback);
  653. #endif
  654.     if(!ApacheSSLSetCertStuff(conn))
  655. {
  656. fprintf(pConfig->fileLogFile,"ApacheSSLSetCertStuff failedn");
  657. log_error("ApacheSSLSetCertStuff failed",conn->server);
  658. exit(1);
  659. }
  660. #if SSLEAY_VERSION_NUMBER >= 0x0800
  661. #else
  662.     SSL_set_verify(conn->client->ssl,nVerify,ApacheSSLVerifyCallback);
  663. #endif
  664.     }
  665. int ApacheSSLSetupConnection(conn_rec * conn)
  666.     {
  667.     server_rec * srvr=conn->server;
  668.     BUFF * fb=conn->client;
  669.     SSLConfigRec *pConfig=get_module_config(srvr->module_config,
  670.       &ssl_module);
  671.     char *cert_file=pConfig->szCertificateFile;
  672.     char *key_file=pConfig->szKeyFile;
  673.     if(pConfig->bDisabled)
  674. {
  675. fb->ssl=NULL;
  676. return TRUE;
  677. }
  678.     
  679.     SSLVerifyConn=conn;
  680.     fb->ssl=SSL_new(pConfig->pSSLCtx);
  681.     SSL_set_fd(fb->ssl,fb->fd);
  682. #if 0
  683.     if (cert_file != NULL) {
  684. if (SSL_use_certificate(fb->ssl,pConfig->px509Certificate) <= 0) {
  685.     fprintf(pConfig->fileLogFile,"unable to set certificaten");
  686.     ERR_print_errors_fp(pConfig->fileLogFile);
  687.     SSLLogError(srvr);
  688.     fb->flags |= B_EOF | B_EOUT;
  689.     return FALSE;
  690. }
  691. if(SSL_use_RSAPrivateKey(fb->ssl,pConfig->prsaKey) <= 0) {
  692.     fprintf(pConfig->fileLogFile,"unable to set private keyn");
  693.     ERR_print_errors_fp(pConfig->fileLogFile);
  694.     SSLLogError(srvr);
  695.     fb->flags |= B_EOF | B_EOUT;
  696.     return FALSE;
  697. }
  698.     }
  699. #endif
  700.     ApacheSSLSetupVerify(conn);
  701.     while(!SSL_is_init_finished(fb->ssl))
  702. {
  703. int ret=SSL_accept(fb->ssl);
  704. if (ret <= 0)
  705.     {
  706.     log_error("SSL_Accept failed",srvr);
  707.     SSLLogError(srvr);
  708.     fb->flags |= B_EOF | B_EOUT;
  709.     return FALSE;
  710.     }
  711. if(conn->client->nVerifyError != X509_V_OK)
  712.     {
  713.     log_error("Verification failed",conn->server);
  714.     SSLLogError(srvr);
  715.     fb->flags |= B_EOF | B_EOUT;
  716.     return FALSE;
  717.     }
  718. if(pConfig->nVerifyClient == VERIFY_REQUIRE && !conn->client->szClientX509)
  719.     {
  720.     log_error("No client certificate",conn->server);
  721.     SSLLogError(conn->server);
  722.     return 0;
  723.     }
  724. fprintf(pConfig->fileLogFile,"CIPHER is %sn",SSL_get_cipher(conn->client->ssl));
  725. fflush(pConfig->fileLogFile);
  726. }
  727.     /* This should be safe.... so I'll use it */
  728.     SSL_set_read_ahead(fb->ssl,1);
  729.     SSLVerifyConn=NULL;
  730.     return TRUE;
  731.     }
  732. module ssl_module =
  733.     {
  734.     STANDARD_MODULE_STUFF,
  735.     InitSSLServer, /* initializer */
  736.     CreateSSLDirConfig, /* dir config creater */
  737.     MergeSSLDirConfig, /* dir merger --- default is to override */
  738.     CreateSSLServerConfig, /* server config */
  739.     NULL, /* merge server config */
  740.     ssl_cmds, /* command table */
  741.     NULL, /* handlers */
  742.     NULL, /* filename translation */
  743.     FakeBasicAuth, /* check_user_id */
  744.     NULL, /* check auth */
  745.     SSLCheckCipher, /* check access */
  746.     NULL, /* type_checker */
  747.     SSLFixups, /* fixups */
  748.     NULL, /* logger */
  749.     };