Fossil SCM
Add ssl-ca-location setting to specify file/directory to pass to OpenSSL as the server CA location. This allows specification of CAs properly on platforms without usable centralised CA certificate lists, or management by external programs. Add note to certificate warning about this setting, and stronger instructions about what to do if the server certificate could not be verified.
Commit
636cc595e192f720fe05337a86d6bf645eb4836f
Parent
a164b63a67369c4…
2 files changed
+12
+37
-1
M
src/db.c
+12
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1740,10 +1740,11 @@ | ||
| 1740 | 1740 | { "mtime-changes", 0, 0, 0, "on" }, |
| 1741 | 1741 | { "pgp-command", 0, 32, 0, "gpg --clearsign -o " }, |
| 1742 | 1742 | { "proxy", 0, 32, 0, "off" }, |
| 1743 | 1743 | { "repo-cksum", 0, 0, 0, "on" }, |
| 1744 | 1744 | { "self-register", 0, 0, 0, "off" }, |
| 1745 | + { "ssl-ca-location",0, 40, 0, "" }, | |
| 1745 | 1746 | { "ssl-identity", 0, 40, 0, "" }, |
| 1746 | 1747 | { "ssh-command", 0, 32, 0, "" }, |
| 1747 | 1748 | { "web-browser", 0, 32, 0, "" }, |
| 1748 | 1749 | { 0,0,0,0,0 } |
| 1749 | 1750 | }; |
| @@ -1859,10 +1860,21 @@ | ||
| 1859 | 1860 | ** |
| 1860 | 1861 | ** self-register Allow users to register themselves through the HTTP UI. |
| 1861 | 1862 | ** This is useful if you want to see other names than |
| 1862 | 1863 | ** "Anonymous" in e.g. ticketing system. On the other hand |
| 1863 | 1864 | ** users can not be deleted. Default: off. |
| 1865 | +** | |
| 1866 | +** ssl-ca-location The full pathname to a file containing PEM encoded | |
| 1867 | +** CA root certificates, or a directory of certificates | |
| 1868 | +** with filenames formed from the certificate hashes as | |
| 1869 | +** required by OpenSSL. | |
| 1870 | +** If set, this will override the OS default list of | |
| 1871 | +** OpenSSL CAs. If unset, the default list will be used. | |
| 1872 | +** Some platforms may add additional certificates. | |
| 1873 | +** Check your platform behaviour is as required if the | |
| 1874 | +** exact contents of the CA root is critical for your | |
| 1875 | +** application. | |
| 1864 | 1876 | ** |
| 1865 | 1877 | ** ssl-identity The full pathname to a file containing a certificate |
| 1866 | 1878 | ** and private key in PEM format. Create by concatenating |
| 1867 | 1879 | ** the certificate and private key files. |
| 1868 | 1880 | ** This identity will be presented to SSL servers to |
| 1869 | 1881 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1740,10 +1740,11 @@ | |
| 1740 | { "mtime-changes", 0, 0, 0, "on" }, |
| 1741 | { "pgp-command", 0, 32, 0, "gpg --clearsign -o " }, |
| 1742 | { "proxy", 0, 32, 0, "off" }, |
| 1743 | { "repo-cksum", 0, 0, 0, "on" }, |
| 1744 | { "self-register", 0, 0, 0, "off" }, |
| 1745 | { "ssl-identity", 0, 40, 0, "" }, |
| 1746 | { "ssh-command", 0, 32, 0, "" }, |
| 1747 | { "web-browser", 0, 32, 0, "" }, |
| 1748 | { 0,0,0,0,0 } |
| 1749 | }; |
| @@ -1859,10 +1860,21 @@ | |
| 1859 | ** |
| 1860 | ** self-register Allow users to register themselves through the HTTP UI. |
| 1861 | ** This is useful if you want to see other names than |
| 1862 | ** "Anonymous" in e.g. ticketing system. On the other hand |
| 1863 | ** users can not be deleted. Default: off. |
| 1864 | ** |
| 1865 | ** ssl-identity The full pathname to a file containing a certificate |
| 1866 | ** and private key in PEM format. Create by concatenating |
| 1867 | ** the certificate and private key files. |
| 1868 | ** This identity will be presented to SSL servers to |
| 1869 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1740,10 +1740,11 @@ | |
| 1740 | { "mtime-changes", 0, 0, 0, "on" }, |
| 1741 | { "pgp-command", 0, 32, 0, "gpg --clearsign -o " }, |
| 1742 | { "proxy", 0, 32, 0, "off" }, |
| 1743 | { "repo-cksum", 0, 0, 0, "on" }, |
| 1744 | { "self-register", 0, 0, 0, "off" }, |
| 1745 | { "ssl-ca-location",0, 40, 0, "" }, |
| 1746 | { "ssl-identity", 0, 40, 0, "" }, |
| 1747 | { "ssh-command", 0, 32, 0, "" }, |
| 1748 | { "web-browser", 0, 32, 0, "" }, |
| 1749 | { 0,0,0,0,0 } |
| 1750 | }; |
| @@ -1859,10 +1860,21 @@ | |
| 1860 | ** |
| 1861 | ** self-register Allow users to register themselves through the HTTP UI. |
| 1862 | ** This is useful if you want to see other names than |
| 1863 | ** "Anonymous" in e.g. ticketing system. On the other hand |
| 1864 | ** users can not be deleted. Default: off. |
| 1865 | ** |
| 1866 | ** ssl-ca-location The full pathname to a file containing PEM encoded |
| 1867 | ** CA root certificates, or a directory of certificates |
| 1868 | ** with filenames formed from the certificate hashes as |
| 1869 | ** required by OpenSSL. |
| 1870 | ** If set, this will override the OS default list of |
| 1871 | ** OpenSSL CAs. If unset, the default list will be used. |
| 1872 | ** Some platforms may add additional certificates. |
| 1873 | ** Check your platform behaviour is as required if the |
| 1874 | ** exact contents of the CA root is critical for your |
| 1875 | ** application. |
| 1876 | ** |
| 1877 | ** ssl-identity The full pathname to a file containing a certificate |
| 1878 | ** and private key in PEM format. Create by concatenating |
| 1879 | ** the certificate and private key files. |
| 1880 | ** This identity will be presented to SSL servers to |
| 1881 |
+37
-1
| --- src/http_ssl.c | ||
| +++ src/http_ssl.c | ||
| @@ -93,17 +93,46 @@ | ||
| 93 | 93 | /* |
| 94 | 94 | ** Call this routine once before any other use of the SSL interface. |
| 95 | 95 | ** This routine does initial configuration of the SSL module. |
| 96 | 96 | */ |
| 97 | 97 | void ssl_global_init(void){ |
| 98 | + const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0; | |
| 99 | + | |
| 98 | 100 | if( sslIsInit==0 ){ |
| 99 | 101 | SSL_library_init(); |
| 100 | 102 | SSL_load_error_strings(); |
| 101 | 103 | ERR_load_BIO_strings(); |
| 102 | 104 | OpenSSL_add_all_algorithms(); |
| 103 | 105 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | - X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); | |
| 106 | + | |
| 107 | + /* Set up acceptable CA root certificates */ | |
| 108 | + zCaSetting = db_get("ssl-ca-location", 0); | |
| 109 | + if( zCaSetting==0 || zCaSetting[0]=='\0' ){ | |
| 110 | + /* CA location not specified, use platform's default certificate store */ | |
| 111 | + X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); | |
| 112 | + }else{ | |
| 113 | + /* User has specified a CA location, make sure it exists and use it */ | |
| 114 | + switch( file_isdir(zCaSetting) ){ | |
| 115 | + case 0: { /* doesn't exist */ | |
| 116 | + fossil_fatal("ssl-ca-location is set to '%s', " | |
| 117 | + "but is not a file or directory", zCaSetting); | |
| 118 | + break; | |
| 119 | + } | |
| 120 | + case 1: { /* directory */ | |
| 121 | + zCaDirectory = zCaSetting; | |
| 122 | + break; | |
| 123 | + } | |
| 124 | + case 2: { /* file */ | |
| 125 | + zCaFile = zCaSetting; | |
| 126 | + break; | |
| 127 | + } | |
| 128 | + } | |
| 129 | + if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){ | |
| 130 | + fossil_fatal("Failed to use CA root certificates from " | |
| 131 | + "ssl-ca-location '%s'", zCaSetting); | |
| 132 | + } | |
| 133 | + } | |
| 105 | 134 | |
| 106 | 135 | /* Load client SSL identity, preferring the filename specified on the command line */ |
| 107 | 136 | const char *identityFile = ( g.zSSLIdentity!= 0) ? g.zSSLIdentity : db_get("ssl-identity", 0); |
| 108 | 137 | if( identityFile!=0 && identityFile[0]!='\0' ){ |
| 109 | 138 | if( SSL_CTX_use_certificate_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!= 1 |
| @@ -225,10 +254,17 @@ | ||
| 225 | 254 | if( hasSavedCertificate ){ |
| 226 | 255 | warning = "WARNING: Certificate doesn't match the " |
| 227 | 256 | "saved certificate for this host!"; |
| 228 | 257 | } |
| 229 | 258 | prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n" |
| 259 | + "Either:\n" | |
| 260 | + " * verify the certificate is correct using the " | |
| 261 | + "SHA1 fingerprint above\n" | |
| 262 | + " * use the global ssl-ca-location setting to specify your CA root\n" | |
| 263 | + " certificates list\n\n" | |
| 264 | + "If you are not expecting this message, answer no and " | |
| 265 | + "contact your server\nadministrator.\n\n" | |
| 230 | 266 | "Accept certificate [a=always/y/N]? ", desc, warning); |
| 231 | 267 | BIO_free(mem); |
| 232 | 268 | |
| 233 | 269 | prompt_user(prompt, &ans); |
| 234 | 270 | free(prompt); |
| 235 | 271 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -93,17 +93,46 @@ | |
| 93 | /* |
| 94 | ** Call this routine once before any other use of the SSL interface. |
| 95 | ** This routine does initial configuration of the SSL module. |
| 96 | */ |
| 97 | void ssl_global_init(void){ |
| 98 | if( sslIsInit==0 ){ |
| 99 | SSL_library_init(); |
| 100 | SSL_load_error_strings(); |
| 101 | ERR_load_BIO_strings(); |
| 102 | OpenSSL_add_all_algorithms(); |
| 103 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); |
| 105 | |
| 106 | /* Load client SSL identity, preferring the filename specified on the command line */ |
| 107 | const char *identityFile = ( g.zSSLIdentity!= 0) ? g.zSSLIdentity : db_get("ssl-identity", 0); |
| 108 | if( identityFile!=0 && identityFile[0]!='\0' ){ |
| 109 | if( SSL_CTX_use_certificate_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!= 1 |
| @@ -225,10 +254,17 @@ | |
| 225 | if( hasSavedCertificate ){ |
| 226 | warning = "WARNING: Certificate doesn't match the " |
| 227 | "saved certificate for this host!"; |
| 228 | } |
| 229 | prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n" |
| 230 | "Accept certificate [a=always/y/N]? ", desc, warning); |
| 231 | BIO_free(mem); |
| 232 | |
| 233 | prompt_user(prompt, &ans); |
| 234 | free(prompt); |
| 235 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -93,17 +93,46 @@ | |
| 93 | /* |
| 94 | ** Call this routine once before any other use of the SSL interface. |
| 95 | ** This routine does initial configuration of the SSL module. |
| 96 | */ |
| 97 | void ssl_global_init(void){ |
| 98 | const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0; |
| 99 | |
| 100 | if( sslIsInit==0 ){ |
| 101 | SSL_library_init(); |
| 102 | SSL_load_error_strings(); |
| 103 | ERR_load_BIO_strings(); |
| 104 | OpenSSL_add_all_algorithms(); |
| 105 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 106 | |
| 107 | /* Set up acceptable CA root certificates */ |
| 108 | zCaSetting = db_get("ssl-ca-location", 0); |
| 109 | if( zCaSetting==0 || zCaSetting[0]=='\0' ){ |
| 110 | /* CA location not specified, use platform's default certificate store */ |
| 111 | X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); |
| 112 | }else{ |
| 113 | /* User has specified a CA location, make sure it exists and use it */ |
| 114 | switch( file_isdir(zCaSetting) ){ |
| 115 | case 0: { /* doesn't exist */ |
| 116 | fossil_fatal("ssl-ca-location is set to '%s', " |
| 117 | "but is not a file or directory", zCaSetting); |
| 118 | break; |
| 119 | } |
| 120 | case 1: { /* directory */ |
| 121 | zCaDirectory = zCaSetting; |
| 122 | break; |
| 123 | } |
| 124 | case 2: { /* file */ |
| 125 | zCaFile = zCaSetting; |
| 126 | break; |
| 127 | } |
| 128 | } |
| 129 | if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){ |
| 130 | fossil_fatal("Failed to use CA root certificates from " |
| 131 | "ssl-ca-location '%s'", zCaSetting); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | /* Load client SSL identity, preferring the filename specified on the command line */ |
| 136 | const char *identityFile = ( g.zSSLIdentity!= 0) ? g.zSSLIdentity : db_get("ssl-identity", 0); |
| 137 | if( identityFile!=0 && identityFile[0]!='\0' ){ |
| 138 | if( SSL_CTX_use_certificate_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!= 1 |
| @@ -225,10 +254,17 @@ | |
| 254 | if( hasSavedCertificate ){ |
| 255 | warning = "WARNING: Certificate doesn't match the " |
| 256 | "saved certificate for this host!"; |
| 257 | } |
| 258 | prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n" |
| 259 | "Either:\n" |
| 260 | " * verify the certificate is correct using the " |
| 261 | "SHA1 fingerprint above\n" |
| 262 | " * use the global ssl-ca-location setting to specify your CA root\n" |
| 263 | " certificates list\n\n" |
| 264 | "If you are not expecting this message, answer no and " |
| 265 | "contact your server\nadministrator.\n\n" |
| 266 | "Accept certificate [a=always/y/N]? ", desc, warning); |
| 267 | BIO_free(mem); |
| 268 | |
| 269 | prompt_user(prompt, &ans); |
| 270 | free(prompt); |
| 271 |