Fossil SCM

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.

jan 2011-03-29 14:12 jan-clientcert
Commit b28995ccbdbb54b047b06eae6d7eb81ae80e329b
1 file changed +73 -15
+73 -15
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -133,11 +133,11 @@
133133
int hasSavedCertificate = 0;
134134
char *connStr ;
135135
ssl_global_init();
136136
137137
/* If client certificate/key has been set, load them into the SSL context. */
138
- load_client_authfiles();
138
+ ssl_load_client_authfiles();
139139
140140
/* Get certificate for current server from global config and
141141
* (if we have it in config) add it to certificate store.
142142
*/
143143
cert = ssl_get_certificate();
@@ -294,34 +294,92 @@
294294
/*
295295
** Read client certificate and key, if set, and store them in the SSL context
296296
** to allow communication with servers which are configured to verify client
297297
** certificates and certificate chains.
298298
** We only support PEM and don't support password protected keys.
299
-*/
300
-void load_client_authfiles(void)
301
-{
302
- const char *certfile;
303
- const char *keyfile;
304
-
305
- certfile = getenv("FOSSIL_CCERT");
306
- if( certfile == NULL )
307
- return;
308
-
309
- keyfile = getenv("FOSSIL_CKEY");
299
+**
300
+** Always try the environment variables first, and if they aren't set, then
301
+** use the global config.
302
+*/
303
+void ssl_load_client_authfiles(void)
304
+{
305
+ char *cafile;
306
+ char *capath;
307
+ char *certfile;
308
+ char *keyfile;
309
+
310
+ cafile = ssl_get_and_set_file_ref("FOSSIL_CAFILE", "cafile");
311
+ capath = ssl_get_and_set_file_ref("FOSSIL_CAPATH", "capath");
312
+
313
+ if( cafile || capath ){
314
+ /* The OpenSSL documentation warns that if several CA certificates match
315
+ * the same name, key identifier and serial number conditions, only the
316
+ * first will be examined. The caveat situation is when one stores an
317
+ * expired CA certificate among the valid ones.
318
+ * Simply put: Do not mix expired and valid certificates.
319
+ */
320
+ if( SSL_CTX_load_verify_locations(sslCtx, cafile, capath) == 0){
321
+ fossil_fatal("SSL: Unable to load CA verification file/path");
322
+ }
323
+ }else{
324
+ fossil_warning("SSL: CA file/path missing for certificate verification.");
325
+ }
326
+
327
+ certfile = ssl_get_and_set_file_ref("FOSSIL_CCERT", "ccert");
328
+ if( !certfile ){
329
+ free(capath);
330
+ free(cafile);
331
+ return;
332
+ }
333
+
334
+ keyfile = ssl_get_and_set_file_ref("FOSSIL_CKEY", "ckey");
310335
311336
/* Assume the key is in the certificate file if key file was not specified */
312337
if( certfile && !keyfile )
313338
keyfile = certfile;
314339
315340
if( SSL_CTX_use_certificate_file(sslCtx, certfile, SSL_FILETYPE_PEM) <= 0 ){
316
- fossil_fatal("Unable to open client certificate in %s.", certfile);
341
+ fossil_fatal("SSL: Unable to open client certificate in %s.", certfile);
317342
}
318343
if( SSL_CTX_use_PrivateKey_file(sslCtx, keyfile, SSL_FILETYPE_PEM) <= 0 ){
319
- fossil_fatal("Unable to open client key in %s.", keyfile);
344
+ fossil_fatal("SSL: Unable to open client key in %s.", keyfile);
320345
}
321346
322347
if( !SSL_CTX_check_private_key(sslCtx) ){
323
- fossil_fatal("Private key does not match the certificate public key.");
348
+ fossil_fatal("SSL: Private key does not match the certificate public "
349
+ "key.");
350
+ }
351
+
352
+ free(keyfile);
353
+ free(certfile);
354
+ free(capath);
355
+ free(cafile);
356
+}
357
+
358
+/*
359
+** Get SSL authentication file reference from environment variable. If set,
360
+** then store varaible in global config. If environment variable was not set,
361
+** attempt to get variable from global config.
362
+**/
363
+char *ssl_get_and_set_file_ref(const char *envvar, const char *dbvar)
364
+{
365
+ char *zVar;
366
+ char *zTmp;
367
+
368
+ zTmp = mprintf("%s:%s", dbvar, g.urlName);
369
+
370
+ zVar = getenv(envvar);
371
+ if( zVar ){
372
+ zVar = strdup(zVar);
373
+ if( zVar == NULL ){
374
+ fossil_fatal("Unable to allocate memory for %s value.", envvar);
375
+ }
376
+ db_set(zTmp, zVar, 1);
377
+ }else{
378
+ zVar = db_get(zTmp, NULL);
324379
}
380
+ free(zTmp);
381
+
382
+ return zVar;
325383
}
326384
327385
#endif /* FOSSIL_ENABLE_SSL */
328386
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -133,11 +133,11 @@
133 int hasSavedCertificate = 0;
134 char *connStr ;
135 ssl_global_init();
136
137 /* If client certificate/key has been set, load them into the SSL context. */
138 load_client_authfiles();
139
140 /* Get certificate for current server from global config and
141 * (if we have it in config) add it to certificate store.
142 */
143 cert = ssl_get_certificate();
@@ -294,34 +294,92 @@
294 /*
295 ** Read client certificate and key, if set, and store them in the SSL context
296 ** to allow communication with servers which are configured to verify client
297 ** certificates and certificate chains.
298 ** We only support PEM and don't support password protected keys.
299 */
300 void load_client_authfiles(void)
301 {
302 const char *certfile;
303 const char *keyfile;
304
305 certfile = getenv("FOSSIL_CCERT");
306 if( certfile == NULL )
307 return;
308
309 keyfile = getenv("FOSSIL_CKEY");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
311 /* Assume the key is in the certificate file if key file was not specified */
312 if( certfile && !keyfile )
313 keyfile = certfile;
314
315 if( SSL_CTX_use_certificate_file(sslCtx, certfile, SSL_FILETYPE_PEM) <= 0 ){
316 fossil_fatal("Unable to open client certificate in %s.", certfile);
317 }
318 if( SSL_CTX_use_PrivateKey_file(sslCtx, keyfile, SSL_FILETYPE_PEM) <= 0 ){
319 fossil_fatal("Unable to open client key in %s.", keyfile);
320 }
321
322 if( !SSL_CTX_check_private_key(sslCtx) ){
323 fossil_fatal("Private key does not match the certificate public key.");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324 }
 
 
 
325 }
326
327 #endif /* FOSSIL_ENABLE_SSL */
328
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -133,11 +133,11 @@
133 int hasSavedCertificate = 0;
134 char *connStr ;
135 ssl_global_init();
136
137 /* If client certificate/key has been set, load them into the SSL context. */
138 ssl_load_client_authfiles();
139
140 /* Get certificate for current server from global config and
141 * (if we have it in config) add it to certificate store.
142 */
143 cert = ssl_get_certificate();
@@ -294,34 +294,92 @@
294 /*
295 ** Read client certificate and key, if set, and store them in the SSL context
296 ** to allow communication with servers which are configured to verify client
297 ** certificates and certificate chains.
298 ** We only support PEM and don't support password protected keys.
299 **
300 ** Always try the environment variables first, and if they aren't set, then
301 ** use the global config.
302 */
303 void ssl_load_client_authfiles(void)
304 {
305 char *cafile;
306 char *capath;
307 char *certfile;
308 char *keyfile;
309
310 cafile = ssl_get_and_set_file_ref("FOSSIL_CAFILE", "cafile");
311 capath = ssl_get_and_set_file_ref("FOSSIL_CAPATH", "capath");
312
313 if( cafile || capath ){
314 /* The OpenSSL documentation warns that if several CA certificates match
315 * the same name, key identifier and serial number conditions, only the
316 * first will be examined. The caveat situation is when one stores an
317 * expired CA certificate among the valid ones.
318 * Simply put: Do not mix expired and valid certificates.
319 */
320 if( SSL_CTX_load_verify_locations(sslCtx, cafile, capath) == 0){
321 fossil_fatal("SSL: Unable to load CA verification file/path");
322 }
323 }else{
324 fossil_warning("SSL: CA file/path missing for certificate verification.");
325 }
326
327 certfile = ssl_get_and_set_file_ref("FOSSIL_CCERT", "ccert");
328 if( !certfile ){
329 free(capath);
330 free(cafile);
331 return;
332 }
333
334 keyfile = ssl_get_and_set_file_ref("FOSSIL_CKEY", "ckey");
335
336 /* Assume the key is in the certificate file if key file was not specified */
337 if( certfile && !keyfile )
338 keyfile = certfile;
339
340 if( SSL_CTX_use_certificate_file(sslCtx, certfile, SSL_FILETYPE_PEM) <= 0 ){
341 fossil_fatal("SSL: Unable to open client certificate in %s.", certfile);
342 }
343 if( SSL_CTX_use_PrivateKey_file(sslCtx, keyfile, SSL_FILETYPE_PEM) <= 0 ){
344 fossil_fatal("SSL: Unable to open client key in %s.", keyfile);
345 }
346
347 if( !SSL_CTX_check_private_key(sslCtx) ){
348 fossil_fatal("SSL: Private key does not match the certificate public "
349 "key.");
350 }
351
352 free(keyfile);
353 free(certfile);
354 free(capath);
355 free(cafile);
356 }
357
358 /*
359 ** Get SSL authentication file reference from environment variable. If set,
360 ** then store varaible in global config. If environment variable was not set,
361 ** attempt to get variable from global config.
362 **/
363 char *ssl_get_and_set_file_ref(const char *envvar, const char *dbvar)
364 {
365 char *zVar;
366 char *zTmp;
367
368 zTmp = mprintf("%s:%s", dbvar, g.urlName);
369
370 zVar = getenv(envvar);
371 if( zVar ){
372 zVar = strdup(zVar);
373 if( zVar == NULL ){
374 fossil_fatal("Unable to allocate memory for %s value.", envvar);
375 }
376 db_set(zTmp, zVar, 1);
377 }else{
378 zVar = db_get(zTmp, NULL);
379 }
380 free(zTmp);
381
382 return zVar;
383 }
384
385 #endif /* FOSSIL_ENABLE_SSL */
386

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button