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