From a97ec73e04b6347bb6aa9794f5ea9f4ca3424801 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Aug 07 2019 19:11:27 +0000 Subject: utils: move parse_cert_verify_opts() into separate file parse_cert_verify_opts() is only used by p11_child, so it makes sense to move the sources nearer together. The related test is still in test_utils but it can be split out as well if there are more p11_child related unit tests. Related to https://pagure.io/SSSD/sssd/issue/4032 Reviewed-by: Alexey Tikhonov Reviewed-by: Jakub Hrozek --- diff --git a/Makefile.am b/Makefile.am index 39cdaa1..5ad959c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3036,12 +3036,22 @@ test_ipa_idmap_LDADD = \ test_utils_SOURCES = \ src/tests/cmocka/test_utils.c \ src/tests/cmocka/test_string_utils.c \ + src/p11_child/p11_child_common_utils.c \ $(NULL) if BUILD_SSH test_utils_SOURCES += src/tests/cmocka/test_sss_ssh.c endif test_utils_CFLAGS = \ $(AM_CFLAGS) +if HAVE_NSS +test_utils_CFLAGS += \ + $(NSS_CFLAGS) \ + $(NULL) +else +test_utils_CFLAGS += \ + $(P11_KIT_CFLAGS) \ + $(NULL) +endif test_utils_LDADD = \ $(CMOCKA_LIBS) \ $(POPT_LIBS) \ @@ -4667,6 +4677,7 @@ proxy_child_LDADD = \ p11_child_SOURCES = \ src/p11_child/p11_child_common.c \ + src/p11_child/p11_child_common_utils.c \ src/util/atomic_io.c \ src/util/util.c \ src/util/util_ext.c \ diff --git a/src/p11_child/p11_child.h b/src/p11_child/p11_child.h index 92ecf74..d31a76f 100644 --- a/src/p11_child/p11_child.h +++ b/src/p11_child/p11_child.h @@ -30,6 +30,14 @@ #define PKCS11_FINIALIZE_INITIALIZE_WAIT_TIME 3 struct p11_ctx; +struct cert_verify_opts { + bool do_ocsp; + bool do_verification; + char *ocsp_default_responder; + char *ocsp_default_responder_signing_cert; + char *crl_file; +}; + enum op_mode { OP_NONE, OP_AUTH, @@ -55,4 +63,7 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx, enum op_mode mode, const char *pin, const char *module_name_in, const char *token_name_in, const char *key_id_in, const char *uri, char **_multi); + +errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, + struct cert_verify_opts **cert_verify_opts); #endif /* __P11_CHILD_H__ */ diff --git a/src/p11_child/p11_child_common_utils.c b/src/p11_child/p11_child_common_utils.c new file mode 100644 index 0000000..0374eff --- /dev/null +++ b/src/p11_child/p11_child_common_utils.c @@ -0,0 +1,182 @@ +/* + SSSD + + Helper child to commmunicate with SmartCard -- common code + + Authors: + Sumit Bose + + Copyright (C) 2019 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "config.h" +#include + +#include "util/util.h" +#include "p11_child/p11_child.h" + +static struct cert_verify_opts *init_cert_verify_opts(TALLOC_CTX *mem_ctx) +{ + struct cert_verify_opts *cert_verify_opts; + + cert_verify_opts = talloc_zero(mem_ctx, struct cert_verify_opts); + if (cert_verify_opts == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return NULL; + } + + cert_verify_opts->do_ocsp = true; + cert_verify_opts->do_verification = true; + cert_verify_opts->ocsp_default_responder = NULL; + cert_verify_opts->ocsp_default_responder_signing_cert = NULL; + cert_verify_opts->crl_file = NULL; + + return cert_verify_opts; +} + +#define OCSP_DEFAUL_RESPONDER "ocsp_default_responder=" +#define OCSP_DEFAUL_RESPONDER_LEN (sizeof(OCSP_DEFAUL_RESPONDER) - 1) + +#define OCSP_DEFAUL_RESPONDER_SIGNING_CERT \ + "ocsp_default_responder_signing_cert=" +#define OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN \ + (sizeof(OCSP_DEFAUL_RESPONDER_SIGNING_CERT) - 1) +#define CRL_FILE "crl_file=" +#define CRL_FILE_LEN (sizeof(CRL_FILE) -1) + +errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, + struct cert_verify_opts **_cert_verify_opts) +{ + int ret; + TALLOC_CTX *tmp_ctx; + char **opts; + size_t c; + struct cert_verify_opts *cert_verify_opts; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + cert_verify_opts = init_cert_verify_opts(tmp_ctx); + if (cert_verify_opts == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "init_cert_verify_opts failed.\n"); + ret = ENOMEM; + goto done; + } + + if (verify_opts == NULL) { + ret = EOK; + goto done; + } + + 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"); + cert_verify_opts->do_ocsp = false; + } else if (strcasecmp(opts[c], "no_verification") == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Found 'no_verification' option, " + "disabling verification completely. " + "This should not be used in production.\n"); + cert_verify_opts->do_verification = false; + } else if (strncasecmp(opts[c], OCSP_DEFAUL_RESPONDER, + OCSP_DEFAUL_RESPONDER_LEN) == 0) { + cert_verify_opts->ocsp_default_responder = + talloc_strdup(cert_verify_opts, + &opts[c][OCSP_DEFAUL_RESPONDER_LEN]); + if (cert_verify_opts->ocsp_default_responder == NULL + || *cert_verify_opts->ocsp_default_responder == '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to parse ocsp_default_responder option [%s].\n", + opts[c]); + ret = EINVAL; + goto done; + } + + DEBUG(SSSDBG_TRACE_ALL, "Using OCSP default responder [%s]\n", + cert_verify_opts->ocsp_default_responder); + } else if (strncasecmp(opts[c], + OCSP_DEFAUL_RESPONDER_SIGNING_CERT, + OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN) == 0) { + cert_verify_opts->ocsp_default_responder_signing_cert = + talloc_strdup(cert_verify_opts, + &opts[c][OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN]); + if (cert_verify_opts->ocsp_default_responder_signing_cert == NULL + || *cert_verify_opts->ocsp_default_responder_signing_cert + == '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to parse ocsp_default_responder_signing_cert " + "option [%s].\n", opts[c]); + ret = EINVAL; + goto done; + } + + DEBUG(SSSDBG_TRACE_ALL, + "Using OCSP default responder signing cert nickname [%s]\n", + cert_verify_opts->ocsp_default_responder_signing_cert); + } else if (strncasecmp(opts[c], CRL_FILE, CRL_FILE_LEN) == 0) { + cert_verify_opts->crl_file = talloc_strdup(cert_verify_opts, + &opts[c][CRL_FILE_LEN]); + if (cert_verify_opts->crl_file == NULL + || *cert_verify_opts->crl_file == '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to parse crl_file option [%s].\n", opts[c]); + ret = EINVAL; + goto done; + } + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unsupported certificate verification option [%s], " \ + "skipping.\n", opts[c]); + } + } + +#ifdef HAVE_NSS + if ((cert_verify_opts->ocsp_default_responder == NULL + && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) + || (cert_verify_opts->ocsp_default_responder != NULL + && cert_verify_opts->ocsp_default_responder_signing_cert == NULL)) { + + DEBUG(SSSDBG_CRIT_FAILURE, + "ocsp_default_responder and ocsp_default_responder_signing_cert " + "must be used together.\n"); + + ret = EINVAL; + goto done; + } +#endif + + ret = EOK; + +done: + if (ret == EOK) { + *_cert_verify_opts = talloc_steal(mem_ctx, cert_verify_opts); + } + + talloc_free(tmp_ctx); + + return ret; +} diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c index cf1c2ae..4bff56b 100644 --- a/src/tests/cmocka/test_utils.c +++ b/src/tests/cmocka/test_utils.c @@ -26,6 +26,7 @@ #include "tests/cmocka/common_mock.h" #include "util/sss_nss.h" +#include "p11_child/p11_child.h" #include "test_utils.h" #define TESTS_PATH "tp_" BASE_FILE_STEM diff --git a/src/util/util.c b/src/util/util.c index a893fac..b72877e 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1010,159 +1010,6 @@ errno_t sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl) return ret; } -static struct cert_verify_opts *init_cert_verify_opts(TALLOC_CTX *mem_ctx) -{ - struct cert_verify_opts *cert_verify_opts; - - cert_verify_opts = talloc_zero(mem_ctx, struct cert_verify_opts); - if (cert_verify_opts == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); - return NULL; - } - - cert_verify_opts->do_ocsp = true; - cert_verify_opts->do_verification = true; - cert_verify_opts->ocsp_default_responder = NULL; - cert_verify_opts->ocsp_default_responder_signing_cert = NULL; - cert_verify_opts->crl_file = NULL; - - return cert_verify_opts; -} - -#define OCSP_DEFAUL_RESPONDER "ocsp_default_responder=" -#define OCSP_DEFAUL_RESPONDER_LEN (sizeof(OCSP_DEFAUL_RESPONDER) - 1) - -#define OCSP_DEFAUL_RESPONDER_SIGNING_CERT \ - "ocsp_default_responder_signing_cert=" -#define OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN \ - (sizeof(OCSP_DEFAUL_RESPONDER_SIGNING_CERT) - 1) -#define CRL_FILE "crl_file=" -#define CRL_FILE_LEN (sizeof(CRL_FILE) -1) - -errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, - struct cert_verify_opts **_cert_verify_opts) -{ - int ret; - TALLOC_CTX *tmp_ctx; - char **opts; - size_t c; - struct cert_verify_opts *cert_verify_opts; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); - return ENOMEM; - } - - cert_verify_opts = init_cert_verify_opts(tmp_ctx); - if (cert_verify_opts == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "init_cert_verify_opts failed.\n"); - ret = ENOMEM; - goto done; - } - - if (verify_opts == NULL) { - ret = EOK; - goto done; - } - - 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"); - cert_verify_opts->do_ocsp = false; - } else if (strcasecmp(opts[c], "no_verification") == 0) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Found 'no_verification' option, " - "disabling verification completely. " - "This should not be used in production.\n"); - cert_verify_opts->do_verification = false; - } else if (strncasecmp(opts[c], OCSP_DEFAUL_RESPONDER, - OCSP_DEFAUL_RESPONDER_LEN) == 0) { - cert_verify_opts->ocsp_default_responder = - talloc_strdup(cert_verify_opts, - &opts[c][OCSP_DEFAUL_RESPONDER_LEN]); - if (cert_verify_opts->ocsp_default_responder == NULL - || *cert_verify_opts->ocsp_default_responder == '\0') { - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to parse ocsp_default_responder option [%s].\n", - opts[c]); - ret = EINVAL; - goto done; - } - - DEBUG(SSSDBG_TRACE_ALL, "Using OCSP default responder [%s]\n", - cert_verify_opts->ocsp_default_responder); - } else if (strncasecmp(opts[c], - OCSP_DEFAUL_RESPONDER_SIGNING_CERT, - OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN) == 0) { - cert_verify_opts->ocsp_default_responder_signing_cert = - talloc_strdup(cert_verify_opts, - &opts[c][OCSP_DEFAUL_RESPONDER_SIGNING_CERT_LEN]); - if (cert_verify_opts->ocsp_default_responder_signing_cert == NULL - || *cert_verify_opts->ocsp_default_responder_signing_cert - == '\0') { - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to parse ocsp_default_responder_signing_cert " - "option [%s].\n", opts[c]); - ret = EINVAL; - goto done; - } - - DEBUG(SSSDBG_TRACE_ALL, - "Using OCSP default responder signing cert nickname [%s]\n", - cert_verify_opts->ocsp_default_responder_signing_cert); - } else if (strncasecmp(opts[c], CRL_FILE, CRL_FILE_LEN) == 0) { - cert_verify_opts->crl_file = talloc_strdup(cert_verify_opts, - &opts[c][CRL_FILE_LEN]); - if (cert_verify_opts->crl_file == NULL - || *cert_verify_opts->crl_file == '\0') { - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to parse crl_file option [%s].\n", opts[c]); - ret = EINVAL; - goto done; - } - } else { - DEBUG(SSSDBG_CRIT_FAILURE, - "Unsupported certificate verification option [%s], " \ - "skipping.\n", opts[c]); - } - } - -#ifdef HAVE_NSS - if ((cert_verify_opts->ocsp_default_responder == NULL - && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) - || (cert_verify_opts->ocsp_default_responder != NULL - && cert_verify_opts->ocsp_default_responder_signing_cert == NULL)) { - - DEBUG(SSSDBG_CRIT_FAILURE, - "ocsp_default_responder and ocsp_default_responder_signing_cert " - "must be used together.\n"); - - ret = EINVAL; - goto done; - } -#endif - - ret = EOK; - -done: - if (ret == EOK) { - *_cert_verify_opts = talloc_steal(mem_ctx, cert_verify_opts); - } - - talloc_free(tmp_ctx); - - return ret; -} - bool is_user_or_group_name(const char *sudo_user_value) { if (sudo_user_value == NULL) { diff --git a/src/util/util.h b/src/util/util.h index 7b3f43b..c7edbbb 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -373,17 +373,6 @@ int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, char **parse_args(const char *str); -struct cert_verify_opts { - bool do_ocsp; - bool do_verification; - char *ocsp_default_responder; - char *ocsp_default_responder_signing_cert; - char *crl_file; -}; - -errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, - struct cert_verify_opts **cert_verify_opts); - errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count, hash_table_t **tbl);