Fossil

Check-in [b28995ccbd]
Login

Check-in [b28995ccbd]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add support for feeding OpenSSL a CA certificate file/path for proper chain verification. This is one of several possible solutions to ticket [727af73f46]. Also cache the CA certificate file/path, client certificate/key file/path references in the global config (similar to how the server certificates are cached), and attempt to use them if the corresponding environment variables have not been set. Prefixed a function with ssl_ to conform to existing naming conventions.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | jan-clientcert
Files: files | file ages | folders
SHA1: b28995ccbdbb54b047b06eae6d7eb81ae80e329b
User & Date: jan 2011-03-29 14:12:28.451
Original Comment: Add support for feeding OpenSSL a CA certificate file/path for proper chain verification. This is one of several possible solutions to ticket [727af73f467a64be0d0bbbcf46c513062a9e4704]. Also cache the CA certificate file/path, client certificate/key file/path references in the global config (similar to how the server certificates are cached), and attempt to use them if the corresponding environment variables have not been set. Prefixed a function with ssl_ to conform to existing naming conventions.
Context
2011-03-29
15:06
Cosmetic: Removed some tabbed indentation. ... (check-in: b261c4a33b user: jan tags: jan-clientcert)
14:12
Add support for feeding OpenSSL a CA certificate file/path for proper chain verification. This is one of several possible solutions to ticket [727af73f46]. Also cache the CA certificate file/path, client certificate/key file/path references in the global config (similar to how the server certificates are cached), and attempt to use them if the corresponding environment variables have not been set. Prefixed a function with ssl_ to conform to existing naming conventions. ... (check-in: b28995ccbd user: jan tags: jan-clientcert)
2011-03-25
18:20
Added very basic client certificate support for https. ... (check-in: 513ea81005 user: jan tags: jan-clientcert)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/http_ssl.c.
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
int ssl_open(void){
  X509 *cert;
  int hasSavedCertificate = 0;
char *connStr ;
  ssl_global_init();

  /* If client certificate/key has been set, load them into the SSL context. */
  load_client_authfiles();

  /* Get certificate for current server from global config and
   * (if we have it in config) add it to certificate store.
   */
  cert = ssl_get_certificate();
  if ( cert!=NULL ){
    X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);







|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
int ssl_open(void){
  X509 *cert;
  int hasSavedCertificate = 0;
char *connStr ;
  ssl_global_init();

  /* If client certificate/key has been set, load them into the SSL context. */
  ssl_load_client_authfiles();

  /* Get certificate for current server from global config and
   * (if we have it in config) add it to certificate store.
   */
  cert = ssl_get_certificate();
  if ( cert!=NULL ){
    X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
292
293
294
295
296
297
298



299
300
301


302
303
304


305















306


307
308
309

310
311
312
313
314
315
316
317
318
319
320
321
322
323

324
































325
326
327
}

/*
** Read client certificate and key, if set, and store them in the SSL context
** to allow communication with servers which are configured to verify client
** certificates and certificate chains.
** We only support PEM and don't support password protected keys.



*/
void load_client_authfiles(void)
{


  const char *certfile;
  const char *keyfile;



  certfile = getenv("FOSSIL_CCERT");















  if( certfile == NULL )


	  return;

  keyfile = getenv("FOSSIL_CKEY");


  /* Assume the key is in the certificate file if key file was not specified */
  if( certfile && !keyfile )
    keyfile = certfile;

  if( SSL_CTX_use_certificate_file(sslCtx, certfile, SSL_FILETYPE_PEM) <= 0 ){
    fossil_fatal("Unable to open client certificate in %s.", certfile);
  }
  if( SSL_CTX_use_PrivateKey_file(sslCtx, keyfile, SSL_FILETYPE_PEM) <= 0 ){
    fossil_fatal("Unable to open client key in %s.", keyfile);
  }

  if( !SSL_CTX_check_private_key(sslCtx) ){
    fossil_fatal("Private key does not match the certificate public key.");

  }
































}

#endif /* FOSSIL_ENABLE_SSL */







>
>
>

|

>
>
|
|

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

|
|
>






|


|



|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
}

/*
** Read client certificate and key, if set, and store them in the SSL context
** to allow communication with servers which are configured to verify client
** certificates and certificate chains.
** We only support PEM and don't support password protected keys.
**
** Always try the environment variables first, and if they aren't set, then
** use the global config.
*/
void ssl_load_client_authfiles(void)
{
  char *cafile;
  char *capath;
  char *certfile;
  char *keyfile;

  cafile = ssl_get_and_set_file_ref("FOSSIL_CAFILE", "cafile");
  capath = ssl_get_and_set_file_ref("FOSSIL_CAPATH", "capath");

  if( cafile || capath ){
     /* The OpenSSL documentation warns that if several CA certificates match
      * the same name, key identifier and serial number conditions, only the
      * first will be examined. The caveat situation is when one stores an
      * expired CA certificate among the valid ones.
      * Simply put: Do not mix expired and valid certificates.
		*/
	  if( SSL_CTX_load_verify_locations(sslCtx, cafile, capath) == 0){
		  fossil_fatal("SSL: Unable to load CA verification file/path");
	  }
  }else{
    fossil_warning("SSL: CA file/path missing for certificate verification.");
  }

  certfile = ssl_get_and_set_file_ref("FOSSIL_CCERT", "ccert");
  if( !certfile ){
	  free(capath);
	  free(cafile);
	  return;
  }

  keyfile = ssl_get_and_set_file_ref("FOSSIL_CKEY", "ckey");

  /* Assume the key is in the certificate file if key file was not specified */
  if( certfile && !keyfile )
    keyfile = certfile;

  if( SSL_CTX_use_certificate_file(sslCtx, certfile, SSL_FILETYPE_PEM) <= 0 ){
    fossil_fatal("SSL: Unable to open client certificate in %s.", certfile);
  }
  if( SSL_CTX_use_PrivateKey_file(sslCtx, keyfile, SSL_FILETYPE_PEM) <= 0 ){
    fossil_fatal("SSL: Unable to open client key in %s.", keyfile);
  }

  if( !SSL_CTX_check_private_key(sslCtx) ){
    fossil_fatal("SSL: Private key does not match the certificate public "
        "key.");
  }

  free(keyfile);
  free(certfile);
  free(capath);
  free(cafile);
}

/*
** Get SSL authentication file reference from environment variable. If set,
** then store varaible in global config. If environment variable was not set,
** attempt to get variable from global config.
**/
char *ssl_get_and_set_file_ref(const char *envvar, const char *dbvar)
{
  char *zVar;
  char *zTmp;

  zTmp = mprintf("%s:%s", dbvar, g.urlName);

  zVar = getenv(envvar);
  if( zVar ){
    zVar = strdup(zVar);
	 if( zVar == NULL ){
      fossil_fatal("Unable to allocate memory for %s value.", envvar);
	 }
    db_set(zTmp, zVar, 1);
  }else{
    zVar = db_get(zTmp, NULL);
  }
  free(zTmp);

  return zVar;
}

#endif /* FOSSIL_ENABLE_SSL */