Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add a built-in self-signed certificate for use with TLS servers. Add --tls and --ssl options to active TLS for "fossil ui" and "fossil server". Add the "tls-server-cert" setting. Automatically start servers as TLS if the redirect-to-https property is 2. |
|---|---|
| Timelines: | family | ancestors | descendants | both | ssl-server |
| Files: | files | file ages | folders |
| SHA3-256: |
7532ffa4e34e3174ae44e8e7b8567ad3 |
| User & Date: | drh 2021-12-27 12:49:00.148 |
Context
|
2021-12-27
| ||
| 16:13 | Rename the "tls-config" command into "ssl-config" for consistency. The older "tls-config" command is retained as an alias. Enhance the command to support server certificate management. check-in: f6051784c5 user: drh tags: ssl-server | |
| 12:49 | Add a built-in self-signed certificate for use with TLS servers. Add --tls and --ssl options to active TLS for "fossil ui" and "fossil server". Add the "tls-server-cert" setting. Automatically start servers as TLS if the redirect-to-https property is 2. check-in: 7532ffa4e3 user: drh tags: ssl-server | |
|
2021-12-26
| ||
| 21:50 | Fix the build on Windows and on builds that omit OpenSSL. Improved error messages. check-in: 637516c447 user: drh tags: ssl-server | |
Changes
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
static SSL *ssl;
static struct { /* Accept this SSL cert for this session only */
char *zHost; /* Subject or host name */
char *zHash; /* SHA2-256 hash of the cert */
} sException;
static int sslNoCertVerify = 0; /* Do not verify SSL certs */
/*
** Clear the SSL error message
*/
static void ssl_clear_errmsg(void){
free(sslErrMsg);
sslErrMsg = 0;
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
static SSL *ssl;
static struct { /* Accept this SSL cert for this session only */
char *zHost; /* Subject or host name */
char *zHash; /* SHA2-256 hash of the cert */
} sException;
static int sslNoCertVerify = 0; /* Do not verify SSL certs */
/* This is a self-signed cert in the PEM format that can be used when
** no other certs are available.
*/
static const char sslSelfCert[] =
"-----BEGIN CERTIFICATE-----\n"
"MIIDMTCCAhkCFGrDmuJkkzWERP/ITBvzwwI2lv0TMA0GCSqGSIb3DQEBCwUAMFQx\n"
"CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOQzESMBAGA1UEBwwJQ2hhcmxvdHRlMRMw\n"
"EQYDVQQKDApGb3NzaWwtU0NNMQ8wDQYDVQQDDAZGb3NzaWwwIBcNMjExMjI3MTEz\n"
"MTU2WhgPMjEyMTEyMjcxMTMxNTZaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJO\n"
"QzESMBAGA1UEBwwJQ2hhcmxvdHRlMRMwEQYDVQQKDApGb3NzaWwtU0NNMQ8wDQYD\n"
"VQQDDAZGb3NzaWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCCbTU2\n"
"6GRQHQqLq7vyZ0OxpAxmgfAKCxt6eIz+jBi2ZM/CB5vVXWVh2+SkSiWEA3UZiUqX\n"
"xZlzmS/CglZdiwLLDJML8B4OiV72oivFH/vJ7+cbvh1dTxnYiHuww7GfQngPrLfe\n"
"fiIYPDk1GTUJHBQ7Ue477F7F8vKuHdVgwktF/JDM6M60aSqlo2D/oysirrb+dlur\n"
"Tlv0rjsYOfq6bLAajoL3qi/vek6DNssoywbge4PfbTgS9g7Gcgncbcet5pvaS12J\n"
"avhFcd4JU4Ity49Hl9S/C2MfZ1tE53xVggRwKz4FPj65M5uymTdcxtjKXtCxIE1k\n"
"KxJxXQh7rIYjm+RTAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFkdtpqcybAzJN8G\n"
"+ONuUm5sXNbWta7JGvm8l0BTSBcCUtJA3hn16iJqXA9KmLnaF2denC4EYk+KlVU1\n"
"QXxskPJ4jB8A5B05jMijYv0nzCxKhviI8CR7GLEEGKzeg9pbW0+O3vaVehoZtdFX\n"
"z3SsCssr9QjCLiApQxMzW1Iv3od2JXeHBwfVMFrWA1VCEUCRs8OSW/VOqDPJLVEi\n"
"G6wxc4kN9dLK+5S29q3nzl24/qzXoF8P9Re5KBCbrwaHgy+OEEceq5jkmfGFxXjw\n"
"pvVCNry5uAhH5NqbXZampUWqiWtM4eTaIPo7Y2mDA1uWhuWtO6F9PsnFJlQHCnwy\n"
"s/TsrXk=\n"
"-----END CERTIFICATE-----\n";
/* This is the private-key corresponding to the cert above
*/
static const char sslSelfPKey[] =
"-----BEGIN PRIVATE KEY-----\n"
"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCCbTU26GRQHQqL\n"
"q7vyZ0OxpAxmgfAKCxt6eIz+jBi2ZM/CB5vVXWVh2+SkSiWEA3UZiUqXxZlzmS/C\n"
"glZdiwLLDJML8B4OiV72oivFH/vJ7+cbvh1dTxnYiHuww7GfQngPrLfefiIYPDk1\n"
"GTUJHBQ7Ue477F7F8vKuHdVgwktF/JDM6M60aSqlo2D/oysirrb+dlurTlv0rjsY\n"
"Ofq6bLAajoL3qi/vek6DNssoywbge4PfbTgS9g7Gcgncbcet5pvaS12JavhFcd4J\n"
"U4Ity49Hl9S/C2MfZ1tE53xVggRwKz4FPj65M5uymTdcxtjKXtCxIE1kKxJxXQh7\n"
"rIYjm+RTAgMBAAECggEANfTH1vc8yIe7HRzmm9lsf8jF+II4s2705y2H5qY+cvYx\n"
"nKtZJGOG1X0KkYy7CGoFv5K0cSUl3lS5FVamM/yWIzoIex/Sz2C1EIL2aI5as6ez\n"
"jB6SN0/J+XI8+Vt7186/rHxfdIPpxuzjHbxX3HTpScETNWcLrghbrPxakbTPPxwt\n"
"+x7QlPmmkFNuMfvkzToFf9NdwL++44TeBPOpvD/Lrw+eyqdth9RJPq9cM96plh9V\n"
"HuRqeD8+QNafaXBdSQs3FJK/cDK/vWGKZWIfFVSDbDhwYljkXGijreFjtXQfkkpF\n"
"rl1J87/H9Ee7z8fTD2YXQHl+0/rghAVtac3u54dpQQKBgQC2XG3OEeMrOp9dNkUd\n"
"F8VffUg0ecwG+9L3LCe7U71K0kPmXjV6xNnuYcNQu84kptc5vI8wD23p29LaxdNc\n"
"9m0lcw06/YYBOPkNphcHkINYZTvVJF10mL3isymzMaTtwDkZUkOjL1B+MTiFT/qp\n"
"ARKrTYGJ4HxY7+tUkI5pUmg4PQKBgQC3GA4d1Rz3Pb/RRpcsZgWknKsKhoN36mSn\n"
"xFJ3wPBvVv2B1ltTMzh/+the0ty6clzMrvoLERzRcheDsNrc/j/TUVG8sVdBYJwX\n"
"tMZyFW4NVMOErT/1ukh6jBqIMBo6NJL3EV/AKj0yniksgKOr0/AAduAccnGST8Jd\n"
"SHOdjwvHzwKBgGZBq/zqgNTDuYseHGE07CMgcDWkumiMGv8ozlq3mSR0hUiPOTPP\n"
"YFjQjyIdPXnF6FfiyPPtIvgIoNK2LVAqiod+XUPf152l4dnqcW13dn9BvOxGyPTR\n"
"lWCikFaAFviOWjY9r9m4dU1dslDmySqthFd0TZgPvgps9ivkJ0cdw30NAoGAMC/E\n"
"h1VvKiK2OP27C5ROJ+STn1GHiCfIFd81VQ8SODtMvL8NifgRBp2eFFaqgOdYRQZI\n"
"CGGYlAbS6XXCJCdF5Peh62dA75PdgN+y2pOJQzjrvB9cle9Q4++7i9wdCvSLOTr5\n"
"WDnFoWy+qVexu6crovOmR9ZWzYrwPFy1EOJ010ECgYBl7Q+jmjOSqsVwhFZ0U7LG\n"
"diN+vXhWfn1wfOWd8u79oaqU/Oy7xyKW2p3H5z2KFrBM/vib53Lh4EwFZjcX+jVG\n"
"krAmbL+M/hP7z3TD2UbESAzR/c6l7FU45xN84Lsz5npkR8H/uAHuqLgb9e430Mjx\n"
"YNMwdb8rChHHChNZu6zuxw==\n"
"-----END PRIVATE KEY-----\n";
/*
** Read a PEM certificate from memory and push it into an SSL_CTX.
** Return the number of errors.
*/
static int sslctx_use_cert_from_mem(
SSL_CTX *ctx,
const char *pData,
int nData
){
BIO *in;
int rc = 1;
X509 *x = 0;
X509 *cert = 0;
in = BIO_new_mem_buf(pData, nData);
if( in==0 ) goto end_of_ucfm;
// x = X509_new_ex(ctx->libctx, ctx->propq);
x = X509_new();
if( x==0 ) goto end_of_ucfm;
cert = PEM_read_bio_X509(in, &x, 0, 0);
if( cert==0 ) goto end_of_ucfm;
rc = SSL_CTX_use_certificate(ctx, x)<=0;
end_of_ucfm:
X509_free(x);
BIO_free(in);
return rc;
}
/*
** Read a PEM private key from memory and add it to an SSL_CTX.
** Return the number of errors.
*/
static int sslctx_use_pkey_from_mem(
SSL_CTX *ctx,
const char *pData,
int nData
){
int rc = 1;
BIO *in;
EVP_PKEY *pkey = 0;
in = BIO_new_mem_buf(pData, nData);
if( in==0 ) goto end_of_upkfm;
pkey = PEM_read_bio_PrivateKey(in, 0, 0, 0);
if( pkey==0 ) goto end_of_upkfm;
rc = SSL_CTX_use_PrivateKey(ctx, pkey)<=0;
EVP_PKEY_free(pkey);
end_of_upkfm:
BIO_free(in);
return rc;
}
/*
** Clear the SSL error message
*/
static void ssl_clear_errmsg(void){
free(sslErrMsg);
sslErrMsg = 0;
}
|
| ︙ | ︙ | |||
579 580 581 582 583 584 585 | } /* ** Initialize the SSL library so that it is able to handle ** server-side connections. Invoke fossil_fatal() if there are ** any problems. ** | > > > | | > > > > > > > | | | | | | | | > > > > > > > > > > > > | 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 |
}
/*
** Initialize the SSL library so that it is able to handle
** server-side connections. Invoke fossil_fatal() if there are
** any problems.
**
** If zKeyFile and zCertFile are not NULL, then they are the names
** of disk files that hold the certificate and private-key for the
** server. If zCertFile is not NULL but zKeyFile is NULL, then
** zCertFile is assumed to be a concatenation of the certificate and
** the private-key in the PEM format.
**
** If zCertFile is NULL, then "tls-server-cert" setting is consulted
** to get the certificate and private-key (concatenated together, in
** the PEM format). If there is no tls-server-cert setting, then
** a built-in self-signed cert is used.
*/
void ssl_init_server(const char *zCertFile, const char *zKeyFile){
if( sslIsInit==0 ){
const char *zTlsCert;
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
sslCtx = SSL_CTX_new(SSLv23_server_method());
if( sslCtx==0 ){
ERR_print_errors_fp(stderr);
fossil_fatal("Error initializing the SSL server");
}
if( zCertFile && zCertFile[0] ){
if( SSL_CTX_use_certificate_file(sslCtx,zCertFile,SSL_FILETYPE_PEM)<=0 ){
ERR_print_errors_fp(stderr);
fossil_fatal("Error loading CERT file \"%s\"", zCertFile);
}
if( zKeyFile==0 ) zKeyFile = zCertFile;
if( SSL_CTX_use_PrivateKey_file(sslCtx, zKeyFile, SSL_FILETYPE_PEM)<=0 ){
ERR_print_errors_fp(stderr);
fossil_fatal("Error loading PRIVATE KEY from file \"%s\"", zKeyFile);
}
}else
if( (zTlsCert = db_get("tls-server-cert",0))!=0 ){
if( sslctx_use_cert_from_mem(sslCtx, zTlsCert, -1)
|| sslctx_use_pkey_from_mem(sslCtx, zTlsCert, -1)
){
fossil_fatal("Error loading the CERT from the"
" 'tls-server-cert' setting");
}
}else if( sslctx_use_cert_from_mem(sslCtx, sslSelfCert, -1)
|| sslctx_use_pkey_from_mem(sslCtx, sslSelfPKey, -1) ){
fossil_fatal("Error loading self-signed CERT");
}
if( !SSL_CTX_check_private_key(sslCtx) ){
fossil_fatal("PRIVATE KEY \"%s\" does not match CERT \"%s\"",
zKeyFile, zCertFile);
}
sslIsInit = 2;
}else{
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 |
#if FOSSIL_ENABLE_SSL
const char *zCertFile = 0;
zCertFile = find_option("tls-cert-file",0,1);
if( zCertFile ){
g.httpUseSSL = 1;
ssl_init_server(zCertFile, zCertFile);
}
#endif
}
/*
** COMMAND: server*
** COMMAND: ui
**
| > > > > > > > > > > | 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 |
#if FOSSIL_ENABLE_SSL
const char *zCertFile = 0;
zCertFile = find_option("tls-cert-file",0,1);
if( zCertFile ){
g.httpUseSSL = 1;
ssl_init_server(zCertFile, zCertFile);
}
if( find_option("tls",0,0)!=0 || find_option("ssl",0,0)!=0 ){
g.httpUseSSL = 1;
ssl_init_server(0,0);
}
#if !defined(_WIN32)
if( db_get_int("redirect-to-https",0)==2 ){
g.httpUseSSL = 1;
ssl_init_server(0,0);
}
#endif
#endif
}
/*
** COMMAND: server*
** COMMAND: ui
**
|
| ︙ | ︙ | |||
2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 |
** set by default for the "ui" command)
** --notfound URL Redirect
** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
** -P|--port TCPPORT listen to request on port TCPPORT
** --repolist If REPOSITORY is dir, URL "/" lists repos.
** --scgi Accept SCGI rather than HTTP
** --skin LABEL Use override skin LABEL
** --th-trace trace TH1 execution (for debugging purposes)
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows.
**
** See also: [[cgi]], [[http]], [[winsrv]]
*/
void cmd_webserver(void){
int iPort, mxPort; /* Range of TCP ports allowed */
| > > > | 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 |
** set by default for the "ui" command)
** --notfound URL Redirect
** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
** -P|--port TCPPORT listen to request on port TCPPORT
** --repolist If REPOSITORY is dir, URL "/" lists repos.
** --scgi Accept SCGI rather than HTTP
** --skin LABEL Use override skin LABEL
** --ssl Use TLS (HTTPS) encryption. Alias for --tls
** --th-trace trace TH1 execution (for debugging purposes)
** --tls Use TLS (HTTPS) encryption.
** --tls-cert-file FN Read the TLS certificate and private key from FN
** --usepidkey Use saved encryption key from parent process. This is
** only necessary when using SEE on Windows.
**
** See also: [[cgi]], [[http]], [[winsrv]]
*/
void cmd_webserver(void){
int iPort, mxPort; /* Range of TCP ports allowed */
|
| ︙ | ︙ |