On Tue, Jun 16, 2015 at 10:44:35AM +0200, Pavel Březina wrote: > On 06/11/2015 01:08 PM, Sumit Bose wrote: > >On Thu, Jun 04, 2015 at 12:31:34PM +0200, Pavel Březina wrote: > >>On 06/04/2015 11:06 AM, Sumit Bose wrote: > >>>Hi, > >>> > >>>this patch-set aims to solve https://fedorahosted.org/sssd/ticket/2596. > >>>The first patch is unrelated but needed to make the changes in the > >>>second patch properly aligned. > >>> > >>>Patches 3,4 and 6 add some certificate related utilities while patch 5 > >>>adds the backend changes and patch 7 the changes for InfoPipe. > >>> > >>>bye, > >>>Sumit > > > >Hi Pavel, > > > >thank you for the review. > > > >> > >>>+errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx, > >>>+ struct sss_domain_info *domain, > >>>+ const char *cert, > >>>+ const char **attrs, > >>>+ struct ldb_result **res) > >>>+{ > >>>+ int ret; > >>>+ char *user_filter; > >>>+ > >>>+ ret = sss_cert_derb64_to_ldap_filter(mem_ctx, cert, SYSDB_USER_CERT, > >>>+ &user_filter); > >>>+ if (ret != EOK) { > >>>+ DEBUG(SSSDBG_OP_FAILURE, "sss_cert_derb64_to_ldap_filter > >>>failed.\n"); > >>>+ return ret; > >>>+ } > >>>+ > >> vv two spaces here > > > >fixed > > > >>>+ ret = sysdb_search_object_by_str_attr(mem_ctx, domain, > >>>+ SYSDB_USER_CERT_FILTER, > >>>+ user_filter, attrs, res); > >>>+ talloc_free(user_filter); > >>>+ > >>>+ return ret; > >>>+} > >>>+ > >>>+errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx, > >>>+ struct sss_domain_info *domain, > >>>+ const char *cert, > >>>+ struct ldb_result **res) > >>>+{ > >>>+ const char *user_attrs[] = SYSDB_PW_ATTRS; > >>>+ > >>>+ return sysdb_search_object_by_cert(mem_ctx, domain, cert, > >>>user_attrs, res); > >> ^^ two spaces here > > > >fixed > > > >>>+} > >> > >>cache_req: > >>>search_str = state->input->type == CACHE_REQ_USER_BY_CERT ? > >>> state->input->orig_name : > >>> state->input->dom_objname; > >> > >>I think it will be better to create a new field in cache_req_input, say > >>'cert', to not abuse fields that resemble object names. The code will be > >>cleaner and you can get rid of few parts like: > > > >I added cert. > > > >> > >>> if (state->input->orig_name != NULL && domain == NULL > >>> && (input->type == CACHE_REQ_USER_BY_NAME > >>> || input->type == CACHE_REQ_GROUP_BY_NAME > >>> || input->type == CACHE_REQ_INITGROUPS)) > > > >new version attached. > > > >bye, > >Sumit > > Hi, > I rebased it on top of current master (just trivial Makefile.am conflicts) > and fixed some indentation. Diff:
yes, I aldready had this in my tree but forgot to send it. > > diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c > index 3aa7099..6d0aede 100644 > --- a/src/db/sysdb_ops.c > +++ b/src/db/sysdb_ops.c > @@ -3720,8 +3720,8 @@ errno_t sysdb_search_object_by_cert(TALLOC_CTX > *mem_ctx, > } > > ret = sysdb_search_object_by_str_attr(mem_ctx, domain, > - SYSDB_USER_CERT_FILTER, > - user_filter, attrs, res); > + SYSDB_USER_CERT_FILTER, > + user_filter, attrs, res); > talloc_free(user_filter); > > return ret; thanks, added > > Ack to all patches but the last. > > >@@ -82,6 +83,17 @@ cache_req_input_create(TALLOC_CTX *mem_ctx, > > goto fail; > > } > > break; > >+ case CACHE_REQ_USER_BY_CERT: > >+ if (name == NULL) { > >+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: certificate cannot be > >NULL!\n"); > >+ goto fail; > >+ } > > Can you create a parameter 'cert' instead of abusing 'name' here? ok, I added it, but maybe in the long when we add searches by SIDs or email addresses something more flexible, maybe a union would be useful here. > > >+ > >+ input->cert = talloc_strdup(input, name); > >+ if (input->cert == NULL) { > >+ goto fail; > >+ } > >+ break; > > >+ case CACHE_REQ_USER_BY_CERT: > >+ fqn = talloc_asprintf(tmp_ctx, "CERT:%s@%s", input->cert, > >domain->name); > >+ if (fqn == NULL) { > >+ ret = ENOMEM; > >+ goto done; > >+ } > >+ break; > > The 'fqn' is used for debugging purpose. How large can string 'input->cert' > get? I'm a little worried that it will just spam log files with long string > noone will ever read. Wouldn't it suffice to just print few > first/middle/last characters (or combined)? I added a small utility which returns the last x characters of a string because I think the last characters are more unique here then the first ones. > > >+ search_str = (state->input->type == CACHE_REQ_USER_BY_CERT) ? > >+ state->input->cert : > >state->input->dom_objname; > > Since you have to break the line anyway, the following may read better, what > do you think? > > search_str = state->input->dom_objname; > if (state->input->type == CERT) { > search_str = ... > } replaced > > >--- a/src/sbus/sssd_dbus_errors.h > >+++ b/src/sbus/sssd_dbus_errors.h > >@@ -25,5 +25,6 @@ > > > > #define SBUS_ERROR_INTERNAL "org.freedesktop.sssd.Error.Internal" > > #define SBUS_ERROR_NOT_FOUND "org.freedesktop.sssd.Error.NotFound" > >+#define SBUS_ERROR_EINVAL "org.freedesktop.sssd.Error.InvalidArgument" > > D-Bus error for EINVAL already exist: DBUS_ERROR_INVALID_ARGS. I think we > should stick to standard ones when applicable. replaced Thank you for the review, new version attached. bye, Sumit
From ddbf02875a53ef5198bf60e61b4f328d7f44288a Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Thu, 7 May 2015 10:58:33 +0200 Subject: [PATCH 1/8] adding ldap_user_auth_type where missing --- src/config/SSSDConfig/__init__.py.in | 2 ++ src/config/etc/sssd.api.d/sssd-ad.conf | 1 + src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + src/config/etc/sssd.api.d/sssd-ldap.conf | 1 + 4 files changed, 5 insertions(+) diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index af7f1bffbd910c0dee177eb64996233ac18fff19..0654cb63bd93c616c85261555e4f38d9fc02ccb2 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -307,6 +307,8 @@ option_strings = { 'ldap_user_nds_login_expiration_time' : _('loginExpirationTime attribute of NDS'), 'ldap_user_nds_login_allowed_time_map' : _('loginAllowedTimeMap attribute of NDS'), 'ldap_user_ssh_public_key' : _('SSH public key attribute'), + 'ldap_user_auth_type' : _('attribute listing allowed authentication types for a user'), + 'ldap_user_extra_attrs' : _('A list of extra attributes to download along with the user entry'), 'ldap_group_search_base' : _('Base DN for group lookups'), diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf index c46f3a7cb50db519d113e15f425c7f746d34ad81..23194d38a35fcc9ae2134c3dbbc7cef1aefcf079 100644 --- a/src/config/etc/sssd.api.d/sssd-ad.conf +++ b/src/config/etc/sssd.api.d/sssd-ad.conf @@ -93,6 +93,7 @@ ldap_user_krb_last_pwd_change = str, None, false ldap_user_krb_password_expiration = str, None, false ldap_pwd_attribute = str, None, false ldap_user_ssh_public_key = str, None, false +ldap_user_auth_type = str, None, false ldap_group_search_base = str, None, false ldap_group_search_scope = str, None, false ldap_group_search_filter = str, None, false diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf index 6bae609fa9ff57e70c195b858eeea4eca680f62f..075a74e3aabe4ff664814b8a1aef8117496e9273 100644 --- a/src/config/etc/sssd.api.d/sssd-ipa.conf +++ b/src/config/etc/sssd.api.d/sssd-ipa.conf @@ -89,6 +89,7 @@ ldap_user_krb_last_pwd_change = str, None, false ldap_user_krb_password_expiration = str, None, false ldap_pwd_attribute = str, None, false ldap_user_ssh_public_key = str, None, false +ldap_user_auth_type = str, None, false ldap_group_search_base = str, None, false ldap_group_search_scope = str, None, false ldap_group_search_filter = str, None, false diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf index ba5f56f1942da552fc6ab8f82851714756683a8f..e27d570b8cdf8ad765d16b8f8befe5c25fbebc28 100644 --- a/src/config/etc/sssd.api.d/sssd-ldap.conf +++ b/src/config/etc/sssd.api.d/sssd-ldap.conf @@ -83,6 +83,7 @@ ldap_user_nds_login_disabled = str, None, false ldap_user_nds_login_expiration_time = str, None, false ldap_user_nds_login_allowed_time_map = str, None, false ldap_user_ssh_public_key = str, None, false +ldap_user_auth_type = str, None, false ldap_group_search_base = str, None, false ldap_group_search_scope = str, None, false ldap_group_search_filter = str, None, false -- 2.1.0
From b69f582a711a5d210e7cf98b3c7242b4baa50d68 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Thu, 7 May 2015 10:59:10 +0200 Subject: [PATCH 2/8] LDAP: add ldap_user_certificate option Related to https://fedorahosted.org/sssd/ticket/2596 --- src/config/SSSDConfig/__init__.py.in | 1 + src/config/etc/sssd.api.d/sssd-ad.conf | 1 + src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + src/config/etc/sssd.api.d/sssd-ldap.conf | 1 + src/db/sysdb.h | 1 + src/man/sssd-ldap.5.xml | 14 ++++++++++++++ src/providers/ad/ad_opts.h | 1 + src/providers/ipa/ipa_opts.h | 1 + src/providers/ldap/ldap_opts.h | 3 +++ src/providers/ldap/sdap.h | 1 + 10 files changed, 25 insertions(+) diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 0654cb63bd93c616c85261555e4f38d9fc02ccb2..f2d9bf0190745d4a5296c56212e5ff97681db59c 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -308,6 +308,7 @@ option_strings = { 'ldap_user_nds_login_allowed_time_map' : _('loginAllowedTimeMap attribute of NDS'), 'ldap_user_ssh_public_key' : _('SSH public key attribute'), 'ldap_user_auth_type' : _('attribute listing allowed authentication types for a user'), + 'ldap_user_certificate' : _('attribute containing the X509 certificate of the user'), 'ldap_user_extra_attrs' : _('A list of extra attributes to download along with the user entry'), diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf index 23194d38a35fcc9ae2134c3dbbc7cef1aefcf079..faab3a51e54d6d498392021a8945501120870f70 100644 --- a/src/config/etc/sssd.api.d/sssd-ad.conf +++ b/src/config/etc/sssd.api.d/sssd-ad.conf @@ -94,6 +94,7 @@ ldap_user_krb_password_expiration = str, None, false ldap_pwd_attribute = str, None, false ldap_user_ssh_public_key = str, None, false ldap_user_auth_type = str, None, false +ldap_user_certificate = str, None, false ldap_group_search_base = str, None, false ldap_group_search_scope = str, None, false ldap_group_search_filter = str, None, false diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf index 075a74e3aabe4ff664814b8a1aef8117496e9273..cfcc00f6f7ca768df861e8cf7face065f90e9e83 100644 --- a/src/config/etc/sssd.api.d/sssd-ipa.conf +++ b/src/config/etc/sssd.api.d/sssd-ipa.conf @@ -90,6 +90,7 @@ ldap_user_krb_password_expiration = str, None, false ldap_pwd_attribute = str, None, false ldap_user_ssh_public_key = str, None, false ldap_user_auth_type = str, None, false +ldap_user_certificate = str, None, false ldap_group_search_base = str, None, false ldap_group_search_scope = str, None, false ldap_group_search_filter = str, None, false diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf index e27d570b8cdf8ad765d16b8f8befe5c25fbebc28..c10290217b1b133792b893d9b80e2599969838a6 100644 --- a/src/config/etc/sssd.api.d/sssd-ldap.conf +++ b/src/config/etc/sssd.api.d/sssd-ldap.conf @@ -84,6 +84,7 @@ ldap_user_nds_login_expiration_time = str, None, false ldap_user_nds_login_allowed_time_map = str, None, false ldap_user_ssh_public_key = str, None, false ldap_user_auth_type = str, None, false +ldap_user_certificate = str, None, false ldap_group_search_base = str, None, false ldap_group_search_scope = str, None, false ldap_group_search_filter = str, None, false diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 32042c1c45f9179511e3cfe10c6ad85cec347b14..e84483dc6d3b7ace9bbe252c696aaa3893f1bc0e 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -132,6 +132,7 @@ #define SYSDB_SSH_PUBKEY "sshPublicKey" #define SYSDB_AUTH_TYPE "authType" +#define SYSDB_USER_CERT "userCertificate" #define SYSDB_SUBDOMAIN_REALM "realmName" #define SYSDB_SUBDOMAIN_FLAT "flatName" diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml index 1b7a2609ac4ebd0bccfd15a04d041e283bcf9cab..f14090843fd32141ad4f491b69868aa7b2412301 100644 --- a/src/man/sssd-ldap.5.xml +++ b/src/man/sssd-ldap.5.xml @@ -814,6 +814,20 @@ </varlistentry> <varlistentry> + <term>ldap_user_certificate (string)</term> + <listitem> + <para> + Name of the LDAP attribute containing the X509 + certificate of the user. + </para> + <para> + Default: no set in the general case, userCertificate + for IPA + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>ldap_group_object_class (string)</term> <listitem> <para> diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h index 0f03d33839affe1381fd5eb72bfeba6e5b1dcc68..cb4c05d846d9abe5eedb28013ad13fff6476d431 100644 --- a/src/providers/ad/ad_opts.h +++ b/src/providers/ad/ad_opts.h @@ -216,6 +216,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = { { "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL }, { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL }, { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL }, SDAP_ATTR_MAP_TERMINATOR }; diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h index 34e9e167eb46f290d017b5af817571122b359b4f..253c0715355536cc181c57beed5326a77e87e464 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -203,6 +203,7 @@ struct sdap_attr_map ipa_user_map[] = { { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL }, { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL }, { "ldap_user_auth_type", "ipaUserAuthType", SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", "userCertificate", SYSDB_USER_CERT, NULL }, SDAP_ATTR_MAP_TERMINATOR }; diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h index f449ec7c309a5f664941cdefbb3c45a2fab10c99..c1b9bf688ef0a92046195c13a11d2c17b2419d67 100644 --- a/src/providers/ldap/ldap_opts.h +++ b/src/providers/ldap/ldap_opts.h @@ -180,6 +180,7 @@ struct sdap_attr_map rfc2307_user_map[] = { { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL }, { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL }, { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL }, SDAP_ATTR_MAP_TERMINATOR }; @@ -235,6 +236,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = { { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL }, { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL }, { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL }, SDAP_ATTR_MAP_TERMINATOR }; @@ -290,6 +292,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = { { "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL }, { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL }, { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL }, SDAP_ATTR_MAP_TERMINATOR }; diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 6612ab200d7ee34be29512ba8df2744ab2a7ecd8..d9b2d18637bdb3e7823af9d1de2c042c8134780f 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -281,6 +281,7 @@ enum sdap_user_attrs { SDAP_AT_NDS_LOGIN_ALLOWED_TIME_MAP, SDAP_AT_USER_SSH_PUBLIC_KEY, SDAP_AT_USER_AUTH_TYPE, + SDAP_AT_USER_CERT, SDAP_OPTS_USER /* attrs counter */ }; -- 2.1.0
From 3419d0db81e6bb1ed8fd5a14c3ecb6a30a652dbc Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Fri, 8 May 2015 09:02:26 +0200 Subject: [PATCH 3/8] certs: add PEM/DER conversion utilities Related to https://fedorahosted.org/sssd/ticket/2596 --- Makefile.am | 33 ++++ configure.ac | 5 +- src/tests/cmocka/test_cert_utils.c | 361 +++++++++++++++++++++++++++++++++++++ src/util/cert.h | 47 +++++ src/util/cert/cert_common.c | 154 ++++++++++++++++ src/util/cert/libcrypto/cert.c | 168 +++++++++++++++++ 6 files changed, 765 insertions(+), 3 deletions(-) create mode 100644 src/tests/cmocka/test_cert_utils.c create mode 100644 src/util/cert.h create mode 100644 src/util/cert/cert_common.c create mode 100644 src/util/cert/libcrypto/cert.c diff --git a/Makefile.am b/Makefile.am index 67c5bd807e5724b390e93d9e6a4193d3b9bfbeaa..5a6c4b352f7e80c15893a7e588caec32514aca8f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -228,6 +228,7 @@ if HAVE_CMOCKA pam-srv-tests \ test_ipa_subdom_util \ test_ipa_subdom_server \ + test_cert_utils \ $(NULL) if HAVE_LIBRESOLV @@ -498,6 +499,7 @@ endif dist_noinst_HEADERS = \ src/monitor/monitor.h \ src/util/crypto/sss_crypto.h \ + src/util/cert.h \ src/util/dlinklist.h \ src/util/util.h \ src/util/io.h \ @@ -721,6 +723,23 @@ libsss_crypt_la_LIBADD = \ libsss_crypt_la_LDFLAGS = \ -avoid-version +pkglib_LTLIBRARIES += libsss_cert.la + +libsss_cert_la_SOURCES = \ + src/util/cert/cert_common.c \ + src/util/cert/libcrypto/cert.c \ + $(NULL) +libsss_cert_la_CFLAGS = \ + $(CRYPTO_CFLAGS) \ + $(NULL) +libsss_cert_la_LIBADD = \ + $(CRYPTO_LIBS) \ + libsss_crypt.la \ + $(NULL) +libsss_cert_la_LDFLAGS = \ + -avoid-version \ + $(NULL) + pkglib_LTLIBRARIES += libsss_util.la libsss_util_la_SOURCES = \ src/confdb/confdb.c \ @@ -2485,6 +2504,20 @@ test_ipa_subdom_server_LDADD = \ libsss_test_common.la \ $(NULL) +test_cert_utils_SOURCES = \ + src/tests/cmocka/test_cert_utils.c \ + $(NULL) +test_cert_utils_CFLAGS = \ + $(AM_CFLAGS) \ + $(NULL) +test_cert_utils_LDADD = \ + $(CMOCKA_LIBS) \ + $(POPT_LIBS) \ + $(TALLOC_LIBS) \ + libsss_debug.la \ + libsss_test_common.la \ + libsss_cert.la \ + $(NULL) endif # HAVE_CMOCKA noinst_PROGRAMS = pam_test_client diff --git a/configure.ac b/configure.ac index 339dd8b68056e747244a90897c742a31366721a1..29bedf74db6594b5788d51570514a07e082d5e42 100644 --- a/configure.ac +++ b/configure.ac @@ -340,9 +340,8 @@ fi if test x$cryptolib = xnss; then AM_CHECK_NSS fi -if test x$cryptolib = xlibcrypto; then - AM_CHECK_LIBCRYPTO -fi + +AM_CHECK_LIBCRYPTO AM_CHECK_INOTIFY diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..5bcbafb27dbdff596c07b8aad10ca15a35ff4ef5 --- /dev/null +++ b/src/tests/cmocka/test_cert_utils.c @@ -0,0 +1,361 @@ +/* + SSSD + + Certificates - Utilities tests + + Authors: + Sumit Bose <sb...@redhat.com> + + Copyright (C) 2015 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 <http://www.gnu.org/licenses/>. +*/ + +#include <popt.h> +#include <openssl/objects.h> + +#include "util/cert.h" +#include "tests/cmocka/common_mock.h" +#include "util/crypto/nss/nss_util.h" + + +/* TODO: create a certificate for this test */ +const uint8_t test_cert_der[] = { +0x30, 0x82, 0x04, 0x09, 0x30, 0x82, 0x02, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x09, +0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, +0x34, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x49, 0x50, 0x41, 0x2e, +0x44, 0x45, 0x56, 0x45, 0x4c, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, +0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, +0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x32, 0x38, 0x31, +0x30, 0x32, 0x31, 0x31, 0x31, 0x5a, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x34, 0x32, 0x38, 0x31, 0x30, +0x32, 0x31, 0x31, 0x31, 0x5a, 0x30, 0x32, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, +0x0c, 0x09, 0x49, 0x50, 0x41, 0x2e, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, +0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x69, 0x70, 0x61, 0x2d, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x2e, +0x69, 0x70, 0x61, 0x2e, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, +0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb2, 0x32, 0x92, 0xab, 0x47, 0xb8, +0x0c, 0x13, 0x54, 0x4a, 0x1f, 0x1e, 0x29, 0x06, 0xff, 0xd0, 0x50, 0xcb, 0xf7, 0x5f, 0x79, 0x91, +0x65, 0xb1, 0x39, 0x01, 0x83, 0x6a, 0xad, 0x9e, 0x77, 0x3b, 0xf3, 0x0d, 0xd7, 0xb9, 0xf6, 0xdc, +0x9e, 0x4a, 0x49, 0xa7, 0xd0, 0x66, 0x72, 0xcc, 0xbf, 0x77, 0xd6, 0xde, 0xa9, 0xfe, 0x67, 0x96, +0xcc, 0x49, 0xf1, 0x37, 0x23, 0x2e, 0xc4, 0x50, 0xf4, 0xeb, 0xba, 0x62, 0xd4, 0x23, 0x4d, 0xf3, +0x37, 0x38, 0x82, 0xee, 0x3b, 0x3f, 0x2c, 0xd0, 0x80, 0x9b, 0x17, 0xaa, 0x9b, 0xeb, 0xa6, 0xdd, +0xf6, 0x15, 0xff, 0x06, 0xb2, 0xce, 0xff, 0xdf, 0x8a, 0x9e, 0x95, 0x85, 0x49, 0x1f, 0x84, 0xfd, +0x81, 0x26, 0xce, 0x06, 0x32, 0x0d, 0x36, 0xca, 0x7c, 0x15, 0x81, 0x68, 0x6b, 0x8f, 0x3e, 0xb3, +0xa2, 0xfc, 0xae, 0xaf, 0xc2, 0x44, 0x58, 0x15, 0x95, 0x40, 0xfc, 0x56, 0x19, 0x91, 0x80, 0xed, +0x42, 0x11, 0x66, 0x04, 0xef, 0x3c, 0xe0, 0x76, 0x33, 0x4b, 0x83, 0xfa, 0x7e, 0xb4, 0x47, 0xdc, +0xfb, 0xed, 0x46, 0xa5, 0x8d, 0x0a, 0x66, 0x87, 0xa5, 0xef, 0x7b, 0x74, 0x62, 0xac, 0xbe, 0x73, +0x36, 0xc9, 0xb4, 0xfe, 0x20, 0xc4, 0x81, 0xf3, 0xfe, 0x78, 0x19, 0xa8, 0xd0, 0xaf, 0x7f, 0x81, +0x72, 0x24, 0x61, 0xd9, 0x76, 0x93, 0xe3, 0x0b, 0xd2, 0x4f, 0x19, 0x17, 0x33, 0x57, 0xd4, 0x82, +0xb0, 0xf1, 0xa8, 0x03, 0xf6, 0x01, 0x99, 0xa9, 0xb8, 0x8c, 0x83, 0xc9, 0xba, 0x19, 0x87, 0xea, +0xd6, 0x3b, 0x06, 0xeb, 0x4c, 0xf7, 0xf1, 0xe5, 0x28, 0xa9, 0x10, 0xb6, 0x46, 0xde, 0xe1, 0xe1, +0x3f, 0xc1, 0xcc, 0x72, 0xbe, 0x2a, 0x43, 0xc6, 0xf6, 0xd0, 0xb5, 0xa0, 0xc4, 0x24, 0x6e, 0x4f, +0xbd, 0xec, 0x22, 0x8a, 0x07, 0x11, 0x3d, 0xf9, 0xd3, 0x15, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, +0x82, 0x01, 0x26, 0x30, 0x82, 0x01, 0x22, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, +0x30, 0x16, 0x80, 0x14, 0xf2, 0x9d, 0x42, 0x4e, 0x0f, 0xc4, 0x48, 0x25, 0x58, 0x2f, 0x1c, 0xce, +0x0f, 0xa1, 0x3f, 0x22, 0xc8, 0x55, 0xc8, 0x91, 0x30, 0x3b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, +0x05, 0x07, 0x01, 0x01, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, +0x05, 0x07, 0x30, 0x01, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x69, 0x70, 0x61, +0x2d, 0x63, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x2e, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x2f, 0x63, 0x61, +0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, +0x04, 0x03, 0x02, 0x04, 0xf0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, +0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, +0x05, 0x07, 0x03, 0x02, 0x30, 0x74, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x6d, 0x30, 0x6b, 0x30, +0x69, 0xa0, 0x31, 0xa0, 0x2f, 0x86, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x69, 0x70, +0x61, 0x2d, 0x63, 0x61, 0x2e, 0x69, 0x70, 0x61, 0x2e, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x2f, 0x69, +0x70, 0x61, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x43, 0x52, 0x4c, +0x2e, 0x62, 0x69, 0x6e, 0xa2, 0x34, 0xa4, 0x32, 0x30, 0x30, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, +0x55, 0x04, 0x0a, 0x0c, 0x05, 0x69, 0x70, 0x61, 0x63, 0x61, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, +0x55, 0x04, 0x03, 0x0c, 0x15, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, +0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, +0x0e, 0x04, 0x16, 0x04, 0x14, 0x2d, 0x2b, 0x3f, 0xcb, 0xf5, 0xb2, 0xff, 0x32, 0x2c, 0xa8, 0xc2, +0x1c, 0xdd, 0xbd, 0x8c, 0x80, 0x1e, 0xdd, 0x31, 0x82, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, +0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9a, 0x47, 0x2e, +0x50, 0xa7, 0x4d, 0x1d, 0x53, 0x0f, 0xc9, 0x71, 0x42, 0x0c, 0xe5, 0xda, 0x7d, 0x49, 0x64, 0xe7, +0xab, 0xc8, 0xdf, 0xdf, 0x02, 0xc1, 0x87, 0xd1, 0x5b, 0xde, 0xda, 0x6f, 0x2b, 0xe4, 0xf0, 0xbe, +0xba, 0x09, 0xdf, 0x02, 0x85, 0x0b, 0x8a, 0xe6, 0x9b, 0x06, 0x7d, 0x69, 0x38, 0x6c, 0x72, 0xff, +0x4c, 0x7b, 0x2a, 0x0d, 0x3f, 0x23, 0x2f, 0x16, 0x46, 0xff, 0x05, 0x93, 0xb0, 0xea, 0x24, 0x28, +0xd7, 0x12, 0xa1, 0x57, 0xb8, 0x59, 0x19, 0x25, 0xf3, 0x43, 0x0a, 0xd3, 0xfd, 0x0f, 0x37, 0x8d, +0xb8, 0xca, 0x15, 0xe7, 0x48, 0x8a, 0xa0, 0xc7, 0xc7, 0x4b, 0x7f, 0x01, 0x3c, 0x58, 0xd7, 0x37, +0xe5, 0xff, 0x7d, 0x2b, 0x01, 0xac, 0x0d, 0x9f, 0x51, 0x6a, 0xe5, 0x40, 0x24, 0xe6, 0x5e, 0x55, +0x0d, 0xf7, 0xb8, 0x2f, 0x42, 0xac, 0x6d, 0xe5, 0x29, 0x6b, 0xc6, 0x0b, 0xa4, 0xbf, 0x19, 0xbd, +0x39, 0x27, 0xee, 0xfe, 0xc5, 0xb3, 0xdb, 0x62, 0xd4, 0xbe, 0xd2, 0x47, 0xba, 0x96, 0x30, 0x5a, +0xfd, 0x62, 0x00, 0xb8, 0x27, 0x5d, 0x2f, 0x3a, 0x94, 0x0b, 0x95, 0x35, 0x85, 0x40, 0x2c, 0xbc, +0x67, 0xdf, 0x8a, 0xf9, 0xf1, 0x7b, 0x19, 0x96, 0x3e, 0x42, 0x48, 0x13, 0x23, 0x04, 0x95, 0xa9, +0x6b, 0x11, 0x33, 0x81, 0x47, 0x5a, 0x83, 0x72, 0xf6, 0x20, 0xfa, 0x8e, 0x41, 0x7b, 0x8f, 0x77, +0x47, 0x7c, 0xc7, 0x5d, 0x46, 0xf4, 0x4f, 0xfd, 0x81, 0x0a, 0xae, 0x39, 0x27, 0xb6, 0x6a, 0x26, +0x63, 0xb1, 0xd3, 0xbf, 0x55, 0x83, 0x82, 0x9b, 0x36, 0x6c, 0x33, 0x64, 0x0f, 0x50, 0xc0, 0x55, +0x94, 0x13, 0xc3, 0x85, 0xf4, 0xd5, 0x71, 0x65, 0xd0, 0xc0, 0xdd, 0xfc, 0xe6, 0xec, 0x9c, 0x5b, +0xf0, 0x11, 0xb5, 0x2c, 0xf3, 0x48, 0xc1, 0x36, 0x8c, 0xa2, 0x96, 0x48, 0x84}; + +#define TEST_CERT_PEM "-----BEGIN CERTIFICATE-----\n" \ +"MIIECTCCAvGgAwIBAgIBCTANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu\n" \ +"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA0Mjgx\n" \ +"MDIxMTFaFw0xNzA0MjgxMDIxMTFaMDIxEjAQBgNVBAoMCUlQQS5ERVZFTDEcMBoG\n" \ +"A1UEAwwTaXBhLWRldmVsLmlwYS5kZXZlbDCCASIwDQYJKoZIhvcNAQEBBQADggEP\n" \ +"ADCCAQoCggEBALIykqtHuAwTVEofHikG/9BQy/dfeZFlsTkBg2qtnnc78w3Xufbc\n" \ +"nkpJp9Bmcsy/d9beqf5nlsxJ8TcjLsRQ9Ou6YtQjTfM3OILuOz8s0ICbF6qb66bd\n" \ +"9hX/BrLO/9+KnpWFSR+E/YEmzgYyDTbKfBWBaGuPPrOi/K6vwkRYFZVA/FYZkYDt\n" \ +"QhFmBO884HYzS4P6frRH3PvtRqWNCmaHpe97dGKsvnM2ybT+IMSB8/54GajQr3+B\n" \ +"ciRh2XaT4wvSTxkXM1fUgrDxqAP2AZmpuIyDyboZh+rWOwbrTPfx5SipELZG3uHh\n" \ +"P8HMcr4qQ8b20LWgxCRuT73sIooHET350xUCAwEAAaOCASYwggEiMB8GA1UdIwQY\n" \ +"MBaAFPKdQk4PxEglWC8czg+hPyLIVciRMDsGCCsGAQUFBwEBBC8wLTArBggrBgEF\n" \ +"BQcwAYYfaHR0cDovL2lwYS1jYS5pcGEuZGV2ZWwvY2Evb2NzcDAOBgNVHQ8BAf8E\n" \ +"BAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHQGA1UdHwRtMGsw\n" \ +"aaAxoC+GLWh0dHA6Ly9pcGEtY2EuaXBhLmRldmVsL2lwYS9jcmwvTWFzdGVyQ1JM\n" \ +"LmJpbqI0pDIwMDEOMAwGA1UECgwFaXBhY2ExHjAcBgNVBAMMFUNlcnRpZmljYXRl\n" \ +"IEF1dGhvcml0eTAdBgNVHQ4EFgQULSs/y/Wy/zIsqMIc3b2MgB7dMYIwDQYJKoZI\n" \ +"hvcNAQELBQADggEBAJpHLlCnTR1TD8lxQgzl2n1JZOeryN/fAsGH0Vve2m8r5PC+\n" \ +"ugnfAoULiuabBn1pOGxy/0x7Kg0/Iy8WRv8Fk7DqJCjXEqFXuFkZJfNDCtP9DzeN\n" \ +"uMoV50iKoMfHS38BPFjXN+X/fSsBrA2fUWrlQCTmXlUN97gvQqxt5Slrxgukvxm9\n" \ +"OSfu/sWz22LUvtJHupYwWv1iALgnXS86lAuVNYVALLxn34r58XsZlj5CSBMjBJWp\n" \ +"axEzgUdag3L2IPqOQXuPd0d8x11G9E/9gQquOSe2aiZjsdO/VYOCmzZsM2QPUMBV\n" \ +"lBPDhfTVcWXQwN385uycW/ARtSzzSME2jKKWSIQ=\n" \ +"-----END CERTIFICATE-----\n" + +#define TEST_CERT_DERB64 \ +"MIIECTCCAvGgAwIBAgIBCTANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \ +"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA0Mjgx" \ +"MDIxMTFaFw0xNzA0MjgxMDIxMTFaMDIxEjAQBgNVBAoMCUlQQS5ERVZFTDEcMBoG" \ +"A1UEAwwTaXBhLWRldmVsLmlwYS5kZXZlbDCCASIwDQYJKoZIhvcNAQEBBQADggEP" \ +"ADCCAQoCggEBALIykqtHuAwTVEofHikG/9BQy/dfeZFlsTkBg2qtnnc78w3Xufbc" \ +"nkpJp9Bmcsy/d9beqf5nlsxJ8TcjLsRQ9Ou6YtQjTfM3OILuOz8s0ICbF6qb66bd" \ +"9hX/BrLO/9+KnpWFSR+E/YEmzgYyDTbKfBWBaGuPPrOi/K6vwkRYFZVA/FYZkYDt" \ +"QhFmBO884HYzS4P6frRH3PvtRqWNCmaHpe97dGKsvnM2ybT+IMSB8/54GajQr3+B" \ +"ciRh2XaT4wvSTxkXM1fUgrDxqAP2AZmpuIyDyboZh+rWOwbrTPfx5SipELZG3uHh" \ +"P8HMcr4qQ8b20LWgxCRuT73sIooHET350xUCAwEAAaOCASYwggEiMB8GA1UdIwQY" \ +"MBaAFPKdQk4PxEglWC8czg+hPyLIVciRMDsGCCsGAQUFBwEBBC8wLTArBggrBgEF" \ +"BQcwAYYfaHR0cDovL2lwYS1jYS5pcGEuZGV2ZWwvY2Evb2NzcDAOBgNVHQ8BAf8E" \ +"BAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHQGA1UdHwRtMGsw" \ +"aaAxoC+GLWh0dHA6Ly9pcGEtY2EuaXBhLmRldmVsL2lwYS9jcmwvTWFzdGVyQ1JM" \ +"LmJpbqI0pDIwMDEOMAwGA1UECgwFaXBhY2ExHjAcBgNVBAMMFUNlcnRpZmljYXRl" \ +"IEF1dGhvcml0eTAdBgNVHQ4EFgQULSs/y/Wy/zIsqMIc3b2MgB7dMYIwDQYJKoZI" \ +"hvcNAQELBQADggEBAJpHLlCnTR1TD8lxQgzl2n1JZOeryN/fAsGH0Vve2m8r5PC+" \ +"ugnfAoULiuabBn1pOGxy/0x7Kg0/Iy8WRv8Fk7DqJCjXEqFXuFkZJfNDCtP9DzeN" \ +"uMoV50iKoMfHS38BPFjXN+X/fSsBrA2fUWrlQCTmXlUN97gvQqxt5Slrxgukvxm9" \ +"OSfu/sWz22LUvtJHupYwWv1iALgnXS86lAuVNYVALLxn34r58XsZlj5CSBMjBJWp" \ +"axEzgUdag3L2IPqOQXuPd0d8x11G9E/9gQquOSe2aiZjsdO/VYOCmzZsM2QPUMBV" \ +"lBPDhfTVcWXQwN385uycW/ARtSzzSME2jKKWSIQ=" + +struct test_state { + void *dummy; +}; + +static int setup(void **state) +{ + struct test_state *ts = NULL; + + assert_true(leak_check_setup()); + + ts = talloc(global_talloc_context, struct test_state); + assert_non_null(ts); + + check_leaks_push(ts); + *state = (void *)ts; + return 0; +} + +static int teardown(void **state) +{ + struct test_state *ts = talloc_get_type_abort(*state, struct test_state); + + assert_non_null(ts); + + assert_true(check_leaks_pop(ts)); + talloc_free(ts); + assert_true(leak_check_teardown()); + return 0; +} + +void test_sss_cert_der_to_pem(void **state) +{ + int ret; + char *pem_str; + size_t pem_size; + struct test_state *ts = talloc_get_type_abort(*state, struct test_state); + assert_non_null(ts); + + ret = sss_cert_der_to_pem(NULL, NULL, 0, NULL, NULL); + assert_int_equal(ret, EINVAL); + + ret = sss_cert_der_to_pem(ts, test_cert_der, sizeof(test_cert_der), + &pem_str, &pem_size); + assert_int_equal(ret, EOK); + assert_int_equal(sizeof(TEST_CERT_PEM) - 1, pem_size); + assert_string_equal(pem_str, TEST_CERT_PEM); + + talloc_free(pem_str); +} + +void test_sss_cert_pem_to_der(void **state) +{ + int ret; + uint8_t *der; + size_t der_size; + struct test_state *ts = talloc_get_type_abort(*state, struct test_state); + assert_non_null(ts); + + ret = sss_cert_pem_to_der(NULL, NULL, NULL, NULL); + assert_int_equal(ret, EINVAL); + + ret = sss_cert_pem_to_der(ts, TEST_CERT_PEM, &der, &der_size); + assert_int_equal(ret, EOK); + assert_int_equal(sizeof(test_cert_der), der_size); + assert_memory_equal(der, test_cert_der, der_size); + + talloc_free(der); +} + +void test_sss_cert_derb64_to_pem(void **state) +{ + int ret; + char *pem_str; + size_t pem_size; + struct test_state *ts = talloc_get_type_abort(*state, struct test_state); + assert_non_null(ts); + + ret = sss_cert_derb64_to_pem(NULL, NULL, NULL, NULL); + assert_int_equal(ret, EINVAL); + + ret = sss_cert_derb64_to_pem(ts, TEST_CERT_DERB64, &pem_str, &pem_size); + assert_int_equal(ret, EOK); + assert_int_equal(sizeof(TEST_CERT_PEM) - 1, pem_size); + assert_string_equal(pem_str, TEST_CERT_PEM); + + talloc_free(pem_str); +} + +void test_sss_cert_pem_to_derb64(void **state) +{ + int ret; + char *derb64; + struct test_state *ts = talloc_get_type_abort(*state, struct test_state); + assert_non_null(ts); + + ret = sss_cert_pem_to_derb64(NULL, NULL, NULL); + assert_int_equal(ret, EINVAL); + + ret = sss_cert_pem_to_derb64(ts, TEST_CERT_PEM, &derb64); + assert_int_equal(ret, EOK); + assert_string_equal(derb64, TEST_CERT_DERB64); + + talloc_free(derb64); +} + +void test_bin_to_ldap_filter_value(void **state) +{ + int ret; + size_t c; + char *str; + struct test_state *ts = talloc_get_type_abort(*state, struct test_state); + assert_non_null(ts); + + struct test_data { + uint8_t blob[5]; + const char *str; + } test_data[] = { + {{0x01, 0x02, 0x03, 0x04, 0x05}, "\\01\\02\\03\\04\\05"}, + {{0x00, 0x00, 0x00, 0x00, 0x00}, "\\00\\00\\00\\00\\00"}, + {{0xff, 0xff, 0xff, 0xff, 0xff}, "\\ff\\ff\\ff\\ff\\ff"}, + {{0xca, 0xfe, 0xc0, 0xff, 0xee}, "\\ca\\fe\\c0\\ff\\ee"}, + {{0}, NULL} + }; + + ret = bin_to_ldap_filter_value(ts, NULL, 0, NULL); + assert_int_equal(ret, EINVAL); + + for (c = 0; test_data[c].str != NULL; c++) { + ret = bin_to_ldap_filter_value(ts, test_data[c].blob, 5, &str); + assert_int_equal(ret, EOK); + assert_string_equal(str, test_data[c].str); + + talloc_free(str); + } + +} + +void test_sss_cert_derb64_to_ldap_filter(void **state) +{ + int ret; + char *filter; + + struct test_state *ts = talloc_get_type_abort(*state, struct test_state); + assert_non_null(ts); + + ret = sss_cert_derb64_to_ldap_filter(ts, NULL, NULL, NULL); + assert_int_equal(ret, EINVAL); + + ret = sss_cert_derb64_to_ldap_filter(ts, "AAECAwQFBgcICQ==", "attrName", + &filter); + assert_int_equal(ret, EOK); + assert_string_equal(filter, + "(attrName=\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09)"); + + talloc_free(filter); +} + +int main(int argc, const char *argv[]) +{ + poptContext pc; + int opt; + int ret; + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_DEBUG_OPTS + POPT_TABLEEND + }; + + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_sss_cert_der_to_pem, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_cert_pem_to_der, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_cert_derb64_to_pem, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_cert_pem_to_derb64, + setup, teardown), + cmocka_unit_test_setup_teardown(test_bin_to_ldap_filter_value, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_cert_derb64_to_ldap_filter, + setup, teardown), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ + debug_level = SSSDBG_INVALID; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + + DEBUG_CLI_INIT(debug_level); + + ret = cmocka_run_group_tests(tests, NULL, NULL); + + CRYPTO_cleanup_all_ex_data(); /* to make valgrind happy */ + +#ifdef HAVE_NSS + /* Cleanup NSS and NSPR to make valgrind happy. */ + nspr_nss_cleanup(); +#endif + + + return ret; +} diff --git a/src/util/cert.h b/src/util/cert.h new file mode 100644 index 0000000000000000000000000000000000000000..79ea1a4ab58149a312bece265798ab3a3f459114 --- /dev/null +++ b/src/util/cert.h @@ -0,0 +1,47 @@ +/* + SSSD - certificate handling utils - openssl version + + Copyright (C) Sumit Bose <sb...@redhat.com> 2015 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <talloc.h> + +#include "util/util.h" + +#ifndef __CERT_H__ +#define __CERT_H__ + +errno_t sss_cert_der_to_pem(TALLOC_CTX *mem_ctx, const uint8_t *der_blob, + size_t der_size, char **pem, size_t *pem_size); + +errno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem, + uint8_t **der_blob, size_t *der_size); + +errno_t sss_cert_derb64_to_pem(TALLOC_CTX *mem_ctx, const char *derb64, + char **pem, size_t *pem_size); + +errno_t sss_cert_pem_to_derb64(TALLOC_CTX *mem_ctx, const char *pem, + char **derb64); + +errno_t sss_cert_derb64_to_ldap_filter(TALLOC_CTX *mem_ctx, const char *derb64, + const char *attr_name, + char **ldap_filter); + +errno_t bin_to_ldap_filter_value(TALLOC_CTX *mem_ctx, + const uint8_t *blob, size_t blob_size, + char **_str); +#endif /* __CERT_H__ */ diff --git a/src/util/cert/cert_common.c b/src/util/cert/cert_common.c new file mode 100644 index 0000000000000000000000000000000000000000..a29696ed3cd9f2168f47323fac97d44e9b49f921 --- /dev/null +++ b/src/util/cert/cert_common.c @@ -0,0 +1,154 @@ +/* + SSSD - certificate handling utils + + Copyright (C) Sumit Bose <sb...@redhat.com> 2015 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include "util/util.h" +#include "util/cert.h" +#include "util/crypto/sss_crypto.h" + +errno_t sss_cert_derb64_to_pem(TALLOC_CTX *mem_ctx, const char *derb64, + char **pem, size_t *pem_size) +{ + int ret; + unsigned char *der; + size_t der_size; + + if (derb64 == NULL) { + return EINVAL; + } + + der = sss_base64_decode(mem_ctx, derb64, &der_size); + if (der == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n"); + return EINVAL; + } + + ret = sss_cert_der_to_pem(mem_ctx, der, der_size, pem, pem_size); + talloc_free(der); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_cert_der_to_pem failed.\n"); + } + + return ret; +} + +errno_t sss_cert_pem_to_derb64(TALLOC_CTX *mem_ctx, const char *pem, + char **derb64) +{ + int ret; + uint8_t *der; + size_t der_size; + + ret = sss_cert_pem_to_der(mem_ctx, pem, &der, &der_size); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_cert_pem_to_der failed.\n"); + return ret; + } + + *derb64 = sss_base64_encode(mem_ctx, der, der_size); + talloc_free(der); + if (*derb64 == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sss_base64_encode failed.\n"); + return EINVAL; + } + + return EOK; +} + +errno_t sss_cert_derb64_to_ldap_filter(TALLOC_CTX *mem_ctx, const char *derb64, + const char *attr_name, + char **ldap_filter) +{ + int ret; + unsigned char *der; + size_t der_size; + char *val; + + if (derb64 == NULL || attr_name == NULL) { + return EINVAL; + } + + der = sss_base64_decode(mem_ctx, derb64, &der_size); + if (der == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n"); + return EINVAL; + } + + ret = bin_to_ldap_filter_value(mem_ctx, der, der_size, &val); + talloc_free(der); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "bin_to_ldap_filter_value failed.\n"); + return ret; + } + + *ldap_filter = talloc_asprintf(mem_ctx, "(%s=%s)", attr_name, val); + talloc_free(val); + if (*ldap_filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + return ENOMEM; + } + + return EOK; +} + +errno_t bin_to_ldap_filter_value(TALLOC_CTX *mem_ctx, + const uint8_t *blob, size_t blob_size, + char **_str) +{ + int ret; + size_t c; + size_t len; + char *str = NULL; + char *p; + + if (blob == NULL || blob_size == 0 || _str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Missing input parameter.\n"); + return EINVAL; + } + + len = (blob_size * 3) + 1; + str = talloc_size(mem_ctx, len); + if (str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n"); + return ENOMEM; + } + str[len - 1] = '\0'; + + p = str; + for (c = 0; c < blob_size; c++) { + ret = snprintf(p, 4, "\\%02x", blob[c]); + if (ret != 3) { + DEBUG(SSSDBG_OP_FAILURE, "snprintf failed.\n"); + ret = EIO; + goto done; + } + + p += 3; + } + + ret = EOK; + +done: + if (ret == EOK) { + *_str = str; + } else { + talloc_free(str); + } + + return ret; +} diff --git a/src/util/cert/libcrypto/cert.c b/src/util/cert/libcrypto/cert.c new file mode 100644 index 0000000000000000000000000000000000000000..1a250f60d1a7dfd5c883ec7e9b1f9491fb74c9b0 --- /dev/null +++ b/src/util/cert/libcrypto/cert.c @@ -0,0 +1,168 @@ +/* + SSSD - certificate handling utils - openssl version + + Copyright (C) Sumit Bose <sb...@redhat.com> 2015 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <openssl/x509.h> +#include <openssl/bio.h> +#include <openssl/pem.h> + +#include "util/util.h" + +errno_t sss_cert_der_to_pem(TALLOC_CTX *mem_ctx, const uint8_t *der_blob, + size_t der_size, char **pem, size_t *pem_size) +{ + X509 *x509 = NULL; + BIO *bio_mem = NULL; + const unsigned char *d; + int ret; + long p_size; + char *p; + + if (der_blob == NULL || der_size == 0) { + return EINVAL; + } + + d = (const unsigned char *) der_blob; + + x509 = d2i_X509(NULL, &d, (int) der_size); + if (x509 == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "d2i_X509 failed.\n"); + return EINVAL; + } + + bio_mem = BIO_new(BIO_s_mem()); + if (bio_mem == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "BIO_new failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = PEM_write_bio_X509(bio_mem, x509); + if (ret != 1) { + DEBUG(SSSDBG_OP_FAILURE, "PEM_write_bio_X509 failed.\n"); + ret = EIO; + goto done; + } + + p_size = BIO_get_mem_data(bio_mem, &p); + if (p_size == 0) { + DEBUG(SSSDBG_OP_FAILURE, "Unexpected PEM size [%ld].\n", p_size); + ret = EINVAL; + goto done; + } + + if (pem != NULL) { + *pem = talloc_strndup(mem_ctx, p, p_size); + if (*pem == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_memdup failed.\n"); + ret = ENOMEM; + goto done; + } + } + + if (pem_size != NULL) { + *pem_size = p_size; + } + + ret = EOK; + +done: + X509_free(x509); + BIO_free_all(bio_mem); + + return ret; +} + +errno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem, + uint8_t **_der_blob, size_t *_der_size) +{ + X509 *x509 = NULL; + BIO *bio_mem = NULL; + int ret; + unsigned char *buf; + int buf_size; + uint8_t *der_blob; + size_t der_size; + + if (pem == NULL) { + return EINVAL; + } + + bio_mem = BIO_new(BIO_s_mem()); + if (bio_mem == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "BIO_new failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = BIO_puts(bio_mem, pem); + if (ret <= 0) { + DEBUG(SSSDBG_OP_FAILURE, "BIO_puts failed.\n"); + ret = EIO; + goto done; + } + + x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL); + if (x509 == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "PEM_read_bio_X509 failed.\n"); + ret = EIO; + goto done; + } + + buf_size = i2d_X509(x509, NULL); + if (buf_size <= 0) { + DEBUG(SSSDBG_OP_FAILURE, "i2d_X509 failed.\n"); + ret = EIO; + goto done; + } + + if (_der_blob != NULL) { + buf = talloc_size(mem_ctx, buf_size); + if (buf == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n"); + ret = ENOMEM; + goto done; + } + + der_blob = buf; + + der_size = i2d_X509(x509, &buf); + if (der_size != buf_size) { + talloc_free(der_blob); + DEBUG(SSSDBG_CRIT_FAILURE, + "i2d_X509 size mismatch between two calls.\n"); + ret = EIO; + goto done; + } + + *_der_blob = der_blob; + } + + if (_der_size != NULL) { + *_der_size = buf_size; + } + + ret = EOK; + +done: + X509_free(x509); + BIO_free_all(bio_mem); + + return ret; + +} -- 2.1.0
From beffc1c892d7b722fcaa509546850a14fa42c292 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Wed, 27 May 2015 11:22:20 +0200 Subject: [PATCH 4/8] sysdb: add sysdb_search_user_by_cert() and sysdb_search_object_by_cert() Related to https://fedorahosted.org/sssd/ticket/2596 --- Makefile.am | 1 + src/db/sysdb.h | 14 ++++++++++++ src/db/sysdb_ops.c | 35 ++++++++++++++++++++++++++++++ src/tests/cwrap/Makefile.am | 2 ++ src/tests/sysdb-tests.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+) diff --git a/Makefile.am b/Makefile.am index 5a6c4b352f7e80c15893a7e588caec32514aca8f..eecbf95ab4492465e68dd9ef09601e230bde2c3f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -809,6 +809,7 @@ libsss_util_la_LIBADD = \ libsss_debug.la \ libsss_child.la \ libsss_crypt.la \ + libsss_cert.la \ $(NULL) if BUILD_SUDO libsss_util_la_SOURCES += src/db/sysdb_sudo.c diff --git a/src/db/sysdb.h b/src/db/sysdb.h index e84483dc6d3b7ace9bbe252c696aaa3893f1bc0e..d468b6c6b86ca8f4f39160242a22bd2d33d70e14 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -194,6 +194,7 @@ #define SYSDB_SID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_SID_STR"=%s))" #define SYSDB_UUID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_UUID"=%s))" +#define SYSDB_USER_CERT_FILTER "(&("SYSDB_UC")%s)" #define SYSDB_HAS_ENUMERATED "has_enumerated" @@ -1064,6 +1065,19 @@ errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx, const char **attrs, struct ldb_result **res); +errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *cert, + const char **attrs, + struct ldb_result **res); + +errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *cert, + struct ldb_result **res); + + + /* === Functions related to GPOs === */ #define SYSDB_GPO_CONTAINER "cn=gpos,cn=ad,cn=custom" diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c index b86cf490e84ab35562f14333fff6f0cd21890e41..437c67b512dd2bf711444d55cf61922325671717 100644 --- a/src/db/sysdb_ops.c +++ b/src/db/sysdb_ops.c @@ -24,6 +24,7 @@ #include "db/sysdb_services.h" #include "db/sysdb_autofs.h" #include "util/crypto/sss_crypto.h" +#include "util/cert.h" #include <time.h> int add_string(struct ldb_message *msg, int flags, @@ -3713,6 +3714,40 @@ errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx, uuid_str, attrs, res); } +errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *cert, + const char **attrs, + struct ldb_result **res) +{ + int ret; + char *user_filter; + + ret = sss_cert_derb64_to_ldap_filter(mem_ctx, cert, SYSDB_USER_CERT, + &user_filter); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_cert_derb64_to_ldap_filter failed.\n"); + return ret; + } + + ret = sysdb_search_object_by_str_attr(mem_ctx, domain, + SYSDB_USER_CERT_FILTER, + user_filter, attrs, res); + talloc_free(user_filter); + + return ret; +} + +errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *cert, + struct ldb_result **res) +{ + const char *user_attrs[] = SYSDB_PW_ATTRS; + + return sysdb_search_object_by_cert(mem_ctx, domain, cert, user_attrs, res); +} + errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, const char *group_name, diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am index b805e834977f60d6ba2efdf0f700061bb5e0e264..dc92192928a55abb247096ef310251098d16038f 100644 --- a/src/tests/cwrap/Makefile.am +++ b/src/tests/cwrap/Makefile.am @@ -109,6 +109,7 @@ server_tests_LDADD = \ $(abs_top_builddir)/libsss_debug.la \ $(abs_top_builddir)/libsss_crypt.la \ $(abs_top_builddir)/libsss_test_common.la \ + $(abs_top_builddir)/libsss_cert.la \ $(NULL) usertools_tests_SOURCES = \ @@ -143,6 +144,7 @@ usertools_tests_LDADD = \ $(abs_top_builddir)/libsss_debug.la \ $(abs_top_builddir)/libsss_crypt.la \ $(abs_top_builddir)/libsss_test_common.la \ + $(abs_top_builddir)/libsss_cert.la \ $(NULL) responder_common_tests_SOURCES =\ diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c index 4478e24a61ad7ae2b593a621bfb9611be0883881..6dd299bfbb3d254788e858c8b5025b3b4dd80304 100644 --- a/src/tests/sysdb-tests.c +++ b/src/tests/sysdb-tests.c @@ -5201,6 +5201,56 @@ START_TEST(test_sysdb_search_object_by_uuid) } END_TEST +/* For simple searches the content of the certificate does not matter */ +#define TEST_USER_CERT_DERB64 "gJznJT7L0aETU5CMk+n+1Q==" +START_TEST(test_sysdb_search_user_by_cert) +{ + errno_t ret; + struct sysdb_test_ctx *test_ctx; + struct ldb_result *res; + struct sysdb_attrs *attrs = NULL; + struct ldb_val val; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + fail_if(ret != EOK, "Could not set up the test"); + + val.data = sss_base64_decode(test_ctx, TEST_USER_CERT_DERB64, &val.length); + fail_unless(val.data != NULL, "sss_base64_decode failed."); + + attrs = sysdb_new_attrs(test_ctx); + fail_unless(attrs != NULL, "sysdb_new_attrs failed"); + + ret = sysdb_attrs_add_val(attrs, SYSDB_USER_CERT, &val); + fail_unless(ret == EOK, "sysdb_attrs_add_val failed with [%d][%s].", + ret, strerror(ret)); + + ret = sysdb_add_user(test_ctx->domain, "certuser", + 234567, 0, "cert user", "/home/certuser", "/bin/bash", + NULL, attrs, 0, 0); + fail_unless(ret == EOK, "sysdb_add_user failed with [%d][%s].", + ret, strerror(ret)); + + ret = sysdb_search_user_by_cert(test_ctx, test_ctx->domain, "ABC", &res); + fail_unless(ret == ENOENT, + "Unexpected return code from sysdb_search_user_by_cert for " + "missing object, expected [%d], got [%d].", ENOENT, ret); + + ret = sysdb_search_user_by_cert(test_ctx, test_ctx->domain, + TEST_USER_CERT_DERB64, &res); + fail_unless(ret == EOK, "sysdb_search_user_by_cert failed with [%d][%s].", + ret, strerror(ret)); + fail_unless(res->count == 1, "Unexpected number of results, " \ + "expected [%u], get [%u].", 1, res->count); + fail_unless(strcmp(ldb_msg_find_attr_as_string(res->msgs[0], + SYSDB_NAME, ""), + "certuser") == 0, "Unexpected object found, " \ + "expected [%s], got [%s].", "certuser", + ldb_msg_find_attr_as_string(res->msgs[0],SYSDB_NAME, "")); + talloc_free(test_ctx); +} +END_TEST + START_TEST(test_sysdb_delete_by_sid) { errno_t ret; @@ -6318,6 +6368,9 @@ Suite *create_sysdb_suite(void) /* Test UUID string searches */ tcase_add_test(tc_sysdb, test_sysdb_search_object_by_uuid); + /* Test user by certificate searches */ + tcase_add_test(tc_sysdb, test_sysdb_search_user_by_cert); + /* Test canonicalizing names */ tcase_add_test(tc_sysdb, test_sysdb_get_real_name); -- 2.1.0
From 940be5f7639dd81008abdf86f6b78389f8c39b7b Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Wed, 27 May 2015 18:23:49 +0200 Subject: [PATCH 5/8] LDAP/IPA: add user lookup by certificate Related to https://fedorahosted.org/sssd/ticket/2596 --- src/providers/data_provider.h | 6 +++- src/providers/data_provider_be.c | 5 ++++ src/providers/ipa/ipa_subdomains_id.c | 14 +++++++++ src/providers/ldap/ldap_id.c | 55 +++++++++++++++++++++++++++++++---- 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index 657d2b798cf28fa59c9f644e343f2a2482609bad..13a700308e9c9d1a80c0310dbb1c17de33607498 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -128,6 +128,7 @@ #define BE_FILTER_ENUM 3 #define BE_FILTER_SECID 4 #define BE_FILTER_UUID 5 +#define BE_FILTER_CERT 6 #define BE_REQ_USER 0x0001 #define BE_REQ_GROUP 0x0002 @@ -140,14 +141,17 @@ #define BE_REQ_HOST 0x0010 #define BE_REQ_BY_SECID 0x0011 #define BE_REQ_USER_AND_GROUP 0x0012 -#define BE_REQ_BY_UUID 0x0013 +#define BE_REQ_BY_UUID 0x0013 +#define BE_REQ_BY_CERT 0x0014 #define BE_REQ_TYPE_MASK 0x00FF #define BE_REQ_FAST 0x1000 #define DP_SEC_ID "secid" +#define DP_CERT "cert" /* sizeof() counts the trailing \0 so we must substract 1 for the string * length */ #define DP_SEC_ID_LEN (sizeof(DP_SEC_ID) - 1) +#define DP_CERT_LEN (sizeof(DP_CERT) - 1) #define EXTRA_NAME_IS_UPN "U" #define EXTRA_INPUT_MAYBE_WITH_VIEW "V" diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c index 34c7b2c766ee4072ee980ad43f1e1d33ee7c8a5a..f5bdfb676011975defa4c5a734d420c8694f3bdd 100644 --- a/src/providers/data_provider_be.c +++ b/src/providers/data_provider_be.c @@ -1199,6 +1199,11 @@ static int be_get_account_info(struct sbus_request *dbus_req, void *user_data) ret = split_name_extended(req, &filter[DP_SEC_ID_LEN + 1], &req->filter_value, &req->extra_value); + } else if (strncmp(filter, DP_CERT"=", DP_CERT_LEN + 1) == 0) { + req->filter_type = BE_FILTER_CERT; + ret = split_name_extended(req, &filter[DP_CERT_LEN + 1], + &req->filter_value, + &req->extra_value); } else if (strcmp(filter, ENUM_INDICATOR) == 0) { req->filter_type = BE_FILTER_ENUM; req->filter_value = NULL; diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index b5c0aa0b531619d34309e12e4cd8084f7beee88a..610b1c58b3b180201cfb5b22f870f8937673e02e 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -934,6 +934,20 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx, ret = EOK; goto done; + } else if (ar->filter_type == BE_FILTER_CERT) { + ret = sysdb_search_object_by_cert(mem_ctx, dom, ar->filter_value, attrs, + &res); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to make request to our cache: [%d]: [%s]\n", + ret, sss_strerror(ret)); + goto done; + } + + *_msg = res->msgs[0]; + + ret = EOK; + goto done; } else if (ar->filter_type == BE_FILTER_IDNUM) { errno = 0; id = strtouint32(ar->filter_value, NULL, 10); diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index d4f46f1dcd69898e5883d21be07f895fd198cf50..ff117d82957b3b23d9cedc5e513255804103f916 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -28,6 +28,7 @@ #include "util/util.h" #include "util/strtonum.h" +#include "util/cert.h" #include "db/sysdb.h" #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async.h" @@ -78,12 +79,13 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, struct tevent_req *req; struct users_get_state *state; const char *attr_name = NULL; - char *clean_name; + char *clean_name = NULL; char *endptr; int ret; uid_t uid; enum idmap_error_code err; char *sid; + char *user_filter = NULL; req = tevent_req_create(memctx, &state, struct users_get_state); if (!req) return NULL; @@ -194,6 +196,23 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, goto done; } break; + case BE_FILTER_CERT: + attr_name = ctx->opts->user_map[SDAP_AT_USER_CERT].name; + if (attr_name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Certificate search not configured for this backend.\n"); + ret = EINVAL; + goto done; + } + + ret = sss_cert_derb64_to_ldap_filter(state, name, attr_name, + &user_filter); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sss_cert_derb64_to_ldap_filter failed.\n"); + goto done; + } + break; default: ret = EINVAL; goto done; @@ -205,29 +224,39 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, goto done; } + if (user_filter == NULL) { + user_filter = talloc_asprintf(state, "(%s=%s)", attr_name, clean_name); + talloc_free(clean_name); + if (user_filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + ret = ENOMEM; + goto done; + } + } + if (state->use_id_mapping || filter_type == BE_FILTER_SECID) { /* When mapping IDs or looking for SIDs, we don't want to limit * ourselves to users with a UID value. But there must be a SID to map * from. */ state->filter = talloc_asprintf(state, - "(&(%s=%s)(objectclass=%s)(%s=*)(%s=*))", - attr_name, clean_name, + "(&%s(objectclass=%s)(%s=*)(%s=*))", + user_filter, ctx->opts->user_map[SDAP_OC_USER].name, ctx->opts->user_map[SDAP_AT_USER_NAME].name, ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name); } else { /* When not ID-mapping, make sure there is a non-NULL UID */ state->filter = talloc_asprintf(state, - "(&(%s=%s)(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))", - attr_name, clean_name, + "(&%s(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))", + user_filter, ctx->opts->user_map[SDAP_OC_USER].name, ctx->opts->user_map[SDAP_AT_USER_NAME].name, ctx->opts->user_map[SDAP_AT_USER_UID].name, ctx->opts->user_map[SDAP_AT_USER_UID].name); } - talloc_zfree(clean_name); + talloc_zfree(user_filter); if (!state->filter) { DEBUG(SSSDBG_OP_FAILURE, "Failed to build the base filter\n"); ret = ENOMEM; @@ -1537,6 +1566,16 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, noexist_delete); break; + case BE_REQ_BY_CERT: + subreq = users_get_send(state, be_ctx->ev, id_ctx, + sdom, conn, + ar->filter_value, + ar->filter_type, + ar->extra_value, + ar->attr_type, + noexist_delete); + break; + default: /*fail*/ ret = EINVAL; state->err = "Invalid request type"; @@ -1602,6 +1641,10 @@ sdap_handle_acct_req_done(struct tevent_req *subreq) ret = sdap_get_user_and_group_recv(subreq, &state->dp_error, &state->sdap_ret); break; + case BE_REQ_BY_CERT: + err = "User lookup by certificate failed"; + ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret); + break; default: /*fail*/ ret = EINVAL; break; -- 2.1.0
From a6848142a03b662918186aa7ade0d6fd02be3269 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Wed, 3 Jun 2015 16:18:05 +0200 Subject: [PATCH 6/8] ncache: add calls for certificate based searches Related to https://fedorahosted.org/sssd/ticket/2596 --- src/responder/common/negcache.c | 31 +++++++++++++++++++++++++++++ src/responder/common/negcache.h | 3 +++ src/tests/cmocka/test_negcache.c | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c index cf70dc52fe122328810064ebd112aec501f892a4..64270f4672f81fcd71f60acb83728d82dd4a1965 100644 --- a/src/responder/common/negcache.c +++ b/src/responder/common/negcache.c @@ -35,6 +35,7 @@ #define NC_UID_PREFIX NC_ENTRY_PREFIX"UID" #define NC_GID_PREFIX NC_ENTRY_PREFIX"GID" #define NC_SID_PREFIX NC_ENTRY_PREFIX"SID" +#define NC_CERT_PREFIX NC_ENTRY_PREFIX"CERT" struct sss_nc_ctx { struct tdb_context *tdb; @@ -417,6 +418,21 @@ int sss_ncache_check_sid(struct sss_nc_ctx *ctx, int ttl, const char *sid) return ret; } +int sss_ncache_check_cert(struct sss_nc_ctx *ctx, int ttl, const char *cert) +{ + char *str; + int ret; + + str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert); + if (!str) return ENOMEM; + + ret = sss_ncache_check_str(ctx, str, ttl); + + talloc_free(str); + return ret; +} + + static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent, const char *domain, const char *name) { @@ -548,6 +564,21 @@ int sss_ncache_set_sid(struct sss_nc_ctx *ctx, bool permanent, const char *sid) return ret; } +int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent, + const char *cert) +{ + char *str; + int ret; + + str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert); + if (!str) return ENOMEM; + + ret = sss_ncache_set_str(ctx, str, permanent); + + talloc_free(str); + return ret; +} + static int delete_permanent(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { diff --git a/src/responder/common/negcache.h b/src/responder/common/negcache.h index b96fbfda5a63ce32c42b31bcfe517d2369f06138..e7cbfe11451399a639d8e77b3479e74968e72921 100644 --- a/src/responder/common/negcache.h +++ b/src/responder/common/negcache.h @@ -37,6 +37,7 @@ int sss_ncache_check_netgr(struct sss_nc_ctx *ctx, int ttl, int sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid); int sss_ncache_check_gid(struct sss_nc_ctx *ctx, int ttl, gid_t gid); int sss_ncache_check_sid(struct sss_nc_ctx *ctx, int ttl, const char *sid); +int sss_ncache_check_cert(struct sss_nc_ctx *ctx, int ttl, const char *cert); int sss_ncache_check_service(struct sss_nc_ctx *ctx, int ttl, struct sss_domain_info *dom, @@ -60,6 +61,8 @@ int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent, int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, uid_t uid); int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent, gid_t gid); int sss_ncache_set_sid(struct sss_nc_ctx *ctx, bool permanent, const char *sid); +int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent, + const char *cert); int sss_ncache_set_service_name(struct sss_nc_ctx *ctx, bool permanent, struct sss_domain_info *dom, const char *name, const char *proto); diff --git a/src/tests/cmocka/test_negcache.c b/src/tests/cmocka/test_negcache.c index 6f9802a38c44adfc41688ce1a9297a8636c5d616..fa07ea2481e2040e3e83eecfb5c69dbec17e26fa 100644 --- a/src/tests/cmocka/test_negcache.c +++ b/src/tests/cmocka/test_negcache.c @@ -45,6 +45,7 @@ #define PORT 21 #define SID "S-1-2-3-4-5" +#define CERT "MIIECTCCAvGgAwIBAgIBCTANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEuREVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA0MjgxMDIxMTFaFw0xNzA0MjgxMDIxMTFaMDIxEjAQBgNVBAoMCUlQQS5ERVZFTDEcMBoGA1UEAwwTaXBhLWRldmVsLmlwYS5kZXZlbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALIykqtHuAwTVEofHikG/9BQy/dfeZFlsTkBg2qtnnc78w3XufbcnkpJp9Bmcsy/d9beqf5nlsxJ8TcjLsRQ9Ou6YtQjTfM3OILuOz8s0ICbF6qb66bd9hX/BrLO/9+KnpWFSR+E/YEmzgYyDTbKfBWBaGuPPrOi/K6vwkRYFZVA/FYZkYDtQhFmBO884HYzS4P6frRH3PvtRqWNCmaHpe97dGKsvnM2ybT+IMSB8/54GajQr3+BciRh2XaT4wvSTxkXM1fUgrDxqAP2AZmpuIyDyboZh+rWOwbrTPfx5SipELZG3uHhP8HMcr4qQ8b20LWgxCRuT73sIooHET350xUCAwEAAaOCASYwggEiMB8GA1UdIwQYMBaAFPKdQk4PxEglWC8czg+hPyLIVciRMDsGCCsGAQUFBwEBBC8wLTArBggrBgEFBQcwAYYfaHR0cDovL2lwYS1jYS5pcGEuZGV2ZWwvY2Evb2NzcDAOBgNVHQ8BAf8EBAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHQGA1UdHwRtMGswaaAxoC+GLWh0dHA6Ly9pcGEtY2EuaXBhLmRldmVsL2lwYS9jcmwvTWFzdGVyQ1JMLmJpbqI0pDIwMDEOMAwGA1UECgwFaXBhY2ExHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAdBgNVHQ4EFgQULSs/y/Wy/zIsqMIc3b2MgB7dMYIwDQYJKoZIhvcNAQELBQADggEBAJpHLlCnTR1TD8lxQgzl2n1JZOeryN/fAsGH0Vve2m8r5PC+ugnfAoULiuabBn1pOGxy/0x7Kg0/Iy8WRv8Fk7DqJCjXEqFXuFkZJfNDCtP9DzeNuMoV50iKoMfHS38BPFjXN+X/fSsBrA2fUWrlQCTmXlUN97gvQqxt5Slrxgukvxm9OSfu/sWz22LUvtJHupYwWv1iALgnXS86lAuVNYVALLxn34r58XsZlj5CSBMjBJWpaxEzgUdag3L2IPqOQXuPd0d8x11G9E/9gQquOSe2aiZjsdO/VYOCmzZsM2QPUMBVlBPDhfTVcWXQwN385uycW/ARtSzzSME2jKKWSIQ=" #define PROTO "TCP" #define LIFETIME 200 #define SHORTSPAN 1 @@ -317,6 +318,46 @@ static void test_sss_ncache_sid(void **state) assert_int_equal(ret, EEXIST); } +/* @test_sss_ncache_cert : test following functions + * sss_ncache_set_cert + * sss_ncache_check_cert_ + */ +static void test_sss_ncache_cert(void **state) +{ + int ret, ttl; + bool permanent; + const char *cert = NULL; + struct test_state *ts; + + ttl = LIFETIME; + cert = CERT; + ts = talloc_get_type_abort(*state, struct test_state); + + /*test when cert in not present in database */ + ret = sss_ncache_check_cert(ts->ctx, ttl, cert); + assert_int_equal(ret, ENOENT); + + /* test when cert is present in database */ + permanent = true; + ret = sss_ncache_set_cert(ts->ctx, permanent, cert); + assert_int_equal(ret, EOK); + + ret = sss_ncache_check_cert(ts->ctx, ttl, cert); + assert_int_equal(ret, EEXIST); + + permanent = false; + ret = sss_ncache_set_cert(ts->ctx, permanent, cert); + assert_int_equal(ret, EOK); + + ret = sss_ncache_check_cert(ts->ctx, ttl, cert); + assert_int_equal(ret, EEXIST); + + /* test when ttl is -1 with cert present in database*/ + ttl = -1; + ret = sss_ncache_check_cert(ts->ctx, ttl, cert); + assert_int_equal(ret, EEXIST); +} + /* @test_sss_ncache_user : test following functions * sss_ncache_check_user * sss_ncache_set_user @@ -809,6 +850,7 @@ int main(void) cmocka_unit_test_setup_teardown(test_sss_ncache_uid, setup, teardown), cmocka_unit_test_setup_teardown(test_sss_ncache_gid, setup, teardown), cmocka_unit_test_setup_teardown(test_sss_ncache_sid, setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_ncache_cert, setup, teardown), cmocka_unit_test_setup_teardown(test_sss_ncache_user, setup, teardown), cmocka_unit_test_setup_teardown(test_sss_ncache_group, setup, teardown), cmocka_unit_test_setup_teardown(test_sss_ncache_netgr, setup, teardown), -- 2.1.0
From 57f6d421a961ed24e6bd4a4ab389a49c3b88f03e Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Tue, 16 Jun 2015 16:58:23 +0200 Subject: [PATCH 7/8] utils: add get_last_x_chars() --- src/tests/cmocka/test_string_utils.c | 28 ++++++++++++++++++++++++++++ src/tests/cmocka/test_utils.c | 1 + src/tests/cmocka/test_utils.h | 1 + src/util/string_utils.c | 17 +++++++++++++++++ src/util/util.h | 2 ++ 5 files changed, 49 insertions(+) diff --git a/src/tests/cmocka/test_string_utils.c b/src/tests/cmocka/test_string_utils.c index 5d3fcf4fe454a0be3a4c72b778003481f66910bb..4832015a5a43ece2c9d476f2a3974d46116ebfce 100644 --- a/src/tests/cmocka/test_string_utils.c +++ b/src/tests/cmocka/test_string_utils.c @@ -192,3 +192,31 @@ void test_guid_blob_to_string_buf(void **state) assert_string_equal(test_data[c].guid_str, str_buf); } } + +void test_get_last_x_chars(void **state) +{ + const char *s; + + s = get_last_x_chars(NULL, 0); + assert_null(s); + + s = get_last_x_chars("abc", 0); + assert_non_null(s); + assert_string_equal(s, ""); + + s = get_last_x_chars("abc", 1); + assert_non_null(s); + assert_string_equal(s, "c"); + + s = get_last_x_chars("abc", 2); + assert_non_null(s); + assert_string_equal(s, "bc"); + + s = get_last_x_chars("abc", 3); + assert_non_null(s); + assert_string_equal(s, "abc"); + + s = get_last_x_chars("abc", 4); + assert_non_null(s); + assert_string_equal(s, "abc"); +} diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c index e7f97f763bc3ee15ecabaa03dc2fffb7b366faa8..d3d00feda0bdd4048519f90ba48ae9d1042a95a1 100644 --- a/src/tests/cmocka/test_utils.c +++ b/src/tests/cmocka/test_utils.c @@ -1267,6 +1267,7 @@ int main(int argc, const char *argv[]) cmocka_unit_test(test_replace_whitespaces), cmocka_unit_test(test_reverse_replace_whitespaces), cmocka_unit_test(test_guid_blob_to_string_buf), + cmocka_unit_test(test_get_last_x_chars), cmocka_unit_test_setup_teardown(test_add_strings_lists, setup_add_strings_lists, teardown_add_strings_lists), diff --git a/src/tests/cmocka/test_utils.h b/src/tests/cmocka/test_utils.h index 61ef7e43a82649d775d9b932def9e957b0761bed..8b51631655afaca8a6a6a8a649677a7d0214499d 100644 --- a/src/tests/cmocka/test_utils.h +++ b/src/tests/cmocka/test_utils.h @@ -30,5 +30,6 @@ void test_textual_public_key(void **state); void test_replace_whitespaces(void **state); void test_reverse_replace_whitespaces(void **state); void test_guid_blob_to_string_buf(void **state); +void test_get_last_x_chars(void **state); #endif /* __TESTS__CMOCKA__TEST_UTILS_H__ */ diff --git a/src/util/string_utils.c b/src/util/string_utils.c index 71b2a092018076fd9c20ef9ac39a11964876cfc3..b6037621ec5218d81f37b901386f2918780a1a2d 100644 --- a/src/util/string_utils.c +++ b/src/util/string_utils.c @@ -108,3 +108,20 @@ errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf, return EOK; } + +const char *get_last_x_chars(const char *str, size_t x) +{ + size_t len; + + if (str == NULL) { + return NULL; + } + + len = strlen(str); + + if (len < x) { + return str; + } + + return (str + len - x); +} diff --git a/src/util/util.h b/src/util/util.h index 786ed303e1d84dd2783295c51c6126b17c344e5a..3d90cf0d1024b93016987a4d3e8a515359fd974d 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -628,6 +628,8 @@ char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx, errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf, size_t buf_size); +const char *get_last_x_chars(const char *str, size_t x); + /* from become_user.c */ errno_t become_user(uid_t uid, gid_t gid); struct sss_creds; -- 2.1.0
From c83ca800e79c107d48caa020102365cc9d2909c5 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Tue, 26 May 2015 14:29:17 +0200 Subject: [PATCH 8/8] IFP: add FindByCertificate method for User objects Related to https://fedorahosted.org/sssd/ticket/2596 --- Makefile.am | 4 +- src/responder/common/responder.h | 3 +- src/responder/common/responder_cache_req.c | 88 +++++++++++++++++++++++++++--- src/responder/common/responder_cache_req.h | 19 ++++++- src/responder/common/responder_dp.c | 11 ++++ src/responder/ifp/ifp_iface.c | 1 + src/responder/ifp/ifp_iface.xml | 4 ++ src/responder/ifp/ifp_iface_generated.c | 26 +++++++++ src/responder/ifp/ifp_iface_generated.h | 5 ++ src/responder/ifp/ifp_users.c | 87 +++++++++++++++++++++++++++++ src/responder/ifp/ifp_users.h | 4 ++ src/responder/ifp/ifpsrv_cmd.c | 4 +- 12 files changed, 242 insertions(+), 14 deletions(-) diff --git a/Makefile.am b/Makefile.am index eecbf95ab4492465e68dd9ef09601e230bde2c3f..b2082bb49d4f7ee4ade71e7db73d9b8470645175 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1132,7 +1132,9 @@ sssd_ifp_CFLAGS = \ $(AM_CFLAGS) sssd_ifp_LDADD = \ $(SSSD_LIBS) \ - $(SSSD_INTERNAL_LTLIBS) + $(SSSD_INTERNAL_LTLIBS) \ + libsss_cert.la \ + $(NULL) dist_dbuspolicy_DATA = \ src/responder/ifp/org.freedesktop.sssd.infopipe.conf dist_dbusservice_DATA = \ diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index 9c7a73809a3de8859aa546c2a7d31620fea39ac9..bd0250d52aae1efdac3bc0847f692542c6cfb6d2 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -281,7 +281,8 @@ enum sss_dp_acct_type { SSS_DP_NETGR, SSS_DP_SERVICES, SSS_DP_SECID, - SSS_DP_USER_AND_GROUP + SSS_DP_USER_AND_GROUP, + SSS_DP_CERT }; struct tevent_req * diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c index 7ba257276b064d923b6144f45ade59cac48849d5..dd81abadf71c5e10e7bc2ea2490429a49bdc0270 100644 --- a/src/responder/common/responder_cache_req.c +++ b/src/responder/common/responder_cache_req.c @@ -34,6 +34,7 @@ struct cache_req_input { /* Provided input. */ const char *orig_name; uint32_t id; + const char *cert; /* Data Provider request type resolved from @type. * FIXME: This is currently needed for data provider calls. We should @@ -56,7 +57,8 @@ struct cache_req_input * cache_req_input_create(TALLOC_CTX *mem_ctx, enum cache_req_type type, const char *name, - uint32_t id) + uint32_t id, + const char *cert) { struct cache_req_input *input; @@ -82,6 +84,17 @@ cache_req_input_create(TALLOC_CTX *mem_ctx, goto fail; } break; + case CACHE_REQ_USER_BY_CERT: + if (cert == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Bug: certificate cannot be NULL!\n"); + goto fail; + } + + input->cert = talloc_strdup(input, cert); + if (input->cert == NULL) { + goto fail; + } + break; case CACHE_REQ_USER_BY_ID: case CACHE_REQ_GROUP_BY_ID: if (id == 0) { @@ -108,6 +121,9 @@ cache_req_input_create(TALLOC_CTX *mem_ctx, case CACHE_REQ_INITGROUPS: input->dp_type = SSS_DP_INITGROUPS; break; + case CACHE_REQ_USER_BY_CERT: + input->dp_type = SSS_DP_CERT; + break; } return input; @@ -192,6 +208,17 @@ cache_req_input_set_domain(struct cache_req_input *input, goto done; } break; + case CACHE_REQ_USER_BY_CERT: + /* certificates might be quite long, only use the last 10 charcters + * for logging */ + fqn = talloc_asprintf(tmp_ctx, "CERT:%s@%s", + get_last_x_chars(input->cert, 10), + domain->name); + if (fqn == NULL) { + ret = ENOMEM; + goto done; + } + break; } input->domain = domain; @@ -227,6 +254,9 @@ static errno_t cache_req_check_ncache(struct cache_req_input *input, case CACHE_REQ_GROUP_BY_ID: ret = sss_ncache_check_gid(ncache, neg_timeout, input->id); break; + case CACHE_REQ_USER_BY_CERT: + ret = sss_ncache_check_cert(ncache, neg_timeout, input->cert); + break; } if (ret == EEXIST) { @@ -254,6 +284,7 @@ static void cache_req_add_to_ncache(struct cache_req_input *input, break; case CACHE_REQ_USER_BY_ID: case CACHE_REQ_GROUP_BY_ID: + case CACHE_REQ_USER_BY_CERT: /* Nothing to do. Those types must be unique among all domains so * the don't contain domain part. Therefore they must be set only * if all domains are search and the entry is not found. */ @@ -290,6 +321,9 @@ static void cache_req_add_to_ncache_global(struct cache_req_input *input, case CACHE_REQ_GROUP_BY_ID: ret = sss_ncache_set_gid(ncache, false, input->id); break; + case CACHE_REQ_USER_BY_CERT: + ret = sss_ncache_set_cert(ncache, false, input->cert); + break; } if (ret != EOK) { @@ -338,6 +372,11 @@ static errno_t cache_req_get_object(TALLOC_CTX *mem_ctx, ret = sysdb_initgroups_with_views(mem_ctx, input->domain, input->dom_objname, &result); break; + case CACHE_REQ_USER_BY_CERT: + one_item_only = true; + ret = sysdb_search_user_by_cert(mem_ctx, input->domain, + input->cert, &result); + break; } if (ret != EOK) { @@ -461,6 +500,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req) const char *extra_flag = NULL; uint64_t cache_expire = 0; errno_t ret; + const char *search_str; state = tevent_req_data(req, struct cache_req_cache_state); @@ -479,6 +519,10 @@ static errno_t cache_req_cache_check(struct tevent_req *req) state->cache_refresh_percent, cache_expire); } + search_str = state->input->dom_objname; + if (state->input->type == CACHE_REQ_USER_BY_CERT) { + search_str = state->input->cert; + } switch (ret) { case EOK: DEBUG(SSSDBG_TRACE_FUNC, "Cached entry is valid, returning...\n"); @@ -492,7 +536,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req) subreq = sss_dp_get_account_send(state, state->rctx, state->input->domain, true, state->input->dp_type, - state->input->dom_objname, + search_str, state->input->id, NULL); if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending out-of-band " @@ -514,7 +558,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req) subreq = sss_dp_get_account_send(state, state->rctx, state->input->domain, true, state->input->dp_type, - state->input->dom_objname, + search_str, state->input->id, extra_flag); if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, @@ -890,7 +934,8 @@ cache_req_user_by_name_send(TALLOC_CTX *mem_ctx, { struct cache_req_input *input; - input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_NAME, name, 0); + input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_NAME, name, 0, + NULL); if (input == NULL) { return NULL; } @@ -912,7 +957,31 @@ cache_req_user_by_id_send(TALLOC_CTX *mem_ctx, { struct cache_req_input *input; - input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_ID, NULL, uid); + input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_ID, NULL, uid, + NULL); + if (input == NULL) { + return NULL; + } + + return cache_req_steal_input_and_send(mem_ctx, ev, rctx, ncache, + neg_timeout, cache_refresh_percent, + domain, input); +} + +struct tevent_req * +cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int neg_timeout, + int cache_refresh_percent, + const char *domain, + const char *pem_cert) +{ + struct cache_req_input *input; + + input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_CERT, + NULL, 0, pem_cert); if (input == NULL) { return NULL; } @@ -934,7 +1003,8 @@ cache_req_group_by_name_send(TALLOC_CTX *mem_ctx, { struct cache_req_input *input; - input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_NAME, name, 0); + input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_NAME, name, 0, + NULL); if (input == NULL) { return NULL; } @@ -956,7 +1026,8 @@ cache_req_group_by_id_send(TALLOC_CTX *mem_ctx, { struct cache_req_input *input; - input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_ID, NULL, gid); + input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_ID, NULL, gid, + NULL); if (input == NULL) { return NULL; } @@ -978,7 +1049,8 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx, { struct cache_req_input *input; - input = cache_req_input_create(mem_ctx, CACHE_REQ_INITGROUPS, name, 0); + input = cache_req_input_create(mem_ctx, CACHE_REQ_INITGROUPS, name, 0, + NULL); if (input == NULL) { return NULL; } diff --git a/src/responder/common/responder_cache_req.h b/src/responder/common/responder_cache_req.h index 088e8efe0ceefe49510bc5eab37e7825b667e5f3..84a9dde7d9df066e44b1352e0a4557f02d08cc15 100644 --- a/src/responder/common/responder_cache_req.h +++ b/src/responder/common/responder_cache_req.h @@ -32,7 +32,8 @@ enum cache_req_type { CACHE_REQ_USER_BY_ID, CACHE_REQ_GROUP_BY_NAME, CACHE_REQ_GROUP_BY_ID, - CACHE_REQ_INITGROUPS + CACHE_REQ_INITGROUPS, + CACHE_REQ_USER_BY_CERT }; struct cache_req_input; @@ -41,7 +42,8 @@ struct cache_req_input * cache_req_input_create(TALLOC_CTX *mem_ctx, enum cache_req_type type, const char *name, - uint32_t id); + uint32_t id, + const char *cert); /** * Currently only SSS_DP_USER and SSS_DP_INITGROUPS are supported. @@ -90,6 +92,19 @@ cache_req_user_by_id_send(TALLOC_CTX *mem_ctx, cache_req_recv(mem_ctx, req, _result, _domain, NULL) struct tevent_req * +cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resp_ctx *rctx, + struct sss_nc_ctx *ncache, + int neg_timeout, + int cache_refresh_percent, + const char *domain, + const char *pem_cert); + +#define cache_req_user_by_cert_recv(mem_ctx, req, _result, _domain, _name) \ + cache_req_recv(mem_ctx, req, _result, _domain, _name) + +struct tevent_req * cache_req_group_by_name_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct resp_ctx *rctx, diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c index 853b3eae3877a8b6b2ffb310a0fb9ccf017498ae..f752c94c37fd0efa0d072ef8c567bd875a08e6f7 100644 --- a/src/responder/common/responder_dp.c +++ b/src/responder/common/responder_dp.c @@ -548,6 +548,9 @@ sss_dp_get_account_msg(void *pvt) case SSS_DP_USER_AND_GROUP: be_type = BE_REQ_USER_AND_GROUP; break; + case SSS_DP_CERT: + be_type = BE_REQ_BY_CERT; + break; } if (info->fast_reply) { @@ -563,6 +566,14 @@ sss_dp_get_account_msg(void *pvt) filter = talloc_asprintf(info, "%s=%s", DP_SEC_ID, info->opt_name); } + } else if (info->type == SSS_DP_CERT) { + if (info->extra) { + filter = talloc_asprintf(info, "%s=%s:%s", DP_CERT, + info->opt_name, info->extra); + } else { + filter = talloc_asprintf(info, "%s=%s", DP_CERT, + info->opt_name); + } } else { if (info->extra) { filter = talloc_asprintf(info, "name=%s:%s", diff --git a/src/responder/ifp/ifp_iface.c b/src/responder/ifp/ifp_iface.c index 015c66dc5323e237dd21575162e434b11acd8ed7..86d8d338c3d18c22a8dc449b6520f65f8968e26b 100644 --- a/src/responder/ifp/ifp_iface.c +++ b/src/responder/ifp/ifp_iface.c @@ -82,6 +82,7 @@ struct iface_ifp_users iface_ifp_users = { { &iface_ifp_users_meta, 0 }, .FindByName = ifp_users_find_by_name, .FindByID = ifp_users_find_by_id, + .FindByCertificate = ifp_users_find_by_cert, .ListByName = ifp_users_list_by_name, .ListByDomainAndName = ifp_users_list_by_domain_and_name }; diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml index 340eb6d23ebfebb508e12118b9ac6c9a71fed099..612a5b5a2817231d5793346778b49cc5a132fc73 100644 --- a/src/responder/ifp/ifp_iface.xml +++ b/src/responder/ifp/ifp_iface.xml @@ -136,6 +136,10 @@ <arg name="id" type="u" direction="in" /> <arg name="result" type="o" direction="out" /> </method> + <method name="FindByCertificate"> + <arg name="pem_cert" type="s" direction="in" /> + <arg name="result" type="o" direction="out" /> + </method> <method name="ListByName"> <arg name="name_filter" type="s" direction="in" /> <arg name="limit" type="u" direction="in" /> diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c index 8255cbea729d9b2c0696cbfdef5c0daf9d958631..a4fdd5d12cd5c82e7832de9d07f55ea6eb621fba 100644 --- a/src/responder/ifp/ifp_iface_generated.c +++ b/src/responder/ifp/ifp_iface_generated.c @@ -685,6 +685,25 @@ int iface_ifp_users_FindByID_finish(struct sbus_request *req, const char *arg_re DBUS_TYPE_INVALID); } +/* arguments for org.freedesktop.sssd.infopipe.Users.FindByCertificate */ +const struct sbus_arg_meta iface_ifp_users_FindByCertificate__in[] = { + { "pem_cert", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.infopipe.Users.FindByCertificate */ +const struct sbus_arg_meta iface_ifp_users_FindByCertificate__out[] = { + { "result", "o" }, + { NULL, } +}; + +int iface_ifp_users_FindByCertificate_finish(struct sbus_request *req, const char *arg_result) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_OBJECT_PATH, &arg_result, + DBUS_TYPE_INVALID); +} + /* arguments for org.freedesktop.sssd.infopipe.Users.ListByName */ const struct sbus_arg_meta iface_ifp_users_ListByName__in[] = { { "name_filter", "s" }, @@ -743,6 +762,13 @@ const struct sbus_method_meta iface_ifp_users__methods[] = { invoke_u_method, }, { + "FindByCertificate", /* name */ + iface_ifp_users_FindByCertificate__in, + iface_ifp_users_FindByCertificate__out, + offsetof(struct iface_ifp_users, FindByCertificate), + invoke_s_method, + }, + { "ListByName", /* name */ iface_ifp_users_ListByName__in, iface_ifp_users_ListByName__out, diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h index d2e5cdd3a689d42509e63adde70237cbde627ee2..4dfe61ddff3763b1d3ee165b9098efd667037663 100644 --- a/src/responder/ifp/ifp_iface_generated.h +++ b/src/responder/ifp/ifp_iface_generated.h @@ -68,6 +68,7 @@ #define IFACE_IFP_USERS "org.freedesktop.sssd.infopipe.Users" #define IFACE_IFP_USERS_FINDBYNAME "FindByName" #define IFACE_IFP_USERS_FINDBYID "FindByID" +#define IFACE_IFP_USERS_FINDBYCERTIFICATE "FindByCertificate" #define IFACE_IFP_USERS_LISTBYNAME "ListByName" #define IFACE_IFP_USERS_LISTBYDOMAINANDNAME "ListByDomainAndName" @@ -235,6 +236,7 @@ struct iface_ifp_users { struct sbus_vtable vtable; /* derive from sbus_vtable */ int (*FindByName)(struct sbus_request *req, void *data, const char *arg_name); int (*FindByID)(struct sbus_request *req, void *data, uint32_t arg_id); + int (*FindByCertificate)(struct sbus_request *req, void *data, const char *arg_pem_cert); int (*ListByName)(struct sbus_request *req, void *data, const char *arg_name_filter, uint32_t arg_limit); int (*ListByDomainAndName)(struct sbus_request *req, void *data, const char *arg_domain_name, const char *arg_name_filter, uint32_t arg_limit); }; @@ -245,6 +247,9 @@ int iface_ifp_users_FindByName_finish(struct sbus_request *req, const char *arg_ /* finish function for FindByID */ int iface_ifp_users_FindByID_finish(struct sbus_request *req, const char *arg_result); +/* finish function for FindByCertificate */ +int iface_ifp_users_FindByCertificate_finish(struct sbus_request *req, const char *arg_result); + /* finish function for ListByName */ int iface_ifp_users_ListByName_finish(struct sbus_request *req, const char *arg_result[], int len_result); diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c index fa6f47f0d2f7ce52c3f0069b8ebf0bf1c98dbf22..2ec74c30b348ac5f2b84cdc8e2dd406fd44a7da3 100644 --- a/src/responder/ifp/ifp_users.c +++ b/src/responder/ifp/ifp_users.c @@ -25,6 +25,7 @@ #include "db/sysdb.h" #include "util/util.h" #include "util/strtonum.h" +#include "util/cert.h" #include "sbus/sssd_dbus_errors.h" #include "responder/common/responder.h" #include "responder/common/responder_cache_req.h" @@ -222,6 +223,92 @@ done: return; } +static void ifp_users_find_by_cert_done(struct tevent_req *req); + +int ifp_users_find_by_cert(struct sbus_request *sbus_req, void *data, + const char *pem_cert) +{ + struct ifp_ctx *ctx; + struct tevent_req *req; + int ret; + char *derb64; + DBusError *error; + + ctx = talloc_get_type(data, struct ifp_ctx); + if (ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); + return ERR_INTERNAL; + } + + ret = sss_cert_pem_to_derb64(sbus_req, pem_cert, &derb64); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_cert_pem_to_derb64 failed.\n"); + + if (ret == ENOMEM) { + return ret; + } + + error = sbus_error_new(sbus_req, DBUS_ERROR_INVALID_ARGS, + "Invalid certificate format"); + sbus_request_fail_and_finish(sbus_req, error); + /* the connection is already terminated with an error message, hence + * we have to return EOK to not terminate the connection twice. */ + return EOK; + } + + req = cache_req_user_by_cert_send(sbus_req, ctx->rctx->ev, ctx->rctx, + ctx->ncache, ctx->neg_timeout, 0, + NULL, derb64); + if (req == NULL) { + return ENOMEM; + } + + tevent_req_set_callback(req, ifp_users_find_by_cert_done, sbus_req); + + return EOK; +} + +static void ifp_users_find_by_cert_done(struct tevent_req *req) +{ + DBusError *error; + struct sbus_request *sbus_req; + struct sss_domain_info *domain; + struct ldb_result *result; + char *object_path; + errno_t ret; + + sbus_req = tevent_req_callback_data(req, struct sbus_request); + + ret = cache_req_user_by_cert_recv(sbus_req, req, &result, &domain, NULL); + talloc_zfree(req); + if (ret == ENOENT) { + error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND, + "User not found"); + goto done; + } else if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " + "user [%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } + + object_path = ifp_users_build_path_from_msg(sbus_req, domain, + result->msgs[0]); + if (object_path == NULL) { + error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, + "Failed to compose object path"); + goto done; + } + +done: + if (ret != EOK) { + sbus_request_fail_and_finish(sbus_req, error); + return; + } + + iface_ifp_users_FindByCertificate_finish(sbus_req, object_path); + return; +} + int ifp_users_list_by_name(struct sbus_request *sbus_req, void *data, const char *filter, diff --git a/src/responder/ifp/ifp_users.h b/src/responder/ifp/ifp_users.h index 4da0a734752a2a1bd11b0e21c532a1302c9126f1..471c3fb019c7cd0858b2928969b045091f370446 100644 --- a/src/responder/ifp/ifp_users.h +++ b/src/responder/ifp/ifp_users.h @@ -43,6 +43,10 @@ int ifp_users_find_by_id(struct sbus_request *sbus_req, void *data, uint32_t id); +int ifp_users_find_by_cert(struct sbus_request *sbus_req, + void *data, + const char *pem_cert); + int ifp_users_list_by_name(struct sbus_request *sbus_req, void *data, const char *filter, diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c index d4d5dc640d634e3f2664a4712432ad9652824b8a..ab6156fd6c92e8fd8176da6664cd6b79eb3f5a97 100644 --- a/src/responder/ifp/ifpsrv_cmd.c +++ b/src/responder/ifp/ifpsrv_cmd.c @@ -497,11 +497,11 @@ ifp_user_get_attr_lookup(struct tevent_req *subreq) switch (state->search_type) { case SSS_DP_USER: input = cache_req_input_create(state, CACHE_REQ_USER_BY_NAME, - state->name, 0); + state->name, 0, NULL); break; case SSS_DP_INITGROUPS: input = cache_req_input_create(state, CACHE_REQ_INITGROUPS, - state->name, 0); + state->name, 0, NULL); break; default: DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported search type [%d]!\n", -- 2.1.0
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel