summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/confdb/confdb.h1
-rw-r--r--src/config/SSSDConfig/__init__.py.in1
-rwxr-xr-xsrc/config/SSSDConfigTest.py3
-rw-r--r--src/config/etc/sssd.api.conf1
-rw-r--r--src/man/sssd.conf.5.xml29
-rw-r--r--src/p11_child/p11_child_nss.c25
-rw-r--r--src/responder/pam/pamsrv.h1
-rw-r--r--src/responder/pam/pamsrv_cmd.c14
-rw-r--r--src/responder/pam/pamsrv_p11.c21
-rw-r--r--src/responder/ssh/sshsrv_cmd.c25
-rw-r--r--src/tests/cmocka/test_cert_utils.c2
-rw-r--r--src/tests/cmocka/test_pam_srv.c41
-rw-r--r--src/util/cert.h1
-rw-r--r--src/util/cert/libcrypto/cert.c1
-rw-r--r--src/util/cert/nss/cert.c15
-rw-r--r--src/util/util.c46
-rw-r--r--src/util/util.h3
17 files changed, 208 insertions, 22 deletions
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 0ef7268f9..fcffcb5a6 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -72,6 +72,7 @@
#define CONFDB_MONITOR_OVERRIDE_SPACE "override_space"
#define CONFDB_MONITOR_USER_RUNAS "user"
#define CONFDB_MONITOR_PRE_KILL_CMD "diag_cmd"
+#define CONFDB_MONITOR_CERT_VERIFICATION "certificate_verification"
/* Both monitor and domains */
#define CONFDB_NAME_REGEX "re_expression"
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 60129e6e7..fe2971d99 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -61,6 +61,7 @@ option_strings = {
'krb5_rcache_dir' : _('Directory on the filesystem where SSSD should store Kerberos replay cache files.'),
'default_domain_suffix' : _('Domain to add to names without a domain component.'),
'user' : _('The user to drop privileges to'),
+ 'certificate_verification' : _('Tune certificate verification'),
# [nss]
'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'),
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index abd4a3925..681d8be96 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -308,7 +308,8 @@ class SSSDConfigTestSSSDService(unittest.TestCase):
'fd_limit',
'client_idle_timeout',
'diag_cmd',
- 'description']
+ 'description',
+ 'certificate_verification']
self.assertTrue(type(options) == dict,
"Options should be a dictionary")
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index 0c03625bd..89cf8634f 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -26,6 +26,7 @@ full_name_format = str, None, false
krb5_rcache_dir = str, None, false
user = str, None, false
default_domain_suffix = str, None, false
+certificate_verification = str, None, false
[nss]
# Name service
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 573f421a7..030485cd7 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -365,6 +365,35 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>certificate_verification (string)</term>
+ <listitem>
+ <para>
+ With this parameter the certificate verification
+ can be tuned with a comma separated list of
+ options. Supported options are:
+ <variablelist>
+ <varlistentry>
+ <term>no_ocsp</term>
+ <listitem>
+ <para>Disables Online Certificate Status
+ Protocol (OCSP) checks. This might be
+ needed if the OCSP servers defined in
+ the certificate are not reachable from
+ the client.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ Unknown options are reported but ignored.
+ </para>
+ <para>
+ Default: not set, i.e. do not restrict
+ certificate vertification
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
</refsect2>
diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
index 39c88d9f4..fe092bb05 100644
--- a/src/p11_child/p11_child_nss.c
+++ b/src/p11_child/p11_child_nss.c
@@ -38,10 +38,12 @@
#include <keyhi.h>
#include <pk11pub.h>
#include <prerror.h>
+#include <ocsp.h>
#include "util/child_common.h"
#include "providers/dp_backend.h"
#include "util/crypto/sss_crypto.h"
+#include "util/cert.h"
enum op_mode {
OP_NONE,
@@ -68,7 +70,7 @@ static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
- enum op_mode mode, const char *pin, char **cert,
+ enum op_mode mode, const char *pin, bool do_ocsp, char **cert,
char **token_name_out)
{
int ret;
@@ -261,6 +263,14 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
return EIO;
}
+ if (do_ocsp) {
+ rv = CERT_EnableOCSPChecking(handle);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE, "CERT_EnableOCSPChecking failed: [%d].\n",
+ PR_GetError());
+ return EIO;
+ }
+ }
found_cert = NULL;
DEBUG(SSSDBG_TRACE_ALL, "Filtered certificates:\n");
@@ -456,6 +466,8 @@ int main(int argc, const char *argv[])
char *slot_name_in = NULL;
char *token_name_out = NULL;
char *nss_db = NULL;
+ bool do_ocsp = true;
+ char *verify_opts = NULL;
struct poptOption long_options[] = {
POPT_AUTOHELP
@@ -475,6 +487,8 @@ int main(int argc, const char *argv[])
{"pin", 0, POPT_ARG_NONE, NULL, 'i', _("Expect PIN on stdin"), NULL},
{"keypad", 0, POPT_ARG_NONE, NULL, 'k', _("Expect PIN on keypad"),
NULL},
+ {"verify", 0, POPT_ARG_STRING, &verify_opts, 0 , _("Tune validation"),
+ NULL},
{"nssdb", 0, POPT_ARG_STRING, &nss_db, 0, _("NSS DB to use"),
NULL},
POPT_TABLEEND
@@ -599,6 +613,13 @@ int main(int argc, const char *argv[])
}
talloc_steal(main_ctx, debug_prg_name);
+ if (verify_opts != NULL) {
+ ret = parse_cert_verify_opts(verify_opts, &do_ocsp);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse verifiy option.\n");
+ goto fail;
+ }
+ }
if (mode == OP_AUTH && pin_mode == PIN_STDIN) {
ret = p11c_recv_data(main_ctx, STDIN_FILENO, &pin);
@@ -608,7 +629,7 @@ int main(int argc, const char *argv[])
}
}
- ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, &cert,
+ ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, do_ocsp, &cert,
&token_name_out);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n");
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
index 64a7d8573..b44e1c337 100644
--- a/src/responder/pam/pamsrv.h
+++ b/src/responder/pam/pamsrv.h
@@ -87,6 +87,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
int child_debug_fd,
const char *nss_db,
time_t timeout,
+ const char *verify_opts,
struct pam_data *pd);
errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
char **cert, char **token_name);
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 80095cc0b..b9fd35325 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1032,6 +1032,7 @@ static errno_t check_cert(TALLOC_CTX *mctx,
{
int p11_child_timeout;
const int P11_CHILD_TIMEOUT_DEFAULT = 10;
+ char *cert_verification_opts;
errno_t ret;
struct tevent_req *req;
@@ -1046,8 +1047,19 @@ static errno_t check_cert(TALLOC_CTX *mctx,
return ret;
}
+ ret = confdb_get_string(pctx->rctx->cdb, mctx, CONFDB_MONITOR_CONF_ENTRY,
+ CONFDB_MONITOR_CERT_VERIFICATION, NULL,
+ &cert_verification_opts);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to read certificate_verification from confdb: [%d]: %s\n",
+ ret, sss_strerror(ret));
+ return ret;
+ }
+
req = pam_check_cert_send(mctx, ev, pctx->p11_child_debug_fd,
- pctx->nss_db, p11_child_timeout, pd);
+ pctx->nss_db, p11_child_timeout,
+ cert_verification_opts, pd);
if (req == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n");
return ENOMEM;
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
index afb28fd52..58310a253 100644
--- a/src/responder/pam/pamsrv_p11.c
+++ b/src/responder/pam/pamsrv_p11.c
@@ -236,6 +236,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
int child_debug_fd,
const char *nss_db,
time_t timeout,
+ const char *verify_opts,
struct pam_data *pd)
{
errno_t ret;
@@ -246,9 +247,10 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
struct timeval tv;
int pipefd_to_child[2];
int pipefd_from_child[2];
- const char *extra_args[5] = {NULL, NULL, NULL, NULL, NULL};
+ const char *extra_args[7] = { NULL };
uint8_t *write_buf = NULL;
size_t write_buf_len = 0;
+ size_t arg_c;
req = tevent_req_create(mem_ctx, &state, struct pam_check_cert_state);
if (req == NULL) {
@@ -262,16 +264,21 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
}
/* extra_args are added in revers order */
- extra_args[1] = "--nssdb";
- extra_args[0] = nss_db;
+ arg_c = 0;
+ extra_args[arg_c++] = nss_db;
+ extra_args[arg_c++] = "--nssdb";
+ if (verify_opts != NULL) {
+ extra_args[arg_c++] = verify_opts;
+ extra_args[arg_c++] = "--verify";
+ }
if (pd->cmd == SSS_PAM_AUTHENTICATE) {
- extra_args[2] = "--auth";
+ extra_args[arg_c++] = "--auth";
switch (sss_authtok_get_type(pd->authtok)) {
case SSS_AUTHTOK_TYPE_SC_PIN:
- extra_args[3] = "--pin";
+ extra_args[arg_c++] = "--pin";
break;
case SSS_AUTHTOK_TYPE_SC_KEYPAD:
- extra_args[3] = "--keypad";
+ extra_args[arg_c++] = "--keypad";
break;
default:
DEBUG(SSSDBG_OP_FAILURE, "Unsupported authtok type.\n");
@@ -279,7 +286,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
goto done;
}
} else if (pd->cmd == SSS_PAM_PREAUTH) {
- extra_args[2] = "--pre";
+ extra_args[arg_c++] = "--pre";
} else {
DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected PAM command [%d}.\n", pd->cmd);
ret = EINVAL;
diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
index 5f5487035..af385fde8 100644
--- a/src/responder/ssh/sshsrv_cmd.c
+++ b/src/responder/ssh/sshsrv_cmd.c
@@ -797,6 +797,8 @@ static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx,
int ret;
size_t d;
TALLOC_CTX *tmp_ctx;
+ char *cert_verification_opts;
+ bool do_ocsp = true;
if (el == NULL) {
DEBUG(SSSDBG_TRACE_ALL, "Mssing element, nothing to do.\n");
@@ -811,9 +813,30 @@ static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx,
for (d = 0; d < el->num_values; d++) {
if (cert_data) {
+
+ ret = confdb_get_string(cctx->rctx->cdb, tmp_ctx,
+ CONFDB_MONITOR_CONF_ENTRY,
+ CONFDB_MONITOR_CERT_VERIFICATION, NULL,
+ &cert_verification_opts);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to read p11_child_timeout from confdb: [%d] %s\n",
+ ret, sss_strerror(ret));
+ return ret;
+ }
+
+ if (cert_verification_opts != NULL) {
+ ret = parse_cert_verify_opts(cert_verification_opts, &do_ocsp);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Failed to parse verifiy option.\n");
+ return ret;
+ }
+ }
+
ret = cert_to_ssh_key(tmp_ctx, ssh_ctx->ca_db,
el->values[d].data, el->values[d].length,
- &key, &key_len);
+ do_ocsp, &key, &key_len);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "cert_to_ssh_key failed.\n");
return ret;
diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c
index 7bd8cf234..658391d14 100644
--- a/src/tests/cmocka/test_cert_utils.c
+++ b/src/tests/cmocka/test_cert_utils.c
@@ -356,7 +356,7 @@ void test_cert_to_ssh_key(void **state)
assert_non_null(exp_key);
ret = cert_to_ssh_key(ts, "sql:" ABS_SRC_DIR "/src/tests/cmocka/p11_nssdb",
- der, der_size, &key, &key_size);
+ der, der_size, false, &key, &key_size);
assert_int_equal(ret, EOK);
assert_int_equal(key_size, exp_key_size);
assert_memory_equal(key, exp_key, exp_key_size);
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
index f3fbf907a..75411feee 100644
--- a/src/tests/cmocka/test_pam_srv.c
+++ b/src/tests/cmocka/test_pam_srv.c
@@ -188,26 +188,38 @@ struct pam_ctx *mock_pctx(TALLOC_CTX *mem_ctx)
return pctx;
}
-static int add_pam_params(struct sss_test_conf_param pam_params[],
- struct confdb_ctx *cdb)
+static int add_confdb_params(struct sss_test_conf_param params[],
+ struct confdb_ctx *cdb, const char *section)
{
const char *val[2];
int ret;
val[1] = NULL;
- for (int i = 0; pam_params[i].key; i++) {
- val[0] = pam_params[i].value;
- ret = confdb_add_param(cdb, true, CONFDB_PAM_CONF_ENTRY,
- pam_params[i].key, val);
+ for (int i = 0; params[i].key; i++) {
+ val[0] = params[i].value;
+ ret = confdb_add_param(cdb, true, section, params[i].key, val);
assert_int_equal(ret, EOK);
}
return EOK;
}
+static int add_pam_params(struct sss_test_conf_param pam_params[],
+ struct confdb_ctx *cdb)
+{
+ return add_confdb_params(pam_params, cdb, CONFDB_PAM_CONF_ENTRY);
+}
+
+static int add_monitor_params(struct sss_test_conf_param monitor_params[],
+ struct confdb_ctx *cdb)
+{
+ return add_confdb_params(monitor_params, cdb, CONFDB_MONITOR_CONF_ENTRY);
+}
+
void test_pam_setup(struct sss_test_conf_param dom_params[],
struct sss_test_conf_param pam_params[],
+ struct sss_test_conf_param monitor_params[],
void **state)
{
errno_t ret;
@@ -243,6 +255,9 @@ void test_pam_setup(struct sss_test_conf_param dom_params[],
ret = add_pam_params(pam_params, pam_test_ctx->rctx->cdb);
assert_int_equal(ret, EOK);
+ ret = add_monitor_params(monitor_params, pam_test_ctx->rctx->cdb);
+ assert_int_equal(ret, EOK);
+
/* Create client context */
pam_test_ctx->cctx = mock_cctx(pam_test_ctx, pam_test_ctx->rctx);
assert_non_null(pam_test_ctx->cctx);
@@ -299,7 +314,12 @@ static int pam_test_setup(void **state)
{ NULL, NULL }, /* Sentinel */
};
- test_pam_setup(dom_params, pam_params, state);
+ struct sss_test_conf_param monitor_params[] = {
+ { "certificate_verification", "no_ocsp"},
+ { NULL, NULL }, /* Sentinel */
+ };
+
+ test_pam_setup(dom_params, pam_params, monitor_params, state);
pam_test_setup_common();
return 0;
@@ -319,7 +339,12 @@ static int pam_cached_test_setup(void **state)
{ NULL, NULL }, /* Sentinel */
};
- test_pam_setup(dom_params, pam_params, state);
+ struct sss_test_conf_param monitor_params[] = {
+ { "certificate_verification", "no_ocsp"},
+ { NULL, NULL }, /* Sentinel */
+ };
+
+ test_pam_setup(dom_params, pam_params, monitor_params, state);
pam_test_setup_common();
return 0;
diff --git a/src/util/cert.h b/src/util/cert.h
index edbafc492..c8c425487 100644
--- a/src/util/cert.h
+++ b/src/util/cert.h
@@ -47,5 +47,6 @@ errno_t bin_to_ldap_filter_value(TALLOC_CTX *mem_ctx,
errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
const uint8_t *der_blob, size_t der_size,
+ bool do_ocsp,
uint8_t **key, size_t *key_size);
#endif /* __CERT_H__ */
diff --git a/src/util/cert/libcrypto/cert.c b/src/util/cert/libcrypto/cert.c
index 01f9554b9..4e2dbe70c 100644
--- a/src/util/cert/libcrypto/cert.c
+++ b/src/util/cert/libcrypto/cert.c
@@ -172,6 +172,7 @@ done:
errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
const uint8_t *der_blob, size_t der_size,
+ bool do_ocsp,
uint8_t **key, size_t *key_size)
{
int ret;
diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c
index 1ada35b63..fbd063cf5 100644
--- a/src/util/cert/nss/cert.c
+++ b/src/util/cert/nss/cert.c
@@ -18,16 +18,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "util/util.h"
+#include "config.h"
#include <nss.h>
#include <cert.h>
#include <base64.h>
#include <key.h>
#include <prerror.h>
+#include <ocsp.h>
+#include <talloc.h>
#include "util/crypto/sss_crypto.h"
#include "util/crypto/nss/nss_util.h"
+#include "util/cert.h"
#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
@@ -220,6 +223,7 @@ done:
errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
const uint8_t *der_blob, size_t der_size,
+ bool do_ocsp,
uint8_t **key, size_t *key_size)
{
CERTCertDBHandle *handle;
@@ -255,6 +259,15 @@ errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
handle = CERT_GetDefaultCertDB();
+ if (do_ocsp) {
+ rv = CERT_EnableOCSPChecking(handle);
+ if (rv != SECSuccess) {
+ DEBUG(SSSDBG_OP_FAILURE, "CERT_EnableOCSPChecking failed: [%d].\n",
+ PR_GetError());
+ return EIO;
+ }
+ }
+
der_item.len = der_size;
der_item.data = discard_const(der_blob);
diff --git a/src/util/util.c b/src/util/util.c
index 11924a371..8c0899b06 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -1106,3 +1106,49 @@ errno_t sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl)
return ret;
}
+
+errno_t parse_cert_verify_opts(const char *verify_opts, bool *do_ocsp)
+{
+ int ret;
+ TALLOC_CTX *tmp_ctx;
+ char **opts;
+ size_t c;
+
+ if (verify_opts == NULL) {
+ *do_ocsp = true;
+
+ return EOK;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+ return ENOMEM;
+ }
+
+ ret = split_on_separator(tmp_ctx, verify_opts, ',', true, true, &opts,
+ NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed.\n");
+ goto done;
+ }
+
+ for (c = 0; opts[c] != NULL; c++) {
+ if (strcasecmp(opts[c], "no_ocsp") == 0) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Found 'no_ocsp' option, disabling OCSP.\n");
+ *do_ocsp = false;
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unsupported certificate verification option [%s], " \
+ "skipping.\n", opts[c]);
+ }
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 3693a5e9f..e1245bb0f 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -424,6 +424,9 @@ int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
char **parse_args(const char *str);
+errno_t parse_cert_verify_opts(const char *verify_opts, bool *do_ocsp);
+
+
errno_t sss_hash_create(TALLOC_CTX *mem_ctx,
unsigned long count,
hash_table_t **tbl);