Read client certificates in mount_davfs.c
This commit is contained in:
parent
563100c460
commit
c6c3fca29a
@ -1,6 +1,10 @@
|
||||
ChangeLog for davfs2
|
||||
--------------------
|
||||
|
||||
2012-02-05 Werner Baumann (werner.baumann@onlinehome.de)
|
||||
* mount_davfs.c, mount_davfs.h, webdav.c:
|
||||
Better handling of client certificates.
|
||||
|
||||
2012-02-01 Werner Baumann (werner.baumann@onlinehome.de)
|
||||
* mount_davfs.c, mount_davfs.h, webdav.c:
|
||||
Add option trust_server_cert.
|
||||
|
@ -216,7 +216,7 @@ static void
|
||||
read_no_proxy_list(dav_args *args);
|
||||
|
||||
static void
|
||||
read_secrets(dav_args *args, const char *filename);
|
||||
read_secrets(dav_args *args, const char *filename, int system);
|
||||
|
||||
static int
|
||||
split_uri(char **scheme, char **host, int *port,char **path, const char *uri);
|
||||
@ -499,6 +499,24 @@ check_dirs(dav_args *args)
|
||||
}
|
||||
release_privileges(args);
|
||||
|
||||
if (args->sys_clicert) {
|
||||
gain_privileges(args);
|
||||
if (stat(args->clicert, &st) < 0)
|
||||
error(EXIT_FAILURE, 0, _("can't read client certificate %s"),
|
||||
args->clicert);
|
||||
release_privileges(args);
|
||||
if (st.st_uid != 0)
|
||||
error(EXIT_FAILURE, 0,
|
||||
_("client certificate file %s has wrong owner"),
|
||||
args->sys_clicert);
|
||||
if ((st.st_mode &
|
||||
(S_IXUSR | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX))
|
||||
!= 0)
|
||||
error(EXIT_FAILURE, 0,
|
||||
_("client certificate file %s has wrong permissions"),
|
||||
args->sys_clicert);
|
||||
}
|
||||
|
||||
fname = xasprintf("%s/%s", DAV_SYS_CONF_DIR, DAV_SECRETS);
|
||||
if (stat(fname, &st) == 0) {
|
||||
if (st.st_uid != 0)
|
||||
@ -556,6 +574,22 @@ check_dirs(dav_args *args)
|
||||
}
|
||||
free(path);
|
||||
|
||||
if (args->clicert) {
|
||||
if (stat(args->clicert, &st) < 0)
|
||||
error(EXIT_FAILURE, 0, _("can't read client certificate %s"),
|
||||
args->clicert);
|
||||
if (st.st_uid != args->uid)
|
||||
error(EXIT_FAILURE, 0,
|
||||
_("client certificate file %s has wrong owner"),
|
||||
args->clicert);
|
||||
if ((st.st_mode &
|
||||
(S_IXUSR | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX))
|
||||
!= 0)
|
||||
error(EXIT_FAILURE, 0,
|
||||
_("client certificate file %s has wrong permissions"),
|
||||
args->clicert);
|
||||
}
|
||||
|
||||
if (stat(args->secrets, &st) == 0) {
|
||||
if (st.st_uid != args->uid)
|
||||
error(EXIT_FAILURE, 0, _("file %s has wrong owner"),
|
||||
@ -1039,7 +1073,7 @@ parse_config(dav_args *args)
|
||||
}
|
||||
}
|
||||
if (!args->ca_cert)
|
||||
error(EXIT_FAILURE, 0, _("can't read server certificate %s"),
|
||||
error(EXIT_FAILURE, 0, _("can't read CA certificate %s"),
|
||||
args->trust_ca_cert);
|
||||
}
|
||||
|
||||
@ -1076,38 +1110,31 @@ parse_config(dav_args *args)
|
||||
args->secrets = xasprintf("%s/.%s/%s", args->home, PACKAGE,
|
||||
DAV_SECRETS);
|
||||
|
||||
if (args->clicert)
|
||||
if (args->clicert) {
|
||||
expand_home(&args->clicert, args);
|
||||
if (args->clicert && *args->clicert != '/' && !args->privileged) {
|
||||
char *f = xasprintf("%s/.%s/%s/%s/%s", args->home, PACKAGE,
|
||||
DAV_CERTS_DIR, DAV_CLICERTS_DIR, args->clicert);
|
||||
if (access(f, F_OK) == 0) {
|
||||
if (*args->clicert != '/') {
|
||||
char *f = xasprintf("%s/.%s/%s/%s/%s", args->home, PACKAGE,
|
||||
DAV_CERTS_DIR, DAV_CLICERTS_DIR, args->clicert);
|
||||
free(args->clicert);
|
||||
args->clicert = f;
|
||||
}
|
||||
}
|
||||
if (args->clicert && *args->clicert != '/' && args->privileged) {
|
||||
char *f = xasprintf("%s/%s/%s/%s", DAV_SYS_CONF_DIR, DAV_CERTS_DIR,
|
||||
DAV_CLICERTS_DIR, args->clicert);
|
||||
free(args->clicert);
|
||||
args->clicert = f;
|
||||
}
|
||||
if (args->clicert) {
|
||||
struct stat st;
|
||||
gain_privileges(args);
|
||||
if (stat(args->clicert, &st) < 0)
|
||||
args->client_cert = ne_ssl_clicert_read(args->clicert);
|
||||
if (!args->client_cert)
|
||||
error(EXIT_FAILURE, 0, _("can't read client certificate %s"),
|
||||
args->clicert);
|
||||
} else if (args->sys_clicert) {
|
||||
if (*args->sys_clicert != '/') {
|
||||
char *f = xasprintf("%s/.%s/%s/%s/%s", args->home, PACKAGE,
|
||||
DAV_CERTS_DIR, DAV_CLICERTS_DIR,
|
||||
args->sys_clicert);
|
||||
free(args->clicert);
|
||||
args->clicert = f;
|
||||
}
|
||||
gain_privileges(args);
|
||||
args->client_cert = ne_ssl_clicert_read(args->sys_clicert);
|
||||
release_privileges(args);
|
||||
if (st.st_uid != args->uid && st.st_uid != 0)
|
||||
error(EXIT_FAILURE, 0,
|
||||
_("client certificate file %s has wrong owner"),
|
||||
args->clicert);
|
||||
if ((st.st_mode &
|
||||
(S_IXUSR | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX))
|
||||
!= 0)
|
||||
error(EXIT_FAILURE, 0,
|
||||
_("client certificate file %s has wrong permissions"),
|
||||
if (!args->client_cert)
|
||||
error(EXIT_FAILURE, 0, _("can't read client certificate %s"),
|
||||
args->clicert);
|
||||
}
|
||||
|
||||
@ -1183,11 +1210,11 @@ static void
|
||||
parse_secrets(dav_args *args)
|
||||
{
|
||||
gain_privileges(args);
|
||||
read_secrets(args, DAV_SYS_CONF_DIR "/" DAV_SECRETS);
|
||||
read_secrets(args, DAV_SYS_CONF_DIR "/" DAV_SECRETS, 1);
|
||||
release_privileges(args);
|
||||
|
||||
if (args->secrets) {
|
||||
read_secrets(args, args->secrets);
|
||||
read_secrets(args, args->secrets, 0);
|
||||
}
|
||||
|
||||
if (args->cl_username) {
|
||||
@ -1241,6 +1268,19 @@ parse_secrets(dav_args *args)
|
||||
}
|
||||
}
|
||||
|
||||
if (args->client_cert && ne_ssl_clicert_encrypted(args->client_cert)) {
|
||||
if (!args->clicert_pw && args->askauth) {
|
||||
printf(_("Please enter the password to decrypt client\n"
|
||||
"certificate %s.\n"), args->clicert);
|
||||
args->clicert_pw = dav_user_input_hidden(_("Password: "));
|
||||
}
|
||||
if (!args->clicert_pw
|
||||
|| ne_ssl_clicert_decrypt(args->client_cert,
|
||||
args->clicert_pw) != 0)
|
||||
error(EXIT_FAILURE, 0, _("can't decrypt client certificate %s"),
|
||||
args->clicert);
|
||||
}
|
||||
|
||||
if (args->debug & DAV_DBG_SECRETS) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Secrets:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
@ -1456,11 +1496,11 @@ delete_args(dav_args *args)
|
||||
if (args->trust_ca_cert)
|
||||
free(args->trust_ca_cert);
|
||||
if (args->ca_cert)
|
||||
free(args->ca_cert);
|
||||
ne_ssl_cert_free(args->ca_cert);
|
||||
if (args->trust_server_cert)
|
||||
free(args->trust_server_cert);
|
||||
if (args->server_cert)
|
||||
free(args->server_cert);
|
||||
ne_ssl_cert_free(args->server_cert);
|
||||
if (args->secrets)
|
||||
free(args->secrets);
|
||||
if (args->username) {
|
||||
@ -1475,6 +1515,10 @@ delete_args(dav_args *args)
|
||||
}
|
||||
if (args->clicert)
|
||||
free(args->clicert);
|
||||
if (args->sys_clicert)
|
||||
free(args->sys_clicert);
|
||||
if (args->client_cert)
|
||||
ne_ssl_clicert_free(args->client_cert);
|
||||
if (args->clicert_pw) {
|
||||
memset(args->clicert_pw, '\0', strlen(args->clicert_pw));
|
||||
free(args->clicert_pw);
|
||||
@ -1846,10 +1890,14 @@ log_dbg_config(dav_args *args)
|
||||
" path: %s", args->path);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
" trust_ca_cert: %s", args->trust_ca_cert);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
" trust_server_cert: %s", args->trust_server_cert);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
" secrets: %s", args->secrets);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
" clicert: %s", args->clicert);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
" sys_clicert: %s", args->sys_clicert);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
" p_host: %s", args->p_host);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
@ -2155,10 +2203,14 @@ read_config(dav_args *args, const char * filename, int system)
|
||||
if (args->secrets)
|
||||
free(args->secrets);
|
||||
args->secrets = xstrdup(parmv[1]);
|
||||
} else if (strcmp(parmv[0], "clientcert") == 0) {
|
||||
} else if (!system && strcmp(parmv[0], "clientcert") == 0) {
|
||||
if (args->clicert)
|
||||
free(args->clicert);
|
||||
args->clicert = xstrdup(parmv[1]);
|
||||
} else if (system && strcmp(parmv[0], "clientcert") == 0) {
|
||||
if (args->sys_clicert)
|
||||
free(args->sys_clicert);
|
||||
args->sys_clicert = xstrdup(parmv[1]);
|
||||
} else if (system && strcmp(parmv[0], "proxy") == 0) {
|
||||
if (split_uri(NULL, &args->p_host, &args->p_port, NULL,
|
||||
parmv[1]) != 0)
|
||||
@ -2322,7 +2374,7 @@ read_no_proxy_list(dav_args *args)
|
||||
Requires: scheme, host, port, path, clicert, p_host, p_port
|
||||
Provides: username, password, p_user, p_passwd, clicert_pw. */
|
||||
static void
|
||||
read_secrets(dav_args *args, const char *filename)
|
||||
read_secrets(dav_args *args, const char *filename, int system)
|
||||
{
|
||||
FILE *file = fopen(filename, "r");
|
||||
if (!file) {
|
||||
@ -2331,6 +2383,17 @@ read_secrets(dav_args *args, const char *filename)
|
||||
return;
|
||||
}
|
||||
|
||||
char *ccert = NULL;
|
||||
if (!system && args->clicert) {
|
||||
ccert = strrchr(args->clicert, '/');
|
||||
} else if (system && args->sys_clicert) {
|
||||
ccert = strrchr(args->sys_clicert, '/');
|
||||
}
|
||||
if (ccert && *(ccert + 1) == '\0')
|
||||
ccert = NULL;
|
||||
if (ccert)
|
||||
ccert++;
|
||||
|
||||
size_t n = 0;
|
||||
char *line = NULL;
|
||||
int length = getline(&line, &n, file);
|
||||
@ -2358,15 +2421,6 @@ read_secrets(dav_args *args, const char *filename)
|
||||
|
||||
char *mp = canonicalize_file_name(parmv[0]);
|
||||
|
||||
char *ccert = NULL;
|
||||
if (args->clicert) {
|
||||
ccert = strrchr(args->clicert, '/');
|
||||
if (ccert && *(ccert + 1) == '\0')
|
||||
ccert = NULL;
|
||||
if (ccert)
|
||||
ccert++;
|
||||
}
|
||||
|
||||
if ((mp && strcmp(mp, mpoint) == 0)
|
||||
|| (scheme && args->scheme
|
||||
&& strcmp(scheme, args->scheme) == 0
|
||||
@ -2404,7 +2458,7 @@ read_secrets(dav_args *args, const char *filename)
|
||||
if (count == 3)
|
||||
args->p_passwd = xstrdup(parmv[2]);
|
||||
|
||||
} else if (args->clicert
|
||||
} else if (!system && args->clicert
|
||||
&& (strcmp(parmv[0], args->clicert) == 0
|
||||
|| strcmp(parmv[0], ccert) == 0)) {
|
||||
|
||||
@ -2416,6 +2470,19 @@ read_secrets(dav_args *args, const char *filename)
|
||||
free(args->clicert_pw);
|
||||
}
|
||||
args->clicert_pw = xstrdup(parmv[1]);
|
||||
|
||||
} else if (system && args->sys_clicert
|
||||
&& (strcmp(parmv[0], args->sys_clicert) == 0
|
||||
|| strcmp(parmv[0], ccert) == 0)) {
|
||||
|
||||
if (count != 2)
|
||||
error_at_line(EXIT_FAILURE, 0, filename, lineno,
|
||||
_("malformed line"));
|
||||
if (args->clicert_pw) {
|
||||
memset(args->clicert_pw, '\0', strlen(args->clicert_pw));
|
||||
free(args->clicert_pw);
|
||||
}
|
||||
args->clicert_pw = xstrdup(parmv[1]);
|
||||
}
|
||||
|
||||
if (scheme) free(scheme);
|
||||
|
@ -73,7 +73,9 @@ typedef struct {
|
||||
char *username; /* User secrets file, system secrets file */
|
||||
char *cl_username; /* Command line */
|
||||
char *password; /* User secrets file, system secrets file */
|
||||
char *clicert; /* User config file, system config file */
|
||||
char *clicert; /* User config file */
|
||||
char *sys_clicert; /* System config file */
|
||||
ne_ssl_client_cert *client_cert;
|
||||
char *clicert_pw; /* User secrets file, system secrets file */
|
||||
char *p_host; /* User config file, sys conf f., environment */
|
||||
int p_port; /* User config file, sys conf f., environment */
|
||||
|
34
src/webdav.c
34
src/webdav.c
@ -422,38 +422,8 @@ dav_init_webdav(dav_args *args)
|
||||
ne_ssl_trust_cert(session, args->ca_cert);
|
||||
}
|
||||
|
||||
if (args->clicert) {
|
||||
uid_t orig = geteuid();
|
||||
seteuid(0);
|
||||
ne_ssl_client_cert *client_cert
|
||||
= ne_ssl_clicert_read(args->clicert);
|
||||
seteuid(orig);
|
||||
if (!client_cert)
|
||||
error(EXIT_FAILURE, 0, _("can't read client certificate %s"),
|
||||
args->clicert);
|
||||
if (client_cert && ne_ssl_clicert_encrypted(client_cert)) {
|
||||
char *pw = NULL;
|
||||
if (!args->clicert_pw && args->askauth) {
|
||||
printf(_("Please enter the password to decrypt client\n"
|
||||
"certificate %s.\n"), args->clicert);
|
||||
pw = dav_user_input_hidden(_("Password: "));
|
||||
} else {
|
||||
pw = xstrdup(args->clicert_pw);
|
||||
}
|
||||
int ret = 1;
|
||||
if (pw) {
|
||||
ret = ne_ssl_clicert_decrypt(client_cert, pw);
|
||||
memset(pw, '\0', strlen(pw));
|
||||
free(pw);
|
||||
}
|
||||
if (ret)
|
||||
error(EXIT_FAILURE, 0,
|
||||
_("can't decrypt client certificate %s"),
|
||||
args->clicert);
|
||||
}
|
||||
ne_ssl_set_clicert(session, client_cert);
|
||||
ne_ssl_clicert_free(client_cert);
|
||||
}
|
||||
if (args->client_cert)
|
||||
ne_ssl_set_clicert(session, args->client_cert);
|
||||
}
|
||||
|
||||
have_terminal = args->askauth;
|
||||
|
Loading…
Reference in New Issue
Block a user