Fossil SCM

Support for client side SSL certificates for extra authentication to https servers. Adds --ssl-identity command line option and ssl-identity setting to specify the filename of a identity file containing a PEM encoded certificate and private key.

ben 2011-05-29 12:49 ben-security
Commit e06ea26e97e20859a812da55b4914cade028d411
+10
--- src/clone.c
+++ src/clone.c
@@ -37,19 +37,21 @@
3737
**
3838
** Options:
3939
**
4040
** --admin-user|-A USERNAME Make USERNAME the administrator
4141
** --private Also clone private branches
42
+** --ssl-identity=filename Use the SSL identity if requested by the server
4243
**
4344
*/
4445
void clone_cmd(void){
4546
char *zPassword;
4647
const char *zDefaultUser; /* Optional name of the default user */
4748
int nErr = 0;
4849
int bPrivate; /* Also clone private branches */
4950
5051
bPrivate = find_option("private",0,0)!=0;
52
+ find_option("ssl-identity",0,1);
5153
url_proxy_options();
5254
if( g.argc < 4 ){
5355
usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
5456
}
5557
db_open_config(0);
@@ -91,10 +93,18 @@
9193
db_initial_setup(0, zDefaultUser, 0);
9294
user_select();
9395
db_set("content-schema", CONTENT_SCHEMA, 0);
9496
db_set("aux-schema", AUX_SCHEMA, 0);
9597
db_set("last-sync-url", g.argv[2], 0);
98
+ if( g.zSSLIdentity!=0 ){
99
+ /* If the --ssl-identity option was specified, store it as a setting */
100
+ Blob fn;
101
+ blob_zero(&fn);
102
+ file_canonical_name(g.zSSLIdentity, &fn);
103
+ db_set("ssl-identity", blob_str(&fn), 0);
104
+ blob_reset(&fn);
105
+ }
96106
db_multi_exec(
97107
"REPLACE INTO config(name,value,mtime)"
98108
" VALUES('server-code', lower(hex(randomblob(20))), now());"
99109
);
100110
url_enable_proxy(0);
101111
--- src/clone.c
+++ src/clone.c
@@ -37,19 +37,21 @@
37 **
38 ** Options:
39 **
40 ** --admin-user|-A USERNAME Make USERNAME the administrator
41 ** --private Also clone private branches
 
42 **
43 */
44 void clone_cmd(void){
45 char *zPassword;
46 const char *zDefaultUser; /* Optional name of the default user */
47 int nErr = 0;
48 int bPrivate; /* Also clone private branches */
49
50 bPrivate = find_option("private",0,0)!=0;
 
51 url_proxy_options();
52 if( g.argc < 4 ){
53 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
54 }
55 db_open_config(0);
@@ -91,10 +93,18 @@
91 db_initial_setup(0, zDefaultUser, 0);
92 user_select();
93 db_set("content-schema", CONTENT_SCHEMA, 0);
94 db_set("aux-schema", AUX_SCHEMA, 0);
95 db_set("last-sync-url", g.argv[2], 0);
 
 
 
 
 
 
 
 
96 db_multi_exec(
97 "REPLACE INTO config(name,value,mtime)"
98 " VALUES('server-code', lower(hex(randomblob(20))), now());"
99 );
100 url_enable_proxy(0);
101
--- src/clone.c
+++ src/clone.c
@@ -37,19 +37,21 @@
37 **
38 ** Options:
39 **
40 ** --admin-user|-A USERNAME Make USERNAME the administrator
41 ** --private Also clone private branches
42 ** --ssl-identity=filename Use the SSL identity if requested by the server
43 **
44 */
45 void clone_cmd(void){
46 char *zPassword;
47 const char *zDefaultUser; /* Optional name of the default user */
48 int nErr = 0;
49 int bPrivate; /* Also clone private branches */
50
51 bPrivate = find_option("private",0,0)!=0;
52 find_option("ssl-identity",0,1);
53 url_proxy_options();
54 if( g.argc < 4 ){
55 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
56 }
57 db_open_config(0);
@@ -91,10 +93,18 @@
93 db_initial_setup(0, zDefaultUser, 0);
94 user_select();
95 db_set("content-schema", CONTENT_SCHEMA, 0);
96 db_set("aux-schema", AUX_SCHEMA, 0);
97 db_set("last-sync-url", g.argv[2], 0);
98 if( g.zSSLIdentity!=0 ){
99 /* If the --ssl-identity option was specified, store it as a setting */
100 Blob fn;
101 blob_zero(&fn);
102 file_canonical_name(g.zSSLIdentity, &fn);
103 db_set("ssl-identity", blob_str(&fn), 0);
104 blob_reset(&fn);
105 }
106 db_multi_exec(
107 "REPLACE INTO config(name,value,mtime)"
108 " VALUES('server-code', lower(hex(randomblob(20))), now());"
109 );
110 url_enable_proxy(0);
111
+8
--- src/db.c
+++ src/db.c
@@ -1662,10 +1662,11 @@
16621662
{ "mtime-changes", 0, 0, "on" },
16631663
{ "pgp-command", 0, 32, "gpg --clearsign -o " },
16641664
{ "proxy", 0, 32, "off" },
16651665
{ "repo-cksum", 0, 0, "on" },
16661666
{ "self-register", 0, 0, "off" },
1667
+ { "ssl-identity", 0, 40, "" },
16671668
{ "ssh-command", 0, 32, "" },
16681669
{ "web-browser", 0, 32, "" },
16691670
{ 0,0,0,0 }
16701671
};
16711672
@@ -1771,10 +1772,17 @@
17711772
**
17721773
** self-register Allow users to register themselves through the HTTP UI.
17731774
** This is useful if you want to see other names than
17741775
** "Anonymous" in e.g. ticketing system. On the other hand
17751776
** users can not be deleted. Default: off.
1777
+**
1778
+** ssl-identity The full pathname to a file containing a certificate
1779
+** and private key in PEM format. Create by concatenating
1780
+** the certificate and private key files.
1781
+** This identity will be presented to SSL servers to
1782
+** authenticate this client, in addition to the normal
1783
+** password authentication.
17761784
**
17771785
** ssh-command Command used to talk to a remote machine with
17781786
** the "ssh://" protocol.
17791787
**
17801788
** web-browser A shell command used to launch your preferred
17811789
--- src/db.c
+++ src/db.c
@@ -1662,10 +1662,11 @@
1662 { "mtime-changes", 0, 0, "on" },
1663 { "pgp-command", 0, 32, "gpg --clearsign -o " },
1664 { "proxy", 0, 32, "off" },
1665 { "repo-cksum", 0, 0, "on" },
1666 { "self-register", 0, 0, "off" },
 
1667 { "ssh-command", 0, 32, "" },
1668 { "web-browser", 0, 32, "" },
1669 { 0,0,0,0 }
1670 };
1671
@@ -1771,10 +1772,17 @@
1771 **
1772 ** self-register Allow users to register themselves through the HTTP UI.
1773 ** This is useful if you want to see other names than
1774 ** "Anonymous" in e.g. ticketing system. On the other hand
1775 ** users can not be deleted. Default: off.
 
 
 
 
 
 
 
1776 **
1777 ** ssh-command Command used to talk to a remote machine with
1778 ** the "ssh://" protocol.
1779 **
1780 ** web-browser A shell command used to launch your preferred
1781
--- src/db.c
+++ src/db.c
@@ -1662,10 +1662,11 @@
1662 { "mtime-changes", 0, 0, "on" },
1663 { "pgp-command", 0, 32, "gpg --clearsign -o " },
1664 { "proxy", 0, 32, "off" },
1665 { "repo-cksum", 0, 0, "on" },
1666 { "self-register", 0, 0, "off" },
1667 { "ssl-identity", 0, 40, "" },
1668 { "ssh-command", 0, 32, "" },
1669 { "web-browser", 0, 32, "" },
1670 { 0,0,0,0 }
1671 };
1672
@@ -1771,10 +1772,17 @@
1772 **
1773 ** self-register Allow users to register themselves through the HTTP UI.
1774 ** This is useful if you want to see other names than
1775 ** "Anonymous" in e.g. ticketing system. On the other hand
1776 ** users can not be deleted. Default: off.
1777 **
1778 ** ssl-identity The full pathname to a file containing a certificate
1779 ** and private key in PEM format. Create by concatenating
1780 ** the certificate and private key files.
1781 ** This identity will be presented to SSL servers to
1782 ** authenticate this client, in addition to the normal
1783 ** password authentication.
1784 **
1785 ** ssh-command Command used to talk to a remote machine with
1786 ** the "ssh://" protocol.
1787 **
1788 ** web-browser A shell command used to launch your preferred
1789
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -78,10 +78,19 @@
7878
** Return the current SSL error message
7979
*/
8080
const char *ssl_errmsg(void){
8181
return sslErrMsg;
8282
}
83
+
84
+/*
85
+** When a server requests a client certificate that hasn't been provided,
86
+** display a warning message explaining what to do next.
87
+*/
88
+static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
89
+ fossil_warning("The remote server requested a client certificate for authentication. Specify the pathname to a file containing the PEM encoded certificate and private key with the --ssl-identity option or the ssl-identity setting.");
90
+ return 0; /* no cert available */
91
+}
8392
8493
/*
8594
** Call this routine once before any other use of the SSL interface.
8695
** This routine does initial configuration of the SSL module.
8796
*/
@@ -91,10 +100,22 @@
91100
SSL_load_error_strings();
92101
ERR_load_BIO_strings();
93102
OpenSSL_add_all_algorithms();
94103
sslCtx = SSL_CTX_new(SSLv23_client_method());
95104
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
110
+ || SSL_CTX_use_PrivateKey_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!=1 ){
111
+ fossil_fatal("Could not load SSL identity from %s", identityFile);
112
+ }
113
+ }
114
+ /* Register a callback to tell the user what to do when the server asks for a cert */
115
+ SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
116
+
96117
sslIsInit = 1;
97118
}
98119
}
99120
100121
/*
101122
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -78,10 +78,19 @@
78 ** Return the current SSL error message
79 */
80 const char *ssl_errmsg(void){
81 return sslErrMsg;
82 }
 
 
 
 
 
 
 
 
 
83
84 /*
85 ** Call this routine once before any other use of the SSL interface.
86 ** This routine does initial configuration of the SSL module.
87 */
@@ -91,10 +100,22 @@
91 SSL_load_error_strings();
92 ERR_load_BIO_strings();
93 OpenSSL_add_all_algorithms();
94 sslCtx = SSL_CTX_new(SSLv23_client_method());
95 X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
 
 
 
 
 
 
 
 
 
 
 
 
96 sslIsInit = 1;
97 }
98 }
99
100 /*
101
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -78,10 +78,19 @@
78 ** Return the current SSL error message
79 */
80 const char *ssl_errmsg(void){
81 return sslErrMsg;
82 }
83
84 /*
85 ** When a server requests a client certificate that hasn't been provided,
86 ** display a warning message explaining what to do next.
87 */
88 static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
89 fossil_warning("The remote server requested a client certificate for authentication. Specify the pathname to a file containing the PEM encoded certificate and private key with the --ssl-identity option or the ssl-identity setting.");
90 return 0; /* no cert available */
91 }
92
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 */
@@ -91,10 +100,22 @@
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
110 || SSL_CTX_use_PrivateKey_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!=1 ){
111 fossil_fatal("Could not load SSL identity from %s", identityFile);
112 }
113 }
114 /* Register a callback to tell the user what to do when the server asks for a cert */
115 SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
116
117 sslIsInit = 1;
118 }
119 }
120
121 /*
122
+2
--- src/main.c
+++ src/main.c
@@ -104,10 +104,11 @@
104104
char *urlProxyAuth; /* Proxy-Authorizer: string */
105105
char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
106106
int dontKeepUrl; /* Do not persist the URL */
107107
108108
const char *zLogin; /* Login name. "" if not logged in. */
109
+ const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
109110
int useLocalauth; /* No login required if from 127.0.0.1 */
110111
int noPswd; /* Logged in without password (on 127.0.0.1) */
111112
int userUid; /* Integer user id */
112113
113114
/* Information used to populate the RCVFROM table */
@@ -249,10 +250,11 @@
249250
g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
250251
if( g.fSqlTrace ) g.fSqlStats = 1;
251252
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
252253
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
253254
g.zLogin = find_option("user", "U", 1);
255
+ g.zSSLIdentity = find_option("ssl-identity", 0, 1);
254256
if( find_option("help",0,0)!=0 ){
255257
/* --help anywhere on the command line is translated into
256258
** "fossil help argv[1] argv[2]..." */
257259
int i;
258260
char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
259261
--- src/main.c
+++ src/main.c
@@ -104,10 +104,11 @@
104 char *urlProxyAuth; /* Proxy-Authorizer: string */
105 char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
106 int dontKeepUrl; /* Do not persist the URL */
107
108 const char *zLogin; /* Login name. "" if not logged in. */
 
109 int useLocalauth; /* No login required if from 127.0.0.1 */
110 int noPswd; /* Logged in without password (on 127.0.0.1) */
111 int userUid; /* Integer user id */
112
113 /* Information used to populate the RCVFROM table */
@@ -249,10 +250,11 @@
249 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
250 if( g.fSqlTrace ) g.fSqlStats = 1;
251 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
252 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
253 g.zLogin = find_option("user", "U", 1);
 
254 if( find_option("help",0,0)!=0 ){
255 /* --help anywhere on the command line is translated into
256 ** "fossil help argv[1] argv[2]..." */
257 int i;
258 char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
259
--- src/main.c
+++ src/main.c
@@ -104,10 +104,11 @@
104 char *urlProxyAuth; /* Proxy-Authorizer: string */
105 char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
106 int dontKeepUrl; /* Do not persist the URL */
107
108 const char *zLogin; /* Login name. "" if not logged in. */
109 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
110 int useLocalauth; /* No login required if from 127.0.0.1 */
111 int noPswd; /* Logged in without password (on 127.0.0.1) */
112 int userUid; /* Integer user id */
113
114 /* Information used to populate the RCVFROM table */
@@ -249,10 +250,11 @@
250 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
251 if( g.fSqlTrace ) g.fSqlStats = 1;
252 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
253 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
254 g.zLogin = find_option("user", "U", 1);
255 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
256 if( find_option("help",0,0)!=0 ){
257 /* --help anywhere on the command line is translated into
258 ** "fossil help argv[1] argv[2]..." */
259 int i;
260 char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
261

Keyboard Shortcuts

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