From 6302a22355acccb3479074e75b63a6fa596ef8ce Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Tue, 25 Jul 2017 13:58:49 +0200 Subject: [PATCH] New upstream release 1.15.3 https://docs.pagure.org/SSSD.sssd/users/relnotes/notes_1_15_3.html --- .gitignore | 1 + ...g-the-version-for-the-1.15.3-release.patch | 23 - 0002-UTIL-Typo-in-comment.patch | 29 - ...ion-sssd-secrets-in-SEE-ALSO-section.patch | 36 - ...on_separator-move-to-a-separate-file.patch | 369 -- ...util-move-string_in_list-to-util_ext.patch | 91 - ...rtmap-add-new-library-libsss_certmap.patch | 5787 ----------------- ...aceholder-for-OpenSSL-implementation.patch | 151 - 0008-sysdb-add-sysdb_attrs_copy.patch | 173 - ...users_send-new-argument-mapped_attrs.patch | 316 - ...ore-the-certificate-from-the-request.patch | 178 - ...to_ldap_filter-add-sss_certmap-suppo.patch | 235 - 0012-sysdb-add-certmap-related-calls.patch | 846 --- 0013-IPA-add-certmap-support.patch | 484 -- ...-nss-idmap-add-sss_nss_getlistbycert.patch | 736 --- ...-buffer-for-certificate-based-reques.patch | 70 - ...A-Add-s2n-request-to-string-function.patch | 44 - ...debug-logging-for-ipa-s2n-operations.patch | 82 - ...input-parameter-for-the-readonly-ope.patch | 45 - ...IL-Fix-a-typo-in-the-tcurl-test-tool.patch | 32 - ...-UTIL-Add-SAFEALIGN_COPY_UINT8_CHECK.patch | 36 - ...-Add-utility-macro-cli_creds_get_gid.patch | 34 - ...ype-specific-getsetters-to-sss_iobuf.patch | 194 - 0023-UTIL-krb5-principal-un-marshalling.patch | 262 - ...nitial-responder-build-and-packaging.patch | 1013 --- ...-request-parsing-and-sending-a-reply.patch | 578 -- ...-internal-ccache-storage-and-retriev.patch | 2153 ------ ...M-Add-a-in-memory-credential-storage.patch | 907 --- ...-KCM-Implement-KCM-server-operations.patch | 2326 ------- 0029-MAN-Add-a-manual-page-for-sssd-kcm.patch | 278 - ...egration-tests-for-the-KCM-responder.patch | 799 --- ...-DB-path-before-the-operation-itself.patch | 405 -- ...-nicer-error-message-on-request-with.patch | 40 - ...aches-in-secrets-for-the-KCM-respond.patch | 206 - ...rt-HTTP-POST-for-creating-containers.patch | 129 - 0035-KCM-Store-ccaches-in-secrets.patch | 3787 ----------- ...rets-ccache-back-end-configurable-ma.patch | 219 - 0037-KCM-Queue-requests-by-the-same-UID.patch | 909 --- ...te-the-responder-if-the-secrets-back.patch | 55 - ...n-3.6-invalid-escape-sequence-deprec.patch | 34 - ...llback-if-pkg-config-for-uuid-is-mis.patch | 30 - ...configure-failure-with-strict-cflags.patch | 52 - ...emove-bashism-from-intgcheck-prepare.patch | 54 - ...Introduce-subdomain_create_conf_path.patch | 127 - ...-use_fully_qualified_names-for-subdo.patch | 531 -- ...Q-Descend-into-subdomains-on-lookups.patch | 172 - ...NSS-TESTS-Fix-subdomains-attribution.patch | 35 - ...e-setup-teardown-for-subdomains-test.patch | 274 - ...e-searches-for-non-fqnames-members-o.patch | 355 - ...s-to-deal-with-the-domain-s-resoluti.patch | 289 - ...tests-for-the-domain-s-resolution-or.patch | 259 - ...omainsResolutionOrder-from-ipaConfig.patch | 369 -- ...ename-_refresh_view-to-_refresh_view.patch | 54 - ...ainsResolutionOrder-from-IPA-ID-View.patch | 347 - ...NKLIST-Add-DLIST_FOR_EACH_SAFE-macro.patch | 37 - ...EQ-Make-use-of-domainResolutionOrder.patch | 795 --- ...ose-replace_char-as-sss_replace_char.patch | 81 - ...omain_resolution_order-config-option.patch | 205 - 0058-ssh-handle-binary-keys-correctly.patch | 48 - ...for-certificates-from-non-default-vi.patch | 52 - ...esponder-that-pkinit-is-not-availabl.patch | 60 - ...ttributes-to-user-from-trusted-domai.patch | 153 - ...users-by-certificates-on-IPA-clients.patch | 209 - ...enable-AD-user-lookup-by-certificate.patch | 30 - ...-SSSD-domain-type-to-distinguish-POS.patch | 242 - ...figuring-application-sections-as-non.patch | 531 -- ...Q-Domain-type-selection-in-cache_req.patch | 976 --- ...rch-both-POSIX-and-non-POSIX-domains.patch | 705 -- ...on-t-crash-when-no-results-are-found.patch | 57 - 0069-PAM-Remove-unneeded-memory-context.patch | 58 - 0070-PAM-Add-application-services.patch | 452 -- ...-SYSDB-Allow-storing-non-POSIX-users.patch | 152 - ...nly-generate-new-UID-in-local-domain.patch | 36 - ...n-POSIX-users-in-application-domains.patch | 141 - ...earch-filters-in-application-domains.patch | 254 - ...e-users-in-a-non-POSIX-domain-using-.patch | 353 - ...-by-one-error-in-secrets-key-parsing.patch | 210 - ...l-add-support-for-ssl-and-raw-output.patch | 1477 ----- ...tor-so-new-options-can-be-added-more.patch | 437 -- ...curl-test-add-support-for-raw-output.patch | 48 - ...rl-test-add-support-for-tls-settings.patch | 61 - ...curl-add-support-for-http-basic-auth.patch | 111 - ...url-test-allow-to-set-custom-headers.patch | 62 - ...t-add-support-for-client-certificate.patch | 52 - 0084-ci-do-not-build-secrets-on-rhel6.patch | 114 - ...-build-make-curl-required-by-secrets.patch | 64 - ...-secrets-use-tcurl-in-proxy-provider.patch | 458 -- ...e-http-parser-code-in-proxy-provider.patch | 611 -- ...allow-to-configure-certificate-check.patch | 253 - ...HTTP-basic-authentication-with-proxy.patch | 38 - 0090-secrets-fix-debug-message.patch | 28 - ...ets-always-add-Content-Length-header.patch | 111 - ...ix-read-shadows-a-global-declaration.patch | 39 - 0093-configure-fix-typo.patch | 28 - ...ccept-certificate-with-data-before-h.patch | 87 - ...ation-of-libsss_certmap-with-libcryp.patch | 48 - ...t-leak-selinux-context-on-clients-de.patch | 68 - ..._info_send-provide-correct-req_input.patch | 88 - ...o-not-fail-if-SELinux-is-not-managed.patch | 210 - 0099-DP-Fix-typo.patch | 38 - ...-Fix-handling-of-enable_files_domain.patch | 77 - ...add-service-and-environment-to-PAM-t.patch | 104 - ...test_client-add-SSSD-getpwnam-lookup.patch | 141 - 0103-sss_sifp-update-method-names.patch | 53 - ...test_client-add-InfoPipe-user-lookup.patch | 130 - ...ntegrate-pam_test_client-into-sssctl.patch | 358 - 0106-i18n-adding-sssctl-files.patch | 33 - ...ck-Message-when-sssd.conf-is-missing.patch | 38 - ...R-add-env-variable-to-disable-plugin.patch | 89 - ...ection-for-NULL-before-unregister-it.patch | 43 - ...se-max-15-characters-for-AD-host-UPN.patch | 48 - 0111-minor-typo-fixes.patch | 169 - ...ional-build-for-krb5_local_auth_plug.patch | 46 - ...t_name-and-sized_domain_name-into-re.patch | 299 - ...main_name-to-format-the-groups-the-u.patch | 94 - 0116-SECRETS-remove-unused-variable.patch | 32 - ...G-message-if-a-group-has-no-ipaNTSec.patch | 41 - ...ck-to-global-domain-resolution-order.patch | 312 - ...-NSS-TESTS-Improve-non-fqnames-tests.patch | 163 - ...-configurationless-shortname-lookups.patch | 138 - ...-Add-some-comments-to-cache_req_doma.patch | 41 - ...-Improve-domaiN_resolution_order-deb.patch | 53 - ...-debug-the-set-domain-resolution-ord.patch | 49 - ...ng-a-NULL-map-to-sdap_search_bases_e.patch | 36 - ...ases-instead-of-domain_to_basedn-whe.patch | 88 - ...B-Fix-standalone-application-domains.patch | 127 - ...-utils-add-sss_domain_is_forest_root.patch | 47 - ...-root-not-listed-in-ad_enabled_domai.patch | 103 - ...add-certificates-to-mapped-attribute.patch | 101 - ...debug-message-for-missing-ipaNTSecur.patch | 44 - 0131-Use-correct-spelling-of-override.patch | 114 - ...-cache_req-Avoid-bool-in-switch-case.patch | 49 - ...ols-The-ai-structure-is-not-an-array.patch | 51 - ...ix-issues-with-multiple-IP-addresses.patch | 46 - ...lit-connect-and-communication-phases.patch | 95 - 0136-KCM-include-missing-header-file.patch | 42 - ...ssd-update-interface-to-version-0.14.patch | 86 + ...able-tests-with-expired-certificates.patch | 28 - sources | 2 +- sssd.spec | 165 +- 140 files changed, 104 insertions(+), 41079 deletions(-) delete mode 100644 0001-Updating-the-version-for-the-1.15.3-release.patch delete mode 100644 0002-UTIL-Typo-in-comment.patch delete mode 100644 0003-MAN-Mention-sssd-secrets-in-SEE-ALSO-section.patch delete mode 100644 0004-split_on_separator-move-to-a-separate-file.patch delete mode 100644 0005-util-move-string_in_list-to-util_ext.patch delete mode 100644 0006-certmap-add-new-library-libsss_certmap.patch delete mode 100644 0007-certmap-add-placeholder-for-OpenSSL-implementation.patch delete mode 100644 0008-sysdb-add-sysdb_attrs_copy.patch delete mode 100644 0009-sdap_get_users_send-new-argument-mapped_attrs.patch delete mode 100644 0010-LDAP-always-store-the-certificate-from-the-request.patch delete mode 100644 0011-sss_cert_derb64_to_ldap_filter-add-sss_certmap-suppo.patch delete mode 100644 0012-sysdb-add-certmap-related-calls.patch delete mode 100644 0013-IPA-add-certmap-support.patch delete mode 100644 0014-nss-idmap-add-sss_nss_getlistbycert.patch delete mode 100644 0015-nss-allow-larger-buffer-for-certificate-based-reques.patch delete mode 100644 0016-IPA-Add-s2n-request-to-string-function.patch delete mode 100644 0017-IPA-Enhance-debug-logging-for-ipa-s2n-operations.patch delete mode 100644 0018-UTIL-iobuf-Make-input-parameter-for-the-readonly-ope.patch delete mode 100644 0019-UTIL-Fix-a-typo-in-the-tcurl-test-tool.patch delete mode 100644 0020-UTIL-Add-SAFEALIGN_COPY_UINT8_CHECK.patch delete mode 100644 0021-UTIL-Add-utility-macro-cli_creds_get_gid.patch delete mode 100644 0022-UTIL-Add-type-specific-getsetters-to-sss_iobuf.patch delete mode 100644 0023-UTIL-krb5-principal-un-marshalling.patch delete mode 100644 0024-KCM-Initial-responder-build-and-packaging.patch delete mode 100644 0025-KCM-request-parsing-and-sending-a-reply.patch delete mode 100644 0026-KCM-Implement-an-internal-ccache-storage-and-retriev.patch delete mode 100644 0027-KCM-Add-a-in-memory-credential-storage.patch delete mode 100644 0028-KCM-Implement-KCM-server-operations.patch delete mode 100644 0029-MAN-Add-a-manual-page-for-sssd-kcm.patch delete mode 100644 0030-TESTS-Add-integration-tests-for-the-KCM-responder.patch delete mode 100644 0031-SECRETS-Create-DB-path-before-the-operation-itself.patch delete mode 100644 0032-SECRETS-Return-a-nicer-error-message-on-request-with.patch delete mode 100644 0033-SECRETS-Store-ccaches-in-secrets-for-the-KCM-respond.patch delete mode 100644 0034-TCURL-Support-HTTP-POST-for-creating-containers.patch delete mode 100644 0035-KCM-Store-ccaches-in-secrets.patch delete mode 100644 0036-KCM-Make-the-secrets-ccache-back-end-configurable-ma.patch delete mode 100644 0037-KCM-Queue-requests-by-the-same-UID.patch delete mode 100644 0038-KCM-Idle-terminate-the-responder-if-the-secrets-back.patch delete mode 100644 0039-SSSDConfig-Python-3.6-invalid-escape-sequence-deprec.patch delete mode 100644 0040-CONFIGURE-Fix-fallback-if-pkg-config-for-uuid-is-mis.patch delete mode 100644 0041-intg-fix-configure-failure-with-strict-cflags.patch delete mode 100644 0042-intg-Remove-bashism-from-intgcheck-prepare.patch delete mode 100644 0043-UTIL-Introduce-subdomain_create_conf_path.patch delete mode 100644 0044-SUBDOMAINS-Allow-use_fully_qualified_names-for-subdo.patch delete mode 100644 0045-CACHE_REQ-Descend-into-subdomains-on-lookups.patch delete mode 100644 0046-NSS-TESTS-Fix-subdomains-attribution.patch delete mode 100644 0047-NSS-TESTS-Improve-setup-teardown-for-subdomains-test.patch delete mode 100644 0048-NSS-TESTS-Include-searches-for-non-fqnames-members-o.patch delete mode 100644 0049-SYSDB-Add-methods-to-deal-with-the-domain-s-resoluti.patch delete mode 100644 0050-SYSDB-TESTS-Add-tests-for-the-domain-s-resolution-or.patch delete mode 100644 0051-IPA-Get-ipaDomainsResolutionOrder-from-ipaConfig.patch delete mode 100644 0052-IPA_SUBDOMAINS-Rename-_refresh_view-to-_refresh_view.patch delete mode 100644 0053-IPA-Get-ipaDomainsResolutionOrder-from-IPA-ID-View.patch delete mode 100644 0054-DLINKLIST-Add-DLIST_FOR_EACH_SAFE-macro.patch delete mode 100644 0055-CACHE_REQ-Make-use-of-domainResolutionOrder.patch delete mode 100644 0056-UTIL-Expose-replace_char-as-sss_replace_char.patch delete mode 100644 0057-Add-domain_resolution_order-config-option.patch delete mode 100644 0058-ssh-handle-binary-keys-correctly.patch delete mode 100644 0059-ssh-add-support-for-certificates-from-non-default-vi.patch delete mode 100644 0060-krb5-return-to-responder-that-pkinit-is-not-availabl.patch delete mode 100644 0061-IPA-add-mapped-attributes-to-user-from-trusted-domai.patch delete mode 100644 0062-IPA-lookup-AD-users-by-certificates-on-IPA-clients.patch delete mode 100644 0063-IPA-enable-AD-user-lookup-by-certificate.patch delete mode 100644 0064-CONFDB-Introduce-SSSD-domain-type-to-distinguish-POS.patch delete mode 100644 0065-CONFDB-Allow-configuring-application-sections-as-non.patch delete mode 100644 0066-CACHE_REQ-Domain-type-selection-in-cache_req.patch delete mode 100644 0067-IFP-Search-both-POSIX-and-non-POSIX-domains.patch delete mode 100644 0068-IFP-ListByName-Don-t-crash-when-no-results-are-found.patch delete mode 100644 0069-PAM-Remove-unneeded-memory-context.patch delete mode 100644 0070-PAM-Add-application-services.patch delete mode 100644 0071-SYSDB-Allow-storing-non-POSIX-users.patch delete mode 100644 0072-SYSDB-Only-generate-new-UID-in-local-domain.patch delete mode 100644 0073-LDAP-save-non-POSIX-users-in-application-domains.patch delete mode 100644 0074-LDAP-Relax-search-filters-in-application-domains.patch delete mode 100644 0075-KRB5-Authenticate-users-in-a-non-POSIX-domain-using-.patch delete mode 100644 0076-KCM-Fix-off-by-one-error-in-secrets-key-parsing.patch delete mode 100644 0077-tcurl-add-support-for-ssl-and-raw-output.patch delete mode 100644 0078-tcurl-test-refactor-so-new-options-can-be-added-more.patch delete mode 100644 0079-tcurl-test-add-support-for-raw-output.patch delete mode 100644 0080-tcurl-test-add-support-for-tls-settings.patch delete mode 100644 0081-tcurl-add-support-for-http-basic-auth.patch delete mode 100644 0082-tcurl-test-allow-to-set-custom-headers.patch delete mode 100644 0083-tcurl-test-add-support-for-client-certificate.patch delete mode 100644 0084-ci-do-not-build-secrets-on-rhel6.patch delete mode 100644 0085-build-make-curl-required-by-secrets.patch delete mode 100644 0086-secrets-use-tcurl-in-proxy-provider.patch delete mode 100644 0087-secrets-remove-http-parser-code-in-proxy-provider.patch delete mode 100644 0088-secrets-allow-to-configure-certificate-check.patch delete mode 100644 0089-secrets-support-HTTP-basic-authentication-with-proxy.patch delete mode 100644 0090-secrets-fix-debug-message.patch delete mode 100644 0091-secrets-always-add-Content-Length-header.patch delete mode 100644 0092-sss_iobuf-fix-read-shadows-a-global-declaration.patch delete mode 100644 0093-configure-fix-typo.patch delete mode 100644 0094-libsss_certmap-Accept-certificate-with-data-before-h.patch delete mode 100644 0095-BUILD-Fix-compilation-of-libsss_certmap-with-libcryp.patch delete mode 100644 0096-responders-do-not-leak-selinux-context-on-clients-de.patch delete mode 100644 0097-ipa_s2n_get_acct_info_send-provide-correct-req_input.patch delete mode 100644 0098-selinux-Do-not-fail-if-SELinux-is-not-managed.patch delete mode 100644 0099-DP-Fix-typo.patch delete mode 100644 0100-CONFDB-Fix-handling-of-enable_files_domain.patch delete mode 100644 0101-pam_test_client-add-service-and-environment-to-PAM-t.patch delete mode 100644 0102-pam_test_client-add-SSSD-getpwnam-lookup.patch delete mode 100644 0103-sss_sifp-update-method-names.patch delete mode 100644 0104-pam_test_client-add-InfoPipe-user-lookup.patch delete mode 100644 0105-sssctl-integrate-pam_test_client-into-sssctl.patch delete mode 100644 0106-i18n-adding-sssctl-files.patch delete mode 100644 0107-config-check-Message-when-sssd.conf-is-missing.patch delete mode 100644 0108-KRB5_LOCATOR-add-env-variable-to-disable-plugin.patch delete mode 100644 0109-sbus-check-connection-for-NULL-before-unregister-it.patch delete mode 100644 0110-UTIL-Use-max-15-characters-for-AD-host-UPN.patch delete mode 100644 0111-minor-typo-fixes.patch delete mode 100644 0112-SPEC-Drop-conditional-build-for-krb5_local_auth_plug.patch delete mode 100644 0114-Move-sized_output_name-and-sized_domain_name-into-re.patch delete mode 100644 0115-IFP-Use-sized_domain_name-to-format-the-groups-the-u.patch delete mode 100644 0116-SECRETS-remove-unused-variable.patch delete mode 100644 0117-IPA-Improve-DEBUG-message-if-a-group-has-no-ipaNTSec.patch delete mode 100644 0118-RESPONDER-Fallback-to-global-domain-resolution-order.patch delete mode 100644 0119-NSS-TESTS-Improve-non-fqnames-tests.patch delete mode 100644 0120-CACHE_REQ-Allow-configurationless-shortname-lookups.patch delete mode 100644 0121-CACHE_REQ_DOMAIN-Add-some-comments-to-cache_req_doma.patch delete mode 100644 0122-RESPONDER_COMMON-Improve-domaiN_resolution_order-deb.patch delete mode 100644 0123-CACHE_REQ_DOMAIN-debug-the-set-domain-resolution-ord.patch delete mode 100644 0124-LDAP-Allow-passing-a-NULL-map-to-sdap_search_bases_e.patch delete mode 100644 0125-IPA-Use-search-bases-instead-of-domain_to_basedn-whe.patch delete mode 100644 0126-CONFDB-Fix-standalone-application-domains.patch delete mode 100644 0127-utils-add-sss_domain_is_forest_root.patch delete mode 100644 0128-ad-handle-forest-root-not-listed-in-ad_enabled_domai.patch delete mode 100644 0129-overrides-add-certificates-to-mapped-attribute.patch delete mode 100644 0130-IPA-Improve-s2n-debug-message-for-missing-ipaNTSecur.patch delete mode 100644 0131-Use-correct-spelling-of-override.patch delete mode 100644 0132-cache_req-Avoid-bool-in-switch-case.patch delete mode 100644 0133-ssh-tools-The-ai-structure-is-not-an-array.patch delete mode 100644 0134-ssh-tools-Fix-issues-with-multiple-IP-addresses.patch delete mode 100644 0135-ssh-tools-Split-connect-and-communication-phases.patch delete mode 100644 0136-KCM-include-missing-header-file.patch create mode 100644 0501-libwbclient-sssd-update-interface-to-version-0.14.patch delete mode 100644 0510-BUILD-Disable-tests-with-expired-certificates.patch diff --git a/.gitignore b/.gitignore index 0a8663e..633f1d0 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ sssd-1.2.91.tar.gz /sssd-1.15.0.tar.gz /sssd-1.15.1.tar.gz /sssd-1.15.2.tar.gz +/sssd-1.15.3.tar.gz diff --git a/0001-Updating-the-version-for-the-1.15.3-release.patch b/0001-Updating-the-version-for-the-1.15.3-release.patch deleted file mode 100644 index 9e1cad2..0000000 --- a/0001-Updating-the-version-for-the-1.15.3-release.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 012ee7c3fe24a5e75d9b0465268c1bb8187b8337 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 15 Mar 2017 18:00:37 +0100 -Subject: [PATCH 01/97] Updating the version for the 1.15.3 release - ---- - version.m4 | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/version.m4 b/version.m4 -index 11e5e71b08b8af7c8d4f39410fea99d5d2ce3a00..da96ecd2e2d58e3e6079741f81a07f99259010b4 100644 ---- a/version.m4 -+++ b/version.m4 -@@ -1,5 +1,5 @@ - # Primary version number --m4_define([VERSION_NUMBER], [1.15.2]) -+m4_define([VERSION_NUMBER], [1.15.3]) - - # If the PRERELEASE_VERSION_NUMBER is set, we'll append - # it to the release tag when creating an RPM or SRPM --- -2.12.2 - diff --git a/0002-UTIL-Typo-in-comment.patch b/0002-UTIL-Typo-in-comment.patch deleted file mode 100644 index 9b7a05a..0000000 --- a/0002-UTIL-Typo-in-comment.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 6fb643c75e59e093c8c52def162ce1f1956430c7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20=C5=BDidek?= -Date: Tue, 14 Mar 2017 18:20:43 +0100 -Subject: [PATCH 02/97] UTIL: Typo in comment -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Lukáš Slebodník ---- - src/util/safe-format-string.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/util/safe-format-string.h b/src/util/safe-format-string.h -index 2f4796de7cea66d9ff0cd808e9e7c33de053feb8..fdebcf966554bcce150ed531173e991973698da0 100644 ---- a/src/util/safe-format-string.h -+++ b/src/util/safe-format-string.h -@@ -42,7 +42,7 @@ - * Features: - * - Only string 's' fields are supported - * - All the varargs should be strings, followed by a NULL argument -- * - Both positional '%$1s' and non-positional '%s' are supported -+ * - Both positional '%1$s' and non-positional '%s' are supported - * - Field widths '%8s' work as expected - * - Precision '%.8s' works, but precision cannot be read from a field - * - Left alignment flag is supported '%-8s'. --- -2.12.2 - diff --git a/0003-MAN-Mention-sssd-secrets-in-SEE-ALSO-section.patch b/0003-MAN-Mention-sssd-secrets-in-SEE-ALSO-section.patch deleted file mode 100644 index 0356627..0000000 --- a/0003-MAN-Mention-sssd-secrets-in-SEE-ALSO-section.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 3c071c4d6ec0d8f798eb862ebc4584123ff44663 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 21 Mar 2017 12:27:16 +0100 -Subject: [PATCH 03/97] MAN: Mention sssd-secrets in "SEE ALSO" section -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves: -https://pagure.io/SSSD/sssd/issue/3344 - -Reviewed-by: Fabiano Fidêncio ---- - src/man/include/seealso.xml | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/man/include/seealso.xml b/src/man/include/seealso.xml -index 25b421748fb19881552de8b6384af2c794063e11..2e9c646c475887bce3612472975ade375edbd819 100644 ---- a/src/man/include/seealso.xml -+++ b/src/man/include/seealso.xml -@@ -28,6 +28,12 @@ - 5 - , - -+ -+ -+ sssd-secrets -+ 5 -+ , -+ - - sss_cache8 - , --- -2.12.2 - diff --git a/0004-split_on_separator-move-to-a-separate-file.patch b/0004-split_on_separator-move-to-a-separate-file.patch deleted file mode 100644 index 40bbd86..0000000 --- a/0004-split_on_separator-move-to-a-separate-file.patch +++ /dev/null @@ -1,369 +0,0 @@ -From 843bc50c04afa6e4f4a4561d887bbbd5f7101ce1 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 8 Feb 2017 14:28:28 +0100 -Subject: [PATCH 04/97] split_on_separator: move to a separate file -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -To be able to include split_on_separator() without additional -dependencies (only talloc), it is moved into a separate file. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 30 ++++++++++--- - src/util/util.c | 93 ---------------------------------------- - src/util/util_ext.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 144 insertions(+), 100 deletions(-) - create mode 100644 src/util/util_ext.c - -diff --git a/Makefile.am b/Makefile.am -index 45b04de2638a745a189c0b4e5794ccd29913b10d..6dae4f2dd7f2dee501add82c7ab4f15fcbcc59ac 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -987,6 +987,7 @@ libsss_util_la_SOURCES = \ - src/sbus/sssd_dbus_common_signals.c \ - src/sbus/sssd_dbus_utils.c \ - src/util/util.c \ -+ src/util/util_ext.c \ - src/util/memory.c \ - src/util/safe-format-string.c \ - src/util/server.c \ -@@ -2355,19 +2356,23 @@ test_authtok_SOURCES = \ - src/tests/cmocka/test_authtok.c \ - src/util/authtok.c \ - src/util/authtok-utils.c \ -- src/util/util.c -+ src/util/util.c \ -+ src/util/util_ext.c \ -+ $(NULL) - test_authtok_CFLAGS = \ - $(AM_CFLAGS) \ - $(TALLOC_CFLAGS) \ - $(POPT_CFLAGS) \ -- $(DHASH_CFLAGS) -+ $(DHASH_CFLAGS) \ -+ $(NULL) - test_authtok_LDADD = \ - $(TALLOC_LIBS) \ - $(CMOCKA_LIBS) \ - $(DHASH_LIBS) \ - $(POPT_LIBS) \ - libsss_test_common.la \ -- libsss_debug.la -+ libsss_debug.la \ -+ $(NULL) - - sss_nss_idmap_tests_SOURCES = \ - src/tests/cmocka/sss_nss_idmap-tests.c -@@ -2839,6 +2844,7 @@ test_child_common_SOURCES = \ - src/util/atomic_io.c \ - src/util/util_errors.c \ - src/util/util.c \ -+ src/util/util_ext.c \ - $(NULL) - test_child_common_CFLAGS = \ - $(AM_CFLAGS) \ -@@ -3774,6 +3780,7 @@ krb5_child_SOURCES = \ - src/util/authtok.c \ - src/util/authtok-utils.c \ - src/util/util.c \ -+ src/util/util_ext.c \ - src/util/signal.c \ - src/util/strtonum.c \ - src/util/become_user.c \ -@@ -3807,6 +3814,7 @@ ldap_child_SOURCES = \ - src/util/authtok.c \ - src/util/authtok-utils.c \ - src/util/util.c \ -+ src/util/util_ext.c \ - src/util/signal.c \ - src/util/become_user.c \ - $(NULL) -@@ -3827,6 +3835,7 @@ selinux_child_SOURCES = \ - src/util/sss_semanage.c \ - src/util/atomic_io.c \ - src/util/util.c \ -+ src/util/util_ext.c \ - $(NULL) - selinux_child_CFLAGS = \ - $(AM_CFLAGS) \ -@@ -3845,6 +3854,7 @@ gpo_child_SOURCES = \ - src/providers/ad/ad_gpo_child.c \ - src/util/atomic_io.c \ - src/util/util.c \ -+ src/util/util_ext.c \ - src/util/signal.c - gpo_child_CFLAGS = \ - $(AM_CFLAGS) \ -@@ -3876,6 +3886,7 @@ p11_child_SOURCES = \ - src/p11_child/p11_child_nss.c \ - src/util/atomic_io.c \ - src/util/util.c \ -+ src/util/util_ext.c \ - $(NULL) - p11_child_CFLAGS = \ - $(AM_CFLAGS) \ -@@ -3893,16 +3904,21 @@ p11_child_LDADD = \ - - memberof_la_SOURCES = \ - src/ldb_modules/memberof.c \ -- src/util/util.c -+ src/util/util.c \ -+ src/util/util_ext.c \ -+ $(NULL) - memberof_la_CFLAGS = \ -- $(AM_CFLAGS) -+ $(AM_CFLAGS) \ -+ $(NULL) - memberof_la_LIBADD = \ - libsss_debug.la \ - $(LDB_LIBS) \ -- $(DHASH_LIBS) -+ $(DHASH_LIBS) \ -+ $(NULL) - memberof_la_LDFLAGS = \ - -avoid-version \ -- -module -+ -module \ -+ $(NULL) - - if BUILD_KRB5_LOCATOR_PLUGIN - sssd_krb5_locator_plugin_la_SOURCES = \ -diff --git a/src/util/util.c b/src/util/util.c -index a528f0c0249c33bfc3d3275250e74d5edcef2e6f..9d6202f695d516f20d648621da81a2d5e746daa5 100644 ---- a/src/util/util.c -+++ b/src/util/util.c -@@ -35,99 +35,6 @@ - int socket_activated = 0; - int dbus_activated = 0; - --int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, -- const char sep, bool trim, bool skip_empty, -- char ***_list, int *size) --{ -- int ret; -- const char *substr_end = str; -- const char *substr_begin = str; -- const char *sep_pos = NULL; -- size_t substr_len; -- char **list = NULL; -- int num_strings = 0; -- TALLOC_CTX *tmp_ctx = NULL; -- -- if (str == NULL || *str == '\0' || _list == NULL) { -- return EINVAL; -- } -- -- tmp_ctx = talloc_new(NULL); -- if (tmp_ctx == NULL) { -- return ENOMEM; -- } -- -- do { -- substr_len = 0; -- -- /* If this is not the first substring, then move from the separator. */ -- if (sep_pos != NULL) { -- substr_end = sep_pos + 1; -- substr_begin = sep_pos + 1; -- } -- -- /* Find end of the first substring */ -- while (*substr_end != sep && *substr_end != '\0') { -- substr_end++; -- substr_len++; -- } -- -- sep_pos = substr_end; -- -- if (trim) { -- /* Trim leading whitespace */ -- while (isspace(*substr_begin) && substr_begin < substr_end) { -- substr_begin++; -- substr_len--; -- } -- -- /* Trim trailing whitespace */ -- while (substr_end - 1 > substr_begin && isspace(*(substr_end-1))) { -- substr_end--; -- substr_len--; -- } -- } -- -- /* Copy the substring to the output list of strings */ -- if (skip_empty == false || substr_len > 0) { -- list = talloc_realloc(tmp_ctx, list, char*, num_strings + 2); -- if (list == NULL) { -- ret = ENOMEM; -- goto done; -- } -- -- /* empty string is stored for substr_len == 0 */ -- list[num_strings] = talloc_strndup(list, substr_begin, substr_len); -- if (list[num_strings] == NULL) { -- ret = ENOMEM; -- goto done; -- } -- num_strings++; -- } -- -- } while (*sep_pos != '\0'); -- -- if (list == NULL) { -- /* No allocations were done, make space for the NULL */ -- list = talloc(tmp_ctx, char *); -- if (list == NULL) { -- ret = ENOMEM; -- goto done; -- } -- } -- list[num_strings] = NULL; -- -- if (size) { -- *size = num_strings; -- } -- -- *_list = talloc_steal(mem_ctx, list); -- ret = EOK; --done: -- talloc_free(tmp_ctx); -- return ret; --} -- - static void free_args(char **args) - { - int i; -diff --git a/src/util/util_ext.c b/src/util/util_ext.c -new file mode 100644 -index 0000000000000000000000000000000000000000..fceb8c873a26471d476b39d5d4e567c445ed8d0b ---- /dev/null -+++ b/src/util/util_ext.c -@@ -0,0 +1,121 @@ -+/* -+ SSSD helper calls - can be used by libraries for external use as well -+ -+ Authors: -+ Simo Sorce -+ -+ Copyright (C) 2017 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 -+#include -+#include -+#include -+ -+#define EOK 0 -+ -+int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, -+ const char sep, bool trim, bool skip_empty, -+ char ***_list, int *size) -+{ -+ int ret; -+ const char *substr_end = str; -+ const char *substr_begin = str; -+ const char *sep_pos = NULL; -+ size_t substr_len; -+ char **list = NULL; -+ int num_strings = 0; -+ TALLOC_CTX *tmp_ctx = NULL; -+ -+ if (str == NULL || *str == '\0' || _list == NULL) { -+ return EINVAL; -+ } -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ do { -+ substr_len = 0; -+ -+ /* If this is not the first substring, then move from the separator. */ -+ if (sep_pos != NULL) { -+ substr_end = sep_pos + 1; -+ substr_begin = sep_pos + 1; -+ } -+ -+ /* Find end of the first substring */ -+ while (*substr_end != sep && *substr_end != '\0') { -+ substr_end++; -+ substr_len++; -+ } -+ -+ sep_pos = substr_end; -+ -+ if (trim) { -+ /* Trim leading whitespace */ -+ while (isspace(*substr_begin) && substr_begin < substr_end) { -+ substr_begin++; -+ substr_len--; -+ } -+ -+ /* Trim trailing whitespace */ -+ while (substr_end - 1 > substr_begin && isspace(*(substr_end-1))) { -+ substr_end--; -+ substr_len--; -+ } -+ } -+ -+ /* Copy the substring to the output list of strings */ -+ if (skip_empty == false || substr_len > 0) { -+ list = talloc_realloc(tmp_ctx, list, char*, num_strings + 2); -+ if (list == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* empty string is stored for substr_len == 0 */ -+ list[num_strings] = talloc_strndup(list, substr_begin, substr_len); -+ if (list[num_strings] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ num_strings++; -+ } -+ -+ } while (*sep_pos != '\0'); -+ -+ if (list == NULL) { -+ /* No allocations were done, make space for the NULL */ -+ list = talloc(tmp_ctx, char *); -+ if (list == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ list[num_strings] = NULL; -+ -+ if (size) { -+ *size = num_strings; -+ } -+ -+ *_list = talloc_steal(mem_ctx, list); -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} --- -2.12.2 - diff --git a/0005-util-move-string_in_list-to-util_ext.patch b/0005-util-move-string_in_list-to-util_ext.patch deleted file mode 100644 index f03e716..0000000 --- a/0005-util-move-string_in_list-to-util_ext.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 8b7548f65a0d812a47d26895671ec6f01b6813c1 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 20 Feb 2017 17:28:51 +0100 -Subject: [PATCH 05/97] util: move string_in_list to util_ext -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -To be able to include string_in_list() without additional -dependencies it is moved into a separate file. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - src/util/util.c | 20 -------------------- - src/util/util_ext.c | 22 ++++++++++++++++++++++ - 2 files changed, 22 insertions(+), 20 deletions(-) - -diff --git a/src/util/util.c b/src/util/util.c -index 9d6202f695d516f20d648621da81a2d5e746daa5..f0e8f9dd6a4bceed6befb74c57aa066b19a72bb7 100644 ---- a/src/util/util.c -+++ b/src/util/util.c -@@ -617,26 +617,6 @@ errno_t add_string_to_list(TALLOC_CTX *mem_ctx, const char *string, - return EOK; - } - --bool string_in_list(const char *string, char **list, bool case_sensitive) --{ -- size_t c; -- int(*compare)(const char *s1, const char *s2); -- -- if (string == NULL || list == NULL || *list == NULL) { -- return false; -- } -- -- compare = case_sensitive ? strcmp : strcasecmp; -- -- for (c = 0; list[c] != NULL; c++) { -- if (compare(string, list[c]) == 0) { -- return true; -- } -- } -- -- return false; --} -- - void safezero(void *data, size_t size) - { - volatile uint8_t *p = data; -diff --git a/src/util/util_ext.c b/src/util/util_ext.c -index fceb8c873a26471d476b39d5d4e567c445ed8d0b..04dc02a8adf32bd0590fe6eba230658e67d0a362 100644 ---- a/src/util/util_ext.c -+++ b/src/util/util_ext.c -@@ -24,6 +24,8 @@ - #include - #include - #include -+#include -+#include - - #define EOK 0 - -@@ -119,3 +121,23 @@ done: - talloc_free(tmp_ctx); - return ret; - } -+ -+bool string_in_list(const char *string, char **list, bool case_sensitive) -+{ -+ size_t c; -+ int(*compare)(const char *s1, const char *s2); -+ -+ if (string == NULL || list == NULL || *list == NULL) { -+ return false; -+ } -+ -+ compare = case_sensitive ? strcmp : strcasecmp; -+ -+ for (c = 0; list[c] != NULL; c++) { -+ if (compare(string, list[c]) == 0) { -+ return true; -+ } -+ } -+ -+ return false; -+} --- -2.12.2 - diff --git a/0006-certmap-add-new-library-libsss_certmap.patch b/0006-certmap-add-new-library-libsss_certmap.patch deleted file mode 100644 index edebb9d..0000000 --- a/0006-certmap-add-new-library-libsss_certmap.patch +++ /dev/null @@ -1,5787 +0,0 @@ -From db36dca3d45e6eefbb30042ee65876566f1a6014 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 2 Feb 2017 11:24:02 +0100 -Subject: [PATCH 06/97] certmap: add new library libsss_certmap -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With this library it would be possible to map certificates and users not -only by adding the full certificate to the user's LDAP object but by -adding e.g. only parts like the issuer and subject name. Additionally -the library is also able to flexible select/match certificates based on -values in the certificate. - -Details about mapping and matching rules can be found in the included -man page. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 55 ++ - configure.ac | 1 + - contrib/sssd.spec.in | 32 + - src/lib/certmap/sss_cert_content_nss.c | 1014 +++++++++++++++++++ - src/lib/certmap/sss_certmap.c | 993 +++++++++++++++++++ - src/lib/certmap/sss_certmap.doxy.in | 3 + - src/lib/certmap/sss_certmap.exports | 13 + - src/lib/certmap/sss_certmap.h | 155 +++ - src/lib/certmap/sss_certmap.pc.in | 11 + - src/lib/certmap/sss_certmap_attr_names.c | 107 +++ - src/lib/certmap/sss_certmap_int.h | 187 ++++ - src/lib/certmap/sss_certmap_krb5_match.c | 558 +++++++++++ - src/lib/certmap/sss_certmap_ldap_mapping.c | 367 +++++++ - src/man/Makefile.am | 2 +- - src/man/po/po4a.cfg | 1 + - src/man/sss-certmap.5.xml | 600 ++++++++++++ - src/tests/cmocka/test_certmap.c | 1443 ++++++++++++++++++++++++++++ - src/tests/dlopen-tests.c | 1 + - 18 files changed, 5542 insertions(+), 1 deletion(-) - create mode 100644 src/lib/certmap/sss_cert_content_nss.c - create mode 100644 src/lib/certmap/sss_certmap.c - create mode 100644 src/lib/certmap/sss_certmap.doxy.in - create mode 100644 src/lib/certmap/sss_certmap.exports - create mode 100644 src/lib/certmap/sss_certmap.h - create mode 100644 src/lib/certmap/sss_certmap.pc.in - create mode 100644 src/lib/certmap/sss_certmap_attr_names.c - create mode 100644 src/lib/certmap/sss_certmap_int.h - create mode 100644 src/lib/certmap/sss_certmap_krb5_match.c - create mode 100644 src/lib/certmap/sss_certmap_ldap_mapping.c - create mode 100644 src/man/sss-certmap.5.xml - create mode 100644 src/tests/cmocka/test_certmap.c - -diff --git a/Makefile.am b/Makefile.am -index 6dae4f2dd7f2dee501add82c7ab4f15fcbcc59ac..8ca12c10d2713b6a72361d84b25486500c79f407 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -278,6 +278,7 @@ if HAVE_CMOCKA - simple-access-tests \ - krb5_common_test \ - test_iobuf \ -+ sss_certmap_test \ - $(NULL) - - if HAVE_LIBRESOLV -@@ -1074,6 +1075,7 @@ SSSD_INTERNAL_LTLIBS = \ - lib_LTLIBRARIES = libipa_hbac.la \ - libsss_idmap.la \ - libsss_nss_idmap.la \ -+ libsss_certmap.la \ - $(NULL) - - pkgconfig_DATA += src/lib/ipa_hbac/ipa_hbac.pc -@@ -1128,6 +1130,7 @@ include_HEADERS = \ - src/lib/ipa_hbac/ipa_hbac.h \ - src/lib/idmap/sss_idmap.h \ - src/sss_client/idmap/sss_nss_idmap.h \ -+ src/lib/certmap/sss_certmap.h \ - $(NULL) - - if BUILD_LIBWBCLIENT -@@ -1712,6 +1715,38 @@ sssd_check_socket_activated_responders_LDADD = \ - $(NULL) - endif - -+if HAVE_NSS -+pkgconfig_DATA += src/lib/certmap/sss_certmap.pc -+libsss_certmap_la_DEPENDENCIES = src/lib/certmap/sss_certmap.exports -+libsss_certmap_la_SOURCES = \ -+ src/lib/certmap/sss_certmap.c \ -+ src/lib/certmap/sss_certmap_attr_names.c \ -+ src/lib/certmap/sss_cert_content_nss.c \ -+ src/lib/certmap/sss_certmap_krb5_match.c \ -+ src/lib/certmap/sss_certmap_ldap_mapping.c \ -+ src/util/util_ext.c \ -+ src/util/cert/cert_common.c \ -+ src/util/crypto/nss/nss_base64.c \ -+ src/util/cert/nss/cert.c \ -+ src/util/crypto/nss/nss_util.c \ -+ $(NULL) -+libsss_certmap_la_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(TALLOC_CFLAGS) \ -+ $(NSS_CFLAGS) \ -+ $(NULL) -+libsss_certmap_la_LIBADD = \ -+ $(TALLOC_LIBS) \ -+ $(NSS_LIBS) \ -+ $(NULL) -+libsss_certmap_la_LDFLAGS = \ -+ -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \ -+ -version-info 0:0:0 -+ -+dist_noinst_DATA += src/lib/certmap/sss_certmap.exports -+dist_noinst_HEADERS += src/lib/certmap/sss_certmap_int.h -+endif -+ - ################# - # Feature Tests # - ################# -@@ -3245,6 +3280,25 @@ test_inotify_LDADD = \ - libsss_test_common.la \ - $(NULL) - -+if HAVE_NSS -+sss_certmap_test_SOURCES = \ -+ src/tests/cmocka/test_certmap.c \ -+ src/lib/certmap/sss_certmap_attr_names.c \ -+ $(NULL) -+sss_certmap_test_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(NSS_CFLAGS) \ -+ $(NULL) -+sss_certmap_test_LDADD = \ -+ $(CMOCKA_LIBS) \ -+ $(POPT_LIBS) \ -+ $(TALLOC_LIBS) \ -+ $(NSS_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_test_common.la \ -+ libsss_certmap.la \ -+ $(NULL) -+endif - endif # HAVE_CMOCKA - - noinst_PROGRAMS = pam_test_client -@@ -4404,6 +4458,7 @@ docs: - $(DOXYGEN) src/lib/ipa_hbac/ipa_hbac.doxy - $(DOXYGEN) src/lib/idmap/sss_idmap.doxy - $(DOXYGEN) src/sss_client/idmap/sss_nss_idmap.doxy -+ $(DOXYGEN) src/lib/certmap/sss_certmap.doxy - if BUILD_IFP - $(DOXYGEN) src/lib/sifp/sss_simpleifp.doxy - endif -diff --git a/configure.ac b/configure.ac -index e6a3b4e857bcbec16873f54008e6b42aeb9b7cd7..dd1012015a5fea9f25e5b5199b4868fbc0bc14c4 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -483,6 +483,7 @@ AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/doxy.config - src/tests/intg/Makefile - src/lib/ipa_hbac/ipa_hbac.pc src/lib/ipa_hbac/ipa_hbac.doxy - src/lib/idmap/sss_idmap.pc src/lib/idmap/sss_idmap.doxy -+ src/lib/certmap/sss_certmap.pc src/lib/certmap/sss_certmap.doxy - src/sss_client/idmap/sss_nss_idmap.pc - src/sss_client/idmap/sss_nss_idmap.doxy - src/sss_client/libwbclient/wbclient_sssd.pc -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 5bd2beb89014ba7c86b4231f0357a7a6e10a18a8..28ebe07a26a3112210b092b7831e7f6aae061c8d 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -658,6 +658,25 @@ The libnfsidmap sssd module provides a way for rpc.idmapd to call SSSD to map - UIDs/GIDs to names and vice versa. It can be also used for mapping principal - (user) name to IDs(UID or GID) or to obtain groups which user are member of. - -+%package -n libsss_certmap -+Summary: SSSD Certficate Mapping Library -+Group: Development/Libraries -+License: LGPLv3+ -+Requires(post): /sbin/ldconfig -+Requires(postun): /sbin/ldconfig -+ -+%description -n libsss_certmap -+Library to map certificates to users based on rules -+ -+%package -n libsss_certmap-devel -+Summary: SSSD Certficate Mapping Library -+Group: Development/Libraries -+License: LGPLv3+ -+Requires: libsss_certmap = %{version}-%{release} -+ -+%description -n libsss_certmap-devel -+Library to map certificates to users based on rules -+ - %prep - %setup -q -n %{name}-%{version} - -@@ -888,6 +907,7 @@ done - %{_datadir}/sssd/sssd.api.d - %{_mandir}/man1/sss_ssh_authorizedkeys.1* - %{_mandir}/man1/sss_ssh_knownhostsproxy.1* -+%{_mandir}/man5/sss-certmap.5* - %{_mandir}/man5/sssd.conf.5* - %{_mandir}/man5/sssd-simple.5* - %{_mandir}/man5/sssd-sudo.5* -@@ -1146,6 +1166,18 @@ done - %files nfs-idmap - %{_libdir}/libnfsidmap/sss.so - -+%files -n libsss_certmap -+%defattr(-,root,root,-) -+%doc src/sss_client/COPYING src/sss_client/COPYING.LESSER -+%{_libdir}/libsss_certmap.so.* -+ -+%files -n libsss_certmap-devel -+%defattr(-,root,root,-) -+%doc certmap_doc/html -+%{_includedir}/sss_certmap.h -+%{_libdir}/libsss_certmap.so -+%{_libdir}/pkgconfig/sss_certmap.pc -+ - %pre common - getent group sssd >/dev/null || groupadd -r sssd - getent passwd sssd >/dev/null || useradd -r -g sssd -d / -s /sbin/nologin -c "User for sssd" sssd -diff --git a/src/lib/certmap/sss_cert_content_nss.c b/src/lib/certmap/sss_cert_content_nss.c -new file mode 100644 -index 0000000000000000000000000000000000000000..d3182895465706c87503b8abb0cea49b7677625d ---- /dev/null -+++ b/src/lib/certmap/sss_cert_content_nss.c -@@ -0,0 +1,1014 @@ -+/* -+ SSSD - certificate handling utils - NSS version -+ The calls defined here should be useable outside of SSSD as well, e.g. in -+ libsss_certmap. -+ -+ Copyright (C) Sumit Bose 2017 -+ -+ 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "util/crypto/sss_crypto.h" -+#include "util/crypto/nss/nss_util.h" -+#include "util/cert.h" -+#include "lib/certmap/sss_certmap.h" -+#include "lib/certmap/sss_certmap_int.h" -+ -+ -+/* The following two functions are copied from NSS's lib/certdb/secname.c -+ * becasue CERT_AddAVA is not exported. I just renamed it and made it static -+ * to avoid issues if the call gets exported some time in future. */ -+ -+static void ** -+AddToArray(PLArenaPool *arena, void **array, void *element) -+{ -+ unsigned count; -+ void **ap; -+ -+ /* Count up number of slots already in use in the array */ -+ count = 0; -+ ap = array; -+ if (ap) { -+ while (*ap++) { -+ count++; -+ } -+ } -+ -+ if (array) { -+ array = (void**) PORT_ArenaGrow(arena, array, -+ (count + 1) * sizeof(void *), -+ (count + 2) * sizeof(void *)); -+ } else { -+ array = (void**) PORT_ArenaAlloc(arena, (count + 2) * sizeof(void *)); -+ } -+ if (array) { -+ array[count] = element; -+ array[count+1] = 0; -+ } -+ return array; -+} -+ -+ -+static SECStatus -+sss_CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava) -+{ -+ rdn->avas = (CERTAVA**) AddToArray(arena, (void**) rdn->avas, ava); -+ return rdn->avas ? SECSuccess : SECFailure; -+} -+ -+static SECItem * -+cert_get_ext_by_tag(CERTCertificate *cert, SECOidTag tag) -+{ -+ SECOidData *oid; -+ int i; -+ -+ oid = SECOID_FindOIDByTag(tag); -+ for (i = 0; -+ (cert->extensions != NULL) && (cert->extensions[i] != NULL); -+ i++) -+ if (SECITEM_ItemsAreEqual(&cert->extensions[i]->id, &oid->oid)) -+ return &cert->extensions[i]->value; -+ return NULL; -+} -+ -+static int get_extended_key_usage_oids(TALLOC_CTX *mem_ctx, -+ CERTCertificate *cert, -+ const char ***_oids) -+{ -+ PLArenaPool *pool; -+ SECItem *ext; -+ SECItem **oids = NULL; -+ const char **oids_list = NULL; -+ size_t c; -+ SECStatus rv; -+ char *tmp_str; -+ int ret; -+ -+ pool = PORT_NewArena(sizeof(double)); -+ ext = cert_get_ext_by_tag(cert, SEC_OID_X509_EXT_KEY_USAGE); -+ if (ext != NULL) { -+ rv = SEC_ASN1DecodeItem(pool, &oids, -+ SEC_ASN1_GET(SEC_SequenceOfObjectIDTemplate), -+ ext); -+ if (rv != SECSuccess) { -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ for (c = 0; (oids != NULL && oids[c] != NULL); c++); -+ oids_list = talloc_zero_array(mem_ctx, const char *, c + 1); -+ if (oids_list == NULL) { -+ return ENOMEM; -+ } -+ -+ for (c = 0; (oids != NULL && oids[c] != NULL); c++) { -+ tmp_str = CERT_GetOidString(oids[c]); -+ /* is it expexted that NSS OID strings start with "OID." but we -+ * prefer the plain dotted-decimal version so the prefix is skipped */ -+ if (tmp_str == NULL || strncmp(tmp_str, "OID.", 4) != 0) { -+ PR_smprintf_free(tmp_str); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ oids_list[c] = talloc_strdup(oids_list, tmp_str + 4); -+ PR_smprintf_free(tmp_str); -+ if(oids_list[c] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ ret = 0; -+ -+done: -+ PORT_FreeArena(pool, PR_TRUE); -+ if (ret == 0) { -+ *_oids = oids_list; -+ } else { -+ talloc_free(oids_list); -+ } -+ -+ return ret; -+ -+} -+ -+static int get_rdn_str(TALLOC_CTX *mem_ctx, CERTAVA **avas, -+ const char **rdn_str) -+{ -+ size_t c; -+ char *tmp_name = NULL; -+ const char *tmp_str = NULL; -+ int ret; -+ SECStatus rv; -+ CERTRDN rdn = { 0 }; -+ CERTName *name = NULL; -+ PLArenaPool *arena = NULL; -+ -+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); -+ if (arena == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ -+ /* Multiple AVAs should be avoided becasue there is no general ordering -+ * rule and the RDN strings are not reproducible */ -+ for (c = 0; avas[c] != NULL; c++) { -+ rv = sss_CERT_AddAVA(arena, &rdn, avas[c]); -+ if (rv != SECSuccess) { -+ ret = EIO; -+ goto done; -+ } -+ } -+ -+ name = CERT_CreateName(&rdn, NULL); -+ if (name == NULL) { -+ ret = EIO; -+ goto done; -+ } -+ -+ tmp_name = CERT_NameToAscii(name); -+ CERT_DestroyName(name); -+ if (tmp_name == NULL) { -+ ret = EIO; -+ goto done; -+ } -+ -+ tmp_str = talloc_strdup(mem_ctx, tmp_name); -+ PORT_Free(tmp_name); -+ if (tmp_str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *rdn_str = tmp_str; -+ } else { -+ talloc_free(discard_const(tmp_str)); -+ } -+ PORT_FreeArena(arena, PR_FALSE); -+ -+ return ret; -+} -+ -+static int get_rdn_list(TALLOC_CTX *mem_ctx, CERTRDN **rdns, -+ const char ***rdn_list) -+{ -+ int ret; -+ size_t c; -+ const char **list = NULL; -+ -+ for (c = 0; rdns[c] != NULL; c++); -+ list = talloc_zero_array(mem_ctx, const char *, c + 1); -+ if (list == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ for (c = 0; rdns[c] != NULL; c++) { -+ ret = get_rdn_str(list, rdns[c]->avas, -+ &(list[c])); -+ if (ret != 0) { -+ goto done; -+ } -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *rdn_list = list; -+ } else { -+ talloc_free(list); -+ } -+ -+ return ret; -+} -+ -+enum san_opt nss_name_type_to_san_opt(CERTGeneralNameType type) -+{ -+ switch (type) { -+ case certOtherName: -+ return SAN_OTHER_NAME; -+ case certRFC822Name: -+ return SAN_RFC822_NAME; -+ case certDNSName: -+ return SAN_DNS_NAME; -+ case certX400Address: -+ return SAN_X400_ADDRESS; -+ case certDirectoryName: -+ return SAN_DIRECTORY_NAME; -+ case certEDIPartyName: -+ return SAN_EDIPART_NAME; -+ case certURI: -+ return SAN_URI; -+ case certIPAddress: -+ return SAN_IP_ADDRESS; -+ case certRegisterID: -+ return SAN_REGISTERED_ID; -+ default: -+ return SAN_INVALID; -+ } -+} -+ -+static int add_to_san_list(TALLOC_CTX *mem_ctx, bool is_bin, -+ enum san_opt san_opt, uint8_t *data, size_t len, -+ struct san_list **item) -+{ -+ struct san_list *i; -+ -+ if (data == NULL || len == 0 || san_opt == SAN_INVALID) { -+ return EINVAL; -+ } -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ return ENOMEM; -+ } -+ -+ i->san_opt = san_opt; -+ if (is_bin) { -+ i->bin_val = talloc_memdup(i, data, len); -+ i->bin_val_len = len; -+ } else { -+ i->val = talloc_strndup(i, (char *) data, len); -+ } -+ if (i->val == NULL) { -+ talloc_free(i); -+ return ENOMEM; -+ } -+ -+ *item = i; -+ -+ return 0; -+} -+ -+/* taken from pkinit_crypto_nss.c of MIT Kerberos */ -+/* KerberosString: RFC 4120, 5.2.1. */ -+static const SEC_ASN1Template kerberos_string_template[] = { -+ { -+ SEC_ASN1_GENERAL_STRING, -+ 0, -+ NULL, -+ sizeof(SECItem), -+ } -+}; -+ -+/* Realm: RFC 4120, 5.2.2. */ -+struct realm { -+ SECItem name; -+}; -+static const SEC_ASN1Template realm_template[] = { -+ { -+ SEC_ASN1_GENERAL_STRING, -+ 0, -+ NULL, -+ sizeof(SECItem), -+ } -+}; -+ -+/* PrincipalName: RFC 4120, 5.2.2. */ -+static const SEC_ASN1Template sequence_of_kerberos_string_template[] = { -+ { -+ SEC_ASN1_SEQUENCE_OF, -+ 0, -+ &kerberos_string_template, -+ 0, -+ } -+}; -+ -+struct principal_name { -+ SECItem name_type; -+ SECItem **name_string; -+}; -+static const SEC_ASN1Template principal_name_template[] = { -+ { -+ SEC_ASN1_SEQUENCE, -+ 0, -+ NULL, -+ sizeof(struct principal_name), -+ }, -+ { -+ SEC_ASN1_CONTEXT_SPECIFIC | 0 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT, -+ offsetof(struct principal_name, name_type), -+ &SEC_IntegerTemplate, -+ sizeof(SECItem), -+ }, -+ { -+ SEC_ASN1_CONTEXT_SPECIFIC | 1 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT, -+ offsetof(struct principal_name, name_string), -+ sequence_of_kerberos_string_template, -+ sizeof(struct SECItem **), -+ }, -+ {0, 0, NULL, 0}, -+}; -+ -+/* KRB5PrincipalName: RFC 4556, 3.2.2. */ -+struct kerberos_principal_name { -+ SECItem realm; -+ struct principal_name principal_name; -+}; -+static const SEC_ASN1Template kerberos_principal_name_template[] = { -+ { -+ SEC_ASN1_SEQUENCE, -+ 0, -+ NULL, -+ sizeof(struct kerberos_principal_name), -+ }, -+ { -+ SEC_ASN1_CONTEXT_SPECIFIC | 0 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT, -+ offsetof(struct kerberos_principal_name, realm), -+ &realm_template, -+ sizeof(struct realm), -+ }, -+ { -+ SEC_ASN1_CONTEXT_SPECIFIC | 1 | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT, -+ offsetof(struct kerberos_principal_name, principal_name), -+ &principal_name_template, -+ sizeof(struct principal_name), -+ }, -+ {0, 0, NULL, 0} -+}; -+ -+#define PKINIT_OID "1.3.6.1.5.2.2" -+#define NT_PRINCIPAL_OID "1.3.6.1.4.1.311.20.2.3" -+ -+static int add_string_other_name_to_san_list(TALLOC_CTX *mem_ctx, -+ enum san_opt san_opt, -+ CERTGeneralName *current, -+ struct san_list **item) -+{ -+ struct san_list *i = NULL; -+ int ret; -+ char *tmp_str; -+ -+ tmp_str = CERT_GetOidString(&(current->name.OthName.oid)); -+ /* is it expexted that NSS OID strings start with "OID." but we -+ * prefer the plain dotted-decimal version so the prefix is skipped */ -+ if (tmp_str == NULL || strncmp(tmp_str, "OID.", 4) != 0) { -+ PR_smprintf_free(tmp_str); -+ return EINVAL; -+ } -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ PR_smprintf_free(tmp_str); -+ return ENOMEM; -+ } -+ i->san_opt = san_opt; -+ -+ i->other_name_oid = talloc_strdup(i, tmp_str + 4); -+ PR_smprintf_free(tmp_str); -+ if (i->other_name_oid == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ i->bin_val = talloc_memdup(i, current->name.OthName.name.data, -+ current->name.OthName.name.len); -+ if (i->bin_val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ i->bin_val_len = current->name.OthName.name.len; -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *item = i; -+ } else { -+ talloc_free(i); -+ } -+ -+ return ret; -+} -+ -+static int get_short_name(TALLOC_CTX *mem_ctx, const char *full_name, -+ char delim, char **short_name) -+{ -+ char *at; -+ char *s; -+ -+ if (full_name == NULL || delim == '\0' || short_name == NULL) { -+ return EINVAL; -+ } -+ -+ at = strchr(full_name, delim); -+ if (at != NULL) { -+ s = talloc_strndup(mem_ctx, full_name, (at - full_name)); -+ } else { -+ s = talloc_strdup(mem_ctx, full_name); -+ } -+ if (s == NULL) { -+ return ENOMEM; -+ } -+ -+ *short_name = s; -+ -+ return 0; -+} -+ -+static int add_nt_princ_to_san_list(TALLOC_CTX *mem_ctx, -+ PLArenaPool *pool, -+ enum san_opt san_opt, -+ CERTGeneralName *current, -+ struct san_list **item) -+{ -+ struct san_list *i = NULL; -+ SECStatus rv; -+ SECItem tmp_secitem = { 0 }; -+ int ret; -+ -+ rv = SEC_ASN1DecodeItem(pool, &tmp_secitem, -+ SEC_ASN1_GET(SEC_UTF8StringTemplate), -+ &(current->name.OthName.name)); -+ if (rv != SECSuccess) { -+ return EINVAL; -+ } -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ return ENOMEM; -+ } -+ i->san_opt = san_opt; -+ -+ i->val = talloc_strndup(i, (char *) tmp_secitem.data, -+ tmp_secitem.len); -+ if (i->val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = get_short_name(i, i->val, '@', &(i->short_name)); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *item = i; -+ } else { -+ talloc_free(i); -+ } -+ -+ return ret; -+} -+ -+static int add_pkinit_princ_to_san_list(TALLOC_CTX *mem_ctx, -+ PLArenaPool *pool, -+ enum san_opt san_opt, -+ CERTGeneralName *current, -+ struct san_list **item) -+{ -+ struct san_list *i = NULL; -+ SECStatus rv; -+ struct kerberos_principal_name kname; -+ int ret; -+ size_t c; -+ -+ rv = SEC_ASN1DecodeItem(pool, &kname, -+ kerberos_principal_name_template, -+ &(current->name.OthName.name)); -+ if (rv != SECSuccess) { -+ return EINVAL; -+ } -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ return ENOMEM; -+ } -+ i->san_opt = san_opt; -+ -+ if (kname.principal_name.name_string != NULL) { -+ i->val = talloc_strdup(i, ""); -+ if (i->val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ for (c = 0; kname.principal_name.name_string[c] != NULL; c++) { -+ if (c > 0) { -+ i->val = talloc_strdup_append(i->val, "/"); -+ if (i->val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ i->val = talloc_strndup_append(i->val, -+ (char *) kname.principal_name.name_string[c]->data, -+ kname.principal_name.name_string[c]->len); -+ if (i->val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ i->val = talloc_strndup_append(i->val, -+ (char *) kname.realm.data, -+ kname.realm.len); -+ if (i->val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = get_short_name(i, i->val, '@', &(i->short_name)); -+ if (ret != 0) { -+ goto done; -+ } -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *item = i; -+ } else { -+ talloc_free(i); -+ } -+ -+ return ret; -+} -+ -+static int add_oid_to_san_list(TALLOC_CTX *mem_ctx, -+ enum san_opt san_opt, -+ SECItem oid, -+ struct san_list **item) -+{ -+ struct san_list *i = NULL; -+ char *tmp_str; -+ -+ tmp_str = CERT_GetOidString(&oid); -+ /* is it expexted that NSS OID strings start with "OID." but we -+ * prefer the plain dotted-decimal version so the prefix is skipped */ -+ if (tmp_str == NULL || strncmp(tmp_str, "OID.", 4) != 0) { -+ PR_smprintf_free(tmp_str); -+ return EINVAL; -+ } -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ PR_smprintf_free(tmp_str); -+ return ENOMEM; -+ } -+ i->san_opt = san_opt; -+ -+ i->val = talloc_strdup(i, tmp_str + 4); -+ PR_smprintf_free(tmp_str); -+ if (i->val == NULL) { -+ talloc_free(i); -+ return ENOMEM; -+ } -+ -+ *item = i; -+ return 0; -+} -+ -+static int add_rdn_list_to_san_list(TALLOC_CTX *mem_ctx, -+ enum san_opt san_opt, -+ CERTName name, -+ struct san_list **item) -+{ -+ struct san_list *i = NULL; -+ int ret; -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ return ENOMEM; -+ } -+ i->san_opt = san_opt; -+ -+ ret = get_rdn_list(i, name.rdns, &(i->rdn_list)); -+ if (ret != 0) { -+ talloc_free(i); -+ return ret; -+ } -+ -+ *item = i; -+ return 0; -+} -+ -+static int add_ip_to_san_list(TALLOC_CTX *mem_ctx, enum san_opt san_opt, -+ uint8_t *data, size_t len, -+ struct san_list **item) -+{ -+ struct san_list *i; -+ PRStatus st; -+ PRNetAddr addr; -+ char addrBuf[80]; -+ -+ if (data == NULL || len == 0 || san_opt == SAN_INVALID) { -+ return EINVAL; -+ } -+ -+ /* taken from secu_PrintIPAddress() */ -+ memset(&addr, 0, sizeof addr); -+ if (len == 4) { -+ addr.inet.family = PR_AF_INET; -+ memcpy(&addr.inet.ip, data, len); -+ } else if (len == 16) { -+ addr.ipv6.family = PR_AF_INET6; -+ memcpy(addr.ipv6.ip.pr_s6_addr, data, len); -+ if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) { -+ /* convert to IPv4. */ -+ addr.inet.family = PR_AF_INET; -+ memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4); -+ memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad); -+ } -+ } else { -+ return EINVAL; -+ } -+ -+ st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf); -+ if (st != PR_SUCCESS) { -+ return EIO; -+ } -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ return ENOMEM; -+ } -+ -+ i->san_opt = san_opt; -+ i->val = talloc_strdup(i, addrBuf); -+ if (i->val == NULL) { -+ talloc_free(i); -+ return ENOMEM; -+ } -+ -+ *item = i; -+ return 0; -+} -+static int add_principal_to_san_list(TALLOC_CTX *mem_ctx, -+ enum san_opt san_opt, -+ const char *princ, -+ struct san_list **item) -+{ -+ struct san_list *i = NULL; -+ int ret; -+ -+ i = talloc_zero(mem_ctx, struct san_list); -+ if (i == NULL) { -+ return ENOMEM; -+ } -+ i->san_opt = san_opt; -+ -+ i->val = talloc_strdup(i, princ); -+ if (i->val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = get_short_name(i, i->val, '@', &(i->short_name)); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *item = i; -+ } else { -+ talloc_free(i); -+ } -+ -+ return ret; -+} -+ -+static int get_san(TALLOC_CTX *mem_ctx, CERTCertificate *cert, -+ struct san_list **san_list) -+{ -+ -+ SECItem subAltName = { 0 }; -+ SECStatus rv; -+ CERTGeneralName *name_list = NULL; -+ CERTGeneralName *current; -+ PLArenaPool *pool = NULL; -+ int ret; -+ struct san_list *list = NULL; -+ struct san_list *item = NULL; -+ struct san_list *item_s = NULL; -+ struct san_list *item_p = NULL; -+ struct san_list *item_pb = NULL; -+ -+ rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, -+ &subAltName); -+ if (rv != SECSuccess) { -+ if (rv == SECFailure -+ && PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) { -+ ret = EOK; -+ } else { -+ ret = EIO; -+ } -+ goto done; -+ } -+ -+ pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); -+ if (pool == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ name_list = CERT_DecodeAltNameExtension(pool, &subAltName); -+ if (name_list == NULL ) { -+ ret = EIO; -+ goto done; -+ } -+ -+ current = name_list; -+ do { -+ switch (current->type) { -+ case certOtherName: -+ ret = add_string_other_name_to_san_list(mem_ctx, -+ SAN_STRING_OTHER_NAME, -+ current, &item_s); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item_s); -+ -+ item_p = NULL; -+ if (strcmp(item_s->other_name_oid, NT_PRINCIPAL_OID) == 0) { -+ ret = add_nt_princ_to_san_list(mem_ctx, pool, SAN_NT, current, -+ &item_p); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item_p); -+ } else if (strcmp(item_s->other_name_oid, PKINIT_OID) == 0) { -+ ret = add_pkinit_princ_to_san_list(mem_ctx, pool, SAN_PKINIT, -+ current, &item_p); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item_p); -+ } -+ -+ if (item_p != NULL) { -+ ret = add_principal_to_san_list(mem_ctx, SAN_PRINCIPAL, -+ item_p->val, &item_pb); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item_pb); -+ } -+ -+ break; -+ case certRFC822Name: -+ case certDNSName: -+ case certURI: -+ ret = add_to_san_list(mem_ctx, false, -+ nss_name_type_to_san_opt(current->type), -+ current->name.other.data, -+ current->name.other.len, &item); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ if (current->type == certRFC822Name -+ || current->type == certDNSName) { -+ ret = get_short_name(item, item->val, -+ (current->type == certRFC822Name -+ ? '@' : '.'), -+ &(item->short_name)); -+ if (ret != 0) { -+ goto done; -+ } -+ } -+ -+ DLIST_ADD(list, item); -+ break; -+ case certIPAddress: -+ ret = add_ip_to_san_list(mem_ctx, -+ nss_name_type_to_san_opt(current->type), -+ current->name.other.data, -+ current->name.other.len, &item); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item); -+ break; -+ case certDirectoryName: -+ ret = add_rdn_list_to_san_list(mem_ctx, -+ nss_name_type_to_san_opt(current->type), -+ current->name.directoryName, &item); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item); -+ break; -+ case certRegisterID: -+ ret = add_oid_to_san_list(mem_ctx, -+ nss_name_type_to_san_opt(current->type), -+ current->name.other, &item); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item); -+ break; -+ case certX400Address: -+ case certEDIPartyName: -+ ret = add_to_san_list(mem_ctx, true, -+ nss_name_type_to_san_opt(current->type), -+ current->name.other.data, -+ current->name.other.len, &item); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(list, item); -+ break; -+ default: -+ ret = EINVAL; -+ } -+ -+ current = CERT_GetNextGeneralName(current); -+ if (current == NULL) { -+ ret = EIO; -+ goto done; -+ } -+ } while (current != name_list); -+ -+done: -+ -+ /* Don't free nameList, it's part of the arena. */ -+ -+ if (pool != NULL) { -+ PORT_FreeArena(pool, PR_FALSE); -+ } -+ -+ if (subAltName.data != NULL) { -+ SECITEM_FreeItem(&subAltName, PR_FALSE); -+ } -+ -+ if (ret == EOK) { -+ *san_list = list; -+ } -+ return ret; -+} -+ -+int sss_cert_get_content(TALLOC_CTX *mem_ctx, -+ const uint8_t *der_blob, size_t der_size, -+ struct sss_cert_content **content) -+{ -+ int ret; -+ struct sss_cert_content *cont = NULL; -+ CERTCertDBHandle *handle; -+ CERTCertificate *cert = NULL; -+ SECItem der_item; -+ NSSInitContext *nss_ctx; -+ -+ if (der_blob == NULL || der_size == 0) { -+ return EINVAL; -+ } -+ -+ nss_ctx = NSS_InitContext("", "", "", "", NULL, NSS_INIT_READONLY -+ | NSS_INIT_NOCERTDB -+ | NSS_INIT_NOMODDB -+ | NSS_INIT_FORCEOPEN -+ | NSS_INIT_NOROOTINIT -+ | NSS_INIT_OPTIMIZESPACE); -+ if (nss_ctx == NULL) { -+ return EIO; -+ } -+ -+ cont = talloc_zero(mem_ctx, struct sss_cert_content); -+ if (cont == NULL) { -+ return ENOMEM; -+ } -+ -+ handle = CERT_GetDefaultCertDB(); -+ der_item.len = der_size; -+ der_item.data = discard_const(der_blob); -+ -+ cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE); -+ if (cert == NULL) { -+ ret = EINVAL; -+ goto done; -+ } -+ -+ cont->issuer_str = talloc_strdup(cont, cert->issuerName); -+ if (cont->issuer_str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = get_rdn_list(cont, cert->issuer.rdns, &cont->issuer_rdn_list); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ cont->subject_str = talloc_strdup(cont, cert->subjectName); -+ if (cont->subject_str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = get_rdn_list(cont, cert->subject.rdns, &cont->subject_rdn_list); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ -+ cont->key_usage = cert->keyUsage; -+ -+ ret = get_extended_key_usage_oids(cont, cert, -+ &(cont->extended_key_usage_oids)); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ ret = get_san(cont, cert, &(cont->san_list)); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ cont->cert_der = talloc_memdup(cont, der_blob, der_size); -+ if (cont->cert_der == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ cont->cert_der_size = der_size; -+ ret = EOK; -+ -+done: -+ -+ CERT_DestroyCertificate(cert); -+ NSS_ShutdownContext(nss_ctx); -+ -+ if (ret == EOK) { -+ *content = cont; -+ } else { -+ talloc_free(cont); -+ } -+ -+ return ret; -+} -diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c -new file mode 100644 -index 0000000000000000000000000000000000000000..080cab8ab585ce64a88c352a23a8062887fa720a ---- /dev/null -+++ b/src/lib/certmap/sss_certmap.c -@@ -0,0 +1,993 @@ -+/* -+ SSSD -+ -+ Library for rule based certificate to user mapping -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2017 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 "util/util.h" -+#include "util/cert.h" -+#include "util/crypto/sss_crypto.h" -+#include "lib/certmap/sss_certmap.h" -+#include "lib/certmap/sss_certmap_int.h" -+ -+int debug_level; -+void sss_debug_fn(const char *file, -+ long line, -+ const char *function, -+ int level, -+ const char *format, ...) -+{ -+ return; -+} -+ -+static int get_type_prefix(TALLOC_CTX *mem_ctx, const char *match_rule, -+ char **type, const char **rule_start) -+{ -+ const char *c; -+ char *delim; -+ -+ *type = NULL; -+ *rule_start = match_rule; -+ -+ delim = strchr(match_rule, ':'); -+ if (delim == NULL) { -+ /* no type prefix found */ -+ return 0; -+ } -+ -+ /* rule starts with ':', empty type */ -+ if (delim == match_rule) { -+ *rule_start = delim + 1; -+ return EOK; -+ } -+ -+ for (c = match_rule; c < delim; c++) { -+ /* type prefix may only contain digits and upper-case ASCII characters */ -+ if (!(isascii(*c) && (isdigit(*c) || isupper(*c)))) { -+ /* no type prefix found */ -+ return 0; -+ } -+ } -+ -+ *rule_start = delim + 1; -+ *type = talloc_strndup(mem_ctx, match_rule, (delim - match_rule)); -+ if (*type == NULL) { -+ return ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static int parse_match_rule(struct sss_certmap_ctx *ctx, const char *match_rule, -+ struct krb5_match_rule **parsed_match_rule) -+{ -+ int ret; -+ char *type; -+ const char *rule_start; -+ -+ ret = get_type_prefix(ctx, match_rule, &type, &rule_start); -+ if (ret != EOK) { -+ CM_DEBUG(ctx, "Failed to read rule type."); -+ goto done; -+ } -+ -+ if (type == NULL || strcmp(type, "KRB5") == 0) { -+ ret = parse_krb5_match_rule(ctx, rule_start, parsed_match_rule); -+ if (ret != EOK) { -+ CM_DEBUG(ctx, "Failed to parse KRB5 matching rule."); -+ goto done; -+ } -+ } else { -+ CM_DEBUG(ctx, "Unsupported matching rule type."); -+ ret = ESRCH; -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ talloc_free(type); -+ -+ return ret; -+} -+ -+static int parse_mapping_rule(struct sss_certmap_ctx *ctx, -+ const char *mapping_rule, -+ struct ldap_mapping_rule **parsed_mapping_rule) -+{ -+ int ret; -+ char *type; -+ const char *rule_start; -+ -+ ret = get_type_prefix(ctx, mapping_rule, &type, &rule_start); -+ if (ret != EOK) { -+ CM_DEBUG(ctx, "Failed to read rule type."); -+ goto done; -+ } -+ -+ if (type == NULL || strcmp(type, "LDAP") == 0) { -+ ret = parse_ldap_mapping_rule(ctx, rule_start, parsed_mapping_rule); -+ if (ret != EOK) { -+ CM_DEBUG(ctx, "Failed to parse LDAP mapping rule."); -+ goto done; -+ } -+ } else { -+ CM_DEBUG(ctx, "Unsupported mapping rule type."); -+ ret = ESRCH; -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ talloc_free(type); -+ -+ return ret; -+} -+ -+int sss_certmap_add_rule(struct sss_certmap_ctx *ctx, -+ uint32_t priority, const char *match_rule, -+ const char *map_rule, const char **domains) -+{ -+ size_t c; -+ int ret; -+ struct match_map_rule *rule; -+ struct TALLOC_CTX *tmp_ctx; -+ struct priority_list *p; -+ struct priority_list *p_new; -+ struct krb5_match_rule *parsed_match_rule; -+ struct ldap_mapping_rule *parsed_mapping_rule; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ rule = talloc_zero(tmp_ctx, struct match_map_rule); -+ if (rule == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ rule->priority = priority; -+ -+ if (match_rule == NULL) { -+ match_rule = DEFAULT_MATCH_RULE; -+ } -+ ret = parse_match_rule(ctx, match_rule, &parsed_match_rule); -+ if (ret == 0) { -+ rule->parsed_match_rule = talloc_steal(rule, parsed_match_rule); -+ rule->match_rule = talloc_strdup(rule, match_rule); -+ if (rule->match_rule == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } else if (ret == ESRCH) { -+ /* report unsupported rules */ -+ goto done; -+ } else { -+ goto done; -+ } -+ -+ if (map_rule == NULL) { -+ map_rule = DEFAULT_MAP_RULE; -+ } -+ ret = parse_mapping_rule(ctx, map_rule, &parsed_mapping_rule); -+ if (ret == 0) { -+ rule->parsed_mapping_rule = talloc_steal(rule, parsed_mapping_rule); -+ rule->map_rule = talloc_strdup(rule, map_rule); -+ if (rule->map_rule == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } else if (ret == ESRCH) { -+ /* report unsupported rules */ -+ goto done; -+ } else { -+ goto done; -+ } -+ -+ if (domains != NULL && *domains != NULL) { -+ for (c = 0; domains[c] != NULL; c++); -+ rule->domains = talloc_zero_array(rule, char *, c + 1); -+ if (rule->domains == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ for (c = 0; domains[c] != NULL; c++) { -+ rule->domains[c] = talloc_strdup(rule->domains, domains[c]); -+ if (rule->domains[c] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ } -+ -+ if (ctx->prio_list == NULL) { -+ ctx->prio_list = talloc_zero(ctx, struct priority_list); -+ if (ctx->prio_list == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ctx->prio_list->priority = rule->priority; -+ ctx->prio_list->rule_list = rule; -+ } else { -+ for (p = ctx->prio_list; p != NULL && p->priority < rule->priority; -+ p = p->next); -+ if (p != NULL && p->priority == priority) { -+ DLIST_ADD(p->rule_list, rule); -+ } else { -+ p_new = talloc_zero(ctx, struct priority_list); -+ if (p_new == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ p_new->priority = rule->priority; -+ p_new->rule_list = rule; -+ -+ if (p == NULL) { -+ DLIST_ADD_END(ctx->prio_list, p_new, struct priority_list *); -+ } else if (p->prev == NULL) { -+ DLIST_ADD(ctx->prio_list, p_new); -+ } else { -+ DLIST_ADD_AFTER(ctx->prio_list, p_new, p->prev); -+ } -+ } -+ } -+ -+ talloc_steal(ctx, rule); -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -+ -+static int expand_cert(struct sss_certmap_ctx *ctx, -+ struct parsed_template *parsed_template, -+ struct sss_cert_content *cert_content, -+ char **expanded) -+{ -+ int ret; -+ char *tmp_str = NULL; -+ -+ if (parsed_template->conversion == NULL -+ || strcmp(parsed_template->conversion, "bin") == 0) { -+ ret = bin_to_ldap_filter_value(ctx, cert_content->cert_der, -+ cert_content->cert_der_size, &tmp_str); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "bin conversion failed."); -+ goto done; -+ } -+ } else if (strcmp(parsed_template->conversion, "base64") == 0) { -+ tmp_str = sss_base64_encode(ctx, cert_content->cert_der, -+ cert_content->cert_der_size); -+ if (tmp_str == NULL) { -+ CM_DEBUG(ctx, "base64 conversion failed."); -+ ret = ENOMEM; -+ goto done; -+ } -+ } else { -+ CM_DEBUG(ctx, "Unsupported conversion."); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *expanded = tmp_str; -+ } else { -+ talloc_free(tmp_str); -+ } -+ -+ return ret; -+} -+ -+static int get_dn_str(struct sss_certmap_ctx *ctx, const char *conversion, -+ const char **rdn_list, char **result) -+{ -+ char *str = NULL; -+ size_t c; -+ int ret; -+ char *conv = NULL; -+ -+ str = talloc_strdup(ctx, ""); -+ if (str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ if (conversion == NULL || strcmp(conversion, "nss_ldap") == 0 -+ || strcmp(conversion, "nss") == 0) { -+ for (c = 0; rdn_list[c] != NULL; c++); -+ while (c != 0) { -+ c--; -+ str = talloc_asprintf_append(str, "%s%s", -+ (rdn_list[c + 1] == NULL) ? "" : ",", -+ rdn_list[c]); -+ if (str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ }; -+ } else if (strcmp(conversion, "ad_ldap") == 0) { -+ for (c = 0; rdn_list[c] != NULL; c++); -+ while (c != 0) { -+ c--; -+ conv = check_ad_attr_name(str, rdn_list[c]); -+ str = talloc_asprintf_append(str, "%s%s", -+ (rdn_list[c + 1] == NULL) ? "" : ",", -+ conv == NULL ? rdn_list[c] : conv); -+ talloc_free(conv); -+ conv = NULL; -+ if (str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ }; -+ } else if (strcmp(conversion, "nss_x500") == 0) { -+ for (c = 0; rdn_list[c] != NULL; c++) { -+ str = talloc_asprintf_append(str, "%s%s", (c == 0) ? "" : ",", -+ rdn_list[c]); -+ if (str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ } else if (strcmp(conversion, "ad_x500") == 0 -+ || strcmp(conversion, "ad") == 0) { -+ for (c = 0; rdn_list[c] != NULL; c++) { -+ conv = check_ad_attr_name(str, rdn_list[c]); -+ str = talloc_asprintf_append(str, "%s%s", -+ (c == 0) ? "" : ",", -+ conv == NULL ? rdn_list[c] : conv); -+ talloc_free(conv); -+ conv = NULL; -+ if (str == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ } else { -+ ret = EINVAL; -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *result = str; -+ } else { -+ talloc_free(str); -+ } -+ -+ return ret; -+} -+ -+static int expand_san_blob(struct sss_certmap_ctx *ctx, enum san_opt san_opt, -+ struct san_list *san_list, char **expanded) -+{ -+ struct san_list *item; -+ char *exp; -+ int ret; -+ -+ DLIST_FOR_EACH(item, san_list) { -+ if (item->san_opt == san_opt) { -+ ret = bin_to_ldap_filter_value(ctx, item->bin_val, -+ item->bin_val_len, &exp); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "bin conversion failed."); -+ return ret; -+ } -+ -+ *expanded = exp; -+ return 0; -+ } -+ } -+ -+ return ENOENT; -+} -+ -+static int expand_san_string(struct sss_certmap_ctx *ctx, enum san_opt san_opt, -+ struct san_list *san_list, const char *attr_name, -+ char **expanded) -+{ -+ struct san_list *item; -+ char *exp; -+ -+ DLIST_FOR_EACH(item, san_list) { -+ if (item->san_opt == san_opt) { -+ if (attr_name == NULL) { -+ exp = talloc_strdup(ctx, item->val); -+ } else if (strcasecmp(attr_name, "short_name") == 0) { -+ exp = talloc_strdup(ctx, item->short_name); -+ } else { -+ CM_DEBUG(ctx, "Unsupported attribute name [%s].", attr_name); -+ return EINVAL; -+ } -+ -+ if (exp == NULL) { -+ return ENOMEM; -+ } -+ -+ *expanded = exp; -+ return 0; -+ } -+ } -+ -+ return ENOENT; -+} -+ -+static int expand_san_rdn_list(struct sss_certmap_ctx *ctx, -+ enum san_opt san_opt, -+ struct san_list *san_list, -+ const char *conversion, -+ char **expanded) -+{ -+ struct san_list *item; -+ char *exp; -+ int ret; -+ -+ DLIST_FOR_EACH(item, san_list) { -+ if (item->san_opt == san_opt) { -+ ret = get_dn_str(ctx, conversion, item->rdn_list, &exp); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ *expanded = exp; -+ return 0; -+ } -+ } -+ -+ return ENOENT; -+} -+ -+ -+static int expand_san(struct sss_certmap_ctx *ctx, -+ struct parsed_template *parsed_template, -+ struct san_list *san_list, -+ char **expanded) -+{ -+ int ret; -+ -+ if (strcmp("subject_rfc822_name", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_RFC822_NAME, san_list, -+ parsed_template->attr_name, expanded); -+ } else if (strcmp("subject_dns_name", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_DNS_NAME, san_list, -+ parsed_template->attr_name, expanded); -+ } else if (strcmp("subject_x400_address", parsed_template->name) == 0) { -+ ret = expand_san_blob(ctx, SAN_X400_ADDRESS, san_list, expanded); -+ } else if (strcmp("subject_directory_name", parsed_template->name) == 0) { -+ ret = expand_san_rdn_list(ctx, SAN_DIRECTORY_NAME, san_list, -+ parsed_template->conversion, expanded); -+ } else if (strcmp("subject_ediparty_name", parsed_template->name) == 0) { -+ ret = expand_san_blob(ctx, SAN_EDIPART_NAME, san_list, expanded); -+ } else if (strcmp("subject_uri", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_URI, san_list, -+ parsed_template->attr_name, expanded); -+ } else if (strcmp("subject_ip_address", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_IP_ADDRESS, san_list, -+ parsed_template->attr_name, expanded); -+ } else if (strcmp("subject_registered_id", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_REGISTERED_ID, san_list, -+ parsed_template->attr_name, expanded); -+ } else if (strcmp("subject_pkinit_principal", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_PKINIT, san_list, -+ parsed_template->attr_name, expanded); -+ } else if (strcmp("subject_nt_principal", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_NT, san_list, -+ parsed_template->attr_name, expanded); -+ } else if (strcmp("subject_principal", parsed_template->name) == 0) { -+ ret = expand_san_string(ctx, SAN_PRINCIPAL, san_list, -+ parsed_template->attr_name, expanded); -+ } else { -+ CM_DEBUG(ctx, "Unsupported template name [%s].n", -+ parsed_template->name); -+ ret = EINVAL; -+ } -+ -+ return ret; -+} -+ -+static int expand_template(struct sss_certmap_ctx *ctx, -+ struct parsed_template *parsed_template, -+ struct sss_cert_content *cert_content, -+ char **expanded) -+{ -+ int ret; -+ char *exp = NULL; -+ -+ if (strcmp("issuer_dn", parsed_template->name) == 0) { -+ ret = get_dn_str(ctx, parsed_template->conversion, -+ cert_content->issuer_rdn_list, &exp); -+ } else if (strcmp("subject_dn", parsed_template->name) == 0) { -+ ret = get_dn_str(ctx, parsed_template->conversion, -+ cert_content->subject_rdn_list, &exp); -+ } else if (strncmp("subject_", parsed_template->name, 8) == 0) { -+ ret = expand_san(ctx, parsed_template, cert_content->san_list, &exp); -+ } else if (strcmp("cert", parsed_template->name) == 0) { -+ ret = expand_cert(ctx, parsed_template, cert_content, &exp); -+ } else { -+ CM_DEBUG(ctx, "Unsupported template name."); -+ ret = EINVAL; -+ goto done; -+ } -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to expand [%s] template.", parsed_template->name); -+ goto done; -+ } -+ -+ if (exp == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *expanded = exp; -+ } else { -+ talloc_free(exp); -+ } -+ -+ return ret; -+} -+ -+static int get_filter(struct sss_certmap_ctx *ctx, -+ struct ldap_mapping_rule *parsed_mapping_rule, -+ struct sss_cert_content *cert_content, -+ char **filter) -+{ -+ struct ldap_mapping_rule_comp *comp; -+ char *result = NULL; -+ char *expanded = NULL; -+ int ret; -+ -+ result = talloc_strdup(ctx, ""); -+ if (result == NULL) { -+ return ENOMEM; -+ } -+ -+ for (comp = parsed_mapping_rule->list; comp != NULL; comp = comp->next) { -+ if (comp->type == comp_string) { -+ result = talloc_strdup_append(result, comp->val); -+ } else if (comp->type == comp_template) { -+ ret = expand_template(ctx, comp->parsed_template, cert_content, -+ &expanded); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to expanded template."); -+ goto done; -+ } -+ -+ result = talloc_strdup_append(result, expanded); -+ talloc_free(expanded); -+ expanded = NULL; -+ if (result == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } else { -+ ret = EINVAL; -+ CM_DEBUG(ctx, "Unsupported component type."); -+ goto done; -+ } -+ } -+ -+ ret = 0; -+done: -+ talloc_free(expanded); -+ if (ret == 0) { -+ *filter = result; -+ } else { -+ talloc_free(result); -+ } -+ -+ return ret; -+} -+ -+static bool check_san_regexp(struct sss_certmap_ctx *ctx, -+ enum san_opt san_opt, regex_t regexp, -+ struct san_list *san_list) -+{ -+ struct san_list *item; -+ bool match = false; -+ int ret; -+ char *tmp_str = NULL; -+ -+ DLIST_FOR_EACH(item, san_list) { -+ if (item->san_opt == san_opt) { -+ if (item->san_opt == SAN_DIRECTORY_NAME) { -+ /* use LDAP order for matching */ -+ ret = get_dn_str(ctx, NULL, item->rdn_list, &tmp_str); -+ if (ret != 0 || tmp_str == NULL) { -+ return false; -+ } -+ match = (regexec(®exp, tmp_str, 0, NULL, 0) == 0); -+ talloc_free(tmp_str); -+ } else { -+ match = (item->val != NULL -+ && regexec(®exp, item->val, 0, NULL, 0) == 0); -+ } -+ if (!match) { -+ return false; -+ } -+ } -+ } -+ -+ return match; -+} -+ -+static bool check_san_blob(enum san_opt san_opt, -+ uint8_t *bin_val, size_t bin_val_len, -+ struct san_list *san_list) -+{ -+ struct san_list *item; -+ bool match = false; -+ -+ if (bin_val == NULL || bin_val_len == 0) { -+ return false; -+ } -+ -+ DLIST_FOR_EACH(item, san_list) { -+ if (item->san_opt == san_opt) { -+ match = (item->bin_val != NULL && item->bin_val_len != 0 -+ && memmem(item->bin_val, item->bin_val_len, -+ bin_val, bin_val_len) != NULL); -+ if (!match) { -+ return false; -+ } -+ } -+ } -+ -+ return match; -+} -+ -+static bool check_san_str_other_name(enum san_opt san_opt, -+ const char *str_other_name_oid, -+ regex_t regexp, -+ struct san_list *san_list) -+{ -+ struct san_list *item; -+ bool match = false; -+ char *tmp_str; -+ -+ if (str_other_name_oid == NULL) { -+ return false; -+ } -+ -+ DLIST_FOR_EACH(item, san_list) { -+ if (item->san_opt == san_opt -+ && strcmp(item->other_name_oid, str_other_name_oid) == 0) { -+ match = false; -+ if (item->bin_val != NULL && item->bin_val_len != 0) { -+ tmp_str = talloc_strndup(item, (char *) item->bin_val, -+ item->bin_val_len); -+ if (tmp_str != NULL) { -+ match = (regexec(®exp, tmp_str, 0, NULL, 0) == 0); -+ } -+ talloc_free(tmp_str); -+ } -+ if (!match) { -+ return false; -+ } -+ } -+ } -+ -+ return match; -+} -+ -+static bool do_san_match(struct sss_certmap_ctx *ctx, -+ struct component_list *comp, -+ struct san_list *san_list) -+{ -+ switch (comp->san_opt) { -+ case SAN_OTHER_NAME: -+ return check_san_blob(SAN_STRING_OTHER_NAME, -+ comp->bin_val, comp->bin_val_len, -+ san_list); -+ break; -+ case SAN_X400_ADDRESS: -+ case SAN_EDIPART_NAME: -+ return check_san_blob(comp->san_opt, comp->bin_val, comp->bin_val_len, -+ san_list); -+ break; -+ case SAN_RFC822_NAME: -+ case SAN_DNS_NAME: -+ case SAN_DIRECTORY_NAME: -+ case SAN_URI: -+ case SAN_IP_ADDRESS: -+ case SAN_REGISTERED_ID: -+ case SAN_PKINIT: -+ case SAN_NT: -+ case SAN_PRINCIPAL: -+ return check_san_regexp(ctx, comp->san_opt, comp->regexp, san_list); -+ break; -+ case SAN_STRING_OTHER_NAME: -+ return check_san_str_other_name(comp->san_opt, comp->str_other_name_oid, -+ comp->regexp, san_list); -+ break; -+ default: -+ CM_DEBUG(ctx, "Unsupported SAN option [%d].", comp->san_opt); -+ return false; -+ } -+} -+ -+static int do_match(struct sss_certmap_ctx *ctx, -+ struct krb5_match_rule *parsed_match_rule, -+ struct sss_cert_content *cert_content) -+{ -+ struct component_list *comp; -+ bool match = false; -+ size_t c; -+ -+ if (parsed_match_rule == NULL || cert_content == NULL) { -+ return EINVAL; -+ } -+ -+ /* Issuer */ -+ for (comp = parsed_match_rule->issuer; comp != NULL; comp = comp->next) { -+ match = (cert_content->issuer_str != NULL -+ && regexec(&(comp->regexp), cert_content->issuer_str, -+ 0, NULL, 0) == 0); -+ if (match && parsed_match_rule->r == relation_or) { -+ /* match */ -+ return 0; -+ } else if (!match && parsed_match_rule->r == relation_and) { -+ /* no match */ -+ return ENOENT; -+ } -+ -+ } -+ -+ /* Subject */ -+ for (comp = parsed_match_rule->subject; comp != NULL; comp = comp->next) { -+ match = (cert_content->subject_str != NULL -+ && regexec(&(comp->regexp), cert_content->subject_str, -+ 0, NULL, 0) == 0); -+ if (match && parsed_match_rule->r == relation_or) { -+ /* match */ -+ return 0; -+ } else if (!match && parsed_match_rule->r == relation_and) { -+ /* no match */ -+ return ENOENT; -+ } -+ -+ } -+ -+ /* Key Usage */ -+ for (comp = parsed_match_rule->ku; comp != NULL; comp = comp->next) { -+ match = ((cert_content->key_usage & comp->ku) == comp->ku); -+ if (match && parsed_match_rule->r == relation_or) { -+ /* match */ -+ return 0; -+ } else if (!match && parsed_match_rule->r == relation_and) { -+ /* no match */ -+ return ENOENT; -+ } -+ } -+ -+ /* Extended Key Usage */ -+ for (comp = parsed_match_rule->eku; comp != NULL; comp = comp->next) { -+ for (c = 0; comp->eku_oid_list[c] != NULL; c++) { -+ match = string_in_list(comp->eku_oid_list[c], -+ discard_const( -+ cert_content->extended_key_usage_oids), -+ true); -+ if (match && parsed_match_rule->r == relation_or) { -+ /* match */ -+ return 0; -+ } else if (!match && parsed_match_rule->r == relation_and) { -+ /* no match */ -+ return ENOENT; -+ } -+ } -+ } -+ -+ /* SAN */ -+ for (comp = parsed_match_rule->san; comp != NULL; comp = comp->next) { -+ match = do_san_match(ctx, comp, cert_content->san_list); -+ if (match && parsed_match_rule->r == relation_or) { -+ /* match */ -+ return 0; -+ } else if (!match && parsed_match_rule->r == relation_and) { -+ /* no match */ -+ return ENOENT; -+ } -+ } -+ -+ if (match) { -+ /* match */ -+ return 0; -+ } -+ -+ /* no match */ -+ return ENOENT; -+} -+ -+int sss_certmap_match_cert(struct sss_certmap_ctx *ctx, -+ const uint8_t *der_cert, size_t der_size) -+{ -+ int ret; -+ struct match_map_rule *r; -+ struct priority_list *p; -+ struct sss_cert_content *cert_content = NULL; -+ -+ ret = sss_cert_get_content(ctx, der_cert, der_size, &cert_content); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to get certificate content."); -+ return ret; -+ } -+ -+ if (ctx->prio_list == NULL) { -+ /* Match all certificates if there are no rules applied */ -+ ret = 0; -+ goto done; -+ } -+ -+ for (p = ctx->prio_list; p != NULL; p = p->next) { -+ for (r = p->rule_list; r != NULL; r = r->next) { -+ ret = do_match(ctx, r->parsed_match_rule, cert_content); -+ if (ret == 0) { -+ /* match */ -+ goto done; -+ } -+ } -+ } -+ -+ ret = ENOENT; -+done: -+ talloc_free(cert_content); -+ -+ return ret; -+} -+ -+int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx, -+ const uint8_t *der_cert, size_t der_size, -+ char **_filter, char ***_domains) -+{ -+ int ret; -+ struct match_map_rule *r; -+ struct priority_list *p; -+ struct sss_cert_content *cert_content = NULL; -+ char *filter = NULL; -+ char **domains = NULL; -+ size_t c; -+ -+ if (_filter == NULL || _domains == NULL) { -+ return EINVAL; -+ } -+ -+ ret = sss_cert_get_content(ctx, der_cert, der_size, &cert_content); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to get certificate content [%d].", ret); -+ return ret; -+ } -+ -+ if (ctx->prio_list == NULL) { -+ if (ctx->default_mapping_rule == NULL) { -+ CM_DEBUG(ctx, "No matching or mapping rules available."); -+ return EINVAL; -+ } -+ -+ ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, &filter); -+ goto done; -+ } -+ -+ for (p = ctx->prio_list; p != NULL; p = p->next) { -+ for (r = p->rule_list; r != NULL; r = r->next) { -+ ret = do_match(ctx, r->parsed_match_rule, cert_content); -+ if (ret == 0) { -+ /* match */ -+ ret = get_filter(ctx, r->parsed_mapping_rule, cert_content, -+ &filter); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to get filter"); -+ goto done; -+ } -+ -+ if (r->domains != NULL) { -+ for (c = 0; r->domains[c] != NULL; c++); -+ domains = talloc_zero_array(ctx, char *, c + 1); -+ if (domains == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (c = 0; r->domains[c] != NULL; c++) { -+ domains[c] = talloc_strdup(domains, r->domains[c]); -+ if (domains[c] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ } -+ -+ ret = 0; -+ goto done; -+ } -+ } -+ } -+ -+ ret = ENOENT; -+ -+done: -+ talloc_free(cert_content); -+ if (ret == 0) { -+ *_filter = filter; -+ *_domains = domains; -+ } else { -+ talloc_free(filter); -+ talloc_free(domains); -+ } -+ -+ return ret; -+} -+ -+int sss_certmap_init(TALLOC_CTX *mem_ctx, -+ sss_certmap_ext_debug *debug, void *debug_priv, -+ struct sss_certmap_ctx **ctx) -+{ -+ int ret; -+ -+ if (ctx == NULL) { -+ return EINVAL; -+ } -+ -+ *ctx = talloc_zero(mem_ctx, struct sss_certmap_ctx); -+ if (*ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ (*ctx)->debug = debug; -+ (*ctx)->debug_priv = debug_priv; -+ -+ ret = parse_mapping_rule(*ctx, DEFAULT_MAP_RULE, -+ &((*ctx)->default_mapping_rule)); -+ if (ret != 0) { -+ CM_DEBUG((*ctx), "Failed to parse default mapping rule."); -+ talloc_free(*ctx); -+ *ctx = NULL; -+ return ret; -+ } -+ -+ CM_DEBUG((*ctx), "sss_certmap initialized."); -+ return EOK; -+} -+ -+void sss_certmap_free_ctx(struct sss_certmap_ctx *ctx) -+{ -+ talloc_free(ctx); -+} -+ -+void sss_certmap_free_filter_and_domains(char *filter, char **domains) -+{ -+ talloc_free(filter); -+ talloc_free(domains); -+} -diff --git a/src/lib/certmap/sss_certmap.doxy.in b/src/lib/certmap/sss_certmap.doxy.in -new file mode 100644 -index 0000000000000000000000000000000000000000..e8959e2099a0f517c314833e47d410306fb02702 ---- /dev/null -+++ b/src/lib/certmap/sss_certmap.doxy.in -@@ -0,0 +1,3 @@ -+PROJECT_NAME = sss_certmap -+OUTPUT_DIRECTORY = certmap_doc -+INPUT = @abs_top_srcdir@/src/lib/certmap/sss_certmap.h -diff --git a/src/lib/certmap/sss_certmap.exports b/src/lib/certmap/sss_certmap.exports -new file mode 100644 -index 0000000000000000000000000000000000000000..8b5d5366697401649547c09c6b6f3db571c2b518 ---- /dev/null -+++ b/src/lib/certmap/sss_certmap.exports -@@ -0,0 +1,13 @@ -+SSS_CERTMAP_0.0 { -+ global: -+ sss_certmap_init; -+ sss_certmap_free_ctx; -+ sss_certmap_err_msg; -+ sss_certmap_add_rule; -+ sss_certmap_match_cert; -+ sss_certmap_get_search_filter; -+ sss_cert_get_content; -+ sss_certmap_free_filter_and_domains; -+ local: -+ *; -+}; -diff --git a/src/lib/certmap/sss_certmap.h b/src/lib/certmap/sss_certmap.h -new file mode 100644 -index 0000000000000000000000000000000000000000..55485cc35e8bd7cf2cb2b0c5a06a7521025e3c43 ---- /dev/null -+++ b/src/lib/certmap/sss_certmap.h -@@ -0,0 +1,155 @@ -+/* -+ SSSD -+ -+ Library for rule based certificate to user mapping -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2017 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 . -+*/ -+ -+#ifndef _SSS_CERTMAP_H_ -+#define _SSS_CERTMAP_H_ -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+/** -+ * @defgroup sss_certmap Allow rule-based mapping of certificates to users -+ * Libsss_certmap provides a mechanism to map X509 certificate to users based -+ * on rules. -+ * @{ -+ */ -+ -+/** -+ * Opaque type for the idmap context -+ */ -+struct sss_certmap_ctx; -+ -+/** -+ * Lowest priority of a rule -+ */ -+#define SSS_CERTMAP_MIN_PRIO UINT32_MAX -+ -+/** -+ * Typedef for external debug callback -+ */ -+typedef void (sss_certmap_ext_debug)(void *pvt, -+ const char *file, long line, -+ const char *function, -+ const char *format, ...); -+/** -+ * @brief Initialize certmap context -+ * -+ * @param[in] mem_ctx Talloc memory context, may be NULL -+ * @param[in] debug Callback to handle debug output, may be NULL -+ * @param[in] debug_priv Private data for debugging callback, may be NULL -+ * @param[out] ctx New certmap context -+ * -+ * @return -+ * - 0: success -+ * - ENOMEM: failed to allocate internal Talloc context -+ * - EINVAL: ctx is NULL -+ */ -+int sss_certmap_init(TALLOC_CTX *mem_ctx, -+ sss_certmap_ext_debug *debug, void *debug_priv, -+ struct sss_certmap_ctx **ctx); -+ -+/** -+ * @brief Free certmap context -+ * -+ * @param[in] ctx certmap context previously initialized with -+ * @ref sss_certmap_init, may be NULL -+ */ -+void sss_certmap_free_ctx(struct sss_certmap_ctx *ctx); -+ -+/** -+ * @brief Add a rule to the certmap context -+ * -+ * @param[in] ctx certmap context previously initialized with -+ * @ref sss_certmap_init -+ * @param[in] priority priority of the rule, 0 is the hightest priority, the -+ * lowest is SSS_CERTMAP_MIN_PRIO -+ * @param[in] match_rule String with the matching rule -+ * @param[in] map_rule String with the mapping rule -+ * @param[in] domains NULL-terminated string array with a list of domains -+ * the rule should be valid for, i.e. only this domains -+ * should be searched for matching users -+ * -+ * @return -+ * - 0: success -+ */ -+int sss_certmap_add_rule(struct sss_certmap_ctx *ctx, -+ uint32_t priority, const char *match_rule, -+ const char *map_rule, const char **domains); -+ -+/** -+ * @brief Check if a certificate matches any of the applied rules -+ * -+ * @param[in] ctx certmap context previously initialized with -+ * @ref sss_certmap_init -+ * @param[in] der_cert binary blog with the DER encoded certificate -+ * @param[in] der_size size of the certificate blob -+ * -+ * @return -+ * - 0: certificate matches a rule -+ * - ENOENT: certificate does not match -+ * - EINVAL: internal error -+ */ -+int sss_certmap_match_cert(struct sss_certmap_ctx *ctx, -+ const uint8_t *der_cert, size_t der_size); -+ -+/** -+ * @brief Get the LDAP filter string for a certificate -+ * -+ * @param[in] ctx certmap context previously initialized with -+ * @ref sss_certmap_init -+ * @param[in] der_cert binary blog with the DER encoded certificate -+ * @param[in] der_size size of the certificate blob -+ * @param[out] filter LDAP filter string, caller should free the data by -+ * calling sss_certmap_free_filter_and_domains -+ * @param[out] domains NULL-terminated array of strings with the domains the -+ * rule applies, caller should free the data by calling -+ * sss_certmap_free_filter_and_domains -+ * -+ * @return -+ * - 0: certificate matches a rule -+ * - ENOENT: certificate does not match -+ * - EINVAL: internal error -+ */ -+int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx, -+ const uint8_t *der_cert, size_t der_size, -+ char **filter, char ***domains); -+ -+/** -+ * @brief Free data returned by @ref sss_certmap_get_search_filter -+ * -+ * @param[in] filter LDAP filter strings returned by -+ * sss_certmap_get_search_filter -+ * @param[in] domains string array of domains returned by -+ * sss_certmap_get_search_filter -+ */ -+void sss_certmap_free_filter_and_domains(char *filter, char **domains); -+ -+/** -+ * @} -+ */ -+#endif /* _SSS_CERTMAP_H_ */ -diff --git a/src/lib/certmap/sss_certmap.pc.in b/src/lib/certmap/sss_certmap.pc.in -new file mode 100644 -index 0000000000000000000000000000000000000000..f1a4432fce8ccd5642a622ca6a8d3a7954fc7ba3 ---- /dev/null -+++ b/src/lib/certmap/sss_certmap.pc.in -@@ -0,0 +1,11 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@ -+ -+Name: sss_certmap -+Description: SSS certificate mapping library -+Version: @VERSION@ -+Libs: -L${libdir} -lsss_certmap -+Cflags: -+URL: https://pagure.io/SSSD/sssd/ -diff --git a/src/lib/certmap/sss_certmap_attr_names.c b/src/lib/certmap/sss_certmap_attr_names.c -new file mode 100644 -index 0000000000000000000000000000000000000000..a28a464910728cdd1f316b2b979da84f440685ea ---- /dev/null -+++ b/src/lib/certmap/sss_certmap_attr_names.c -@@ -0,0 +1,107 @@ -+/* -+ SSSD -+ -+ Library for rule based certificate to user mapping - Attribute name -+ mapping for different implementations -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2017 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 . -+*/ -+ -+/* NSS data taken from nss-utils:nss/lib/util/secoid.c and -+ * nss:nss/lib/certdb/alg1485.c */ -+ -+/* AD data taken from -+ * https://msdn.microsoft.com/en-us/library/windows/desktop/aa376556%28v=vs.85%29.aspx -+ * and wine source code dlls/crypt32/oid.c  and include/wincrypt.h . */ -+ -+#include -+#include -+#include -+ -+struct oid_attr_name_map { -+ bool nss_ad_differ; -+ const char *oid; -+ const char *nss; -+ const char *ad; -+} oid_attr_name_map[] = { -+ { false, "2.5.4.3", "CN", "CN"}, -+ { true, "2.5.4.8", "ST", "S"}, -+ { false, "2.5.4.10", "O", "O"}, -+ { false, "2.5.4.11", "OU", "OU"}, -+ { false, "2.5.4.46", "dnQualifier", "dnQualifier"}, -+ { false, "2.5.4.6", "C", "C"}, -+ { true, "2.5.4.5", "serialNumber", "SERIALNUMBER"}, -+ { false, "2.5.4.7", "L", "L"}, -+ { true, "2.5.4.12", "title", "T"}, -+ { false, "2.5.4.4", "SN", "SN"}, -+ { true, "2.5.4.42", "givenName", "G"}, -+ { true, "2.5.4.43", "initials", "I"}, -+ { true, "2.5.4.44", "generationQualifier", "OID.2.5.4.44"}, -+ { false, "0.9.2342.19200300.100.1.25", "DC", "DC"}, -+ { true, "0.9.2342.19200300.100.1.3", "MAIL", "OID,0.9.2342.19200300.100.1.3"}, -+ { true, "0.9.2342.19200300.100.1.1", "UID", "OID.0.9.2342.19200300.100.1.1"}, -+ { true, "2.5.4.13", "OID.2.5.4.13", "Description"}, -+ { true, "2.5.4.16", "postalAddress", "OID.2.5.4.16"}, -+ { true, "2.5.4.17", "postalCode", "PostalCode"}, -+ { true, "2.5.4.18", "postOfficeBox", "POBox"}, -+ { true, "2.5.4.51", "houseIdentifier", "OID.2.5.4.51"}, -+ { false, "1.2.840.113549.1.9.1", "E", "E"}, -+ { false, "2.5.4.9", "STREET", "STREET"}, -+ { true, "2.5.4.65", "pseudonym", "OID.2.5.4.65"}, -+ { true, "2.5.4.15", "businessCategory", "OID.2.5.4.15"}, -+ { true, "2.5.4.41", "name", "OID.2.5.4.41"}, -+ -+ { false, NULL, NULL, NULL} -+}; -+ -+char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn) -+{ -+ char *p; -+ size_t c; -+ size_t len; -+ -+ if (rdn == NULL) { -+ return NULL; -+ } -+ -+ p = strchr(rdn, '='); -+ if (p == NULL) { -+ return NULL; -+ } -+ -+ len = p - rdn; -+ if (len == 0) { -+ return NULL; -+ } -+ -+ for (c = 0; oid_attr_name_map[c].oid != NULL; c++) { -+ if (!oid_attr_name_map[c].nss_ad_differ) { -+ continue; -+ } -+ -+ if (strlen(oid_attr_name_map[c].nss) != len -+ || strncmp(rdn, oid_attr_name_map[c].nss, len) != 0) { -+ continue; -+ } -+ -+ return talloc_asprintf(mem_ctx, "%s%s", oid_attr_name_map[c].ad, p); -+ } -+ -+ return NULL; -+} -diff --git a/src/lib/certmap/sss_certmap_int.h b/src/lib/certmap/sss_certmap_int.h -new file mode 100644 -index 0000000000000000000000000000000000000000..28f1c596cfb5e78077b6a8e9baefa88b4900a022 ---- /dev/null -+++ b/src/lib/certmap/sss_certmap_int.h -@@ -0,0 +1,187 @@ -+/* -+ SSSD -+ -+ Library for rule based certificate to user mapping -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2017 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 -+#include -+ -+#ifndef __SSS_CERTMAP_INT_H__ -+#define __SSS_CERTMAP_INT_H__ -+ -+#define CM_DEBUG(cm_ctx, format, ...) do { \ -+ if (cm_ctx != NULL && cm_ctx->debug != NULL) { \ -+ cm_ctx->debug(cm_ctx->debug_priv, __FILE__, __LINE__, __FUNCTION__, \ -+ format, ##__VA_ARGS__); \ -+ } \ -+} while (0) -+ -+#define DEFAULT_MATCH_RULE "digitalSignatureclientAuth" -+#define DEFAULT_MAP_RULE "LDAP:(userCertificate;binary={cert!bin})" -+ -+enum san_opt { -+ SAN_OTHER_NAME = 0, -+ SAN_RFC822_NAME, -+ SAN_DNS_NAME, -+ SAN_X400_ADDRESS, -+ SAN_DIRECTORY_NAME, -+ SAN_EDIPART_NAME, -+ SAN_URI, -+ SAN_IP_ADDRESS, -+ SAN_REGISTERED_ID, -+ SAN_PKINIT, -+ SAN_NT, -+ SAN_PRINCIPAL, -+ SAN_STRING_OTHER_NAME, -+ -+ SAN_END, -+ SAN_INVALID -+}; -+ -+/* KRB5 matching rule */ -+enum relation_type { -+ relation_none = 0, -+ relation_and, -+ relation_or -+}; -+ -+struct component_list { -+ char *val; -+ regex_t regexp; -+ uint32_t ku; -+ const char **eku_oid_list; -+ enum san_opt san_opt; -+ char *str_other_name_oid; -+ uint8_t *bin_val; -+ size_t bin_val_len; -+ struct component_list *prev; -+ struct component_list *next; -+}; -+ -+struct krb5_match_rule { -+ enum relation_type r; -+ struct component_list *issuer; -+ struct component_list *subject; -+ struct component_list *ku; -+ struct component_list *eku; -+ struct component_list *san; -+}; -+ -+enum comp_type { -+ comp_none = 0, -+ comp_string, -+ comp_template -+}; -+ -+struct parsed_template { -+ char *name; -+ char *attr_name; -+ char *conversion; -+}; -+ -+struct ldap_mapping_rule_comp { -+ enum comp_type type; -+ char *val; -+ struct parsed_template *parsed_template; -+ struct ldap_mapping_rule_comp *prev; -+ struct ldap_mapping_rule_comp *next; -+}; -+ -+struct ldap_mapping_rule { -+ struct ldap_mapping_rule_comp *list; -+}; -+ -+struct match_map_rule { -+ uint32_t priority; -+ char *match_rule; -+ struct krb5_match_rule *parsed_match_rule; -+ char *map_rule; -+ struct ldap_mapping_rule *parsed_mapping_rule; -+ char **domains; -+ struct match_map_rule *prev; -+ struct match_map_rule *next; -+}; -+ -+struct priority_list { -+ uint32_t priority; -+ struct match_map_rule *rule_list; -+ struct priority_list *prev; -+ struct priority_list *next; -+}; -+ -+struct sss_certmap_ctx { -+ struct priority_list *prio_list; -+ sss_certmap_ext_debug *debug; -+ void *debug_priv; -+ struct ldap_mapping_rule *default_mapping_rule; -+}; -+ -+struct san_list { -+ enum san_opt san_opt; -+ char *val; -+ uint8_t *bin_val; -+ size_t bin_val_len; -+ char *other_name_oid; -+ char *short_name; -+ const char **rdn_list; -+ struct san_list *prev; -+ struct san_list *next; -+}; -+ -+/* key usage flags, see RFC 3280 section 4.2.1.3 */ -+#define SSS_KU_DIGITAL_SIGNATURE 0x0080 -+#define SSS_KU_NON_REPUDIATION 0x0040 -+#define SSS_KU_KEY_ENCIPHERMENT 0x0020 -+#define SSS_KU_DATA_ENCIPHERMENT 0x0010 -+#define SSS_KU_KEY_AGREEMENT 0x0008 -+#define SSS_KU_KEY_CERT_SIGN 0x0004 -+#define SSS_KU_CRL_SIGN 0x0002 -+#define SSS_KU_ENCIPHER_ONLY 0x0001 -+#define SSS_KU_DECIPHER_ONLY 0x8000 -+ -+struct sss_cert_content { -+ const char *issuer_str; -+ const char **issuer_rdn_list; -+ const char *subject_str; -+ const char **subject_rdn_list; -+ uint32_t key_usage; -+ const char **extended_key_usage_oids; -+ struct san_list *san_list; -+ -+ uint8_t *cert_der; -+ size_t cert_der_size; -+}; -+ -+int sss_cert_get_content(TALLOC_CTX *mem_ctx, -+ const uint8_t *der_blob, size_t der_size, -+ struct sss_cert_content **content); -+ -+char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn); -+ -+int parse_krb5_match_rule(struct sss_certmap_ctx *ctx, -+ const char *rule_start, -+ struct krb5_match_rule **match_rule); -+ -+int parse_ldap_mapping_rule(struct sss_certmap_ctx *ctx, -+ const char *rule_start, -+ struct ldap_mapping_rule **mapping_rule); -+#endif /* __SSS_CERTMAP_INT_H__ */ -diff --git a/src/lib/certmap/sss_certmap_krb5_match.c b/src/lib/certmap/sss_certmap_krb5_match.c -new file mode 100644 -index 0000000000000000000000000000000000000000..e40f17b8ace46e61087e0a2fa570a362a84cead2 ---- /dev/null -+++ b/src/lib/certmap/sss_certmap_krb5_match.c -@@ -0,0 +1,558 @@ -+/* -+ SSSD -+ -+ Library for rule based certificate to user mapping - KRB5 matching rules -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2017 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 "util/util.h" -+#include "util/cert.h" -+#include "util/crypto/sss_crypto.h" -+#include "lib/certmap/sss_certmap.h" -+#include "lib/certmap/sss_certmap_int.h" -+ -+static bool is_dotted_decimal(const char *s, size_t len) -+{ -+ size_t c = 0; -+ bool has_dot = false; -+ -+ if (s == NULL || !isdigit(s[c++])) { -+ return false; -+ } -+ -+ while ((len == 0 && s[c] != '\0') || (len != 0 && c < len)) { -+ if (s[c] != '.' && !isdigit(s[c])) { -+ return false; -+ } -+ if (!has_dot && s[c] == '.') { -+ has_dot = true; -+ } -+ c++; -+ } -+ -+ return (has_dot && isdigit(s[c - 1])); -+} -+ -+static int component_list_destructor(void *data) -+{ -+ struct component_list *comp = talloc_get_type(data, struct component_list); -+ -+ if (comp != NULL) { -+ regfree(&(comp->regexp)); -+ } -+ -+ return 0; -+} -+ -+/* -+ * The syntax of the MIT Kerberos style matching rules is: -+ * [KRB5:][relation-operator]component-rule ... -+ * -+ * where: -+ * -+ * relation-operator -+ * can be either &&, meaning all component rules must match, or ||, -+ * meaning only one component rule must match. The default is &&. -+ * -+ * component-rule -+ * can be one of the following. Note that there is no punctuation or whitespace between component rules. -+ * regular-expression -+ * regular-expression -+ * regular-expression -+ * extended-key-usage -+ * key-usage -+ * -+ * see man sss-certmap for more details -+ * -+ */ -+ -+static int get_comp_value(TALLOC_CTX *mem_ctx, -+ struct sss_certmap_ctx *ctx, -+ const char **cur, -+ struct component_list **_comp) -+ -+{ -+ struct component_list *comp = NULL; -+ const char *end; -+ int ret; -+ -+ comp = talloc_zero(mem_ctx, struct component_list); -+ if (comp == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ talloc_set_destructor((TALLOC_CTX *) comp, component_list_destructor); -+ -+ end = strchr(*cur, '<'); -+ -+ if (end == NULL) { -+ comp->val = talloc_strdup(comp, *cur); -+ } else { -+ comp->val = talloc_strndup(comp, *cur, end - *cur); -+ } -+ if (comp->val == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ if (*(comp->val) == '\0') { -+ CM_DEBUG(ctx, "Missing component value."); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ *cur += strlen(comp->val); -+ *_comp = comp; -+ ret = 0; -+ -+done: -+ if (ret != 0) { -+ talloc_free(comp); -+ } -+ -+ return ret; -+} -+ -+static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx, -+ struct sss_certmap_ctx *ctx, -+ const char **cur, -+ struct component_list **_comp) -+{ -+ struct component_list *comp = NULL; -+ int ret; -+ char **eku_list; -+ size_t c; -+ size_t k; -+ const char *o; -+ size_t e = 0; -+ int eku_list_size; -+ -+ struct ext_key_usage { -+ const char *name; -+ const char *oid; -+ } ext_key_usage[] = { -+ /* RFC 3280 section 4.2.1.13 */ -+ {"serverAuth", "1.3.6.1.5.5.7.3.1"}, -+ {"clientAuth", "1.3.6.1.5.5.7.3.2"}, -+ {"codeSigning", "1.3.6.1.5.5.7.3.3"}, -+ {"emailProtection", "1.3.6.1.5.5.7.3.4"}, -+ {"timeStamping", "1.3.6.1.5.5.7.3.8"}, -+ {"OCSPSigning", "1.3.6.1.5.5.7.3.9"}, -+ -+ /* RFC 4556 section 3.2.2 */ -+ {"KPClientAuth", "1.3.6.1.5.2.3.4"}, -+ {"pkinit", "1.3.6.1.5.2.3.4"}, -+ -+ /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/ -+ {"msScLogin", "1.3.6.1.4.1.311.20.2.2"}, -+ -+ {NULL ,0} -+ }; -+ -+ ret = get_comp_value(mem_ctx, ctx, cur, &comp); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to parse regexp."); -+ goto done; -+ } -+ -+ ret = split_on_separator(mem_ctx, comp->val, ',', true, true, -+ &eku_list, &eku_list_size); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to split list."); -+ goto done; -+ } -+ -+ for (c = 0; eku_list[c] != NULL; c++) { -+ for (k = 0; ext_key_usage[k].name != NULL; k++) { -+CM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name); -+ if (strcasecmp(eku_list[c], ext_key_usage[k].name) == 0) { -+ if (comp->eku_oid_list == NULL) { -+ comp->eku_oid_list = talloc_zero_array(comp, const char *, -+ eku_list_size + 1); -+ if (comp->eku_oid_list == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list, -+ ext_key_usage[k].oid); -+ if (comp->eku_oid_list[e] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ e++; -+ break; -+ } -+ } -+ -+ if (ext_key_usage[k].name == NULL) { -+ /* check for an dotted-decimal OID */ -+ if (*(eku_list[c]) != '.') { -+ o = eku_list[c]; -+ if (is_dotted_decimal(o, 0)) { -+ /* looks like a OID, only '.' and digits */ -+ comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list, -+ eku_list[c]); -+ if (comp->eku_oid_list[e] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ e++; -+ continue; -+ } -+ } -+ CM_DEBUG(ctx, "No matching extended key usage found."); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *_comp = comp; -+ } else { -+ talloc_free(comp); -+ } -+ -+ return ret; -+} -+ -+static int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx, -+ struct sss_certmap_ctx *ctx, -+ const char **cur, -+ struct component_list **_comp) -+{ -+ struct component_list *comp = NULL; -+ int ret; -+ char **ku_list; -+ size_t c; -+ size_t k; -+ -+ struct key_usage { -+ const char *name; -+ uint32_t flag; -+ } key_usage[] = { -+ {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE}, -+ {"nonRepudiation" , SSS_KU_NON_REPUDIATION}, -+ {"keyEncipherment" , SSS_KU_KEY_ENCIPHERMENT}, -+ {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT}, -+ {"keyAgreement" , SSS_KU_KEY_AGREEMENT}, -+ {"keyCertSign" , SSS_KU_KEY_CERT_SIGN}, -+ {"cRLSign" , SSS_KU_CRL_SIGN}, -+ {"encipherOnly" , SSS_KU_ENCIPHER_ONLY}, -+ {"decipherOnly" , SSS_KU_DECIPHER_ONLY}, -+ {NULL ,0} -+ }; -+ -+ -+ ret = get_comp_value(mem_ctx, ctx, cur, &comp); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to get value."); -+ goto done; -+ } -+ -+ ret = split_on_separator(mem_ctx, comp->val, ',', true, true, -+ &ku_list, NULL); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to split list."); -+ goto done; -+ } -+ -+ for (c = 0; ku_list[c] != NULL; c++) { -+ for (k = 0; key_usage[k].name != NULL; k++) { -+ if (strcasecmp(ku_list[c], key_usage[k].name) == 0) { -+ comp->ku |= key_usage[k].flag; -+ break; -+ } -+ } -+ -+ if (key_usage[k].name == NULL) { -+ /* FIXME: add check for numerical ku */ -+ CM_DEBUG(ctx, "No matching key usage found."); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *_comp = comp; -+ } else { -+ talloc_free(comp); -+ } -+ -+ return ret; -+} -+ -+static int parse_krb5_get_component_value(TALLOC_CTX *mem_ctx, -+ struct sss_certmap_ctx *ctx, -+ const char **cur, -+ struct component_list **_comp) -+{ -+ struct component_list *comp = NULL; -+ int ret; -+ -+ ret = get_comp_value(mem_ctx, ctx, cur, &comp); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to parse regexp."); -+ goto done; -+ } -+ -+ ret = regcomp(&(comp->regexp), comp->val, REG_EXTENDED); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to parse regexp."); -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *_comp = comp; -+ } else { -+ talloc_free(comp); -+ } -+ -+ return ret; -+} -+ -+struct san_name { -+ const char *name; -+ enum san_opt san_opt; -+ bool is_string; -+} san_names[] = { -+ /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */ -+ {"otherName", SAN_OTHER_NAME, false}, -+ {"rfc822Name", SAN_RFC822_NAME,true}, -+ {"dNSName", SAN_DNS_NAME, true}, -+ {"x400Address", SAN_X400_ADDRESS, false}, -+ {"directoryName", SAN_DIRECTORY_NAME, true}, -+ {"ediPartyName", SAN_EDIPART_NAME, false}, -+ {"uniformResourceIdentifier", SAN_URI, true}, -+ {"iPAddress", SAN_IP_ADDRESS, true}, -+ {"registeredID", SAN_REGISTERED_ID, true}, -+ /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */ -+ {"pkinitSAN", SAN_PKINIT, true}, -+ /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */ -+ {"ntPrincipalName", SAN_NT, true}, -+ /* both previous principal types */ -+ {"Principal", SAN_PRINCIPAL, true}, -+ {"stringOtherName", SAN_STRING_OTHER_NAME, true}, -+ {NULL, SAN_END, false} -+}; -+ -+static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx, -+ struct sss_certmap_ctx *ctx, -+ const char **cur, -+ enum san_opt *option, -+ char **str_other_name_oid) -+{ -+ char *end; -+ size_t c; -+ size_t len; -+ -+ end = strchr(*cur, '>'); -+ if (end == NULL) { -+ CM_DEBUG(ctx, "Failed to parse SAN option."); -+ return EINVAL; -+ } -+ -+ len = end - *cur; -+ -+ if (len == 0) { -+ c= SAN_PRINCIPAL; -+ } else { -+ for (c = 0; san_names[c].name != NULL; c++) { -+ if (strncasecmp(*cur, san_names[c].name, len) == 0) { -+ break; -+ } -+ } -+ if (san_names[c].name == NULL) { -+ if (is_dotted_decimal(*cur, len)) { -+ c = SAN_STRING_OTHER_NAME; -+ *str_other_name_oid = talloc_strndup(mem_ctx, *cur, len); -+ if (*str_other_name_oid == NULL) { -+ CM_DEBUG(ctx, "talloc_strndup failed."); -+ return ENOMEM; -+ } -+ } else { -+ CM_DEBUG(ctx, "Unknown SAN option."); -+ return EINVAL; -+ } -+ } -+ } -+ -+ *option = san_names[c].san_opt; -+ *cur = end + 1; -+ -+ return 0; -+} -+ -+static int parse_krb5_get_san_value(TALLOC_CTX *mem_ctx, -+ struct sss_certmap_ctx *ctx, -+ const char **cur, -+ struct component_list **_comp) -+{ -+ struct component_list *comp = NULL; -+ enum san_opt san_opt = SAN_PRINCIPAL; -+ int ret; -+ char *str_other_name_oid = NULL; -+ -+ if (*(*cur - 1) == ':') { -+ ret = parse_krb5_get_san_option(mem_ctx, ctx, cur, &san_opt, -+ &str_other_name_oid); -+ if (ret != 0) { -+ goto done; -+ } -+ } -+ -+ if (san_names[san_opt].is_string) { -+ ret = parse_krb5_get_component_value(mem_ctx, ctx, cur, &comp); -+ if (ret != 0) { -+ goto done; -+ } -+ } else { -+ ret = get_comp_value(mem_ctx, ctx, cur, &comp); -+ if (ret != 0) { -+ goto done; -+ } -+ -+ if (comp->val != NULL) { -+ comp->bin_val = sss_base64_decode(comp, comp->val, -+ &comp->bin_val_len); -+ /* for some reasons the NSS version of sss_base64_decode might -+ * return a non-NULL value on error but len is still 0, so better -+ * check both. */ -+ if (comp->bin_val == NULL || comp->bin_val_len == 0) { -+ CM_DEBUG(ctx, "Base64 decode failed."); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ } -+ comp->san_opt = san_opt; -+ -+done: -+ if (ret == 0) { -+ comp->str_other_name_oid = talloc_steal(comp, str_other_name_oid); -+ *_comp = comp; -+ } else { -+ talloc_free(comp); -+ talloc_free(str_other_name_oid); -+ } -+ -+ return ret; -+} -+ -+int parse_krb5_match_rule(struct sss_certmap_ctx *ctx, -+ const char *rule_start, -+ struct krb5_match_rule **match_rule) -+{ -+ const char *cur; -+ struct krb5_match_rule *rule; -+ struct component_list *comp; -+ int ret; -+ -+ rule = talloc_zero(ctx, struct krb5_match_rule); -+ if (rule == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ cur = rule_start; -+ /* check relation */ -+ if (strncmp(cur, "&&", 2) == 0) { -+ rule->r = relation_and; -+ cur += 2; -+ } else if (strncmp(cur, "||", 2) == 0) { -+ rule->r = relation_or; -+ cur += 2; -+ } else { -+ rule->r = relation_and; -+ } -+ -+ while (*cur != '\0') { -+ /* new component must start with '<' */ -+ if (*cur != '<') { -+ CM_DEBUG(ctx, "Invalid KRB5 matching rule."); -+ ret = EINVAL; -+ goto done; -+ } -+ cur++; -+ -+ if (strncmp(cur, "ISSUER>", 7) == 0) { -+ cur += 7; -+ ret = parse_krb5_get_component_value(rule, ctx, &cur, &comp); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(rule->issuer, comp); -+ } else if (strncmp(cur, "SUBJECT>", 8) == 0) { -+ cur += 8; -+ ret = parse_krb5_get_component_value(rule, ctx, &cur, &comp); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(rule->subject, comp); -+ } else if (strncmp(cur, "KU>", 3) == 0) { -+ cur += 3; -+ ret = parse_krb5_get_ku_value(rule, ctx, &cur, &comp); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(rule->ku, comp); -+ } else if (strncmp(cur, "EKU>", 4) == 0) { -+ cur += 4; -+ ret = parse_krb5_get_eku_value(rule, ctx, &cur, &comp); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(rule->eku, comp); -+ } else if (strncmp(cur, "SAN>", 4) == 0 -+ || strncmp(cur, "SAN:", 4) == 0) { -+ cur += 4; -+ ret = parse_krb5_get_san_value(rule, ctx, &cur, &comp); -+ if (ret != 0) { -+ goto done; -+ } -+ DLIST_ADD(rule->san, comp); -+ } else { -+ CM_DEBUG(ctx, "Invalid KRB5 matching rule."); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *match_rule = rule; -+ } else { -+ talloc_free(rule); -+ } -+ -+ return ret; -+} -diff --git a/src/lib/certmap/sss_certmap_ldap_mapping.c b/src/lib/certmap/sss_certmap_ldap_mapping.c -new file mode 100644 -index 0000000000000000000000000000000000000000..c64c05b311f043b4d70f98f718780601c3e6a002 ---- /dev/null -+++ b/src/lib/certmap/sss_certmap_ldap_mapping.c -@@ -0,0 +1,367 @@ -+/* -+ SSSD -+ -+ Library for rule based certificate to user mapping - LDAP mapping rules -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2017 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 "util/util.h" -+#include "util/cert.h" -+#include "util/crypto/sss_crypto.h" -+#include "lib/certmap/sss_certmap.h" -+#include "lib/certmap/sss_certmap_int.h" -+struct template_table { -+ const char *name; -+ const char **attr_name; -+ const char **conversion; -+}; -+ -+const char *empty[] = {NULL}; -+const char *name_attr[] = {"short_name", NULL}; -+const char *x500_conv[] = {"ad_x500", "ad", "ad_ldap", -+ "nss_x500", "nss", "nss_ldap", NULL}; -+const char *bin_conv[] = {"bin", "base64", NULL}; -+ -+struct template_table template_table[] = { -+ {"issuer_dn", empty, x500_conv}, -+ {"subject_dn", empty, x500_conv}, -+ {"cert", empty, bin_conv}, -+ {"subject_rfc822_name", name_attr, empty}, -+ {"subject_dns_name", name_attr, empty}, -+ {"subject_x400_address", empty, empty}, -+ {"subject_directory_name", empty, empty}, -+ {"subject_ediparty_name", empty, empty}, -+ {"subject_uri", empty, empty}, -+ {"subject_ip_address", empty, empty}, -+ {"subject_registered_id", empty, empty}, -+ {"subject_pkinit_principal", name_attr, empty}, -+ {"subject_nt_principal", name_attr, empty}, -+ {"subject_principal", name_attr, empty}, -+ {NULL, NULL, NULL}}; -+ -+static int check_parsed_template(struct sss_certmap_ctx *ctx, -+ struct parsed_template *parsed) -+{ -+ size_t n; -+ size_t a; -+ size_t c; -+ bool attr_name_valid = false; -+ bool conversion_valid = false; -+ -+ for (n = 0; template_table[n].name != NULL; n++) { -+ if (strcmp(template_table[n].name, parsed->name) != 0) { -+ continue; -+ } -+ -+ if (parsed->attr_name != NULL) { -+ for (a = 0; template_table[n].attr_name[a] != NULL; a++) { -+ if (strcmp(template_table[n].attr_name[a], -+ parsed->attr_name) == 0) { -+ attr_name_valid = true; -+ break; -+ } -+ } -+ } else { -+ attr_name_valid = true; -+ } -+ -+ if (parsed->conversion != NULL) { -+ for (c = 0; template_table[n].conversion[c] != NULL; c++) { -+ if (strcmp(template_table[n].conversion[c], -+ parsed->conversion) == 0) { -+ conversion_valid = true; -+ break; -+ } -+ } -+ } else { -+ conversion_valid = true; -+ } -+ -+ if (attr_name_valid && conversion_valid) { -+ return 0; -+ } -+ } -+ -+ return EINVAL; -+} -+ -+static int parse_template(TALLOC_CTX *mem_ctx, struct sss_certmap_ctx *ctx, -+ const char *template, -+ struct parsed_template **parsed_template) -+{ -+ int ret; -+ struct parsed_template *parsed = NULL; -+ const char *dot; -+ const char *excl; -+ const char *p; -+ -+ parsed = talloc_zero(mem_ctx, struct parsed_template); -+ if (parsed == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ dot = strchr(template, '.'); -+ if (dot != NULL) { -+ p = strchr(dot + 1, '.'); -+ if (p != NULL) { -+ CM_DEBUG(ctx, "Only one '.' allowed in template."); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (dot == template) { -+ CM_DEBUG(ctx, "Missing name in template."); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ excl = strchr(template, '!'); -+ if (excl != NULL) { -+ p = strchr(excl + 1, '!'); -+ if (p != NULL) { -+ CM_DEBUG(ctx, "Only one '!' allowed in template."); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (excl == template) { -+ CM_DEBUG(ctx, "Missing name in template."); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ if (excl != NULL && excl[1] != '\0') { -+ parsed->conversion = talloc_strdup(parsed, excl + 1); -+ if (parsed->conversion == NULL) { -+ CM_DEBUG(ctx, "Memory allocation failed."); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ if (dot != NULL && dot[1] != '\0' && dot[1] != '!') { -+ if (excl == NULL) { -+ parsed->attr_name = talloc_strdup(parsed, dot + 1); -+ } else { -+ parsed->attr_name = talloc_strndup(parsed, dot + 1, -+ (excl - dot - 1)); -+ } -+ if (parsed->attr_name == NULL) { -+ CM_DEBUG(ctx, "Memory allocation failed."); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ if (dot != NULL) { -+ parsed->name = talloc_strndup(parsed, template, (dot - template)); -+ } else if (excl != NULL) { -+ parsed->name = talloc_strndup(parsed, template, (excl - template)); -+ } else { -+ parsed->name = talloc_strdup(parsed, template); -+ } -+ if (parsed->name == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = check_parsed_template(ctx, parsed); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Parse template invalid."); -+ goto done; -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *parsed_template = parsed; -+ } else { -+ talloc_free(parsed); -+ } -+ -+ return ret; -+} -+ -+static int add_comp(struct sss_certmap_ctx *ctx, struct ldap_mapping_rule *rule, -+ const char *string, enum comp_type type) -+{ -+ int ret; -+ struct ldap_mapping_rule_comp *comp; -+ -+ comp = talloc_zero(rule, struct ldap_mapping_rule_comp); -+ if (comp == NULL) { -+ return ENOMEM; -+ } -+ -+ comp->type = type; -+ comp->val = talloc_strdup(comp, string); -+ if (comp->val == NULL) { -+ talloc_free(comp); -+ return ENOMEM; -+ } -+ -+ if (type == comp_template) { -+ ret = parse_template(comp, ctx, string, &comp->parsed_template); -+ if (ret != 0) { -+ talloc_free(comp); -+ return ret; -+ } -+ } -+ -+ DLIST_ADD_END(rule->list, comp, struct ldap_mapping_rule_comp *); -+ -+ return 0; -+} -+ -+static int add_string(struct sss_certmap_ctx *ctx, -+ struct ldap_mapping_rule *rule, const char *string) -+{ -+ return add_comp(ctx, rule, string, comp_string); -+} -+ -+static int add_template(struct sss_certmap_ctx *ctx, -+ struct ldap_mapping_rule *rule, const char *string) -+{ -+ return add_comp(ctx, rule, string, comp_template); -+} -+ -+int parse_ldap_mapping_rule(struct sss_certmap_ctx *ctx, -+ const char *rule_start, -+ struct ldap_mapping_rule **mapping_rule) -+{ -+ size_t c; -+ const char *cur; -+ char *tmp_string = NULL; -+ size_t tmp_string_size; -+ struct ldap_mapping_rule *rule = NULL; -+ int ret; -+ bool in_template = false; -+ -+ rule = talloc_zero(ctx, struct ldap_mapping_rule); -+ if (rule == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ tmp_string_size = strlen(rule_start) + 1; -+ tmp_string = talloc_zero_size(ctx, tmp_string_size); -+ if (tmp_string == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ cur = rule_start; -+ c = 0; -+ -+ while (*cur != '\0') { -+ if (c > tmp_string_size) { -+ CM_DEBUG(ctx, "Cannot parse mapping rule."); -+ ret = EIO; -+ goto done; -+ } -+ switch (*cur) { -+ case '{': -+ if (in_template) { -+ CM_DEBUG(ctx, "'{' not allowed in templates."); -+ ret = EINVAL; -+ goto done; -+ } -+ if (cur[1] == '{') { -+ /* Add only a single '{' to the output */ -+ tmp_string[c] = '{'; -+ c++; -+ cur += 2; -+ } else { -+ if (c != 0) { -+ ret = add_string(ctx, rule, tmp_string); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to add string."); -+ ret = EINVAL; -+ goto done; -+ } -+ memset(tmp_string, 0, tmp_string_size); -+ c = 0; -+ } -+ cur++; -+ in_template = true; -+ } -+ break; -+ case '}': -+ if (cur[1] == '}') { -+ if (in_template) { -+ CM_DEBUG(ctx, "'}}' not allowed in templates."); -+ ret = EINVAL; -+ goto done; -+ } else { -+ /* Add only a single '}' to the output */ -+ tmp_string[c] = '}'; -+ c++; -+ cur += 2; -+ } -+ } else { -+ ret = add_template(ctx, rule, tmp_string); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to add template."); -+ ret = EINVAL; -+ goto done; -+ } -+ memset(tmp_string, 0, tmp_string_size); -+ c = 0; -+ cur++; -+ in_template = false; -+ } -+ break; -+ default: -+ tmp_string[c] = *cur; -+ c++; -+ cur++; -+ } -+ } -+ if (in_template) { -+ CM_DEBUG(ctx, "Rule ended inside template."); -+ ret = EINVAL; -+ goto done; -+ } -+ if (c != 0) { -+ ret = add_string(ctx, rule, tmp_string); -+ if (ret != 0) { -+ CM_DEBUG(ctx, "Failed to add string."); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ ret = 0; -+ -+done: -+ if (ret == 0) { -+ *mapping_rule = rule; -+ } else { -+ talloc_free(rule); -+ } -+ -+ talloc_free(tmp_string); -+ -+ return ret; -+} -diff --git a/src/man/Makefile.am b/src/man/Makefile.am -index 215ce693b56e74db394dbc238c03c87f5f6efe99..142d6e2743f814294e3d92c8342070b8230bb3e5 100644 ---- a/src/man/Makefile.am -+++ b/src/man/Makefile.am -@@ -59,7 +59,7 @@ man_MANS = \ - sss_useradd.8 sss_userdel.8 sss_usermod.8 \ - sss_groupadd.8 sss_groupdel.8 sss_groupmod.8 \ - sssd.8 sssd.conf.5 sssd-ldap.5 \ -- sssd-krb5.5 sssd-simple.5 \ -+ sssd-krb5.5 sssd-simple.5 sss-certmap.5 \ - sssd_krb5_locator_plugin.8 sss_groupshow.8 \ - pam_sss.8 sss_obfuscate.8 sss_cache.8 sss_debuglevel.8 sss_seed.8 \ - sss_override.8 idmap_sss.8 sssctl.8 \ -diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg -index ffcf9a2793da3c0115bc846744ccb9592a9a68ef..d1f6ac39f841c61ae3d2393fb3402dc21b9cbd69 100644 ---- a/src/man/po/po4a.cfg -+++ b/src/man/po/po4a.cfg -@@ -6,6 +6,7 @@ - [type:docbook] pam_sss.8.xml $lang:$(builddir)/$lang/pam_sss.8.xml - [type:docbook] sssd_krb5_locator_plugin.8.xml $lang:$(builddir)/$lang/sssd_krb5_locator_plugin.8.xml - [type:docbook] sssd-simple.5.xml $lang:$(builddir)/$lang/sssd-simple.5.xml -+[type:docbook] sss-certmap.5.xml $lang:$(builddir)/$lang/sss-certmap.5.xml - [type:docbook] sssd-ipa.5.xml $lang:$(builddir)/$lang/sssd-ipa.5.xml - [type:docbook] sssd-ad.5.xml $lang:$(builddir)/$lang/sssd-ad.5.xml - [type:docbook] sssd-sudo.5.xml $lang:$(builddir)/$lang/sssd-sudo.5.xml -diff --git a/src/man/sss-certmap.5.xml b/src/man/sss-certmap.5.xml -new file mode 100644 -index 0000000000000000000000000000000000000000..bbe68509f2222613a7ed69599519d7fca0506df0 ---- /dev/null -+++ b/src/man/sss-certmap.5.xml -@@ -0,0 +1,600 @@ -+ -+ -+ -+SSSD Manual pages -+ -+ -+ -+ -+ sss-certmap -+ 5 -+ File Formats and Conventions -+ -+ -+ -+ sss-certmap -+ SSSD Certificate Matching and Mapping Rules -+ -+ -+ -+ DESCRIPTION -+ -+ The manual page describes the rules which can be used by SSSD and -+ other components to match X.509 certificates and map them to -+ accounts. -+ -+ -+ Each rule has four components, a priority, a -+ matching rule, a mapping rule and a -+ domain list. All components are optional. A missing -+ priority will add the rule with the lowest priority. -+ The default matching rule will match certificates with -+ the digitalSignature key usage and clientAuth extended key usage. If -+ the mapping rule is empty the certificates will be -+ searched in the userCertificate attribute as DER encoded binary. If -+ no domains are given only the local domain will be searched. -+ -+ -+ -+ -+ RULE COMPONENTS -+ -+ PRIORITY -+ -+ The rules are process by priority while the number '0' (zero) -+ indicates the highest priority. The higher the number the lower is -+ the priority. A missing value indicates the lowest priority. -+ -+ -+ Internally the priority is treated as unsigned 32bit integer, using -+ a priority value larger than 4294967295 will cause an error. -+ -+ -+ -+ MATCHING RULE -+ -+ The matching rule is used to select a certificate to which the -+ mapping rule should be applied. It uses a system similar to the one -+ used by pkinit_cert_match option of MIT Kerberos. It -+ consists of a keyword enclosed by '<' and '>' which identified -+ a certain part of the certificate and a pattern which should be -+ found for the rule to match. Multiple keyword pattern pairs can be -+ either joined with '&&' (and) or '||' (or). -+ -+ -+ The available options are: -+ -+ -+ <SUBJECT>regular-expression -+ -+ -+ With this a part or the whole subject name of the -+ certificate can be matched. For the matching POSIX -+ Extended Regular Expression syntax is used, see regex(7) -+ for details. -+ -+ -+ For the matching the subject name stored in the -+ certificate in DER encoded ASN.1 is converted into a -+ string according to RFC 4514. This means the most -+ specific name component comes first. Please note that -+ not all possible attribute names are covered by RFC -+ 4514. The names included are 'CN', 'L', 'ST', 'O', -+ 'OU', 'C', 'STREET', 'DC' and 'UID'. Other attribute -+ names might be shown differently on different platform -+ and by different tools. To avoid confusion those -+ attribute names are best not used or covered by a -+ suitable regular-expression. -+ -+ -+ Example: <SUBJECT>.*,DC=MY,DC=DOMAIN -+ -+ -+ -+ -+ <ISSUER>regular-expression -+ -+ -+ With this a part or the whole issuer name of the -+ certificate can be matched. All comments for -+ <SUBJECT> apply her as well. -+ -+ -+ Example: <ISSUER>^CN=My-CA,DC=MY,DC=DOMAIN$ -+ -+ -+ -+ -+ <KU>key-usage -+ -+ -+ This option can be used to specify which key usage -+ values the certificate should have. The following value -+ can be used in a comma separate list: -+ -+ digitalSignature -+ nonRepudiation -+ keyEncipherment -+ dataEncipherment -+ keyAgreement -+ keyCertSign -+ cRLSign -+ encipherOnly -+ decipherOnly -+ -+ -+ -+ A numerical value in the range of a 32bit unsigned -+ integer can be used as well to cover special use cases. -+ -+ -+ Example: <KU>digitalSignature,keyEncipherment -+ -+ -+ -+ -+ <EKU>extended-key-usage -+ -+ -+ This option can be used to specify which extended key -+ usage the certificate should have. The following value -+ can be used in a comma separated list: -+ -+ serverAuth -+ clientAuth -+ codeSigning -+ emailProtection -+ timeStamping -+ OCSPSigning -+ KPClientAuth -+ pkinit -+ msScLogin -+ -+ -+ -+ Extended key usages which are not listed above can be -+ specified with their OID in dotted-decimal notation. -+ -+ -+ Example: <EKU>clientAuth,1.3.6.1.5.2.3.4 -+ -+ -+ -+ -+ <SAN>regular-expression -+ -+ -+ To be compatible with the usage of MIT Kerberos this -+ option will match the Kerberos principals in the PKINIT -+ or AD NT Principal SAN as <SAN:Principal> does. -+ -+ -+ Example: <SAN>.*@MY\.REALM -+ -+ -+ -+ -+ <SAN:Principal>regular-expression -+ -+ -+ Match the Kerberos principals in the PKINIT or AD NT -+ Principal SAN. -+ -+ -+ Example: <SAN:Principal>.*@MY\.REALM -+ -+ -+ -+ -+ <SAN:ntPrincipalName>regular-expression -+ -+ -+ Match the Kerberos principals from the AD NT Principal -+ SAN. -+ -+ -+ Example: <SAN:ntPrincipalName>.*@MY.AD.REALM -+ -+ -+ -+ -+ <SAN:pkinit>regular-expression -+ -+ -+ Match the Kerberos principals from the PKINIT SAN. -+ -+ -+ Example: <SAN:ntPrincipalName>.*@MY\.PKINIT\.REALM -+ -+ -+ -+ -+ <SAN:dotted-decimal-oid>regular-expression -+ -+ -+ Take the value of the otherName SAN component given by -+ the OID in dotted-decimal notation, interpret it as -+ string and try to match it against the regular -+ expression. -+ -+ -+ Example: <SAN:1.2.3.4>test -+ -+ -+ -+ -+ <SAN:otherName>base64-string -+ -+ -+ Do a binary match with the base64 encoded blob against -+ all otherName SAN components. With this option it is -+ possible to match against custom otherName components -+ with special encodings which could not be treated as -+ strings. -+ -+ -+ Example: <SAN:otherName>MTIz -+ -+ -+ -+ -+ <SAN:rfc822Name>regular-expression -+ -+ -+ Match the value of the rfc822Name SAN. -+ -+ -+ Example: <SAN:rfc822Name>.*@email\.domain -+ -+ -+ -+ -+ <SAN:dNSName>regular-expression -+ -+ -+ Match the value of the dNSName SAN. -+ -+ -+ Example: <SAN:dNSName>.*\.my\.dns\.domain -+ -+ -+ -+ -+ <SAN:x400Address>base64-string -+ -+ -+ Binary match the value of the x400Address SAN. -+ -+ -+ Example: <SAN:x400Address>MTIz -+ -+ -+ -+ -+ <SAN:directoryName>regular-expression -+ -+ -+ Match the value of the directoryName SAN. The same -+ comments as given for <ISSUER> and <SUBJECT> -+ apply here as well. -+ -+ -+ Example: <SAN:directoryName>.*,DC=com -+ -+ -+ -+ -+ <SAN:ediPartyName>base64-string -+ -+ -+ Binary match the value of the ediPartyName SAN. -+ -+ -+ Example: <SAN:ediPartyName>MTIz -+ -+ -+ -+ -+ <SAN:uniformResourceIdentifier>regular-expression -+ -+ -+ Match the value of the uniformResourceIdentifier SAN. -+ -+ -+ Example: <SAN:uniformResourceIdentifier>URN:.* -+ -+ -+ -+ -+ <SAN:iPAddress>regular-expression -+ -+ -+ Match the value of the iPAddress SAN. -+ -+ -+ Example: <SAN:iPAddress>192\.168\..* -+ -+ -+ -+ -+ <SAN:registeredID>regular-expression -+ -+ -+ Match the value of the registeredID SAN as -+ dotted-decimal string. -+ -+ -+ Example: <SAN:registeredID>1\.2\.3\..* -+ -+ -+ -+ -+ -+ -+ -+ MAPPING RULE -+ -+ The mapping rule is used to associate a certificate with one or more -+ accounts. A Smartcard with the certificate and the matching private -+ key can then be used to authenticate as one of those accounts. -+ -+ -+ Currently SSSD basically only supports LDAP to lookup user -+ information (the exception is the proxy provider which is not of -+ relevance here). Because of this the mapping rule is based on LDAP -+ search filter syntax with templates to add certificate content to -+ the filter. It is expected that the filter will only contain the -+ specific data needed for the mapping an that the caller will embed -+ it in another filter to do the actual search. Because of this the -+ filter string should start and stop with '(' and ')' respectively. -+ -+ -+ In general it is recommended to use attributes from the certificate -+ and add them to special attributes to the LDAP user object. E.g. the -+ 'altSecurityIdentities' attribute in AD or the 'ipaCertMapData' -+ attribute for IPA can be used. -+ -+ -+ This should be preferred to read user specific data from the -+ certificate like e.g. an email address and search for it in the LDAP -+ server. The reason is that the user specific data in LDAP might -+ change for various reasons would would break the mapping. On the -+ other hand it would be hard to break the mapping on purpose for a -+ specific user. -+ -+ -+ The templates to add certificate data to the search filter are based -+ on Python-style formatting strings. They consists of a keyword in -+ curly braces with an optional sub-component specifier separated by a -+ '.' or an optional conversion/formatting option separated by a '!'. -+ Allowed values are: -+ -+ -+ {issuer_dn[!((ad|ad_x500)|ad_ldap|nss_x500|(nss|nss_ldap))]} -+ -+ -+ This template will add the full issuer DN converted to a -+ string according to RFC 4514. If X.500 ordering (most -+ specific RDN comes last) an option with the '_x500' -+ prefix should be used. -+ -+ -+ The conversion options starting with 'ad_' will use -+ attribute names as used by AD, e.g. 'S' instead of 'ST'. -+ -+ -+ The conversion options starting with 'nss_' will use -+ attribute names as used by NSS. -+ -+ -+ The default conversion option is 'nss', i.e. attribute -+ names according to NSS and LDAP/RFC 4514 ordering. -+ -+ -+ Example: (ipacertmapdata=X509:<I>{issuer_dn!ad}<S>{subject_dn!ad}) -+ -+ -+ -+ -+ {subject_dn[!((ad|ad_x500)|ad_ldap|nss_x500|(nss|nss_ldap))]} -+ -+ -+ This template will add the full subject DN converted to -+ string according to RFC 4514. If X.500 ordering (most -+ specific RDN comes last) an option with the '_x500' -+ prefix should be used. -+ -+ -+ The conversion options starting with 'ad_' will use -+ attribute names as used by AD, e.g. 'S' instead of 'ST'. -+ -+ -+ The conversion options starting with 'nss_' will use -+ attribute names as used by NSS. -+ -+ -+ The default conversion option is 'nss', i.e. attribute -+ names according to NSS and LDAP/RFC 4514 ordering. -+ -+ -+ Example: (ipacertmapdata=X509:<I>{issuer_dn!nss_x500}<S>{subject_dn!nss_x500}) -+ -+ -+ -+ -+ {cert[!(bin|base64)]} -+ -+ -+ This template will add the whole DER encoded certificate -+ as a string to the search filter. Depending on the -+ conversion option the binary certificate is either -+ converted to an escaped hex sequence '\xx' or base64. -+ The escaped hex sequence is the default and can e.g. be -+ used with the LDAP attribute 'userCertificate;binary'. -+ -+ -+ Example: (userCertificate;binary={cert!bin}) -+ -+ -+ -+ -+ {subject_principal[.short_name]} -+ -+ -+ This template will add the Kerberos principal which is -+ taken either from the SAN used by pkinit or the one used -+ by AD. The 'short_name' component represent the first -+ part of the principal before the '@' sign. -+ -+ -+ Example: (|(userPrincipal={subject_principal})(samAccountName={subject_principal.short_name})) -+ -+ -+ -+ -+ {subject_pkinit_principal[.short_name]} -+ -+ -+ This template will add the Kerberos principal which is -+ given by then SAN used by pkinit. The 'short_name' -+ component represent the first part of the principal -+ before the '@' sign. -+ -+ -+ Example: (|(userPrincipal={subject_pkinit_principal})(uid={subject_pkinit_principal.short_name})) -+ -+ -+ -+ -+ {subject_nt_principal[.short_name]} -+ -+ -+ This template will add the Kerberos principal which is -+ given by then SAN used by AD. The 'short_name' component -+ represent the first part of the principal before the '@' -+ sign. -+ -+ -+ Example: (|(userPrincipal={subject_principal})(samAccountName={subject_principal.short_name})) -+ -+ -+ -+ -+ {subject_rfc822_name[.short_name]} -+ -+ -+ This template will add the string which is stored in the -+ rfc822Name component of the SAN, typically an email -+ address. The 'short_name' component represent the first -+ part of the address before the '@' sign. -+ -+ -+ Example: (|(mail={subject_rfc822_name})(uid={subject_rfc822_name.short_name})) -+ -+ -+ -+ -+ {subject_dns_name[.short_name]} -+ -+ -+ This template will add the string which is stored in the -+ dNSName component of the SAN, typically a fully-qualified host name. -+ The 'short_name' component represent the first -+ part of the name before the first '.' sign. -+ -+ -+ Example: (|(fqdn={subject_dns_name})(host={subject_dns_name.short_name})) -+ -+ -+ -+ -+ {subject_uri} -+ -+ -+ This template will add the string which is stored in the -+ uniformResourceIdentifier component of the SAN. -+ -+ -+ Example: (uri={subject_uri}) -+ -+ -+ -+ -+ {subject_ip_address} -+ -+ -+ This template will add the string which is stored in the -+ iPAddress component of the SAN. -+ -+ -+ Example: (ip={subject_ip_address}) -+ -+ -+ -+ -+ {subject_x400_address} -+ -+ -+ This template will add the value which is stored in the -+ x400Address component of the SAN as escaped hex -+ sequence. -+ -+ -+ Example: (attr:binary={subject_x400_address}) -+ -+ -+ -+ -+ {subject_directory_name[!((ad|ad_x500)|ad_ldap|nss_x500|(nss|nss_ldap))]} -+ -+ -+ This template will add the DN string of the value which -+ is stored in the directoryName component of the SAN. -+ -+ -+ Example: (orig_dn={subject_directory_name}) -+ -+ -+ -+ -+ {subject_ediparty_name} -+ -+ -+ This template will add the value which is stored in the -+ ediPartyName component of the SAN as escaped hex -+ sequence. -+ -+ -+ Example: (attr:binary={subject_ediparty_name}) -+ -+ -+ -+ -+ {subject_registered_id} -+ -+ -+ This template will add the OID which is stored in the -+ registeredID component of the SAN as as dotted-decimal -+ string. -+ -+ -+ Example: (oid={subject_registered_id}) -+ -+ -+ -+ -+ -+ -+ -+ DOMAIN LIST -+ -+ If the domain list is not empty users mapped to a given certificate -+ are not only searched in the local domain but in the listed domains -+ as well as long as they are know by SSSD. Domains not know to SSSD -+ will be ignored. -+ -+ -+ -+ -+ -diff --git a/src/tests/cmocka/test_certmap.c b/src/tests/cmocka/test_certmap.c -new file mode 100644 -index 0000000000000000000000000000000000000000..c998443d086eaa72cc2a05c38ddfc5ba590a1ce7 ---- /dev/null -+++ b/src/tests/cmocka/test_certmap.c -@@ -0,0 +1,1443 @@ -+/* -+ SSSD -+ -+ certmap - Tests for SSSD's certificate mapping library -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2017 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 -+#include -+#include -+#include -+#include -+ -+#include "lib/certmap/sss_certmap.h" -+#include "lib/certmap/sss_certmap_int.h" -+ -+#include "util/crypto/sss_crypto.h" -+ -+#include "tests/cmocka/common_mock.h" -+#include "tests/common.h" -+ -+#ifdef HAVE_NSS -+#include "util/crypto/nss/nss_util.h" -+#endif -+ -+struct priv_sss_debug { -+ int level; -+}; -+ -+void ext_debug(void *private, const char *file, long line, const char *function, -+ const char *format, ...) -+{ -+ va_list ap; -+ struct priv_sss_debug *data = private; -+ int level = SSSDBG_OP_FAILURE; -+ -+ if (data != NULL) { -+ level = data->level; -+ } -+ -+ if (DEBUG_IS_SET(level)) { -+ va_start(ap, format); -+ sss_vdebug_fn(file, line, function, level, APPEND_LINE_FEED, -+ format, ap); -+ va_end(ap); -+ } -+} -+ -+static void test_sss_certmap_init(void **state) -+{ -+ int ret; -+ struct sss_certmap_ctx *ctx; -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ -+ sss_certmap_free_ctx(ctx); -+} -+ -+static struct sss_certmap_ctx *setup_prio(const int *l) -+{ -+ int ret; -+ size_t c; -+ struct sss_certmap_ctx *ctx; -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ -+ for (c = 0; c < 10; c++) { -+ ret = sss_certmap_add_rule(ctx, l[c], NULL, NULL, NULL); -+ assert_int_equal(ret, EOK); -+ } -+ -+ return ctx; -+} -+ -+static void test_sss_certmap_add_rule(void **state) -+{ -+ struct sss_certmap_ctx *ctx; -+ int i; -+ struct priority_list *p; -+ struct priority_list *last; -+ size_t c; -+ -+ const int tests_a[][10] = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, -+ {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, -+ {1, 3, 5 ,7, 9, 0, 2, 4, 6, 8}, -+ {0, 2, 4, 6, 8, 1, 3, 5, 7, 9}, -+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; -+ -+ const int tests_b[][10] = {{0, 0, 0, 0, 1, 1, 1, 2, 2, 2}, -+ {2, 2, 2, 1, 1, 1, 0, 0, 0, 0}, -+ {0, 1, 2, 0, 1, 2, 0, 1, 2, 0}, -+ {0, 2, 1, 0, 2, 1, 0, 2, 1, 0}, -+ {0, 1, 2, 0, 2, 1, 0, 0, 1, 2}, -+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; -+ -+ for (c = 0; tests_a[c][0] != 0 || tests_a[c][9] != 0; c++) { -+ ctx = setup_prio(tests_a[0]); -+ assert_non_null(ctx); -+ i = 0; -+ for (p = ctx->prio_list; p != NULL; p = p->next) { -+ assert_int_equal(i, p->priority); -+ assert_non_null(p->rule_list); -+ assert_int_equal(i, p->rule_list->priority); -+ assert_null(p->rule_list->prev); -+ assert_null(p->rule_list->next); -+ i++; -+ } -+ -+ i = 9; -+ for (last = ctx->prio_list; last->next != NULL; last = last->next); -+ for (p = last; p != NULL; p = p->prev) { -+ assert_int_equal(i, p->priority); -+ assert_int_equal(i, p->rule_list->priority); -+ i--; -+ } -+ -+ sss_certmap_free_ctx(ctx); -+ } -+ for (c = 0; tests_b[c][0] != 0 || tests_b[c][9] != 0; c++) { -+ ctx = setup_prio(tests_b[0]); -+ assert_non_null(ctx); -+ i = 0; -+ for (p = ctx->prio_list; p != NULL; p = p->next) { -+ assert_int_equal(i, p->priority); -+ assert_non_null(p->rule_list); -+ assert_int_equal(i, p->rule_list->priority); -+ assert_null(p->rule_list->prev); -+ assert_non_null(p->rule_list->next); -+ assert_ptr_equal(p->rule_list, p->rule_list->next->prev); -+ assert_non_null(p->rule_list->next->next); -+ assert_ptr_equal(p->rule_list->next, -+ p->rule_list->next->next->prev); -+ if (i == 0) { -+ assert_non_null(p->rule_list->next->next->next); -+ assert_ptr_equal(p->rule_list->next->next, -+ p->rule_list->next->next->next->prev); -+ assert_null(p->rule_list->next->next->next->next); -+ } else { -+ assert_null(p->rule_list->next->next->next); -+ } -+ i++; -+ } -+ sss_certmap_free_ctx(ctx); -+ } -+} -+ -+static void test_sss_certmap_add_matching_rule(void **state) -+{ -+ struct sss_certmap_ctx *ctx; -+ int ret; -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "fsdf", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "FDSF:fsdf", NULL, NULL); -+ assert_int_equal(ret, ESRCH); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "KRB5:", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "ddqwdq", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "digitalSignature,dddq", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ -+ ret = sss_certmap_add_rule(ctx, 1, "", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "dwqwqw", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, ".", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, ".1.2.3", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "1.2.3.", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "1.a.3", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "prio_list); -+ -+ /* invalid base64 input */ -+ ret = sss_certmap_add_rule(ctx, 1, "...", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ /* invalid OID input */ -+ ret = sss_certmap_add_rule(ctx, 1, "dqq", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "dqq", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "dqq", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "dqq", NULL, NULL); -+ assert_int_equal(ret, EINVAL); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "a", NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_null(ctx->prio_list->rule_list->parsed_match_rule->subject); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->issuer); -+ assert_string_equal("a", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->val); -+ talloc_free(ctx); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_add_rule(ctx, 1, "&&a", NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_null(ctx->prio_list->rule_list->parsed_match_rule->subject); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->issuer); -+ assert_string_equal("a", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->val); -+ talloc_free(ctx); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_add_rule(ctx, 1, "KRB5:||a", NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_or); -+ assert_null(ctx->prio_list->rule_list->parsed_match_rule->subject); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->issuer); -+ assert_string_equal("a", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->val); -+ talloc_free(ctx); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_add_rule(ctx, 1, "KRB5:ab", NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->subject); -+ assert_string_equal("b", -+ ctx->prio_list->rule_list->parsed_match_rule->subject->val); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->issuer); -+ assert_string_equal("a", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->val); -+ talloc_free(ctx); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_add_rule(ctx, 1000, -+ "KRB5:abcd", -+ NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->subject); -+ assert_string_equal("d", -+ ctx->prio_list->rule_list->parsed_match_rule->subject->val); -+ assert_string_equal("b", -+ ctx->prio_list->rule_list->parsed_match_rule->subject->next->val); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->issuer); -+ assert_string_equal("c", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->val); -+ assert_string_equal("a", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->next->val); -+ -+ ret = sss_certmap_add_rule(ctx, 99, -+ "KRB5:ab" -+ "dataEncipherment,cRLSignc" -+ "d", -+ NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->subject); -+ assert_string_equal("d", -+ ctx->prio_list->rule_list->parsed_match_rule->subject->val); -+ assert_string_equal("b", -+ ctx->prio_list->rule_list->parsed_match_rule->subject->next->val); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->issuer); -+ assert_string_equal("c", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->val); -+ assert_string_equal("a", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->next->val); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->ku); -+ assert_int_equal(SSS_KU_CRL_SIGN|SSS_KU_DATA_ENCIPHERMENT, -+ ctx->prio_list->rule_list->parsed_match_rule->ku->ku); -+ -+ ret = sss_certmap_add_rule(ctx, 98, -+ "KRB5:ab" -+ "dataEncipherment,cRLSignc" -+ "clientAuth,emailProtection" -+ "d", -+ NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->subject); -+ assert_string_equal("d", -+ ctx->prio_list->rule_list->parsed_match_rule->subject->val); -+ assert_string_equal("b", -+ ctx->prio_list->rule_list->parsed_match_rule->subject->next->val); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->issuer); -+ assert_string_equal("c", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->val); -+ assert_string_equal("a", -+ ctx->prio_list->rule_list->parsed_match_rule->issuer->next->val); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->ku); -+ assert_int_equal(SSS_KU_CRL_SIGN|SSS_KU_DATA_ENCIPHERMENT, -+ ctx->prio_list->rule_list->parsed_match_rule->ku->ku); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->eku); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.2", -+ discard_const( -+ ctx->prio_list->rule_list->parsed_match_rule->eku->eku_oid_list), -+ true)); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.4", -+ discard_const( -+ ctx->prio_list->rule_list->parsed_match_rule->eku->eku_oid_list), -+ true)); -+ assert_null( -+ ctx->prio_list->rule_list->parsed_match_rule->eku->eku_oid_list[2]); -+ -+ ret = sss_certmap_add_rule(ctx, 97, -+ "KRB5:clientAuth,1.2.3,emailProtection", -+ NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->eku); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.2", -+ discard_const( -+ ctx->prio_list->rule_list->parsed_match_rule->eku->eku_oid_list), -+ true)); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.4", -+ discard_const( -+ ctx->prio_list->rule_list->parsed_match_rule->eku->eku_oid_list), -+ true)); -+ assert_true(string_in_list("1.2.3", -+ discard_const( -+ ctx->prio_list->rule_list->parsed_match_rule->eku->eku_oid_list), -+ true)); -+ assert_null( -+ ctx->prio_list->rule_list->parsed_match_rule->eku->eku_oid_list[3]); -+ -+ /* SAN tests */ -+ ret = sss_certmap_add_rule(ctx, 89, "KRB5:abc", NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->san); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->san->san_opt, -+ SAN_PRINCIPAL); -+ assert_string_equal(ctx->prio_list->rule_list->parsed_match_rule->san->val, -+ "abc"); -+ -+ ret = sss_certmap_add_rule(ctx, 88, "KRB5:def", NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->san); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->san->san_opt, -+ SAN_DNS_NAME); -+ assert_string_equal(ctx->prio_list->rule_list->parsed_match_rule->san->val, -+ "def"); -+ -+ ret = sss_certmap_add_rule(ctx, 87, "KRB5:aGlq", -+ NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->san); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->san->san_opt, -+ SAN_X400_ADDRESS); -+ assert_int_equal( -+ ctx->prio_list->rule_list->parsed_match_rule->san->bin_val_len, -+ 3); -+ assert_memory_equal( -+ ctx->prio_list->rule_list->parsed_match_rule->san->bin_val, -+ "hij", 3); -+ -+ ret = sss_certmap_add_rule(ctx, 86, "KRB5:klm", -+ NULL, NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->r, -+ relation_and); -+ assert_non_null(ctx->prio_list->rule_list->parsed_match_rule->san); -+ assert_int_equal(ctx->prio_list->rule_list->parsed_match_rule->san->san_opt, -+ SAN_STRING_OTHER_NAME); -+ assert_string_equal(ctx->prio_list->rule_list->parsed_match_rule->san->val, -+ "klm"); -+ assert_string_equal("1.2.3.4", -+ ctx->prio_list->rule_list->parsed_match_rule->san->str_other_name_oid); -+ -+ talloc_free(ctx); -+} -+ -+static void test_check_ad_attr_name(void **state) -+{ -+ char *res; -+ -+ res = check_ad_attr_name(NULL, NULL); -+ assert_null(res); -+ -+ res = check_ad_attr_name(NULL, ""); -+ assert_null(res); -+ -+ res = check_ad_attr_name(NULL, "dsddqwdas"); -+ assert_null(res); -+ -+ res = check_ad_attr_name(NULL, "dsddq=wdas"); -+ assert_null(res); -+ -+ res = check_ad_attr_name(NULL, "CN=abc"); -+ assert_null(res); -+ -+ res = check_ad_attr_name(NULL, "O=xyz"); -+ assert_null(res); -+ -+ res = check_ad_attr_name(NULL, "ST=def"); -+ assert_non_null(res); -+ assert_string_equal(res, "S=def"); -+ talloc_free(res); -+} -+ -+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}; -+ -+const uint8_t test_cert2_der[] = { -+0x30, 0x82, 0x06, 0x98, 0x30, 0x82, 0x05, 0x80, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x61, -+0x22, 0x88, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, -+0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x0a, -+0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x05, 0x64, 0x65, 0x76, 0x65, -+0x6c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, -+0x19, 0x16, 0x02, 0x61, 0x64, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, -+0x61, 0x64, 0x2d, 0x41, 0x44, 0x2d, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x2d, 0x43, 0x41, 0x30, -+0x1e, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x31, 0x31, 0x31, 0x31, 0x33, 0x35, 0x31, 0x31, 0x31, 0x5a, -+0x17, 0x0d, 0x31, 0x37, 0x31, 0x31, 0x31, 0x31, 0x31, 0x33, 0x35, 0x31, 0x31, 0x31, 0x5a, 0x30, -+0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, -+0x19, 0x16, 0x05, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x0a, 0x09, 0x92, -+0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x02, 0x61, 0x64, 0x31, 0x0e, 0x30, 0x0c, -+0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x05, 0x55, 0x73, 0x65, 0x72, 0x73, 0x31, 0x0c, 0x30, 0x0a, -+0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x74, 0x20, 0x75, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, -+0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x16, 0x74, 0x65, 0x73, 0x74, 0x2e, -+0x75, 0x73, 0x65, 0x72, 0x40, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, -+0x6e, 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, 0x9c, 0xcf, 0x36, 0x99, 0xde, 0x63, 0x74, 0x2b, 0x77, 0x25, 0x9e, 0x24, 0xd9, 0x77, -+0x4b, 0x5f, 0x98, 0xc0, 0x8c, 0xd7, 0x20, 0x91, 0xc0, 0x1c, 0xe8, 0x37, 0x45, 0xbf, 0x3c, 0xd9, -+0x33, 0xbd, 0xe9, 0xde, 0xc9, 0x5d, 0xd4, 0xcd, 0x06, 0x0a, 0x0d, 0xd4, 0xf1, 0x7c, 0x74, 0x5b, -+0x29, 0xd5, 0x66, 0x9c, 0x2c, 0x9f, 0x6b, 0x1a, 0x0f, 0x0d, 0xe6, 0x6c, 0x62, 0xa5, 0x41, 0x4f, -+0xc3, 0xa4, 0x88, 0x27, 0x11, 0x5d, 0xb7, 0xb1, 0xfb, 0xf8, 0x8d, 0xee, 0x43, 0x8d, 0x93, 0xb5, -+0x8c, 0xb4, 0x34, 0x06, 0xf5, 0xe9, 0x2f, 0x5a, 0x26, 0x68, 0xd7, 0x43, 0x60, 0x82, 0x5e, 0x22, -+0xa7, 0xc6, 0x34, 0x40, 0x19, 0xa5, 0x8e, 0xf0, 0x58, 0x9f, 0x16, 0x2d, 0x43, 0x3f, 0x0c, 0xda, -+0xe2, 0x23, 0xf6, 0x09, 0x2a, 0x5e, 0xbd, 0x84, 0x27, 0xc8, 0xab, 0xd5, 0x70, 0xf8, 0x3d, 0x9c, -+0x14, 0xc2, 0xc2, 0xa2, 0x77, 0xe8, 0x44, 0x73, 0x10, 0x01, 0x34, 0x40, 0x1f, 0xc6, 0x2f, 0xa0, -+0x70, 0xee, 0x2f, 0xd5, 0x4b, 0xbe, 0x4c, 0xc7, 0x45, 0xf7, 0xac, 0x9c, 0xc3, 0x68, 0x5b, 0x1d, -+0x5a, 0x4b, 0x77, 0x65, 0x76, 0xe4, 0xb3, 0x92, 0xf4, 0x84, 0x0a, 0x9e, 0x6a, 0x9c, 0xc9, 0x53, -+0x42, 0x9f, 0x6d, 0xfe, 0xf9, 0xf5, 0xf2, 0x9a, 0x15, 0x50, 0x47, 0xef, 0xf4, 0x06, 0x59, 0xc8, -+0x50, 0x48, 0x4b, 0x46, 0x95, 0x68, 0x25, 0xc5, 0xbd, 0x4f, 0x65, 0x34, 0x00, 0xfc, 0x31, 0x69, -+0xf8, 0x3e, 0xe0, 0x20, 0x83, 0x41, 0x27, 0x0b, 0x5c, 0x46, 0x98, 0x14, 0xf0, 0x07, 0xde, 0x02, -+0x17, 0xb1, 0xd2, 0x9c, 0xbe, 0x1c, 0x0d, 0x56, 0x22, 0x1b, 0x02, 0xfe, 0xda, 0x69, 0xb9, 0xef, -+0x91, 0x37, 0x39, 0x7f, 0x24, 0xda, 0xc4, 0x81, 0x5e, 0x82, 0x31, 0x2f, 0x98, 0x1d, 0xf7, 0x73, -+0x5b, 0x23, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x03, 0x5d, 0x30, 0x82, 0x03, 0x59, 0x30, -+0x3d, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x07, 0x04, 0x30, 0x30, 0x2e, -+0x06, 0x26, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x08, 0x87, 0x85, 0xa1, 0x23, 0x84, -+0xc8, 0xb2, 0x26, 0x83, 0x9d, 0x9d, 0x21, 0x82, 0xd4, 0xa6, 0x1b, 0x86, 0xa3, 0xba, 0x37, 0x81, -+0x10, 0x85, 0x89, 0xd5, 0x02, 0xd6, 0x8f, 0x24, 0x02, 0x01, 0x64, 0x02, 0x01, 0x02, 0x30, 0x29, -+0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x22, 0x30, 0x20, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, -+0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04, 0x06, 0x0a, 0x2b, -+0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x04, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, -+0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x35, 0x06, 0x09, 0x2b, 0x06, 0x01, -+0x04, 0x01, 0x82, 0x37, 0x15, 0x0a, 0x04, 0x28, 0x30, 0x26, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, -+0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, -+0x03, 0x04, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x04, -+0x30, 0x81, 0x94, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x0f, 0x04, 0x81, -+0x86, 0x30, 0x81, 0x83, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, -+0x2a, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2d, 0x30, 0x0b, -+0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16, 0x30, 0x0b, 0x06, 0x09, 0x60, -+0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x19, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, -+0x65, 0x03, 0x04, 0x01, 0x02, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, -+0x01, 0x05, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x30, 0x07, -+0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x07, 0x30, 0x0e, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, -+0x0d, 0x03, 0x02, 0x02, 0x02, 0x00, 0x80, 0x30, 0x0e, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, -+0x0d, 0x03, 0x04, 0x02, 0x02, 0x02, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, -+0x04, 0x14, 0x49, 0xac, 0xad, 0xe0, 0x65, 0x30, 0xc4, 0xce, 0xa0, 0x09, 0x03, 0x5b, 0xad, 0x4a, -+0x7b, 0x49, 0x5e, 0xc9, 0x6c, 0xb4, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, -+0x16, 0x80, 0x14, 0x62, 0x50, 0xb6, 0x8d, 0xa1, 0xe6, 0x2d, 0x91, 0xbf, 0xb0, 0x54, 0x4d, 0x8f, -+0xa8, 0xca, 0x10, 0xae, 0xb8, 0xdd, 0x54, 0x30, 0x81, 0xcc, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, -+0x81, 0xc4, 0x30, 0x81, 0xc1, 0x30, 0x81, 0xbe, 0xa0, 0x81, 0xbb, 0xa0, 0x81, 0xb8, 0x86, 0x81, -+0xb5, 0x6c, 0x64, 0x61, 0x70, 0x3a, 0x2f, 0x2f, 0x2f, 0x43, 0x4e, 0x3d, 0x61, 0x64, 0x2d, 0x41, -+0x44, 0x2d, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x2d, 0x43, 0x41, 0x2c, 0x43, 0x4e, 0x3d, 0x61, -+0x64, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2c, 0x43, 0x4e, 0x3d, 0x43, 0x44, 0x50, 0x2c, -+0x43, 0x4e, 0x3d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x25, 0x32, 0x30, 0x4b, 0x65, 0x79, 0x25, -+0x32, 0x30, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x43, 0x4e, 0x3d, 0x53, 0x65, -+0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x43, 0x4e, 0x3d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, -+0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x44, 0x43, 0x3d, 0x61, 0x64, 0x2c, 0x44, 0x43, -+0x3d, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x3f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, -+0x74, 0x65, 0x52, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, -+0x3f, 0x62, 0x61, 0x73, 0x65, 0x3f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, -+0x73, 0x3d, 0x63, 0x52, 0x4c, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, -+0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x30, 0x81, 0xbe, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, -+0x07, 0x01, 0x01, 0x04, 0x81, 0xb1, 0x30, 0x81, 0xae, 0x30, 0x81, 0xab, 0x06, 0x08, 0x2b, 0x06, -+0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x81, 0x9e, 0x6c, 0x64, 0x61, 0x70, 0x3a, 0x2f, 0x2f, -+0x2f, 0x43, 0x4e, 0x3d, 0x61, 0x64, 0x2d, 0x41, 0x44, 0x2d, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, -+0x2d, 0x43, 0x41, 0x2c, 0x43, 0x4e, 0x3d, 0x41, 0x49, 0x41, 0x2c, 0x43, 0x4e, 0x3d, 0x50, 0x75, -+0x62, 0x6c, 0x69, 0x63, 0x25, 0x32, 0x30, 0x4b, 0x65, 0x79, 0x25, 0x32, 0x30, 0x53, 0x65, 0x72, -+0x76, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x43, 0x4e, 0x3d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, -+0x73, 0x2c, 0x43, 0x4e, 0x3d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, -+0x6f, 0x6e, 0x2c, 0x44, 0x43, 0x3d, 0x61, 0x64, 0x2c, 0x44, 0x43, 0x3d, 0x64, 0x65, 0x76, 0x65, -+0x6c, 0x3f, 0x63, 0x41, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3f, -+0x62, 0x61, 0x73, 0x65, 0x3f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, -+0x3d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x75, -+0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x3f, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x38, -+0x30, 0x36, 0xa0, 0x1c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03, -+0xa0, 0x0e, 0x0c, 0x0c, 0x74, 0x75, 0x31, 0x40, 0x61, 0x64, 0x2e, 0x64, 0x65, 0x76, 0x65, 0x6c, -+0x81, 0x16, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x40, 0x65, 0x6d, 0x61, 0x69, -+0x6c, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, -+0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x41, 0x45, 0x0a, 0x6d, -+0xbb, 0x7f, 0x5c, 0x07, 0x0c, 0xc9, 0xb0, 0x39, 0x55, 0x6d, 0x7c, 0xb5, 0x02, 0xcd, 0xe8, 0xb2, -+0xe5, 0x02, 0x94, 0x77, 0x60, 0xdb, 0xd1, 0xaf, 0x1d, 0xdb, 0x44, 0x5f, 0xce, 0x83, 0xdb, 0x80, -+0x2e, 0xe2, 0xb2, 0x08, 0x25, 0x82, 0x14, 0xcb, 0x48, 0x95, 0x20, 0x13, 0x6c, 0xa9, 0xaa, 0xf8, -+0x31, 0x56, 0xed, 0xc0, 0x3b, 0xd4, 0xae, 0x2e, 0xe3, 0x8f, 0x05, 0xfc, 0xab, 0x5f, 0x2a, 0x69, -+0x23, 0xbc, 0xb8, 0x8c, 0xec, 0x2d, 0xa9, 0x0b, 0x86, 0x95, 0x73, 0x73, 0xdb, 0x17, 0xce, 0xc6, -+0xae, 0xc5, 0xb4, 0xc1, 0x25, 0x87, 0x3b, 0x67, 0x43, 0x9e, 0x87, 0x5a, 0xe6, 0xb9, 0xa0, 0x28, -+0x12, 0x3d, 0xa8, 0x2e, 0xd7, 0x5e, 0xef, 0x65, 0x2d, 0xe6, 0xa5, 0x67, 0x84, 0xac, 0xfd, 0x31, -+0xc1, 0x78, 0xd8, 0x72, 0x51, 0xa2, 0x88, 0x55, 0x0f, 0x97, 0x47, 0x93, 0x07, 0xea, 0x8a, 0x53, -+0x27, 0x4e, 0x34, 0x54, 0x34, 0x1f, 0xa0, 0x6a, 0x03, 0x44, 0xfb, 0x23, 0x61, 0x8e, 0x87, 0x8e, -+0x3c, 0xd0, 0x8f, 0xae, 0xe4, 0xcf, 0xee, 0x65, 0xa8, 0xba, 0x96, 0x68, 0x08, 0x1c, 0x60, 0xe2, -+0x4e, 0x11, 0xa3, 0x74, 0xb8, 0xa5, 0x4e, 0xea, 0x6a, 0x82, 0x4c, 0xc2, 0x4d, 0x63, 0x8e, 0x9f, -+0x7c, 0x2f, 0xa8, 0xc0, 0x62, 0xf8, 0xf7, 0xd9, 0x25, 0xc4, 0x91, 0xab, 0x4d, 0x6a, 0x44, 0xaf, -+0x75, 0x93, 0x53, 0x03, 0xa4, 0x99, 0xc8, 0xcd, 0x91, 0x89, 0x60, 0x75, 0x30, 0x99, 0x76, 0x05, -+0x5a, 0xa0, 0x03, 0xa7, 0xa1, 0x2c, 0x03, 0x04, 0x8f, 0xd4, 0x5a, 0x31, 0x52, 0x28, 0x5a, 0xe6, -+0xa2, 0xd3, 0x43, 0x21, 0x5b, 0xdc, 0xa2, 0x1d, 0x55, 0xa9, 0x48, 0xc5, 0xc4, 0xaa, 0xf3, 0x8b, -+0xe6, 0x3e, 0x75, 0x96, 0xe4, 0x3e, 0x64, 0xaf, 0xe8, 0xa7, 0x6a, 0xb6}; -+ -+void test_sss_cert_get_content(void **state) -+{ -+ int ret; -+ struct sss_cert_content *content; -+ -+ ret = sss_cert_get_content(NULL, test_cert_der, sizeof(test_cert_der), -+ &content); -+ assert_int_equal(ret , 0); -+ assert_non_null(content); -+ assert_non_null(content->issuer_str); -+ assert_string_equal(content->issuer_str, "CN=Certificate Authority,O=IPA.DEVEL"); -+ assert_non_null(content->subject_str); -+ assert_string_equal(content->subject_str, "CN=ipa-devel.ipa.devel,O=IPA.DEVEL"); -+ assert_int_equal(content->key_usage, SSS_KU_DIGITAL_SIGNATURE -+ |SSS_KU_NON_REPUDIATION -+ |SSS_KU_KEY_ENCIPHERMENT -+ |SSS_KU_DATA_ENCIPHERMENT); -+ assert_non_null(content->extended_key_usage_oids); -+ assert_non_null(content->extended_key_usage_oids[0]); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.1", -+ discard_const(content->extended_key_usage_oids), true)); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.2", -+ discard_const(content->extended_key_usage_oids), true)); -+ assert_null(content->extended_key_usage_oids[2]); -+ assert_int_equal(content->cert_der_size, sizeof(test_cert_der)); -+ assert_memory_equal(content->cert_der, test_cert_der, sizeof(test_cert_der)); -+ -+ assert_non_null(content->issuer_rdn_list); -+ assert_string_equal(content->issuer_rdn_list[0], "O=IPA.DEVEL"); -+ assert_string_equal(content->issuer_rdn_list[1], "CN=Certificate Authority"); -+ assert_null(content->issuer_rdn_list[2]); -+ -+ assert_non_null(content->subject_rdn_list); -+ assert_string_equal(content->subject_rdn_list[0], "O=IPA.DEVEL"); -+ assert_string_equal(content->subject_rdn_list[1], "CN=ipa-devel.ipa.devel"); -+ assert_null(content->subject_rdn_list[2]); -+ -+ -+ talloc_free(content); -+} -+ -+void test_sss_cert_get_content_2(void **state) -+{ -+ int ret; -+ struct sss_cert_content *content; -+ struct san_list *i; -+ -+ ret = sss_cert_get_content(NULL, test_cert2_der, sizeof(test_cert2_der), -+ &content); -+ assert_int_equal(ret, 0); -+ assert_non_null(content); -+ assert_non_null(content->issuer_str); -+ assert_string_equal(content->issuer_str, -+ "CN=ad-AD-SERVER-CA,DC=ad,DC=devel"); -+ assert_non_null(content->subject_str); -+#if 0 -+FIXME: -+ assert_string_equal(content->subject_str, -+ "E=test.user@email.domain,CN=t u,CN=Users,DC=ad,DC=devel,DC=ad,DC=devel"); -+ //"CN=t u/emailAddress=test.user@email.domain,DC=ad,DC=devel"); -+#endif -+ assert_int_equal(content->key_usage, SSS_KU_DIGITAL_SIGNATURE -+ |SSS_KU_KEY_ENCIPHERMENT); -+ assert_non_null(content->extended_key_usage_oids); -+ assert_non_null(content->extended_key_usage_oids[0]); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.2", -+ discard_const(content->extended_key_usage_oids), true)); -+ assert_true(string_in_list("1.3.6.1.5.5.7.3.4", -+ discard_const(content->extended_key_usage_oids), true)); -+ /* Can use Microsoft Encrypted File System OID */ -+ assert_true(string_in_list("1.3.6.1.4.1.311.10.3.4", -+ discard_const(content->extended_key_usage_oids), true)); -+ assert_null(content->extended_key_usage_oids[3]); -+ assert_int_equal(content->cert_der_size, sizeof(test_cert2_der)); -+ assert_memory_equal(content->cert_der, test_cert2_der, -+ sizeof(test_cert2_der)); -+ -+ assert_non_null(content->issuer_rdn_list); -+ assert_string_equal(content->issuer_rdn_list[0], "DC=devel"); -+ assert_string_equal(content->issuer_rdn_list[1], "DC=ad"); -+ assert_string_equal(content->issuer_rdn_list[2], "CN=ad-AD-SERVER-CA"); -+ assert_null(content->issuer_rdn_list[3]); -+ -+ assert_non_null(content->subject_rdn_list); -+ assert_string_equal(content->subject_rdn_list[0], "DC=devel"); -+ assert_string_equal(content->subject_rdn_list[1], "DC=ad"); -+ assert_string_equal(content->subject_rdn_list[2], "CN=Users"); -+ assert_string_equal(content->subject_rdn_list[3], "CN=t u"); -+ assert_string_equal(content->subject_rdn_list[4], -+ "E=test.user@email.domain"); -+ //"CN=t u/emailAddress=test.user@email.domain"); -+ assert_null(content->subject_rdn_list[5]); -+ -+ assert_non_null(content->san_list); -+ -+ DLIST_FOR_EACH(i, content->san_list) { -+ switch (i->san_opt) { -+ case SAN_RFC822_NAME: -+ assert_string_equal(i->val, "test.user@email.domain"); -+ assert_string_equal(i->short_name, "test.user"); -+ break; -+ case SAN_STRING_OTHER_NAME: -+ assert_string_equal(i->other_name_oid, "1.3.6.1.4.1.311.20.2.3"); -+ assert_int_equal(i->bin_val_len, 14); -+ assert_memory_equal(i->bin_val, "\f\ftu1@ad.devel", 14); -+ break; -+ case SAN_NT: -+ case SAN_PRINCIPAL: -+ assert_string_equal(i->val, "tu1@ad.devel"); -+ assert_string_equal(i->short_name, "tu1"); -+ break; -+ default: -+ assert_true(false); -+ } -+ } -+ -+ talloc_free(content); -+} -+ -+static void test_sss_certmap_match_cert(void **state) -+{ -+ struct sss_certmap_ctx *ctx; -+ int ret; -+ size_t c; -+ -+ struct match_tests { -+ const char *rule; -+ int result; -+ } match_tests[] = { -+ {"KRB5:digitalSignature", 0}, -+ {"KRB5:digitalSignature,nonRepudiation", 0}, -+ {"KRB5:digitalSignature,cRLSign", ENOENT}, -+ {"KRB5:clientAuth", 0}, -+ {"KRB5:clientAuth,OCSPSigning", ENOENT}, -+ {"KRB5:clientAuth,serverAuth", 0}, -+ {NULL, 0} -+ }; -+ -+ struct match_tests match_tests_2[] = { -+ {"KRB5:digitalSignature", 0}, -+ {"KRB5:keyEncipherment", 0}, -+ {"KRB5:digitalSignature,keyEncipherment", 0}, -+ {"KRB5:digitalSignature,keyEncipherment,cRLSign", ENOENT}, -+ {"KRB5:clientAuth", 0}, -+ {"KRB5:clientAuth,1.3.6.1.4.1.311.10.3.4", 0}, -+ {"KRB5:clientAuth,1.3.6.1.4.1.311.10.3.41", ENOENT}, -+ {"KRB5:tu1", 0}, -+ {"KRB5:tu1", 0}, -+ {"KRB5:tu1", 0}, -+ {"KRB5:tu1", ENOENT}, -+ {"KRB5:^tu1@ad.devel$", 0}, -+ {"KRB5:tu", ENOENT}, -+ {"KRB5:test.user", 0}, -+ {"KRB5:test.usertu1", 0}, -+ {"KRB5:||test.usertu1", 0}, -+ {"KRB5:&&tu1tu1", ENOENT}, -+ {"KRB5:||tu1tu1", 0}, -+ {"KRB5:MTIz", ENOENT}, /* 123 */ -+ {"KRB5:DAx0dTFAYWQuZGV2ZWw=", 0}, /* "\f\ftu1@ad.devel" */ -+ {"KRB5:DAx0dTFAYWQuZGV2ZWx4", ENOENT}, /* "\f\ftu1@ad.develx" */ -+ {"KRB5:dHUxQGFkLmRldmVs", 0}, /* "tu1@ad.devel" */ -+ {"KRB5:test", ENOENT}, -+ {"KRB5:tu1@ad", 0}, -+ /* Fails becasue the NT principal SAN starts with binary values */ -+ {"KRB5:^tu1@ad.devel$", ENOENT}, -+ {NULL, 0} -+ }; -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, "KRB5:xyzxyz", -+ NULL, NULL); -+ assert_int_equal(ret, EOK); -+ -+ ret = sss_certmap_match_cert(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der)); -+ assert_int_equal(ret, ENOENT); -+ -+ ret = sss_certmap_add_rule(ctx, 1, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ NULL, NULL); -+ assert_int_equal(ret, EOK); -+ -+ ret = sss_certmap_match_cert(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der)); -+ assert_int_equal(ret, 0); -+ -+ sss_certmap_free_ctx(ctx); -+ -+ for (c = 0; match_tests[c].rule != NULL; c++) { -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, match_tests[c].rule, NULL, NULL); -+ assert_int_equal(ret, EOK); -+ -+ ret = sss_certmap_match_cert(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der)); -+ assert_int_equal(ret, match_tests[c].result); -+ -+ sss_certmap_free_ctx(ctx); -+ } -+ -+ for (c = 0; match_tests_2[c].rule != NULL; c++) { -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ -+ print_error("Checking matching rule [%s]\n", match_tests_2[c].rule); -+ -+ ret = sss_certmap_add_rule(ctx, 1, match_tests_2[c].rule, NULL, NULL); -+ assert_int_equal(ret, EOK); -+ -+ ret = sss_certmap_match_cert(ctx, discard_const(test_cert2_der), -+ sizeof(test_cert2_der)); -+ assert_int_equal(ret, match_tests_2[c].result); -+ -+ sss_certmap_free_ctx(ctx); -+ } -+} -+ -+static void test_sss_certmap_add_mapping_rule(void **state) -+{ -+ struct sss_certmap_ctx *ctx; -+ int ret; -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 1, NULL, "FWEAWEF:fwefwe", NULL); -+ assert_int_equal(ret, ESRCH); -+ -+ ret = sss_certmap_add_rule(ctx, 1, NULL, "LDAP:abc", NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule->list); -+ assert_int_equal(comp_string, -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->type); -+ assert_string_equal("abc", -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->val); -+ talloc_free(ctx); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_add_rule(ctx, 1, NULL, "LDAP:abc{issuer_dn}", NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule->list); -+ assert_int_equal(comp_string, -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->type); -+ assert_string_equal("abc", -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->val); -+ assert_int_equal(comp_template, -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->next->type); -+ assert_string_equal("issuer_dn", -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->next->val); -+ talloc_free(ctx); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_add_rule(ctx, 1, NULL, "{issuer_dn}a:b{{c}}", NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule->list); -+ assert_int_equal(comp_template, -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->type); -+ assert_string_equal("issuer_dn", -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->val); -+ assert_int_equal(comp_string, -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->next->type); -+ assert_string_equal("a:b{c}", -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->next->val); -+ talloc_free(ctx); -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_add_rule(ctx, 1, NULL, "LDAP:{issuer_dn}{subject_dn}", -+ NULL); -+ assert_int_equal(ret, 0); -+ assert_non_null(ctx->prio_list); -+ assert_non_null(ctx->prio_list->rule_list); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule); -+ assert_non_null(ctx->prio_list->rule_list->parsed_mapping_rule->list); -+ assert_int_equal(comp_template, -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->type); -+ assert_string_equal("issuer_dn", -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->val); -+ assert_int_equal(comp_template, -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->next->type); -+ assert_string_equal("subject_dn", -+ ctx->prio_list->rule_list->parsed_mapping_rule->list->next->val); -+ talloc_free(ctx); -+} -+ -+#define TEST_CERT_BIN \ -+ "\\30\\82\\04\\09\\30\\82\\02\\f1\\a0\\03\\02\\01\\02\\02\\01\\09" \ -+ "\\30\\0d\\06\\09\\2a\\86\\48\\86\\f7\\0d\\01\\01\\0b\\05\\00\\30" \ -+ "\\34\\31\\12\\30\\10\\06\\03\\55\\04\\0a\\0c\\09\\49\\50\\41\\2e" \ -+ "\\44\\45\\56\\45\\4c\\31\\1e\\30\\1c\\06\\03\\55\\04\\03\\0c\\15" \ -+ "\\43\\65\\72\\74\\69\\66\\69\\63\\61\\74\\65\\20\\41\\75\\74\\68" \ -+ "\\6f\\72\\69\\74\\79\\30\\1e\\17\\0d\\31\\35\\30\\34\\32\\38\\31" \ -+ "\\30\\32\\31\\31\\31\\5a\\17\\0d\\31\\37\\30\\34\\32\\38\\31\\30" \ -+ "\\32\\31\\31\\31\\5a\\30\\32\\31\\12\\30\\10\\06\\03\\55\\04\\0a" \ -+ "\\0c\\09\\49\\50\\41\\2e\\44\\45\\56\\45\\4c\\31\\1c\\30\\1a\\06" \ -+ "\\03\\55\\04\\03\\0c\\13\\69\\70\\61\\2d\\64\\65\\76\\65\\6c\\2e" \ -+ "\\69\\70\\61\\2e\\64\\65\\76\\65\\6c\\30\\82\\01\\22\\30\\0d\\06" \ -+ "\\09\\2a\\86\\48\\86\\f7\\0d\\01\\01\\01\\05\\00\\03\\82\\01\\0f" \ -+ "\\00\\30\\82\\01\\0a\\02\\82\\01\\01\\00\\b2\\32\\92\\ab\\47\\b8" \ -+ "\\0c\\13\\54\\4a\\1f\\1e\\29\\06\\ff\\d0\\50\\cb\\f7\\5f\\79\\91" \ -+ "\\65\\b1\\39\\01\\83\\6a\\ad\\9e\\77\\3b\\f3\\0d\\d7\\b9\\f6\\dc" \ -+ "\\9e\\4a\\49\\a7\\d0\\66\\72\\cc\\bf\\77\\d6\\de\\a9\\fe\\67\\96" \ -+ "\\cc\\49\\f1\\37\\23\\2e\\c4\\50\\f4\\eb\\ba\\62\\d4\\23\\4d\\f3" \ -+ "\\37\\38\\82\\ee\\3b\\3f\\2c\\d0\\80\\9b\\17\\aa\\9b\\eb\\a6\\dd" \ -+ "\\f6\\15\\ff\\06\\b2\\ce\\ff\\df\\8a\\9e\\95\\85\\49\\1f\\84\\fd" \ -+ "\\81\\26\\ce\\06\\32\\0d\\36\\ca\\7c\\15\\81\\68\\6b\\8f\\3e\\b3" \ -+ "\\a2\\fc\\ae\\af\\c2\\44\\58\\15\\95\\40\\fc\\56\\19\\91\\80\\ed" \ -+ "\\42\\11\\66\\04\\ef\\3c\\e0\\76\\33\\4b\\83\\fa\\7e\\b4\\47\\dc" \ -+ "\\fb\\ed\\46\\a5\\8d\\0a\\66\\87\\a5\\ef\\7b\\74\\62\\ac\\be\\73" \ -+ "\\36\\c9\\b4\\fe\\20\\c4\\81\\f3\\fe\\78\\19\\a8\\d0\\af\\7f\\81" \ -+ "\\72\\24\\61\\d9\\76\\93\\e3\\0b\\d2\\4f\\19\\17\\33\\57\\d4\\82" \ -+ "\\b0\\f1\\a8\\03\\f6\\01\\99\\a9\\b8\\8c\\83\\c9\\ba\\19\\87\\ea" \ -+ "\\d6\\3b\\06\\eb\\4c\\f7\\f1\\e5\\28\\a9\\10\\b6\\46\\de\\e1\\e1" \ -+ "\\3f\\c1\\cc\\72\\be\\2a\\43\\c6\\f6\\d0\\b5\\a0\\c4\\24\\6e\\4f" \ -+ "\\bd\\ec\\22\\8a\\07\\11\\3d\\f9\\d3\\15\\02\\03\\01\\00\\01\\a3" \ -+ "\\82\\01\\26\\30\\82\\01\\22\\30\\1f\\06\\03\\55\\1d\\23\\04\\18" \ -+ "\\30\\16\\80\\14\\f2\\9d\\42\\4e\\0f\\c4\\48\\25\\58\\2f\\1c\\ce" \ -+ "\\0f\\a1\\3f\\22\\c8\\55\\c8\\91\\30\\3b\\06\\08\\2b\\06\\01\\05" \ -+ "\\05\\07\\01\\01\\04\\2f\\30\\2d\\30\\2b\\06\\08\\2b\\06\\01\\05" \ -+ "\\05\\07\\30\\01\\86\\1f\\68\\74\\74\\70\\3a\\2f\\2f\\69\\70\\61" \ -+ "\\2d\\63\\61\\2e\\69\\70\\61\\2e\\64\\65\\76\\65\\6c\\2f\\63\\61" \ -+ "\\2f\\6f\\63\\73\\70\\30\\0e\\06\\03\\55\\1d\\0f\\01\\01\\ff\\04" \ -+ "\\04\\03\\02\\04\\f0\\30\\1d\\06\\03\\55\\1d\\25\\04\\16\\30\\14" \ -+ "\\06\\08\\2b\\06\\01\\05\\05\\07\\03\\01\\06\\08\\2b\\06\\01\\05" \ -+ "\\05\\07\\03\\02\\30\\74\\06\\03\\55\\1d\\1f\\04\\6d\\30\\6b\\30" \ -+ "\\69\\a0\\31\\a0\\2f\\86\\2d\\68\\74\\74\\70\\3a\\2f\\2f\\69\\70" \ -+ "\\61\\2d\\63\\61\\2e\\69\\70\\61\\2e\\64\\65\\76\\65\\6c\\2f\\69" \ -+ "\\70\\61\\2f\\63\\72\\6c\\2f\\4d\\61\\73\\74\\65\\72\\43\\52\\4c" \ -+ "\\2e\\62\\69\\6e\\a2\\34\\a4\\32\\30\\30\\31\\0e\\30\\0c\\06\\03" \ -+ "\\55\\04\\0a\\0c\\05\\69\\70\\61\\63\\61\\31\\1e\\30\\1c\\06\\03" \ -+ "\\55\\04\\03\\0c\\15\\43\\65\\72\\74\\69\\66\\69\\63\\61\\74\\65" \ -+ "\\20\\41\\75\\74\\68\\6f\\72\\69\\74\\79\\30\\1d\\06\\03\\55\\1d" \ -+ "\\0e\\04\\16\\04\\14\\2d\\2b\\3f\\cb\\f5\\b2\\ff\\32\\2c\\a8\\c2" \ -+ "\\1c\\dd\\bd\\8c\\80\\1e\\dd\\31\\82\\30\\0d\\06\\09\\2a\\86\\48" \ -+ "\\86\\f7\\0d\\01\\01\\0b\\05\\00\\03\\82\\01\\01\\00\\9a\\47\\2e" \ -+ "\\50\\a7\\4d\\1d\\53\\0f\\c9\\71\\42\\0c\\e5\\da\\7d\\49\\64\\e7" \ -+ "\\ab\\c8\\df\\df\\02\\c1\\87\\d1\\5b\\de\\da\\6f\\2b\\e4\\f0\\be" \ -+ "\\ba\\09\\df\\02\\85\\0b\\8a\\e6\\9b\\06\\7d\\69\\38\\6c\\72\\ff" \ -+ "\\4c\\7b\\2a\\0d\\3f\\23\\2f\\16\\46\\ff\\05\\93\\b0\\ea\\24\\28" \ -+ "\\d7\\12\\a1\\57\\b8\\59\\19\\25\\f3\\43\\0a\\d3\\fd\\0f\\37\\8d" \ -+ "\\b8\\ca\\15\\e7\\48\\8a\\a0\\c7\\c7\\4b\\7f\\01\\3c\\58\\d7\\37" \ -+ "\\e5\\ff\\7d\\2b\\01\\ac\\0d\\9f\\51\\6a\\e5\\40\\24\\e6\\5e\\55" \ -+ "\\0d\\f7\\b8\\2f\\42\\ac\\6d\\e5\\29\\6b\\c6\\0b\\a4\\bf\\19\\bd" \ -+ "\\39\\27\\ee\\fe\\c5\\b3\\db\\62\\d4\\be\\d2\\47\\ba\\96\\30\\5a" \ -+ "\\fd\\62\\00\\b8\\27\\5d\\2f\\3a\\94\\0b\\95\\35\\85\\40\\2c\\bc" \ -+ "\\67\\df\\8a\\f9\\f1\\7b\\19\\96\\3e\\42\\48\\13\\23\\04\\95\\a9" \ -+ "\\6b\\11\\33\\81\\47\\5a\\83\\72\\f6\\20\\fa\\8e\\41\\7b\\8f\\77" \ -+ "\\47\\7c\\c7\\5d\\46\\f4\\4f\\fd\\81\\0a\\ae\\39\\27\\b6\\6a\\26" \ -+ "\\63\\b1\\d3\\bf\\55\\83\\82\\9b\\36\\6c\\33\\64\\0f\\50\\c0\\55" \ -+ "\\94\\13\\c3\\85\\f4\\d5\\71\\65\\d0\\c0\\dd\\fc\\e6\\ec\\9c\\5b" \ -+ "\\f0\\11\\b5\\2c\\f3\\48\\c1\\36\\8c\\a2\\96\\48\\84" -+ -+#define TEST_CERT2_BIN \ -+ "\\30\\82\\06\\98\\30\\82\\05\\80\\a0\\03\\02\\01\\02\\02\\0a\\61" \ -+ "\\22\\88\\c2\\00\\00\\00\\00\\02\\a6\\30\\0d\\06\\09\\2a\\86\\48" \ -+ "\\86\\f7\\0d\\01\\01\\05\\05\\00\\30\\45\\31\\15\\30\\13\\06\\0a" \ -+ "\\09\\92\\26\\89\\93\\f2\\2c\\64\\01\\19\\16\\05\\64\\65\\76\\65" \ -+ "\\6c\\31\\12\\30\\10\\06\\0a\\09\\92\\26\\89\\93\\f2\\2c\\64\\01" \ -+ "\\19\\16\\02\\61\\64\\31\\18\\30\\16\\06\\03\\55\\04\\03\\13\\0f" \ -+ "\\61\\64\\2d\\41\\44\\2d\\53\\45\\52\\56\\45\\52\\2d\\43\\41\\30" \ -+ "\\1e\\17\\0d\\31\\36\\31\\31\\31\\31\\31\\33\\35\\31\\31\\31\\5a" \ -+ "\\17\\0d\\31\\37\\31\\31\\31\\31\\31\\33\\35\\31\\31\\31\\5a\\30" \ -+ "\\70\\31\\15\\30\\13\\06\\0a\\09\\92\\26\\89\\93\\f2\\2c\\64\\01" \ -+ "\\19\\16\\05\\64\\65\\76\\65\\6c\\31\\12\\30\\10\\06\\0a\\09\\92" \ -+ "\\26\\89\\93\\f2\\2c\\64\\01\\19\\16\\02\\61\\64\\31\\0e\\30\\0c" \ -+ "\\06\\03\\55\\04\\03\\13\\05\\55\\73\\65\\72\\73\\31\\0c\\30\\0a" \ -+ "\\06\\03\\55\\04\\03\\13\\03\\74\\20\\75\\31\\25\\30\\23\\06\\09" \ -+ "\\2a\\86\\48\\86\\f7\\0d\\01\\09\\01\\16\\16\\74\\65\\73\\74\\2e" \ -+ "\\75\\73\\65\\72\\40\\65\\6d\\61\\69\\6c\\2e\\64\\6f\\6d\\61\\69" \ -+ "\\6e\\30\\82\\01\\22\\30\\0d\\06\\09\\2a\\86\\48\\86\\f7\\0d\\01" \ -+ "\\01\\01\\05\\00\\03\\82\\01\\0f\\00\\30\\82\\01\\0a\\02\\82\\01" \ -+ "\\01\\00\\9c\\cf\\36\\99\\de\\63\\74\\2b\\77\\25\\9e\\24\\d9\\77" \ -+ "\\4b\\5f\\98\\c0\\8c\\d7\\20\\91\\c0\\1c\\e8\\37\\45\\bf\\3c\\d9" \ -+ "\\33\\bd\\e9\\de\\c9\\5d\\d4\\cd\\06\\0a\\0d\\d4\\f1\\7c\\74\\5b" \ -+ "\\29\\d5\\66\\9c\\2c\\9f\\6b\\1a\\0f\\0d\\e6\\6c\\62\\a5\\41\\4f" \ -+ "\\c3\\a4\\88\\27\\11\\5d\\b7\\b1\\fb\\f8\\8d\\ee\\43\\8d\\93\\b5" \ -+ "\\8c\\b4\\34\\06\\f5\\e9\\2f\\5a\\26\\68\\d7\\43\\60\\82\\5e\\22" \ -+ "\\a7\\c6\\34\\40\\19\\a5\\8e\\f0\\58\\9f\\16\\2d\\43\\3f\\0c\\da" \ -+ "\\e2\\23\\f6\\09\\2a\\5e\\bd\\84\\27\\c8\\ab\\d5\\70\\f8\\3d\\9c" \ -+ "\\14\\c2\\c2\\a2\\77\\e8\\44\\73\\10\\01\\34\\40\\1f\\c6\\2f\\a0" \ -+ "\\70\\ee\\2f\\d5\\4b\\be\\4c\\c7\\45\\f7\\ac\\9c\\c3\\68\\5b\\1d" \ -+ "\\5a\\4b\\77\\65\\76\\e4\\b3\\92\\f4\\84\\0a\\9e\\6a\\9c\\c9\\53" \ -+ "\\42\\9f\\6d\\fe\\f9\\f5\\f2\\9a\\15\\50\\47\\ef\\f4\\06\\59\\c8" \ -+ "\\50\\48\\4b\\46\\95\\68\\25\\c5\\bd\\4f\\65\\34\\00\\fc\\31\\69" \ -+ "\\f8\\3e\\e0\\20\\83\\41\\27\\0b\\5c\\46\\98\\14\\f0\\07\\de\\02" \ -+ "\\17\\b1\\d2\\9c\\be\\1c\\0d\\56\\22\\1b\\02\\fe\\da\\69\\b9\\ef" \ -+ "\\91\\37\\39\\7f\\24\\da\\c4\\81\\5e\\82\\31\\2f\\98\\1d\\f7\\73" \ -+ "\\5b\\23\\02\\03\\01\\00\\01\\a3\\82\\03\\5d\\30\\82\\03\\59\\30" \ -+ "\\3d\\06\\09\\2b\\06\\01\\04\\01\\82\\37\\15\\07\\04\\30\\30\\2e" \ -+ "\\06\\26\\2b\\06\\01\\04\\01\\82\\37\\15\\08\\87\\85\\a1\\23\\84" \ -+ "\\c8\\b2\\26\\83\\9d\\9d\\21\\82\\d4\\a6\\1b\\86\\a3\\ba\\37\\81" \ -+ "\\10\\85\\89\\d5\\02\\d6\\8f\\24\\02\\01\\64\\02\\01\\02\\30\\29" \ -+ "\\06\\03\\55\\1d\\25\\04\\22\\30\\20\\06\\08\\2b\\06\\01\\05\\05" \ -+ "\\07\\03\\02\\06\\08\\2b\\06\\01\\05\\05\\07\\03\\04\\06\\0a\\2b" \ -+ "\\06\\01\\04\\01\\82\\37\\0a\\03\\04\\30\\0e\\06\\03\\55\\1d\\0f" \ -+ "\\01\\01\\ff\\04\\04\\03\\02\\05\\a0\\30\\35\\06\\09\\2b\\06\\01" \ -+ "\\04\\01\\82\\37\\15\\0a\\04\\28\\30\\26\\30\\0a\\06\\08\\2b\\06" \ -+ "\\01\\05\\05\\07\\03\\02\\30\\0a\\06\\08\\2b\\06\\01\\05\\05\\07" \ -+ "\\03\\04\\30\\0c\\06\\0a\\2b\\06\\01\\04\\01\\82\\37\\0a\\03\\04" \ -+ "\\30\\81\\94\\06\\09\\2a\\86\\48\\86\\f7\\0d\\01\\09\\0f\\04\\81" \ -+ "\\86\\30\\81\\83\\30\\0b\\06\\09\\60\\86\\48\\01\\65\\03\\04\\01" \ -+ "\\2a\\30\\0b\\06\\09\\60\\86\\48\\01\\65\\03\\04\\01\\2d\\30\\0b" \ -+ "\\06\\09\\60\\86\\48\\01\\65\\03\\04\\01\\16\\30\\0b\\06\\09\\60" \ -+ "\\86\\48\\01\\65\\03\\04\\01\\19\\30\\0b\\06\\09\\60\\86\\48\\01" \ -+ "\\65\\03\\04\\01\\02\\30\\0b\\06\\09\\60\\86\\48\\01\\65\\03\\04" \ -+ "\\01\\05\\30\\0a\\06\\08\\2a\\86\\48\\86\\f7\\0d\\03\\07\\30\\07" \ -+ "\\06\\05\\2b\\0e\\03\\02\\07\\30\\0e\\06\\08\\2a\\86\\48\\86\\f7" \ -+ "\\0d\\03\\02\\02\\02\\00\\80\\30\\0e\\06\\08\\2a\\86\\48\\86\\f7" \ -+ "\\0d\\03\\04\\02\\02\\02\\00\\30\\1d\\06\\03\\55\\1d\\0e\\04\\16" \ -+ "\\04\\14\\49\\ac\\ad\\e0\\65\\30\\c4\\ce\\a0\\09\\03\\5b\\ad\\4a" \ -+ "\\7b\\49\\5e\\c9\\6c\\b4\\30\\1f\\06\\03\\55\\1d\\23\\04\\18\\30" \ -+ "\\16\\80\\14\\62\\50\\b6\\8d\\a1\\e6\\2d\\91\\bf\\b0\\54\\4d\\8f" \ -+ "\\a8\\ca\\10\\ae\\b8\\dd\\54\\30\\81\\cc\\06\\03\\55\\1d\\1f\\04" \ -+ "\\81\\c4\\30\\81\\c1\\30\\81\\be\\a0\\81\\bb\\a0\\81\\b8\\86\\81" \ -+ "\\b5\\6c\\64\\61\\70\\3a\\2f\\2f\\2f\\43\\4e\\3d\\61\\64\\2d\\41" \ -+ "\\44\\2d\\53\\45\\52\\56\\45\\52\\2d\\43\\41\\2c\\43\\4e\\3d\\61" \ -+ "\\64\\2d\\73\\65\\72\\76\\65\\72\\2c\\43\\4e\\3d\\43\\44\\50\\2c" \ -+ "\\43\\4e\\3d\\50\\75\\62\\6c\\69\\63\\25\\32\\30\\4b\\65\\79\\25" \ -+ "\\32\\30\\53\\65\\72\\76\\69\\63\\65\\73\\2c\\43\\4e\\3d\\53\\65" \ -+ "\\72\\76\\69\\63\\65\\73\\2c\\43\\4e\\3d\\43\\6f\\6e\\66\\69\\67" \ -+ "\\75\\72\\61\\74\\69\\6f\\6e\\2c\\44\\43\\3d\\61\\64\\2c\\44\\43" \ -+ "\\3d\\64\\65\\76\\65\\6c\\3f\\63\\65\\72\\74\\69\\66\\69\\63\\61" \ -+ "\\74\\65\\52\\65\\76\\6f\\63\\61\\74\\69\\6f\\6e\\4c\\69\\73\\74" \ -+ "\\3f\\62\\61\\73\\65\\3f\\6f\\62\\6a\\65\\63\\74\\43\\6c\\61\\73" \ -+ "\\73\\3d\\63\\52\\4c\\44\\69\\73\\74\\72\\69\\62\\75\\74\\69\\6f" \ -+ "\\6e\\50\\6f\\69\\6e\\74\\30\\81\\be\\06\\08\\2b\\06\\01\\05\\05" \ -+ "\\07\\01\\01\\04\\81\\b1\\30\\81\\ae\\30\\81\\ab\\06\\08\\2b\\06" \ -+ "\\01\\05\\05\\07\\30\\02\\86\\81\\9e\\6c\\64\\61\\70\\3a\\2f\\2f" \ -+ "\\2f\\43\\4e\\3d\\61\\64\\2d\\41\\44\\2d\\53\\45\\52\\56\\45\\52" \ -+ "\\2d\\43\\41\\2c\\43\\4e\\3d\\41\\49\\41\\2c\\43\\4e\\3d\\50\\75" \ -+ "\\62\\6c\\69\\63\\25\\32\\30\\4b\\65\\79\\25\\32\\30\\53\\65\\72" \ -+ "\\76\\69\\63\\65\\73\\2c\\43\\4e\\3d\\53\\65\\72\\76\\69\\63\\65" \ -+ "\\73\\2c\\43\\4e\\3d\\43\\6f\\6e\\66\\69\\67\\75\\72\\61\\74\\69" \ -+ "\\6f\\6e\\2c\\44\\43\\3d\\61\\64\\2c\\44\\43\\3d\\64\\65\\76\\65" \ -+ "\\6c\\3f\\63\\41\\43\\65\\72\\74\\69\\66\\69\\63\\61\\74\\65\\3f" \ -+ "\\62\\61\\73\\65\\3f\\6f\\62\\6a\\65\\63\\74\\43\\6c\\61\\73\\73" \ -+ "\\3d\\63\\65\\72\\74\\69\\66\\69\\63\\61\\74\\69\\6f\\6e\\41\\75" \ -+ "\\74\\68\\6f\\72\\69\\74\\79\\30\\3f\\06\\03\\55\\1d\\11\\04\\38" \ -+ "\\30\\36\\a0\\1c\\06\\0a\\2b\\06\\01\\04\\01\\82\\37\\14\\02\\03" \ -+ "\\a0\\0e\\0c\\0c\\74\\75\\31\\40\\61\\64\\2e\\64\\65\\76\\65\\6c" \ -+ "\\81\\16\\74\\65\\73\\74\\2e\\75\\73\\65\\72\\40\\65\\6d\\61\\69" \ -+ "\\6c\\2e\\64\\6f\\6d\\61\\69\\6e\\30\\0d\\06\\09\\2a\\86\\48\\86" \ -+ "\\f7\\0d\\01\\01\\05\\05\\00\\03\\82\\01\\01\\00\\41\\45\\0a\\6d" \ -+ "\\bb\\7f\\5c\\07\\0c\\c9\\b0\\39\\55\\6d\\7c\\b5\\02\\cd\\e8\\b2" \ -+ "\\e5\\02\\94\\77\\60\\db\\d1\\af\\1d\\db\\44\\5f\\ce\\83\\db\\80" \ -+ "\\2e\\e2\\b2\\08\\25\\82\\14\\cb\\48\\95\\20\\13\\6c\\a9\\aa\\f8" \ -+ "\\31\\56\\ed\\c0\\3b\\d4\\ae\\2e\\e3\\8f\\05\\fc\\ab\\5f\\2a\\69" \ -+ "\\23\\bc\\b8\\8c\\ec\\2d\\a9\\0b\\86\\95\\73\\73\\db\\17\\ce\\c6" \ -+ "\\ae\\c5\\b4\\c1\\25\\87\\3b\\67\\43\\9e\\87\\5a\\e6\\b9\\a0\\28" \ -+ "\\12\\3d\\a8\\2e\\d7\\5e\\ef\\65\\2d\\e6\\a5\\67\\84\\ac\\fd\\31" \ -+ "\\c1\\78\\d8\\72\\51\\a2\\88\\55\\0f\\97\\47\\93\\07\\ea\\8a\\53" \ -+ "\\27\\4e\\34\\54\\34\\1f\\a0\\6a\\03\\44\\fb\\23\\61\\8e\\87\\8e" \ -+ "\\3c\\d0\\8f\\ae\\e4\\cf\\ee\\65\\a8\\ba\\96\\68\\08\\1c\\60\\e2" \ -+ "\\4e\\11\\a3\\74\\b8\\a5\\4e\\ea\\6a\\82\\4c\\c2\\4d\\63\\8e\\9f" \ -+ "\\7c\\2f\\a8\\c0\\62\\f8\\f7\\d9\\25\\c4\\91\\ab\\4d\\6a\\44\\af" \ -+ "\\75\\93\\53\\03\\a4\\99\\c8\\cd\\91\\89\\60\\75\\30\\99\\76\\05" \ -+ "\\5a\\a0\\03\\a7\\a1\\2c\\03\\04\\8f\\d4\\5a\\31\\52\\28\\5a\\e6" \ -+ "\\a2\\d3\\43\\21\\5b\\dc\\a2\\1d\\55\\a9\\48\\c5\\c4\\aa\\f3\\8b" \ -+ "\\e6\\3e\\75\\96\\e4\\3e\\64\\af\\e8\\a7\\6a\\b6" -+ -+static void test_sss_certmap_get_search_filter(void **state) -+{ -+ int ret; -+ struct sss_certmap_ctx *ctx; -+ char *filter; -+ char **domains; -+ const char *dom_list[] = {"test.dom", NULL}; -+ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ -+ ret = sss_certmap_add_rule(ctx, 100, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ "LDAP:rule100={issuer_dn}{subject_dn}", NULL); -+ assert_int_equal(ret, 0); -+ -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule100=CN=Certificate Authority,O=IPA.DEVEL" -+ "CN=ipa-devel.ipa.devel,O=IPA.DEVEL"); -+ assert_null(domains); -+ -+ ret = sss_certmap_add_rule(ctx, 99, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ "LDAP:rule99={issuer_dn}{subject_dn}", -+ dom_list); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule99=CN=Certificate Authority,O=IPA.DEVEL" -+ "CN=ipa-devel.ipa.devel,O=IPA.DEVEL"); -+ assert_non_null(domains); -+ assert_string_equal(domains[0], "test.dom"); -+ assert_null(domains[1]); -+ -+ ret = sss_certmap_add_rule(ctx, 98, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ "LDAP:rule98=userCertificate;binary={cert!bin}", -+ dom_list); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule98=userCertificate;binary=" TEST_CERT_BIN); -+ assert_non_null(domains); -+ assert_string_equal(domains[0], "test.dom"); -+ assert_null(domains[1]); -+ -+ ret = sss_certmap_add_rule(ctx, 97, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ "LDAP:rule97={issuer_dn!nss_x500}{subject_dn}", -+ dom_list); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule97=O=IPA.DEVEL,CN=Certificate Authority" -+ "CN=ipa-devel.ipa.devel,O=IPA.DEVEL"); -+ assert_non_null(domains); -+ assert_string_equal(domains[0], "test.dom"); -+ assert_null(domains[1]); -+ -+ ret = sss_certmap_add_rule(ctx, 96, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ "LDAP:rule96={issuer_dn!nss_x500}{subject_dn!nss_x500}", -+ dom_list); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule96=O=IPA.DEVEL,CN=Certificate Authority" -+ "O=IPA.DEVEL,CN=ipa-devel.ipa.devel"); -+ assert_non_null(domains); -+ assert_string_equal(domains[0], "test.dom"); -+ assert_null(domains[1]); -+ -+ ret = sss_certmap_add_rule(ctx, 95, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ NULL, NULL); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")"); -+ assert_null(domains); -+ -+ ret = sss_certmap_add_rule(ctx, 94, -+ "KRB5:CN=Certificate Authority,O=IPA.DEVEL", -+ "LDAP:rule94={issuer_dn!ad_x500}{subject_dn!ad_x500}", -+ dom_list); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert_der), -+ sizeof(test_cert_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule94=O=IPA.DEVEL,CN=Certificate Authority" -+ "O=IPA.DEVEL,CN=ipa-devel.ipa.devel"); -+ assert_non_null(domains); -+ assert_string_equal(domains[0], "test.dom"); -+ assert_null(domains[1]); -+ -+ -+ ret = sss_certmap_add_rule(ctx, 89, NULL, -+ "(rule89={subject_nt_principal})", -+ NULL); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert2_der), -+ sizeof(test_cert2_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "(rule89=tu1@ad.devel)"); -+ assert_null(domains); -+ -+ ret = sss_certmap_add_rule(ctx, 88, NULL, -+ "(rule88={subject_nt_principal.short_name})", -+ NULL); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert2_der), -+ sizeof(test_cert2_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "(rule88=tu1)"); -+ assert_null(domains); -+ -+ ret = sss_certmap_add_rule(ctx, 87, NULL, -+ "LDAP:rule87={issuer_dn!nss_x500}{subject_dn!nss_x500}", -+ NULL); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert2_der), -+ sizeof(test_cert2_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule87=DC=devel,DC=ad,CN=ad-AD-SERVER-CA" -+ "DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain"); -+ assert_null(domains); -+ -+ ret = sss_certmap_add_rule(ctx, 86, NULL, -+ "LDAP:rule86={issuer_dn!ad_x500}{subject_dn!ad_x500}", -+ NULL); -+ assert_int_equal(ret, 0); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert2_der), -+ sizeof(test_cert2_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "rule86=DC=devel,DC=ad,CN=ad-AD-SERVER-CA" -+ "DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain"); -+ assert_null(domains); -+ -+ -+ sss_certmap_free_ctx(ctx); -+ -+ /* check defaults when no rules are added yet */ -+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(ctx); -+ assert_null(ctx->prio_list); -+ ret = sss_certmap_get_search_filter(ctx, discard_const(test_cert2_der), -+ sizeof(test_cert2_der), -+ &filter, &domains); -+ assert_int_equal(ret, 0); -+ assert_non_null(filter); -+ assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT2_BIN")"); -+ assert_null(domains); -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ int rv; -+ poptContext pc; -+ int opt; -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ SSSD_DEBUG_OPTS -+ POPT_TABLEEND -+ }; -+ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test(test_sss_certmap_init), -+ cmocka_unit_test(test_sss_certmap_add_rule), -+ cmocka_unit_test(test_sss_certmap_add_matching_rule), -+ cmocka_unit_test(test_check_ad_attr_name), -+ cmocka_unit_test(test_sss_cert_get_content), -+ cmocka_unit_test(test_sss_cert_get_content_2), -+ cmocka_unit_test(test_sss_certmap_match_cert), -+ cmocka_unit_test(test_sss_certmap_add_mapping_rule), -+ cmocka_unit_test(test_sss_certmap_get_search_filter), -+ }; -+ -+ /* 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); -+ -+#ifdef HAVE_NSS -+ nspr_nss_init(); -+#endif -+ -+ tests_set_cwd(); -+ rv = cmocka_run_group_tests(tests, NULL, NULL); -+ -+#ifdef HAVE_NSS -+ /* Cleanup NSS and NSPR to make valgrind happy. */ -+ nspr_nss_cleanup(); -+#endif -+ -+ return rv; -+} -diff --git a/src/tests/dlopen-tests.c b/src/tests/dlopen-tests.c -index 419857cc739d197493e46629d00aa5fb6cfde824..3914317de90f870fab42d2d72d8e2eb5ea8d9e14 100644 ---- a/src/tests/dlopen-tests.c -+++ b/src/tests/dlopen-tests.c -@@ -45,6 +45,7 @@ struct so { - { "libsss_idmap.so", { LIBPFX"libsss_idmap.so", NULL } }, - { "libsss_nss_idmap.so", { LIBPFX"libsss_nss_idmap.so", NULL } }, - { "libnss_sss.so", { LIBPFX"libnss_sss.so", NULL } }, -+ { "libsss_certmap.so", { LIBPFX"libsss_certmap.so", NULL } }, - { "pam_sss.so", { LIBPFX"pam_sss.so", NULL } }, - #ifdef BUILD_LIBWBCLIENT - { "libwbclient.so", { LIBPFX"libwbclient.so", NULL } }, --- -2.12.2 - diff --git a/0007-certmap-add-placeholder-for-OpenSSL-implementation.patch b/0007-certmap-add-placeholder-for-OpenSSL-implementation.patch deleted file mode 100644 index 2602e8e..0000000 --- a/0007-certmap-add-placeholder-for-OpenSSL-implementation.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 31a6661ff2a640fbcf97460df2415fd1bab309b5 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 15 Mar 2017 10:57:09 +0100 -Subject: [PATCH 07/97] certmap: add placeholder for OpenSSL implementation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 30 +++++++++++++++++++++-------- - src/lib/certmap/sss_cert_content_crypto.c | 32 +++++++++++++++++++++++++++++++ - src/lib/certmap/sss_certmap_int.h | 8 +++++--- - 3 files changed, 59 insertions(+), 11 deletions(-) - create mode 100644 src/lib/certmap/sss_cert_content_crypto.c - -diff --git a/Makefile.am b/Makefile.am -index 8ca12c10d2713b6a72361d84b25486500c79f407..7947b7a5fbe3ca1034baac1c13c53300994b1bf8 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -278,9 +278,12 @@ if HAVE_CMOCKA - simple-access-tests \ - krb5_common_test \ - test_iobuf \ -- sss_certmap_test \ - $(NULL) - -+if HAVE_NSS -+non_interactive_cmocka_based_tests += sss_certmap_test -+endif #HAVE_NSS -+ - if HAVE_LIBRESOLV - non_interactive_cmocka_based_tests += test_resolv_fake - endif # HAVE_LIBRESOLV -@@ -1715,7 +1718,6 @@ sssd_check_socket_activated_responders_LDADD = \ - $(NULL) - endif - --if HAVE_NSS - pkgconfig_DATA += src/lib/certmap/sss_certmap.pc - libsss_certmap_la_DEPENDENCIES = src/lib/certmap/sss_certmap.exports - libsss_certmap_la_SOURCES = \ -@@ -1726,26 +1728,38 @@ libsss_certmap_la_SOURCES = \ - src/lib/certmap/sss_certmap_ldap_mapping.c \ - src/util/util_ext.c \ - src/util/cert/cert_common.c \ -- src/util/crypto/nss/nss_base64.c \ -- src/util/cert/nss/cert.c \ -- src/util/crypto/nss/nss_util.c \ - $(NULL) - libsss_certmap_la_CFLAGS = \ - $(AM_CFLAGS) \ - $(TALLOC_CFLAGS) \ -- $(NSS_CFLAGS) \ - $(NULL) - libsss_certmap_la_LIBADD = \ - $(TALLOC_LIBS) \ -- $(NSS_LIBS) \ - $(NULL) - libsss_certmap_la_LDFLAGS = \ - -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \ - -version-info 0:0:0 - -+if HAVE_NSS -+libsss_certmap_la_SOURCES += \ -+ src/util/crypto/nss/nss_base64.c \ -+ src/util/cert/nss/cert.c \ -+ src/util/crypto/nss/nss_util.c \ -+ $(NULL) -+libsss_certmap_la_CFLAGS += $(NSS_CFLAGS) -+libsss_certmap_la_LIBADD += $(NSS_LIBS) -+else -+libsss_certmap_la_SOURCES += \ -+ src/util/crypto/libcrypto/crypto_base64.c \ -+ src/util/cert/libcrypto/cert.c \ -+ $(NULL) -+ -+libsss_certmap_la_CFLAGS += $(CRYPTO_CFLAGS) -+libsss_certmap_la_LIBADD += $(CRYPTO_LIBS) -+endif -+ - dist_noinst_DATA += src/lib/certmap/sss_certmap.exports - dist_noinst_HEADERS += src/lib/certmap/sss_certmap_int.h --endif - - ################# - # Feature Tests # -diff --git a/src/lib/certmap/sss_cert_content_crypto.c b/src/lib/certmap/sss_cert_content_crypto.c -new file mode 100644 -index 0000000000000000000000000000000000000000..bddcf9bce986bd986aa0aa5f16a0744a97ab36d6 ---- /dev/null -+++ b/src/lib/certmap/sss_cert_content_crypto.c -@@ -0,0 +1,32 @@ -+/* -+ SSSD - certificate handling utils - OpenSSL version -+ The calls defined here should be useable outside of SSSD as well, e.g. in -+ libsss_certmap. -+ -+ Copyright (C) Sumit Bose 2017 -+ -+ 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 -+ -+#include "lib/certmap/sss_certmap.h" -+#include "lib/certmap/sss_certmap_int.h" -+ -+int sss_cert_get_content(TALLOC_CTX *mem_ctx, -+ const uint8_t *der_blob, size_t der_size, -+ struct sss_cert_content **content) -+{ -+ return EINVAL; -+} -diff --git a/src/lib/certmap/sss_certmap_int.h b/src/lib/certmap/sss_certmap_int.h -index 28f1c596cfb5e78077b6a8e9baefa88b4900a022..0b4cda73639be9b323ac3388f97be90bc1a771f2 100644 ---- a/src/lib/certmap/sss_certmap_int.h -+++ b/src/lib/certmap/sss_certmap_int.h -@@ -22,12 +22,14 @@ - along with this program. If not, see . - */ - --#include --#include -- - #ifndef __SSS_CERTMAP_INT_H__ - #define __SSS_CERTMAP_INT_H__ - -+#include -+#include -+#include -+#include -+ - #define CM_DEBUG(cm_ctx, format, ...) do { \ - if (cm_ctx != NULL && cm_ctx->debug != NULL) { \ - cm_ctx->debug(cm_ctx->debug_priv, __FILE__, __LINE__, __FUNCTION__, \ --- -2.12.2 - diff --git a/0008-sysdb-add-sysdb_attrs_copy.patch b/0008-sysdb-add-sysdb_attrs_copy.patch deleted file mode 100644 index 3c97a52..0000000 --- a/0008-sysdb-add-sysdb_attrs_copy.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 3994e8779d16db3e9fb30f03e5ecf5e811095ac2 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 21 Sep 2015 12:32:48 +0200 -Subject: [PATCH 08/97] sysdb: add sysdb_attrs_copy() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - src/db/sysdb.c | 24 ++++++++++++++ - src/db/sysdb.h | 1 + - src/tests/sysdb-tests.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 112 insertions(+) - -diff --git a/src/db/sysdb.c b/src/db/sysdb.c -index 5160e3df3810a113d4ec1371350e51a074aaa146..98b7afbfab5141fa9b63a4aab31c620545b3c1f2 100644 ---- a/src/db/sysdb.c -+++ b/src/db/sysdb.c -@@ -752,6 +752,30 @@ done: - return ret; - } - -+errno_t sysdb_attrs_copy(struct sysdb_attrs *src, struct sysdb_attrs *dst) -+{ -+ int ret; -+ size_t c; -+ size_t d; -+ -+ if (src == NULL || dst == NULL) { -+ return EINVAL; -+ } -+ -+ for (c = 0; c < src->num; c++) { -+ for (d = 0; d < src->a[c].num_values; d++) { -+ ret = sysdb_attrs_add_val_safe(dst, src->a[c].name, -+ &src->a[c].values[d]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n"); -+ return ret; -+ } -+ } -+ } -+ -+ return EOK; -+} -+ - int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs, - const char *attr_name, - const char *domain, -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 83d0d794c737c094d1fd52e7cc7f2113b5d9a7a0..c677957bb639e40db2f985205160612094302e78 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -352,6 +352,7 @@ int sysdb_attrs_add_lc_name_alias_safe(struct sysdb_attrs *attrs, - int sysdb_attrs_copy_values(struct sysdb_attrs *src, - struct sysdb_attrs *dst, - const char *name); -+errno_t sysdb_attrs_copy(struct sysdb_attrs *src, struct sysdb_attrs *dst); - int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name, - struct ldb_message_element **el); - int sysdb_attrs_get_el_ext(struct sysdb_attrs *attrs, const char *name, -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index 013b01a9a68d9de87d796d3aff41d98cef8cccc3..c343c734a27a335303974b6866a5d9e88d4c307e 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -4997,6 +4997,92 @@ START_TEST(test_sysdb_attrs_add_string_safe) - } - END_TEST - -+START_TEST(test_sysdb_attrs_copy) -+{ -+ int ret; -+ struct sysdb_attrs *src; -+ struct sysdb_attrs *dst; -+ TALLOC_CTX *tmp_ctx; -+ const char *val; -+ const char **array; -+ -+ ret = sysdb_attrs_copy(NULL, NULL); -+ fail_unless(ret == EINVAL, "Wrong return code"); -+ -+ tmp_ctx = talloc_new(NULL); -+ fail_unless(tmp_ctx != NULL, "talloc_new failed"); -+ -+ src = sysdb_new_attrs(tmp_ctx); -+ fail_unless(src != NULL, "sysdb_new_attrs failed"); -+ -+ ret = sysdb_attrs_copy(src, NULL); -+ fail_unless(ret == EINVAL, "Wrong return code"); -+ -+ dst = sysdb_new_attrs(tmp_ctx); -+ fail_unless(dst != NULL, "sysdb_new_attrs failed"); -+ -+ ret = sysdb_attrs_copy(NULL, dst); -+ fail_unless(ret == EINVAL, "Wrong return code"); -+ -+ ret = sysdb_attrs_copy(src, dst); -+ fail_unless(ret == EOK, "sysdb_attrs_copy failed"); -+ fail_unless(dst->num == 0, "Wrong number of elements"); -+ -+ ret = sysdb_attrs_add_string(src, TEST_ATTR_NAME, TEST_ATTR_VALUE); -+ fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); -+ -+ ret = sysdb_attrs_copy(src, dst); -+ fail_unless(ret == EOK, "sysdb_attrs_copy failed"); -+ fail_unless(dst->num == 1, "Wrong number of elements"); -+ ret = sysdb_attrs_get_string(dst, TEST_ATTR_NAME, &val); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string failed.\n"); -+ fail_unless(strcmp(val, TEST_ATTR_VALUE) == 0, "Wrong attribute value."); -+ -+ /* Make sure the same entry is not copied twice */ -+ ret = sysdb_attrs_copy(src, dst); -+ fail_unless(ret == EOK, "sysdb_attrs_copy failed"); -+ fail_unless(dst->num == 1, "Wrong number of elements"); -+ ret = sysdb_attrs_get_string(dst, TEST_ATTR_NAME, &val); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string failed.\n"); -+ fail_unless(strcmp(val, TEST_ATTR_VALUE) == 0, "Wrong attribute value."); -+ -+ /* Add new value to existing attribute */ -+ ret = sysdb_attrs_add_string(src, TEST_ATTR_NAME, TEST_ATTR_VALUE"_2nd"); -+ fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); -+ -+ ret = sysdb_attrs_copy(src, dst); -+ fail_unless(ret == EOK, "sysdb_attrs_copy failed"); -+ fail_unless(dst->num == 1, "Wrong number of elements"); -+ ret = sysdb_attrs_get_string_array(dst, TEST_ATTR_NAME, tmp_ctx, &array); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string_array failed.\n"); -+ fail_unless(strcmp(array[0], TEST_ATTR_VALUE) == 0, -+ "Wrong attribute value."); -+ fail_unless(strcmp(array[1], TEST_ATTR_VALUE"_2nd") == 0, -+ "Wrong attribute value."); -+ fail_unless(array[2] == NULL, "Wrong number of values."); -+ -+ /* Add new attribute */ -+ ret = sysdb_attrs_add_string(src, TEST_ATTR_NAME"_2nd", TEST_ATTR_VALUE); -+ fail_unless(ret == EOK, "sysdb_attrs_add_val failed."); -+ -+ ret = sysdb_attrs_copy(src, dst); -+ fail_unless(ret == EOK, "sysdb_attrs_copy failed"); -+ fail_unless(dst->num == 2, "Wrong number of elements"); -+ ret = sysdb_attrs_get_string_array(dst, TEST_ATTR_NAME, tmp_ctx, &array); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string_array failed.\n"); -+ fail_unless(strcmp(array[0], TEST_ATTR_VALUE) == 0, -+ "Wrong attribute value."); -+ fail_unless(strcmp(array[1], TEST_ATTR_VALUE"_2nd") == 0, -+ "Wrong attribute value."); -+ fail_unless(array[2] == NULL, "Wrong number of values."); -+ ret = sysdb_attrs_get_string(dst, TEST_ATTR_NAME"_2nd", &val); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string failed.\n"); -+ fail_unless(strcmp(val, TEST_ATTR_VALUE) == 0, "Wrong attribute value."); -+ -+ talloc_free(tmp_ctx); -+} -+END_TEST -+ - START_TEST (test_sysdb_search_return_ENOENT) - { - struct sysdb_test_ctx *test_ctx; -@@ -6995,6 +7081,7 @@ Suite *create_sysdb_suite(void) - tcase_add_test(tc_sysdb, test_sysdb_attrs_add_val); - tcase_add_test(tc_sysdb, test_sysdb_attrs_add_val_safe); - tcase_add_test(tc_sysdb, test_sysdb_attrs_add_string_safe); -+ tcase_add_test(tc_sysdb, test_sysdb_attrs_copy); - - /* ===== Test search return empty result ===== */ - tcase_add_test(tc_sysdb, test_sysdb_search_return_ENOENT); --- -2.12.2 - diff --git a/0009-sdap_get_users_send-new-argument-mapped_attrs.patch b/0009-sdap_get_users_send-new-argument-mapped_attrs.patch deleted file mode 100644 index fb73c77..0000000 --- a/0009-sdap_get_users_send-new-argument-mapped_attrs.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 70c0648f021ded3d31313eb962e1ad140f242673 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Sun, 12 Mar 2017 18:31:03 +0100 -Subject: [PATCH 09/97] sdap_get_users_send(): new argument mapped_attrs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -mapped_attrs can be a list of sysdb_attrs which are not available on -the server side but should be store with the cached user entry. This is -needed e.g. when the input to look up the user in LDAP is not an -attribute which is stored in LDAP but some data where LDAP attributes -are extracted from. The current use case is the certificate mapping -library which can create LDAP search filters based on content of the -certificate. To allow upcoming cache lookup to use the input directly it -is stored in the user object in the cache. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - src/db/sysdb.h | 3 ++ - src/db/sysdb_ops.c | 61 ++++++++++++++++++++++++++++++ - src/providers/ldap/ldap_id.c | 4 +- - src/providers/ldap/sdap_async.h | 3 +- - src/providers/ldap/sdap_async_enum.c | 2 +- - src/providers/ldap/sdap_async_initgroups.c | 2 +- - src/providers/ldap/sdap_async_private.h | 1 + - src/providers/ldap/sdap_async_users.c | 41 +++++++++++++++++++- - src/providers/ldap/sdap_users.h | 1 + - 9 files changed, 111 insertions(+), 7 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index c677957bb639e40db2f985205160612094302e78..098f47f91187aac75c58c02f0af738c344765762 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -1246,6 +1246,9 @@ errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx, - errno_t sysdb_remove_cert(struct sss_domain_info *domain, - const char *cert); - -+errno_t sysdb_remove_mapped_data(struct sss_domain_info *domain, -+ struct sysdb_attrs *mapped_attr); -+ - /* === 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 242d3ce3bb795691e329790a07c3493672e8f523..6c2254df2b75d3d3419528523103ad9cddb40c9d 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -4685,6 +4685,67 @@ errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx, - return sysdb_search_object_by_cert(mem_ctx, domain, cert, user_attrs, res); - } - -+errno_t sysdb_remove_mapped_data(struct sss_domain_info *domain, -+ struct sysdb_attrs *mapped_attr) -+{ -+ int ret; -+ char *val; -+ char *filter; -+ const char *attrs[] = {SYSDB_NAME, NULL}; -+ struct ldb_result *res = NULL; -+ size_t c; -+ bool all_ok = true; -+ -+ if (mapped_attr->num != 1 || mapped_attr->a[0].num_values != 1) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unsupported number of attributes.\n"); -+ return EINVAL; -+ } -+ -+ ret = bin_to_ldap_filter_value(NULL, mapped_attr->a[0].values[0].data, -+ mapped_attr->a[0].values[0].length, &val); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "bin_to_ldap_filter_value failed.\n"); -+ return ret; -+ } -+ -+ filter = talloc_asprintf(NULL, "(&("SYSDB_UC")(%s=%s))", -+ mapped_attr->a[0].name, val); -+ talloc_free(val); -+ if (filter == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); -+ return ENOMEM; -+ } -+ -+ ret = sysdb_search_object_attr(NULL, domain, filter, attrs, false, &res); -+ talloc_free(filter); -+ if (ret == ENOENT || res == NULL) { -+ DEBUG(SSSDBG_TRACE_ALL, "Mapped data not found.\n"); -+ talloc_free(res); -+ return EOK; -+ } else if (ret != EOK) { -+ talloc_free(res); -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_object_attr failed.\n"); -+ return ret; -+ } -+ -+ for (c = 0; c < res->count; c++) { -+ DEBUG(SSSDBG_TRACE_ALL, "Removing mapped data from [%s].\n", -+ ldb_dn_get_linearized(res->msgs[c]->dn)); -+ /* The timestamp cache is skipped on purpose here. */ -+ ret = sysdb_set_cache_entry_attr(domain->sysdb->ldb, res->msgs[c]->dn, -+ mapped_attr, SYSDB_MOD_DEL); -+ if (ret != EOK) { -+ all_ok = false; -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to remove mapped data from [%s], skipping.\n", -+ ldb_dn_get_linearized(res->msgs[c]->dn)); -+ } -+ } -+ talloc_free(res); -+ -+ return (all_ok ? EOK : EIO); -+} -+ - errno_t sysdb_remove_cert(struct sss_domain_info *domain, - const char *cert) - { -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index e9455b538daa2d65d944dbb68022a2773623d7b7..898ddb18689d55fcc3fdf021b38df0e574003eb2 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -442,7 +442,7 @@ static void users_get_search(struct tevent_req *req) - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), -- lookup_type); -+ lookup_type, NULL); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; -@@ -507,7 +507,7 @@ static void users_get_done(struct tevent_req *subreq) - ret = sdap_fallback_local_user(state, state->shortname, uid, &usr_attrs); - if (ret == EOK) { - ret = sdap_save_user(state, state->ctx->opts, state->domain, -- usr_attrs[0], NULL, 0); -+ usr_attrs[0], NULL, NULL, 0); - } - } - } -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index 2ebde6b83646408e446c91cb324809cb767b2617..6e5800b42ba4a045fa7985b09a80b6b86b8c6055 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -90,7 +90,8 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- enum sdap_entry_lookup_type lookup_type); -+ enum sdap_entry_lookup_type lookup_type, -+ struct sysdb_attrs *mapped_attrs); - int sdap_get_users_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp); - -diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c -index 387e53155b567ce106cc68009c7cb99e27d24a17..3f65059e18d5c8b548da0babec867d27c3a64198 100644 ---- a/src/providers/ldap/sdap_async_enum.c -+++ b/src/providers/ldap/sdap_async_enum.c -@@ -635,7 +635,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT), -- SDAP_LOOKUP_ENUMERATE); -+ SDAP_LOOKUP_ENUMERATE, NULL); - if (!subreq) { - ret = ENOMEM; - goto fail; -diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c -index 8c7a65bf36abf341e077cf9eac18a234d3a07c07..79af7a3eda3fe8533933535c98c2b4b4698dfda2 100644 ---- a/src/providers/ldap/sdap_async_initgroups.c -+++ b/src/providers/ldap/sdap_async_initgroups.c -@@ -2991,7 +2991,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) - DEBUG(SSSDBG_TRACE_ALL, "Storing the user\n"); - - ret = sdap_save_user(state, state->opts, state->dom, state->orig_user, -- NULL, 0); -+ NULL, NULL, 0); - if (ret) { - goto fail; - } -diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h -index 266bc03115e2bdd6a283f5f7da565fd00d3a77be..72507442a9ffd5c0e24ccbd95d75d3ebf9bf0940 100644 ---- a/src/providers/ldap/sdap_async_private.h -+++ b/src/providers/ldap/sdap_async_private.h -@@ -94,6 +94,7 @@ int sdap_save_users(TALLOC_CTX *memctx, - struct sdap_options *opts, - struct sysdb_attrs **users, - int num_users, -+ struct sysdb_attrs *mapped_attrs, - char **_usn_value); - - int sdap_initgr_common_store(struct sysdb_ctx *sysdb, -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index 87d91d8247c37a4c6a1d83b7189399056528fc90..3d957ab584865f74499bc732395388a78965fe5f 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -117,6 +117,7 @@ int sdap_save_user(TALLOC_CTX *memctx, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sysdb_attrs *attrs, -+ struct sysdb_attrs *mapped_attrs, - char **_usn_value, - time_t now) - { -@@ -511,6 +512,11 @@ int sdap_save_user(TALLOC_CTX *memctx, - user_attrs, missing, cache_timeout, now); - if (ret) goto done; - -+ if (mapped_attrs != NULL) { -+ ret = sysdb_set_user_attr(dom, user_name, mapped_attrs, SYSDB_MOD_ADD); -+ if (ret) return ret; -+ } -+ - if (_usn_value) { - *_usn_value = talloc_steal(memctx, usn_value); - } -@@ -537,6 +543,7 @@ int sdap_save_users(TALLOC_CTX *memctx, - struct sdap_options *opts, - struct sysdb_attrs **users, - int num_users, -+ struct sysdb_attrs *mapped_attrs, - char **_usn_value) - { - TALLOC_CTX *tmpctx; -@@ -565,11 +572,20 @@ int sdap_save_users(TALLOC_CTX *memctx, - } - in_transaction = true; - -+ if (mapped_attrs != NULL) { -+ ret = sysdb_remove_mapped_data(dom, mapped_attrs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_remove_mapped_data failed, " -+ "some cached entries might contain invalid mapping data.\n"); -+ } -+ } -+ - now = time(NULL); - for (i = 0; i < num_users; i++) { - usn_value = NULL; - -- ret = sdap_save_user(tmpctx, opts, dom, users[i], &usn_value, now); -+ ret = sdap_save_user(tmpctx, opts, dom, users[i], mapped_attrs, -+ &usn_value, now); - - /* Do not fail completely on errors. - * Just report the failure to save and go on */ -@@ -868,6 +884,7 @@ struct sdap_get_users_state { - - char *higher_usn; - struct sysdb_attrs **users; -+ struct sysdb_attrs *mapped_attrs; - size_t count; - }; - -@@ -883,7 +900,8 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- enum sdap_entry_lookup_type lookup_type) -+ enum sdap_entry_lookup_type lookup_type, -+ struct sysdb_attrs *mapped_attrs) - { - errno_t ret; - struct tevent_req *req; -@@ -900,6 +918,23 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - state->filter = filter; - PROBE(SDAP_SEARCH_USER_SEND, state->filter); - -+ if (mapped_attrs == NULL) { -+ state->mapped_attrs = NULL; -+ } else { -+ state->mapped_attrs = sysdb_new_attrs(state); -+ if (state->mapped_attrs == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_attrs_copy(mapped_attrs, state->mapped_attrs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_copy failed.\n"); -+ goto done; -+ } -+ } -+ - subreq = sdap_search_user_send(state, ev, dom, opts, search_bases, - sh, attrs, filter, timeout, lookup_type); - if (subreq == NULL) { -@@ -938,9 +973,11 @@ static void sdap_get_users_done(struct tevent_req *subreq) - } - - PROBE(SDAP_SEARCH_USER_SAVE_BEGIN, state->filter); -+ - ret = sdap_save_users(state, state->sysdb, - state->dom, state->opts, - state->users, state->count, -+ state->mapped_attrs, - &state->higher_usn); - PROBE(SDAP_SEARCH_USER_SAVE_END, state->filter); - if (ret) { -diff --git a/src/providers/ldap/sdap_users.h b/src/providers/ldap/sdap_users.h -index 78dafb31a2a07e7289055daec77c5dc5da1bdeef..a6d088a6d7114db75b0f0ea22ef85c57da6fab0f 100644 ---- a/src/providers/ldap/sdap_users.h -+++ b/src/providers/ldap/sdap_users.h -@@ -34,6 +34,7 @@ int sdap_save_user(TALLOC_CTX *memctx, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sysdb_attrs *attrs, -+ struct sysdb_attrs *mapped_attrs, - char **_usn_value, - time_t now); - --- -2.12.2 - diff --git a/0010-LDAP-always-store-the-certificate-from-the-request.patch b/0010-LDAP-always-store-the-certificate-from-the-request.patch deleted file mode 100644 index 6f192be..0000000 --- a/0010-LDAP-always-store-the-certificate-from-the-request.patch +++ /dev/null @@ -1,178 +0,0 @@ -From 81c564a0692aa4b719af2219f52894e6cd4bdf9f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 30 Nov 2015 12:14:55 +0100 -Subject: [PATCH 10/97] LDAP: always store the certificate from the request -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Store the certificate used to lookup a user as mapped attribute in the -cached user object. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - src/db/sysdb.h | 1 + - src/db/sysdb_ops.c | 4 ++-- - src/providers/ldap/ldap_id.c | 19 ++++++++++++++++++- - src/tests/cmocka/test_nss_srv.c | 2 +- - src/tests/cmocka/test_pam_srv.c | 6 +++--- - src/tests/sysdb-tests.c | 4 ++-- - 6 files changed, 27 insertions(+), 9 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 098f47f91187aac75c58c02f0af738c344765762..3db22b3689bf6ffd9a48e29c229916e3fac9ca1b 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -139,6 +139,7 @@ - - #define SYSDB_AUTH_TYPE "authType" - #define SYSDB_USER_CERT "userCertificate" -+#define SYSDB_USER_MAPPED_CERT "userMappedCertificate" - #define SYSDB_USER_EMAIL "mail" - - #define SYSDB_SUBDOMAIN_REALM "realmName" -diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c -index 6c2254df2b75d3d3419528523103ad9cddb40c9d..8ae25764478e522255b177f9e8de1d3ca1ad43fd 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -4660,7 +4660,7 @@ errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx, - int ret; - char *user_filter; - -- ret = sss_cert_derb64_to_ldap_filter(mem_ctx, cert, SYSDB_USER_CERT, -+ ret = sss_cert_derb64_to_ldap_filter(mem_ctx, cert, SYSDB_USER_MAPPED_CERT, - &user_filter); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sss_cert_derb64_to_ldap_filter failed.\n"); -@@ -4749,7 +4749,7 @@ errno_t sysdb_remove_mapped_data(struct sss_domain_info *domain, - errno_t sysdb_remove_cert(struct sss_domain_info *domain, - const char *cert) - { -- struct ldb_message_element el = { 0, SYSDB_USER_CERT, 0, NULL }; -+ struct ldb_message_element el = { 0, SYSDB_USER_MAPPED_CERT, 0, NULL }; - struct sysdb_attrs del_attrs = { 1, &el }; - const char *attrs[] = {SYSDB_NAME, NULL}; - struct ldb_result *res = NULL; -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index 898ddb18689d55fcc3fdf021b38df0e574003eb2..a8b4bc2cfc6e9d4e0d74b0e3e036afbcbf7eb26e 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -60,6 +60,7 @@ struct users_get_state { - int dp_error; - int sdap_ret; - bool noexist_delete; -+ struct sysdb_attrs *extra_attrs; - }; - - static int users_get_retry(struct tevent_req *req); -@@ -99,6 +100,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - state->conn = conn; - state->dp_error = DP_ERR_FATAL; - state->noexist_delete = noexist_delete; -+ state->extra_attrs = NULL; - - state->op = sdap_id_op_create(state, state->conn->conn_cache); - if (!state->op) { -@@ -251,6 +253,21 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - "sss_cert_derb64_to_ldap_filter failed.\n"); - goto done; - } -+ -+ state->extra_attrs = sysdb_new_attrs(state); -+ if (state->extra_attrs == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_attrs_add_base64_blob(state->extra_attrs, -+ SYSDB_USER_MAPPED_CERT, filter_value); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_base64_blob failed.\n"); -+ goto done; -+ } -+ - break; - default: - ret = EINVAL; -@@ -442,7 +459,7 @@ static void users_get_search(struct tevent_req *req) - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), -- lookup_type, NULL); -+ lookup_type, state->extra_attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index 72bbaf9bf35ebb3fc4208afaa3c7af95922afcb0..76b9c6fb05673130de0957e93291919c263a28f3 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -3508,7 +3508,7 @@ static void test_nss_getnamebycert(void **state) - der = sss_base64_decode(nss_test_ctx, TEST_TOKEN_CERT, &der_size); - assert_non_null(der); - -- ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size); - talloc_free(der); - assert_int_equal(ret, EOK); - -diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c -index ae2e555f7024027d1c0063031f8882bf81a31905..847419658bb983e6548722d6fa6fb22c63ee86b8 100644 ---- a/src/tests/cmocka/test_pam_srv.c -+++ b/src/tests/cmocka/test_pam_srv.c -@@ -1598,7 +1598,7 @@ static int test_lookup_by_cert_cb(void *pvt) - der = sss_base64_decode(pam_test_ctx, pvt, &der_size); - assert_non_null(der); - -- ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size); - talloc_free(der); - assert_int_equal(ret, EOK); - -@@ -1630,7 +1630,7 @@ static int test_lookup_by_cert_double_cb(void *pvt) - der = sss_base64_decode(pam_test_ctx, pvt, &der_size); - assert_non_null(der); - -- ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size); - talloc_free(der); - assert_int_equal(ret, EOK); - -@@ -1658,7 +1658,7 @@ static int test_lookup_by_cert_wrong_user_cb(void *pvt) - der = sss_base64_decode(pam_test_ctx, pvt, &der_size); - assert_non_null(der); - -- ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size); - talloc_free(der); - assert_int_equal(ret, EOK); - -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index c343c734a27a335303974b6866a5d9e88d4c307e..5bdd631fbfa1b4463fb169e5f07b65fb2c784096 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -5721,7 +5721,7 @@ START_TEST(test_sysdb_search_user_by_cert) - val.data = sss_base64_decode(test_ctx, TEST_USER_CERT_DERB64, &val.length); - fail_unless(val.data != NULL, "sss_base64_decode failed."); - -- ret = sysdb_attrs_add_val(data->attrs, SYSDB_USER_CERT, &val); -+ ret = sysdb_attrs_add_val(data->attrs, SYSDB_USER_MAPPED_CERT, &val); - fail_unless(ret == EOK, "sysdb_attrs_add_val failed with [%d][%s].", - ret, strerror(ret)); - -@@ -5750,7 +5750,7 @@ START_TEST(test_sysdb_search_user_by_cert) - data2 = test_data_new_user(test_ctx, 2345671); - fail_if(data2 == NULL); - -- ret = sysdb_attrs_add_val(data2->attrs, SYSDB_USER_CERT, &val); -+ ret = sysdb_attrs_add_val(data2->attrs, SYSDB_USER_MAPPED_CERT, &val); - fail_unless(ret == EOK, "sysdb_attrs_add_val failed with [%d][%s].", - ret, strerror(ret)); - --- -2.12.2 - diff --git a/0011-sss_cert_derb64_to_ldap_filter-add-sss_certmap-suppo.patch b/0011-sss_cert_derb64_to_ldap_filter-add-sss_certmap-suppo.patch deleted file mode 100644 index c850334..0000000 --- a/0011-sss_cert_derb64_to_ldap_filter-add-sss_certmap-suppo.patch +++ /dev/null @@ -1,235 +0,0 @@ -From b341ee51cffd98b642b9c68a417f8a7504e303a1 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 2 Feb 2017 16:34:32 +0100 -Subject: [PATCH 11/97] sss_cert_derb64_to_ldap_filter: add sss_certmap support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Use certificate mapping library if available to lookup a user by -certificate in LDAP. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 1 + - src/db/sysdb_ops.c | 2 +- - src/db/sysdb_views.c | 4 +- - src/providers/ipa/ipa_views.c | 2 +- - src/providers/ldap/ldap_id.c | 2 +- - src/tests/cmocka/test_cert_utils.c | 4 +- - src/util/cert.h | 3 ++ - src/util/cert/cert_common.c | 76 ++++++++++++++++++++++++++++++++------ - 8 files changed, 76 insertions(+), 18 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 7947b7a5fbe3ca1034baac1c13c53300994b1bf8..f262cc24832358910dbb92ccd46f93c9eda8a295 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -952,6 +952,7 @@ libsss_cert_la_LIBADD = \ - $(TALLOC_LIBS) \ - libsss_crypt.la \ - libsss_debug.la \ -+ libsss_certmap.la \ - $(NULL) - libsss_cert_la_LDFLAGS = \ - -avoid-version \ -diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c -index 8ae25764478e522255b177f9e8de1d3ca1ad43fd..919f22370ff87eff2bf0bb569ca90f1ee699a61e 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -4661,7 +4661,7 @@ errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx, - char *user_filter; - - ret = sss_cert_derb64_to_ldap_filter(mem_ctx, cert, SYSDB_USER_MAPPED_CERT, -- &user_filter); -+ NULL, NULL, &user_filter); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sss_cert_derb64_to_ldap_filter failed.\n"); - return ret; -diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c -index 9dc48f5b6c414bbc7c64bcd1fe73553f388588bd..1c416dd14049237e9f35d52f154035e3ff861469 100644 ---- a/src/db/sysdb_views.c -+++ b/src/db/sysdb_views.c -@@ -862,8 +862,8 @@ errno_t sysdb_search_override_by_cert(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sss_cert_derb64_to_ldap_filter(tmp_ctx, cert, SYSDB_USER_CERT, -- &cert_filter); -+ ret = sss_cert_derb64_to_ldap_filter(tmp_ctx, cert, SYSDB_USER_CERT, NULL, -+ NULL, &cert_filter); - - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sss_cert_derb64_to_ldap_filter failed.\n"); -diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c -index 29f589ec1fd05f59175dcc4592e6395941e6e034..5b6fcbc9b7c6f2ea7dbeecb01a5a3fd11b8a6854 100644 ---- a/src/providers/ipa/ipa_views.c -+++ b/src/providers/ipa/ipa_views.c -@@ -156,7 +156,7 @@ static errno_t dp_id_data_to_override_filter(TALLOC_CTX *mem_ctx, - if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_BY_CERT) { - ret = sss_cert_derb64_to_ldap_filter(mem_ctx, ar->filter_value, - ipa_opts->override_map[IPA_AT_OVERRIDE_USER_CERT].name, -- &cert_filter); -+ NULL, NULL, &cert_filter); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sss_cert_derb64_to_ldap_filter failed.\n"); -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index a8b4bc2cfc6e9d4e0d74b0e3e036afbcbf7eb26e..8e60769d09383ac8ebe33e5f64fd4fd9788e82cd 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -247,7 +247,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - } - - ret = sss_cert_derb64_to_ldap_filter(state, filter_value, attr_name, -- &user_filter); -+ NULL, NULL, &user_filter); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sss_cert_derb64_to_ldap_filter failed.\n"); -diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c -index 35e8cb7513968079861048a7e8b0631229f202c0..5830131754e4cf318273151b586ef36d6a349829 100644 ---- a/src/tests/cmocka/test_cert_utils.c -+++ b/src/tests/cmocka/test_cert_utils.c -@@ -297,11 +297,11 @@ void test_sss_cert_derb64_to_ldap_filter(void **state) - 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); -+ ret = sss_cert_derb64_to_ldap_filter(ts, NULL, NULL, NULL, NULL, NULL); - assert_int_equal(ret, EINVAL); - - ret = sss_cert_derb64_to_ldap_filter(ts, "AAECAwQFBgcICQ==", "attrName", -- &filter); -+ NULL, NULL, &filter); - assert_int_equal(ret, EOK); - assert_string_equal(filter, - "(attrName=\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09)"); -diff --git a/src/util/cert.h b/src/util/cert.h -index bb64d0d7a0a48207df60f6e6e554da5e16a16b03..4598aa8df0cd860fed71d9cd2e4beec7f1910578 100644 ---- a/src/util/cert.h -+++ b/src/util/cert.h -@@ -21,6 +21,7 @@ - #include - - #include "util/util.h" -+#include "lib/certmap/sss_certmap.h" - - #ifndef __CERT_H__ - #define __CERT_H__ -@@ -39,6 +40,8 @@ errno_t sss_cert_pem_to_derb64(TALLOC_CTX *mem_ctx, const char *pem, - - errno_t sss_cert_derb64_to_ldap_filter(TALLOC_CTX *mem_ctx, const char *derb64, - const char *attr_name, -+ struct sss_certmap_ctx *certmap_ctx, -+ struct sss_domain_info *dom, - char **ldap_filter); - - errno_t bin_to_ldap_filter_value(TALLOC_CTX *mem_ctx, -diff --git a/src/util/cert/cert_common.c b/src/util/cert/cert_common.c -index a29696ed3cd9f2168f47323fac97d44e9b49f921..766877089429ff1c01000a3986316c74583e3fa4 100644 ---- a/src/util/cert/cert_common.c -+++ b/src/util/cert/cert_common.c -@@ -72,12 +72,17 @@ errno_t sss_cert_pem_to_derb64(TALLOC_CTX *mem_ctx, const char *pem, - - errno_t sss_cert_derb64_to_ldap_filter(TALLOC_CTX *mem_ctx, const char *derb64, - const char *attr_name, -+ struct sss_certmap_ctx *certmap_ctx, -+ struct sss_domain_info *dom, - char **ldap_filter) - { - int ret; - unsigned char *der; - size_t der_size; - char *val; -+ char *filter = NULL; -+ char **domains = NULL; -+ size_t c; - - if (derb64 == NULL || attr_name == NULL) { - return EINVAL; -@@ -89,18 +94,67 @@ errno_t sss_cert_derb64_to_ldap_filter(TALLOC_CTX *mem_ctx, const char *derb64, - 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; -- } -+ if (certmap_ctx == NULL) { -+ 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; -+ *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; -+ } -+ } else { -+ ret = sss_certmap_get_search_filter(certmap_ctx, der, der_size, -+ &filter, &domains); -+ talloc_free(der); -+ if (ret != 0) { -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Certificate does not match matching-rules.\n"); -+ } else { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sss_certmap_get_search_filter failed.\n"); -+ } -+ } else { -+ if (domains == NULL) { -+ if (IS_SUBDOMAIN(dom)) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Rule applies only to local domain.\n"); -+ ret = ENOENT; -+ } -+ } else { -+ for (c = 0; domains[c] != NULL; c++) { -+ if (strcasecmp(dom->name, domains[c]) == 0) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Rule applies to current domain [%s].\n", -+ dom->name); -+ ret = EOK; -+ break; -+ } -+ } -+ if (domains[c] == NULL) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Rule does not apply to current domain [%s].\n", -+ dom->name); -+ ret = ENOENT; -+ } -+ } -+ } -+ -+ if (ret == EOK) { -+ *ldap_filter = talloc_strdup(mem_ctx, filter); -+ if (*ldap_filter == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ } -+ } -+ sss_certmap_free_filter_and_domains(filter, domains); -+ return ret; - } - - return EOK; --- -2.12.2 - diff --git a/0012-sysdb-add-certmap-related-calls.patch b/0012-sysdb-add-certmap-related-calls.patch deleted file mode 100644 index 5673df9..0000000 --- a/0012-sysdb-add-certmap-related-calls.patch +++ /dev/null @@ -1,846 +0,0 @@ -From 49f8ec8e0a3723a748bdb043d6dc1fb2a3977a8a Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 6 Feb 2017 10:27:22 +0100 -Subject: [PATCH 12/97] sysdb: add certmap related calls -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add sysdb calls to write and read data for the certificate mapping -library to the cache. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 17 ++ - src/db/sysdb.h | 27 +++ - src/db/sysdb_certmap.c | 425 ++++++++++++++++++++++++++++++++++ - src/tests/cmocka/test_sysdb_certmap.c | 260 +++++++++++++++++++++ - 4 files changed, 729 insertions(+) - create mode 100644 src/db/sysdb_certmap.c - create mode 100644 src/tests/cmocka/test_sysdb_certmap.c - -diff --git a/Makefile.am b/Makefile.am -index f262cc24832358910dbb92ccd46f93c9eda8a295..bd0ca0d303e1742ad26c7648cd24e2c0135af34e 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -254,6 +254,7 @@ if HAVE_CMOCKA - test_sysdb_ts_cache \ - test_sysdb_views \ - test_sysdb_subdomains \ -+ test_sysdb_certmap \ - test_sysdb_sudo \ - test_sysdb_utils \ - test_wbc_calls \ -@@ -974,6 +975,7 @@ libsss_util_la_SOURCES = \ - src/db/sysdb_ranges.c \ - src/db/sysdb_idmap.c \ - src/db/sysdb_gpo.c \ -+ src/db/sysdb_certmap.c \ - src/monitor/monitor_sbus.c \ - src/providers/dp_auth_util.c \ - src/providers/dp_pam_data_util.c \ -@@ -2773,6 +2775,21 @@ test_sysdb_subdomains_LDADD = \ - libsss_test_common.la \ - $(NULL) - -+test_sysdb_certmap_SOURCES = \ -+ src/tests/cmocka/test_sysdb_certmap.c \ -+ $(NULL) -+test_sysdb_certmap_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(NULL) -+test_sysdb_certmap_LDADD = \ -+ $(CMOCKA_LIBS) \ -+ $(LDB_LIBS) \ -+ $(POPT_LIBS) \ -+ $(TALLOC_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_test_common.la \ -+ $(NULL) -+ - test_sysdb_sudo_SOURCES = \ - src/tests/cmocka/test_sysdb_sudo.c \ - $(NULL) -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 3db22b3689bf6ffd9a48e29c229916e3fac9ca1b..0cbb2c5c02355e9e9a4e73b075f92d16e4855045 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -39,6 +39,7 @@ - #define SYSDB_NETGROUP_CONTAINER "cn=Netgroups" - #define SYSDB_RANGE_CONTAINER "cn=ranges" - #define SYSDB_VIEW_CONTAINER "cn=views" -+#define SYSDB_CERTMAP_CONTAINER "cn=certmap" - #define SYSDB_TMPL_USER_BASE SYSDB_USERS_CONTAINER","SYSDB_DOM_BASE - #define SYSDB_TMPL_GROUP_BASE SYSDB_GROUPS_CONTAINER","SYSDB_DOM_BASE - #define SYSDB_TMPL_CUSTOM_BASE SYSDB_CUSTOM_CONTAINER","SYSDB_DOM_BASE -@@ -46,6 +47,7 @@ - #define SYSDB_TMPL_RANGE_BASE SYSDB_RANGE_CONTAINER","SYSDB_BASE - #define SYSDB_TMPL_VIEW_BASE SYSDB_VIEW_CONTAINER","SYSDB_BASE - #define SYSDB_TMPL_VIEW_SEARCH_BASE "cn=%s,"SYSDB_TMPL_VIEW_BASE -+#define SYSDB_TMPL_CERTMAP_BASE SYSDB_CERTMAP_CONTAINER","SYSDB_BASE - - #define SYSDB_SUBDOMAIN_CLASS "subdomain" - #define SYSDB_USER_CLASS "user" -@@ -58,6 +60,7 @@ - #define SYSDB_ID_RANGE_CLASS "idRange" - #define SYSDB_DOMAIN_ID_RANGE_CLASS "domainIDRange" - #define SYSDB_TRUSTED_AD_DOMAIN_RANGE_CLASS "TrustedADDomainRange" -+#define SYSDB_CERTMAP_CLASS "certificateMappingRule" - - #define SYSDB_DN "dn" - #define SYSDB_NAME "name" -@@ -158,6 +161,12 @@ - #define SYSDB_DOMAIN_ID "domainID" - #define SYSDB_ID_RANGE_TYPE "idRangeType" - -+#define SYSDB_CERTMAP_PRIORITY "priority" -+#define SYSDB_CERTMAP_MATCHING_RULE "matchingRule" -+#define SYSDB_CERTMAP_MAPPING_RULE "mappingRule" -+#define SYSDB_CERTMAP_DOMAINS "domains" -+#define SYSDB_CERTMAP_USER_NAME_HINT "userNameHint" -+ - #define ORIGINALAD_PREFIX "originalAD" - #define OVERRIDE_PREFIX "override" - #define SYSDB_DEFAULT_OVERRIDE_NAME "defaultOverrideName" -@@ -264,6 +273,7 @@ - #define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE - #define SYSDB_TMPL_RANGE SYSDB_NAME"=%s,"SYSDB_TMPL_RANGE_BASE - #define SYSDB_TMPL_OVERRIDE SYSDB_OVERRIDE_ANCHOR_UUID"=%s,"SYSDB_TMPL_VIEW_SEARCH_BASE -+#define SYSDB_TMPL_CERTMAP SYSDB_NAME"=%s,"SYSDB_TMPL_CERTMAP_BASE - - #define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD - #define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE -@@ -320,6 +330,15 @@ struct range_info { - char *range_type; - }; - -+struct certmap_info { -+ char *name; -+ uint32_t priority; -+ char *match_rule; -+ char *map_rule; -+ const char **domains; -+}; -+ -+ - /* These attributes are stored in the timestamp cache */ - extern const char *sysdb_ts_cache_attrs[]; - -@@ -619,6 +638,14 @@ uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom, - const char *attr_name, - uint64_t default_value); - -+errno_t sysdb_update_certmap(struct sysdb_ctx *sysdb, -+ struct certmap_info **certmaps, -+ bool user_name_hint); -+ -+errno_t sysdb_get_certmap(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, -+ struct certmap_info ***certmaps, -+ bool *user_name_hint); -+ - /* Sysdb initialization. - * call this function *only* once to initialize the database and get - * the sysdb ctx */ -diff --git a/src/db/sysdb_certmap.c b/src/db/sysdb_certmap.c -new file mode 100644 -index 0000000000000000000000000000000000000000..4917796b11c3967b4d147ebee7c7e83f09b872ce ---- /dev/null -+++ b/src/db/sysdb_certmap.c -@@ -0,0 +1,425 @@ -+/* -+ SSSD -+ -+ System Database - certificate mapping rules related calls -+ -+ Copyright (C) 2017 Sumit Bose -+ -+ 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 "util/util.h" -+#include "db/sysdb_private.h" -+ -+static errno_t sysdb_create_certmap_container(struct sysdb_ctx *sysdb, -+ bool user_name_hint) -+{ -+ struct ldb_message *msg = NULL; -+ errno_t ret; -+ -+ msg = ldb_msg_new(sysdb); -+ if (msg == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ msg->dn = ldb_dn_new(msg, sysdb->ldb, SYSDB_TMPL_CERTMAP_BASE); -+ if (msg->dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ ret = ldb_msg_add_string(msg, "cn", "certmap"); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ ret = ldb_msg_add_string(msg, SYSDB_CERTMAP_USER_NAME_HINT, -+ user_name_hint ? "TRUE" : "FALSE"); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ /* do a synchronous add */ -+ ret = ldb_add(sysdb->ldb, msg); -+ if (ret != LDB_SUCCESS) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Failed to add certmap container (%d, [%s])!\n", -+ ret, ldb_errstring(sysdb->ldb)); -+ ret = EIO; -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ talloc_free(msg); -+ -+ return ret; -+} -+ -+static errno_t sysdb_certmap_add(struct sysdb_ctx *sysdb, -+ struct certmap_info *certmap) -+{ -+ struct ldb_message *msg; -+ struct ldb_message_element *el; -+ int ret; -+ TALLOC_CTX *tmp_ctx; -+ size_t c; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed"); -+ return ENOMEM; -+ } -+ -+ msg = ldb_msg_new(tmp_ctx); -+ if (msg == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ msg->dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, -+ SYSDB_TMPL_CERTMAP, certmap->name); -+ if (msg->dn == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_CERTMAP_CLASS); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); -+ goto done; -+ } -+ -+ ret = sysdb_add_string(msg, SYSDB_NAME, certmap->name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); -+ goto done; -+ } -+ -+ if (certmap->map_rule != NULL) { -+ ret = sysdb_add_string(msg, SYSDB_CERTMAP_MAPPING_RULE, -+ certmap->map_rule); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); -+ goto done; -+ } -+ } -+ -+ if (certmap->match_rule != NULL) { -+ ret = sysdb_add_string(msg, SYSDB_CERTMAP_MATCHING_RULE, -+ certmap->match_rule); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); -+ goto done; -+ } -+ } -+ -+ if (certmap->domains != NULL) { -+ for (c = 0; certmap->domains[c] != NULL; c++); -+ el = talloc_zero(tmp_ctx, struct ldb_message_element); -+ if (el == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ el->name = talloc_strdup(el, SYSDB_CERTMAP_DOMAINS); -+ if(el->name == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ el->num_values = c; -+ el->values = talloc_zero_array(el, struct ldb_val, c + 1); -+ if (el->values == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (c = 0; certmap->domains[c] != NULL; c++) { -+ el->values[c].data = (uint8_t *) talloc_strdup(el->values, -+ certmap->domains[c]); -+ if (el->values[c].data == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ el->values[c].length = strlen(certmap->domains[c]); -+ } -+ -+ ret = ldb_msg_add(msg, el, LDB_FLAG_MOD_ADD); -+ if (ret != LDB_SUCCESS) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add failed.\n"); -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ } -+ -+ ret = sysdb_add_ulong(msg, SYSDB_CERTMAP_PRIORITY, -+ (unsigned long)certmap->priority); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_ulong failed.\n"); -+ goto done; -+ } -+ -+ ret = ldb_add(sysdb->ldb, msg); -+ if (ret != LDB_SUCCESS) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_add failed.\n"); -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret) { -+ DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, sss_strerror(ret)); -+ } -+ talloc_zfree(tmp_ctx); -+ return ret; -+} -+ -+errno_t sysdb_update_certmap(struct sysdb_ctx *sysdb, -+ struct certmap_info **certmaps, -+ bool user_name_hint) -+{ -+ size_t c; -+ struct ldb_dn *container_dn = NULL; -+ bool in_transaction = false; -+ int ret; -+ int sret; -+ -+ if (certmaps == NULL) { -+ return EINVAL; -+ } -+ -+ container_dn = ldb_dn_new(sysdb, sysdb->ldb, SYSDB_TMPL_CERTMAP_BASE); -+ if (container_dn == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); -+ return ENOMEM; -+ } -+ -+ ret = sysdb_transaction_start(sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n"); -+ goto done; -+ } -+ in_transaction = true; -+ -+ ret = sysdb_delete_recursive(sysdb, container_dn, true); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n"); -+ goto done; -+ } -+ ret = sysdb_create_certmap_container(sysdb, user_name_hint); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_create_certmap_container failed.\n"); -+ goto done; -+ } -+ -+ for (c = 0; certmaps[c] != NULL; c++) { -+ ret = sysdb_certmap_add(sysdb, certmaps[c]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_certmap_add failed.\n"); -+ goto done; -+ } -+ } -+ -+ ret = sysdb_transaction_commit(sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_transaction_commit failed.\n"); -+ goto done; -+ } -+ in_transaction = false; -+ -+done: -+ if (in_transaction) { -+ sret = sysdb_transaction_cancel(sysdb); -+ if (sret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction.\n"); -+ } -+ } -+ -+ talloc_free(container_dn); -+ -+ return ret; -+} -+ -+errno_t sysdb_get_certmap(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, -+ struct certmap_info ***certmaps, bool *user_name_hint) -+{ -+ size_t c; -+ size_t d; -+ struct ldb_dn *container_dn = NULL; -+ int ret; -+ struct certmap_info **maps; -+ TALLOC_CTX *tmp_ctx = NULL; -+ struct ldb_result *res; -+ const char *tmp_str; -+ uint64_t tmp_uint; -+ struct ldb_message_element *tmp_el; -+ const char *attrs[] = {SYSDB_NAME, -+ SYSDB_CERTMAP_PRIORITY, -+ SYSDB_CERTMAP_MATCHING_RULE, -+ SYSDB_CERTMAP_MAPPING_RULE, -+ SYSDB_CERTMAP_DOMAINS, -+ NULL}; -+ const char *config_attrs[] = {SYSDB_CERTMAP_USER_NAME_HINT, -+ NULL}; -+ size_t num_values; -+ bool hint = false; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ container_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_TMPL_CERTMAP_BASE); -+ if (container_dn == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = ldb_search(sysdb->ldb, tmp_ctx, &res, container_dn, LDB_SCOPE_BASE, -+ config_attrs, SYSDB_CERTMAP_USER_NAME_HINT"=*"); -+ if (ret != LDB_SUCCESS || res->count != 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to read certmap config, skipping.\n"); -+ } else { -+ hint = ldb_msg_find_attr_as_bool(res->msgs[0], -+ SYSDB_CERTMAP_USER_NAME_HINT, false); -+ } -+ -+ ret = ldb_search(sysdb->ldb, tmp_ctx, &res, -+ container_dn, LDB_SCOPE_SUBTREE, -+ attrs, "objectclass=%s", SYSDB_CERTMAP_CLASS); -+ if (ret != LDB_SUCCESS) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_search failed.\n"); -+ ret = EIO; -+ goto done; -+ } -+ -+ if (res->count == 0) { -+ DEBUG(SSSDBG_TRACE_FUNC, "No certificate maps found.\n"); -+ ret = ENOENT; -+ goto done; -+ } -+ -+ maps = talloc_zero_array(tmp_ctx, struct certmap_info *, res->count + 1); -+ if (maps == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (c = 0; c < res->count; c++) { -+ maps[c] = talloc_zero(maps, struct certmap_info); -+ if (maps[c] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], SYSDB_NAME, NULL); -+ if (tmp_str == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "The object [%s] doesn't have a name.\n", -+ ldb_dn_get_linearized(res->msgs[c]->dn)); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ maps[c]->name = talloc_strdup(maps, tmp_str); -+ if (maps[c]->name == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], -+ SYSDB_CERTMAP_MAPPING_RULE, NULL); -+ if (tmp_str != NULL) { -+ maps[c]->map_rule = talloc_strdup(maps, tmp_str); -+ if (maps[c]->map_rule == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], -+ SYSDB_CERTMAP_MATCHING_RULE, NULL); -+ if (tmp_str != NULL) { -+ maps[c]->match_rule = talloc_strdup(maps, tmp_str); -+ if (maps[c]->match_rule == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ tmp_uint = ldb_msg_find_attr_as_uint64(res->msgs[c], -+ SYSDB_CERTMAP_PRIORITY, -+ (uint64_t) -1); -+ if (tmp_uint != (uint64_t) -1) { -+ if (tmp_uint >= UINT32_MAX) { -+ DEBUG(SSSDBG_OP_FAILURE, "Priority value [%lu] too large.\n", -+ (unsigned long) tmp_uint); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ maps[c]->priority = (uint32_t) tmp_uint; -+ } -+ -+ tmp_el = ldb_msg_find_element(res->msgs[c], SYSDB_CERTMAP_DOMAINS); -+ if (tmp_el != NULL) { -+ num_values = tmp_el->num_values; -+ } else { -+ num_values = 0; -+ } -+ -+ maps[c]->domains = talloc_zero_array(maps[c], const char *, -+ num_values + 1); -+ if (maps[c]->domains == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (d = 0; d < num_values; d++) { -+ maps[c]->domains[d] = talloc_strndup(maps[c]->domains, -+ (char *) tmp_el->values[d].data, -+ tmp_el->values[d].length); -+ if (maps[c]->domains[d] == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ } -+ -+ *certmaps = talloc_steal(mem_ctx, maps); -+ *user_name_hint = hint; -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -diff --git a/src/tests/cmocka/test_sysdb_certmap.c b/src/tests/cmocka/test_sysdb_certmap.c -new file mode 100644 -index 0000000000000000000000000000000000000000..fb07165561779226935f436c308c85abfc305635 ---- /dev/null -+++ b/src/tests/cmocka/test_sysdb_certmap.c -@@ -0,0 +1,260 @@ -+/* -+ SSSD -+ -+ sysdb_certmap - Tests for sysdb certmap realted calls -+ -+ Authors: -+ Jakub Hrozek -+ -+ Copyright (C) 2017 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 -+#include -+#include -+#include -+#include -+ -+#include "tests/cmocka/common_mock.h" -+#include "tests/common.h" -+ -+#define TESTS_PATH "certmap_" BASE_FILE_STEM -+#define TEST_CONF_DB "test_sysdb_certmap.ldb" -+#define TEST_ID_PROVIDER "ldap" -+#define TEST_DOM_NAME "certmap_test" -+ -+struct certmap_test_ctx { -+ struct sss_test_ctx *tctx; -+}; -+ -+static int test_sysdb_setup(void **state) -+{ -+ struct certmap_test_ctx *test_ctx; -+ struct sss_test_conf_param params[] = { -+ { NULL, NULL }, /* Sentinel */ -+ }; -+ -+ assert_true(leak_check_setup()); -+ -+ test_ctx = talloc_zero(global_talloc_context, -+ struct certmap_test_ctx); -+ assert_non_null(test_ctx); -+ check_leaks_push(test_ctx); -+ -+ test_dom_suite_setup(TESTS_PATH); -+ -+ test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, -+ TEST_CONF_DB, TEST_DOM_NAME, -+ TEST_ID_PROVIDER, params); -+ assert_non_null(test_ctx->tctx); -+ -+ *state = test_ctx; -+ return 0; -+} -+ -+static int test_sysdb_teardown(void **state) -+{ -+ struct certmap_test_ctx *test_ctx = -+ talloc_get_type(*state, struct certmap_test_ctx); -+ -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); -+ talloc_free(test_ctx->tctx); -+ assert_true(check_leaks_pop(test_ctx)); -+ talloc_free(test_ctx); -+ assert_true(leak_check_teardown()); -+ return 0; -+} -+ -+static void test_sysdb_get_certmap_not_exists(void **state) -+{ -+ int ret; -+ struct certmap_info **certmap; -+ bool user_name_hint; -+ struct certmap_test_ctx *ctctx = talloc_get_type(*state, -+ struct certmap_test_ctx); -+ -+ ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, -+ &user_name_hint); -+ assert_int_equal(ret, ENOENT); -+ -+} -+ -+static void check_certmap(struct certmap_info *m, struct certmap_info *r, -+ size_t exp_domains) -+{ -+ size_t d; -+ -+ assert_non_null(r); -+ assert_non_null(m); -+ assert_string_equal(m->name, r->name); -+ -+ if (r->map_rule == NULL) { -+ assert_null(m->map_rule); -+ } else { -+ assert_string_equal(m->map_rule, r->map_rule); -+ } -+ -+ if (r->match_rule == NULL) { -+ assert_null(m->match_rule); -+ } else { -+ assert_string_equal(m->match_rule, r->match_rule); -+ } -+ -+ assert_int_equal(m->priority, r->priority); -+ assert_non_null(m->domains); -+ if (r->domains == NULL) { -+ assert_null(m->domains[0]); -+ } else { -+ for (d = 0; r->domains[d]; d++) { -+ assert_non_null(m->domains[d]); -+ assert_true(string_in_list(m->domains[d], discard_const(r->domains), -+ true)); -+ } -+ -+ assert_int_equal(d, exp_domains); -+ } -+ -+} -+ -+static void test_sysdb_update_certmap(void **state) -+{ -+ int ret; -+ const char *domains[] = { "dom1.test", "dom2.test", "dom3.test", NULL }; -+ struct certmap_info map_a = { discard_const("map_a"), 11, discard_const("abc"), discard_const("def"), NULL }; -+ struct certmap_info map_b = { discard_const("map_b"), 22, discard_const("abc"), NULL, domains }; -+ struct certmap_info *certmap_empty[] = { NULL }; -+ struct certmap_info *certmap_a[] = { &map_a, NULL }; -+ struct certmap_info *certmap_b[] = { &map_b, NULL }; -+ struct certmap_info *certmap_ab[] = { &map_a, &map_b, NULL }; -+ struct certmap_info **certmap; -+ struct certmap_test_ctx *ctctx = talloc_get_type(*state, -+ struct certmap_test_ctx); -+ bool user_name_hint; -+ -+ ret = sysdb_update_certmap(ctctx->tctx->sysdb, NULL, false); -+ assert_int_equal(ret, EINVAL); -+ -+ ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_empty, false); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, -+ &user_name_hint); -+ assert_int_equal(ret, ENOENT); -+ -+ ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_a, false); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, -+ &user_name_hint); -+ assert_int_equal(ret, EOK); -+ assert_false(user_name_hint); -+ assert_non_null(certmap); -+ assert_non_null(certmap[0]); -+ assert_string_equal(certmap[0]->name, map_a.name); -+ assert_string_equal(certmap[0]->map_rule, map_a.map_rule); -+ assert_string_equal(certmap[0]->match_rule, map_a.match_rule); -+ assert_int_equal(certmap[0]->priority, map_a.priority); -+ assert_non_null(certmap[0]->domains); -+ assert_null(certmap[0]->domains[0]); -+ assert_null(certmap[1]); -+ check_certmap(certmap[0], &map_a, 0); -+ talloc_free(certmap); -+ -+ ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_b, true); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, -+ &user_name_hint); -+ assert_int_equal(ret, EOK); -+ assert_true(user_name_hint); -+ assert_non_null(certmap); -+ assert_non_null(certmap[0]); -+ -+ check_certmap(certmap[0], &map_b, 3); -+ assert_null(certmap[1]); -+ talloc_free(certmap); -+ -+ ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_ab, false); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, -+ &user_name_hint); -+ assert_int_equal(ret, EOK); -+ assert_false(user_name_hint); -+ assert_non_null(certmap); -+ assert_non_null(certmap[0]); -+ assert_non_null(certmap[1]); -+ assert_null(certmap[2]); -+ if (strcmp(certmap[0]->name, "map_a") == 0) { -+ check_certmap(certmap[0], &map_a, 0); -+ check_certmap(certmap[1], &map_b, 3); -+ } else { -+ check_certmap(certmap[0], &map_b, 3); -+ check_certmap(certmap[1], &map_a, 0); -+ } -+ talloc_free(certmap); -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ int rv; -+ int no_cleanup = 0; -+ poptContext pc; -+ int opt; -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ SSSD_DEBUG_OPTS -+ {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0, -+ _("Do not delete the test database after a test run"), NULL }, -+ POPT_TABLEEND -+ }; -+ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown(test_sysdb_get_certmap_not_exists, -+ test_sysdb_setup, -+ test_sysdb_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_update_certmap, -+ test_sysdb_setup, -+ test_sysdb_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); -+ -+ tests_set_cwd(); -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, LOCAL_SYSDB_FILE); -+ test_dom_suite_setup(TESTS_PATH); -+ rv = cmocka_run_group_tests(tests, NULL, NULL); -+ -+ if (rv == 0 && no_cleanup == 0) { -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, LOCAL_SYSDB_FILE); -+ } -+ return rv; -+} --- -2.12.2 - diff --git a/0013-IPA-add-certmap-support.patch b/0013-IPA-add-certmap-support.patch deleted file mode 100644 index a52276d..0000000 --- a/0013-IPA-add-certmap-support.patch +++ /dev/null @@ -1,484 +0,0 @@ -From c44728a02d5e2c9eaced11e74820a6ae6a985f61 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 6 Feb 2017 10:28:46 +0100 -Subject: [PATCH 13/97] IPA: add certmap support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Read certificate mapping data from the IPA server and configure the -certificate mapping library accordingly. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - src/providers/ipa/ipa_config.h | 2 + - src/providers/ipa/ipa_subdomains.c | 354 ++++++++++++++++++++++++++++++ - src/providers/ipa/ipa_subdomains_server.c | 4 + - src/providers/ldap/ldap_id.c | 4 +- - src/providers/ldap/sdap.h | 4 + - 5 files changed, 367 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_config.h b/src/providers/ipa/ipa_config.h -index 2f1e147d7edab0aca2a16269c6a73bc607b21bd5..60f2d5d7b71227a1d86889ceaf6f0f9ac868480d 100644 ---- a/src/providers/ipa/ipa_config.h -+++ b/src/providers/ipa/ipa_config.h -@@ -37,6 +37,8 @@ - #define IPA_CONFIG_SEARCH_BASE_TEMPLATE "cn=etc,%s" - #define IPA_CONFIG_FILTER "(&(cn=ipaConfig)(objectClass=ipaGuiConfig))" - -+#define IPA_OC_CONFIG "ipaConfig" -+ - struct tevent_req * ipa_get_config_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_handle *sh, -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index b2e96b204213a52014edcc6042ffa1ff8152b8bf..7537550606ef09c0b87a80932c75aa4f93c0efab 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -56,6 +56,24 @@ - - #define IPA_SUBDOMAIN_DISABLED_PERIOD 3600 - -+#define IPA_OC_CERTMAP_CONFIG_OBJECT "ipaCertMapConfigObject" -+#define IPA_CERTMAP_PROMPT_USERNAME "ipaCertMapPromptUserName" -+ -+#define IPA_OC_CERTMAP_RULE "ipaCertMapRule" -+#define IPA_CERTMAP_MAPRULE "ipaCertMapMapRule" -+#define IPA_CERTMAP_MATCHRULE "ipaCertMapMatchRule" -+#define IPA_CERTMAP_PRIORITY "ipaCertMapPriority" -+#define IPA_ENABLED_FLAG "ipaEnabledFlag" -+#define IPA_TRUE_VALUE "TRUE" -+#define IPA_ASSOCIATED_DOMAIN "associatedDomain" -+ -+#define OBJECTCLASS "objectClass" -+ -+#define CERTMAP_FILTER "(|(&("OBJECTCLASS"="IPA_OC_CERTMAP_RULE")" \ -+ "("IPA_ENABLED_FLAG"="IPA_TRUE_VALUE"))" \ -+ "("OBJECTCLASS"="IPA_OC_CERTMAP_CONFIG_OBJECT"))" -+ -+ - struct ipa_subdomains_ctx { - struct be_ctx *be_ctx; - struct ipa_id_ctx *ipa_id_ctx; -@@ -286,6 +304,193 @@ done: - return ret; - } - -+struct priv_sss_debug { -+ int level; -+}; -+ -+void ext_debug(void *private, const char *file, long line, const char *function, -+ const char *format, ...) -+{ -+ va_list ap; -+ struct priv_sss_debug *data = private; -+ int level = SSSDBG_OP_FAILURE; -+ -+ if (data != NULL) { -+ level = data->level; -+ } -+ -+ if (DEBUG_IS_SET(level)) { -+ va_start(ap, format); -+ sss_vdebug_fn(file, line, function, level, APPEND_LINE_FEED, -+ format, ap); -+ va_end(ap); -+ } -+} -+ -+static errno_t ipa_certmap_parse_results(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ struct sdap_options *sdap_opts, -+ size_t count, -+ struct sysdb_attrs **reply, -+ struct certmap_info ***_certmap_list) -+{ -+ struct certmap_info **certmap_list = NULL; -+ struct certmap_info *m; -+ const char *value; -+ const char **values; -+ size_t c; -+ size_t lc = 0; -+ int ret; -+ struct sss_certmap_ctx *certmap_ctx = NULL; -+ const char **ocs = NULL; -+ bool user_name_hint = false; -+ -+ certmap_list = talloc_zero_array(mem_ctx, struct certmap_info *, count + 1); -+ if (certmap_list == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n"); -+ return ENOMEM; -+ } -+ -+ for (c = 0; c < count; c++) { -+ ret = sysdb_attrs_get_string_array(reply[c], SYSDB_OBJECTCLASS, mem_ctx, -+ &ocs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Missing objectclasses for config objects.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (string_in_list(IPA_OC_CERTMAP_CONFIG_OBJECT, discard_const(ocs), -+ false)) { -+ ret = sysdb_attrs_get_bool(reply[c], IPA_CERTMAP_PROMPT_USERNAME, -+ &user_name_hint); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to read user name hint option, skipping.\n"); -+ } -+ continue; -+ } -+ -+ m = talloc_zero(certmap_list, struct certmap_info); -+ if (m == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); -+ goto done; -+ } -+ -+ m->name = talloc_strdup(m, value); -+ if (m->name == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_attrs_get_string(reply[c], IPA_CERTMAP_MATCHRULE, &value); -+ if (ret == EOK) { -+ m->match_rule = talloc_strdup(m, value); -+ if (m->match_rule == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } else if (ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); -+ goto done; -+ } -+ -+ ret = sysdb_attrs_get_string(reply[c], IPA_CERTMAP_MAPRULE, &value); -+ if (ret == EOK) { -+ m->map_rule = talloc_strdup(m, value); -+ if (m->map_rule == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } else if (ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); -+ goto done; -+ } -+ -+ ret = sysdb_attrs_get_string_array(reply[c], IPA_ASSOCIATED_DOMAIN, m, -+ &values); -+ if (ret == EOK) { -+ m->domains = values; -+ } else if (ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); -+ goto done; -+ } -+ -+ ret = sysdb_attrs_get_uint32_t(reply[c], IPA_CERTMAP_PRIORITY, -+ &m->priority); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); -+ goto done; -+ } else if (ret == ENOENT) { -+ m->priority = SSS_CERTMAP_MIN_PRIO; -+ } -+ -+ certmap_list[lc++] = m; -+ } -+ -+ certmap_list[lc] = NULL; -+ -+ ret = sss_certmap_init(mem_ctx, ext_debug, NULL, &certmap_ctx); -+ if (ret != 0) { -+ DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_init failed.\n"); -+ goto done; -+ } -+ -+ for (c = 0; certmap_list[c] != NULL; c++) { -+ DEBUG(SSSDBG_TRACE_ALL, "Trying to add rule [%s][%d][%s][%s].\n", -+ certmap_list[c]->name, -+ certmap_list[c]->priority, -+ certmap_list[c]->match_rule, -+ certmap_list[c]->map_rule); -+ -+ ret = sss_certmap_add_rule(certmap_ctx, certmap_list[c]->priority, -+ certmap_list[c]->match_rule, -+ certmap_list[c]->map_rule, -+ certmap_list[c]->domains); -+ if (ret != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "sss_certmap_add_rule failed for rule [%s], skipping. " -+ "Please check for typos and if rule syntax is supported.\n", -+ certmap_list[c]->name); -+ goto done; -+ } -+ } -+ -+ ret = sysdb_update_certmap(domain->sysdb, certmap_list, user_name_hint); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_certmap failed"); -+ goto done; -+ } -+ -+ sss_certmap_free_ctx(sdap_opts->certmap_ctx); -+ sdap_opts->certmap_ctx = talloc_steal(sdap_opts, certmap_ctx); -+ -+ if (_certmap_list != NULL) { -+ *_certmap_list = certmap_list; -+ } -+ ret = EOK; -+ -+done: -+ talloc_free(ocs); -+ if (ret != EOK) { -+ sss_certmap_free_ctx(certmap_ctx); -+ talloc_free(certmap_list); -+ } -+ -+ return ret; -+} -+ - static errno_t ipa_subdom_enumerates(struct sss_domain_info *parent, - struct sysdb_attrs *attrs, - bool *_enumerates) -@@ -801,6 +1006,125 @@ static errno_t ipa_subdomains_ranges_recv(struct tevent_req *req) - return EOK; - } - -+#define IPA_CERTMAP_SEARCH_BASE_TEMPLATE "cn=certmap,%s" -+ -+struct ipa_subdomains_certmap_state { -+ struct sss_domain_info *domain; -+ struct sdap_options *sdap_opts; -+}; -+ -+static void ipa_subdomains_certmap_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+ipa_subdomains_certmap_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ipa_subdomains_ctx *sd_ctx, -+ struct sdap_handle *sh) -+{ -+ struct ipa_subdomains_certmap_state *state; -+ struct tevent_req *subreq; -+ struct tevent_req *req; -+ errno_t ret; -+ char *ldap_basedn; -+ char *search_base; -+ const char *attrs[] = { OBJECTCLASS, IPA_CN, -+ IPA_CERTMAP_MAPRULE, IPA_CERTMAP_MATCHRULE, -+ IPA_CERTMAP_PRIORITY, IPA_ASSOCIATED_DOMAIN, -+ IPA_CERTMAP_PROMPT_USERNAME, -+ NULL }; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct ipa_subdomains_certmap_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); -+ return NULL; -+ } -+ -+ state->domain = sd_ctx->be_ctx->domain; -+ state->sdap_opts = sd_ctx->sdap_id_ctx->opts; -+ -+ ret = domain_to_basedn(state, state->domain->name, &ldap_basedn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n"); -+ goto immediately; -+ } -+ -+ search_base = talloc_asprintf(state, IPA_CERTMAP_SEARCH_BASE_TEMPLATE, -+ ldap_basedn); -+ if (search_base == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ subreq = sdap_get_generic_send(state, ev, sd_ctx->sdap_id_ctx->opts, sh, -+ search_base, LDAP_SCOPE_SUBTREE, -+ CERTMAP_FILTER, -+ attrs, NULL, 0, 0, false); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ tevent_req_set_callback(subreq, ipa_subdomains_certmap_done, req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void ipa_subdomains_certmap_done(struct tevent_req *subreq) -+{ -+ struct ipa_subdomains_certmap_state *state; -+ struct tevent_req *req; -+ struct sysdb_attrs **reply; -+ size_t reply_count; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct ipa_subdomains_certmap_state); -+ -+ ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get data from LDAP [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = ipa_certmap_parse_results(state, state->domain, -+ state->sdap_opts, -+ reply_count, reply, NULL); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unable to parse certmap results [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t ipa_subdomains_certmap_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -+ - struct ipa_subdomains_master_state { - struct sss_domain_info *domain; - struct ipa_options *ipa_options; -@@ -1365,6 +1689,7 @@ struct ipa_subdomains_refresh_state { - static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req); - static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq); -+static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq); -@@ -1487,6 +1812,35 @@ static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq) - return; - } - -+ subreq = ipa_subdomains_certmap_send(state, state->ev, state->sd_ctx, -+ sdap_id_op_handle(state->sdap_op)); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ tevent_req_set_callback(subreq, ipa_subdomains_refresh_certmap_done, req); -+ return; -+} -+ -+static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq) -+{ -+ struct ipa_subdomains_refresh_state *state; -+ struct tevent_req *req; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct ipa_subdomains_refresh_state); -+ -+ ret = ipa_subdomains_certmap_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to read certificate mapping rules " -+ "[%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ - subreq = ipa_subdomains_master_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); - if (subreq == NULL) { -diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c -index 1af8676c5a9c49121d0f0118a46796c6637f04f9..ae3baf036e4278fb67d86b42742fb7e80b46724e 100644 ---- a/src/providers/ipa/ipa_subdomains_server.c -+++ b/src/providers/ipa/ipa_subdomains_server.c -@@ -362,6 +362,10 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, - ad_id_ctx->sdap_id_ctx->opts->idmap_ctx = - id_ctx->sdap_id_ctx->opts->idmap_ctx; - -+ /* Set up the certificate mapping context */ -+ ad_id_ctx->sdap_id_ctx->opts->certmap_ctx = -+ id_ctx->sdap_id_ctx->opts->certmap_ctx; -+ - *_ad_id_ctx = ad_id_ctx; - return EOK; - } -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index 8e60769d09383ac8ebe33e5f64fd4fd9788e82cd..0bee0ca8d71abece6749fdb8393b9ceacb64417d 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -247,7 +247,9 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - } - - ret = sss_cert_derb64_to_ldap_filter(state, filter_value, attr_name, -- NULL, NULL, &user_filter); -+ ctx->opts->certmap_ctx, -+ state->domain, -+ &user_filter); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sss_cert_derb64_to_ldap_filter failed.\n"); -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index 6079a8bf62d0bdf23c8d462dc0f19c705e391a6e..afdc01948eefe9dda943c8c7ad01a42dd76a1da8 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -25,6 +25,7 @@ - #include "providers/backend.h" - #include - #include "util/sss_ldap.h" -+#include "lib/certmap/sss_certmap.h" - - struct sdap_msg { - struct sdap_msg *next; -@@ -478,6 +479,9 @@ struct sdap_options { - - bool support_matching_rule; - enum dc_functional_level dc_functional_level; -+ -+ /* Certificate mapping support */ -+ struct sss_certmap_ctx *certmap_ctx; - }; - - struct sdap_server_opts { --- -2.12.2 - diff --git a/0014-nss-idmap-add-sss_nss_getlistbycert.patch b/0014-nss-idmap-add-sss_nss_getlistbycert.patch deleted file mode 100644 index 6cba9cd..0000000 --- a/0014-nss-idmap-add-sss_nss_getlistbycert.patch +++ /dev/null @@ -1,736 +0,0 @@ -From 440797cba931aa491bf418035f55935943e22b4b Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 15 Mar 2017 14:21:26 +0100 -Subject: [PATCH 14/97] nss-idmap: add sss_nss_getlistbycert() - -This patch adds a getlistbycert() call to libsss_nss_idmap to make it on -par with InfoPipe. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 2 +- - src/python/pysss_nss_idmap.c | 103 ++++++++++++++++++- - src/responder/nss/nss_cmd.c | 7 ++ - src/responder/nss/nss_protocol.h | 6 ++ - src/responder/nss/nss_protocol_sid.c | 63 ++++++++++++ - src/sss_client/idmap/sss_nss_idmap.c | 110 +++++++++++++++++++- - src/sss_client/idmap/sss_nss_idmap.exports | 6 ++ - src/sss_client/idmap/sss_nss_idmap.h | 17 +++- - src/sss_client/sss_cli.h | 5 + - src/tests/cmocka/test_nss_srv.c | 158 +++++++++++++++++++++++++++++ - 10 files changed, 471 insertions(+), 6 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index bd0ca0d303e1742ad26c7648cd24e2c0135af34e..7516338bc6fd95045d20db8155a0c82fd7003358 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1128,7 +1128,7 @@ libsss_nss_idmap_la_LIBADD = \ - $(CLIENT_LIBS) - libsss_nss_idmap_la_LDFLAGS = \ - -Wl,--version-script,$(srcdir)/src/sss_client/idmap/sss_nss_idmap.exports \ -- -version-info 2:0:2 -+ -version-info 3:0:3 - - dist_noinst_DATA += src/sss_client/idmap/sss_nss_idmap.exports - -diff --git a/src/python/pysss_nss_idmap.c b/src/python/pysss_nss_idmap.c -index c57cc10a86a7a9a22a791c1eae027a1aafa8f780..2e5851c7a6e48629fd93e428aada499fcbe36ebb 100644 ---- a/src/python/pysss_nss_idmap.c -+++ b/src/python/pysss_nss_idmap.c -@@ -36,9 +36,37 @@ enum lookup_type { - SIDBYID, - NAMEBYSID, - IDBYSID, -- NAMEBYCERT -+ NAMEBYCERT, -+ LISTBYCERT - }; - -+static int add_dict_to_list(PyObject *py_list, PyObject *res_type, -+ PyObject *res, PyObject *id_type) -+{ -+ int ret; -+ PyObject *py_dict; -+ -+ py_dict = PyDict_New(); -+ if (py_dict == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = PyDict_SetItem(py_dict, res_type, res); -+ if (ret != 0) { -+ Py_XDECREF(py_dict); -+ return ret; -+ } -+ -+ ret = PyDict_SetItem(py_dict, PyBytes_FromString(SSS_TYPE_KEY), id_type); -+ if (ret != 0) { -+ Py_XDECREF(py_dict); -+ return ret; -+ } -+ -+ ret = PyList_Append(py_list, py_dict); -+ -+ return ret; -+} - static int add_dict(PyObject *py_result, PyObject *key, PyObject *res_type, - PyObject *res, PyObject *id_type) - { -@@ -191,6 +219,57 @@ static int do_getnamebycert(PyObject *py_result, PyObject *py_cert) - return ret; - } - -+static int do_getlistbycert(PyObject *py_result, PyObject *py_cert) -+{ -+ int ret; -+ const char *cert; -+ char **names = NULL; -+ enum sss_id_type *id_types = NULL; -+ size_t c; -+ -+ cert = py_string_or_unicode_as_string(py_cert); -+ if (cert == NULL) { -+ return EINVAL; -+ } -+ -+ ret = sss_nss_getlistbycert(cert, &names, &id_types); -+ if (ret == 0) { -+ -+ PyObject *py_list; -+ -+ py_list = PyList_New(0); -+ if (py_list == NULL) { -+ return ENOMEM; -+ } -+ -+ for (c = 0; names[c] != NULL; c++) { -+ ret = add_dict_to_list(py_list, -+ PyBytes_FromString(SSS_NAME_KEY), -+ PyUnicode_FromString(names[c]), -+ PYNUMBER_FROMLONG(id_types[c])); -+ if (ret != 0) { -+ goto done; -+ } -+ } -+ ret = PyDict_SetItem(py_result, py_cert, py_list); -+ if (ret != 0) { -+ goto done; -+ } -+ } -+ -+done: -+ free(id_types); -+ if (names != NULL) { -+ for (c = 0; names[c] != NULL; c++) { -+ free(names[c]); -+ } -+ free(names); -+ } -+ -+ return ret; -+} -+ -+ - static int do_getidbysid(PyObject *py_result, PyObject *py_sid) - { - const char *sid; -@@ -231,6 +310,9 @@ static int do_lookup(enum lookup_type type, PyObject *py_result, - case NAMEBYCERT: - return do_getnamebycert(py_result, py_inp); - break; -+ case LISTBYCERT: -+ return do_getlistbycert(py_result, py_inp); -+ break; - default: - return ENOSYS; - } -@@ -368,7 +450,7 @@ static PyObject * py_getidbysid(PyObject *module, PyObject *args) - } - - PyDoc_STRVAR(getnamebycert_doc, --"getnamebycert(sid or list/tuple of certificates) -> dict(sid => dict(results))\n\ -+"getnamebycert(certificate or list/tuple of certificates) -> dict(certificate => dict(results))\n\ - \n\ - Returns a dictionary with a dictonary of results for each given certificates.\n\ - The result dictonary contain the name and the type of the object which can be\n\ -@@ -382,6 +464,21 @@ static PyObject * py_getnamebycert(PyObject *module, PyObject *args) - return check_args(NAMEBYCERT, args); - } - -+PyDoc_STRVAR(getlistbycert_doc, -+"getnamebycert(certificate or list/tuple of certificates) -> dict(certificate => dict(results))\n\ -+\n\ -+Returns a dictionary with a dictonary of results for each given certificates.\n\ -+The result dictonary contain the name and the type of the object which can be\n\ -+accessed with the key constants NAME_KEY and TYPE_KEY, respectively.\n\ -+\n\ -+NOTE: getlistbycert currently works only with id_provider set as \"ad\" or \"ipa\"" -+); -+ -+static PyObject * py_getlistbycert(PyObject *module, PyObject *args) -+{ -+ return check_args(LISTBYCERT, args); -+} -+ - static PyMethodDef methods[] = { - { sss_py_const_p(char, "getsidbyname"), (PyCFunction) py_getsidbyname, - METH_VARARGS, getsidbyname_doc }, -@@ -393,6 +490,8 @@ static PyMethodDef methods[] = { - METH_VARARGS, getidbysid_doc }, - { sss_py_const_p(char, "getnamebycert"), (PyCFunction) py_getnamebycert, - METH_VARARGS, getnamebycert_doc }, -+ { sss_py_const_p(char, "getlistbycert"), (PyCFunction) py_getlistbycert, -+ METH_VARARGS, getlistbycert_doc }, - { NULL,NULL, 0, NULL } - }; - -diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c -index 08b3d32f2662efc1cc803f6e9e5f2d064f7d3033..1931bf62a686c7f30852dac547866609cf54a81b 100644 ---- a/src/responder/nss/nss_cmd.c -+++ b/src/responder/nss/nss_cmd.c -@@ -932,6 +932,12 @@ static errno_t nss_cmd_getnamebycert(struct cli_ctx *cli_ctx) - nss_protocol_fill_single_name); - } - -+static errno_t nss_cmd_getlistbycert(struct cli_ctx *cli_ctx) -+{ -+ return nss_getby_cert(cli_ctx, CACHE_REQ_USER_BY_CERT, -+ nss_protocol_fill_name_list); -+} -+ - struct sss_cmd_table *get_nss_cmds(void) - { - static struct sss_cmd_table nss_cmds[] = { -@@ -961,6 +967,7 @@ struct sss_cmd_table *get_nss_cmds(void) - { SSS_NSS_GETIDBYSID, nss_cmd_getidbysid }, - { SSS_NSS_GETORIGBYNAME, nss_cmd_getorigbyname }, - { SSS_NSS_GETNAMEBYCERT, nss_cmd_getnamebycert }, -+ { SSS_NSS_GETLISTBYCERT, nss_cmd_getlistbycert }, - { SSS_CLI_NULL, NULL } - }; - -diff --git a/src/responder/nss/nss_protocol.h b/src/responder/nss/nss_protocol.h -index c94e7b911eb3c0f97b8c06b1766573311cde41ae..e4c0e52c0e642e885ef2c8423ea564beff7242cf 100644 ---- a/src/responder/nss/nss_protocol.h -+++ b/src/responder/nss/nss_protocol.h -@@ -175,6 +175,12 @@ nss_protocol_fill_single_name(struct nss_ctx *nss_ctx, - struct cache_req_result *result); - - errno_t -+nss_protocol_fill_name_list(struct nss_ctx *nss_ctx, -+ struct nss_cmd_ctx *cmd_ctx, -+ struct sss_packet *packet, -+ struct cache_req_result *result); -+ -+errno_t - nss_protocol_fill_id(struct nss_ctx *nss_ctx, - struct nss_cmd_ctx *cmd_ctx, - struct sss_packet *packet, -diff --git a/src/responder/nss/nss_protocol_sid.c b/src/responder/nss/nss_protocol_sid.c -index 0b97e65f75412d40832d861568d8e2f9de5e1732..a6a4e27d039c67ef98f6d5900d5e3fcadb3ee717 100644 ---- a/src/responder/nss/nss_protocol_sid.c -+++ b/src/responder/nss/nss_protocol_sid.c -@@ -498,3 +498,66 @@ nss_protocol_fill_id(struct nss_ctx *nss_ctx, - - return EOK; - } -+ -+errno_t -+nss_protocol_fill_name_list(struct nss_ctx *nss_ctx, -+ struct nss_cmd_ctx *cmd_ctx, -+ struct sss_packet *packet, -+ struct cache_req_result *result) -+{ -+ enum sss_id_type *id_types; -+ size_t rp = 0; -+ size_t body_len; -+ uint8_t *body; -+ errno_t ret; -+ struct sized_string *sz_names; -+ size_t len; -+ size_t c; -+ const char *tmp_str; -+ -+ sz_names = talloc_array(cmd_ctx, struct sized_string, result->count); -+ if (sz_names == NULL) { -+ return ENOMEM; -+ } -+ -+ id_types = talloc_array(cmd_ctx, enum sss_id_type, result->count); -+ if (id_types == NULL) { -+ return ENOMEM; -+ } -+ -+ len = 0; -+ for (c = 0; c < result->count; c++) { -+ ret = nss_get_id_type(cmd_ctx, result, &(id_types[c])); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ tmp_str = nss_get_name_from_msg(result->domain, result->msgs[c]); -+ if (tmp_str == NULL) { -+ return EINVAL; -+ } -+ to_sized_string(&(sz_names[c]), tmp_str); -+ -+ len += sz_names[c].len; -+ } -+ -+ len += (2 + result->count) * sizeof(uint32_t); -+ -+ ret = sss_packet_grow(packet, len); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n"); -+ return ret; -+ } -+ -+ sss_packet_get_body(packet, &body, &body_len); -+ -+ SAFEALIGN_SET_UINT32(&body[rp], result->count, &rp); /* Num results. */ -+ SAFEALIGN_SET_UINT32(&body[rp], 0, &rp); /* Reserved. */ -+ for (c = 0; c < result->count; c++) { -+ SAFEALIGN_SET_UINT32(&body[rp], id_types[c], &rp); -+ SAFEALIGN_SET_STRING(&body[rp], sz_names[c].str, sz_names[c].len, -+ &rp); -+ } -+ -+ return EOK; -+} -diff --git a/src/sss_client/idmap/sss_nss_idmap.c b/src/sss_client/idmap/sss_nss_idmap.c -index fa5a499e3606f7e45a406de4d63002ba35365cb1..6f3af267a1e763e7dce77e3862be377ae2bfe984 100644 ---- a/src/sss_client/idmap/sss_nss_idmap.c -+++ b/src/sss_client/idmap/sss_nss_idmap.c -@@ -31,6 +31,7 @@ - #include "util/strtonum.h" - - #define DATA_START (3 * sizeof(uint32_t)) -+#define LIST_START (2 * sizeof(uint32_t)) - union input { - const char *str; - uint32_t id; -@@ -38,10 +39,12 @@ union input { - - struct output { - enum sss_id_type type; -+ enum sss_id_type *types; - union { - char *str; - uint32_t id; - struct sss_nss_kv *kv_list; -+ char **names; - } d; - }; - -@@ -72,6 +75,63 @@ void sss_nss_free_kv(struct sss_nss_kv *kv_list) - } - } - -+void sss_nss_free_list(char **l) -+{ -+ size_t c; -+ -+ if (l != NULL) { -+ for (c = 0; l[c] != NULL; c++) { -+ free(l[c]); -+ } -+ free(l); -+ } -+} -+ -+static int buf_to_name_type_list(uint8_t *buf, size_t buf_len, uint32_t num, -+ char ***names, enum sss_id_type **types) -+{ -+ int ret; -+ size_t c; -+ char **n = NULL; -+ enum sss_id_type *t = NULL; -+ size_t rp = 0; -+ -+ n = calloc(num + 1, sizeof(char *)); -+ if (n == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ t = calloc(num + 1, sizeof(enum sss_id_type)); -+ if (t == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (c = 0; c < num; c++) { -+ SAFEALIGN_COPY_UINT32(&(t[c]), buf + rp, &rp); -+ n[c] = strdup((char *) buf + rp); -+ if (n[c] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ rp += strlen(n[c]) + 1; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ sss_nss_free_list(n); -+ free(t); -+ } else { -+ *names = n; -+ *types = t; -+ } -+ -+ return ret; -+} -+ - static int buf_to_kv_list(uint8_t *buf, size_t buf_len, - struct sss_nss_kv **kv_list) - { -@@ -153,13 +213,14 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd , - size_t data_len; - uint32_t c; - struct sss_nss_kv *kv_list; -+ char **names; -+ enum sss_id_type *types; - - switch (cmd) { - case SSS_NSS_GETSIDBYNAME: - case SSS_NSS_GETNAMEBYSID: - case SSS_NSS_GETIDBYSID: - case SSS_NSS_GETORIGBYNAME: -- case SSS_NSS_GETNAMEBYCERT: - ret = sss_strnlen(inp.str, 2048, &inp_len); - if (ret != EOK) { - return EINVAL; -@@ -169,6 +230,17 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd , - rd.data = inp.str; - - break; -+ case SSS_NSS_GETNAMEBYCERT: -+ case SSS_NSS_GETLISTBYCERT: -+ ret = sss_strnlen(inp.str, 10 * 1024 , &inp_len); -+ if (ret != EOK) { -+ return EINVAL; -+ } -+ -+ rd.len = inp_len + 1; -+ rd.data = inp.str; -+ -+ break; - case SSS_NSS_GETSIDBYID: - rd.len = sizeof(uint32_t); - rd.data = &inp.id; -@@ -195,7 +267,7 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd , - if (num_results == 0) { - ret = ENOENT; - goto done; -- } else if (num_results > 1) { -+ } else if (num_results > 1 && cmd != SSS_NSS_GETLISTBYCERT) { - ret = EBADMSG; - goto done; - } -@@ -237,6 +309,18 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd , - out->d.id = c; - - break; -+ case SSS_NSS_GETLISTBYCERT: -+ ret = buf_to_name_type_list(repbuf + LIST_START, replen - LIST_START, -+ num_results, -+ &names, &types); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ out->types = types; -+ out->d.names = names; -+ -+ break; - case SSS_NSS_GETORIGBYNAME: - ret = buf_to_kv_list(repbuf + DATA_START, data_len, &kv_list); - if (ret != EOK) { -@@ -392,3 +476,25 @@ int sss_nss_getnamebycert(const char *cert, char **fq_name, - - return ret; - } -+ -+int sss_nss_getlistbycert(const char *cert, char ***fq_name, -+ enum sss_id_type **type) -+{ -+ int ret; -+ union input inp; -+ struct output out; -+ -+ if (fq_name == NULL || cert == NULL || *cert == '\0') { -+ return EINVAL; -+ } -+ -+ inp.str = cert; -+ -+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETLISTBYCERT, &out); -+ if (ret == EOK) { -+ *fq_name = out.d.names; -+ *type = out.types; -+ } -+ -+ return ret; -+} -diff --git a/src/sss_client/idmap/sss_nss_idmap.exports b/src/sss_client/idmap/sss_nss_idmap.exports -index bd5d80212017d38334c3cdeefa47d6029f42aebb..49dac6fc9351b0ca98cd46e83b85ec8ef0075a0d 100644 ---- a/src/sss_client/idmap/sss_nss_idmap.exports -+++ b/src/sss_client/idmap/sss_nss_idmap.exports -@@ -25,3 +25,9 @@ SSS_NSS_IDMAP_0.2.0 { - global: - sss_nss_getnamebycert; - } SSS_NSS_IDMAP_0.1.0; -+ -+SSS_NSS_IDMAP_0.3.0 { -+ # public functions -+ global: -+ sss_nss_getlistbycert; -+} SSS_NSS_IDMAP_0.2.0; -diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h -index 8a6299194e7b91e084b26c0c96e2f93875a832e7..cbf19479ff9ec6e0d6e07e1f7e48a1571e147740 100644 ---- a/src/sss_client/idmap/sss_nss_idmap.h -+++ b/src/sss_client/idmap/sss_nss_idmap.h -@@ -130,7 +130,7 @@ int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list, - * @param[in] cert base64 encoded certificate - * @param[out] fq_name Fully qualified name of a user or a group, - * must be freed by the caller -- * @param[out] type Type of the object related to the SID -+ * @param[out] type Type of the object related to the cert - * - * @return - * - see #sss_nss_getsidbyname -@@ -139,6 +139,21 @@ int sss_nss_getnamebycert(const char *cert, char **fq_name, - enum sss_id_type *type); - - /** -+ * @brief Return a list of fully qualified names for the given base64 encoded -+ * X.509 certificate in DER format -+ * -+ * @param[in] cert base64 encoded certificate -+ * @param[out] fq_name List of fully qualified name of users or groups, -+ * must be freed by the caller -+ * @param[out] type List of types of the objects related to the cert -+ * -+ * @return -+ * - see #sss_nss_getsidbyname -+ */ -+int sss_nss_getlistbycert(const char *cert, char ***fq_name, -+ enum sss_id_type **type); -+ -+/** - * @brief Free key-value list returned by sss_nss_getorigbyname() - * - * @param[in] kv_list Key-value list returned by sss_nss_getorigbyname(). -diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h -index 8091e11515184dc9b7f32eed535055d9eee3143f..59fee7a4eceb2c185e156e812af7f2f4c6b2a0dd 100644 ---- a/src/sss_client/sss_cli.h -+++ b/src/sss_client/sss_cli.h -@@ -260,6 +260,11 @@ SSS_NSS_GETNAMEBYCERT = 0x0116, /**< Takes the zero terminated string - of a X509 certificate and returns the zero - terminated fully qualified name of the - related object. */ -+SSS_NSS_GETLISTBYCERT = 0x0117, /**< Takes the zero terminated string -+ of the base64 encoded DER representation -+ of a X509 certificate and returns a list -+ of zero terminated fully qualified names -+ of the related objects. */ - }; - - /** -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index 76b9c6fb05673130de0957e93291919c263a28f3..50714715cc80338640f2a77ecbe17bd5e0d6e911 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -3454,6 +3454,16 @@ struct passwd testbycert = { - .pw_passwd = discard_const("*"), - }; - -+struct passwd testbycert2 = { -+ .pw_name = discard_const("testcertuser2"), -+ .pw_uid = 23457, -+ .pw_gid = 6890, -+ .pw_dir = discard_const("/home/testcertuser2"), -+ .pw_gecos = discard_const("test cert user2"), -+ .pw_shell = discard_const("/bin/sh"), -+ .pw_passwd = discard_const("*"), -+}; -+ - #define TEST_TOKEN_CERT \ - "MIIECTCCAvGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \ - "REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA2MjMx" \ -@@ -3495,6 +3505,57 @@ static int test_nss_getnamebycert_check(uint32_t status, uint8_t *body, size_t b - return EOK; - } - -+static int test_nss_getlistbycert_check(uint32_t status, uint8_t *body, size_t blen) -+{ -+ size_t rp = 0; -+ uint32_t id_type; -+ uint32_t num; -+ uint32_t reserved; -+ const char *name; -+ int found = 0; -+ const char *fq_name1 = "testcertuser@"TEST_DOM_NAME ; -+ const char *fq_name2 = "testcertuser2@"TEST_DOM_NAME; -+ -+ assert_int_equal(status, EOK); -+ -+ /* num_results and reserved */ -+ SAFEALIGN_COPY_UINT32(&num, body + rp, &rp); -+ assert_in_range(num, 1, 2); -+ SAFEALIGN_COPY_UINT32(&reserved, body + rp, &rp); -+ assert_int_equal(reserved, 0); -+ -+ SAFEALIGN_COPY_UINT32(&id_type, body + rp, &rp); -+ assert_int_equal(id_type, SSS_ID_TYPE_UID); -+ -+ name = (const char *)body + rp; -+ if (num == 1) { -+ assert_string_equal(name, fq_name1); -+ return EOK; -+ } -+ -+ rp += strlen(name) + 1; -+ if (strcmp(name, fq_name1) == 0) { -+ found = 1; -+ } else if (strcmp(name, fq_name2) == 0) { -+ found = 2; -+ } -+ assert_in_range(found, 1, 2); -+ -+ SAFEALIGN_COPY_UINT32(&id_type, body + rp, &rp); -+ assert_int_equal(id_type, SSS_ID_TYPE_UID); -+ -+ name = (const char *)body + rp; -+ if (found == 1) { -+ assert_string_equal(name, fq_name2); -+ } else { -+ assert_string_equal(name, fq_name1); -+ } -+ -+ -+ return EOK; -+} -+ -+ - static void test_nss_getnamebycert(void **state) - { - errno_t ret; -@@ -3572,6 +3633,99 @@ void test_nss_getnamebycert_neg(void **state) - assert_int_equal(nss_test_ctx->ncache_hits, 1); - } - -+static void test_nss_getlistbycert(void **state) -+{ -+ errno_t ret; -+ struct sysdb_attrs *attrs; -+ unsigned char *der = NULL; -+ size_t der_size; -+ -+ attrs = sysdb_new_attrs(nss_test_ctx); -+ assert_non_null(attrs); -+ -+ der = sss_base64_decode(nss_test_ctx, TEST_TOKEN_CERT, &der_size); -+ assert_non_null(der); -+ -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ talloc_free(der); -+ assert_int_equal(ret, EOK); -+ -+ /* Prime the cache with a valid user */ -+ ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom, -+ &testbycert, attrs, 0); -+ assert_int_equal(ret, EOK); -+ talloc_free(attrs); -+ -+ mock_input_cert(TEST_TOKEN_CERT); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETLISTBYCERT); -+ mock_fill_bysid(); -+ -+ /* Query for that user, call a callback when command finishes */ -+ /* Should go straight to back end, without contacting DP. */ -+ /* If there is only a single user mapped the result will look like the */ -+ /* result of getnamebycert. */ -+ set_cmd_cb(test_nss_getlistbycert_check); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETLISTBYCERT, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+static void test_nss_getlistbycert_multi(void **state) -+{ -+ errno_t ret; -+ struct sysdb_attrs *attrs; -+ unsigned char *der = NULL; -+ size_t der_size; -+ -+ der = sss_base64_decode(nss_test_ctx, TEST_TOKEN_CERT, &der_size); -+ assert_non_null(der); -+ -+ attrs = sysdb_new_attrs(nss_test_ctx); -+ assert_non_null(attrs); -+ -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ assert_int_equal(ret, EOK); -+ -+ /* Prime the cache with two valid user */ -+ ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom, -+ &testbycert, attrs, 0); -+ assert_int_equal(ret, EOK); -+ talloc_free(attrs); -+ -+ /* Looks like attrs is modified during store_user() makes sure we start -+ * with fresh data. */ -+ attrs = sysdb_new_attrs(nss_test_ctx); -+ assert_non_null(attrs); -+ -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ talloc_free(der); -+ assert_int_equal(ret, EOK); -+ -+ ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom, -+ &testbycert2, attrs, 0); -+ assert_int_equal(ret, EOK); -+ talloc_free(attrs); -+ -+ mock_input_cert(TEST_TOKEN_CERT); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETLISTBYCERT); -+ mock_fill_bysid(); -+ -+ /* Query for that user, call a callback when command finishes */ -+ /* Should go straight to back end, without contacting DP */ -+ set_cmd_cb(test_nss_getlistbycert_check); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETLISTBYCERT, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ - struct passwd sid_user = { - .pw_name = discard_const("testusersid"), - .pw_uid = 1234, -@@ -3818,6 +3972,10 @@ int main(int argc, const char *argv[]) - nss_test_setup, nss_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getnamebycert, - nss_test_setup, nss_test_teardown), -+ cmocka_unit_test_setup_teardown(test_nss_getlistbycert, -+ nss_test_setup, nss_test_teardown), -+ cmocka_unit_test_setup_teardown(test_nss_getlistbycert_multi, -+ nss_test_setup, nss_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getsidbyname, - nss_test_setup, nss_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getsidbyupn, --- -2.12.2 - diff --git a/0015-nss-allow-larger-buffer-for-certificate-based-reques.patch b/0015-nss-allow-larger-buffer-for-certificate-based-reques.patch deleted file mode 100644 index 153e50d..0000000 --- a/0015-nss-allow-larger-buffer-for-certificate-based-reques.patch +++ /dev/null @@ -1,70 +0,0 @@ -From a0b1bfa76073d3ce3208e67e6d72bb92088edac5 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 28 Feb 2017 14:19:53 +0100 -Subject: [PATCH 15/97] nss: allow larger buffer for certificate based requests - -To make sure larger certificates can be processed as well the maximal -buffer size is increased for requests by certificate. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek ---- - src/responder/common/responder_packet.c | 21 ++++++++++++++++++++- - src/responder/common/responder_packet.h | 1 + - 2 files changed, 21 insertions(+), 1 deletion(-) - -diff --git a/src/responder/common/responder_packet.c b/src/responder/common/responder_packet.c -index 4f5e110837eb76609d31a77c62a00e00530ffc90..cc4d66995965cca4c86a80c31d2afd4c9ac3e0e4 100644 ---- a/src/responder/common/responder_packet.c -+++ b/src/responder/common/responder_packet.c -@@ -179,6 +179,8 @@ int sss_packet_recv(struct sss_packet *packet, int fd) - size_t rb; - size_t len; - void *buf; -+ size_t new_len; -+ int ret; - - buf = (uint8_t *)packet->buffer + packet->iop; - if (packet->iop > 4) len = sss_packet_get_len(packet) - packet->iop; -@@ -205,7 +207,24 @@ int sss_packet_recv(struct sss_packet *packet, int fd) - } - - if (sss_packet_get_len(packet) > packet->memsize) { -- return EINVAL; -+ /* Allow certificate based requests to use larger buffer but not -+ * larger than SSS_CERT_PACKET_MAX_RECV_SIZE. Due to the way -+ * sss_packet_grow() works the packet len must be set to '0' first and -+ * then grow to the expected size. */ -+ if ((sss_packet_get_cmd(packet) == SSS_NSS_GETNAMEBYCERT -+ || sss_packet_get_cmd(packet) == SSS_NSS_GETLISTBYCERT) -+ && packet->memsize < SSS_CERT_PACKET_MAX_RECV_SIZE -+ && (new_len = sss_packet_get_len(packet)) -+ < SSS_CERT_PACKET_MAX_RECV_SIZE) { -+ new_len = sss_packet_get_len(packet); -+ sss_packet_set_len(packet, 0); -+ ret = sss_packet_grow(packet, new_len); -+ if (ret != EOK) { -+ return ret; -+ } -+ } else { -+ return EINVAL; -+ } - } - - packet->iop += rb; -diff --git a/src/responder/common/responder_packet.h b/src/responder/common/responder_packet.h -index 3ad0eee28477e446c9e4996617beb55f32923d47..afceb4aaefa40fd86bdfde820c92c09b65cd8702 100644 ---- a/src/responder/common/responder_packet.h -+++ b/src/responder/common/responder_packet.h -@@ -25,6 +25,7 @@ - #include "sss_client/sss_cli.h" - - #define SSS_PACKET_MAX_RECV_SIZE 1024 -+#define SSS_CERT_PACKET_MAX_RECV_SIZE ( 10 * SSS_PACKET_MAX_RECV_SIZE ) - - struct sss_packet; - --- -2.12.2 - diff --git a/0016-IPA-Add-s2n-request-to-string-function.patch b/0016-IPA-Add-s2n-request-to-string-function.patch deleted file mode 100644 index 2bdfc0e..0000000 --- a/0016-IPA-Add-s2n-request-to-string-function.patch +++ /dev/null @@ -1,44 +0,0 @@ -From a04bef313508c423ed06cc54805a3b8106ab90cd Mon Sep 17 00:00:00 2001 -From: Justin Stephenson -Date: Mon, 20 Mar 2017 11:51:05 -0400 -Subject: [PATCH 16/97] IPA: Add s2n request to string function - -Add a function to convert request_types to string allowing the -ability to print request type information for ipa_s2n functions during -IPA client operations. - -Reviewed-by: Sumit Bose ---- - src/providers/ipa/ipa_s2n_exop.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 07bbb2b4d252c8ca9ada4d890c36c903c9f75773..4fe20689fe4c0f2bb5217691dd05b37d2a1cc820 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -979,6 +979,22 @@ done: - return ret; - } - -+static const char *ipa_s2n_reqtype2str(enum request_types request_type) -+{ -+ switch (request_type) { -+ case REQ_SIMPLE: -+ return "REQ_SIMPLE"; -+ case REQ_FULL: -+ return "REQ_FULL"; -+ case REQ_FULL_WITH_MEMBERS: -+ return "REQ_FULL_WITH_MEMBERS"; -+ default: -+ break; -+ } -+ -+ return "Unknown request type"; -+} -+ - struct ipa_s2n_get_list_state { - struct tevent_context *ev; - struct ipa_id_ctx *ipa_ctx; --- -2.12.2 - diff --git a/0017-IPA-Enhance-debug-logging-for-ipa-s2n-operations.patch b/0017-IPA-Enhance-debug-logging-for-ipa-s2n-operations.patch deleted file mode 100644 index c890706..0000000 --- a/0017-IPA-Enhance-debug-logging-for-ipa-s2n-operations.patch +++ /dev/null @@ -1,82 +0,0 @@ -From cd83aead3c9799ac05d8f8977dbb92bbd399c6d5 Mon Sep 17 00:00:00 2001 -From: Justin Stephenson -Date: Thu, 16 Mar 2017 14:46:55 -0400 -Subject: [PATCH 17/97] IPA: Enhance debug logging for ipa s2n operations - -Add log messages to provide useful debug logging surrounding -IPA client extended operations to the IPA Server during AD trust -requests to retrieve information. Print more details about the -objects requested and received during the ipa_s2n operations. - -This will improve log analysis and troubleshooting efforts during AD -trust user and group resolution failures on IPA clients, such as missing -groups. - -Reviewed-by: Sumit Bose ---- - src/providers/ipa/ipa_s2n_exop.c | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 4fe20689fe4c0f2bb5217691dd05b37d2a1cc820..c99312274073858e5e03f3e82c069dafc839eb61 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -1156,6 +1156,13 @@ static errno_t ipa_s2n_get_list_step(struct tevent_req *req) - need_v1 = true; - } - -+ if (state->req_input.type == REQ_INP_NAME -+ && state->req_input.inp.name != NULL) { -+ DEBUG(SSSDBG_TRACE_FUNC, "Sending request_type: [%s] for group [%s].\n", -+ ipa_s2n_reqtype2str(state->request_type), -+ state->list[state->list_idx]); -+ } -+ - subreq = ipa_s2n_exop_send(state, state->ev, state->sh, need_v1, - state->exop_timeout, bv_req); - if (subreq == NULL) { -@@ -1194,6 +1201,9 @@ static void ipa_s2n_get_list_next(struct tevent_req *subreq) - goto fail; - } - -+ DEBUG(SSSDBG_TRACE_FUNC, "Received [%s] attributes from IPA server.\n", -+ state->attrs->a.name); -+ - if (is_default_view(state->ipa_ctx->view_name)) { - ret = ipa_s2n_get_list_save_step(req); - if (ret == EOK) { -@@ -1375,6 +1385,11 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx, - goto fail; - } - -+ DEBUG(SSSDBG_TRACE_FUNC, "Sending request_type: [%s] for trust user [%s] " -+ "to IPA server\n", -+ ipa_s2n_reqtype2str(state->request_type), -+ req_input->inp.name); -+ - subreq = ipa_s2n_exop_send(state, state->ev, state->sh, is_v1, - state->exop_timeout, bv_req); - if (subreq == NULL) { -@@ -1661,6 +1676,19 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - state->attrs = attrs; - - if (attrs->response_type == RESP_USER_GROUPLIST) { -+ -+ if (DEBUG_IS_SET(SSSDBG_TRACE_FUNC)) { -+ size_t c; -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Received [%zu] groups in group list " -+ "from IPA Server\n", attrs->ngroups); -+ -+ for (c = 0; c < attrs->ngroups; c++) { -+ DEBUG(SSSDBG_TRACE_FUNC, "[%s].\n", attrs->groups[c]); -+ } -+ } -+ -+ - ret = get_group_dn_list(state, state->dom, - attrs->ngroups, attrs->groups, - &group_dn_list, &missing_list); --- -2.12.2 - diff --git a/0018-UTIL-iobuf-Make-input-parameter-for-the-readonly-ope.patch b/0018-UTIL-iobuf-Make-input-parameter-for-the-readonly-ope.patch deleted file mode 100644 index 7977ff4..0000000 --- a/0018-UTIL-iobuf-Make-input-parameter-for-the-readonly-ope.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 3a4a88259ba90d3dc45c1adbbfd39bd7c0204a12 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 15 Mar 2017 13:32:42 +0100 -Subject: [PATCH 18/97] UTIL: iobuf: Make input parameter for the readonly - operation const -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/util/sss_iobuf.c | 2 +- - src/util/sss_iobuf.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/util/sss_iobuf.c b/src/util/sss_iobuf.c -index 7c72ea94d7a005dfd9671793b3ad470a6de7967a..900418b750a3455ebc2c3bb1893db726692260b8 100644 ---- a/src/util/sss_iobuf.c -+++ b/src/util/sss_iobuf.c -@@ -49,7 +49,7 @@ struct sss_iobuf *sss_iobuf_init_empty(TALLOC_CTX *mem_ctx, - } - - struct sss_iobuf *sss_iobuf_init_readonly(TALLOC_CTX *mem_ctx, -- uint8_t *data, -+ const uint8_t *data, - size_t size) - { - struct sss_iobuf *iobuf; -diff --git a/src/util/sss_iobuf.h b/src/util/sss_iobuf.h -index eae357a40f2948e63df189f2842edee68691a542..900faaa212230f72f52e344c085167e80ae2b465 100644 ---- a/src/util/sss_iobuf.h -+++ b/src/util/sss_iobuf.h -@@ -47,7 +47,7 @@ struct sss_iobuf *sss_iobuf_init_empty(TALLOC_CTX *mem_ctx, - * @return The newly created buffer on success or NULL on an error. - */ - struct sss_iobuf *sss_iobuf_init_readonly(TALLOC_CTX *mem_ctx, -- uint8_t *data, -+ const uint8_t *data, - size_t size); - - /* --- -2.12.2 - diff --git a/0019-UTIL-Fix-a-typo-in-the-tcurl-test-tool.patch b/0019-UTIL-Fix-a-typo-in-the-tcurl-test-tool.patch deleted file mode 100644 index 0624d7a..0000000 --- a/0019-UTIL-Fix-a-typo-in-the-tcurl-test-tool.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 24889dc5e7eb7bc992ab0fa05edfdfa1d157131a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 15 Mar 2017 13:42:03 +0100 -Subject: [PATCH 19/97] UTIL: Fix a typo in the tcurl test tool -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/tests/tcurl_test_tool.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 35ea979780df47c92ed92bc5bba713faa8909b90..38cea432885c97ca3827c8f158bf7e3ebfc67b31 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -204,8 +204,8 @@ int main(int argc, const char *argv[]) - urls[i], - headers, - inbufs[i], -- 10); -- if (ctx == NULL) { -+ 5); -+ if (req == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, "Could not create request\n"); - talloc_zfree(tool_ctx); - return 1; --- -2.12.2 - diff --git a/0020-UTIL-Add-SAFEALIGN_COPY_UINT8_CHECK.patch b/0020-UTIL-Add-SAFEALIGN_COPY_UINT8_CHECK.patch deleted file mode 100644 index eea6ae8..0000000 --- a/0020-UTIL-Add-SAFEALIGN_COPY_UINT8_CHECK.patch +++ /dev/null @@ -1,36 +0,0 @@ -From c194e8d7cad0184d710d9979e9f12d5cfe176f4a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 23 Feb 2017 20:55:05 +0100 -Subject: [PATCH 20/97] UTIL: Add SAFEALIGN_COPY_UINT8_CHECK -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This macro will be used later in the KCM code - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/util/util_safealign.h | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/util/util_safealign.h b/src/util/util_safealign.h -index 0d9a579cdbfafc30bf2d0a6ad2651c71428ebd93..57f04a17d4a38300b959c1593d756b351ebd89e8 100644 ---- a/src/util/util_safealign.h -+++ b/src/util/util_safealign.h -@@ -130,6 +130,12 @@ safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter) - safealign_memcpy(dest, src, srclen, pctr); \ - } while(0) - -+#define SAFEALIGN_COPY_UINT8_CHECK(dest, src, len, pctr) do { \ -+ if ((*(pctr) + sizeof(uint8_t)) > (len) || \ -+ SIZE_T_OVERFLOW(*(pctr), sizeof(uint8_t))) { return EINVAL; } \ -+ safealign_memcpy(dest, src, sizeof(uint8_t), pctr); \ -+} while(0) -+ - /* Aliases for backward compatibility. */ - #define SAFEALIGN_SET_VALUE SAFEALIGN_SETMEM_VALUE - #define SAFEALIGN_SET_INT64 SAFEALIGN_SETMEM_INT64 --- -2.12.2 - diff --git a/0021-UTIL-Add-utility-macro-cli_creds_get_gid.patch b/0021-UTIL-Add-utility-macro-cli_creds_get_gid.patch deleted file mode 100644 index a390f3f..0000000 --- a/0021-UTIL-Add-utility-macro-cli_creds_get_gid.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 4f511a4c5f0084e22ce4c7613f1b279533c68cc5 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 20 Sep 2016 22:00:27 +0200 -Subject: [PATCH 21/97] UTIL: Add utility macro cli_creds_get_gid() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The KCM responder checks the owneship of the ccache based on both UID -and GID of the peer. In order to reuse the already existing creds -structure, let's just add a new macro that returns the GID from the -creds structure. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/util/util_creds.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/util/util_creds.h b/src/util/util_creds.h -index 65468fa12b8c6921859574c40f5759c936a10e86..936b9965d1ccd2b437d93b38d789b6f8389f47a6 100644 ---- a/src/util/util_creds.h -+++ b/src/util/util_creds.h -@@ -71,6 +71,7 @@ struct cli_creds { - }; - - #define cli_creds_get_uid(x) x->ucred.uid -+#define cli_creds_get_gid(x) x->ucred.gid - - #else /* not HAVE_UCRED */ - struct cli_creds { --- -2.12.2 - diff --git a/0022-UTIL-Add-type-specific-getsetters-to-sss_iobuf.patch b/0022-UTIL-Add-type-specific-getsetters-to-sss_iobuf.patch deleted file mode 100644 index cb64a8d..0000000 --- a/0022-UTIL-Add-type-specific-getsetters-to-sss_iobuf.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 5f7f45a64bdb9353f15b945db4ad2564b4b28ab2 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 23 Feb 2017 21:57:13 +0100 -Subject: [PATCH 22/97] UTIL: Add type-specific getsetters to sss_iobuf -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The KCM responder receives its input as unstructured data. To make the -parsing easier, this commit adds several type-specific getsetters to the -iobuf module. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/util/sss_iobuf.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ - src/util/sss_iobuf.h | 33 ++++++++++++++++ - 2 files changed, 141 insertions(+) - -diff --git a/src/util/sss_iobuf.c b/src/util/sss_iobuf.c -index 900418b750a3455ebc2c3bb1893db726692260b8..fc288d2df2bfaaba393dd490d4da8976de804cb5 100644 ---- a/src/util/sss_iobuf.c -+++ b/src/util/sss_iobuf.c -@@ -184,6 +184,25 @@ errno_t sss_iobuf_read(struct sss_iobuf *iobuf, - return EOK; - } - -+errno_t sss_iobuf_read_len(struct sss_iobuf *iobuf, -+ size_t len, -+ uint8_t *_buf) -+{ -+ size_t read; -+ errno_t ret; -+ -+ ret = sss_iobuf_read(iobuf, len, _buf, &read); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ if (read != len) { -+ return ENOBUFS; -+ } -+ -+ return EOK; -+} -+ - errno_t sss_iobuf_write_len(struct sss_iobuf *iobuf, - uint8_t *buf, - size_t len) -@@ -203,3 +222,92 @@ errno_t sss_iobuf_write_len(struct sss_iobuf *iobuf, - - return EOK; - } -+ -+errno_t sss_iobuf_read_uint32(struct sss_iobuf *iobuf, -+ uint32_t *_val) -+{ -+ SAFEALIGN_COPY_UINT32_CHECK(_val, iobuf_ptr(iobuf), -+ iobuf->capacity, &iobuf->dp); -+ return EOK; -+} -+ -+errno_t sss_iobuf_read_int32(struct sss_iobuf *iobuf, -+ int32_t *_val) -+{ -+ SAFEALIGN_COPY_INT32_CHECK(_val, iobuf_ptr(iobuf), -+ iobuf->capacity, &iobuf->dp); -+ return EOK; -+} -+ -+errno_t sss_iobuf_write_uint32(struct sss_iobuf *iobuf, -+ uint32_t val) -+{ -+ errno_t ret; -+ -+ ret = ensure_bytes(iobuf, sizeof(uint32_t)); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ SAFEALIGN_SETMEM_UINT32(iobuf_ptr(iobuf), val, &iobuf->dp); -+ return EOK; -+} -+ -+errno_t sss_iobuf_write_int32(struct sss_iobuf *iobuf, -+ int32_t val) -+{ -+ errno_t ret; -+ -+ ret = ensure_bytes(iobuf, sizeof(int32_t)); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ SAFEALIGN_SETMEM_INT32(iobuf_ptr(iobuf), val, &iobuf->dp); -+ return EOK; -+} -+ -+errno_t sss_iobuf_read_stringz(struct sss_iobuf *iobuf, -+ const char **_out) -+{ -+ uint8_t *end; -+ size_t len; -+ -+ if (iobuf == NULL) { -+ return EINVAL; -+ } -+ -+ if (_out == NULL) { -+ return EINVAL; -+ } -+ -+ *_out = NULL; -+ -+ end = memchr(iobuf_ptr(iobuf), '\0', sss_iobuf_get_size(iobuf)); -+ if (end == NULL) { -+ return EINVAL; -+ } -+ -+ len = end + 1 - iobuf_ptr(iobuf); -+ if (sss_iobuf_get_size(iobuf) < len) { -+ return EINVAL; -+ } -+ -+ *_out = (const char *) iobuf_ptr(iobuf); -+ iobuf->dp += len; -+ return EOK; -+} -+ -+errno_t sss_iobuf_write_stringz(struct sss_iobuf *iobuf, -+ const char *str) -+{ -+ if (iobuf == NULL || str == NULL) { -+ return EINVAL; -+ } -+ -+ SAFEALIGN_MEMCPY_CHECK(iobuf_ptr(iobuf), -+ str, strlen(str)+1, -+ sss_iobuf_get_size(iobuf), -+ &iobuf->dp); -+ return EOK; -+} -diff --git a/src/util/sss_iobuf.h b/src/util/sss_iobuf.h -index 900faaa212230f72f52e344c085167e80ae2b465..cc3dfd1e98eeb49b979ac321bd0253bffa8a6dff 100644 ---- a/src/util/sss_iobuf.h -+++ b/src/util/sss_iobuf.h -@@ -96,6 +96,22 @@ errno_t sss_iobuf_read(struct sss_iobuf *iobuf, - size_t *_read); - - /* -+ * @brief Read an exact number of bytes from an IO buffer -+ * -+ * Read exactly len bytes from an IO buffer. If the buffer contains fewer -+ * bytes than len, ENOBUFS is returned. -+ * -+ * @param[in] iobuf The IO buffer to read from -+ * @param[in] len The maximum number of bytes to read -+ * @param[out] _buf The buffer to read data into from iobuf -+ * -+ * @return EOK on success, errno otherwise -+ */ -+errno_t sss_iobuf_read_len(struct sss_iobuf *iobuf, -+ size_t len, -+ uint8_t *_buf); -+ -+/* - * @brief Write into an IO buffer - * - * Attempts to write len bytes into the iobuf. If the capacity is exceeded, -@@ -115,4 +131,21 @@ errno_t sss_iobuf_write_len(struct sss_iobuf *iobuf, - uint8_t *buf, - size_t len); - -+errno_t sss_iobuf_read_uint32(struct sss_iobuf *iobuf, -+ uint32_t *_val); -+ -+errno_t sss_iobuf_write_uint32(struct sss_iobuf *iobuf, -+ uint32_t val); -+ -+errno_t sss_iobuf_read_int32(struct sss_iobuf *iobuf, -+ int32_t *_val); -+ -+errno_t sss_iobuf_write_int32(struct sss_iobuf *iobuf, -+ int32_t val); -+ -+errno_t sss_iobuf_read_stringz(struct sss_iobuf *iobuf, -+ const char **_out); -+ -+errno_t sss_iobuf_write_stringz(struct sss_iobuf *iobuf, -+ const char *str); - #endif /* __SSS_IOBUF_H_ */ --- -2.12.2 - diff --git a/0023-UTIL-krb5-principal-un-marshalling.patch b/0023-UTIL-krb5-principal-un-marshalling.patch deleted file mode 100644 index 0026e2b..0000000 --- a/0023-UTIL-krb5-principal-un-marshalling.patch +++ /dev/null @@ -1,262 +0,0 @@ -From 1dbf09404e20b6e30a24afe72b6d349734aee62f Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 20 Sep 2016 22:03:30 +0200 -Subject: [PATCH 23/97] UTIL: krb5 principal (un)marshalling -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The KCM responder needs to read the contents of the principal blob that -the Kerberos library sends. Since libkrb5 doesn't export any API to do -so, we need to implement marshalling and unmarshalling of the principal -ourselves. - -In future, when the KCM server also supports renewals, we will also need -to unmarshall the credentials, but until that is not really needed, the -credentials will be stored as a blob. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/util/sss_krb5.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - src/util/sss_krb5.h | 9 +++ - 2 files changed, 204 insertions(+) - -diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c -index 4808a7703d07bb4eba91f14a7a515aadaec1774b..d461cf881566af37f31524c16f6a5f1511a5dc89 100644 ---- a/src/util/sss_krb5.c -+++ b/src/util/sss_krb5.c -@@ -24,6 +24,7 @@ - - #include "config.h" - -+#include "util/sss_iobuf.h" - #include "util/util.h" - #include "util/sss_krb5.h" - -@@ -1128,3 +1129,197 @@ done: - - return res; - } -+ -+static errno_t iobuf_read_uint32be(struct sss_iobuf *iobuf, -+ uint32_t *_val) -+{ -+ uint32_t beval; -+ errno_t ret; -+ -+ ret = sss_iobuf_read_uint32(iobuf, &beval); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ *_val = be32toh(beval); -+ return EOK; -+} -+ -+static errno_t iobuf_write_uint32be(struct sss_iobuf *iobuf, -+ uint32_t val) -+{ -+ uint32_t beval; -+ -+ beval = htobe32(val); -+ return sss_iobuf_write_uint32(iobuf, beval); -+} -+ -+static errno_t iobuf_get_len_bytes(TALLOC_CTX *mem_ctx, -+ struct sss_iobuf *iobuf, -+ uint32_t *_nbytes, -+ uint8_t **_bytes) -+{ -+ errno_t ret; -+ uint32_t nbytes; -+ uint8_t *bytes = NULL; -+ -+ ret = iobuf_read_uint32be(iobuf, &nbytes); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ bytes = talloc_zero_size(mem_ctx, nbytes); -+ if (bytes == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = sss_iobuf_read_len(iobuf, nbytes, bytes); -+ if (ret != EOK) { -+ talloc_free(bytes); -+ return ret; -+ } -+ -+ *_bytes = bytes; -+ *_nbytes = nbytes; -+ return EOK; -+} -+ -+static errno_t get_krb5_data(TALLOC_CTX *mem_ctx, -+ struct sss_iobuf *iobuf, -+ krb5_data *k5data) -+{ -+ errno_t ret; -+ uint32_t nbytes; -+ uint8_t *bytes = NULL; -+ -+ ret = iobuf_get_len_bytes(mem_ctx, iobuf, &nbytes, &bytes); -+ if (ret != EOK) { -+ talloc_free(bytes); -+ return ret; -+ } -+ -+ k5data->data = (char *) bytes; /* FIXME - the cast is ugly */ -+ k5data->length = nbytes; -+ return EOK; -+} -+ -+static errno_t set_krb5_data(struct sss_iobuf *iobuf, -+ krb5_data *k5data) -+{ -+ errno_t ret; -+ -+ ret = iobuf_write_uint32be(iobuf, k5data->length); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ if (k5data->length > 0) { -+ ret = sss_iobuf_write_len(iobuf, -+ (uint8_t *) k5data->data, -+ k5data->length); -+ if (ret != EOK) { -+ return ret; -+ } -+ } -+ -+ return EOK; -+} -+ -+/* FIXME - it would be nice if Kerberos exported these APIs.. */ -+krb5_error_code sss_krb5_unmarshal_princ(TALLOC_CTX *mem_ctx, -+ struct sss_iobuf *iobuf, -+ krb5_principal *_princ) -+{ -+ krb5_principal princ = NULL; -+ krb5_error_code ret; -+ uint32_t ncomps; -+ -+ if (iobuf == NULL || _princ == NULL) { -+ return EINVAL; -+ } -+ -+ princ = talloc_zero(mem_ctx, struct krb5_principal_data); -+ if (princ == NULL) { -+ return ENOMEM; -+ } -+ -+ princ->magic = KV5M_PRINCIPAL; -+ -+ ret = iobuf_read_uint32be(iobuf, (uint32_t *) &princ->type); -+ if (ret != EOK) { -+ goto fail; -+ } -+ -+ ret = iobuf_read_uint32be(iobuf, &ncomps); -+ if (ret != EOK) { -+ goto fail; -+ } -+ -+ if (ncomps > sss_iobuf_get_capacity(iobuf)) { -+ /* Sanity check to avoid large allocations */ -+ ret = EINVAL; -+ goto fail; -+ } -+ -+ if (ncomps != 0) { -+ princ->data = talloc_zero_array(princ, krb5_data, ncomps); -+ if (princ->data == NULL) { -+ ret = ENOMEM; -+ goto fail; -+ } -+ -+ princ->length = ncomps; -+ } -+ -+ ret = get_krb5_data(princ, iobuf, &princ->realm); -+ if (ret != EOK) { -+ goto fail; -+ } -+ -+ for (size_t i = 0; i < ncomps; i++) { -+ ret = get_krb5_data(princ->data, iobuf, &princ->data[i]); -+ if (ret != EOK) { -+ goto fail; -+ } -+ } -+ -+ *_princ = princ; -+ return 0; -+ -+fail: -+ talloc_free(princ); -+ return ret; -+} -+ -+krb5_error_code sss_krb5_marshal_princ(krb5_principal princ, -+ struct sss_iobuf *iobuf) -+{ -+ krb5_error_code ret; -+ -+ if (iobuf == NULL || princ == NULL) { -+ return EINVAL; -+ } -+ -+ ret = iobuf_write_uint32be(iobuf, princ->type); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = iobuf_write_uint32be(iobuf, princ->length); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = set_krb5_data(iobuf, &princ->realm); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ for (int i = 0; i < princ->length; i++) { -+ ret = set_krb5_data(iobuf, &princ->data[i]); -+ if (ret != EOK) { -+ return ret; -+ } -+ } -+ return EOK; -+} -diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h -index ac0f6082c75a8878f72346733e592b7575d44089..0d9043be98749b1a21a1b74c68f07298fa27f230 100644 ---- a/src/util/sss_krb5.h -+++ b/src/util/sss_krb5.h -@@ -32,6 +32,7 @@ - #include - #endif - -+#include "util/sss_iobuf.h" - #include "util/util.h" - - #define KRB5_CHILD_LOG_FILE "krb5_child" -@@ -186,4 +187,12 @@ krb5_error_code sss_krb5_kt_have_content(krb5_context context, - krb5_keytab keytab); - - bool sss_krb5_realm_has_proxy(const char *realm); -+ -+krb5_error_code sss_krb5_marshal_princ(krb5_principal princ, -+ struct sss_iobuf *iobuf); -+ -+krb5_error_code sss_krb5_unmarshal_princ(TALLOC_CTX *mem_ctx, -+ struct sss_iobuf *iobuf, -+ krb5_principal *_princ); -+ - #endif /* __SSS_KRB5_H__ */ --- -2.12.2 - diff --git a/0024-KCM-Initial-responder-build-and-packaging.patch b/0024-KCM-Initial-responder-build-and-packaging.patch deleted file mode 100644 index 8e9eea5..0000000 --- a/0024-KCM-Initial-responder-build-and-packaging.patch +++ /dev/null @@ -1,1013 +0,0 @@ -From b9c563c29243291f40489bb0dcbf3946fca72d58 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 1 Aug 2016 12:52:07 +0200 -Subject: [PATCH 24/97] KCM: Initial responder build and packaging -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Adds the initial build of the Kerberos Cache Manager responder (KCM). - -This is a deamon that is capable of holding and storing Kerberos -ccaches. When KCM is used, the kerberos libraries (invoked through e.g. -kinit) are referred to as a 'client' and the KCM deamon is referred to -as 'server'. - -At the moment, only the Heimdal implementation of Kerberos implements the -KCM server: - https://www.h5l.org/manual/HEAD/info/heimdal/Credential-cache-server-_002d-KCM.html -This patch adds a KCM server to SSSD. - -In MIT, only the 'client-side' support was added: - http://k5wiki.kerberos.org/wiki/Projects/KCM_client -This page also describes the protocol between the client and the server. - -The client is capable of talking to the server over either UNIX sockets -(Linux, most Unixes) or Mach RPC (macOS). Our server only implements the -UNIX sockets way and should be socket-activated by systemd, although can -in theory be also ran explicitly. - -The KCM server only builds if the configuration option "--with-kcm" is -enabled. It is packaged in a new subpackage sssd-kcm in order to allow -distributions to enable the KCM credential caches by installing this -subpackage only, without the rest of the SSSD. The sssd-kcm subpackage -also includes a krb5.conf.d snippet that allows the admin to just uncomment -the KCM defaults and instructs them to start the socket. - -The server can be configured in sssd.conf in the "[kcm]" section. -By default, the server only listens on the same socket path the Heimdal -server uses, which is "/var/run/.heim_org.h5l.kcm-socket". This is, -however, configurable. - -The file src/responder/kcm/kcm.h is more or less directly imported from -the MIT Kerberos tree, with an additional sentinel code and some -comments. Not all KCM operations are implemented, only those that also -the MIT client implements. That said, this KCM server should also be -usable with a Heimdal client, although no special testing was with this -hybrid. - -The patch also adds several error codes that will be used in later -patches. - -Related to: - https://pagure.io/SSSD/sssd/issue/2887 - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - Makefile.am | 53 ++++++++ - configure.ac | 10 +- - contrib/kcm_default_ccache | 12 ++ - contrib/sssd.spec.in | 41 ++++++ - src/conf_macros.m4 | 16 +++ - src/confdb/confdb.h | 3 + - src/config/cfg_rules.ini | 19 +++ - src/external/libcurl.m4 | 6 +- - src/responder/kcm/kcm.c | 254 +++++++++++++++++++++++++++++++++++ - src/responder/kcm/kcm.h | 97 +++++++++++++ - src/responder/kcm/kcmsrv_cmd.c | 65 +++++++++ - src/responder/kcm/kcmsrv_pvt.h | 58 ++++++++ - src/sysv/systemd/sssd-kcm.service.in | 9 ++ - src/sysv/systemd/sssd-kcm.socket.in | 10 ++ - src/util/util_errors.c | 5 + - src/util/util_errors.h | 5 + - 16 files changed, 658 insertions(+), 5 deletions(-) - create mode 100644 contrib/kcm_default_ccache - create mode 100644 src/responder/kcm/kcm.c - create mode 100644 src/responder/kcm/kcm.h - create mode 100644 src/responder/kcm/kcmsrv_cmd.c - create mode 100644 src/responder/kcm/kcmsrv_pvt.h - create mode 100644 src/sysv/systemd/sssd-kcm.service.in - create mode 100644 src/sysv/systemd/sssd-kcm.socket.in - -diff --git a/Makefile.am b/Makefile.am -index 7516338bc6fd95045d20db8155a0c82fd7003358..4248536e90370c1aab59549a9c18408ef314e6d4 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -87,6 +87,7 @@ sudolibdir = @sudolibpath@ - polkitdir = @polkitdir@ - pamconfdir = $(sysconfdir)/pam.d - systemtap_tapdir = @tapset_dir@ -+krb5sysincludedir = $(sysconfdir)/krb5.conf.d - - if HAVE_SYSTEMD_UNIT - ifp_exec_cmd = $(sssdlibexecdir)/sssd_ifp --uid 0 --gid 0 --debug-to-files --dbus-activated -@@ -186,6 +187,11 @@ endif - if BUILD_SECRETS - sssdlibexec_PROGRAMS += sssd_secrets - endif -+if BUILD_KCM -+sssdlibexec_PROGRAMS += sssd_kcm -+dist_krb5sysinclude_DATA = contrib/kcm_default_ccache -+endif -+ - - if BUILD_PAC_RESPONDER - sssdlibexec_PROGRAMS += sssd_pac -@@ -703,6 +709,8 @@ dist_noinst_HEADERS = \ - src/responder/secrets/secsrv_private.h \ - src/responder/secrets/secsrv_local.h \ - src/responder/secrets/secsrv_proxy.h \ -+ src/responder/kcm/kcm.h \ -+ src/responder/kcm/kcmsrv_pvt.h \ - src/sbus/sbus_client.h \ - src/sbus/sssd_dbus.h \ - src/sbus/sssd_dbus_meta.h \ -@@ -1476,6 +1484,24 @@ sssd_secrets_LDADD = \ - $(NULL) - endif - -+if BUILD_KCM -+sssd_kcm_SOURCES = \ -+ src/responder/kcm/kcm.c \ -+ src/responder/kcm/kcmsrv_cmd.c \ -+ src/util/sss_sockets.c \ -+ $(SSSD_RESPONDER_OBJ) \ -+ $(NULL) -+sssd_kcm_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(KRB5_CFLAGS) \ -+ $(NULL) -+sssd_kcm_LDADD = \ -+ $(KRB5_LIBS) \ -+ $(SSSD_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ $(NULL) -+endif -+ - sssd_be_SOURCES = \ - src/providers/data_provider_be.c \ - src/providers/data_provider_req.c \ -@@ -4259,6 +4285,12 @@ if BUILD_SUDO - src/sysv/systemd/sssd-sudo.service \ - $(NULL) - endif -+if BUILD_KCM -+ systemdunit_DATA += \ -+ src/sysv/systemd/sssd-kcm.socket \ -+ src/sysv/systemd/sssd-kcm.service \ -+ $(NULL) -+endif - if WITH_JOURNALD - systemdconf_DATA += \ - src/sysv/systemd/journal.conf -@@ -4350,6 +4382,12 @@ EXTRA_DIST += \ - src/sysv/systemd/sssd-sudo.service.in \ - $(NULL) - endif -+if BUILD_KCM -+EXTRA_DIST += \ -+ src/sysv/systemd/sssd-kcm.socket.in \ -+ src/sysv/systemd/sssd-kcm.service.in \ -+ $(NULL) -+endif - - src/sysv/systemd/sssd.service: src/sysv/systemd/sssd.service.in Makefile - @$(MKDIR_P) src/sysv/systemd/ -@@ -4433,6 +4471,16 @@ src/sysv/systemd/sssd-sudo.service: src/sysv/systemd/sssd-sudo.service.in Makefi - $(replace_script) - endif - -+if BUILD_KCM -+src/sysv/systemd/sssd-kcm.socket: src/sysv/systemd/sssd-kcm.socket.in Makefile -+ @$(MKDIR_P) src/sysv/systemd/ -+ $(replace_script) -+ -+src/sysv/systemd/sssd-kcm.service: src/sysv/systemd/sssd-kcm.service.in Makefile -+ @$(MKDIR_P) src/sysv/systemd/ -+ $(replace_script) -+endif -+ - SSSD_USER_DIRS = \ - $(DESTDIR)$(dbpath) \ - $(DESTDIR)$(keytabdir) \ -@@ -4596,6 +4644,9 @@ install-data-hook: - if BUILD_SAMBA - mv $(DESTDIR)/$(winbindplugindir)/winbind_idmap_sss.so $(DESTDIR)/$(winbindplugindir)/sss.so - endif -+if BUILD_KCM -+ $(MKDIR_P) $(DESTDIR)/$(krb5sysincludedir) -+endif - - uninstall-hook: - if [ -f $(abs_builddir)/src/config/.files2 ]; then \ -@@ -4670,6 +4721,8 @@ endif - rm -f $(builddir)/src/sysv/systemd/sssd-sudo.service - rm -f $(builddir)/src/sysv/systemd/sssd-secrets.socket - rm -f $(builddir)/src/sysv/systemd/sssd-secrets.service -+ rm -f $(builddir)/src/sysv/systemd/sssd-kcm.socket -+ rm -f $(builddir)/src/sysv/systemd/sssd-kcm.service - rm -f $(builddir)/src/sysv/systemd/journal.conf - - CLEANFILES += *.X */*.X */*/*.X -diff --git a/configure.ac b/configure.ac -index dd1012015a5fea9f25e5b5199b4868fbc0bc14c4..c363d48a806cc1998e85779a92b6b59b0e2a5c9c 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -155,6 +155,7 @@ WITH_SSSD_USER - SSSD_RUNSTATEDIR - WITH_SECRETS - WITH_SECRETS_DB_PATH -+WITH_KCM - - m4_include([src/external/pkg.m4]) - m4_include([src/external/libpopt.m4]) -@@ -193,13 +194,20 @@ m4_include([src/external/libresolv.m4]) - m4_include([src/external/intgcheck.m4]) - m4_include([src/external/systemtap.m4]) - m4_include([src/external/service.m4]) --m4_include([src/external/libcurl.m4]) - - if test x$with_secrets = xyes; then - m4_include([src/external/libhttp_parser.m4]) - m4_include([src/external/libjansson.m4]) - fi - -+if test x$with_kcm = xyes; then -+ m4_include([src/external/libcurl.m4]) -+fi -+# This variable is defined by external/libcurl.m4, but conditionals -+# must be always evaluated -+AM_CONDITIONAL([BUILD_WITH_LIBCURL], -+ [test x"$have_curlopt_unix_sockpath" = xyes]) -+ - WITH_UNICODE_LIB - if test x$unicode_lib = xlibunistring; then - m4_include([src/external/libunistring.m4]) -diff --git a/contrib/kcm_default_ccache b/contrib/kcm_default_ccache -new file mode 100644 -index 0000000000000000000000000000000000000000..ac88fca86b60b19f772912b5d9d14595a96d101d ---- /dev/null -+++ b/contrib/kcm_default_ccache -@@ -0,0 +1,12 @@ -+# This file should normally be installed by your distribution into a -+# directory that is included from the Kerberos configuration file (/etc/krb5.conf) -+# On Fedora/RHEL/CentOS, this is /etc/krb5.conf.d/ -+# -+# To enable the KCM credential cache, uncomment the following lines and -+# enable the KCM socket and the service: -+# systemctl enable sssd-kcm.socket -+# systemctl start sssd-kcm.socket -+# systemctl enable sssd-kcm.service -+ -+#[libdefaults] -+# default_ccache_name = KCM: -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 28ebe07a26a3112210b092b7831e7f6aae061c8d..5c7c2af521a84ef2ca6cca7b2d6cd1f9b3057056 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -112,6 +112,13 @@ - %global enable_systemtap_opt --enable-systemtap - %endif - -+%if (0%{?fedora} >= 23 || 0%{?rhel} >= 7) -+ %global with_kcm 1 -+ %global with_kcm_option --with-kcm -+%else -+ %global with_kcm_option --without-kcm -+%endif -+ - Name: @PACKAGE_NAME@ - Version: @PACKAGE_VERSION@ - Release: 0@PRERELEASE_VERSION@%{?dist} -@@ -677,6 +684,18 @@ Requires: libsss_certmap = %{version}-%{release} - %description -n libsss_certmap-devel - Library to map certificates to users based on rules - -+%if (0%{?with_kcm} == 1) -+%package kcm -+Summary: An implementation of a Kerberos KCM server -+Group: Applications/System -+License: GPLv3+ -+Requires: sssd-common = %{version}-%{release} -+ -+%description kcm -+An implementation of a Kerberos KCM server. Use this package if you want to -+use the KCM: Kerberos credentials cache. -+%endif -+ - %prep - %setup -q -n %{name}-%{version} - -@@ -706,6 +725,7 @@ autoreconf -ivf - %{?with_python3_option} \ - %{?enable_polkit_rules_option} \ - %{?enable_systemtap_opt} \ -+ %{?with_kcm_option} \ - %{?experimental} - - make %{?_smp_mflags} all -@@ -1178,6 +1198,15 @@ done - %{_libdir}/libsss_certmap.so - %{_libdir}/pkgconfig/sss_certmap.pc - -+%if (0%{?with_kcm} == 1) -+%files kcm -+%{_libexecdir}/%{servicename}/sssd_kcm -+%dir %{_sysconfdir}/krb5.conf.d -+%config(noreplace) %{_sysconfdir}/krb5.conf.d/kcm_default_ccache -+%{_unitdir}/sssd-kcm.socket -+%{_unitdir}/sssd-kcm.service -+%endif -+ - %pre common - getent group sssd >/dev/null || groupadd -r sssd - getent passwd sssd >/dev/null || useradd -r -g sssd -d / -s /sbin/nologin -c "User for sssd" sssd -@@ -1274,6 +1303,18 @@ fi - - %postun -n libsss_simpleifp -p /sbin/ldconfig - -+%if (0%{?with_kcm} == 1) -+%post kcm -+%systemd_post sssd-kcm.socket -+ -+%preun kcm -+%systemd_preun sssd-kcm.socket -+ -+%postun kcm -+%systemd_postun_with_restart sssd-kcm.socket -+%systemd_postun_with_restart sssd-kcm.service -+%endif -+ - %changelog - * Mon Mar 15 2010 Stephen Gallagher - @PACKAGE_VERSION@-0@PRERELEASE_VERSION@ - - Automated build of the SSSD -diff --git a/src/conf_macros.m4 b/src/conf_macros.m4 -index 749e7694f4dd7086468e461194ef274be2094236..420997229cb3c244afd8fb21b074e43a21de0eda 100644 ---- a/src/conf_macros.m4 -+++ b/src/conf_macros.m4 -@@ -887,6 +887,22 @@ AC_DEFUN([WITH_SECRETS], - AM_CONDITIONAL([BUILD_SECRETS], [test x"$with_secrets" = xyes]) - ]) - -+AC_DEFUN([WITH_KCM], -+ [ AC_ARG_WITH([kcm], -+ [AC_HELP_STRING([--with-kcm], -+ [Whether to build with KCM server support [yes]] -+ ) -+ ], -+ [with_kcm=$withval], -+ with_kcm=yes -+ ) -+ -+ if test x"$with_kcm" = xyes; then -+ AC_DEFINE(BUILD_KCM, 1, [whether to build with KCM server support]) -+ fi -+ AM_CONDITIONAL([BUILD_KCM], [test x"$with_kcm" = xyes]) -+ ]) -+ - AC_DEFUN([WITH_SECRETS_DB_PATH], - [ AC_ARG_WITH([secrets-db-path], - [AC_HELP_STRING([--with-secrets-db-path=PATH], -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index c05b1cee45ece748bf8e2b1e1ecf3dc28979e48b..c443e869a7a6782265b42c4ad122867c4e3dd8e0 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -231,6 +231,9 @@ - #define CONFDB_SEC_MAX_SECRETS "max_secrets" - #define CONFDB_SEC_MAX_PAYLOAD_SIZE "max_payload_size" - -+/* KCM Service */ -+#define CONFDB_KCM_CONF_ENTRY "config/kcm" -+#define CONFDB_KCM_SOCKET "socket_path" - - struct confdb_ctx; - struct config_file_ctx; -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index c287328828cae2f0ad8a5a105f1c2b3e05353021..5e789c51658c51c0af1338d23d6c0f30f40bf119 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -9,6 +9,7 @@ section = ssh - section = pac - section = ifp - section = secrets -+section = kcm - section_re = ^secrets/users/[0-9]\+$ - section_re = ^domain/.*$ - -@@ -262,6 +263,24 @@ option = forward_headers - option = username - option = password - -+# KCM responder -+[rule/allowed_kcm_options] -+validator = ini_allowed_options -+section_re = ^kcm$ -+ -+option = timeout -+option = debug -+option = debug_level -+option = debug_timestamps -+option = debug_microseconds -+option = debug_to_files -+option = command -+option = reconnection_retries -+option = fd_limit -+option = client_idle_timeout -+option = description -+option = socket_path -+ - [rule/allowed_domain_options] - validator = ini_allowed_options - section_re = ^domain/.*$ -diff --git a/src/external/libcurl.m4 b/src/external/libcurl.m4 -index 3bc303ca4e1dea8a04117e32b8c4466b80d885b1..b420b04ad806bd1251f086b773ffe480d39f8bd3 100644 ---- a/src/external/libcurl.m4 -+++ b/src/external/libcurl.m4 -@@ -9,8 +9,8 @@ AS_IF([test x$enable_libcurl = xyes], - [PKG_CHECK_MODULES([CURL], - [libcurl], - [found_libcurl=yes], -- [AC_MSG_WARN([ --The libcurl development library was not found. Some features will be disabled.]) -+ [AC_MSG_ERROR([ -+The libcurl development library was not found.]) - ])]) - - AS_IF([test x"$found_libcurl" = xyes], -@@ -32,7 +32,5 @@ AS_IF([test x"$found_libcurl" = xyes], - AC_SUBST(CURL_LIBS) - AC_SUBST(CURL_CFLAGS) - --AM_CONDITIONAL([BUILD_WITH_LIBCURL], -- [test x"$have_curlopt_unix_sockpath" = xyes]) - AM_COND_IF([BUILD_WITH_LIBCURL], - [AC_DEFINE_UNQUOTED(HAVE_LIBCURL, 1, [Build with libcurl support])]) -diff --git a/src/responder/kcm/kcm.c b/src/responder/kcm/kcm.c -new file mode 100644 -index 0000000000000000000000000000000000000000..90a6999c5e39d48a1a2ea8168d171612a65077d5 ---- /dev/null -+++ b/src/responder/kcm/kcm.c -@@ -0,0 +1,254 @@ -+/* -+ SSSD -+ -+ KCM Server - the mainloop and server setup -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 -+ -+#include "responder/kcm/kcm.h" -+#include "responder/kcm/kcmsrv_pvt.h" -+#include "responder/common/responder.h" -+#include "util/util.h" -+ -+#define DEFAULT_KCM_FD_LIMIT 2048 -+ -+#ifndef SSS_KCM_SOCKET_NAME -+#define SSS_KCM_SOCKET_NAME DEFAULT_KCM_SOCKET_PATH -+#endif -+ -+static int kcm_responder_ctx_destructor(void *ptr) -+{ -+ struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx); -+ -+ /* mark that we are shutting down the responder, so it is propagated -+ * into underlying contexts that are freed right before rctx */ -+ DEBUG(SSSDBG_TRACE_FUNC, "Responder is being shut down\n"); -+ rctx->shutting_down = true; -+ -+ return 0; -+} -+ -+static int kcm_get_config(struct kcm_ctx *kctx) -+{ -+ int ret; -+ char *sock_name; -+ -+ ret = confdb_get_int(kctx->rctx->cdb, -+ CONFDB_KCM_CONF_ENTRY, -+ CONFDB_SERVICE_FD_LIMIT, -+ DEFAULT_KCM_FD_LIMIT, -+ &kctx->fd_limit); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Failed to get file descriptors limit\n"); -+ goto done; -+ } -+ -+ ret = confdb_get_int(kctx->rctx->cdb, -+ kctx->rctx->confdb_service_path, -+ CONFDB_RESPONDER_CLI_IDLE_TIMEOUT, -+ CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT, -+ &kctx->rctx->client_idle_timeout); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get the client idle timeout [%d]: %s\n", -+ ret, strerror(ret)); -+ goto done; -+ } -+ -+ /* Ensure that the client timeout is at least ten seconds */ -+ if (kctx->rctx->client_idle_timeout < 10) { -+ kctx->rctx->client_idle_timeout = 10; -+ } -+ -+ ret = confdb_get_string(kctx->rctx->cdb, -+ kctx->rctx, -+ kctx->rctx->confdb_service_path, -+ CONFDB_KCM_SOCKET, -+ SSS_KCM_SOCKET_NAME, -+ &sock_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get the client idle timeout [%d]: %s\n", -+ ret, strerror(ret)); -+ goto done; -+ } -+ kctx->rctx->sock_name = sock_name; -+ -+ ret = EOK; -+ -+done: -+ return ret; -+} -+ -+static int kcm_data_destructor(void *ptr) -+{ -+ struct kcm_resp_ctx *kcm_data = talloc_get_type(ptr, struct kcm_resp_ctx); -+ -+ if (kcm_data != NULL) { -+ krb5_free_context(kcm_data->k5c); -+ } -+ return 0; -+} -+ -+static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx) -+{ -+ struct kcm_resp_ctx *kcm_data; -+ krb5_error_code kret; -+ -+ kcm_data = talloc_zero(mem_ctx, struct kcm_resp_ctx); -+ if (kcm_data == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing kcm data\n"); -+ return NULL; -+ } -+ -+ kret = krb5_init_context(&kcm_data->k5c); -+ if (kret != EOK) { -+ talloc_free(kcm_data); -+ return NULL; -+ } -+ talloc_set_destructor((TALLOC_CTX*)kcm_data, kcm_data_destructor); -+ -+ return kcm_data; -+} -+ -+static int kcm_process_init(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct confdb_ctx *cdb) -+{ -+ struct resp_ctx *rctx; -+ struct kcm_ctx *kctx; -+ int ret; -+ -+ rctx = talloc_zero(mem_ctx, struct resp_ctx); -+ if (rctx == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing resp_ctx\n"); -+ return ENOMEM; -+ } -+ rctx->ev = ev; -+ rctx->cdb = cdb; -+ rctx->confdb_service_path = CONFDB_KCM_CONF_ENTRY; -+ rctx->shutting_down = false; -+ rctx->lfd = -1; -+ rctx->priv_lfd = -1; -+ -+ talloc_set_destructor((TALLOC_CTX*)rctx, kcm_responder_ctx_destructor); -+ -+ kctx = talloc_zero(rctx, struct kcm_ctx); -+ if (kctx == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing kcm_ctx\n"); -+ ret = ENOMEM; -+ goto fail; -+ } -+ -+ kctx->rctx = rctx; -+ kctx->rctx->pvt_ctx = kctx; -+ -+ ret = kcm_get_config(kctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fatal error getting KCM config\n"); -+ goto fail; -+ } -+ -+ kctx->kcm_data = kcm_data_setup(kctx); -+ if (kctx->kcm_data == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "fatal error initializing responder data\n"); -+ ret = EIO; -+ goto fail; -+ } -+ -+ /* Set up file descriptor limits */ -+ responder_set_fd_limit(kctx->fd_limit); -+ -+ ret = activate_unix_sockets(rctx, kcm_connection_setup); -+ if (ret != EOK) goto fail; -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "KCM Initialization complete\n"); -+ -+ return EOK; -+ -+fail: -+ talloc_free(rctx); -+ return ret; -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ int opt; -+ poptContext pc; -+ struct main_context *main_ctx; -+ int ret; -+ uid_t uid; -+ gid_t gid; -+ -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ SSSD_MAIN_OPTS -+ SSSD_SERVER_OPTS(uid, gid) -+ POPT_TABLEEND -+ }; -+ -+ /* Set debug level to invalid value so we can deside if -d 0 was used. */ -+ debug_level = SSSDBG_INVALID; -+ -+ umask(DFL_RSP_UMASK); -+ -+ 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_INIT(debug_level); -+ -+ /* set up things like debug, signals, daemonization, etc... */ -+ debug_log_file = "sssd_kcm"; -+ -+ ret = server_setup("sssd[kcm]", 0, uid, gid, CONFDB_KCM_CONF_ENTRY, -+ &main_ctx); -+ if (ret != EOK) return 2; -+ -+ ret = die_if_parent_died(); -+ if (ret != EOK) { -+ /* This is not fatal, don't return */ -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not set up to exit when parent process does\n"); -+ } -+ -+ ret = kcm_process_init(main_ctx, -+ main_ctx->event_ctx, -+ main_ctx->confdb_ctx); -+ if (ret != EOK) return 3; -+ -+ /* loop on main */ -+ server_loop(main_ctx); -+ -+ return 0; -+} -diff --git a/src/responder/kcm/kcm.h b/src/responder/kcm/kcm.h -new file mode 100644 -index 0000000000000000000000000000000000000000..1ea7e9bbca754dca2eeb72a08830fa2f95713b4f ---- /dev/null -+++ b/src/responder/kcm/kcm.h -@@ -0,0 +1,97 @@ -+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -+/* include/kcm.h - Kerberos cache manager protocol declarations */ -+/* -+ * Copyright (C) 2014 by the Massachusetts Institute of Technology. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -+ * OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef KCM_H -+#define KCM_H -+ -+#define KCM_PROTOCOL_VERSION_MAJOR 2 -+#define KCM_PROTOCOL_VERSION_MINOR 0 -+ -+#define KCM_UUID_LEN 16 -+ -+/* This should ideally be in RUNSTATEDIR, but Heimdal uses a hardcoded -+ * /var/run, and we need to use the same default path. */ -+#define DEFAULT_KCM_SOCKET_PATH "/var/run/.heim_org.h5l.kcm-socket" -+#define DEFAULT_KCM_MACH_SERVICE "org.h5l.kcm" -+ -+/* -+ * All requests begin with: -+ * major version (1 bytes) -+ * minor version (1 bytes) -+ * opcode (16-bit big-endian) -+ * -+ * All replies begin with a 32-bit big-endian reply code. -+ * -+ * Parameters are appended to the request or reply with no delimiters. Flags -+ * and time offsets are stored as 32-bit big-endian integers. Names are -+ * marshalled as zero-terminated strings. Principals and credentials are -+ * marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists -+ * are not delimited, so nothing can come after them. -+ */ -+ -+/* Opcodes without comments are currently unused in the MIT client -+ * implementation. */ -+typedef enum kcm_opcode { -+ KCM_OP_NOOP, -+ KCM_OP_GET_NAME, -+ KCM_OP_RESOLVE, -+ KCM_OP_GEN_NEW, /* 0x3 () -> (name) */ -+ KCM_OP_INITIALIZE, /* 0x4 (name, princ) -> () */ -+ KCM_OP_DESTROY, /* 0x4 (name) -> () */ -+ KCM_OP_STORE, /* 0x6 (name, cred) -> () */ -+ KCM_OP_RETRIEVE, -+ KCM_OP_GET_PRINCIPAL, /* 0x8 (name) -> (princ) */ -+ KCM_OP_GET_CRED_UUID_LIST, /* 0x9 (name) -> (uuid, ...) */ -+ KCM_OP_GET_CRED_BY_UUID, /* 0xa (name, uuid) -> (cred) */ -+ KCM_OP_REMOVE_CRED, /* (name, flags, credtag) -> () */ -+ KCM_OP_SET_FLAGS, -+ KCM_OP_CHOWN, -+ KCM_OP_CHMOD, -+ KCM_OP_GET_INITIAL_TICKET, -+ KCM_OP_GET_TICKET, -+ KCM_OP_MOVE_CACHE, -+ KCM_OP_GET_CACHE_UUID_LIST, /* 0x12 () -> (uuid, ...) */ -+ KCM_OP_GET_CACHE_BY_UUID, /* 0x13 (uuid) -> (name) */ -+ KCM_OP_GET_DEFAULT_CACHE, /* 0x14 () -> (name) */ -+ KCM_OP_SET_DEFAULT_CACHE, /* 0x15 (name) -> () */ -+ KCM_OP_GET_KDC_OFFSET, /* 0x16 (name) -> (offset) */ -+ KCM_OP_SET_KDC_OFFSET, /* 0x17 (name, offset) -> () */ -+ KCM_OP_ADD_NTLM_CRED, -+ KCM_OP_HAVE_NTLM_CRED, -+ KCM_OP_DEL_NTLM_CRED, -+ KCM_OP_DO_NTLM_AUTH, -+ KCM_OP_GET_NTLM_USER_LIST, -+ -+ KCM_OP_SENTINEL, /* SSSD addition, not in the MIT header */ -+} kcm_opcode; -+ -+#endif /* KCM_H */ -diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c -new file mode 100644 -index 0000000000000000000000000000000000000000..e9a03cbd41169c93e00b0630dc1e05e205881ec9 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_cmd.c -@@ -0,0 +1,65 @@ -+/* -+ SSSD -+ -+ KCM Server - the KCM server request and reply parsing and dispatching -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 "util/util.h" -+#include "responder/common/responder.h" -+ -+struct kcm_proto_ctx { -+ void *unused; -+}; -+ -+static void kcm_fd_handler(struct tevent_context *ev, -+ struct tevent_fd *fde, -+ uint16_t flags, void *ptr) -+{ -+ errno_t ret; -+ struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx); -+ -+ /* Always reset the idle timer on any activity */ -+ ret = reset_client_idle_timer(cctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Could not create idle timer for client. " -+ "This connection may not auto-terminate\n"); -+ /* Non-fatal, continue */ -+ } -+} -+ -+int kcm_connection_setup(struct cli_ctx *cctx) -+{ -+ struct kcm_proto_ctx *protocol_ctx; -+ -+ protocol_ctx = talloc_zero(cctx, struct kcm_proto_ctx); -+ if (protocol_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ cctx->protocol_ctx = protocol_ctx; -+ cctx->cfd_handler = kcm_fd_handler; -+ return EOK; -+} -+ -+/* Dummy, not used here but required to link to other responder files */ -+struct cli_protocol_version *register_cli_protocol_version(void) -+{ -+ return NULL; -+} -diff --git a/src/responder/kcm/kcmsrv_pvt.h b/src/responder/kcm/kcmsrv_pvt.h -new file mode 100644 -index 0000000000000000000000000000000000000000..a7c9d062c17f09986d894064176c3a461d396ac0 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_pvt.h -@@ -0,0 +1,58 @@ -+/* -+ SSSD -+ -+ KCM Server - private header file -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 . -+*/ -+ -+#ifndef __KCMSRV_PVT_H__ -+#define __KCMSRV_PVT_H__ -+ -+#include "config.h" -+ -+#include -+#include "responder/common/responder.h" -+ -+/* KCM IO structure */ -+struct kcm_data { -+ uint8_t *data; -+ size_t length; -+}; -+ -+/* To avoid leaking the sssd-specific responder data to other -+ * modules, the ccache databases and other KCM specific data -+ * are kept separately -+ */ -+struct kcm_resp_ctx { -+ krb5_context k5c; -+}; -+ -+/* responder context that contains both the responder data, -+ * like the ccaches and the sssd-specific stuff like the -+ * generic responder ctx -+ */ -+struct kcm_ctx { -+ struct resp_ctx *rctx; -+ int fd_limit; -+ char *socket_path; -+ -+ struct kcm_resp_ctx *kcm_data; -+}; -+ -+int kcm_connection_setup(struct cli_ctx *cctx); -+ -+#endif /* __KCMSRV_PVT_H__ */ -diff --git a/src/sysv/systemd/sssd-kcm.service.in b/src/sysv/systemd/sssd-kcm.service.in -new file mode 100644 -index 0000000000000000000000000000000000000000..1e2bee12dc3bedd17d41b86f91c9b2b52d985c40 ---- /dev/null -+++ b/src/sysv/systemd/sssd-kcm.service.in -@@ -0,0 +1,9 @@ -+[Unit] -+Description=SSSD Kerberos Cache Manager -+Documentation=man:sssd-kcm(5) -+ -+[Install] -+Also=sssd-kcm.socket -+ -+[Service] -+ExecStart=@libexecdir@/sssd/sssd_kcm --uid 0 --gid 0 --debug-to-files -diff --git a/src/sysv/systemd/sssd-kcm.socket.in b/src/sysv/systemd/sssd-kcm.socket.in -new file mode 100644 -index 0000000000000000000000000000000000000000..80ec1c0c8f190e83de0b603df8e90aa49d2ec181 ---- /dev/null -+++ b/src/sysv/systemd/sssd-kcm.socket.in -@@ -0,0 +1,10 @@ -+[Unit] -+Description=SSSD Secrets Service responder socket -+Documentation=man:sssd-kcm(8) -+Requires=sssd-secrets.socket -+ -+[Socket] -+ListenStream=@localstatedir@/run/.heim_org.h5l.kcm-socket -+ -+[Install] -+WantedBy=sockets.target -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 17388c997db5315c2491af1021e75aff07632488..23cfdf9c6116a2c8e569a041e8289b65a112fd08 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -40,6 +40,7 @@ struct err_string error_to_str[] = { - { "Credentials are expired, old ccache was removed" }, /* ERR_CREDS_EXPIRED_CCACHE */ - { "Failure setting user credentials"}, /* ERR_CREDS_INVALID */ - { "No cached credentials available" }, /* ERR_NO_CACHED_CREDS */ -+ { "No matching credentials found" }, /* ERR_NO_MATCHING_CREDS */ - { "Cached credentials are expired" }, /* ERR_CACHED_CREDS_EXPIRED */ - { "Authentication Denied" }, /* ERR_AUTH_DENIED */ - { "Authentication Failed" }, /* ERR_AUTH_FAILED */ -@@ -104,6 +105,10 @@ struct err_string error_to_str[] = { - { "The secret payload size is too large" }, /* ERR_SEC_PAYLOAD_SIZE_IS_TOO_LARGE */ - { "No authentication methode available" }, /* ERR_NO_AUTH_METHOD_AVAILABLE */ - { "Smartcard authentication not supported" }, /* ERR_SC_AUTH_NOT_SUPPORTED */ -+ { "Malformed input KCM packet" }, /* ERR_KCM_MALFORMED_IN_PKT */ -+ { "KCM operation not implemented" }, /* ERR_KCM_OP_NOT_IMPLEMENTED */ -+ { "End of credential cache reached" }, /* ERR_KCM_CC_END */ -+ { "Credential cache name not allowed" }, /* ERR_KCM_WRONG_CCNAME_FORMAT */ - { "ERR_LAST" } /* ERR_LAST */ - }; - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 7aacad26084a3a2af6333988f07db865f6a4d299..387d481616db1ed5e22b73fae82632a582fae946 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -62,6 +62,7 @@ enum sssd_errors { - ERR_CREDS_EXPIRED_CCACHE, - ERR_CREDS_INVALID, - ERR_NO_CACHED_CREDS, -+ ERR_NO_MATCHING_CREDS, - ERR_CACHED_CREDS_EXPIRED, - ERR_AUTH_DENIED, - ERR_AUTH_FAILED, -@@ -126,6 +127,10 @@ enum sssd_errors { - ERR_SEC_PAYLOAD_SIZE_IS_TOO_LARGE, - ERR_NO_AUTH_METHOD_AVAILABLE, - ERR_SC_AUTH_NOT_SUPPORTED, -+ ERR_KCM_MALFORMED_IN_PKT, -+ ERR_KCM_OP_NOT_IMPLEMENTED, -+ ERR_KCM_CC_END, -+ ERR_KCM_WRONG_CCNAME_FORMAT, - ERR_LAST /* ALWAYS LAST */ - }; - --- -2.12.2 - diff --git a/0025-KCM-request-parsing-and-sending-a-reply.patch b/0025-KCM-request-parsing-and-sending-a-reply.patch deleted file mode 100644 index e42d4c0..0000000 --- a/0025-KCM-request-parsing-and-sending-a-reply.patch +++ /dev/null @@ -1,578 +0,0 @@ -From 9dcdbf596e138df3eec202487549a67cd3b0091b Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 23 Sep 2016 14:00:10 +0200 -Subject: [PATCH 25/97] KCM: request parsing and sending a reply -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Implements parsing the KCM client request into per-client buffers and -sending a response for both the failure case and for success. - -The protocol is documented at: - http://k5wiki.kerberos.org/wiki/Projects/KCM_client - -Several places don't use the sss_iobuf structure, because they don't -parse variable-length data from the buffer and it's much more efficient -to just allocate the needed request and reply structure on the stack. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/responder/kcm/kcmsrv_cmd.c | 467 ++++++++++++++++++++++++++++++++++++++++- - src/responder/kcm/kcmsrv_pvt.h | 21 +- - 2 files changed, 474 insertions(+), 14 deletions(-) - -diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c -index e9a03cbd41169c93e00b0630dc1e05e205881ec9..cbf70353730d8a4e03d8f75c97395f4ef007e77f 100644 ---- a/src/responder/kcm/kcmsrv_cmd.c -+++ b/src/responder/kcm/kcmsrv_cmd.c -@@ -19,14 +19,430 @@ - along with this program. If not, see . - */ - -+#include -+ - #include "config.h" - #include "util/util.h" -+#include "util/sss_iobuf.h" - #include "responder/common/responder.h" -+#include "responder/kcm/kcmsrv_pvt.h" -+#include "responder/kcm/kcm.h" - --struct kcm_proto_ctx { -- void *unused; -+/* The first four bytes of a message is always the size */ -+#define KCM_MSG_LEN_SIZE 4 -+ -+/* The return code is 32bits */ -+#define KCM_RETCODE_SIZE 4 -+ -+/* The maximum length of a request or reply as defined by the RPC -+ * protocol. This is the same constant size as MIT KRB5 uses -+ */ -+#define KCM_PACKET_MAX_SIZE 2048 -+ -+/* KCM operation, its raw input and raw output and result */ -+struct kcm_op_io { -+ struct kcm_op *op; -+ struct kcm_data request; -+ struct sss_iobuf *reply; -+}; -+ -+/** -+ * KCM IO-vector operations -+ */ -+struct kcm_iovec { -+ /* We don't use iovec b/c void pointers don't allow for -+ * pointer arithmetics and it's convenient to keep track -+ * of processed bytes -+ */ -+ uint8_t *kiov_base; -+ size_t kiov_len; -+ size_t nprocessed; -+}; -+ -+static errno_t kcm_iovec_op(int fd, struct kcm_iovec *kiov, bool do_read) -+{ -+ ssize_t len; -+ struct iovec iov[1]; -+ -+ iov[0].iov_base = kiov->kiov_base + kiov->nprocessed; -+ iov[0].iov_len = kiov->kiov_len - kiov->nprocessed; -+ if (iov[0].iov_len == 0) { -+ /* This iovec is full (read) or depleted (write), proceed to the next one */ -+ return EOK; -+ } -+ -+ if (do_read) { -+ len = readv(fd, iov, 1); -+ } else { -+ len = writev(fd, iov, 1); -+ } -+ -+ if (len == -1) { -+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { -+ return EAGAIN; -+ } else { -+ return errno; -+ } -+ } -+ -+ if (len == 0) { -+ /* Read event on fd that doesn't yield data? error */ -+ return ENODATA; -+ } -+ -+ /* Decrease the amount of available free space in the iovec */ -+ kiov->nprocessed += len; -+ return EOK; -+} -+ -+static errno_t kcm_read_iovec(int fd, struct kcm_iovec *kiov) -+{ -+ return kcm_iovec_op(fd, kiov, true); -+} -+ -+static errno_t kcm_write_iovec(int fd, struct kcm_iovec *kiov) -+{ -+ return kcm_iovec_op(fd, kiov, false); -+} -+ -+/** -+ * Parsing KCM input -+ * -+ * The request is received as two IO vectors: -+ * -+ * first iovec: -+ * length 32-bit big-endian integer -+ * -+ * second iovec: -+ * major protocol number 8-bit big-endian integer -+ * minor protocol number 8-bit big-endian integer -+ * opcode 16-bit big-endian integer -+ * message payload buffer -+ */ -+struct kcm_reqbuf { -+ uint8_t lenbuf[KCM_MSG_LEN_SIZE]; -+ struct kcm_iovec v_len; -+ -+ /* Includes the major, minor versions etc */ -+ uint8_t msgbuf[KCM_PACKET_MAX_SIZE]; -+ struct kcm_iovec v_msg; -+}; -+ -+static errno_t kcm_input_parse(struct kcm_reqbuf *reqbuf, -+ struct kcm_op_io *op_io) -+{ -+ size_t lc = 0; -+ size_t mc = 0; -+ uint16_t opcode = 0; -+ uint16_t opcode_be = 0; -+ uint32_t len_be = 0; -+ uint32_t msglen; -+ uint8_t proto_maj = 0; -+ uint8_t proto_min = 0; -+ -+ /* The first 4 bytes before the payload is message length */ -+ SAFEALIGN_COPY_UINT32_CHECK(&len_be, -+ reqbuf->v_len.kiov_base, -+ reqbuf->v_len.kiov_len, -+ &lc); -+ msglen = be32toh(len_be); -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Received message with length %"PRIu32"\n", msglen); -+ -+ if (msglen == 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Illegal zero-length message\n"); -+ return EBADMSG; -+ } -+ -+ if (msglen != reqbuf->v_msg.nprocessed) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Sender claims the message is %"PRIu32" bytes, " -+ "but received %zu\n", -+ msglen, reqbuf->v_msg.nprocessed); -+ return EBADMSG; -+ } -+ -+ /* First 16 bits are 8 bit major and 8bit major protocol version */ -+ SAFEALIGN_COPY_UINT8_CHECK(&proto_maj, -+ reqbuf->v_msg.kiov_base + mc, -+ reqbuf->v_msg.kiov_len, -+ &mc); -+ SAFEALIGN_COPY_UINT8_CHECK(&proto_min, -+ reqbuf->v_msg.kiov_base + mc, -+ reqbuf->v_msg.kiov_len, -+ &mc); -+ -+ if (proto_maj != KCM_PROTOCOL_VERSION_MAJOR) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Expected major version %d, got %"PRIu16"\n", -+ KCM_PROTOCOL_VERSION_MAJOR, (uint16_t) proto_maj); -+ return ERR_KCM_MALFORMED_IN_PKT; -+ } -+ -+ if (proto_min != KCM_PROTOCOL_VERSION_MINOR) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Expected minor version %d, got %"PRIu16"\n", -+ KCM_PROTOCOL_VERSION_MINOR, (uint16_t) proto_maj); -+ return ERR_KCM_MALFORMED_IN_PKT; -+ } -+ -+ SAFEALIGN_COPY_UINT16_CHECK(&opcode_be, -+ reqbuf->v_msg.kiov_base + mc, -+ reqbuf->v_msg.kiov_len, -+ &mc); -+ -+ opcode = be16toh(opcode_be); -+ DEBUG(SSSDBG_TRACE_LIBS, "Received operation code %"PRIu16"\n", opcode); -+ -+ return EOK; -+} -+ -+/** -+ * Constructing a reply for failure and success -+ * -+ * The reply consists of three IO vectors: -+ * 1) length iovec: -+ * length: 32-bit big-endian -+ * -+ * 2) return code iovec: -+ * retcode: 32-bit big-endian. Non-zero on failure in the KCM server, -+ * zero if the KCM operation ran (even if the operation itself -+ * failed) -+ * -+ * 3) reply iovec -+ * message: buffer, first 32-bits of the buffer is the return code of -+ * the KCM operation, the rest depends on the operation itself. -+ * The buffer's length is specified by the first integer in the -+ * reply (very intuitive, right?) -+ * -+ * The client always reads the length and return code iovectors. However, the -+ * client reads the reply iovec only if retcode is 0 in the return code iovector -+ * (see kcmio_unix_socket_read() in the MIT tree) -+ */ -+struct kcm_repbuf { -+ uint8_t lenbuf[KCM_MSG_LEN_SIZE]; -+ struct kcm_iovec v_len; -+ -+ uint8_t rcbuf[KCM_RETCODE_SIZE]; -+ struct kcm_iovec v_rc; -+ -+ uint8_t msgbuf[KCM_PACKET_MAX_SIZE]; -+ struct kcm_iovec v_msg; -+}; -+ -+static errno_t kcm_failbuf_construct(errno_t ret, -+ struct kcm_repbuf *repbuf) -+{ -+ size_t c; -+ -+ c = 0; -+ SAFEALIGN_SETMEM_UINT32(repbuf->lenbuf, 0, &c); -+ c = 0; -+ SAFEALIGN_SETMEM_UINT32(repbuf->rcbuf, htobe32(ret), &c); -+ -+ return EOK; -+} -+ -+/** -+ * Construct a reply buffer and send it to the KCM client -+ */ -+static void kcm_reply_error(struct cli_ctx *cctx, -+ errno_t retcode, -+ struct kcm_repbuf *repbuf) -+{ -+ errno_t ret; -+ krb5_error_code kerr; -+ -+ DEBUG(SSSDBG_OP_FAILURE, -+ "KCM operation returs failure [%d]: %s\n", -+ retcode, sss_strerror(retcode)); -+ kerr = sss2krb5_error(retcode); -+ -+ ret = kcm_failbuf_construct(kerr, repbuf); -+ if (ret != EOK) { -+ /* If we can't construct the reply buffer, just terminate the client */ -+ talloc_free(cctx); -+ return; -+ } -+ -+ TEVENT_FD_WRITEABLE(cctx->cfde); -+} -+ -+/** -+ * Request-reply dispatcher -+ */ -+struct kcm_req_ctx { -+ /* client context owns per-client buffers including this one */ -+ struct cli_ctx *cctx; -+ -+ /* raw IO buffers */ -+ struct kcm_reqbuf reqbuf; -+ struct kcm_repbuf repbuf; -+ -+ /* long-lived responder structures */ -+ struct kcm_ctx *kctx; -+ -+ struct kcm_op_io op_io; - }; - -+static errno_t kcm_recv_data(int fd, struct kcm_reqbuf *reqbuf) -+{ -+ errno_t ret; -+ -+ ret = kcm_read_iovec(fd, &reqbuf->v_len); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = kcm_read_iovec(fd, &reqbuf->v_msg); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+static struct kcm_req_ctx *kcm_new_req(TALLOC_CTX *mem_ctx, -+ struct cli_ctx *cctx, -+ struct kcm_ctx *kctx) -+{ -+ struct kcm_req_ctx *req; -+ -+ req = talloc_zero(cctx, struct kcm_req_ctx); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ req->reqbuf.v_len.kiov_base = req->reqbuf.lenbuf; -+ req->reqbuf.v_len.kiov_len = KCM_MSG_LEN_SIZE; -+ -+ req->reqbuf.v_msg.kiov_base = req->reqbuf.msgbuf; -+ req->reqbuf.v_msg.kiov_len = KCM_PACKET_MAX_SIZE; -+ -+ req->repbuf.v_len.kiov_base = req->repbuf.lenbuf; -+ req->repbuf.v_len.kiov_len = KCM_MSG_LEN_SIZE; -+ -+ req->repbuf.v_rc.kiov_base = req->repbuf.rcbuf; -+ req->repbuf.v_rc.kiov_len = KCM_RETCODE_SIZE; -+ -+ req->repbuf.v_msg.kiov_base = req->repbuf.msgbuf; -+ /* Length of the msg iobuf will be adjusted later, so far use the full -+ * length so that constructing the reply can use that capacity -+ */ -+ req->repbuf.v_msg.kiov_len = KCM_PACKET_MAX_SIZE; -+ -+ req->cctx = cctx; -+ req->kctx = kctx; -+ -+ return req; -+} -+ -+static void kcm_recv(struct cli_ctx *cctx) -+{ -+ struct kcm_req_ctx *req; -+ struct kcm_ctx *kctx; -+ int ret; -+ -+ kctx = talloc_get_type(cctx->rctx->pvt_ctx, struct kcm_ctx); -+ req = talloc_get_type(cctx->state_ctx, struct kcm_req_ctx); -+ if (req == NULL) { -+ /* A new request comes in, setup data structures */ -+ req = kcm_new_req(cctx, cctx, kctx); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot set up client connection\n"); -+ talloc_free(cctx); -+ return; -+ } -+ -+ cctx->state_ctx = req; -+ } -+ -+ ret = kcm_recv_data(cctx->cfd, &req->reqbuf); -+ switch (ret) { -+ case ENODATA: -+ DEBUG(SSSDBG_TRACE_ALL, "Client closed connection.\n"); -+ talloc_free(cctx); -+ return; -+ case EAGAIN: -+ DEBUG(SSSDBG_TRACE_ALL, "Retry later\n"); -+ return; -+ case EOK: -+ /* all fine */ -+ break; -+ default: -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Failed to receive data (%d, %s), aborting client\n", -+ ret, sss_strerror(ret)); -+ talloc_free(cctx); -+ return; -+ } -+ -+ ret = kcm_input_parse(&req->reqbuf, &req->op_io); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Failed to parse data (%d, %s), aborting client\n", -+ ret, sss_strerror(ret)); -+ goto fail; -+ } -+ -+ /* do not read anymore, client is done sending */ -+ TEVENT_FD_NOT_READABLE(cctx->cfde); -+ -+ kcm_reply_error(cctx, ret, &req->repbuf); -+ return; -+ -+fail: -+ /* Fail with reply */ -+ kcm_reply_error(cctx, ret, &req->repbuf); -+} -+ -+static int kcm_send_data(struct cli_ctx *cctx) -+{ -+ struct kcm_req_ctx *req; -+ errno_t ret; -+ -+ req = talloc_get_type(cctx->state_ctx, struct kcm_req_ctx); -+ -+ ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_len); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_rc); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_msg); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+static void kcm_send(struct cli_ctx *cctx) -+{ -+ errno_t ret; -+ -+ ret = kcm_send_data(cctx); -+ if (ret == EAGAIN) { -+ /* not all data was sent, loop again */ -+ return; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n"); -+ talloc_free(cctx); -+ return; -+ } -+ -+ /* ok all sent */ -+ TEVENT_FD_NOT_WRITEABLE(cctx->cfde); -+ TEVENT_FD_READABLE(cctx->cfde); -+ talloc_zfree(cctx->state_ctx); -+ return; -+} -+ - static void kcm_fd_handler(struct tevent_context *ev, - struct tevent_fd *fde, - uint16_t flags, void *ptr) -@@ -39,25 +455,54 @@ static void kcm_fd_handler(struct tevent_context *ev, - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Could not create idle timer for client. " -- "This connection may not auto-terminate\n"); -+ "This connection may not auto-terminate\n"); - /* Non-fatal, continue */ - } -+ -+ if (flags & TEVENT_FD_READ) { -+ kcm_recv(cctx); -+ return; -+ } -+ if (flags & TEVENT_FD_WRITE) { -+ kcm_send(cctx); -+ return; -+ } - } - - int kcm_connection_setup(struct cli_ctx *cctx) - { -- struct kcm_proto_ctx *protocol_ctx; -- -- protocol_ctx = talloc_zero(cctx, struct kcm_proto_ctx); -- if (protocol_ctx == NULL) { -- return ENOMEM; -- } -- -- cctx->protocol_ctx = protocol_ctx; - cctx->cfd_handler = kcm_fd_handler; - return EOK; - } - -+krb5_error_code sss2krb5_error(errno_t err) -+{ -+ switch (err) { -+ case EOK: -+ return 0; -+ case ENOMEM: -+ return KRB5_CC_NOMEM; -+ case EACCES: -+ return KRB5_FCC_PERM; -+ case ERR_KCM_OP_NOT_IMPLEMENTED: -+ return KRB5_CC_NOSUPP; -+ case ERR_WRONG_NAME_FORMAT: -+ return KRB5_CC_BADNAME; -+ case ERR_NO_MATCHING_CREDS: -+ return KRB5_FCC_NOFILE; -+ case ERR_NO_CREDS: -+ return KRB5_CC_NOTFOUND; -+ case ERR_KCM_CC_END: -+ return KRB5_CC_END; -+ case ERR_KCM_MALFORMED_IN_PKT: -+ case EINVAL: -+ case EIO: -+ return KRB5_CC_IO; -+ } -+ -+ return KRB5_FCC_INTERNAL; -+} -+ - /* Dummy, not used here but required to link to other responder files */ - struct cli_protocol_version *register_cli_protocol_version(void) - { -diff --git a/src/responder/kcm/kcmsrv_pvt.h b/src/responder/kcm/kcmsrv_pvt.h -index a7c9d062c17f09986d894064176c3a461d396ac0..fd1fd9fa32d59a323d465def68999f24f84e3923 100644 ---- a/src/responder/kcm/kcmsrv_pvt.h -+++ b/src/responder/kcm/kcmsrv_pvt.h -@@ -27,13 +27,20 @@ - #include - #include "responder/common/responder.h" - --/* KCM IO structure */ -+/* -+ * KCM IO structure -+ * -+ * In theory we cold use sss_iobuf there, but since iobuf was -+ * made opaque, this allows it to allocate the structures on -+ * the stack in one go. -+ * */ - struct kcm_data { - uint8_t *data; - size_t length; - }; - --/* To avoid leaking the sssd-specific responder data to other -+/* -+ * To avoid leaking the sssd-specific responder data to other - * modules, the ccache databases and other KCM specific data - * are kept separately - */ -@@ -41,7 +48,8 @@ struct kcm_resp_ctx { - krb5_context k5c; - }; - --/* responder context that contains both the responder data, -+/* -+ * responder context that contains both the responder data, - * like the ccaches and the sssd-specific stuff like the - * generic responder ctx - */ -@@ -55,4 +63,11 @@ struct kcm_ctx { - - int kcm_connection_setup(struct cli_ctx *cctx); - -+/* -+ * Internally in SSSD-KCM we use SSSD-internal error codes so that we -+ * can always the same sss_strerror() functions to format the errors -+ * nicely, but the client expects libkrb5 error codes. -+ */ -+krb5_error_code sss2krb5_error(errno_t err); -+ - #endif /* __KCMSRV_PVT_H__ */ --- -2.12.2 - diff --git a/0026-KCM-Implement-an-internal-ccache-storage-and-retriev.patch b/0026-KCM-Implement-an-internal-ccache-storage-and-retriev.patch deleted file mode 100644 index 187b125..0000000 --- a/0026-KCM-Implement-an-internal-ccache-storage-and-retriev.patch +++ /dev/null @@ -1,2153 +0,0 @@ -From bea0dc79faf609de8603cb42f190adae544bc8fb Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 7 Mar 2017 13:49:21 +0100 -Subject: [PATCH 26/97] KCM: Implement an internal ccache storage and retrieval - API -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In order for the KCM server to work with ccaches stored in different -locations, implement a middle-man between the KCM server and the ccache -storage. - -This module has asynchronous API because we can't assume anything about -where the ccaches are stored. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - Makefile.am | 9 + - configure.ac | 1 + - contrib/sssd.spec.in | 1 + - src/external/libuuid.m4 | 17 + - src/responder/kcm/kcmsrv_ccache.c | 1423 +++++++++++++++++++++++++++++++++ - src/responder/kcm/kcmsrv_ccache.h | 306 +++++++ - src/responder/kcm/kcmsrv_ccache_be.h | 204 +++++ - src/responder/kcm/kcmsrv_ccache_pvt.h | 62 ++ - src/responder/kcm/kcmsrv_pvt.h | 1 + - 9 files changed, 2024 insertions(+) - create mode 100644 src/external/libuuid.m4 - create mode 100644 src/responder/kcm/kcmsrv_ccache.c - create mode 100644 src/responder/kcm/kcmsrv_ccache.h - create mode 100644 src/responder/kcm/kcmsrv_ccache_be.h - create mode 100644 src/responder/kcm/kcmsrv_ccache_pvt.h - -diff --git a/Makefile.am b/Makefile.am -index 4248536e90370c1aab59549a9c18408ef314e6d4..a2b9dc49e95fa2d025f5174d2902866fab180a78 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -711,6 +711,9 @@ dist_noinst_HEADERS = \ - src/responder/secrets/secsrv_proxy.h \ - src/responder/kcm/kcm.h \ - src/responder/kcm/kcmsrv_pvt.h \ -+ src/responder/kcm/kcmsrv_ccache.h \ -+ src/responder/kcm/kcmsrv_ccache_pvt.h \ -+ src/responder/kcm/kcmsrv_ccache_be.h \ - src/sbus/sbus_client.h \ - src/sbus/sssd_dbus.h \ - src/sbus/sssd_dbus_meta.h \ -@@ -1488,16 +1491,22 @@ if BUILD_KCM - sssd_kcm_SOURCES = \ - src/responder/kcm/kcm.c \ - src/responder/kcm/kcmsrv_cmd.c \ -+ src/responder/kcm/kcmsrv_ccache.c \ - src/util/sss_sockets.c \ -+ src/util/sss_krb5.c \ -+ src/util/sss_iobuf.c \ - $(SSSD_RESPONDER_OBJ) \ - $(NULL) - sssd_kcm_CFLAGS = \ - $(AM_CFLAGS) \ - $(KRB5_CFLAGS) \ -+ $(UUID_CFLAGS) \ - $(NULL) - sssd_kcm_LDADD = \ - $(KRB5_LIBS) \ - $(SSSD_LIBS) \ -+ $(UUID_LIBS) \ -+ $(SYSTEMD_DAEMON_LIBS) \ - $(SSSD_INTERNAL_LTLIBS) \ - $(NULL) - endif -diff --git a/configure.ac b/configure.ac -index c363d48a806cc1998e85779a92b6b59b0e2a5c9c..cf5e2557ef0a1bd6374200aa33abea6c509d03aa 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -202,6 +202,7 @@ fi - - if test x$with_kcm = xyes; then - m4_include([src/external/libcurl.m4]) -+ m4_include([src/external/libuuid.m4]) - fi - # This variable is defined by external/libcurl.m4, but conditionals - # must be always evaluated -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 5c7c2af521a84ef2ca6cca7b2d6cd1f9b3057056..52d33b4de281dc1d91a9027ac1c8c878e66fb396 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -222,6 +222,7 @@ BuildRequires: systemtap-sdt-devel - %endif - BuildRequires: http-parser-devel - BuildRequires: jansson-devel -+BuildRequires: libuuid-devel - - %description - Provides a set of daemons to manage access to remote directories and -diff --git a/src/external/libuuid.m4 b/src/external/libuuid.m4 -new file mode 100644 -index 0000000000000000000000000000000000000000..55411a2118bd787c9d50ba61f9cb791e1c76088d ---- /dev/null -+++ b/src/external/libuuid.m4 -@@ -0,0 +1,17 @@ -+AC_SUBST(UUID_LIBS) -+AC_SUBST(UUID_CFLAGS) -+ -+PKG_CHECK_MODULES([UUID], [uuid], [found_uuid=yes], [found_uuid=no]) -+ -+SSS_AC_EXPAND_LIB_DIR() -+AS_IF([test x"$found_uuid" = xyes], -+ [AC_CHECK_HEADERS([uuid/uuid.h], -+ [AC_CHECK_LIB([uuid], -+ [uuid_generate], -+ [UUID_LIBS="-L$sss_extra_libdir -luuid"], -+ [AC_MSG_ERROR([libuuid missing uuid_generate])], -+ [-L$sss_extra_libdir -luuid])], -+ [AC_MSG_ERROR([ -+You must have the header file uuid.h installed to build sssd -+with KCM responder. If you want to build sssd without KCM responder -+then specify --without-kcm when running configure.])])]) -diff --git a/src/responder/kcm/kcmsrv_ccache.c b/src/responder/kcm/kcmsrv_ccache.c -new file mode 100644 -index 0000000000000000000000000000000000000000..2c565b8378e3ec297faf655d3c48d7ab902713d3 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ccache.c -@@ -0,0 +1,1423 @@ -+/* -+ SSSD -+ -+ KCM Server - the KCM ccache operations -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 "util/crypto/sss_crypto.h" -+#include "util/util.h" -+#include "util/sss_krb5.h" -+#include "responder/kcm/kcmsrv_ccache.h" -+#include "responder/kcm/kcmsrv_ccache_pvt.h" -+#include "responder/kcm/kcmsrv_ccache_be.h" -+ -+static int kcm_cc_destructor(struct kcm_ccache *cc) -+{ -+ if (cc == NULL) { -+ return 0; -+ } -+ -+ krb5_free_principal(NULL, cc->client); -+ return 0; -+} -+ -+errno_t kcm_cc_new(TALLOC_CTX *mem_ctx, -+ krb5_context k5c, -+ struct cli_creds *owner, -+ const char *name, -+ krb5_principal princ, -+ struct kcm_ccache **_cc) -+{ -+ struct kcm_ccache *cc; -+ krb5_error_code kret; -+ errno_t ret; -+ -+ cc = talloc_zero(mem_ctx, struct kcm_ccache); -+ if (cc == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = kcm_check_name(name, owner); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Name %s is malformed\n", name); -+ return ret; -+ } -+ -+ cc->name = talloc_strdup(cc, name); -+ if (cc->name == NULL) { -+ talloc_free(cc); -+ return ENOMEM; -+ } -+ -+ uuid_generate(cc->uuid); -+ -+ kret = krb5_copy_principal(k5c, princ, &cc->client); -+ if (kret != 0) { -+ const char *err_msg = sss_krb5_get_error_message(k5c, kret); -+ DEBUG(SSSDBG_OP_FAILURE, -+ "krb5_copy_principal failed: [%d][%s]\n", kret, err_msg); -+ sss_krb5_free_error_message(k5c, err_msg); -+ talloc_free(cc); -+ return ERR_INTERNAL; -+ } -+ -+ cc->owner.uid = cli_creds_get_uid(owner); -+ cc->owner.gid = cli_creds_get_gid(owner); -+ cc->kdc_offset = INT32_MAX; -+ -+ talloc_set_destructor(cc, kcm_cc_destructor); -+ *_cc = cc; -+ return EOK; -+} -+ -+const char *kcm_cc_get_name(struct kcm_ccache *cc) -+{ -+ return cc ? cc->name : NULL; -+} -+ -+errno_t kcm_cc_get_uuid(struct kcm_ccache *cc, uuid_t _uuid) -+{ -+ if (cc == NULL) { -+ return EINVAL; -+ } -+ uuid_copy(_uuid, cc->uuid); -+ return EOK; -+} -+ -+krb5_principal kcm_cc_get_client_principal(struct kcm_ccache *cc) -+{ -+ return cc ? cc->client : NULL; -+} -+ -+bool kcm_cc_access(struct kcm_ccache *cc, -+ struct cli_creds *client) -+{ -+ bool ok; -+ uid_t uid = cli_creds_get_uid(client); -+ gid_t gid = cli_creds_get_gid(client); -+ -+ if (cc == NULL) { -+ return false; -+ } -+ -+ if (uid == 0 && gid == 0) { -+ /* root can access any ccache */ -+ return true; -+ } -+ -+ ok = ((cc->owner.uid == uid) && (cc->owner.gid == gid)); -+ if (!ok) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Client %"SPRIuid":%"SPRIgid" has no access to ccache %s\n", -+ cli_creds_get_uid(client), -+ cli_creds_get_gid(client), -+ cc->name); -+ } -+ return ok; -+} -+ -+int32_t kcm_cc_get_offset(struct kcm_ccache *cc) -+{ -+ return cc ? cc->kdc_offset : INT32_MAX; -+} -+ -+errno_t kcm_cc_store_cred_blob(struct kcm_ccache *cc, -+ struct sss_iobuf *cred_blob) -+{ -+ struct kcm_cred *kcreds; -+ uuid_t uuid; -+ errno_t ret; -+ -+ if (cc == NULL || cred_blob == NULL) { -+ return EINVAL; -+ } -+ -+ uuid_generate(uuid); -+ kcreds = kcm_cred_new(cc, uuid, cred_blob); -+ if (kcreds == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = kcm_cc_store_creds(cc, kcreds); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+struct kcm_cred *kcm_cc_get_cred(struct kcm_ccache *cc) -+{ -+ if (cc == NULL) { -+ return NULL; -+ } -+ -+ return cc->creds; -+} -+ -+struct kcm_cred *kcm_cc_next_cred(struct kcm_cred *crd) -+{ -+ if (crd == NULL) { -+ return NULL; -+ } -+ -+ return crd->next; -+} -+ -+struct kcm_cred *kcm_cred_new(TALLOC_CTX *mem_ctx, -+ uuid_t uuid, -+ struct sss_iobuf *cred_blob) -+{ -+ struct kcm_cred *kcreds; -+ -+ kcreds = talloc_zero(mem_ctx, struct kcm_cred); -+ if (kcreds == NULL) { -+ return NULL; -+ } -+ -+ uuid_copy(kcreds->uuid, uuid); -+ kcreds->cred_blob = talloc_steal(kcreds, cred_blob); -+ return kcreds; -+} -+ -+/* Add a cred to ccache */ -+errno_t kcm_cc_store_creds(struct kcm_ccache *cc, -+ struct kcm_cred *crd) -+{ -+ DLIST_ADD(cc->creds, crd); -+ talloc_steal(cc, crd); -+ return EOK; -+} -+ -+errno_t kcm_cred_get_uuid(struct kcm_cred *crd, uuid_t _uuid) -+{ -+ if (crd == NULL) { -+ return EINVAL; -+ } -+ uuid_copy(_uuid, crd->uuid); -+ return EOK; -+} -+ -+struct sss_iobuf *kcm_cred_get_creds(struct kcm_cred *crd) -+{ -+ return crd ? crd->cred_blob : NULL; -+} -+ -+struct kcm_ccdb *kcm_ccdb_init(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ enum kcm_ccdb_be cc_be) -+{ -+ errno_t ret; -+ struct kcm_ccdb *ccdb = NULL; -+ -+ if (ev == NULL) { -+ return NULL; -+ } -+ -+ ccdb = talloc_zero(mem_ctx, struct kcm_ccdb); -+ if (ccdb == NULL) { -+ return NULL; -+ } -+ ccdb->ev = ev; -+ -+ switch (cc_be) { -+ case CCDB_BE_MEMORY: -+ DEBUG(SSSDBG_FUNC_DATA, "KCM back end: memory\n"); -+ /* Not implemented yet */ -+ break; -+ case CCDB_BE_SECRETS: -+ DEBUG(SSSDBG_FUNC_DATA, "KCM back end: sssd-secrets\n"); -+ /* Not implemented yet */ -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unknown ccache database\n"); -+ break; -+ } -+ -+ if (ccdb->ops == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Ccache database not initialized\n"); -+ talloc_free(ccdb); -+ return NULL; -+ } -+ -+ ret = ccdb->ops->init(ccdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize ccache database\n"); -+ talloc_free(ccdb); -+ return NULL; -+ } -+ -+ return ccdb; -+} -+ -+struct kcm_ccdb_nextid_state { -+ char *next_cc; -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+}; -+ -+static void kcm_ccdb_nextid_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_nextid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_nextid_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_nextid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->client = client; -+ -+ if (ev == NULL || db == NULL || client == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = state->db->ops->nextid_send(mem_ctx, ev, state->db, client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_nextid_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_nextid_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_nextid_state *state = tevent_req_data(req, -+ struct kcm_ccdb_nextid_state); -+ errno_t ret; -+ unsigned int nextid; -+ -+ ret = state->db->ops->nextid_recv(subreq, &nextid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to generate next UID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->next_cc = talloc_asprintf(state, "%"SPRIuid":%u", -+ cli_creds_get_uid(state->client), -+ nextid); -+ if (state->next_cc == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed\n"); -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "generated %s\n", state->next_cc); -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_nextid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ char **_next_cc) -+{ -+ struct kcm_ccdb_nextid_state *state = tevent_req_data(req, -+ struct kcm_ccdb_nextid_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_next_cc = talloc_steal(mem_ctx, state->next_cc); -+ return EOK; -+} -+ -+struct kcm_ccdb_list_state { -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ -+ uuid_t *uuid_list; -+}; -+ -+static void kcm_ccdb_list_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_list_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_list_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_list_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->client = client; -+ -+ if (ev == NULL || db == NULL || client == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = state->db->ops->list_send(mem_ctx, -+ ev, -+ state->db, -+ client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_list_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_list_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_list_state *state = tevent_req_data(req, -+ struct kcm_ccdb_list_state); -+ errno_t ret; -+ -+ ret = state->db->ops->list_recv(subreq, state, &state->uuid_list); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to list all ccaches [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_list_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t **_uuid_list) -+{ -+ struct kcm_ccdb_list_state *state = tevent_req_data(req, -+ struct kcm_ccdb_list_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_uuid_list = talloc_steal(mem_ctx, state->uuid_list); -+ return EOK; -+} -+ -+struct kcm_ccdb_get_default_state { -+ struct kcm_ccdb *db; -+ uuid_t uuid; -+}; -+ -+static void kcm_ccdb_get_default_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_get_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_get_default_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_get_default_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ -+ if (ev == NULL || db == NULL || client == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = db->ops->get_default_send(mem_ctx, ev, db, client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_get_default_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_get_default_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_get_default_state *state = tevent_req_data(req, -+ struct kcm_ccdb_get_default_state); -+ errno_t ret; -+ -+ ret = state->db->ops->get_default_recv(subreq, state->uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get the default ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_get_default_recv(struct tevent_req *req, -+ uuid_t *uuid) -+{ -+ struct kcm_ccdb_get_default_state *state = tevent_req_data(req, -+ struct kcm_ccdb_get_default_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ if (uuid != NULL) { -+ /* The caller might supply a NULL dfl to just check if there is -+ * some default ccache -+ */ -+ uuid_copy(*uuid, state->uuid); -+ } -+ -+ return EOK; -+} -+ -+struct kcm_ccdb_set_default_state { -+ struct tevent_context *ev; -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ uuid_t uuid; -+}; -+ -+static void kcm_ccdb_set_default_uuid_resolved(struct tevent_req *subreq); -+static void kcm_ccdb_set_default_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_set_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_set_default_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_set_default_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->ev = ev; -+ state->client = client; -+ uuid_copy(state->uuid, uuid); -+ -+ if (ev == NULL || db == NULL || client == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ if (uuid_is_null(uuid)) { -+ /* NULL UUID means to just reset the default to 'no default' */ -+ subreq = state->db->ops->set_default_send(state, -+ state->ev, -+ state->db, -+ state->client, -+ state->uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_set_default_done, req); -+ } else { -+ /* Otherwise we need to check if the client can access the UUID -+ * about to be set as default -+ */ -+ subreq = db->ops->getbyuuid_send(state, ev, db, client, uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_set_default_uuid_resolved, req); -+ } -+ -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_set_default_uuid_resolved(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_set_default_state *state = tevent_req_data(req, -+ struct kcm_ccdb_set_default_state); -+ errno_t ret; -+ bool ok; -+ struct kcm_ccache *cc; -+ -+ ret = state->db->ops->getbyuuid_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get cache by UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (cc == NULL) { -+ DEBUG(SSSDBG_TRACE_LIBS, "No cache found by UUID\n"); -+ tevent_req_error(req, ERR_KCM_CC_END); -+ return; -+ } -+ -+ ok = kcm_cc_access(cc, state->client); -+ if (!ok) { -+ tevent_req_error(req, EACCES); -+ return; -+ } -+ -+ subreq = state->db->ops->set_default_send(state, -+ state->ev, -+ state->db, -+ state->client, -+ state->uuid); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_set_default_done, req); -+} -+ -+static void kcm_ccdb_set_default_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_set_default_state *state = tevent_req_data(req, -+ struct kcm_ccdb_set_default_state); -+ errno_t ret; -+ -+ ret = state->db->ops->set_default_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to set the default ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_set_default_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+struct kcm_ccdb_getbyname_state { -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ -+ struct kcm_ccache *cc; -+}; -+ -+static void kcm_ccdb_getbyname_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_getbyname_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_getbyname_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_getbyname_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->client = client; -+ -+ if (ev == NULL || db == NULL || client == NULL || name == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = db->ops->getbyname_send(state, ev, db, client, name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_getbyname_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_getbyname_state *state = tevent_req_data(req, -+ struct kcm_ccdb_getbyname_state); -+ errno_t ret; -+ bool ok; -+ -+ ret = state->db->ops->getbyname_recv(subreq, state, &state->cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get cache by name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (state->cc == NULL) { -+ DEBUG(SSSDBG_TRACE_LIBS, "No cache found by name\n"); -+ tevent_req_done(req); -+ return; -+ } -+ -+ ok = kcm_cc_access(state->cc, state->client); -+ if (!ok) { -+ tevent_req_error(req, EACCES); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_getbyname_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct kcm_ccdb_getbyname_state *state = tevent_req_data(req, -+ struct kcm_ccdb_getbyname_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+struct kcm_ccdb_getbyuuid_state { -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ -+ struct kcm_ccache *cc; -+}; -+ -+static void kcm_ccdb_getbyuuid_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_getbyuuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_getbyuuid_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_getbyuuid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->client = client; -+ -+ if (ev == NULL || db == NULL || client == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = db->ops->getbyuuid_send(state, ev, db, client, uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_getbyuuid_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_getbyuuid_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_getbyuuid_state *state = tevent_req_data(req, -+ struct kcm_ccdb_getbyuuid_state); -+ errno_t ret; -+ bool ok; -+ -+ ret = state->db->ops->getbyuuid_recv(subreq, state, &state->cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get cache by UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (state->cc == NULL) { -+ DEBUG(SSSDBG_TRACE_LIBS, "No cache found by UUID\n"); -+ tevent_req_done(req); -+ return; -+ } -+ -+ ok = kcm_cc_access(state->cc, state->client); -+ if (!ok) { -+ tevent_req_error(req, EACCES); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_getbyuuid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct kcm_ccdb_getbyuuid_state *state = tevent_req_data(req, -+ struct kcm_ccdb_getbyuuid_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+struct kcm_ccdb_name_by_uuid_state { -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ -+ const char *name; -+}; -+ -+static void kcm_ccdb_name_by_uuid_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_name_by_uuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_name_by_uuid_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, -+ &state, -+ struct kcm_ccdb_name_by_uuid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->client = client; -+ -+ if (ev == NULL || db == NULL || client == NULL || uuid_is_null(uuid)) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = db->ops->name_by_uuid_send(state, ev, db, client, uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_name_by_uuid_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_name_by_uuid_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_name_by_uuid_state *state = tevent_req_data(req, -+ struct kcm_ccdb_name_by_uuid_state); -+ errno_t ret; -+ -+ ret = state->db->ops->name_by_uuid_recv(subreq, state, &state->name); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to resolve cache by UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_name_by_uuid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ const char **_name) -+{ -+ struct kcm_ccdb_name_by_uuid_state *state = tevent_req_data(req, -+ struct kcm_ccdb_name_by_uuid_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_name = talloc_steal(mem_ctx, state->name); -+ return EOK; -+} -+ -+struct kcm_ccdb_uuid_by_name_state { -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ -+ uuid_t uuid; -+}; -+ -+static void kcm_ccdb_uuid_by_name_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_uuid_by_name_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_uuid_by_name_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, -+ &state, -+ struct kcm_ccdb_uuid_by_name_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->client = client; -+ -+ if (ev == NULL || db == NULL || client == NULL || name == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = db->ops->uuid_by_name_send(state, ev, db, client, name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_uuid_by_name_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_uuid_by_name_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_uuid_by_name_state *state = tevent_req_data(req, -+ struct kcm_ccdb_uuid_by_name_state); -+ errno_t ret; -+ -+ ret = state->db->ops->uuid_by_name_recv(subreq, state, state->uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to resolve cache by UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_uuid_by_name_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t _uuid) -+{ -+ struct kcm_ccdb_uuid_by_name_state *state = tevent_req_data(req, -+ struct kcm_ccdb_uuid_by_name_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ uuid_copy(_uuid, state->uuid); -+ return EOK; -+} -+ -+struct kcm_ccdb_create_cc_state { -+ struct kcm_ccdb *db; -+}; -+ -+static void kcm_ccdb_create_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_create_cc_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ struct kcm_ccache *cc) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_create_cc_state *state = NULL; -+ errno_t ret; -+ bool ok; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_create_cc_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ -+ if (ev == NULL || db == NULL || client == NULL || cc == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ ok = kcm_cc_access(cc, client); -+ if (!ok) { -+ ret = EACCES; -+ goto immediate; -+ } -+ -+ subreq = state->db->ops->create_send(mem_ctx, -+ ev, -+ state->db, -+ client, -+ cc); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_create_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_create_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_create_cc_state *state = tevent_req_data(req, -+ struct kcm_ccdb_create_cc_state); -+ errno_t ret; -+ -+ ret = state->db->ops->create_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to create ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_create_cc_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+void kcm_mod_ctx_clear(struct kcm_mod_ctx *mod_ctx) -+{ -+ if (mod_ctx == NULL) { -+ return; -+ } -+ -+ mod_ctx->kdc_offset = INT32_MAX; -+} -+ -+void kcm_mod_cc(struct kcm_ccache *cc, struct kcm_mod_ctx *mod_ctx) -+{ -+ if (cc == NULL || mod_ctx == NULL) { -+ return; -+ } -+ -+ if (mod_ctx->kdc_offset != INT32_MAX) { -+ cc->kdc_offset = mod_ctx->kdc_offset; -+ } -+ -+} -+ -+struct kcm_ccdb_mod_cc_state { -+ struct kcm_ccdb *db; -+}; -+ -+static void kcm_ccdb_mod_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_mod_cc_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct kcm_mod_ctx *mod_cc) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_mod_cc_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_mod_cc_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ -+ if (ev == NULL || db == NULL || client == NULL || mod_cc == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = state->db->ops->mod_send(mem_ctx, -+ ev, -+ state->db, -+ client, -+ uuid, -+ mod_cc); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_mod_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_mod_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_mod_cc_state *state = tevent_req_data(req, -+ struct kcm_ccdb_mod_cc_state); -+ errno_t ret; -+ -+ ret = state->db->ops->mod_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to create ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_mod_cc_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+struct kcm_ccdb_store_cred_blob_state { -+ struct kcm_ccdb *db; -+}; -+ -+static void kcm_ccdb_store_cred_blob_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_store_cred_blob_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct sss_iobuf *cred_blob) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_store_cred_blob_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_store_cred_blob_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ -+ if (ev == NULL || db == NULL || client == NULL || cred_blob == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = state->db->ops->store_cred_send(mem_ctx, -+ ev, -+ state->db, -+ client, -+ uuid, -+ cred_blob); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_store_cred_blob_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_store_cred_blob_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_store_cred_blob_state *state = tevent_req_data(req, -+ struct kcm_ccdb_store_cred_blob_state); -+ errno_t ret; -+ -+ ret = state->db->ops->store_cred_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to create ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_store_cred_blob_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+struct kcm_ccdb_delete_cc_state { -+ struct tevent_context *ev; -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ uuid_t uuid; -+}; -+ -+static void kcm_ccdb_delete_done(struct tevent_req *subreq); -+static void kcm_ccdb_delete_get_default_done(struct tevent_req *subreq); -+static void kcm_ccdb_delete_default_reset_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_ccdb_delete_cc_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_ccdb_delete_cc_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_ccdb_delete_cc_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->db = db; -+ state->ev = ev; -+ state->client = client; -+ uuid_copy(state->uuid, uuid); -+ -+ if (ev == NULL || db == NULL || client == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = state->db->ops->delete_send(state, -+ state->ev, -+ state->db, -+ state->client, -+ state->uuid); -+ tevent_req_set_callback(subreq, kcm_ccdb_delete_done, req); -+ -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_ccdb_delete_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_delete_cc_state *state = tevent_req_data(req, -+ struct kcm_ccdb_delete_cc_state); -+ errno_t ret; -+ -+ ret = state->db->ops->delete_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to delete ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* The delete operation must also check if the deleted ccache was -+ * the default and reset the default if it was -+ */ -+ subreq = state->db->ops->get_default_send(state, -+ state->ev, -+ state->db, -+ state->client); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_delete_get_default_done, req); -+} -+ -+static void kcm_ccdb_delete_get_default_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_delete_cc_state *state = tevent_req_data(req, -+ struct kcm_ccdb_delete_cc_state); -+ errno_t ret; -+ uuid_t dfl_uuid; -+ uuid_t null_uuid; -+ -+ ret = state->db->ops->get_default_recv(subreq, dfl_uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get the default ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (uuid_compare(dfl_uuid, state->uuid) != 0) { -+ /* The ccache about to be deleted was not the default, quit */ -+ tevent_req_done(req); -+ return; -+ } -+ -+ /* If we deleted the default ccache, reset the default ccache to 'none' */ -+ uuid_clear(null_uuid); -+ -+ subreq = state->db->ops->set_default_send(state, -+ state->ev, -+ state->db, -+ state->client, -+ null_uuid); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_ccdb_delete_default_reset_done, req); -+} -+ -+static void kcm_ccdb_delete_default_reset_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_ccdb_delete_cc_state *state = tevent_req_data(req, -+ struct kcm_ccdb_delete_cc_state); -+ errno_t ret; -+ -+ ret = state->db->ops->set_default_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to NULL the default ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_ccdb_delete_cc_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+void kcm_debug_uuid(uuid_t uuid) -+{ -+ char dbgbuf[UUID_STR_SIZE]; -+ -+ if (!(debug_level & SSSDBG_TRACE_ALL) || uuid == NULL) { -+ return; -+ } -+ -+ uuid_unparse(uuid, dbgbuf); -+ DEBUG(SSSDBG_TRACE_ALL, "UUID: %s\n", dbgbuf); -+} -+ -+errno_t kcm_check_name(const char *name, struct cli_creds *client) -+{ -+ char prefix[64]; -+ size_t prefix_len; -+ -+ prefix_len = snprintf(prefix, sizeof(prefix), -+ "%"SPRIuid, cli_creds_get_uid(client)); -+ -+ if (strncmp(name, prefix, prefix_len) != 0) { -+ return ERR_KCM_WRONG_CCNAME_FORMAT; -+ } -+ return EOK; -+} -diff --git a/src/responder/kcm/kcmsrv_ccache.h b/src/responder/kcm/kcmsrv_ccache.h -new file mode 100644 -index 0000000000000000000000000000000000000000..130ae48ae30d5e1e2ab238a647a9b9dc76cc4945 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ccache.h -@@ -0,0 +1,306 @@ -+/* -+ SSSD -+ -+ KCM Server - the KCM ccache operations -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 . -+*/ -+#ifndef _KCMSRV_CCACHE_H_ -+#define _KCMSRV_CCACHE_H_ -+ -+#include "config.h" -+ -+#include -+#include -+ -+#include "util/util.h" -+#include "util/sss_iobuf.h" -+#include "util/util_creds.h" -+ -+#define UUID_BYTES 16 -+#define UUID_STR_SIZE 37 -+ -+/* -+ * Credentials are opaque to the KCM server -+ * -+ * Each ccache has a unique UUID. -+ */ -+struct kcm_cred; -+ -+/* -+ * An opaque ccache type and its operations -+ * -+ * Contains zero or some KCM credentials. One credential in the cache -+ * is marked as the default one. The client can set and get the default -+ * cache (e.g. with kswitch) but one cache is always the default -- we -+ * fall back to the one created first. -+ * -+ * Each cache has a name and a UUID. Heimdal allows the name to be changed, -+ * we don't (yet, because the MIT client doesn't allow that either) -+ * -+ * Each ccache also stores a client principal. -+ */ -+struct kcm_ccache; -+ -+/* -+ * Create a new KCM ccache owned by mem_ctx on the -+ * memory level. -+ * -+ * When created, the ccache contains no credendials -+ */ -+errno_t kcm_cc_new(TALLOC_CTX *mem_ctx, -+ krb5_context k5c, -+ struct cli_creds *owner, -+ const char *name, -+ krb5_principal princ, -+ struct kcm_ccache **_cc); -+ -+/* -+ * Returns true if a client can access a ccache. -+ * -+ * Note that root can access any ccache */ -+bool kcm_cc_access(struct kcm_ccache *cc, -+ struct cli_creds *client); -+ -+/* -+ * Since the kcm_ccache structure is opaque, the kcmsrv_ccache -+ * layer contains a number of getsetters to read and write -+ * properties of the kcm_ccache structure -+ */ -+const char *kcm_cc_get_name(struct kcm_ccache *cc); -+errno_t kcm_cc_get_uuid(struct kcm_ccache *cc, uuid_t _uuid); -+krb5_principal kcm_cc_get_client_principal(struct kcm_ccache *cc); -+int32_t kcm_cc_get_offset(struct kcm_ccache *cc); -+ -+/* Mainly useful for creating a cred structure from a persistent -+ * storage -+ */ -+struct kcm_cred *kcm_cred_new(TALLOC_CTX *mem_ctx, -+ uuid_t uuid, -+ struct sss_iobuf *cred_blob); -+ -+/* Add a cred to ccache */ -+errno_t kcm_cc_store_creds(struct kcm_ccache *cc, -+ struct kcm_cred *crd); -+ -+errno_t kcm_cred_get_uuid(struct kcm_cred *crd, uuid_t uuid); -+ -+/* -+ * At the moment, the credentials are stored without unmarshalling -+ * them, just as the clients sends the credentials. -+ */ -+struct sss_iobuf *kcm_cred_get_creds(struct kcm_cred *crd); -+errno_t kcm_cc_store_cred_blob(struct kcm_ccache *cc, -+ struct sss_iobuf *cred_blob); -+ /* -+ * The KCM server can call kcm_cred_get_creds to fetch the first -+ * credential, then iterate over the credentials with -+ * kcm_cc_next_cred until it returns NULL -+ */ -+struct kcm_cred *kcm_cc_get_cred(struct kcm_ccache *cc); -+struct kcm_cred *kcm_cc_next_cred(struct kcm_cred *crd); -+ -+enum kcm_ccdb_be { -+ CCDB_BE_MEMORY, -+ CCDB_BE_SECRETS, -+}; -+ -+/* An opaque database that contains all the ccaches */ -+struct kcm_ccdb; -+ -+/* -+ * Initialize a ccache database of type cc_be -+ */ -+struct kcm_ccdb *kcm_ccdb_init(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ enum kcm_ccdb_be cc_be); -+ -+/* -+ * In KCM, each ccache name is usually in the form of "UID: -+ * -+ * The is generated by the KCM ccache database. Use this function -+ * to retrieve the next number -+ */ -+struct tevent_req *kcm_ccdb_nextid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client); -+errno_t kcm_ccdb_nextid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ char **_nextid); -+ -+/* -+ * List all ccaches that belong to a given client -+ * -+ * The cc_list the recv function returns is NULL-terminated. -+ * -+ * NOTE: Contrary to how Heimdal behaves, root CAN NOT list all ccaches -+ * of all users. This is a deliberate decision to treat root as any other -+ * user, except it can access a ccache of another user by name, just not -+ * list them. -+ * -+ * If a client has no ccaches, the function returns OK, but an empty list -+ * containing just the NULL sentinel. -+ */ -+struct tevent_req *kcm_ccdb_list_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client); -+errno_t kcm_ccdb_list_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t **_uuid_list); -+ -+/* -+ * Retrieve a ccache by name. -+ * -+ * If there is no such ccache, return EOK, but a NULL _cc pointer -+ */ -+struct tevent_req *kcm_ccdb_getbyname_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name); -+errno_t kcm_ccdb_getbyname_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc); -+ -+/* -+ * Retrieve a ccache by UUID -+ * -+ * If there is no such ccache, return EOK, but a NULL _cc pointer -+ */ -+struct tevent_req *kcm_ccdb_getbyuuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+errno_t kcm_ccdb_getbyuuid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc); -+ -+/* -+ * Retrieve the default ccache. If there is no default cache, -+ * return EOK, but a NULL UUID. -+ */ -+struct tevent_req *kcm_ccdb_get_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client); -+errno_t kcm_ccdb_get_default_recv(struct tevent_req *req, -+ uuid_t *uuid); -+ -+/* -+ * Translating name to UUID is often considerably faster than doing a full -+ * CC retrieval, hence this function and the converse. If the UUID cannot -+ * be found in the database, return ERR_KCM_CC_END -+ */ -+struct tevent_req *kcm_ccdb_name_by_uuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+errno_t kcm_ccdb_name_by_uuid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ const char **_name); -+ -+/* -+ * Translating UUID to name is often considerably faster than doing a full -+ * CC retrieval, hence this function and the converse. If the UUID cannot -+ * be found in the database, return ERR_KCM_CC_END -+ */ -+struct tevent_req *kcm_ccdb_uuid_by_name_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name); -+errno_t kcm_ccdb_uuid_by_name_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t _uuid); -+ -+/* -+ * Set the default ccache. Passing a NULL UUID is a legal operation -+ * that 'unsets' the default ccache. -+ */ -+struct tevent_req *kcm_ccdb_set_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+errno_t kcm_ccdb_set_default_recv(struct tevent_req *req); -+ -+/* -+ * Add a ccache to the database. -+ */ -+struct tevent_req *kcm_ccdb_create_cc_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ struct kcm_ccache *cc); -+errno_t kcm_ccdb_create_cc_recv(struct tevent_req *req); -+ -+/* -+ * Modify cache properties in a db -+ */ -+struct kcm_mod_ctx { -+ int32_t kdc_offset; -+ /* More settable properties (like name, when we support renames -+ * will be added later -+ */ -+}; -+ -+void kcm_mod_ctx_clear(struct kcm_mod_ctx *mod_ctx); -+void kcm_mod_cc(struct kcm_ccache *cc, struct kcm_mod_ctx *mod_ctx); -+ -+struct tevent_req *kcm_ccdb_mod_cc_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct kcm_mod_ctx *mod_cc); -+errno_t kcm_ccdb_mod_cc_recv(struct tevent_req *req); -+ -+/* -+ * Store a credential in a cache -+ */ -+struct tevent_req *kcm_ccdb_store_cred_blob_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct sss_iobuf *cred_blob); -+errno_t kcm_ccdb_store_cred_blob_recv(struct tevent_req *req); -+ -+/* -+ * Delete a ccache from the database -+ */ -+struct tevent_req *kcm_ccdb_delete_cc_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+errno_t kcm_ccdb_delete_cc_recv(struct tevent_req *req); -+ -+void kcm_debug_uuid(uuid_t uuid); -+ -+/* -+ * The KCM clients are not allowed (except root) to create ccaches -+ * with arbitrary names. Instead, we assert that the ccache name -+ * begins with UID where UID is the stringified representation of -+ * the client's UID number -+ */ -+errno_t kcm_check_name(const char *name, struct cli_creds *client); -+ -+#endif /* _KCMSRV_CCACHE_H_ */ -diff --git a/src/responder/kcm/kcmsrv_ccache_be.h b/src/responder/kcm/kcmsrv_ccache_be.h -new file mode 100644 -index 0000000000000000000000000000000000000000..1bd2b6981e227675866e82e0a5389445cac4df66 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ccache_be.h -@@ -0,0 +1,204 @@ -+/* -+ SSSD -+ -+ KCM Server - the KCM ccache database interface -+ -+ This file should only be included from the ccache.c module. -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 . -+*/ -+ -+#ifndef _KCMSRV_CCACHE_BE_ -+#define _KCMSRV_CCACHE_BE_ -+ -+#include "config.h" -+ -+#include -+#include "responder/kcm/kcmsrv_ccache.h" -+ -+typedef errno_t -+(*ccdb_init_fn)(struct kcm_ccdb *db); -+ -+typedef struct tevent_req * -+(*ccdb_nextid_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client); -+typedef errno_t -+(*ccdb_nextid_recv_fn)(struct tevent_req *req, -+ unsigned int *_nextid); -+ -+typedef struct tevent_req * -+(*ccdb_set_default_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+typedef errno_t -+(*ccdb_set_default_recv_fn)(struct tevent_req *req); -+ -+typedef struct tevent_req * -+(*ccdb_get_default_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client); -+typedef errno_t -+(*ccdb_get_default_recv_fn)(struct tevent_req *req, -+ uuid_t dfl); -+ -+ -+typedef struct tevent_req * -+(*ccdb_list_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client); -+typedef errno_t -+(*ccdb_list_recv_fn)(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t **_uuid_list); -+ -+typedef struct tevent_req * -+(*ccdb_getbyname_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name); -+typedef errno_t -+(*ccdb_getbyname_recv_fn)(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc); -+ -+typedef struct tevent_req * -+(*ccdb_getbyuuid_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+typedef errno_t -+(*ccdb_getbyuuid_recv_fn)(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc); -+ -+typedef struct tevent_req * -+(*ccdb_name_by_uuid_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+typedef errno_t -+(*ccdb_name_by_uuid_recv_fn)(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ const char **_name); -+ -+typedef struct tevent_req * -+(*ccdb_uuid_by_name_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name); -+typedef errno_t -+(*ccdb_uuid_by_name_recv_fn)(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t _uuid); -+ -+typedef struct tevent_req * -+(*ccdb_create_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ struct kcm_ccache *cc); -+typedef errno_t -+(*ccdb_create_recv_fn)(struct tevent_req *req); -+ -+typedef struct tevent_req * -+(*ccdb_mod_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct kcm_mod_ctx *mod_cc); -+typedef errno_t -+(*ccdb_mod_recv_fn)(struct tevent_req *req); -+ -+typedef struct tevent_req * -+(*kcm_ccdb_store_cred_blob_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct sss_iobuf *cred_blob); -+typedef errno_t -+(*kcm_ccdb_store_cred_blob_recv_fn)(struct tevent_req *req); -+ -+typedef struct tevent_req * -+(*ccdb_delete_send_fn)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid); -+typedef errno_t -+(*ccdb_delete_recv_fn)(struct tevent_req *req); -+ -+/* -+ * Each ccache back end (for example memory or secrets) must implement -+ * all these functions. The functions are wrapped by the kcm_ccdb -+ * interface that performs additional sanity checks or contains shared -+ * logic such as access checks but in general doesn't assume anything -+ * about how the operations work. -+ */ -+struct kcm_ccdb_ops { -+ ccdb_init_fn init; -+ -+ ccdb_nextid_send_fn nextid_send; -+ ccdb_nextid_recv_fn nextid_recv; -+ -+ ccdb_set_default_send_fn set_default_send; -+ ccdb_set_default_recv_fn set_default_recv; -+ -+ ccdb_get_default_send_fn get_default_send; -+ ccdb_get_default_recv_fn get_default_recv; -+ -+ ccdb_list_send_fn list_send; -+ ccdb_list_recv_fn list_recv; -+ -+ ccdb_getbyname_send_fn getbyname_send; -+ ccdb_getbyname_recv_fn getbyname_recv; -+ -+ ccdb_getbyuuid_send_fn getbyuuid_send; -+ ccdb_getbyuuid_recv_fn getbyuuid_recv; -+ -+ ccdb_name_by_uuid_send_fn name_by_uuid_send; -+ ccdb_name_by_uuid_recv_fn name_by_uuid_recv; -+ -+ ccdb_uuid_by_name_send_fn uuid_by_name_send; -+ ccdb_uuid_by_name_recv_fn uuid_by_name_recv; -+ -+ ccdb_create_send_fn create_send; -+ ccdb_create_recv_fn create_recv; -+ -+ ccdb_mod_send_fn mod_send; -+ ccdb_mod_recv_fn mod_recv; -+ -+ kcm_ccdb_store_cred_blob_send_fn store_cred_send; -+ kcm_ccdb_store_cred_blob_recv_fn store_cred_recv; -+ -+ ccdb_delete_send_fn delete_send; -+ ccdb_delete_recv_fn delete_recv; -+}; -+ -+extern const struct kcm_ccdb_ops ccdb_mem_ops; -+ -+#endif /* _KCMSRV_CCACHE_BE_ */ -diff --git a/src/responder/kcm/kcmsrv_ccache_pvt.h b/src/responder/kcm/kcmsrv_ccache_pvt.h -new file mode 100644 -index 0000000000000000000000000000000000000000..0cc24c2b8cd4d44080d2aa4384f7b2a73520c5a0 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ccache_pvt.h -@@ -0,0 +1,62 @@ -+/* -+ SSSD -+ -+ KCM Server - the KCM ccache operations - private structures -+ -+ Should be accessed only from the ccache layer. -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 . -+*/ -+#ifndef _KCMSRV_CCACHE_PVT_H -+#define _KCMSRV_CCACHE_PVT_H -+ -+#include "responder/kcm/kcmsrv_ccache.h" -+#include "responder/kcm/kcmsrv_ccache_be.h" -+ -+struct kcm_ccache_owner { -+ uid_t uid; -+ gid_t gid; -+}; -+ -+struct kcm_cred { -+ struct sss_iobuf *cred_blob; -+ /* Randomly generated 16 bytes */ -+ uuid_t uuid; -+ -+ struct kcm_cred *next; -+ struct kcm_cred *prev; -+}; -+ -+struct kcm_ccdb { -+ enum kcm_ccdb_be cc_be_type; -+ struct tevent_context *ev; -+ -+ void *db_handle; -+ const struct kcm_ccdb_ops *ops; -+}; -+ -+struct kcm_ccache { -+ const char *name; -+ struct kcm_ccache_owner owner; -+ uuid_t uuid; -+ -+ krb5_principal client; -+ int32_t kdc_offset; -+ -+ struct kcm_cred *creds; -+}; -+ -+#endif /* _KCMSRV_CCACHE_PVT_H */ -diff --git a/src/responder/kcm/kcmsrv_pvt.h b/src/responder/kcm/kcmsrv_pvt.h -index fd1fd9fa32d59a323d465def68999f24f84e3923..a29680246c1e616da75e1bbff951ce2fad66fb65 100644 ---- a/src/responder/kcm/kcmsrv_pvt.h -+++ b/src/responder/kcm/kcmsrv_pvt.h -@@ -46,6 +46,7 @@ struct kcm_data { - */ - struct kcm_resp_ctx { - krb5_context k5c; -+ struct kcm_ccdb *db; - }; - - /* --- -2.12.2 - diff --git a/0027-KCM-Add-a-in-memory-credential-storage.patch b/0027-KCM-Add-a-in-memory-credential-storage.patch deleted file mode 100644 index b27d8f9..0000000 --- a/0027-KCM-Add-a-in-memory-credential-storage.patch +++ /dev/null @@ -1,907 +0,0 @@ -From 70fe6e2bb398b8669ad1aebeaf0abcbffc307475 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 7 Mar 2017 13:49:43 +0100 -Subject: [PATCH 27/97] KCM: Add a in-memory credential storage -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Implements a simple back end for the ccache module that lets the KCM -server store credentials directly in memory. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - Makefile.am | 1 + - src/responder/kcm/kcm.c | 13 +- - src/responder/kcm/kcmsrv_ccache.c | 2 +- - src/responder/kcm/kcmsrv_ccache_mem.c | 805 ++++++++++++++++++++++++++++++++++ - 4 files changed, 817 insertions(+), 4 deletions(-) - create mode 100644 src/responder/kcm/kcmsrv_ccache_mem.c - -diff --git a/Makefile.am b/Makefile.am -index a2b9dc49e95fa2d025f5174d2902866fab180a78..5605c1a53c44fd9e83394e80b7f71828df1d39b6 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1492,6 +1492,7 @@ sssd_kcm_SOURCES = \ - src/responder/kcm/kcm.c \ - src/responder/kcm/kcmsrv_cmd.c \ - src/responder/kcm/kcmsrv_ccache.c \ -+ src/responder/kcm/kcmsrv_ccache_mem.c \ - src/util/sss_sockets.c \ - src/util/sss_krb5.c \ - src/util/sss_iobuf.c \ -diff --git a/src/responder/kcm/kcm.c b/src/responder/kcm/kcm.c -index 90a6999c5e39d48a1a2ea8168d171612a65077d5..2c12ef215ce3967df183e51c20590c5f439d278f 100644 ---- a/src/responder/kcm/kcm.c -+++ b/src/responder/kcm/kcm.c -@@ -22,9 +22,9 @@ - #include "config.h" - - #include --#include - - #include "responder/kcm/kcm.h" -+#include "responder/kcm/kcmsrv_ccache.h" - #include "responder/kcm/kcmsrv_pvt.h" - #include "responder/common/responder.h" - #include "util/util.h" -@@ -110,7 +110,8 @@ static int kcm_data_destructor(void *ptr) - return 0; - } - --static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx) -+static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev) - { - struct kcm_resp_ctx *kcm_data; - krb5_error_code kret; -@@ -121,6 +122,12 @@ static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx) - return NULL; - } - -+ kcm_data->db = kcm_ccdb_init(kcm_data, ev, CCDB_BE_MEMORY); -+ if (kcm_data->db == NULL) { -+ talloc_free(kcm_data); -+ return NULL; -+ } -+ - kret = krb5_init_context(&kcm_data->k5c); - if (kret != EOK) { - talloc_free(kcm_data); -@@ -169,7 +176,7 @@ static int kcm_process_init(TALLOC_CTX *mem_ctx, - goto fail; - } - -- kctx->kcm_data = kcm_data_setup(kctx); -+ kctx->kcm_data = kcm_data_setup(kctx, ev); - if (kctx->kcm_data == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, - "fatal error initializing responder data\n"); -diff --git a/src/responder/kcm/kcmsrv_ccache.c b/src/responder/kcm/kcmsrv_ccache.c -index 2c565b8378e3ec297faf655d3c48d7ab902713d3..2ae120269b0c62275ba2acdff6d6daa8b7077708 100644 ---- a/src/responder/kcm/kcmsrv_ccache.c -+++ b/src/responder/kcm/kcmsrv_ccache.c -@@ -240,7 +240,7 @@ struct kcm_ccdb *kcm_ccdb_init(TALLOC_CTX *mem_ctx, - switch (cc_be) { - case CCDB_BE_MEMORY: - DEBUG(SSSDBG_FUNC_DATA, "KCM back end: memory\n"); -- /* Not implemented yet */ -+ ccdb->ops = &ccdb_mem_ops; - break; - case CCDB_BE_SECRETS: - DEBUG(SSSDBG_FUNC_DATA, "KCM back end: sssd-secrets\n"); -diff --git a/src/responder/kcm/kcmsrv_ccache_mem.c b/src/responder/kcm/kcmsrv_ccache_mem.c -new file mode 100644 -index 0000000000000000000000000000000000000000..1c4f3df8d3b35b0428a143d4b545562d9cc0e574 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ccache_mem.c -@@ -0,0 +1,805 @@ -+/* -+ SSSD -+ -+ KCM Server - ccache in-memory storage -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 -+ -+#include "util/util.h" -+#include "responder/kcm/kcmsrv_ccache_pvt.h" -+#include "responder/kcm/kcmsrv_ccache_be.h" -+ -+struct ccdb_mem; -+ -+/* -+ * The KCM memory database is just a double-linked list of kcm_ccache structures -+ */ -+struct ccache_mem_wrap { -+ struct kcm_ccache *cc; -+ bool is_default; -+ -+ struct ccache_mem_wrap *next; -+ struct ccache_mem_wrap *prev; -+ -+ struct ccdb_mem *mem_be; -+}; -+ -+struct ccdb_mem { -+ /* Both ccaches and the next-id are kept in memory */ -+ struct ccache_mem_wrap *head; -+ unsigned int nextid; -+}; -+ -+/* In order to provide a consistent interface, we need to let the caller -+ * of getbyXXX own the ccache, therefore the memory back end returns a shallow -+ * copy of the ccache -+ */ -+static struct kcm_ccache *kcm_ccache_dup(TALLOC_CTX *mem_ctx, -+ struct kcm_ccache *in) -+{ -+ struct kcm_ccache *out; -+ -+ out = talloc_zero(mem_ctx, struct kcm_ccache); -+ if (out == NULL) { -+ return NULL; -+ } -+ memcpy(out, in, sizeof(struct kcm_ccache)); -+ -+ return out; -+} -+ -+static struct ccache_mem_wrap *memdb_get_by_uuid(struct ccdb_mem *memdb, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ uid_t uid; -+ struct ccache_mem_wrap *ccwrap = NULL; -+ struct ccache_mem_wrap *out = NULL; -+ -+ uid = cli_creds_get_uid(client); -+ -+ DLIST_FOR_EACH(ccwrap, memdb->head) { -+ if (ccwrap->cc == NULL) { -+ /* since KCM stores ccaches, better not crash.. */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); -+ continue; -+ } -+ -+ if (ccwrap->cc->owner.uid == uid) { -+ if (uuid_compare(uuid, ccwrap->cc->uuid) == 0) { -+ out = ccwrap; -+ break; -+ } -+ } -+ } -+ -+ return out; -+} -+ -+static struct ccache_mem_wrap *memdb_get_by_name(struct ccdb_mem *memdb, -+ struct cli_creds *client, -+ const char *name) -+{ -+ uid_t uid; -+ struct ccache_mem_wrap *ccwrap = NULL; -+ struct ccache_mem_wrap *out = NULL; -+ -+ uid = cli_creds_get_uid(client); -+ -+ DLIST_FOR_EACH(ccwrap, memdb->head) { -+ if (ccwrap->cc == NULL) { -+ /* since KCM stores ccaches, better not crash.. */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); -+ continue; -+ } -+ -+ if (ccwrap->cc->owner.uid == uid) { -+ if (strcmp(ccwrap->cc->name, name) == 0) { -+ out = ccwrap; -+ break; -+ } -+ } -+ } -+ -+ return out; -+} -+ -+/* Since with the in-memory database, the database operations are just -+ * fake-async wrappers around otherwise sync operations, we don't often -+ * need any state, so we use this empty structure instead -+ */ -+struct ccdb_mem_dummy_state { -+}; -+ -+static int ccwrap_destructor(void *ptr) -+{ -+ struct ccache_mem_wrap *ccwrap = talloc_get_type(ptr, struct ccache_mem_wrap); -+ -+ if (ccwrap == NULL) { -+ return 0; -+ } -+ -+ if (ccwrap->cc != NULL) { -+ if (ccwrap->cc->creds) { -+ safezero(sss_iobuf_get_data(ccwrap->cc->creds->cred_blob), -+ sss_iobuf_get_size(ccwrap->cc->creds->cred_blob)); -+ } -+ } -+ -+ -+ DLIST_REMOVE(ccwrap->mem_be->head, ccwrap); -+ -+ return 0; -+} -+ -+static errno_t ccdb_mem_init(struct kcm_ccdb *db) -+{ -+ struct ccdb_mem *memdb = NULL; -+ -+ memdb = talloc_zero(db, struct ccdb_mem); -+ if (memdb == NULL) { -+ return ENOMEM; -+ } -+ db->db_handle = memdb; -+ -+ return EOK; -+} -+ -+struct ccdb_mem_nextid_state { -+ unsigned int nextid; -+}; -+ -+static struct tevent_req *ccdb_mem_nextid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_nextid_state *state = NULL; -+ struct ccdb_mem *memdb = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_nextid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ if (memdb == NULL) { -+ ret = EIO; -+ goto immediate; -+ } -+ -+ state->nextid = memdb->nextid++; -+ -+ ret = EOK; -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_nextid_recv(struct tevent_req *req, -+ unsigned int *_nextid) -+{ -+ struct ccdb_mem_nextid_state *state = tevent_req_data(req, -+ struct ccdb_mem_nextid_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_nextid = state->nextid; -+ return EOK; -+} -+ -+struct ccdb_mem_list_state { -+ uuid_t *uuid_list; -+}; -+ -+static struct tevent_req *ccdb_mem_list_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct ccache_mem_wrap *ccwrap = NULL; -+ struct ccdb_mem_list_state *state = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ size_t num_ccaches = 0; -+ size_t cc_index = 0; -+ errno_t ret; -+ uid_t uid; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_list_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ uid = cli_creds_get_uid(client); -+ -+ DLIST_FOR_EACH(ccwrap, memdb->head) { -+ if (ccwrap->cc->owner.uid == uid) { -+ num_ccaches++; -+ } -+ } -+ -+ state->uuid_list = talloc_zero_array(state, uuid_t, num_ccaches+1); -+ if (state->uuid_list == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ cc_index = 0; -+ DLIST_FOR_EACH(ccwrap, memdb->head) { -+ if (ccwrap->cc->owner.uid == uid) { -+ uuid_copy(state->uuid_list[cc_index], ccwrap->cc->uuid); -+ cc_index++; -+ } -+ } -+ uuid_clear(state->uuid_list[num_ccaches]); -+ -+ ret = EOK; -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_list_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t **_uuid_list) -+{ -+ struct ccdb_mem_list_state *state = tevent_req_data(req, -+ struct ccdb_mem_list_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_uuid_list = talloc_steal(mem_ctx, state->uuid_list); -+ return EOK; -+} -+ -+static struct tevent_req *ccdb_mem_set_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_dummy_state *state = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ struct ccache_mem_wrap *ccwrap = NULL; -+ uid_t uid = cli_creds_get_uid(client); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ /* Reset all ccache defaults first */ -+ DLIST_FOR_EACH(ccwrap, memdb->head) { -+ if (ccwrap->cc == NULL) { -+ /* since KCM stores ccaches, better not crash.. */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); -+ continue; -+ } -+ -+ if (ccwrap->cc->owner.uid == uid) { -+ ccwrap->is_default = false; -+ } -+ } -+ -+ /* Then set the default for the right ccache. This also allows to -+ * pass a null uuid to just reset the old ccache (for example after -+ * deleting the default -+ */ -+ ccwrap = memdb_get_by_uuid(memdb, client, uuid); -+ if (ccwrap != NULL) { -+ ccwrap->is_default = true; -+ } -+ -+ tevent_req_done(req); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_set_default_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+struct ccdb_mem_get_default_state { -+ uuid_t dfl_uuid; -+}; -+ -+static struct tevent_req *ccdb_mem_get_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_get_default_state *state = NULL; -+ struct ccache_mem_wrap *ccwrap = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ uid_t uid = cli_creds_get_uid(client); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_get_default_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ -+ /* Reset all ccache defaults first */ -+ DLIST_FOR_EACH(ccwrap, memdb->head) { -+ if (ccwrap->cc == NULL) { -+ /* since KCM stores ccaches, better not crash.. */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: ccwrap contains NULL cc\n"); -+ continue; -+ } -+ -+ if (ccwrap->cc->owner.uid == uid && ccwrap->is_default == true) { -+ break; -+ } -+ } -+ -+ if (ccwrap == NULL) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "No ccache marked as default, returning null ccache\n"); -+ uuid_clear(state->dfl_uuid); -+ } else { -+ uuid_copy(state->dfl_uuid, ccwrap->cc->uuid); -+ } -+ -+ tevent_req_done(req); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_get_default_recv(struct tevent_req *req, -+ uuid_t dfl) -+{ -+ struct ccdb_mem_get_default_state *state = tevent_req_data(req, -+ struct ccdb_mem_get_default_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ uuid_copy(dfl, state->dfl_uuid); -+ return EOK; -+} -+ -+struct ccdb_mem_getbyuuid_state { -+ struct kcm_ccache *cc; -+}; -+ -+static struct tevent_req *ccdb_mem_getbyuuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_getbyuuid_state *state = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ struct ccache_mem_wrap *ccwrap = NULL; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_getbyuuid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ ccwrap = memdb_get_by_uuid(memdb, client, uuid); -+ if (ccwrap != NULL) { -+ state->cc = kcm_ccache_dup(state, ccwrap->cc); -+ } -+ -+ tevent_req_done(req); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_getbyuuid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct ccdb_mem_getbyuuid_state *state = tevent_req_data(req, -+ struct ccdb_mem_getbyuuid_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+struct ccdb_mem_getbyname_state { -+ struct kcm_ccache *cc; -+}; -+ -+static struct tevent_req *ccdb_mem_getbyname_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_getbyname_state *state = NULL; -+ struct ccache_mem_wrap *ccwrap = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_getbyname_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ ccwrap = memdb_get_by_name(memdb, client, name); -+ if (ccwrap != NULL) { -+ state->cc = kcm_ccache_dup(state, ccwrap->cc); -+ } -+ -+ tevent_req_done(req); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_getbyname_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct ccdb_mem_getbyname_state *state = tevent_req_data(req, -+ struct ccdb_mem_getbyname_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+struct ccdb_mem_name_by_uuid_state { -+ const char *name; -+}; -+ -+struct tevent_req *ccdb_mem_name_by_uuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_name_by_uuid_state *state = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ struct ccache_mem_wrap *ccwrap = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_name_by_uuid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ ccwrap = memdb_get_by_uuid(memdb, client, uuid); -+ if (ccwrap == NULL) { -+ ret = ERR_KCM_CC_END; -+ goto immediate; -+ } -+ -+ state->name = talloc_strdup(state, ccwrap->cc->name); -+ if (state->name == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ ret = EOK; -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+errno_t ccdb_mem_name_by_uuid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ const char **_name) -+{ -+ struct ccdb_mem_name_by_uuid_state *state = tevent_req_data(req, -+ struct ccdb_mem_name_by_uuid_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_name = talloc_steal(mem_ctx, state->name); -+ return EOK; -+} -+ -+struct ccdb_mem_uuid_by_name_state { -+ uuid_t uuid; -+}; -+ -+struct tevent_req *ccdb_mem_uuid_by_name_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_uuid_by_name_state *state = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ struct ccache_mem_wrap *ccwrap = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_uuid_by_name_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ ccwrap = memdb_get_by_name(memdb, client, name); -+ if (ccwrap == NULL) { -+ ret = ERR_KCM_CC_END; -+ goto immediate; -+ } -+ -+ uuid_copy(state->uuid, ccwrap->cc->uuid); -+ -+ ret = EOK; -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+errno_t ccdb_mem_uuid_by_name_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t _uuid) -+{ -+ struct ccdb_mem_uuid_by_name_state *state = tevent_req_data(req, -+ struct ccdb_mem_uuid_by_name_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ uuid_copy(_uuid, state->uuid); -+ return EOK; -+} -+ -+static struct tevent_req *ccdb_mem_create_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ struct kcm_ccache *cc) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_dummy_state *state = NULL; -+ struct ccache_mem_wrap *ccwrap; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ ccwrap = talloc_zero(memdb, struct ccache_mem_wrap); -+ if (ccwrap == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ ccwrap->cc = cc; -+ ccwrap->mem_be = memdb; -+ talloc_steal(ccwrap, cc); -+ -+ DLIST_ADD(memdb->head, ccwrap); -+ talloc_set_destructor((TALLOC_CTX *) ccwrap, ccwrap_destructor); -+ -+ ret = EOK; -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_create_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+static struct tevent_req *ccdb_mem_mod_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct kcm_mod_ctx *mod_cc) -+{ -+ errno_t ret; -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_dummy_state *state = NULL; -+ struct ccache_mem_wrap *ccwrap = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ /* UUID is immutable, so search by that */ -+ ccwrap = memdb_get_by_uuid(memdb, client, uuid); -+ if (ccwrap == NULL) { -+ ret = ERR_KCM_CC_END; -+ goto immediate; -+ } -+ -+ kcm_mod_cc(ccwrap->cc, mod_cc); -+ -+ ret = EOK; -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_mod_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+static struct tevent_req *ccdb_mem_store_cred_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct sss_iobuf *cred_blob) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_dummy_state *state = NULL; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ struct ccache_mem_wrap *ccwrap = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ ccwrap = memdb_get_by_uuid(memdb, client, uuid); -+ if (ccwrap == NULL) { -+ ret = ERR_KCM_CC_END; -+ goto immediate; -+ } -+ -+ ret = kcm_cc_store_cred_blob(ccwrap->cc, cred_blob); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot store credentials to ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ ret = EOK; -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_store_cred_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+static struct tevent_req *ccdb_mem_delete_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_mem_dummy_state *state = NULL; -+ struct ccache_mem_wrap *ccwrap; -+ struct ccdb_mem *memdb = talloc_get_type(db->db_handle, struct ccdb_mem); -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_mem_dummy_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ ccwrap = memdb_get_by_uuid(memdb, client, uuid); -+ if (ccwrap == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "BUG: Attempting to free unknown ccache\n"); -+ ret = ERR_KCM_CC_END; -+ goto immediate; -+ } -+ -+ ret = EOK; -+ /* Destructor takes care of everything */ -+ talloc_free(ccwrap); -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_mem_delete_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+const struct kcm_ccdb_ops ccdb_mem_ops = { -+ .init = ccdb_mem_init, -+ -+ .nextid_send = ccdb_mem_nextid_send, -+ .nextid_recv = ccdb_mem_nextid_recv, -+ -+ .set_default_send = ccdb_mem_set_default_send, -+ .set_default_recv = ccdb_mem_set_default_recv, -+ -+ .get_default_send = ccdb_mem_get_default_send, -+ .get_default_recv = ccdb_mem_get_default_recv, -+ -+ .list_send = ccdb_mem_list_send, -+ .list_recv = ccdb_mem_list_recv, -+ -+ .getbyname_send = ccdb_mem_getbyname_send, -+ .getbyname_recv = ccdb_mem_getbyname_recv, -+ -+ .getbyuuid_send = ccdb_mem_getbyuuid_send, -+ .getbyuuid_recv = ccdb_mem_getbyuuid_recv, -+ -+ .name_by_uuid_send = ccdb_mem_name_by_uuid_send, -+ .name_by_uuid_recv = ccdb_mem_name_by_uuid_recv, -+ -+ .uuid_by_name_send = ccdb_mem_uuid_by_name_send, -+ .uuid_by_name_recv = ccdb_mem_uuid_by_name_recv, -+ -+ .create_send = ccdb_mem_create_send, -+ .create_recv = ccdb_mem_create_recv, -+ -+ .mod_send = ccdb_mem_mod_send, -+ .mod_recv = ccdb_mem_mod_recv, -+ -+ .store_cred_send = ccdb_mem_store_cred_send, -+ .store_cred_recv = ccdb_mem_store_cred_recv, -+ -+ .delete_send = ccdb_mem_delete_send, -+ .delete_recv = ccdb_mem_delete_recv, -+}; --- -2.12.2 - diff --git a/0028-KCM-Implement-KCM-server-operations.patch b/0028-KCM-Implement-KCM-server-operations.patch deleted file mode 100644 index 5fb8b1e..0000000 --- a/0028-KCM-Implement-KCM-server-operations.patch +++ /dev/null @@ -1,2326 +0,0 @@ -From 1ec4198f38d34a1f82a2db55d8c9782a434fb55f Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 23 Sep 2016 14:49:09 +0200 -Subject: [PATCH 28/97] KCM: Implement KCM server operations -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Implements the actual KCM server operations. On a high level, each -operation unmarhalls the needed data from the input buffer, calls into -the ccache db and marshalls a response. - -Only the operations that are also implemented by the MIT client are -implemented by our KCM server. - -Resolves: - https://pagure.io/SSSD/sssd/issue/2887 - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - Makefile.am | 2 + - src/responder/kcm/kcmsrv_cmd.c | 151 +++- - src/responder/kcm/kcmsrv_ops.c | 1954 ++++++++++++++++++++++++++++++++++++++++ - src/responder/kcm/kcmsrv_ops.h | 45 + - 4 files changed, 2143 insertions(+), 9 deletions(-) - create mode 100644 src/responder/kcm/kcmsrv_ops.c - create mode 100644 src/responder/kcm/kcmsrv_ops.h - -diff --git a/Makefile.am b/Makefile.am -index 5605c1a53c44fd9e83394e80b7f71828df1d39b6..49b4cabf9ee3ce1417f955c972376894f3709b33 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -714,6 +714,7 @@ dist_noinst_HEADERS = \ - src/responder/kcm/kcmsrv_ccache.h \ - src/responder/kcm/kcmsrv_ccache_pvt.h \ - src/responder/kcm/kcmsrv_ccache_be.h \ -+ src/responder/kcm/kcmsrv_ops.h \ - src/sbus/sbus_client.h \ - src/sbus/sssd_dbus.h \ - src/sbus/sssd_dbus_meta.h \ -@@ -1493,6 +1494,7 @@ sssd_kcm_SOURCES = \ - src/responder/kcm/kcmsrv_cmd.c \ - src/responder/kcm/kcmsrv_ccache.c \ - src/responder/kcm/kcmsrv_ccache_mem.c \ -+ src/responder/kcm/kcmsrv_ops.c \ - src/util/sss_sockets.c \ - src/util/sss_krb5.c \ - src/util/sss_iobuf.c \ -diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c -index cbf70353730d8a4e03d8f75c97395f4ef007e77f..537e88953fd1a190a9a73bcdd430d8e0db8f9291 100644 ---- a/src/responder/kcm/kcmsrv_cmd.c -+++ b/src/responder/kcm/kcmsrv_cmd.c -@@ -23,10 +23,10 @@ - - #include "config.h" - #include "util/util.h" --#include "util/sss_iobuf.h" - #include "responder/common/responder.h" - #include "responder/kcm/kcmsrv_pvt.h" - #include "responder/kcm/kcm.h" -+#include "responder/kcm/kcmsrv_ops.h" - - /* The first four bytes of a message is always the size */ - #define KCM_MSG_LEN_SIZE 4 -@@ -133,7 +133,6 @@ static errno_t kcm_input_parse(struct kcm_reqbuf *reqbuf, - { - size_t lc = 0; - size_t mc = 0; -- uint16_t opcode = 0; - uint16_t opcode_be = 0; - uint32_t len_be = 0; - uint32_t msglen; -@@ -162,7 +161,7 @@ static errno_t kcm_input_parse(struct kcm_reqbuf *reqbuf, - return EBADMSG; - } - -- /* First 16 bits are 8 bit major and 8bit major protocol version */ -+ /* First 16 bits are 8 bit major and 8bit minor protocol version */ - SAFEALIGN_COPY_UINT8_CHECK(&proto_maj, - reqbuf->v_msg.kiov_base + mc, - reqbuf->v_msg.kiov_len, -@@ -191,8 +190,16 @@ static errno_t kcm_input_parse(struct kcm_reqbuf *reqbuf, - reqbuf->v_msg.kiov_len, - &mc); - -- opcode = be16toh(opcode_be); -- DEBUG(SSSDBG_TRACE_LIBS, "Received operation code %"PRIu16"\n", opcode); -+ op_io->op = kcm_get_opt(be16toh(opcode_be)); -+ if (op_io->op == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Did not find a KCM operation handler for the requested opcode\n"); -+ return ERR_KCM_MALFORMED_IN_PKT; -+ } -+ -+ /* The operation only receives the payload, not the opcode or the protocol info */ -+ op_io->request.data = reqbuf->v_msg.kiov_base + mc; -+ op_io->request.length = reqbuf->v_msg.nprocessed - mc; - - return EOK; - } -@@ -240,6 +247,46 @@ static errno_t kcm_failbuf_construct(errno_t ret, - c = 0; - SAFEALIGN_SETMEM_UINT32(repbuf->rcbuf, htobe32(ret), &c); - -+ DEBUG(SSSDBG_TRACE_LIBS, "Sent reply with error %d\n", ret); -+ return EOK; -+} -+ -+/* retcode is 0 if the operation at least ran, non-zero if there -+ * was some kind of internal KCM error, like input couldn't be parsed -+ */ -+static errno_t kcm_output_construct(struct kcm_op_io *op_io, -+ struct kcm_repbuf *repbuf) -+{ -+ size_t c; -+ size_t replen; -+ -+ replen = sss_iobuf_get_len(op_io->reply); -+ if (replen > KCM_PACKET_MAX_SIZE) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Reply exceeds the KCM protocol limit, aborting\n"); -+ return E2BIG; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Sending a reply with %zu bytes of payload\n", replen); -+ c = 0; -+ SAFEALIGN_SETMEM_UINT32(repbuf->lenbuf, htobe32(replen), &c); -+ -+ c = 0; -+ SAFEALIGN_SETMEM_UINT32(repbuf->rcbuf, 0, &c); -+ -+ if (replen > 0) { -+ c = 0; -+ SAFEALIGN_MEMCPY_CHECK(repbuf->msgbuf, -+ sss_iobuf_get_data(op_io->reply), -+ replen, -+ repbuf->v_msg.kiov_len, -+ &c); -+ -+ /* Length of the buffer to send to KCM client */ -+ repbuf->v_msg.kiov_len = replen; -+ } -+ - return EOK; - } - -@@ -260,7 +307,8 @@ static void kcm_reply_error(struct cli_ctx *cctx, - - ret = kcm_failbuf_construct(kerr, repbuf); - if (ret != EOK) { -- /* If we can't construct the reply buffer, just terminate the client */ -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot construct the reply buffer, terminating client\n"); - talloc_free(cctx); - return; - } -@@ -268,6 +316,24 @@ static void kcm_reply_error(struct cli_ctx *cctx, - TEVENT_FD_WRITEABLE(cctx->cfde); - } - -+static void kcm_send_reply(struct cli_ctx *cctx, -+ struct kcm_op_io *op_io, -+ struct kcm_repbuf *repbuf) -+{ -+ errno_t ret; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Sending a reply\n"); -+ ret = kcm_output_construct(op_io, repbuf); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot construct the reply buffer, terminating client\n"); -+ kcm_reply_error(cctx, ret, repbuf); -+ return; -+ } -+ -+ TEVENT_FD_WRITEABLE(cctx->cfde); -+} -+ - /** - * Request-reply dispatcher - */ -@@ -285,17 +351,67 @@ struct kcm_req_ctx { - struct kcm_op_io op_io; - }; - -+static void kcm_cmd_request_done(struct tevent_req *req); -+ -+static errno_t kcm_cmd_dispatch(struct kcm_req_ctx *req_ctx) -+{ -+ struct tevent_req *req; -+ struct cli_ctx *cctx; -+ -+ cctx = req_ctx->cctx; -+ -+ req = kcm_cmd_send(req_ctx, cctx->ev, req_ctx->kctx->kcm_data, -+ req_ctx->cctx->creds, -+ &req_ctx->op_io.request, -+ req_ctx->op_io.op); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to schedule KCM operation.\n"); -+ return ENOMEM; -+ } -+ -+ tevent_req_set_callback(req, kcm_cmd_request_done, req_ctx); -+ return EOK; -+} -+ -+static void kcm_cmd_request_done(struct tevent_req *req) -+{ -+ struct kcm_req_ctx *req_ctx; -+ struct cli_ctx *cctx; -+ errno_t ret; -+ -+ req_ctx = tevent_req_callback_data(req, struct kcm_req_ctx); -+ cctx = req_ctx->cctx; -+ -+ ret = kcm_cmd_recv(req_ctx, req, -+ &req_ctx->op_io.reply); -+ talloc_free(req); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "KCM operation failed [%d]: %s\n", ret, sss_strerror(ret)); -+ kcm_reply_error(cctx, ret, &req_ctx->repbuf); -+ return; -+ } -+ -+ kcm_send_reply(cctx, &req_ctx->op_io, &req_ctx->repbuf); -+} -+ - static errno_t kcm_recv_data(int fd, struct kcm_reqbuf *reqbuf) - { - errno_t ret; - - ret = kcm_read_iovec(fd, &reqbuf->v_len); - if (ret != EOK) { -+ /* Not all errors are fatal, hence we don't print DEBUG messages -+ * here, but in the caller -+ */ - return ret; - } - - ret = kcm_read_iovec(fd, &reqbuf->v_msg); - if (ret != EOK) { -+ /* Not all errors are fatal, hence we don't print DEBUG messages -+ * here, but in the caller -+ */ - return ret; - } - -@@ -389,7 +505,15 @@ static void kcm_recv(struct cli_ctx *cctx) - /* do not read anymore, client is done sending */ - TEVENT_FD_NOT_READABLE(cctx->cfde); - -- kcm_reply_error(cctx, ret, &req->repbuf); -+ ret = kcm_cmd_dispatch(req); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Failed to dispatch KCM operation [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto fail; -+ } -+ -+ /* Dispatched request resumes in kcm_cmd_request_done */ - return; - - fail: -@@ -406,16 +530,25 @@ static int kcm_send_data(struct cli_ctx *cctx) - - ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_len); - if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to write the length iovec [%d]: %s\n", -+ ret, sss_strerror(ret)); - return ret; - } - - ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_rc); - if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to write the retcode iovec [%d]: %s\n", -+ ret, sss_strerror(ret)); - return ret; - } - - ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_msg); - if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to write the msg iovec [%d]: %s\n", -+ ret, sss_strerror(ret)); - return ret; - } - -@@ -428,7 +561,7 @@ static void kcm_send(struct cli_ctx *cctx) - - ret = kcm_send_data(cctx); - if (ret == EAGAIN) { -- /* not all data was sent, loop again */ -+ DEBUG(SSSDBG_TRACE_ALL, "Sending data again..\n"); - return; - } else if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n"); -@@ -436,7 +569,7 @@ static void kcm_send(struct cli_ctx *cctx) - return; - } - -- /* ok all sent */ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "All data sent!\n"); - TEVENT_FD_NOT_WRITEABLE(cctx->cfde); - TEVENT_FD_READABLE(cctx->cfde); - talloc_zfree(cctx->state_ctx); -diff --git a/src/responder/kcm/kcmsrv_ops.c b/src/responder/kcm/kcmsrv_ops.c -new file mode 100644 -index 0000000000000000000000000000000000000000..50e8cc635424e15d53e3c8d122c5525044f59c8a ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ops.c -@@ -0,0 +1,1954 @@ -+/* -+ SSSD -+ -+ KCM Server - the KCM server operations -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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/sss_iobuf.h" -+#include "util/sss_krb5.h" -+#include "util/util_creds.h" -+#include "responder/kcm/kcm.h" -+#include "responder/kcm/kcmsrv_pvt.h" -+#include "responder/kcm/kcmsrv_ops.h" -+#include "responder/kcm/kcmsrv_ccache.h" -+ -+#define KCM_REPLY_MAX 2048 -+ -+struct kcm_op_ctx { -+ struct kcm_resp_ctx *kcm_data; -+ struct cli_creds *client; -+ -+ struct sss_iobuf *input; -+ struct sss_iobuf *reply; -+}; -+ -+/* Each operation follows the same pattern and is implemented using -+ * functions with this prototype. The operation receives an op_ctx -+ * that serves as a state of the operation and can be used to keep -+ * track of any temporary data. The operation writes its output data -+ * into the op_ctx reply IO buffer and returns the op_ret status code -+ * separately. -+ * -+ * The operation always returns EOK unless an internal error occurs, -+ * the result of the operation is stored in the op_ret variable -+ */ -+typedef struct tevent_req* -+(*kcm_srv_send_method)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx); -+typedef errno_t -+(*kcm_srv_recv_method)(struct tevent_req *req, -+ uint32_t *_op_ret); -+ -+struct kcm_op { -+ const char *name; -+ kcm_srv_send_method fn_send; -+ kcm_srv_recv_method fn_recv; -+}; -+ -+struct kcm_cmd_state { -+ struct kcm_op *op; -+ -+ struct kcm_op_ctx *op_ctx; -+ struct sss_iobuf *reply; -+ -+ uint32_t op_ret; -+}; -+ -+static void kcm_cmd_done(struct tevent_req *subreq); -+ -+struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_resp_ctx *kcm_data, -+ struct cli_creds *client, -+ struct kcm_data *input, -+ struct kcm_op *op) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_cmd_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_cmd_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op = op; -+ -+ if (op == NULL) { -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "KCM operation %s\n", op->name); -+ DEBUG(SSSDBG_TRACE_LIBS, "%zu bytes on KCM input\n", input->length); -+ -+ state->reply = sss_iobuf_init_empty(state, -+ KCM_REPLY_MAX, -+ KCM_REPLY_MAX); -+ if (state->reply == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ if (op->fn_send == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "KCM op %s has no handler\n", kcm_opt_name(op)); -+ ret = ERR_KCM_OP_NOT_IMPLEMENTED; -+ goto immediate; -+ } -+ -+ /* Allocating op_ctx on the heap makes it possible for operations to use -+ * op_ctx as their temporary context and avoid tmp_ctx altogether -+ */ -+ state->op_ctx = talloc_zero(state, struct kcm_op_ctx); -+ if (state->op_ctx == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ state->op_ctx->kcm_data = kcm_data; -+ state->op_ctx->client = client; -+ -+ state->op_ctx->input = sss_iobuf_init_readonly(state->op_ctx, -+ input->data, -+ input->length); -+ if (state->op_ctx->input == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ /* -+ * The internal operation returns the opcode and the buffer separately. -+ * The KCM server reply to the client also always contains zero if the -+ * operation ran to completion, both are uint32_t. -+ * FIXME: -+ * Alternatively, we could extend iobuf API so that we can just pass -+ * the reply's buffer+sizeof(2*uint32_t) and avoid the useless allocations -+ */ -+ state->op_ctx->reply = sss_iobuf_init_empty( -+ state, -+ KCM_REPLY_MAX - 2*sizeof(uint32_t), -+ KCM_REPLY_MAX - 2*sizeof(uint32_t)); -+ if (state->reply == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ subreq = op->fn_send(state, ev, state->op_ctx); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_cmd_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_cmd_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct kcm_cmd_state *state = tevent_req_data(req, struct kcm_cmd_state); -+ errno_t ret; -+ krb5_error_code kerr; -+ -+ ret = state->op->fn_recv(subreq, &state->op_ret); -+ talloc_free(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "op receive function failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "KCM operation %s returned [%d]: %s\n", -+ kcm_opt_name(state->op), state->op_ret, sss_strerror(state->op_ret)); -+ -+ kerr = sss2krb5_error(state->op_ret); -+ -+ /* The first four bytes of the reply is the operation status code */ -+ ret = sss_iobuf_write_uint32(state->reply, htobe32(kerr)); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = sss_iobuf_write_len(state->reply, -+ sss_iobuf_get_data(state->op_ctx->reply), -+ sss_iobuf_get_len(state->op_ctx->reply)); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+errno_t kcm_cmd_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ struct sss_iobuf **_reply) -+{ -+ struct kcm_cmd_state *state = NULL; -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ state = tevent_req_data(req, struct kcm_cmd_state); -+ -+ *_reply = talloc_steal(mem_ctx, state->reply); -+ return EOK; -+} -+ -+/* ======= KCM operations ======= */ -+ -+/* Operations that don't return any extra information except for the op_ret -+ * can use this macro in the _recv function to avoid code duplication -+ */ -+#define KCM_OP_RET_FROM_TYPE(req, state_type, _op_ret_out) do { \ -+ state_type *state = NULL; \ -+ state = tevent_req_data(req, state_type); \ -+ TEVENT_REQ_RETURN_ON_ERROR(req); \ -+ *_op_ret_out = state->op_ret; \ -+ return EOK; \ -+} while(0); -+ -+struct kcm_op_common_state { -+ uint32_t op_ret; -+ struct kcm_op_ctx *op_ctx; -+ struct tevent_context *ev; -+}; -+ -+static errno_t kcm_op_common_recv(struct tevent_req *req, -+ uint32_t *_op_ret) -+{ -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_op_ret = state->op_ret; -+ return EOK; -+} -+ -+/* () -> (name) */ -+static void kcm_op_gen_new_done(struct tevent_req *subreq); -+ -+static struct tevent_req *kcm_op_gen_new_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ subreq = kcm_ccdb_nextid_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_gen_new_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_gen_new_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ char *newid; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ -+ ret = kcm_ccdb_nextid_recv(subreq, state, &newid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot generate a new ID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Generated a new ID %s\n", newid); -+ -+ ret = sss_iobuf_write_stringz(state->op_ctx->reply, newid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot write generated ID %d: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* (princ) -> () */ -+struct kcm_op_initialize_state { -+ uint32_t op_ret; -+ struct kcm_op_ctx *op_ctx; -+ struct tevent_context *ev; -+ -+ struct kcm_ccache *new_cc; -+ const char *name; -+ krb5_principal princ; -+}; -+ -+static void kcm_op_initialize_got_byname(struct tevent_req *subreq); -+static void kcm_op_initialize_cc_create_done(struct tevent_req *subreq); -+static void kcm_op_initialize_cc_delete_done(struct tevent_req *subreq); -+static void kcm_op_initialize_create_step(struct tevent_req *req); -+static void kcm_op_initialize_got_default(struct tevent_req *subreq); -+static void kcm_op_initialize_set_default_done(struct tevent_req *subreq); -+ -+static struct tevent_req *kcm_op_initialize_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_initialize_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_initialize_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ state->ev = ev; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &state->name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot read input name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Initializing ccache %s\n", state->name); -+ -+ ret = kcm_check_name(state->name, op_ctx->client); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Name %s is malformed [%d]: %s\n", -+ state->name, ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ ret = sss_krb5_unmarshal_princ(op_ctx, op_ctx->input, &state->princ); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot unmarshal principal [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ subreq = kcm_ccdb_getbyname_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ state->name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_initialize_got_byname, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_initialize_got_byname(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_initialize_state *state = tevent_req_data(req, -+ struct kcm_op_initialize_state); -+ bool ok; -+ uuid_t uuid; -+ -+ ret = kcm_ccdb_getbyname_recv(subreq, state, &state->new_cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccache by name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (state->new_cc != NULL) { -+ ok = kcm_cc_access(state->new_cc, state->op_ctx->client); -+ if (!ok) { -+ state->op_ret = EACCES; -+ tevent_req_done(req); -+ return; -+ } -+ -+ ret = kcm_cc_get_uuid(state->new_cc, uuid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get new ccache UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return; -+ } -+ -+ /* Nuke any previous cache and its contents during initialization */ -+ subreq = kcm_ccdb_delete_cc_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ uuid); -+ if (subreq == NULL) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_initialize_cc_delete_done, req); -+ return; -+ } -+ -+ kcm_op_initialize_create_step(req); -+} -+ -+static void kcm_op_initialize_cc_delete_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ errno_t ret; -+ -+ ret = kcm_ccdb_delete_cc_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot delete ccache from the db %d: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ kcm_op_initialize_create_step(req); -+} -+ -+static void kcm_op_initialize_create_step(struct tevent_req *req) -+{ -+ struct tevent_req *subreq; -+ struct kcm_op_initialize_state *state = tevent_req_data(req, -+ struct kcm_op_initialize_state); -+ errno_t ret; -+ -+ ret = kcm_cc_new(state->op_ctx, -+ state->op_ctx->kcm_data->k5c, -+ state->op_ctx->client, -+ state->name, -+ state->princ, -+ &state->new_cc); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot create new ccache %d: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = kcm_ccdb_create_cc_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ state->new_cc); -+ if (subreq == NULL) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_initialize_cc_create_done, req); -+} -+ -+static void kcm_op_initialize_cc_create_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_initialize_state *state = tevent_req_data(req, -+ struct kcm_op_initialize_state); -+ errno_t ret; -+ -+ ret = kcm_ccdb_create_cc_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot add ccache to db %d: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* If there was no previous default ccache, set this one as default */ -+ subreq = kcm_ccdb_get_default_send(state, state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client); -+ if (subreq == NULL) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_initialize_got_default, req); -+} -+ -+static void kcm_op_initialize_got_default(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_initialize_state *state = tevent_req_data(req, -+ struct kcm_op_initialize_state); -+ errno_t ret; -+ uuid_t dfl_uuid; -+ uuid_t old_dfl_uuid; -+ -+ ret = kcm_ccdb_get_default_recv(subreq, &old_dfl_uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get default ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (uuid_is_null(old_dfl_uuid) == false) { -+ /* If there was a previous default ccache, switch to the initialized -+ * one by default -+ */ -+ ret = kcm_cc_get_uuid(state->new_cc, dfl_uuid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get new ccache UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return; -+ } -+ -+ subreq = kcm_ccdb_set_default_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ dfl_uuid); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_initialize_set_default_done, req); -+ return; -+ } -+ -+ /* ENOENT, done */ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+static void kcm_op_initialize_set_default_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_initialize_state *state = tevent_req_data(req, -+ struct kcm_op_initialize_state); -+ errno_t ret; -+ -+ ret = kcm_ccdb_set_default_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot set default ccache %d: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+static errno_t kcm_op_initialize_recv(struct tevent_req *req, -+ uint32_t *_op_ret) -+{ -+ KCM_OP_RET_FROM_TYPE(req, struct kcm_op_initialize_state, _op_ret); -+} -+ -+/* (name) -> () */ -+static void kcm_op_destroy_getbyname_done(struct tevent_req *subreq); -+static void kcm_op_destroy_delete_done(struct tevent_req *subreq); -+ -+static struct tevent_req *kcm_op_destroy_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ state->ev = ev; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot unmarshall input name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Destroying credentials of %s\n", name); -+ -+ subreq = kcm_ccdb_uuid_by_name_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_destroy_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_destroy_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ uuid_t uuid; -+ -+ ret = kcm_ccdb_uuid_by_name_recv(subreq, state, uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get matching ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = kcm_ccdb_delete_cc_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ uuid); -+ if (subreq == NULL) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_destroy_delete_done, req); -+} -+ -+static void kcm_op_destroy_delete_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ -+ ret = kcm_ccdb_delete_cc_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot delete ccache from the db [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* (name, cred) -> () */ -+struct kcm_op_store_state { -+ uint32_t op_ret; -+ struct kcm_op_ctx *op_ctx; -+ struct tevent_context *ev; -+ -+ struct sss_iobuf *cred_blob; -+}; -+ -+static void kcm_op_store_getbyname_done(struct tevent_req *subreq); -+static void kcm_op_store_done(struct tevent_req *subreq); -+ -+static struct tevent_req *kcm_op_store_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_store_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ size_t creds_len; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_store_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ state->ev = ev; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot unmarshall input name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Storing credentials for %s\n", name); -+ -+ creds_len = sss_iobuf_get_size(op_ctx->input) - strlen(name) -1; -+ if (creds_len > KCM_REPLY_MAX) { -+ /* Protects against underflows and in general adds sanity */ -+ ret = E2BIG; -+ goto immediate; -+ } -+ -+ state->cred_blob = sss_iobuf_init_empty(state, -+ creds_len, -+ creds_len); -+ if (state->cred_blob == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ ret = sss_iobuf_read(op_ctx->input, -+ creds_len, -+ sss_iobuf_get_data(state->cred_blob), -+ NULL); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot unmarshall input cred blob [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ subreq = kcm_ccdb_uuid_by_name_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_store_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_store_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_store_state *state = tevent_req_data(req, -+ struct kcm_op_store_state); -+ uuid_t uuid; -+ -+ ret = kcm_ccdb_uuid_by_name_recv(subreq, state, uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccache by name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = kcm_ccdb_store_cred_blob_send(state, state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ uuid, -+ state->cred_blob); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_store_done, req); -+} -+ -+static void kcm_op_store_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_store_state *state = tevent_req_data(req, -+ struct kcm_op_store_state); -+ -+ ret = kcm_ccdb_store_cred_blob_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot store credentials [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+static errno_t kcm_op_store_recv(struct tevent_req *req, -+ uint32_t *_op_ret) -+{ -+ KCM_OP_RET_FROM_TYPE(req, struct kcm_op_store_state, _op_ret); -+} -+ -+/* (name) -> (princ) */ -+static void kcm_op_get_principal_getbyname_done(struct tevent_req *subreq); -+ -+static struct tevent_req *kcm_op_get_principal_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ goto immediate; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Requested principal %s\n", name); -+ -+ subreq = kcm_ccdb_getbyname_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_principal_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_get_principal_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct kcm_ccache *cc; -+ krb5_principal princ; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ -+ ret = kcm_ccdb_getbyname_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccache by name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (cc == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that name\n"); -+ state->op_ret = ERR_NO_MATCHING_CREDS; -+ tevent_req_done(req); -+ return; -+ } -+ -+ /* Marshall the principal to the reply */ -+ princ = kcm_cc_get_client_principal(cc); -+ if (princ == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Credentials with no principal?\n"); -+ tevent_req_error(req, EIO); -+ return; -+ } -+ -+ ret = sss_krb5_marshal_princ(princ, state->op_ctx->reply); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot marshall principal [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* (name) -> (uuid, ...) */ -+static void kcm_op_get_cred_uuid_getbyname_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+kcm_op_get_cred_uuid_list_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ goto immediate; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Returning UUID list for %s\n", name); -+ -+ subreq = kcm_ccdb_getbyname_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_cred_uuid_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_get_cred_uuid_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct kcm_ccache *cc; -+ struct kcm_cred *crd; -+ uuid_t uuid; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ -+ ret = kcm_ccdb_getbyname_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccache by name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (cc == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that UUID\n"); -+ state->op_ret = ERR_NO_CREDS; -+ tevent_req_done(req); -+ return; -+ } -+ -+ for (crd = kcm_cc_get_cred(cc); -+ crd != NULL; -+ crd = kcm_cc_next_cred(crd)) { -+ ret = kcm_cred_get_uuid(crd, uuid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "Credential has no UUID, skipping\n"); -+ continue; -+ } -+ -+ kcm_debug_uuid(uuid); -+ -+ ret = sss_iobuf_write_len(state->op_ctx->reply, -+ uuid, UUID_BYTES); -+ if (ret != EOK) { -+ char uuid_errbuf[UUID_STR_SIZE]; -+ uuid_parse(uuid_errbuf, uuid); -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot marshall UUID %s [%d]: %s\n", -+ uuid_errbuf, ret, sss_strerror(ret)); -+ continue; -+ } -+ } -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* (name, uuid) -> (cred) */ -+static void kcm_op_get_cred_by_uuid_getbyname_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+kcm_op_get_cred_by_uuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ goto immediate; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Returning creds by UUID for %s\n", name); -+ -+ subreq = kcm_ccdb_getbyname_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_cred_by_uuid_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_get_cred_by_uuid_getbyname_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ errno_t ret; -+ struct kcm_ccache *cc; -+ struct kcm_cred *crd; -+ uuid_t uuid_in; -+ uuid_t uuid; -+ struct sss_iobuf *cred_blob; -+ -+ ret = kcm_ccdb_getbyname_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccache by name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (cc == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that name\n"); -+ state->op_ret = ERR_NO_MATCHING_CREDS; -+ tevent_req_done(req); -+ return; -+ } -+ -+ ret = sss_iobuf_read_len(state->op_ctx->input, -+ UUID_BYTES, uuid_in); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot read input UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ for (crd = kcm_cc_get_cred(cc); -+ crd != NULL; -+ crd = kcm_cc_next_cred(crd)) { -+ ret = kcm_cred_get_uuid(crd, uuid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot get UUID from creds, skipping\n"); -+ continue; -+ } -+ -+ if (uuid_compare(uuid, uuid_in) == 0) { -+ break; -+ } -+ kcm_debug_uuid(uuid); -+ } -+ -+ if (crd == NULL) { -+ state->op_ret = ERR_KCM_CC_END; -+ DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that UUID\n"); -+ tevent_req_done(req); -+ return; -+ } -+ -+ cred_blob = kcm_cred_get_creds(crd); -+ if (cred_blob == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Credentials lack the creds blob\n"); -+ state->op_ret = ERR_NO_CREDS; -+ tevent_req_done(req); -+ return; -+ } -+ -+ ret = sss_iobuf_write_len(state->op_ctx->reply, -+ sss_iobuf_get_data(cred_blob), -+ sss_iobuf_get_size(cred_blob)); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot write ccache blob [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* (name, flags, credtag) -> () */ -+/* FIXME */ -+static struct tevent_req * -+kcm_op_remove_cred_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct kcm_op_common_state *state = NULL; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ state->op_ret = ERR_KCM_OP_NOT_IMPLEMENTED; -+ tevent_req_post(req, ev); -+ tevent_req_done(req); -+ return req; -+} -+ -+/* () -> (uuid, ...) */ -+static void kcm_op_get_cache_uuid_list_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+kcm_op_get_cache_uuid_list_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Returning full UUID list\n"); -+ -+ subreq = kcm_ccdb_list_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_cache_uuid_list_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_get_cache_uuid_list_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ errno_t ret; -+ uuid_t *uuid_list; -+ -+ ret = kcm_ccdb_list_recv(subreq, state, &uuid_list); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot list the ccache DB [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (uuid_list == NULL || uuid_list[0] == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "Nothing to list\n"); -+ state->op_ret = ERR_NO_MATCHING_CREDS; -+ tevent_req_done(req); -+ return; -+ } -+ -+ for (int i = 0; -+ uuid_is_null(uuid_list[i]) == false; -+ i++) { -+ kcm_debug_uuid(uuid_list[i]); -+ -+ ret = sss_iobuf_write_len(state->op_ctx->reply, -+ uuid_list[i], -+ UUID_BYTES); -+ if (ret != EOK) { -+ char uuid_errbuf[UUID_STR_SIZE]; -+ uuid_parse(uuid_errbuf, uuid_list[i]); -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot marshall UUID %s [%d]: %s\n", -+ uuid_errbuf, ret, sss_strerror(ret)); -+ tevent_req_done(req); -+ return; -+ } -+ } -+ -+ tevent_req_done(req); -+} -+ -+/* (uuid) -> (name) */ -+static void kcm_op_get_cache_by_uuid_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+kcm_op_get_cache_by_uuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ uuid_t uuid_in; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Retrieving cache by UUID\n"); -+ -+ ret = sss_iobuf_read_len(op_ctx->input, -+ UUID_BYTES, uuid_in); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot read input UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ kcm_debug_uuid(uuid_in); -+ -+ subreq = kcm_ccdb_getbyuuid_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ uuid_in); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_cache_by_uuid_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_get_cache_by_uuid_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct kcm_ccache *cc; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ const char *name; -+ -+ ret = kcm_ccdb_getbyuuid_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccahe by UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (cc == NULL) { -+ state->op_ret = ERR_KCM_CC_END; -+ tevent_req_done(req); -+ return; -+ } -+ -+ name = kcm_cc_get_name(cc); -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Found %s by UUID\n", name); -+ -+ ret = sss_iobuf_write_stringz(state->op_ctx->reply, -+ name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot write output name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* () -> (name) */ -+struct kcm_op_get_default_ccache_state { -+ uint32_t op_ret; -+ struct kcm_op_ctx *op_ctx; -+ struct tevent_context *ev; -+ -+ const char *name; -+}; -+ -+static void kcm_op_get_get_default_done(struct tevent_req *subreq); -+static void kcm_op_get_default_ccache_byuuid_done(struct tevent_req *subreq); -+static void kcm_op_get_default_ccache_list_done(struct tevent_req *subreq); -+static errno_t -+kcm_op_get_default_ccache_reply_step(struct kcm_op_get_default_ccache_state *state); -+ -+static struct tevent_req * -+kcm_op_get_default_ccache_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_get_default_ccache_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct kcm_op_get_default_ccache_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ state->ev = ev; -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Getting client's default ccache\n"); -+ -+ subreq = kcm_ccdb_get_default_send(state, ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_get_default_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_get_get_default_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct kcm_op_get_default_ccache_state *state = tevent_req_data(req, -+ struct kcm_op_get_default_ccache_state); -+ errno_t ret; -+ uuid_t dfl_uuid; -+ -+ ret = kcm_ccdb_get_default_recv(subreq, &dfl_uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get default ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (uuid_is_null(dfl_uuid) == true) { -+ /* No cache marked as default -- get an existing ccache for ID -+ * and treat the default as simply the first one -+ */ -+ subreq = kcm_ccdb_list_send(state, state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_default_ccache_list_done, req); -+ return; -+ } -+ -+ /* Existing default */ -+ subreq = kcm_ccdb_name_by_uuid_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ dfl_uuid); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_default_ccache_byuuid_done, req); -+ return; -+} -+ -+static void kcm_op_get_default_ccache_byuuid_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct kcm_op_get_default_ccache_state *state = tevent_req_data(req, -+ struct kcm_op_get_default_ccache_state); -+ errno_t ret; -+ -+ ret = kcm_ccdb_name_by_uuid_recv(subreq, state, &state->name); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccahe by UUID [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = kcm_op_get_default_ccache_reply_step(state); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static void kcm_op_get_default_ccache_list_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct kcm_op_get_default_ccache_state *state = tevent_req_data(req, -+ struct kcm_op_get_default_ccache_state); -+ errno_t ret; -+ uuid_t *uuid_list; -+ -+ ret = kcm_ccdb_list_recv(subreq, state, &uuid_list); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot list ccaches [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (uuid_list == NULL || uuid_is_null(uuid_list[0])) { -+ /* No cache at all, just send back a reply */ -+ ret = kcm_op_get_default_ccache_reply_step(state); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+ return; -+ } -+ -+ /* Otherwise resolve the first cache and use it as a default */ -+ subreq = kcm_ccdb_name_by_uuid_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ uuid_list[0]); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_default_ccache_byuuid_done, req); -+ return; -+} -+ -+static errno_t -+kcm_op_get_default_ccache_reply_step(struct kcm_op_get_default_ccache_state *state) -+{ -+ errno_t ret; -+ -+ if (state->name == NULL) { -+ state->name = talloc_asprintf(state, -+ "%"SPRIuid, -+ cli_creds_get_uid(state->op_ctx->client)); -+ if (state->name == NULL) { -+ return ENOMEM; -+ } -+ } -+ DEBUG(SSSDBG_TRACE_INTERNAL, "The default ccache is %s\n", state->name); -+ -+ ret = sss_iobuf_write_stringz(state->op_ctx->reply, state->name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot write output name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+static errno_t kcm_op_get_default_ccache_recv(struct tevent_req *req, -+ uint32_t *_op_ret) -+{ -+ KCM_OP_RET_FROM_TYPE(req, struct kcm_op_get_default_ccache_state, _op_ret); -+} -+ -+/* (name) -> () */ -+static void kcm_op_set_default_ccache_getbyname_done(struct tevent_req *subreq); -+static void kcm_op_set_default_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+kcm_op_set_default_ccache_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ state->ev = ev; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot read input name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Setting default ccache %s\n", name); -+ -+ subreq = kcm_ccdb_uuid_by_name_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_set_default_ccache_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_set_default_ccache_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ uuid_t dfl_uuid; -+ -+ ret = kcm_ccdb_uuid_by_name_recv(subreq, state, dfl_uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get ccache by name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = kcm_ccdb_set_default_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ dfl_uuid); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_set_default_done, req); -+ return; -+} -+ -+static void kcm_op_set_default_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ -+ ret = kcm_ccdb_set_default_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot set default ccache %d: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* (name) -> (offset) */ -+static void kcm_op_get_kdc_offset_getbyname_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+kcm_op_get_kdc_offset_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_common_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot read input name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Requested offset for principal %s\n", name); -+ -+ subreq = kcm_ccdb_getbyname_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_get_kdc_offset_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_get_kdc_offset_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct kcm_ccache *cc; -+ int32_t offset; -+ int32_t offset_be; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_common_state *state = tevent_req_data(req, -+ struct kcm_op_common_state); -+ -+ ret = kcm_ccdb_getbyname_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get matching ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (cc == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "No matching credentials\n"); -+ state->op_ret = ERR_NO_MATCHING_CREDS; -+ tevent_req_done(req); -+ return; -+ } -+ -+ offset = kcm_cc_get_offset(cc); -+ DEBUG(SSSDBG_TRACE_LIBS, "KDC offset: %"PRIu32"\n", offset); -+ -+ offset_be = htobe32(offset); -+ ret = sss_iobuf_write_int32(state->op_ctx->reply, offset_be); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot write KDC offset [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+/* (name, offset) -> () */ -+/* () -> (name) */ -+struct kcm_op_set_kdc_offset_state { -+ uint32_t op_ret; -+ struct kcm_op_ctx *op_ctx; -+ struct tevent_context *ev; -+}; -+ -+static void kcm_op_set_kdc_offset_getbyname_done(struct tevent_req *subreq); -+static void kcm_op_set_kdc_offset_mod_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+kcm_op_set_kdc_offset_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_op_ctx *op_ctx) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct kcm_op_set_kdc_offset_state *state = NULL; -+ errno_t ret; -+ const char *name; -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_set_kdc_offset_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->op_ctx = op_ctx; -+ state->ev = ev; -+ -+ ret = sss_iobuf_read_stringz(op_ctx->input, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot read input name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Setting offset for principal %s\n", name); -+ -+ subreq = kcm_ccdb_uuid_by_name_send(state, ev, -+ op_ctx->kcm_data->db, -+ op_ctx->client, -+ name); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, kcm_op_set_kdc_offset_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_op_set_kdc_offset_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct kcm_mod_ctx *mod_ctx; -+ int32_t offset_be; -+ uuid_t uuid; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_set_kdc_offset_state *state = tevent_req_data(req, -+ struct kcm_op_set_kdc_offset_state); -+ -+ ret = kcm_ccdb_uuid_by_name_recv(subreq, state, uuid); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get matching ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = sss_iobuf_read_int32(state->op_ctx->input, &offset_be); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot read KDC offset [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ mod_ctx = talloc(state, struct kcm_mod_ctx); -+ if (mod_ctx == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ kcm_mod_ctx_clear(mod_ctx); -+ mod_ctx->kdc_offset = be32toh(offset_be); -+ -+ subreq = kcm_ccdb_mod_cc_send(state, -+ state->ev, -+ state->op_ctx->kcm_data->db, -+ state->op_ctx->client, -+ uuid, -+ mod_ctx); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, kcm_op_set_kdc_offset_mod_done, req); -+} -+ -+static void kcm_op_set_kdc_offset_mod_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct kcm_op_set_kdc_offset_state *state = tevent_req_data(req, -+ struct kcm_op_set_kdc_offset_state); -+ -+ ret = kcm_ccdb_mod_cc_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot modify ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->op_ret = EOK; -+ tevent_req_done(req); -+} -+ -+static errno_t kcm_op_set_kdc_offset_recv(struct tevent_req *req, -+ uint32_t *_op_ret) -+{ -+ KCM_OP_RET_FROM_TYPE(req, struct kcm_op_set_kdc_offset_state, _op_ret); -+} -+ -+static struct kcm_op kcm_optable[] = { -+ { "NOOP", NULL, NULL }, -+ { "GET_NAME", NULL, NULL }, -+ { "RESOLVE", NULL, NULL }, -+ { "GEN_NEW", kcm_op_gen_new_send, NULL }, -+ { "INITIALIZE", kcm_op_initialize_send, kcm_op_initialize_recv }, -+ { "DESTROY", kcm_op_destroy_send, NULL }, -+ { "STORE", kcm_op_store_send, kcm_op_store_recv }, -+ { "RETRIEVE", NULL, NULL }, -+ { "GET_PRINCIPAL", kcm_op_get_principal_send, NULL }, -+ { "GET_CRED_UUID_LIST", kcm_op_get_cred_uuid_list_send, NULL }, -+ { "GET_CRED_BY_UUID", kcm_op_get_cred_by_uuid_send, NULL }, -+ { "REMOVE_CRED", kcm_op_remove_cred_send, NULL }, -+ { "SET_FLAGS", NULL, NULL }, -+ { "CHOWN", NULL, NULL }, -+ { "CHMOD", NULL, NULL }, -+ { "GET_INITIAL_TICKET", NULL, NULL }, -+ { "GET_TICKET", NULL, NULL }, -+ { "MOVE_CACHE", NULL, NULL }, -+ { "GET_CACHE_UUID_LIST", kcm_op_get_cache_uuid_list_send, NULL }, -+ { "GET_CACHE_BY_UUID", kcm_op_get_cache_by_uuid_send, NULL }, -+ { "GET_DEFAULT_CACHE", kcm_op_get_default_ccache_send, kcm_op_get_default_ccache_recv }, -+ { "SET_DEFAULT_CACHE", kcm_op_set_default_ccache_send, NULL }, -+ { "GET_KDC_OFFSET", kcm_op_get_kdc_offset_send, NULL }, -+ { "SET_KDC_OFFSET", kcm_op_set_kdc_offset_send, kcm_op_set_kdc_offset_recv }, -+ { "ADD_NTLM_CRED", NULL, NULL }, -+ { "HAVE_NTLM_CRED", NULL, NULL }, -+ { "DEL_NTLM_CRED", NULL, NULL }, -+ { "DO_NTLM_AUTH", NULL, NULL }, -+ { "GET_NTLM_USER_LIST", NULL, NULL }, -+ -+ { NULL, NULL, NULL } -+}; -+ -+struct kcm_op *kcm_get_opt(uint16_t opcode) -+{ -+ struct kcm_op *op; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "The client requested operation %"PRIu16"\n", opcode); -+ -+ if (opcode >= KCM_OP_SENTINEL) { -+ return NULL; -+ } -+ -+ op = &kcm_optable[opcode]; -+ if (op->fn_recv == NULL) { -+ op->fn_recv = kcm_op_common_recv; -+ } -+ return op; -+} -+ -+const char *kcm_opt_name(struct kcm_op *op) -+{ -+ if (op == NULL || op->name == NULL) { -+ return "Unknown operation"; -+ } -+ -+ return op->name; -+} -diff --git a/src/responder/kcm/kcmsrv_ops.h b/src/responder/kcm/kcmsrv_ops.h -new file mode 100644 -index 0000000000000000000000000000000000000000..8e6feaf56a10b73c8b6375aea9ef26c392b5b492 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ops.h -@@ -0,0 +1,45 @@ -+/* -+ SSSD -+ -+ KCM Server - private header file -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 . -+*/ -+ -+#ifndef __KCMSRV_OPS_H__ -+#define __KCMSRV_OPS_H__ -+ -+#include "config.h" -+ -+#include -+#include "util/sss_iobuf.h" -+#include "responder/kcm/kcmsrv_pvt.h" -+ -+struct kcm_op; -+struct kcm_op *kcm_get_opt(uint16_t opcode); -+const char *kcm_opt_name(struct kcm_op *op); -+ -+struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_resp_ctx *kcm_data, -+ struct cli_creds *client, -+ struct kcm_data *input, -+ struct kcm_op *op); -+errno_t kcm_cmd_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ struct sss_iobuf **_reply); -+ -+#endif /* __KCMSRV_OPS_H__ */ --- -2.12.2 - diff --git a/0029-MAN-Add-a-manual-page-for-sssd-kcm.patch b/0029-MAN-Add-a-manual-page-for-sssd-kcm.patch deleted file mode 100644 index 090658b..0000000 --- a/0029-MAN-Add-a-manual-page-for-sssd-kcm.patch +++ /dev/null @@ -1,278 +0,0 @@ -From ba89271f594e5ed381b4dcb876a2d2787cf51902 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 8 Mar 2017 17:46:09 +0100 -Subject: [PATCH 29/97] MAN: Add a manual page for sssd-kcm -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - contrib/sssd.spec.in | 1 + - src/man/Makefile.am | 9 ++- - src/man/po/po4a.cfg | 1 + - src/man/sssd-kcm.8.xml | 193 +++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 203 insertions(+), 1 deletion(-) - create mode 100644 src/man/sssd-kcm.8.xml - -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 52d33b4de281dc1d91a9027ac1c8c878e66fb396..1d4d020415ee28292bb4d88c78de205465d812f1 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -1206,6 +1206,7 @@ done - %config(noreplace) %{_sysconfdir}/krb5.conf.d/kcm_default_ccache - %{_unitdir}/sssd-kcm.socket - %{_unitdir}/sssd-kcm.service -+%{_mandir}/man8/sssd-kcm.8* - %endif - - %pre common -diff --git a/src/man/Makefile.am b/src/man/Makefile.am -index 142d6e2743f814294e3d92c8342070b8230bb3e5..3a063614f085691652db32d76315375466e0d3de 100644 ---- a/src/man/Makefile.am -+++ b/src/man/Makefile.am -@@ -27,6 +27,9 @@ endif - if BUILD_SECRETS - SEC_CONDS = ;with_secrets - endif -+if BUILD_SECRETS -+KCM_CONDS = ;with_kcm -+endif - if GPO_DEFAULT_ENFORCING - GPO_CONDS = ;gpo_default_enforcing - else -@@ -40,7 +43,7 @@ FILES_CONDS = ;enable_files_domain - else - FILES_CONDS = ;no_enable_files_domain - endif --CONDS = with_false$(SUDO_CONDS)$(AUTOFS_CONDS)$(SSH_CONDS)$(PAC_RESPONDER_CONDS)$(IFP_CONDS)$(GPO_CONDS)$(SEC_CONDS)$(SYSTEMD_CONDS)$(FILES_CONDS) -+CONDS = with_false$(SUDO_CONDS)$(AUTOFS_CONDS)$(SSH_CONDS)$(PAC_RESPONDER_CONDS)$(IFP_CONDS)$(GPO_CONDS)$(SEC_CONDS)$(SYSTEMD_CONDS)$(FILES_CONDS)$(KCM_CONDS) - - - #Special Rules: -@@ -85,6 +88,10 @@ if BUILD_SECRETS - man_MANS += sssd-secrets.5 - endif - -+if BUILD_KCM -+man_MANS += sssd-kcm.8 -+endif -+ - if BUILD_NFS_IDMAP - man_MANS += sss_rpcidmapd.5 - endif -diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg -index d1f6ac39f841c61ae3d2393fb3402dc21b9cbd69..a02f97e777fa76615e4d5cbcfc788956706d8cd0 100644 ---- a/src/man/po/po4a.cfg -+++ b/src/man/po/po4a.cfg -@@ -31,6 +31,7 @@ - [type:docbook] sssctl.8.xml $lang:$(builddir)/$lang/sssctl.8.xml - [type:docbook] sssd-files.5.xml $lang:$(builddir)/$lang/sssd-files.5.xml - [type:docbook] sssd-secrets.5.xml $lang:$(builddir)/$lang/sssd-secrets.5.xml -+[type:docbook] sssd-kcm.8.xml $lang:$(builddir)/$lang/sssd-kcm.8.xml - [type:docbook] include/service_discovery.xml $lang:$(builddir)/$lang/include/service_discovery.xml opt:"-k 0" - [type:docbook] include/upstream.xml $lang:$(builddir)/$lang/include/upstream.xml opt:"-k 0" - [type:docbook] include/failover.xml $lang:$(builddir)/$lang/include/failover.xml opt:"-k 0" -diff --git a/src/man/sssd-kcm.8.xml b/src/man/sssd-kcm.8.xml -new file mode 100644 -index 0000000000000000000000000000000000000000..5dc93838e48723bdb470c0a9c8575bd17c7593e8 ---- /dev/null -+++ b/src/man/sssd-kcm.8.xml -@@ -0,0 +1,193 @@ -+ -+ -+ -+SSSD Manual pages -+ -+ -+ -+ -+ sssd-kcm -+ 8 -+ File Formats and Conventions -+ -+ -+ -+ sssd-kcm -+ SSSD Kerberos Cache Manager -+ -+ -+ -+ DESCRIPTION -+ -+ This manual page describes the configuration of the SSSD Kerberos -+ Cache Manager (KCM). KCM is a process that stores, tracks and -+ manages Kerberos credential caches. It originates in the Heimdal -+ Kerberos project, although the MIT Kerberos library also provides -+ client side (more details on that below) support for the KCM -+ credential cache. -+ -+ -+ In a setup where Kerberos caches are managed by KCM, the -+ Kerberos library (typically used through an application, like -+ e.g., -+ -+ kinit1 -+ , -+ is a "KCM client" and the KCM daemon -+ is being referred to as a "KCM server". The client -+ and server communicate over a UNIX socket. -+ -+ -+ The KCM server keeps track of each credential caches's owner and -+ performs access check control based on the UID and GID of the -+ KCM client. The root user has access to all credential caches. -+ -+ -+ The KCM credential cache has several interesting properties: -+ -+ -+ -+ since the process runs in userspace, it is subject to UID namespacing, ulike the kernel keyring -+ -+ -+ -+ -+ unlike the kernel keyring-based cache, which is shared between all containers, the KCM server is a separate process whose entry point is a UNIX socket -+ -+ -+ -+ -+ the SSSD implementation stores the ccaches in the SSSD -+ -+ sssd-secrets5 -+ -+ secrets store, allowing the ccaches to survive KCM server restarts or machine reboots. -+ -+ -+ -+ This allows the system to use a collection-aware credential -+ cache, yet share the credential cache between some or no -+ containers by bind-mounting the socket. -+ -+ -+ -+ -+ USING THE KCM CREDENTIAL CACHE -+ -+ In order to use KCM credential cache, it must be selected as the default -+ credential type in -+ -+ krb5.conf5 -+ , -+ The credentials cache name must be only KCM: -+ without any template expansions. For example: -+ -+[libdefaults] -+ default_ccache_name = KCM: -+ -+ -+ -+ Next, make sure the Kerberos client libraries and the KCM server must agree -+ on the UNIX socket path. By default, both use the same path -+ /var/run/.heim_org.h5l.kcm-socket. To configure -+ the Kerberos library, change its kcm_socket option which -+ is described in the -+ -+ krb5.conf5 -+ -+ manual page. -+ -+ -+ Finally, make sure the SSSD KCM server can be contacted. -+ The KCM service is typically socket-activated by -+ -+ systemd -+ 1 -+ . -+ Unlike -+ other SSSD services, it cannot be started by adding the -+ kcm string to the service -+ directive. -+ -+systemctl start sssd-kcm.socket -+systemctl enable sssd-kcm.socket -+systemctl enable sssd-kcm.service -+ -+ Please note your distribution may already configure the units -+ for you. -+ -+ -+ -+ -+ THE CREDENTIAL CACHE STORAGE -+ -+ The credential caches are stored in the SSSD secrets service (see -+ -+ sssd-secrets5 -+ -+ for more details). Therefore it is important that also the sssd-secrets -+ service is enabled and its socket is started: -+ -+systemctl start sssd-secrets.socket -+systemctl enable sssd-secrets.socket -+systemctl enable sssd-secrets.service -+ -+ Your distribution should already set the dependencies between the services. -+ -+ -+ -+ -+ CONFIGURATION OPTIONS -+ -+ The KCM service is configured in the kcm -+ section of the sssd.conf file. Please note that currently, -+ is it not sufficient to restart the sssd-kcm service, because -+ the sssd configuration is only parsed and read to an internal -+ configuration database by the sssd service. Therefore you -+ must restart the sssd service if you change anything in the -+ kcm section of sssd.conf. -+ For a detailed syntax reference, refer to the FILE FORMAT section of the -+ -+ sssd.conf -+ 5 -+ manual page. -+ -+ -+ The generic SSSD service options such as -+ debug_level or fd_limit are -+ accepted by the kcm service. Please refer to the -+ -+ sssd.conf -+ 5 -+ manual page for a complete list. In addition, -+ there are some KCM-specific options as well. -+ -+ -+ -+ socket_path (string) -+ -+ -+ The socket the KCM service will listen on. -+ -+ -+ Default: /var/run/.heim_org.h5l.kcm-socket -+ -+ -+ -+ -+ -+ -+ -+ SEE ALSO -+ -+ -+ sssd8 -+ , -+ -+ sssd.conf5 -+ , -+ -+ -+ -+ --- -2.12.2 - diff --git a/0030-TESTS-Add-integration-tests-for-the-KCM-responder.patch b/0030-TESTS-Add-integration-tests-for-the-KCM-responder.patch deleted file mode 100644 index 4d089c9..0000000 --- a/0030-TESTS-Add-integration-tests-for-the-KCM-responder.patch +++ /dev/null @@ -1,799 +0,0 @@ -From 0700118d8388c38b8cb28279510b206b76a3a411 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 13 Dec 2016 17:17:16 +0100 -Subject: [PATCH 30/97] TESTS: Add integration tests for the KCM responder -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce -Reviewed-by: Lukáš Slebodník ---- - contrib/ci/configure.sh | 7 + - contrib/ci/deps.sh | 6 + - src/tests/intg/Makefile.am | 4 + - src/tests/intg/kdc.py | 175 +++++++++++++++++++++ - src/tests/intg/krb5utils.py | 156 +++++++++++++++++++ - src/tests/intg/test_kcm.py | 361 ++++++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 709 insertions(+) - create mode 100644 src/tests/intg/kdc.py - create mode 100644 src/tests/intg/krb5utils.py - create mode 100644 src/tests/intg/test_kcm.py - -diff --git a/contrib/ci/configure.sh b/contrib/ci/configure.sh -index 8e779cfe634a7555e0e8e3b52f42c07e62980fbc..7590743c2aa5fe31bcdf1a3e92a3f482dbec699b 100644 ---- a/contrib/ci/configure.sh -+++ b/contrib/ci/configure.sh -@@ -38,6 +38,13 @@ if [[ "$DISTRO_BRANCH" == -redhat-redhatenterprise*-6.*- || - "--disable-cifs-idmap-plugin" - "--with-syslog=syslog" - "--without-python3-bindings" -+ "--without-kcm" -+ ) -+fi -+ -+if [[ "$DISTRO_BRANCH" == -redhat-fedora-2[0-2]* ]]; then -+ CONFIGURE_ARG_LIST+=( -+ "--without-kcm" - ) - fi - -diff --git a/contrib/ci/deps.sh b/contrib/ci/deps.sh -index c525e62e8c1d5b9fa042dee4ad03790dbceba242..4467e117c3a896a7f01ef7cb9e94fe28c2ea2838 100644 ---- a/contrib/ci/deps.sh -+++ b/contrib/ci/deps.sh -@@ -47,6 +47,8 @@ if [[ "$DISTRO_BRANCH" == -redhat-* ]]; then - uid_wrapper - python-requests - curl-devel -+ krb5-server -+ krb5-workstation - ) - _DEPS_LIST_SPEC=` - sed -e 's/@PACKAGE_VERSION@/0/g' \ -@@ -122,6 +124,10 @@ if [[ "$DISTRO_BRANCH" == -debian-* ]]; then - libhttp-parser-dev - libjansson-dev - libcurl4-openssl-dev -+ krb5-kdc -+ krb5-admin-server -+ krb5-user -+ uuid-dev - ) - DEPS_INTGCHECK_SATISFIED=true - fi -diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am -index 1d36fa0d2d50307fbc871f5b2a6f0cb1cc95db81..8526beace09b15c99aa27ac98d5038d1980f6a71 100644 ---- a/src/tests/intg/Makefile.am -+++ b/src/tests/intg/Makefile.am -@@ -26,6 +26,9 @@ dist_noinst_DATA = \ - files_ops.py \ - test_files_ops.py \ - test_files_provider.py \ -+ kdc.py \ -+ krb5utils.py \ -+ test_kcm.py \ - $(NULL) - - config.py: config.py.m4 -@@ -80,5 +83,6 @@ intgcheck-installed: config.py passwd group - NSS_WRAPPER_MODULE_FN_PREFIX="sss" \ - UID_WRAPPER=1 \ - UID_WRAPPER_ROOT=1 \ -+ NON_WRAPPED_UID=$$(echo $$UID) \ - fakeroot $(PYTHON2) $(PYTEST) -v --tb=native $(INTGCHECK_PYTEST_ARGS) . - rm -f $(DESTDIR)$(logpath)/* -diff --git a/src/tests/intg/kdc.py b/src/tests/intg/kdc.py -new file mode 100644 -index 0000000000000000000000000000000000000000..dec33a979916c0979561afb22dc39d6eb8894ff3 ---- /dev/null -+++ b/src/tests/intg/kdc.py -@@ -0,0 +1,175 @@ -+# -+# MIT Kerberos server class -+# -+# Copyright (c) 2016 Red Hat, Inc. -+# -+# This 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; version 2 only -+# -+# 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 . -+# -+import os -+import signal -+import shutil -+import subprocess -+ -+from util import * -+ -+ -+class KDC(object): -+ """ -+ MIT Kerberos KDC instance -+ """ -+ -+ def __init__(self, basedir, realm, -+ includedir=None, -+ kdc_port=10088, -+ kadmin_port=10749, -+ master_key='master'): -+ self.basedir = basedir -+ self.realm = realm -+ self.kdc_port = kdc_port -+ self.kadmin_port = kadmin_port -+ self.master_key = master_key -+ -+ self.kdc_basedir = self.basedir + "/var/krb5kdc" -+ self.includedir = includedir or (self.kdc_basedir + "/include") -+ self.kdc_logdir = self.kdc_basedir + "/log" -+ self.kdc_conf_path = self.kdc_basedir + "/kdc.conf" -+ self.krb5_conf_path = self.kdc_basedir + "/krb5.conf" -+ -+ self.kdc_pid_file = self.kdc_basedir + "/kdc.pid" -+ -+ self.acl_file = self.kdc_basedir + "/kadm5.acl" -+ -+ self.admin_princ = "admin/admin@" + self.realm -+ -+ def start_kdc(self, extra_args=[]): -+ args = ["krb5kdc", '-P', self.kdc_pid_file] + extra_args -+ return self._run_in_env(args, self.get_krb5_env()) -+ -+ def stop_kdc(self): -+ try: -+ with open(self.kdc_pid_file, "r") as pid_file: -+ os.kill(int(pid_file.read()), signal.SIGTERM) -+ except IOError as ioex: -+ if ioex.errno == 2: -+ pass -+ else: -+ raise ioex -+ -+ def teardown(self): -+ self.stop_kdc() -+ shutil.rmtree(self.kdc_basedir) -+ -+ def set_up(self): -+ self._create_config() -+ self._create_acl() -+ self._create_kdb() -+ -+ def get_krb5_env(self): -+ my_env = os.environ -+ my_env['KRB5_CONFIG'] = self.krb5_conf_path -+ my_env['KRB5_KDC_PROFILE'] = self.kdc_conf_path -+ return my_env -+ -+ def add_config(self, include_files): -+ for name, contents in include_files.items(): -+ include_fpath = os.path.join(self.includedir, name) -+ with open(include_fpath, 'w') as include_file: -+ include_file.write(contents) -+ -+ def add_principal(self, princ, password=None): -+ args = ["kadmin.local", "-q"] -+ if password is None: -+ args += ["addprinc -randkey %s" % (princ)] -+ else: -+ args += ["addprinc -pw %s %s" % (password, princ)] -+ return self._run_in_env(args, self.get_krb5_env()) -+ -+ def _run_in_env(self, args, env): -+ cmd = subprocess.Popen(args, env=env) -+ out, err = cmd.communicate() -+ return cmd.returncode, out, err -+ -+ def _create_config(self): -+ try: -+ os.makedirs(self.kdc_basedir) -+ os.makedirs(self.kdc_logdir) -+ os.makedirs(self.includedir) -+ except OSError as osex: -+ if osex.errno == 17: -+ pass -+ -+ kdc_conf = self._format_kdc_conf() -+ with open(self.kdc_conf_path, 'w') as kdc_conf_file: -+ kdc_conf_file.write(kdc_conf) -+ -+ krb5_conf = self._format_krb5_conf() -+ with open(self.krb5_conf_path, 'w') as krb5_conf_file: -+ krb5_conf_file.write(krb5_conf) -+ -+ def _create_acl(self): -+ with open(self.acl_file, 'w') as acl_fobject: -+ acl_fobject.write(self.admin_princ) -+ -+ def _create_kdb(self): -+ self._run_in_env( -+ ['kdb5_util', 'create', '-W', '-s', '-P', self.master_key], -+ self.get_krb5_env() -+ ) -+ -+ def _format_kdc_conf(self): -+ database_path = self.kdc_basedir + "/principal" -+ key_stash = self.kdc_basedir + "/stash." + self.realm -+ -+ kdc_logfile = "FILE:" + self.kdc_logdir + "/krb5kdc.log" -+ kadmin_logfile = "FILE:" + self.kdc_logdir + "/kadmin.log" -+ libkrb5_logfile = "FILE:" + self.kdc_logdir + "/libkrb5.log" -+ -+ kdc_conf = unindent(""" -+ [kdcdefaults] -+ kdc_ports = {self.kdc_port} -+ kdc_tcp_ports = {self.kdc_port} -+ -+ [realms] -+ {self.realm} = {{ -+ kadmind_port = {self.kadmin_port} -+ database_name = {database_path} -+ key_stash_file = {key_stash} -+ acl_file = {self.acl_file} -+ }} -+ -+ [logging] -+ kdc = {kdc_logfile} -+ admin_server = {kadmin_logfile} -+ default = {libkrb5_logfile} -+ """).format(**locals()) -+ return kdc_conf -+ -+ def _format_krb5_conf(self): -+ kdc_uri = "localhost:%d" % self.kdc_port -+ kadmin_uri = "localhost:%d" % self.kadmin_port -+ -+ krb5_conf = unindent(""" -+ includedir {self.includedir} -+ -+ [libdefaults] -+ default_realm = {self.realm} -+ dns_lookup_kdc = false -+ dns_lookup_realm = false -+ -+ [realms] -+ {self.realm} = {{ -+ kdc = {kdc_uri} -+ admin_server = {kadmin_uri} -+ }} -+ """).format(**locals()) -+ return krb5_conf -diff --git a/src/tests/intg/krb5utils.py b/src/tests/intg/krb5utils.py -new file mode 100644 -index 0000000000000000000000000000000000000000..775cffd0bbfa011f2d8ffc1169dccfef96d78fab ---- /dev/null -+++ b/src/tests/intg/krb5utils.py -@@ -0,0 +1,156 @@ -+# -+# MIT Kerberos server class -+# -+# Copyright (c) 2016 Red Hat, Inc. -+# -+# This 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; version 2 only -+# -+# 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 . -+# -+import os -+import subprocess -+ -+ -+class NoPrincipals(Exception): -+ def __init__(self): -+ Exception.__init__(self, 'No principals in the collection') -+ -+ -+class PrincNotFound(Exception): -+ def __init__(self, principal): -+ Exception.__init__(self, 'Principal %s not found' % principal) -+ -+ -+class Krb5Utils(object): -+ """ -+ Helper class to test Kerberos command line utilities -+ """ -+ def __init__(self, krb5_conf_path): -+ self.krb5_conf_path = krb5_conf_path -+ -+ def _run_in_env(self, args, stdin=None, extra_env=None): -+ my_env = os.environ -+ my_env['KRB5_CONFIG'] = self.krb5_conf_path -+ -+ if 'KRB5CCNAME' in my_env: -+ del my_env['KRB5CCNAME'] -+ if extra_env is not None: -+ my_env.update(extra_env) -+ -+ cmd = subprocess.Popen(args, -+ env=my_env, -+ stdin=subprocess.PIPE, -+ stdout=subprocess.PIPE, -+ stderr=subprocess.PIPE) -+ out, err = cmd.communicate(stdin) -+ return cmd.returncode, out.decode('utf-8'), err.decode('utf-8') -+ -+ def kinit(self, principal, password, env=None): -+ args = ["kinit", principal] -+ return self._run_in_env(args, password.encode('utf-8'), env) -+ -+ def kvno(self, principal, env=None): -+ args = ["kvno", principal] -+ return self._run_in_env(args, env) -+ -+ def kdestroy(self, all_ccaches=False, env=None): -+ args = ["kdestroy"] -+ if all_ccaches is True: -+ args += ["-A"] -+ retval, _, _ = self._run_in_env(args, env) -+ return retval -+ -+ def kswitch(self, principal, env=None): -+ args = ["kswitch", '-p', principal] -+ retval, _, _ = self._run_in_env(args, env) -+ return retval -+ -+ def _check_klist_l(self, line, exp_principal, exp_cache): -+ try: -+ princ, cache = line.split() -+ except ValueError: -+ return False -+ -+ if exp_cache is not None and cache != exp_cache: -+ return False -+ -+ if exp_principal != princ: -+ return False -+ -+ return True -+ -+ def num_princs(self, env=None): -+ args = ["klist", "-l"] -+ retval, out, err = self._run_in_env(args, extra_env=env) -+ if retval != 0: -+ return 0 -+ -+ outlines = [l for l in out.split('\n') if len(l) > 1] -+ return len(outlines) - 2 -+ -+ def list_princs(self, env=None): -+ args = ["klist", "-l"] -+ retval, out, err = self._run_in_env(args, extra_env=env) -+ if retval == 1: -+ raise NoPrincipals -+ elif retval != 0: -+ raise Exception("klist failed: %d: %s\n", retval, err) -+ -+ outlines = out.split('\n') -+ if len(outlines) < 2: -+ raise Exception("Not enough output from klist -l") -+ -+ return [l for l in outlines[2:] if len(l) > 0] -+ -+ def has_principal(self, exp_principal, exp_cache=None, env=None): -+ try: -+ princlist = self.list_princs(env) -+ except NoPrincipals: -+ return False -+ -+ for line in princlist: -+ matches = self._check_klist_l(line, exp_principal, exp_cache) -+ if matches is True: -+ return True -+ -+ return False -+ -+ def default_principal(self, env=None): -+ principals = self.list_princs(env) -+ return principals[0].split()[0] -+ -+ def _parse_klist_a(self, out): -+ dflprinc = None -+ thisrealm = None -+ ccache_dict = dict() -+ -+ for line in [l for l in out.split('\n') if len(l) > 0]: -+ if line.startswith("Default principal"): -+ dflprinc = line.split()[2] -+ thisrealm = '@' + dflprinc.split('@')[1] -+ elif thisrealm is not None and line.endswith(thisrealm): -+ svc = line.split()[-1] -+ if dflprinc in ccache_dict: -+ ccache_dict[dflprinc].append(svc) -+ else: -+ ccache_dict[dflprinc] = [svc] -+ -+ return ccache_dict -+ -+ def list_all_princs(self, env=None): -+ args = ["klist", "-A"] -+ retval, out, err = self._run_in_env(args, extra_env=env) -+ if retval == 1: -+ raise NoPrincipals -+ elif retval != 0: -+ raise Exception("klist -A failed: %d: %s\n", retval, err) -+ -+ return self._parse_klist_a(out) -diff --git a/src/tests/intg/test_kcm.py b/src/tests/intg/test_kcm.py -new file mode 100644 -index 0000000000000000000000000000000000000000..ad1e4923bfe339cb040464757431d2ef3bf57ce1 ---- /dev/null -+++ b/src/tests/intg/test_kcm.py -@@ -0,0 +1,361 @@ -+# -+# KCM responder integration tests -+# -+# Copyright (c) 2016 Red Hat, Inc. -+# -+# This 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; version 2 only -+# -+# 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 . -+# -+import os -+import os.path -+import stat -+import subprocess -+import pytest -+import socket -+import time -+import signal -+ -+import kdc -+import krb5utils -+import config -+from util import unindent, run_shell -+ -+class KcmTestEnv(object): -+ def __init__(self, k5kdc, k5util): -+ self.k5kdc = k5kdc -+ self.k5util = k5util -+ self.counter = 0 -+ -+ def my_uid(self): -+ s_myuid = os.environ['NON_WRAPPED_UID'] -+ return int(s_myuid) -+ -+ def ccname(self, my_uid=None): -+ if my_uid is None: -+ my_uid = self.my_uid() -+ -+ return "KCM:%d" % my_uid -+ -+ -+@pytest.fixture(scope="module") -+def kdc_instance(request): -+ """Kerberos server instance fixture""" -+ kdc_instance = kdc.KDC(config.PREFIX, "KCMTEST") -+ try: -+ kdc_instance.set_up() -+ kdc_instance.start_kdc() -+ except: -+ kdc_instance.teardown() -+ raise -+ request.addfinalizer(kdc_instance.teardown) -+ return kdc_instance -+ -+ -+def create_conf_fixture(request, contents): -+ """Generate sssd.conf and add teardown for removing it""" -+ with open(config.CONF_PATH, "w") as conf: -+ conf.write(contents) -+ os.chmod(config.CONF_PATH, stat.S_IRUSR | stat.S_IWUSR) -+ request.addfinalizer(lambda: os.unlink(config.CONF_PATH)) -+ -+ -+def create_sssd_kcm_fixture(sock_path, request): -+ if subprocess.call(['sssd', "--genconf"]) != 0: -+ raise Exception("failed to regenerate confdb") -+ -+ resp_path = os.path.join(config.LIBEXEC_PATH, "sssd", "sssd_kcm") -+ if not os.access(resp_path, os.X_OK): -+ # It would be cleaner to use pytest.mark.skipif on the package level -+ # but upstream insists on supporting RHEL-6.. -+ pytest.skip("No KCM responder, skipping") -+ -+ kcm_pid = os.fork() -+ assert kcm_pid >= 0 -+ -+ if kcm_pid == 0: -+ if subprocess.call([resp_path, "--uid=0", "--gid=0"]) != 0: -+ print("sssd_kcm failed to start") -+ sys.exit(99) -+ else: -+ abs_sock_path = os.path.join(config.RUNSTATEDIR, sock_path) -+ sck = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) -+ for _ in range(1, 10): -+ try: -+ sck.connect(abs_sock_path) -+ except: -+ time.sleep(0.1) -+ else: -+ break -+ sck.close() -+ assert os.path.exists(abs_sock_path) -+ -+ def kcm_teardown(): -+ if kcm_pid == 0: -+ return -+ os.kill(kcm_pid, signal.SIGTERM) -+ -+ request.addfinalizer(kcm_teardown) -+ return kcm_pid -+ -+ -+@pytest.fixture -+def setup_for_kcm(request, kdc_instance): -+ """ -+ Just set up the local provider for tests and enable the KCM -+ responder -+ """ -+ kcm_path = os.path.join(config.RUNSTATEDIR, "kcm.socket") -+ -+ sssd_conf = unindent("""\ -+ [sssd] -+ domains = local -+ services = nss -+ -+ [domain/local] -+ id_provider = local -+ -+ [kcm] -+ socket_path = {kcm_path} -+ """).format(**locals()) -+ -+ kcm_socket_include = unindent(""" -+ [libdefaults] -+ default_ccache_name = KCM: -+ kcm_socket = {kcm_path} -+ """).format(**locals()) -+ kdc_instance.add_config({'kcm_socket': kcm_socket_include}) -+ -+ create_conf_fixture(request, sssd_conf) -+ create_sssd_kcm_fixture(kcm_path, request) -+ -+ k5util = krb5utils.Krb5Utils(kdc_instance.krb5_conf_path) -+ -+ return KcmTestEnv(kdc_instance, k5util) -+ -+ -+def test_kcm_init_list_destroy(setup_for_kcm): -+ """ -+ Test that kinit, kdestroy and klist work with KCM -+ """ -+ testenv = setup_for_kcm -+ testenv.k5kdc.add_principal("kcmtest", "Secret123") -+ -+ ok = testenv.k5util.has_principal("kcmtest@KCMTEST") -+ assert ok is False -+ nprincs = testenv.k5util.num_princs() -+ assert nprincs == 0 -+ -+ out, _, _ = testenv.k5util.kinit("kcmtest", "Secret123") -+ assert out == 0 -+ nprincs = testenv.k5util.num_princs() -+ assert nprincs == 1 -+ -+ exp_ccname = testenv.ccname() -+ ok = testenv.k5util.has_principal("kcmtest@KCMTEST", exp_ccname) -+ assert ok is True -+ -+ out = testenv.k5util.kdestroy() -+ assert out == 0 -+ -+ ok = testenv.k5util.has_principal("kcmtest@KCMTEST") -+ assert ok is False -+ nprincs = testenv.k5util.num_princs() -+ assert nprincs == 0 -+ -+ -+def test_kcm_overwrite(setup_for_kcm): -+ """ -+ That that reusing a ccache reinitializes the cache and doesn't -+ add the same principal twice -+ """ -+ testenv = setup_for_kcm -+ testenv.k5kdc.add_principal("kcmtest", "Secret123") -+ exp_ccache = {'kcmtest@KCMTEST': ['krbtgt/KCMTEST@KCMTEST']} -+ -+ assert testenv.k5util.num_princs() == 0 -+ -+ out, _, _ = testenv.k5util.kinit("kcmtest", "Secret123") -+ assert out == 0 -+ assert exp_ccache == testenv.k5util.list_all_princs() -+ -+ out, _, _ = testenv.k5util.kinit("kcmtest", "Secret123") -+ assert out == 0 -+ assert exp_ccache == testenv.k5util.list_all_princs() -+ -+ -+def test_collection_init_list_destroy(setup_for_kcm): -+ """ -+ Test that multiple principals and service tickets can be stored -+ in a collection. -+ """ -+ testenv = setup_for_kcm -+ testenv.k5kdc.add_principal("alice", "alicepw") -+ testenv.k5kdc.add_principal("bob", "bobpw") -+ testenv.k5kdc.add_principal("carol", "carolpw") -+ testenv.k5kdc.add_principal("host/somehostname") -+ -+ assert testenv.k5util.num_princs() == 0 -+ -+ out, _, _ = testenv.k5util.kinit("alice", "alicepw") -+ assert out == 0 -+ assert testenv.k5util.default_principal() == 'alice@KCMTEST' -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 1 -+ assert cc_coll['alice@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert 'bob@KCMTEST' not in cc_coll -+ assert 'carol@KCMTEST' not in cc_coll -+ -+ out, _, _ = testenv.k5util.kinit("bob", "bobpw") -+ assert out == 0 -+ assert testenv.k5util.default_principal() == 'bob@KCMTEST' -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 2 -+ assert cc_coll['alice@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert cc_coll['bob@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert 'carol@KCMTEST' not in cc_coll -+ -+ out, _, _ = testenv.k5util.kinit("carol", "carolpw") -+ assert out == 0 -+ assert testenv.k5util.default_principal() == 'carol@KCMTEST' -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 3 -+ assert cc_coll['alice@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert cc_coll['bob@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert cc_coll['carol@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ -+ out, _, _ = testenv.k5util.kvno('host/somehostname') -+ assert out == 0 -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 3 -+ assert set(cc_coll['carol@KCMTEST']) == set(['krbtgt/KCMTEST@KCMTEST', -+ 'host/somehostname@KCMTEST']) -+ -+ out = testenv.k5util.kdestroy() -+ assert out == 0 -+ assert testenv.k5util.default_principal() == 'bob@KCMTEST' -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 2 -+ assert cc_coll['alice@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert cc_coll['bob@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert 'carol@KCMTEST' not in cc_coll -+ -+ # FIXME - a bug in libkrb5? -+ #out = testenv.k5util.kdestroy(all_ccaches=True) -+ #assert out == 0 -+ #cc_coll = testenv.k5util.list_all_princs() -+ #assert len(cc_coll) == 0 -+ -+ -+def test_kswitch(setup_for_kcm): -+ """ -+ Test switching between principals -+ """ -+ testenv = setup_for_kcm -+ testenv.k5kdc.add_principal("alice", "alicepw") -+ testenv.k5kdc.add_principal("bob", "bobpw") -+ testenv.k5kdc.add_principal("host/somehostname") -+ testenv.k5kdc.add_principal("host/differenthostname") -+ -+ out, _, _ = testenv.k5util.kinit("alice", "alicepw") -+ assert out == 0 -+ assert testenv.k5util.default_principal() == 'alice@KCMTEST' -+ -+ out, _, _ = testenv.k5util.kinit("bob", "bobpw") -+ assert out == 0 -+ assert testenv.k5util.default_principal() == 'bob@KCMTEST' -+ -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 2 -+ assert cc_coll['alice@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ assert cc_coll['bob@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ -+ out = testenv.k5util.kswitch("alice@KCMTEST") -+ assert testenv.k5util.default_principal() == 'alice@KCMTEST' -+ out, _, _ = testenv.k5util.kvno('host/somehostname') -+ assert out == 0 -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 2 -+ assert set(cc_coll['alice@KCMTEST']) == set(['krbtgt/KCMTEST@KCMTEST', -+ 'host/somehostname@KCMTEST']) -+ assert cc_coll['bob@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -+ -+ out = testenv.k5util.kswitch("bob@KCMTEST") -+ assert testenv.k5util.default_principal() == 'bob@KCMTEST' -+ out, _, _ = testenv.k5util.kvno('host/differenthostname') -+ assert out == 0 -+ cc_coll = testenv.k5util.list_all_princs() -+ assert len(cc_coll) == 2 -+ assert set(cc_coll['alice@KCMTEST']) == set(['krbtgt/KCMTEST@KCMTEST', -+ 'host/somehostname@KCMTEST']) -+ assert set(cc_coll['bob@KCMTEST']) == set([ -+ 'krbtgt/KCMTEST@KCMTEST', -+ 'host/differenthostname@KCMTEST']) -+ -+ -+def test_subsidiaries(setup_for_kcm): -+ """ -+ Test that subsidiary caches are usable and KCM: without specifying UID -+ can be used to identify the collection -+ """ -+ testenv = setup_for_kcm -+ testenv.k5kdc.add_principal("alice", "alicepw") -+ testenv.k5kdc.add_principal("bob", "bobpw") -+ testenv.k5kdc.add_principal("host/somehostname") -+ testenv.k5kdc.add_principal("host/differenthostname") -+ -+ out, _, _ = testenv.k5util.kinit("alice", "alicepw") -+ assert out == 0 -+ out, _, _ = testenv.k5util.kvno('host/somehostname') -+ -+ out, _, _ = testenv.k5util.kinit("bob", "bobpw") -+ assert out == 0 -+ out, _, _ = testenv.k5util.kvno('host/differenthostname') -+ -+ exp_cc_coll = dict() -+ exp_cc_coll['alice@KCMTEST'] = 'host/somehostname@KCMTEST' -+ exp_cc_coll['bob@KCMTEST'] = 'host/differenthostname@KCMTEST' -+ -+ klist_l = testenv.k5util.list_princs() -+ princ_ccache = dict() -+ for line in klist_l: -+ princ, subsidiary = line.split() -+ princ_ccache[princ] = subsidiary -+ -+ for princ, subsidiary in princ_ccache.items(): -+ env = {'KRB5CCNAME': subsidiary} -+ cc_coll = testenv.k5util.list_all_princs(env=env) -+ assert len(cc_coll) == 1 -+ assert princ in cc_coll -+ assert exp_cc_coll[princ] in cc_coll[princ] -+ -+ cc_coll = testenv.k5util.list_all_princs(env={'KRB5CCNAME': 'KCM:'}) -+ assert len(cc_coll) == 2 -+ assert set(cc_coll['alice@KCMTEST']) == set(['krbtgt/KCMTEST@KCMTEST', -+ 'host/somehostname@KCMTEST']) -+ assert set(cc_coll['bob@KCMTEST']) == set([ -+ 'krbtgt/KCMTEST@KCMTEST', -+ 'host/differenthostname@KCMTEST']) -+ -+ -+def test_kdestroy_nocache(setup_for_kcm): -+ """ -+ Destroying a non-existing ccache should not throw an error -+ """ -+ testenv = setup_for_kcm -+ testenv.k5kdc.add_principal("alice", "alicepw") -+ out, _, _ = testenv.k5util.kinit("alice", "alicepw") -+ assert out == 0 -+ -+ testenv.k5util.kdestroy() -+ assert out == 0 -+ out = testenv.k5util.kdestroy() -+ assert out == 0 --- -2.12.2 - diff --git a/0031-SECRETS-Create-DB-path-before-the-operation-itself.patch b/0031-SECRETS-Create-DB-path-before-the-operation-itself.patch deleted file mode 100644 index cd8e052..0000000 --- a/0031-SECRETS-Create-DB-path-before-the-operation-itself.patch +++ /dev/null @@ -1,405 +0,0 @@ -From 8bb2fcbce7c3fcfd986f1bc835fbcc43ac7cd9d1 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 3 Jan 2017 16:00:38 +0100 -Subject: [PATCH 31/97] SECRETS: Create DB path before the operation itself -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is a refactoring where instead of creating the ldb path in the -operation itself, we create the ldb path when creating the local db request -and pass the path to the operation. - -This would allow us to store different kind of objects in the secrets -storage later. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/responder/secrets/local.c | 170 +++++++++++++++++++++--------------------- - 1 file changed, 84 insertions(+), 86 deletions(-) - -diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c -index ed70193bcb27d84eaf449f6f7571c94f466c9896..9dcdd9925e542499d3a962b4998103b07c26a5ab 100644 ---- a/src/responder/secrets/local.c -+++ b/src/responder/secrets/local.c -@@ -199,39 +199,36 @@ static char *local_dn_to_path(TALLOC_CTX *mem_ctx, - return path; - } - -+struct local_db_req { -+ char *path; -+ struct ldb_dn *basedn; -+}; -+ - #define LOCAL_SIMPLE_FILTER "(type=simple)" - #define LOCAL_CONTAINER_FILTER "(type=container)" - - static int local_db_get_simple(TALLOC_CTX *mem_ctx, - struct local_context *lctx, -- const char *req_path, -+ struct local_db_req *lc_req, - char **secret) - { - TALLOC_CTX *tmp_ctx; - static const char *attrs[] = { "secret", "enctype", NULL }; - struct ldb_result *res; -- struct ldb_dn *dn; - const char *attr_secret; - const char *attr_enctype; - int ret; - -- DEBUG(SSSDBG_TRACE_FUNC, "Retrieving a secret from [%s]\n", req_path); -+ DEBUG(SSSDBG_TRACE_FUNC, "Retrieving a secret from [%s]\n", lc_req->path); - - tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) return ENOMEM; - -- ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret)); -- goto done; -- } -- - DEBUG(SSSDBG_TRACE_INTERNAL, - "Searching for [%s] at [%s] with scope=base\n", -- LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(dn)); -+ LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(lc_req->basedn)); - -- ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, -+ ret = ldb_search(lctx->ldb, tmp_ctx, &res, lc_req->basedn, LDB_SCOPE_BASE, - attrs, "%s", LOCAL_SIMPLE_FILTER); - if (ret != EOK) { - DEBUG(SSSDBG_TRACE_LIBS, -@@ -278,34 +275,26 @@ done: - - static int local_db_list_keys(TALLOC_CTX *mem_ctx, - struct local_context *lctx, -- const char *req_path, -+ struct local_db_req *lc_req, - char ***_keys, - int *num_keys) - { - TALLOC_CTX *tmp_ctx; - static const char *attrs[] = { "secret", NULL }; - struct ldb_result *res; -- struct ldb_dn *dn; - char **keys; - int ret; - - tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) return ENOMEM; - -- DEBUG(SSSDBG_TRACE_FUNC, "Listing keys at [%s]\n", req_path); -- -- ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret)); -- goto done; -- } -+ DEBUG(SSSDBG_TRACE_FUNC, "Listing keys at [%s]\n", lc_req->path); - - DEBUG(SSSDBG_TRACE_INTERNAL, - "Searching for [%s] at [%s] with scope=subtree\n", -- LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(dn)); -+ LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(lc_req->basedn)); - -- ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE, -+ ret = ldb_search(lctx->ldb, tmp_ctx, &res, lc_req->basedn, LDB_SCOPE_SUBTREE, - attrs, "%s", LOCAL_SIMPLE_FILTER); - if (ret != EOK) { - DEBUG(SSSDBG_TRACE_LIBS, -@@ -327,7 +316,7 @@ static int local_db_list_keys(TALLOC_CTX *mem_ctx, - } - - for (unsigned i = 0; i < res->count; i++) { -- keys[i] = local_dn_to_path(keys, dn, res->msgs[i]->dn); -+ keys[i] = local_dn_to_path(keys, lc_req->basedn, res->msgs[i]->dn); - if (!keys[i]) { - ret = ENOMEM; - goto done; -@@ -474,7 +463,7 @@ static int local_check_max_payload_size(struct local_context *lctx, - - static int local_db_put_simple(TALLOC_CTX *mem_ctx, - struct local_context *lctx, -- const char *req_path, -+ struct local_db_req *lc_req, - const char *secret) - { - struct ldb_message *msg; -@@ -482,20 +471,14 @@ static int local_db_put_simple(TALLOC_CTX *mem_ctx, - char *enc_secret; - int ret; - -+ DEBUG(SSSDBG_TRACE_FUNC, "Adding a secret to [%s]\n", lc_req->path); -+ - msg = ldb_msg_new(mem_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } -- -- DEBUG(SSSDBG_TRACE_FUNC, "Adding a secret to [%s]\n", req_path); -- -- ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret)); -- goto done; -- } -+ msg->dn = lc_req->basedn; - - /* make sure containers exist */ - ret = local_db_check_containers(msg, lctx, msg->dn); -@@ -585,32 +568,24 @@ done: - - static int local_db_delete(TALLOC_CTX *mem_ctx, - struct local_context *lctx, -- const char *req_path) -+ struct local_db_req *lc_req) - { - TALLOC_CTX *tmp_ctx; -- struct ldb_dn *dn; - static const char *attrs[] = { NULL }; - struct ldb_result *res; - int ret; - -- DEBUG(SSSDBG_TRACE_FUNC, "Removing a secret from [%s]\n", req_path); -+ DEBUG(SSSDBG_TRACE_FUNC, "Removing a secret from [%s]\n", lc_req->path); - - tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) return ENOMEM; - -- ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret)); -- goto done; -- } -- - DEBUG(SSSDBG_TRACE_INTERNAL, - "Searching for [%s] at [%s] with scope=base\n", -- LOCAL_CONTAINER_FILTER, ldb_dn_get_linearized(dn)); -+ LOCAL_CONTAINER_FILTER, ldb_dn_get_linearized(lc_req->basedn)); - -- ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, -- attrs, LOCAL_CONTAINER_FILTER); -+ ret = ldb_search(lctx->ldb, tmp_ctx, &res, lc_req->basedn, LDB_SCOPE_BASE, -+ attrs, LOCAL_CONTAINER_FILTER); - if (ret != EOK) { - DEBUG(SSSDBG_TRACE_LIBS, - "ldb_search returned %d: %s\n", ret, ldb_strerror(ret)); -@@ -619,8 +594,8 @@ static int local_db_delete(TALLOC_CTX *mem_ctx, - - if (res->count == 1) { - DEBUG(SSSDBG_TRACE_INTERNAL, -- "Searching for children of [%s]\n", ldb_dn_get_linearized(dn)); -- ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL, -+ "Searching for children of [%s]\n", ldb_dn_get_linearized(lc_req->basedn)); -+ ret = ldb_search(lctx->ldb, tmp_ctx, &res, lc_req->basedn, LDB_SCOPE_ONELEVEL, - attrs, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_TRACE_LIBS, -@@ -632,13 +607,13 @@ static int local_db_delete(TALLOC_CTX *mem_ctx, - ret = EEXIST; - DEBUG(SSSDBG_OP_FAILURE, - "Failed to remove '%s': Container is not empty\n", -- ldb_dn_get_linearized(dn)); -+ ldb_dn_get_linearized(lc_req->basedn)); - - goto done; - } - } - -- ret = ldb_delete(lctx->ldb, dn); -+ ret = ldb_delete(lctx->ldb, lc_req->basedn); - if (ret != EOK) { - DEBUG(SSSDBG_TRACE_LIBS, - "ldb_delete returned %d: %s\n", ret, ldb_strerror(ret)); -@@ -653,25 +628,19 @@ done: - - static int local_db_create(TALLOC_CTX *mem_ctx, - struct local_context *lctx, -- const char *req_path) -+ struct local_db_req *lc_req) - { - struct ldb_message *msg; - int ret; - -+ DEBUG(SSSDBG_TRACE_FUNC, "Creating a container at [%s]\n", lc_req->path); -+ - msg = ldb_msg_new(mem_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } -- -- DEBUG(SSSDBG_TRACE_FUNC, "Creating a container at [%s]\n", req_path); -- -- ret = local_db_dn(msg, lctx->ldb, req_path, &msg->dn); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret)); -- goto done; -- } -+ msg->dn = lc_req->basedn; - - /* make sure containers exist */ - ret = local_db_check_containers(msg, lctx, msg->dn); -@@ -724,10 +693,13 @@ done: - } - - static int local_secrets_map_path(TALLOC_CTX *mem_ctx, -+ struct ldb_context *ldb, - struct sec_req_ctx *secreq, -- char **local_db_path) -+ struct local_db_req **_lc_req) - { - int ret; -+ struct local_db_req *lc_req; -+ const char *basedn; - - /* be strict for now */ - if (secreq->parsed_url.fragment != NULL) { -@@ -755,20 +727,46 @@ static int local_secrets_map_path(TALLOC_CTX *mem_ctx, - } - } - -- /* drop SEC_BASEPATH prefix */ -- *local_db_path = -- talloc_strdup(mem_ctx, &secreq->mapped_path[sizeof(SEC_BASEPATH) - 1]); -- if (!*local_db_path) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Failed to map request to local db path\n"); -+ lc_req = talloc(mem_ctx, struct local_db_req); -+ if (lc_req == NULL) { - return ENOMEM; - } - -- DEBUG(SSSDBG_TRACE_LIBS, "Local DB path is %s\n", *local_db_path); -- return EOK; -+ /* drop the prefix and select a basedn instead */ -+ if (strncmp(secreq->mapped_path, -+ SEC_BASEPATH, sizeof(SEC_BASEPATH) - 1) == 0) { -+ lc_req->path = talloc_strdup(lc_req, -+ secreq->mapped_path + (sizeof(SEC_BASEPATH) - 1)); -+ basedn = SECRETS_BASEDN; -+ } else { -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (lc_req->path == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to map request to local db path\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = local_db_dn(mem_ctx, ldb, basedn, lc_req->path, &lc_req->basedn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to map request to local db DN\n"); -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Local DB path is %s\n", lc_req->path); -+ ret = EOK; -+ *_lc_req = lc_req; -+done: -+ if (ret != EOK) { -+ talloc_free(lc_req); -+ } -+ return ret; - } - -- - struct local_secret_state { - struct tevent_context *ev; - struct sec_req_ctx *secreq; -@@ -785,7 +783,7 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - struct sec_data body = { 0 }; - const char *content_type; - bool body_is_json; -- char *req_path; -+ struct local_db_req *lc_req; - char *secret; - char **keys; - int nkeys; -@@ -821,14 +819,14 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - } - DEBUG(SSSDBG_TRACE_LIBS, "Content-Type: %s\n", content_type); - -- ret = local_secrets_map_path(state, secreq, &req_path); -+ ret = local_secrets_map_path(state, lctx->ldb, secreq, &lc_req); - if (ret) goto done; - - switch (secreq->method) { - case HTTP_GET: -- DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP GET at [%s]\n", req_path); -- if (req_path[strlen(req_path) - 1] == '/') { -- ret = local_db_list_keys(state, lctx, req_path, &keys, &nkeys); -+ DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP GET at [%s]\n", lc_req->path); -+ if (lc_req->path[strlen(lc_req->path) - 1] == '/') { -+ ret = local_db_list_keys(state, lctx, lc_req, &keys, &nkeys); - if (ret) goto done; - - ret = sec_array_to_json(state, keys, nkeys, &body.data); -@@ -838,7 +836,7 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - break; - } - -- ret = local_db_get_simple(state, lctx, req_path, &secret); -+ ret = local_db_get_simple(state, lctx, lc_req, &secret); - if (ret) goto done; - - if (body_is_json) { -@@ -855,7 +853,7 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - break; - - case HTTP_PUT: -- DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP PUT at [%s]\n", req_path); -+ DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP PUT at [%s]\n", lc_req->path); - if (body_is_json) { - ret = sec_json_to_simple_secret(state, secreq->body.data, - &secret); -@@ -866,27 +864,27 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - } - if (ret) goto done; - -- ret = local_db_put_simple(state, lctx, req_path, secret); -+ ret = local_db_put_simple(state, lctx, lc_req, secret); - if (ret) goto done; - break; - - case HTTP_DELETE: -- ret = local_db_delete(state, lctx, req_path); -+ ret = local_db_delete(state, lctx, lc_req); - if (ret) goto done; - break; - - case HTTP_POST: -- DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP POST at [%s]\n", req_path); -- plen = strlen(req_path); -+ DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP POST at [%s]\n", lc_req->path); -+ plen = strlen(lc_req->path); - -- if (req_path[plen - 1] != '/') { -+ if (lc_req->path[plen - 1] != '/') { - ret = EINVAL; - goto done; - } - -- req_path[plen - 1] = '\0'; -+ lc_req->path[plen - 1] = '\0'; - -- ret = local_db_create(state, lctx, req_path); -+ ret = local_db_create(state, lctx, lc_req); - if (ret) goto done; - break; - --- -2.12.2 - diff --git a/0032-SECRETS-Return-a-nicer-error-message-on-request-with.patch b/0032-SECRETS-Return-a-nicer-error-message-on-request-with.patch deleted file mode 100644 index 8b34f38..0000000 --- a/0032-SECRETS-Return-a-nicer-error-message-on-request-with.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 73ce539aa70f43ccd5302b3ef8a02ff028558b12 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 3 Feb 2017 14:33:47 +0100 -Subject: [PATCH 32/97] SECRETS: Return a nicer error message on request with - no PUT data -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -I managed to create this pathological situation with the tcurl tool -which didn't send any PUT data. The error in sssd-secrets was quite -strange (ENOMEM). This patch just adds a safeguard sooner so that we -return a graceful error. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/responder/secrets/local.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c -index 9dcdd9925e542499d3a962b4998103b07c26a5ab..26c97a2849febbf0ac482d526cf927bfc103b4f2 100644 ---- a/src/responder/secrets/local.c -+++ b/src/responder/secrets/local.c -@@ -853,6 +853,12 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - break; - - case HTTP_PUT: -+ if (secreq->body.length == 0) { -+ DEBUG(SSSDBG_OP_FAILURE, "PUT with no data\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ - DEBUG(SSSDBG_TRACE_LIBS, "Processing HTTP PUT at [%s]\n", lc_req->path); - if (body_is_json) { - ret = sec_json_to_simple_secret(state, secreq->body.data, --- -2.12.2 - diff --git a/0033-SECRETS-Store-ccaches-in-secrets-for-the-KCM-respond.patch b/0033-SECRETS-Store-ccaches-in-secrets-for-the-KCM-respond.patch deleted file mode 100644 index 0914fb0..0000000 --- a/0033-SECRETS-Store-ccaches-in-secrets-for-the-KCM-respond.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 60612b5fbdaaa62ebe6c7f4c27200316f08506d6 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 21 Mar 2017 14:14:42 +0100 -Subject: [PATCH 33/97] SECRETS: Store ccaches in secrets for the KCM responder -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Adds a new "hive" to the secrets responder whose base path is /kcm. Only -root can contact the /kcm hive, because the KCM responder only runs as -root and it must impersonate other users and store ccaches on their behalf. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/responder/secrets/local.c | 16 +++++++- - src/responder/secrets/providers.c | 71 ++++++++++++++++++++++++++++++---- - src/responder/secrets/secsrv_private.h | 10 ++++- - 3 files changed, 86 insertions(+), 11 deletions(-) - -diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c -index 26c97a2849febbf0ac482d526cf927bfc103b4f2..02007ada8b673071ecba033df0eb3f81af93fcbd 100644 ---- a/src/responder/secrets/local.c -+++ b/src/responder/secrets/local.c -@@ -26,6 +26,9 @@ - - #define MKEY_SIZE (256 / 8) - -+#define SECRETS_BASEDN "cn=secrets" -+#define KCM_BASEDN "cn=kcm" -+ - struct local_context { - struct ldb_context *ldb; - struct sec_data master_key; -@@ -119,6 +122,7 @@ static int local_encrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, - - static int local_db_dn(TALLOC_CTX *mem_ctx, - struct ldb_context *ldb, -+ const char *basedn, - const char *req_path, - struct ldb_dn **req_dn) - { -@@ -126,7 +130,7 @@ static int local_db_dn(TALLOC_CTX *mem_ctx, - const char *s, *e; - int ret; - -- dn = ldb_dn_new(mem_ctx, ldb, "cn=secrets"); -+ dn = ldb_dn_new(mem_ctx, ldb, basedn); - if (!dn) { - ret = ENOMEM; - goto done; -@@ -738,6 +742,11 @@ static int local_secrets_map_path(TALLOC_CTX *mem_ctx, - lc_req->path = talloc_strdup(lc_req, - secreq->mapped_path + (sizeof(SEC_BASEPATH) - 1)); - basedn = SECRETS_BASEDN; -+ } else if (strncmp(secreq->mapped_path, -+ SEC_KCM_BASEPATH, sizeof(SEC_KCM_BASEPATH) - 1) == 0) { -+ lc_req->path = talloc_strdup(lc_req, -+ secreq->mapped_path + (sizeof(SEC_KCM_BASEPATH) - 1)); -+ basedn = KCM_BASEDN; - } else { - ret = EINVAL; - goto done; -@@ -820,7 +829,10 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx, - DEBUG(SSSDBG_TRACE_LIBS, "Content-Type: %s\n", content_type); - - ret = local_secrets_map_path(state, lctx->ldb, secreq, &lc_req); -- if (ret) goto done; -+ if (ret) { -+ DEBUG(SSSDBG_OP_FAILURE, "Cannot map request path to local path\n"); -+ goto done; -+ } - - switch (secreq->method) { - case HTTP_GET: -diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c -index eba555d2e422d08db211979422a2957e48b51589..94831c73036d269addca45c0117811a2c68873fd 100644 ---- a/src/responder/secrets/providers.c -+++ b/src/responder/secrets/providers.c -@@ -24,6 +24,14 @@ - #include "responder/secrets/secsrv_proxy.h" - #include - -+typedef int (*url_mapper_fn)(struct sec_req_ctx *secreq, -+ char **mapped_path); -+ -+struct url_pfx_router { -+ const char *prefix; -+ url_mapper_fn mapper_fn; -+}; -+ - static int sec_map_url_to_user_path(struct sec_req_ctx *secreq, - char **mapped_path) - { -@@ -42,10 +50,43 @@ static int sec_map_url_to_user_path(struct sec_req_ctx *secreq, - return ENOMEM; - } - -- DEBUG(SSSDBG_TRACE_LIBS, "User-specific path is [%s]\n", *mapped_path); -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "User-specific secrets path is [%s]\n", *mapped_path); - return EOK; - } - -+static int kcm_map_url_to_path(struct sec_req_ctx *secreq, -+ char **mapped_path) -+{ -+ uid_t c_euid; -+ -+ c_euid = client_euid(secreq->cctx->creds); -+ if (c_euid != KCM_PEER_UID) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "UID %"SPRIuid" is not allowed to access " -+ "the "SEC_KCM_BASEPATH" hive\n", -+ c_euid); -+ return EPERM; -+ } -+ -+ *mapped_path = talloc_strdup(secreq, secreq->parsed_url.path ); -+ if (!*mapped_path) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to map request to user specific url\n"); -+ return ENOMEM; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "User-specific KCM path is [%s]\n", *mapped_path); -+ return EOK; -+} -+ -+static struct url_pfx_router secrets_url_mapping[] = { -+ { SEC_BASEPATH, sec_map_url_to_user_path }, -+ { SEC_KCM_BASEPATH, kcm_map_url_to_path }, -+ { NULL, NULL }, -+}; -+ - int sec_req_routing(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq, - struct provider_handle **handle) - { -@@ -55,21 +96,35 @@ int sec_req_routing(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq, - char *provider; - int num_sections; - int ret; -+ url_mapper_fn mapper_fn = NULL; - - sctx = talloc_get_type(secreq->cctx->rctx->pvt_ctx, struct sec_ctx); - -- /* patch must start with /secrets/ for now */ -- ret = strncasecmp(secreq->parsed_url.path, -- SEC_BASEPATH, sizeof(SEC_BASEPATH) - 1); -- if (ret != 0) { -+ for (int i = 0; secrets_url_mapping[i].prefix != NULL; i++) { -+ if (strncasecmp(secreq->parsed_url.path, -+ secrets_url_mapping[i].prefix, -+ strlen(secrets_url_mapping[i].prefix)) == 0) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Mapping prefix %s\n", secrets_url_mapping[i].prefix); -+ mapper_fn = secrets_url_mapping[i].mapper_fn; -+ break; -+ } -+ } -+ -+ if (mapper_fn == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, -- "Path [%s] does not start with "SEC_BASEPATH"\n", -+ "Path [%s] does not start with any allowed prefix\n", - secreq->parsed_url.path); - return EPERM; - } - -- ret = sec_map_url_to_user_path(secreq, &secreq->mapped_path); -- if (ret) return ret; -+ ret = mapper_fn(secreq, &secreq->mapped_path); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to map the user path [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } - - /* source default provider */ - ret = confdb_get_string(secreq->cctx->rctx->cdb, mem_ctx, -diff --git a/src/responder/secrets/secsrv_private.h b/src/responder/secrets/secsrv_private.h -index 1c3fbd8eadb237551233f048503ddc01b4ba00ae..a8544f656517a17fe4576247779bff4850beaf97 100644 ---- a/src/responder/secrets/secsrv_private.h -+++ b/src/responder/secrets/secsrv_private.h -@@ -101,7 +101,15 @@ int sec_get_provider(struct sec_ctx *sctx, const char *name, - struct provider_handle **out_handle); - int sec_add_provider(struct sec_ctx *sctx, struct provider_handle *handle); - --#define SEC_BASEPATH "/secrets/" -+#define SEC_BASEPATH "/secrets/" -+#define SEC_KCM_BASEPATH "/kcm/" -+ -+/* The KCM responder must "impersonate" the owner of the credentials. -+ * Only a trusted UID can do that -- root by default, but unit -+ * tests might choose otherwise */ -+#ifndef KCM_PEER_UID -+#define KCM_PEER_UID 0 -+#endif /* KCM_PEER_UID */ - - /* providers.c */ - int sec_req_routing(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq, --- -2.12.2 - diff --git a/0034-TCURL-Support-HTTP-POST-for-creating-containers.patch b/0034-TCURL-Support-HTTP-POST-for-creating-containers.patch deleted file mode 100644 index 97a530b..0000000 --- a/0034-TCURL-Support-HTTP-POST-for-creating-containers.patch +++ /dev/null @@ -1,129 +0,0 @@ -From c9db8b8b19827c3d492b8d2769aa77a37dbc12d3 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 14 Mar 2017 15:34:57 +0100 -Subject: [PATCH 34/97] TCURL: Support HTTP POST for creating containers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The curl integration must allow us to create containers, therefore we -also add support of the POST HTTP request type. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/tests/intg/test_secrets.py | 28 ++++++++++++++++++++++++++++ - src/tests/tcurl_test_tool.c | 5 +++++ - src/util/tev_curl.c | 7 +++++++ - src/util/tev_curl.h | 1 + - 4 files changed, 41 insertions(+) - -diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py -index cbc1a1f06d2abb826bc0a880cb5a842f577657ea..d71c1904558cc6f8a6eee36c4049582705bc30ac 100644 ---- a/src/tests/intg/test_secrets.py -+++ b/src/tests/intg/test_secrets.py -@@ -271,6 +271,34 @@ def test_curlwrap_crd_ops(setup_for_secrets, - 'http://localhost/secrets/foo'], - 404) - -+ # Create a container -+ run_curlwrap_tool([curlwrap_tool, '-o', -+ '-v', '-s', sock_path, -+ 'http://localhost/secrets/cont/'], -+ 200) -+ -+ # set a secret foo:bar -+ run_curlwrap_tool([curlwrap_tool, '-p', -+ '-v', '-s', sock_path, -+ 'http://localhost/secrets/cont/cfoo', -+ 'foo_under_cont'], -+ 200) -+ -+ # list secrets -+ output = run_curlwrap_tool([curlwrap_tool, -+ '-v', '-s', sock_path, -+ 'http://localhost/secrets/cont/'], -+ 200) -+ assert "cfoo" in output -+ -+ # get the foo secret -+ output = run_curlwrap_tool([curlwrap_tool, -+ '-v', '-s', sock_path, -+ 'http://localhost/secrets/cont/cfoo'], -+ 200) -+ assert "foo_under_cont" in output -+ -+ - - def test_curlwrap_parallel(setup_for_secrets, - curlwrap_tool): -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 38cea432885c97ca3827c8f158bf7e3ebfc67b31..2af950ebb76a22bdf4a6dfd58442b10486e64293 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -88,6 +88,7 @@ int main(int argc, const char *argv[]) - { "get", 'g', POPT_ARG_NONE, NULL, 'g', "Perform a HTTP GET (default)", NULL }, - { "put", 'p', POPT_ARG_NONE, NULL, 'p', "Perform a HTTP PUT", NULL }, - { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, -+ { "post", 'o', POPT_ARG_NONE, NULL, 'o', "Perform a HTTP POST", NULL }, - { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "Print response code and body", NULL }, - POPT_TABLEEND - }; -@@ -118,6 +119,9 @@ int main(int argc, const char *argv[]) - case 'd': - req_type = TCURL_HTTP_DELETE; - break; -+ case 'o': -+ req_type = TCURL_HTTP_POST; -+ break; - case 'v': - pc_verbose = 1; - break; -@@ -145,6 +149,7 @@ int main(int argc, const char *argv[]) - switch (req_type) { - case TCURL_HTTP_GET: - case TCURL_HTTP_DELETE: -+ case TCURL_HTTP_POST: - urls[n_reqs++] = extra_arg_ptr; - break; - case TCURL_HTTP_PUT: -diff --git a/src/util/tev_curl.c b/src/util/tev_curl.c -index fd436653b5aeb611a9648a8b81a330fd3fcfe875..645d1182d10f825f209f48e0ba7e6804dde1971c 100644 ---- a/src/util/tev_curl.c -+++ b/src/util/tev_curl.c -@@ -154,6 +154,8 @@ static const char *http_req2str(enum tcurl_http_request req) - return "PUT"; - case TCURL_HTTP_DELETE: - return "DELETE"; -+ case TCURL_HTTP_POST: -+ return "POST"; - } - - return "Uknown request type"; -@@ -815,6 +817,11 @@ static errno_t tcurl_set_options(struct tcurl_http_state *state, - } - - switch (req_type) { -+ case TCURL_HTTP_POST: -+ crv = curl_easy_setopt(state->http_handle, -+ CURLOPT_CUSTOMREQUEST, -+ "POST"); -+ break; - case TCURL_HTTP_PUT: - /* CURLOPT_UPLOAD enables HTTP_PUT */ - crv = curl_easy_setopt(state->http_handle, -diff --git a/src/util/tev_curl.h b/src/util/tev_curl.h -index de0601df4327d97001a8a825cd4709936f6c8466..444eb286e09d189b4588e2b2152b5202df3914d8 100644 ---- a/src/util/tev_curl.h -+++ b/src/util/tev_curl.h -@@ -34,6 +34,7 @@ enum tcurl_http_request { - TCURL_HTTP_GET, - TCURL_HTTP_PUT, - TCURL_HTTP_DELETE, -+ TCURL_HTTP_POST, - }; - - /** --- -2.12.2 - diff --git a/0035-KCM-Store-ccaches-in-secrets.patch b/0035-KCM-Store-ccaches-in-secrets.patch deleted file mode 100644 index 5f763f7..0000000 --- a/0035-KCM-Store-ccaches-in-secrets.patch +++ /dev/null @@ -1,3787 +0,0 @@ -From cac0db2f8004ae88b9263dc3888a11a2d3d3d114 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 20 Mar 2017 11:49:43 +0100 -Subject: [PATCH 35/97] KCM: Store ccaches in secrets -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Adds a new KCM responder ccache back end that forwards all requests to -sssd-secrets. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - Makefile.am | 40 +- - contrib/sssd.spec.in | 1 + - src/responder/kcm/kcmsrv_ccache.h | 49 + - src/responder/kcm/kcmsrv_ccache_json.c | 921 +++++++++++ - src/responder/kcm/kcmsrv_ccache_secrets.c | 2169 ++++++++++++++++++++++++++ - src/tests/cmocka/test_kcm_json_marshalling.c | 234 +++ - src/tests/intg/test_kcm.py | 132 +- - src/util/util_errors.c | 2 + - src/util/util_errors.h | 2 + - 9 files changed, 3525 insertions(+), 25 deletions(-) - create mode 100644 src/responder/kcm/kcmsrv_ccache_json.c - create mode 100644 src/responder/kcm/kcmsrv_ccache_secrets.c - create mode 100644 src/tests/cmocka/test_kcm_json_marshalling.c - -diff --git a/Makefile.am b/Makefile.am -index 49b4cabf9ee3ce1417f955c972376894f3709b33..e9eaa312c91e3aee40bcf13c90a0ad8c683045d5 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -303,6 +303,10 @@ if HAVE_INOTIFY - non_interactive_cmocka_based_tests += test_inotify - endif # HAVE_INOTIFY - -+if BUILD_KCM -+non_interactive_cmocka_based_tests += test_kcm_json -+endif # BUILD_KCM -+ - if BUILD_SAMBA - non_interactive_cmocka_based_tests += \ - ad_access_filter_tests \ -@@ -1494,19 +1498,26 @@ sssd_kcm_SOURCES = \ - src/responder/kcm/kcmsrv_cmd.c \ - src/responder/kcm/kcmsrv_ccache.c \ - src/responder/kcm/kcmsrv_ccache_mem.c \ -+ src/responder/kcm/kcmsrv_ccache_json.c \ -+ src/responder/kcm/kcmsrv_ccache_secrets.c \ - src/responder/kcm/kcmsrv_ops.c \ - src/util/sss_sockets.c \ - src/util/sss_krb5.c \ - src/util/sss_iobuf.c \ -+ src/util/tev_curl.c \ - $(SSSD_RESPONDER_OBJ) \ - $(NULL) - sssd_kcm_CFLAGS = \ - $(AM_CFLAGS) \ - $(KRB5_CFLAGS) \ - $(UUID_CFLAGS) \ -+ $(CURL_CFLAGS) \ -+ $(JANSSON_CFLAGS) \ - $(NULL) - sssd_kcm_LDADD = \ - $(KRB5_LIBS) \ -+ $(CURL_LIBS) \ -+ $(JANSSON_LIBS) \ - $(SSSD_LIBS) \ - $(UUID_LIBS) \ - $(SYSTEMD_DAEMON_LIBS) \ -@@ -3369,6 +3380,30 @@ sss_certmap_test_LDADD = \ - libsss_certmap.la \ - $(NULL) - endif -+ -+if BUILD_KCM -+test_kcm_json_SOURCES = \ -+ src/tests/cmocka/test_kcm_json_marshalling.c \ -+ src/responder/kcm/kcmsrv_ccache_json.c \ -+ src/responder/kcm/kcmsrv_ccache.c \ -+ src/util/sss_krb5.c \ -+ src/util/sss_iobuf.c \ -+ $(NULL) -+test_kcm_json_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(UUID_CFLAGS) \ -+ $(NULL) -+test_kcm_json_LDADD = \ -+ $(JANSSON_LIBS) \ -+ $(UUID_LIBS) \ -+ $(KRB5_LIBS) \ -+ $(CMOCKA_LIBS) \ -+ $(SSSD_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_test_common.la \ -+ $(NULL) -+endif # BUILD_KCM -+ - endif # HAVE_CMOCKA - - noinst_PROGRAMS = pam_test_client -@@ -3431,8 +3466,9 @@ intgcheck-prepare: - --enable-intgcheck-reqs \ - --without-semanage \ - --enable-files-domain \ -- $(INTGCHECK_CONFIGURE_FLAGS); \ -- $(MAKE) $(AM_MAKEFLAGS); \ -+ $(INTGCHECK_CONFIGURE_FLAGS) \ -+ CFLAGS="$$CFLAGS $(AM_CFLAGS) -DKCM_PEER_UID=$$(id -u)"; \ -+ $(MAKE) $(AM_MAKEFLAGS) ; \ - : Force single-thread install to workaround concurrency issues; \ - $(MAKE) $(AM_MAKEFLAGS) -j1 install; \ - : Remove .la files from LDB module directory to avoid loader warnings; \ -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 1d4d020415ee28292bb4d88c78de205465d812f1..af14d4e3d6b9ffeb4696f1517113b8daa575cb99 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -223,6 +223,7 @@ BuildRequires: systemtap-sdt-devel - BuildRequires: http-parser-devel - BuildRequires: jansson-devel - BuildRequires: libuuid-devel -+BuildRequires: libcurl-devel - - %description - Provides a set of daemons to manage access to remote directories and -diff --git a/src/responder/kcm/kcmsrv_ccache.h b/src/responder/kcm/kcmsrv_ccache.h -index 130ae48ae30d5e1e2ab238a647a9b9dc76cc4945..18c8c47ad4ecb24521a85a1833b239c7a2a8bb45 100644 ---- a/src/responder/kcm/kcmsrv_ccache.h -+++ b/src/responder/kcm/kcmsrv_ccache.h -@@ -303,4 +303,53 @@ void kcm_debug_uuid(uuid_t uuid); - */ - errno_t kcm_check_name(const char *name, struct cli_creds *client); - -+/* -+ * ccahe marshalling to and from JSON. This is used when the ccaches -+ * are stored in the secrets store -+ */ -+ -+/* -+ * The secrets store is a key-value store at heart. We store the UUID -+ * and the name in the key to allow easy lookups be either key -+ */ -+bool sec_key_match_name(const char *sec_key, -+ const char *name); -+ -+bool sec_key_match_uuid(const char *sec_key, -+ uuid_t uuid); -+ -+const char *sec_key_get_name(const char *sec_key); -+ -+errno_t sec_key_get_uuid(const char *sec_key, -+ uuid_t uuid); -+ -+/* Create a URL for the default client's ccache */ -+const char *sec_dfl_url_create(TALLOC_CTX *mem_ctx, -+ struct cli_creds *client); -+ -+/* Create a URL for the client's ccache container */ -+const char *sec_container_url_create(TALLOC_CTX *mem_ctx, -+ struct cli_creds *client); -+ -+const char *sec_cc_url_create(TALLOC_CTX *mem_ctx, -+ struct cli_creds *client, -+ const char *sec_key); -+ -+/* -+ * sec_key is a concatenation of the ccache's UUID and name -+ * sec_value is the JSON dump of the ccache contents -+ */ -+errno_t sec_kv_to_ccache(TALLOC_CTX *mem_ctx, -+ const char *sec_key, -+ const char *sec_value, -+ struct cli_creds *client, -+ struct kcm_ccache **_cc); -+ -+/* Convert a kcm_ccache to a key-value pair to be stored in secrets */ -+errno_t kcm_ccache_to_sec_input(TALLOC_CTX *mem_ctx, -+ struct kcm_ccache *cc, -+ struct cli_creds *client, -+ const char **_url, -+ struct sss_iobuf **_payload); -+ - #endif /* _KCMSRV_CCACHE_H_ */ -diff --git a/src/responder/kcm/kcmsrv_ccache_json.c b/src/responder/kcm/kcmsrv_ccache_json.c -new file mode 100644 -index 0000000000000000000000000000000000000000..40b64861c209206d6f60ccd0843857edee24a844 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ccache_json.c -@@ -0,0 +1,921 @@ -+/* -+ SSSD -+ -+ KCM Server - ccache JSON (un)marshalling for storing ccaches in -+ sssd-secrets -+ -+ Copyright (C) Red Hat, 2017 -+ -+ 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 -+#include -+ -+#include "util/util.h" -+#include "util/util_creds.h" -+#include "util/crypto/sss_crypto.h" -+#include "responder/kcm/kcmsrv_ccache_pvt.h" -+ -+/* The base for storing secrets is: -+ * http://localhost/kcm/persistent/$uid -+ * -+ * Under $base, there are two containers: -+ * /ccache - stores the ccaches -+ * /ntlm - stores NTLM creds [Not implement yet] -+ * -+ * There is also a special entry that contains the UUID of the default -+ * cache for this UID: -+ * /default - stores the UUID of the default ccache for this UID -+ * -+ * Each ccache has a name and an UUID. On the secrets level, the 'secret' -+ * is a concatenation of the stringified UUID and the name separated -+ * by a plus-sign. -+ */ -+#define KCM_SEC_URL "http://localhost/kcm/persistent" -+#define KCM_SEC_BASE_FMT KCM_SEC_URL"/%"SPRIuid"/" -+#define KCM_SEC_CCACHE_FMT KCM_SEC_BASE_FMT"ccache/" -+#define KCM_SEC_DFL_FMT KCM_SEC_BASE_FMT"default" -+ -+ -+/* -+ * We keep the JSON representation of the ccache versioned to allow -+ * us to modify the format in a future version -+ */ -+#define KS_JSON_VERSION 1 -+ -+/* -+ * The secrets store is a key-value store at heart. We store the UUID -+ * and the name in the key to allow easy lookups be either key -+ */ -+#define SEC_KEY_SEPARATOR '-' -+ -+/* Compat definition of json_array_foreach for older systems */ -+#ifndef json_array_foreach -+#define json_array_foreach(array, idx, value) \ -+ for(idx = 0; \ -+ idx < json_array_size(array) && (value = json_array_get(array, idx)); \ -+ idx++) -+#endif -+ -+const char *sec_container_url_create(TALLOC_CTX *mem_ctx, -+ struct cli_creds *client) -+{ -+ return talloc_asprintf(mem_ctx, -+ KCM_SEC_CCACHE_FMT, -+ cli_creds_get_uid(client)); -+} -+ -+const char *sec_cc_url_create(TALLOC_CTX *mem_ctx, -+ struct cli_creds *client, -+ const char *sec_key) -+{ -+ return talloc_asprintf(mem_ctx, -+ KCM_SEC_CCACHE_FMT"%s", -+ cli_creds_get_uid(client), -+ sec_key); -+} -+ -+const char *sec_dfl_url_create(TALLOC_CTX *mem_ctx, -+ struct cli_creds *client) -+{ -+ return talloc_asprintf(mem_ctx, -+ KCM_SEC_DFL_FMT, -+ cli_creds_get_uid(client)); -+} -+ -+static const char *sec_key_create(TALLOC_CTX *mem_ctx, -+ const char *name, -+ uuid_t uuid) -+{ -+ char uuid_str[UUID_STR_SIZE]; -+ -+ uuid_unparse(uuid, uuid_str); -+ return talloc_asprintf(mem_ctx, -+ "%s%c%s", uuid_str, SEC_KEY_SEPARATOR, name); -+} -+ -+static errno_t sec_key_parse(TALLOC_CTX *mem_ctx, -+ const char *sec_key, -+ const char **_name, -+ uuid_t uuid) -+{ -+ char uuid_str[UUID_STR_SIZE]; -+ -+ if (strlen(sec_key) < UUID_STR_SIZE + 2) { -+ /* One char for separator and at least one for the name */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key); -+ return EINVAL; -+ } -+ -+ strncpy(uuid_str, sec_key, sizeof(uuid_str)-1); -+ if (sec_key[UUID_STR_SIZE - 1] != SEC_KEY_SEPARATOR) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n"); -+ return EINVAL; -+ } -+ uuid_str[UUID_STR_SIZE-1] = '\0'; -+ -+ *_name = talloc_strdup(mem_ctx, sec_key + UUID_STR_SIZE); -+ if (*_name == NULL) { -+ return ENOMEM; -+ } -+ uuid_parse(uuid_str, uuid); -+ -+ return EOK; -+} -+ -+errno_t sec_key_get_uuid(const char *sec_key, -+ uuid_t uuid) -+{ -+ char uuid_str[UUID_STR_SIZE]; -+ -+ if (strlen(sec_key) < UUID_STR_SIZE + 2) { -+ /* One char for separator and at least one for the name */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key); -+ return EINVAL; -+ } -+ -+ if (sec_key[UUID_STR_SIZE-1] != SEC_KEY_SEPARATOR) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n"); -+ return EINVAL; -+ } -+ -+ strncpy(uuid_str, sec_key, UUID_STR_SIZE-1); -+ uuid_str[UUID_STR_SIZE-1] = '\0'; -+ uuid_parse(uuid_str, uuid); -+ return EOK; -+} -+ -+const char *sec_key_get_name(const char *sec_key) -+{ -+ if (strlen(sec_key) < UUID_STR_SIZE + 2) { -+ /* One char for separator and at least one for the name */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key); -+ return NULL; -+ } -+ -+ return sec_key + UUID_STR_SIZE; -+} -+ -+bool sec_key_match_name(const char *sec_key, -+ const char *name) -+{ -+ if (strlen(sec_key) < UUID_STR_SIZE + 2) { -+ /* One char for separator and at least one for the name */ -+ DEBUG(SSSDBG_MINOR_FAILURE, "Key %s is too short\n", sec_key); -+ return false; -+ } -+ -+ return strcmp(sec_key + UUID_STR_SIZE, name) == 0; -+} -+ -+bool sec_key_match_uuid(const char *sec_key, -+ uuid_t uuid) -+{ -+ errno_t ret; -+ uuid_t key_uuid; -+ -+ ret = sec_key_get_uuid(sec_key, key_uuid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot convert key to UUID\n"); -+ return false; -+ } -+ -+ return uuid_compare(key_uuid, uuid) == 0; -+} -+ -+/* -+ * Creates an array of principal elements that will be used later -+ * in the form of: -+ * "componenets": [ "elem1", "elem2", ...] -+ */ -+static json_t *princ_data_to_json(TALLOC_CTX *mem_ctx, -+ krb5_principal princ) -+{ -+ json_t *jdata = NULL; -+ json_t *data_array = NULL; -+ int ret; -+ char *str_princ_data; -+ -+ data_array = json_array(); -+ if (data_array == NULL) { -+ return NULL; -+ } -+ -+ for (ssize_t i = 0; i < princ->length; i++) { -+ /* FIXME - it might be cleaner to use stringn here, but the libjansson -+ * version on RHEL-7 doesn't support that -+ */ -+ str_princ_data = talloc_zero_array(mem_ctx, -+ char, -+ princ->data[i].length + 1); -+ if (str_princ_data == NULL) { -+ return NULL; -+ } -+ memcpy(str_princ_data, princ->data[i].data, princ->data[i].length); -+ str_princ_data[princ->data[i].length] = '\0'; -+ -+ jdata = json_string(str_princ_data); -+ talloc_free(str_princ_data); -+ if (jdata == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert principal data to string\n"); -+ json_decref(data_array); -+ return NULL; -+ } -+ -+ ret = json_array_append_new(data_array, jdata); -+ if (ret != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot append principal data to array\n"); -+ json_decref(jdata); -+ json_decref(data_array); -+ return NULL; -+ } -+ /* data_array now owns the reference to jdata */ -+ } -+ -+ return data_array; -+} -+ -+/* Creates: -+ * { -+ * "type": "number", -+ * "realm": "string", -+ * "componenents": [ "elem1", "elem2", ...] -+ * } -+ */ -+static json_t *princ_to_json(TALLOC_CTX *mem_ctx, -+ krb5_principal princ) -+{ -+ json_t *jprinc = NULL; -+ json_t *components = NULL; -+ json_error_t error; -+ char *str_realm_data; -+ -+ components = princ_data_to_json(mem_ctx, princ); -+ if (components == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert principal data to JSON\n"); -+ return NULL; -+ } -+ -+ /* FIXME - it might be cleaner to use the s% specifier here, but the libjansson -+ * version on RHEL-7 doesn't support that -+ */ -+ str_realm_data = talloc_zero_array(mem_ctx, -+ char, -+ princ->realm.length + 1); -+ if (str_realm_data == NULL) { -+ return NULL; -+ } -+ memcpy(str_realm_data, princ->realm.data, princ->realm.length); -+ str_realm_data[princ->realm.length] = '\0'; -+ -+ jprinc = json_pack_ex(&error, -+ JSON_STRICT, -+ "{s:i, s:s, s:o}", -+ "type", princ->type, -+ "realm", str_realm_data, -+ "components", components); -+ talloc_free(str_realm_data); -+ if (jprinc == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to pack JSON princ structure on line %d: %s\n", -+ error.line, error.text); -+ json_decref(components); -+ return NULL; -+ } -+ -+ return jprinc; -+} -+ -+/* Creates: -+ * { -+ * "uuid": , -+ * "payload": , -+ * }, -+ */ -+static json_t *cred_to_json(struct kcm_cred *crd) -+{ -+ char uuid_str[UUID_STR_SIZE]; -+ uint8_t *cred_blob_data; -+ size_t cred_blob_size; -+ json_t *jcred; -+ json_error_t error; -+ char *base64_cred_blob; -+ -+ uuid_unparse(crd->uuid, uuid_str); -+ cred_blob_data = sss_iobuf_get_data(crd->cred_blob); -+ cred_blob_size = sss_iobuf_get_size(crd->cred_blob); -+ -+ base64_cred_blob = sss_base64_encode(crd, cred_blob_data, cred_blob_size); -+ if (base64_cred_blob == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot base64 encode the certificate blob\n"); -+ return NULL; -+ } -+ -+ jcred = json_pack_ex(&error, -+ JSON_STRICT, -+ "{s:s, s:s}", -+ "uuid", uuid_str, -+ "payload", base64_cred_blob); -+ talloc_free(base64_cred_blob); -+ if (jcred == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to pack JSON cred structure on line %d: %s\n", -+ error.line, error.text); -+ return NULL; -+ } -+ return jcred; -+} -+ -+/* -+ * Creates: -+ * [ -+ * { -+ * "uuid": , -+ * "payload": , -+ * }, -+ * ... -+ * ] -+ */ -+static json_t *creds_to_json_array(struct kcm_cred *creds) -+{ -+ struct kcm_cred *crd; -+ json_t *array; -+ json_t *jcred; -+ -+ array = json_array(); -+ if (array == NULL) { -+ return NULL; -+ } -+ -+ DLIST_FOR_EACH(crd, creds) { -+ jcred = cred_to_json(crd); -+ if (jcred == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert credentials to JSON\n"); -+ json_decref(array); -+ return NULL; -+ } -+ -+ json_array_append_new(array, jcred); -+ /* array now owns jcred */ -+ jcred = NULL; -+ } -+ -+ return array; -+} -+ -+/* -+ * The ccache is formatted in JSON as: -+ * { -+ * version: number -+ * kdc_offset: number -+ * principal : { -+ * "type": "number", -+ * "realm": "string", -+ * "componenents": [ "elem1", "elem2", ...] -+ * } -+ * creds : [ -+ * { -+ * "uuid": , -+ * "payload": , -+ * }, -+ * { -+ * ... -+ * } -+ * ] -+ * } -+ * } -+ */ -+static json_t *ccache_to_json(struct kcm_ccache *cc) -+{ -+ json_t *princ = NULL; -+ json_t *creds = NULL; -+ json_t *jcc = NULL; -+ json_error_t error; -+ -+ princ = princ_to_json(cc, cc->client); -+ if (princ == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert princ to JSON\n"); -+ return NULL; -+ } -+ -+ creds = creds_to_json_array(cc->creds); -+ if (creds == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert creds to JSON array\n"); -+ json_decref(princ); -+ return NULL; -+ } -+ -+ jcc = json_pack_ex(&error, -+ JSON_STRICT, -+ "{s:i, s:i, s:o, s:o}", -+ "version", KS_JSON_VERSION, -+ "kdc_offset", cc->kdc_offset, -+ "principal", princ, -+ "creds", creds); -+ if (jcc == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to pack JSON ccache structure on line %d: %s\n", -+ error.line, error.text); -+ json_decref(creds); -+ json_decref(princ); -+ return NULL; -+ } -+ -+ return jcc; -+} -+ -+static errno_t ccache_to_sec_kv(TALLOC_CTX *mem_ctx, -+ struct kcm_ccache *cc, -+ const char **_sec_key, -+ const char **_sec_value) -+{ -+ json_t *jcc = NULL; -+ char *jdump; -+ -+ jcc = ccache_to_json(cc); -+ if (jcc == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert ccache to JSON\n"); -+ return ERR_JSON_ENCODING; -+ } -+ -+ /* it would be more efficient to learn the size with json_dumpb and -+ * a NULL buffer, but that's only available since 2.10 -+ */ -+ jdump = json_dumps(jcc, JSON_INDENT(4) | JSON_ENSURE_ASCII); -+ if (jdump == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot dump JSON\n"); -+ return ERR_JSON_ENCODING; -+ } -+ -+ *_sec_key = sec_key_create(mem_ctx, cc->name, cc->uuid); -+ *_sec_value = talloc_strdup(mem_ctx, jdump); -+ free(jdump); -+ json_decref(jcc); -+ if (*_sec_key == NULL || *_sec_value == NULL) { -+ return ENOMEM; -+ } -+ -+ return EOK; -+} -+ -+errno_t kcm_ccache_to_sec_input(TALLOC_CTX *mem_ctx, -+ struct kcm_ccache *cc, -+ struct cli_creds *client, -+ const char **_url, -+ struct sss_iobuf **_payload) -+{ -+ errno_t ret; -+ const char *key; -+ const char *value; -+ const char *url; -+ struct sss_iobuf *payload; -+ TALLOC_CTX *tmp_ctx; -+ -+ tmp_ctx = talloc_new(mem_ctx); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = ccache_to_sec_kv(mem_ctx, cc, &key, &value); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert cache %s to JSON [%d]: %s\n", -+ cc->name, ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ url = sec_cc_url_create(tmp_ctx, client, key); -+ if (url == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ payload = sss_iobuf_init_readonly(tmp_ctx, -+ (const uint8_t *) value, -+ strlen(value)+1); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot create payload buffer\n"); -+ goto done; -+ } -+ -+ ret = EOK; -+ *_url = talloc_steal(mem_ctx, url); -+ *_payload = talloc_steal(mem_ctx, payload); -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t sec_value_to_json(const char *input, -+ json_t **_root) -+{ -+ json_t *root = NULL; -+ json_error_t error; -+ int ok; -+ -+ root = json_loads(input, 0, &error); -+ if (root == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to parse JSON payload on line %d: %s\n", -+ error.line, error.text); -+ return ERR_JSON_DECODING; -+ } -+ -+ ok = json_is_object(root); -+ if (!ok) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Json data is not an object.\n"); -+ json_decref(root); -+ return ERR_JSON_DECODING; -+ } -+ -+ *_root = root; -+ return EOK; -+} -+ -+/* -+ * ccache unmarshalling from JSON -+ */ -+static errno_t json_element_to_krb5_data(TALLOC_CTX *mem_ctx, -+ json_t *element, -+ krb5_data *data) -+{ -+ const char *str_value; -+ size_t str_len; -+ -+ /* FIXME - it might be cleaner to use stringn here, but the libjansson -+ * version on RHEL-7 doesn't support that -+ */ -+ str_value = json_string_value(element); -+ if (str_value == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "JSON element not a string\n"); -+ return EINVAL; -+ } -+ str_len = strlen(str_value); -+ -+ data->data = talloc_strndup(mem_ctx, str_value, str_len); -+ if (data->data == NULL) { -+ return ENOMEM; -+ } -+ data->length = str_len; -+ -+ return EOK; -+} -+ -+static errno_t json_array_to_krb5_data(TALLOC_CTX *mem_ctx, -+ json_t *array, -+ krb5_data **_data, -+ size_t *_len) -+{ -+ errno_t ret; -+ int ok; -+ size_t len; -+ size_t idx; -+ json_t *element; -+ krb5_data *data; -+ -+ ok = json_is_array(array); -+ if (!ok) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Json object is not an array.\n"); -+ return ERR_JSON_DECODING; -+ } -+ -+ len = json_array_size(array); -+ if (len == 0) { -+ *_data = NULL; -+ *_len = 0; -+ return EOK; -+ } -+ -+ data = talloc_zero_array(mem_ctx, krb5_data, len); -+ if (data == NULL) { -+ return ENOMEM; -+ } -+ -+ json_array_foreach(array, idx, element) { -+ ret = json_element_to_krb5_data(data, element, &data[idx]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert krb5 data element from JSON"); -+ talloc_free(data); -+ return ret; -+ } -+ } -+ -+ *_data = data; -+ *_len = len; -+ return EOK; -+} -+ -+static errno_t json_to_princ(TALLOC_CTX *mem_ctx, -+ json_t *js_princ, -+ krb5_principal *_princ) -+{ -+ errno_t ret; -+ json_t *components = NULL; -+ int ok; -+ krb5_principal princ = NULL; -+ TALLOC_CTX *tmp_ctx = NULL; -+ char *realm_str; -+ size_t realm_size; -+ json_error_t error; -+ -+ ok = json_is_object(js_princ); -+ if (!ok) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Json principal is not an object.\n"); -+ ret = ERR_JSON_DECODING; -+ goto done; -+ } -+ -+ tmp_ctx = talloc_new(mem_ctx); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ princ = talloc_zero(tmp_ctx, struct krb5_principal_data); -+ if (princ == NULL) { -+ return ENOMEM; -+ } -+ princ->magic = KV5M_PRINCIPAL; -+ -+ /* FIXME - it might be cleaner to use the s% specifier here, but the libjansson -+ * version on RHEL-7 doesn't support that -+ */ -+ ret = json_unpack_ex(js_princ, -+ &error, -+ JSON_STRICT, -+ "{s:i, s:s, s:o}", -+ "type", &princ->type, -+ "realm", &realm_str, -+ "components", &components); -+ if (ret != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to unpack JSON princ structure on line %d: %s\n", -+ error.line, error.text); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ realm_size = strlen(realm_str); -+ -+ princ->realm.data = talloc_strndup(mem_ctx, realm_str, realm_size); -+ if (princ->realm.data == NULL) { -+ return ENOMEM; -+ } -+ princ->realm.length = realm_size; -+ princ->realm.magic = 0; -+ -+ ret = json_array_to_krb5_data(princ, components, -+ &princ->data, -+ (size_t *) &princ->length); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert principal from JSON"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ *_princ = talloc_steal(mem_ctx, princ); -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t json_elem_to_cred(TALLOC_CTX *mem_ctx, -+ json_t *element, -+ struct kcm_cred **_crd) -+{ -+ errno_t ret; -+ char *uuid_str; -+ json_error_t error; -+ uuid_t uuid; -+ struct sss_iobuf *cred_blob; -+ const char *base64_cred_blob; -+ struct kcm_cred *crd; -+ uint8_t *outbuf; -+ size_t outbuf_size; -+ TALLOC_CTX *tmp_ctx = NULL; -+ -+ ret = json_unpack_ex(element, -+ &error, -+ JSON_STRICT, -+ "{s:s, s:s}", -+ "uuid", &uuid_str, -+ "payload", &base64_cred_blob); -+ if (ret != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to unpack JSON cred structure on line %d: %s\n", -+ error.line, error.text); -+ return EINVAL; -+ } -+ -+ uuid_parse(uuid_str, uuid); -+ -+ tmp_ctx = talloc_new(mem_ctx); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ outbuf = sss_base64_decode(tmp_ctx, base64_cred_blob, &outbuf_size); -+ if (outbuf == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot decode cred blob\n"); -+ ret = EIO; -+ goto done; -+ } -+ -+ cred_blob = sss_iobuf_init_readonly(tmp_ctx, outbuf, outbuf_size); -+ if (cred_blob == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ crd = kcm_cred_new(tmp_ctx, uuid, cred_blob); -+ if (crd == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = EOK; -+ *_crd = talloc_steal(mem_ctx, crd); -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t json_to_creds(struct kcm_ccache *cc, -+ json_t *jcreds) -+{ -+ errno_t ret; -+ int ok; -+ size_t idx; -+ json_t *value; -+ struct kcm_cred *crd; -+ -+ ok = json_is_array(jcreds); -+ if (!ok) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Json creds object is not an array.\n"); -+ return ERR_JSON_DECODING; -+ } -+ -+ json_array_foreach(jcreds, idx, value) { -+ ret = json_elem_to_cred(cc, value, &crd); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert JSON cred element [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ -+ ret = kcm_cc_store_creds(cc, crd); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot store creds in ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ } -+ -+ return EOK; -+} -+ -+static errno_t sec_json_value_to_ccache(struct kcm_ccache *cc, -+ json_t *root) -+{ -+ errno_t ret; -+ json_t *princ = NULL; -+ json_t *creds = NULL; -+ json_error_t error; -+ int version; -+ -+ ret = json_unpack_ex(root, -+ &error, -+ JSON_STRICT, -+ "{s:i, s:i, s:o, s:o}", -+ "version", &version, -+ "kdc_offset", &cc->kdc_offset, -+ "principal", &princ, -+ "creds", &creds); -+ if (ret != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to unpack JSON creds structure on line %d: %s\n", -+ error.line, error.text); -+ return EINVAL; -+ } -+ -+ if (version != KS_JSON_VERSION) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Expected version %d, received version %d\n", -+ KS_JSON_VERSION, version); -+ return EINVAL; -+ } -+ -+ ret = json_to_princ(cc, princ, &cc->client); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot store JSON to principal [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ -+ ret = json_to_creds(cc, creds); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot store JSON to creds [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return EOK; -+ } -+ -+ return EOK; -+} -+ -+/* -+ * sec_key is a concatenation of the ccache's UUID and name -+ * sec_value is the JSON dump of the ccache contents -+ */ -+errno_t sec_kv_to_ccache(TALLOC_CTX *mem_ctx, -+ const char *sec_key, -+ const char *sec_value, -+ struct cli_creds *client, -+ struct kcm_ccache **_cc) -+{ -+ errno_t ret; -+ json_t *root = NULL; -+ struct kcm_ccache *cc = NULL; -+ TALLOC_CTX *tmp_ctx = NULL; -+ -+ ret = sec_value_to_json(sec_value, &root); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot store secret to JSN [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ tmp_ctx = talloc_new(mem_ctx); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ cc = talloc_zero(tmp_ctx, struct kcm_ccache); -+ if (cc == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* We rely on sssd-secrets only searching the user's subtree so we -+ * set the ownership to the client -+ */ -+ cc->owner.uid = cli_creds_get_uid(client); -+ cc->owner.gid = cli_creds_get_gid(client); -+ -+ ret = sec_key_parse(cc, sec_key, &cc->name, cc->uuid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannt parse secret key [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = sec_json_value_to_ccache(cc, root); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannt parse secret value [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ *_cc = talloc_steal(mem_ctx, cc); -+done: -+ talloc_free(tmp_ctx); -+ json_decref(root); -+ return ret; -+} -diff --git a/src/responder/kcm/kcmsrv_ccache_secrets.c b/src/responder/kcm/kcmsrv_ccache_secrets.c -new file mode 100644 -index 0000000000000000000000000000000000000000..8be7daea59bd6e04ab8393aae9f8adc29df11c21 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_ccache_secrets.c -@@ -0,0 +1,2169 @@ -+/* -+ SSSD -+ -+ KCM Server - ccache storage in sssd-secrets -+ -+ Copyright (C) Red Hat, 2016 -+ -+ 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 -+#include -+ -+#include "util/util.h" -+#include "util/crypto/sss_crypto.h" -+#include "util/tev_curl.h" -+#include "responder/kcm/kcmsrv_ccache_pvt.h" -+#include "responder/kcm/kcmsrv_ccache_be.h" -+ -+#ifndef SSSD_SECRETS_SOCKET -+#define SSSD_SECRETS_SOCKET VARDIR"/run/secrets.socket" -+#endif /* SSSD_SECRETS_SOCKET */ -+ -+#ifndef SEC_TIMEOUT -+#define SEC_TIMEOUT 5 -+#endif /* SEC_TIMEOUT */ -+ -+/* Just to keep the name of the ccache readable */ -+#define MAX_CC_NUM 99999 -+ -+/* Compat definition of json_array_foreach for older systems */ -+#ifndef json_array_foreach -+#define json_array_foreach(array, idx, value) \ -+ for(idx = 0; \ -+ idx < json_array_size(array) && (value = json_array_get(array, idx)); \ -+ idx++) -+#endif -+ -+static const char *find_by_name(const char **sec_key_list, -+ const char *name) -+{ -+ const char *sec_name = NULL; -+ -+ if (sec_key_list == NULL) { -+ return NULL; -+ } -+ -+ for (int i = 0; sec_key_list[i]; i++) { -+ if (sec_key_match_name(sec_key_list[i], name)) { -+ sec_name = sec_key_list[i]; -+ break; -+ } -+ } -+ -+ return sec_name; -+} -+ -+static const char *find_by_uuid(const char **sec_key_list, -+ uuid_t uuid) -+{ -+ const char *sec_name = NULL; -+ -+ if (sec_key_list == NULL) { -+ return NULL; -+ } -+ -+ for (int i = 0; sec_key_list[i]; i++) { -+ if (sec_key_match_uuid(sec_key_list[i], uuid)) { -+ sec_name = sec_key_list[i]; -+ break; -+ } -+ } -+ -+ return sec_name; -+} -+ -+static const char *sec_headers[] = { -+ "Content-type: application/octet-stream", -+ NULL, -+}; -+ -+struct ccdb_sec { -+ struct tcurl_ctx *tctx; -+}; -+ -+static errno_t http2errno(int http_code) -+{ -+ if (http_code != 200) { -+ DEBUG(SSSDBG_OP_FAILURE, "HTTP request returned %d\n", http_code); -+ } -+ -+ switch (http_code) { -+ case 200: -+ return EOK; -+ case 404: -+ return ERR_NO_CREDS; -+ case 400: -+ return ERR_INPUT_PARSE; -+ case 403: -+ return EACCES; -+ case 409: -+ return EEXIST; -+ case 413: -+ return E2BIG; -+ case 507: -+ return ENOSPC; -+ } -+ -+ return EIO; -+} -+ -+/* -+ * Helper request to list all UUID+name pairs -+ */ -+struct sec_list_state { -+ const char **sec_key_list; -+ size_t sec_key_list_len; -+}; -+ -+static void sec_list_done(struct tevent_req *subreq); -+static errno_t sec_list_parse(struct sss_iobuf *outbuf, -+ TALLOC_CTX *mem_ctx, -+ const char ***_list, -+ size_t *_list_len); -+ -+static struct tevent_req *sec_list_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ccdb_sec *secdb, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct sec_list_state *state = NULL; -+ errno_t ret; -+ const char *container_url; -+ -+ req = tevent_req_create(mem_ctx, &state, struct sec_list_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Listing all ccaches in the secrets store\n"); -+ container_url = sec_container_url_create(state, client); -+ if (container_url == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ subreq = tcurl_http_send(state, ev, secdb->tctx, -+ TCURL_HTTP_GET, -+ SSSD_SECRETS_SOCKET, -+ container_url, -+ sec_headers, -+ NULL, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, sec_list_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void sec_list_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct sec_list_state *state = tevent_req_data(req, -+ struct sec_list_state); -+ struct sss_iobuf *outbuf; -+ int http_code; -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, &outbuf); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "list HTTP request failed [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code == 404) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Nothing to list\n"); -+ /* If no ccaches are found, return an empty list */ -+ state->sec_key_list = talloc_zero_array(state, const char *, 1); -+ if (state->sec_key_list == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ } else if (http_code == 200) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Found %zu items\n", state->sec_key_list_len); -+ ret = sec_list_parse(outbuf, state, -+ &state->sec_key_list, -+ &state->sec_key_list_len); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ } else { -+ tevent_req_error(req, http2errno(http_code)); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "list done\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t sec_list_parse(struct sss_iobuf *outbuf, -+ TALLOC_CTX *mem_ctx, -+ const char ***_list, -+ size_t *_list_len) -+{ -+ json_t *root; -+ uint8_t *sec_http_list; -+ json_error_t error; -+ json_t *element; -+ errno_t ret; -+ int ok; -+ size_t idx; -+ const char **list = NULL; -+ size_t list_len; -+ -+ sec_http_list = sss_iobuf_get_data(outbuf); -+ if (sec_http_list == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "No data in output buffer?\n"); -+ return EINVAL; -+ } -+ -+ root = json_loads((const char *) sec_http_list, 0, &error); -+ if (root == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to parse JSON payload on line %d: %s\n", -+ error.line, error.text); -+ return ERR_JSON_DECODING; -+ } -+ -+ ok = json_is_array(root); -+ if (!ok) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "list reply is not an object.\n"); -+ ret = ERR_JSON_DECODING; -+ goto done; -+ } -+ -+ list_len = json_array_size(root); -+ list = talloc_zero_array(mem_ctx, const char *, list_len + 1); -+ if (list == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ json_array_foreach(root, idx, element) { -+ list[idx] = talloc_strdup(list, json_string_value(element)); -+ if (list[idx] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+ *_list = list; -+ *_list_len = list_len; -+done: -+ if (ret != EOK) { -+ talloc_free(list); -+ } -+ json_decref(root); -+ return ret; -+} -+ -+static errno_t sec_list_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ const char ***_sec_key_list, -+ size_t *_sec_key_list_len) -+ -+{ -+ struct sec_list_state *state = tevent_req_data(req, -+ struct sec_list_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ if (_sec_key_list != NULL) { -+ *_sec_key_list = talloc_steal(mem_ctx, state->sec_key_list); -+ } -+ if (_sec_key_list_len != NULL) { -+ *_sec_key_list_len = state->sec_key_list_len; -+ } -+ return EOK; -+} -+ -+/* -+ * Helper request to get a ccache by key -+ */ -+struct sec_get_state { -+ const char *sec_key; -+ struct cli_creds *client; -+ -+ struct kcm_ccache *cc; -+}; -+ -+static void sec_get_done(struct tevent_req *subreq); -+ -+static struct tevent_req *sec_get_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ccdb_sec *secdb, -+ struct cli_creds *client, -+ const char *sec_key) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct sec_get_state *state = NULL; -+ errno_t ret; -+ const char *cc_url; -+ -+ req = tevent_req_create(mem_ctx, &state, struct sec_get_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->sec_key = sec_key; -+ state->client = client; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Retrieving ccache %s\n", sec_key); -+ -+ cc_url = sec_cc_url_create(state, state->client, state->sec_key); -+ if (cc_url == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ subreq = tcurl_http_send(state, -+ ev, -+ secdb->tctx, -+ TCURL_HTTP_GET, -+ SSSD_SECRETS_SOCKET, -+ cc_url, -+ sec_headers, -+ NULL, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, sec_get_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void sec_get_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct sec_get_state *state = tevent_req_data(req, -+ struct sec_get_state); -+ struct sss_iobuf *outbuf; -+ const char *sec_value; -+ int http_code; -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, &outbuf); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "GET HTTP request failed [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code != 200) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "GET operation returned HTTP error %d\n", http_code); -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ sec_value = (const char *) sss_iobuf_get_data(outbuf); -+ if (sec_value == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "No data in output buffer\n"); -+ tevent_req_error(req, EINVAL); -+ return; -+ } -+ -+ ret = sec_kv_to_ccache(state, -+ state->sec_key, -+ sec_value, -+ state->client, -+ &state->cc); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot convert JSON keyval to ccache blob [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "GET done\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t sec_get_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct sec_get_state *state = tevent_req_data(req, struct sec_get_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+/* -+ * Helper request to get a ccache name or ID -+ */ -+struct sec_get_ccache_state { -+ struct tevent_context *ev; -+ struct ccdb_sec *secdb; -+ struct cli_creds *client; -+ const char *name; -+ uuid_t uuid; -+ -+ const char *sec_key; -+ -+ struct kcm_ccache *cc; -+}; -+ -+static void sec_get_ccache_list_done(struct tevent_req *subreq); -+static void sec_get_ccache_done(struct tevent_req *subreq); -+ -+static struct tevent_req *sec_get_ccache_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ccdb_sec *secdb, -+ struct cli_creds *client, -+ const char *name, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct sec_get_ccache_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct sec_get_ccache_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->secdb = secdb; -+ state->client = client; -+ state->name = name; -+ uuid_copy(state->uuid, uuid); -+ -+ if ((name == NULL && uuid_is_null(uuid)) -+ || (name != NULL && !uuid_is_null(uuid))) { -+ DEBUG(SSSDBG_OP_FAILURE, "Expected one of name, uuid to be set\n"); -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ subreq = sec_list_send(state, ev, secdb, client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, sec_get_ccache_list_done, req); -+ return req; -+ -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void sec_get_ccache_list_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct sec_get_ccache_state *state = tevent_req_data(req, -+ struct sec_get_ccache_state); -+ const char **sec_key_list; -+ -+ ret = sec_list_recv(subreq, state, &sec_key_list, NULL); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot list keys [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (state->name != NULL) { -+ state->sec_key = find_by_name(sec_key_list, state->name); -+ } else { -+ state->sec_key = find_by_uuid(sec_key_list, state->uuid); -+ } -+ -+ if (state->sec_key == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot find item in the ccache list\n"); -+ /* Don't error out, just return an empty list */ -+ tevent_req_done(req); -+ return; -+ } -+ -+ subreq = sec_get_send(state, -+ state->ev, -+ state->secdb, -+ state->client, -+ state->sec_key); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, sec_get_ccache_done, req); -+} -+ -+static void sec_get_ccache_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sec_get_ccache_state *state = tevent_req_data(req, -+ struct sec_get_ccache_state); -+ -+ ret = sec_get_recv(subreq, state, &state->cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot resolve key to ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t sec_get_ccache_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct sec_get_ccache_state *state = tevent_req_data(req, -+ struct sec_get_ccache_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+/* -+ * The actual sssd-secrets back end -+ */ -+static errno_t ccdb_sec_init(struct kcm_ccdb *db) -+{ -+ struct ccdb_sec *secdb = NULL; -+ -+ secdb = talloc_zero(db, struct ccdb_sec); -+ if (secdb == NULL) { -+ return ENOMEM; -+ } -+ -+ secdb->tctx = tcurl_init(secdb, db->ev); -+ if (secdb->tctx == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Cannot initialize tcurl\n"); -+ talloc_zfree(secdb); -+ return ENOMEM; -+ } -+ -+ /* We just need the random numbers to generate pseudo-random ccache names -+ * and avoid conflicts */ -+ srand(time(NULL)); -+ -+ db->db_handle = secdb; -+ return EOK; -+} -+ -+/* -+ * Helper request to get a ccache by key -+ */ -+struct sec_patch_state { -+ struct tevent_context *ev; -+ struct ccdb_sec *secdb; -+ struct cli_creds *client; -+ -+ const char *sec_key_url; -+ struct sss_iobuf *sec_value; -+}; -+ -+static void sec_patch_del_done(struct tevent_req *subreq); -+static void sec_patch_put_done(struct tevent_req *subreq); -+ -+static struct tevent_req *sec_patch_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ccdb_sec *secdb, -+ struct cli_creds *client, -+ const char *sec_key_url, -+ struct sss_iobuf *sec_value) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct sec_patch_state *state = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct sec_patch_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->secdb = secdb; -+ state->client = client; -+ state->sec_key_url = sec_key_url; -+ state->sec_value = sec_value; -+ -+ subreq = tcurl_http_send(state, state->ev, -+ state->secdb->tctx, -+ TCURL_HTTP_DELETE, -+ SSSD_SECRETS_SOCKET, -+ state->sec_key_url, -+ sec_headers, -+ NULL, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, sec_patch_del_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void sec_patch_del_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sec_patch_state *state = tevent_req_data(req, -+ struct sec_patch_state); -+ int http_code; -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, NULL); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot delete key [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code == 404) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Key %s does not exist, moving on\n", state->sec_key_url); -+ } else if (http_code != 200) { -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Adding new payload\n"); -+ -+ subreq = tcurl_http_send(state, -+ state->ev, -+ state->secdb->tctx, -+ TCURL_HTTP_PUT, -+ SSSD_SECRETS_SOCKET, -+ state->sec_key_url, -+ sec_headers, -+ state->sec_value, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, sec_patch_put_done, req); -+} -+ -+static void sec_patch_put_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sec_patch_state *state = tevent_req_data(req, -+ struct sec_patch_state); -+ int http_code; -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, NULL); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot put new value [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code != 200) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to add the payload\n"); -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "payload created\n"); -+ tevent_req_done(req); -+} -+ -+ -+static errno_t sec_patch_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+/* The operations between the KCM and sssd-secrets */ -+ -+struct ccdb_sec_nextid_state { -+ struct tevent_context *ev; -+ struct ccdb_sec *secdb; -+ struct cli_creds *client; -+ -+ unsigned int nextid; -+ char *nextid_name; -+ -+ int maxtries; -+ int numtry; -+}; -+ -+static errno_t ccdb_sec_nextid_generate(struct tevent_req *req); -+static void ccdb_sec_nextid_list_done(struct tevent_req *subreq); -+ -+/* Generate a unique ID */ -+/* GET the name from secrets, if doesn't exist, OK, if exists, try again */ -+static struct tevent_req *ccdb_sec_nextid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct ccdb_sec_nextid_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_nextid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->secdb = secdb; -+ state->client = client; -+ -+ state->maxtries = 3; -+ state->numtry = 0; -+ -+ ret = ccdb_sec_nextid_generate(req); -+ if (ret != EOK) { -+ goto immediate; -+ } -+ -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t ccdb_sec_nextid_generate(struct tevent_req *req) -+{ -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_nextid_state *state = tevent_req_data(req, -+ struct ccdb_sec_nextid_state); -+ -+ if (state->numtry >= state->maxtries) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to find a random ccache in %d tries\n", state->numtry); -+ return EBUSY; -+ } -+ -+ state->nextid = rand() % MAX_CC_NUM; -+ state->nextid_name = talloc_asprintf(state, "%"SPRIuid":%u", -+ cli_creds_get_uid(state->client), -+ state->nextid); -+ if (state->nextid_name == NULL) { -+ return ENOMEM; -+ } -+ -+ subreq = sec_list_send(state, state->ev, state->secdb, state->client); -+ if (subreq == NULL) { -+ return ENOMEM; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_nextid_list_done, req); -+ -+ state->numtry++; -+ return EOK; -+} -+ -+static void ccdb_sec_nextid_list_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_nextid_state *state = tevent_req_data(req, -+ struct ccdb_sec_nextid_state); -+ const char **sec_key_list; -+ size_t sec_key_list_len; -+ size_t i; -+ -+ ret = sec_list_recv(subreq, state, &sec_key_list, &sec_key_list_len); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot list keys [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ for (i = 0; i < sec_key_list_len; i++) { -+ if (sec_key_match_name(sec_key_list[i], state->nextid_name) == true) { -+ break; -+ } -+ } -+ -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Failed to find a random key, trying again..\n"); -+ if (i < sec_key_list_len) { -+ /* Try again */ -+ ret = ccdb_sec_nextid_generate(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Generated new ccache name %u\n", state->nextid); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_nextid_recv(struct tevent_req *req, -+ unsigned int *_nextid) -+{ -+ struct ccdb_sec_nextid_state *state = tevent_req_data(req, -+ struct ccdb_sec_nextid_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_nextid = state->nextid; -+ return EOK; -+} -+ -+/* IN: HTTP PUT $base/default -d 'uuid' */ -+/* We chose only UUID here to avoid issues later with renaming */ -+struct ccdb_sec_set_default_state { -+}; -+ -+static void ccdb_sec_set_default_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_set_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_set_default_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ struct sss_iobuf *uuid_iobuf; -+ errno_t ret; -+ const char *url; -+ char uuid_str[UUID_STR_SIZE]; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_set_default_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ uuid_unparse(uuid, uuid_str); -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Setting the default ccache to %s\n", uuid_str); -+ -+ url = sec_dfl_url_create(state, client); -+ if (url == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ uuid_iobuf = sss_iobuf_init_readonly(state, -+ (uint8_t *) uuid_str, -+ UUID_STR_SIZE); -+ if (uuid_iobuf == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ subreq = sec_patch_send(state, ev, secdb, client, url, uuid_iobuf); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_set_default_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_set_default_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ -+ ret = sec_patch_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sec_patch request failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Set the default ccache\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_set_default_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+/* IN: HTTP GET $base/default */ -+/* OUT: uuid */ -+struct ccdb_sec_get_default_state { -+ uuid_t uuid; -+}; -+ -+static void ccdb_sec_get_default_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_get_default_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_get_default_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ const char *url; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_get_default_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Getting the default ccache\n"); -+ url = sec_dfl_url_create(state, client); -+ if (url == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ subreq = tcurl_http_send(state, ev, secdb->tctx, -+ TCURL_HTTP_GET, -+ SSSD_SECRETS_SOCKET, -+ url, -+ sec_headers, -+ NULL, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_get_default_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_get_default_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ int http_code; -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct ccdb_sec_get_default_state *state = tevent_req_data(req, -+ struct ccdb_sec_get_default_state); -+ struct sss_iobuf *outbuf; -+ size_t uuid_size; -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, &outbuf); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Communication with the secrets responder failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code == 404) { -+ /* Return a NULL uuid */ -+ uuid_clear(state->uuid); -+ tevent_req_done(req); -+ return; -+ } else if (http_code != 200) { -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ uuid_size = sss_iobuf_get_len(outbuf); -+ if (uuid_size != UUID_STR_SIZE) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unexpected UUID size %zu\n", uuid_size); -+ tevent_req_error(req, EIO); -+ return; -+ } -+ -+ uuid_parse((const char *) sss_iobuf_get_data(outbuf), state->uuid); -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Got the default ccache\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_get_default_recv(struct tevent_req *req, -+ uuid_t uuid) -+{ -+ struct ccdb_sec_get_default_state *state = tevent_req_data(req, -+ struct ccdb_sec_get_default_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ uuid_copy(uuid, state->uuid); -+ return EOK; -+} -+ -+/* HTTP GET $base/ccache/ */ -+/* OUT: a list of */ -+struct ccdb_sec_list_state { -+ uuid_t *uuid_list; -+}; -+ -+static void ccdb_sec_list_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_list_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_list_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_list_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Listing all ccaches\n"); -+ -+ subreq = sec_list_send(state, ev, secdb, client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_list_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_list_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_list_state *state = tevent_req_data(req, -+ struct ccdb_sec_list_state); -+ const char **sec_key_list; -+ size_t sec_key_list_len; -+ -+ ret = sec_list_recv(subreq, state, &sec_key_list, &sec_key_list_len); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Communication with the secrets responder failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Found %zu ccaches\n", sec_key_list_len); -+ -+ state->uuid_list = talloc_array(state, uuid_t, sec_key_list_len + 1); -+ if (state->uuid_list == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ for (size_t i = 0; i < sec_key_list_len; i++) { -+ ret = sec_key_get_uuid(sec_key_list[i], -+ state->uuid_list[i]); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ } -+ /* Sentinel */ -+ uuid_clear(state->uuid_list[sec_key_list_len]); -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Listing all caches done\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_list_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ uuid_t **_uuid_list) -+{ -+ struct ccdb_sec_list_state *state = tevent_req_data(req, -+ struct ccdb_sec_list_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_uuid_list = talloc_steal(mem_ctx, state->uuid_list); -+ return EOK; -+} -+ -+struct ccdb_sec_getbyuuid_state { -+ struct kcm_ccache *cc; -+}; -+ -+ -+/* HTTP GET $base/ccache/ */ -+/* OUT: a list of */ -+/* for each item in list, compare with the uuid: portion */ -+/* HTTP GET $base/ccache/uuid:name */ -+/* return result */ -+static void ccdb_sec_getbyuuid_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_getbyuuid_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ errno_t ret; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_getbyuuid_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_getbyuuid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Getting ccache by UUID\n"); -+ -+ subreq = sec_get_ccache_send(state, ev, secdb, client, NULL, uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_getbyuuid_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_getbyuuid_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_getbyuuid_state *state = tevent_req_data(req, -+ struct ccdb_sec_getbyuuid_state); -+ -+ ret = sec_get_ccache_recv(subreq, state, &state->cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot retrieve the ccache [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Got ccache by UUID\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_getbyuuid_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct ccdb_sec_getbyuuid_state *state = tevent_req_data(req, -+ struct ccdb_sec_getbyuuid_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+/* HTTP GET $base/ccache/ */ -+/* OUT: a list of */ -+/* for each item in list, compare with the :name portion */ -+/* HTTP GET $base/ccache/uuid:name */ -+/* return result */ -+struct ccdb_sec_getbyname_state { -+ struct kcm_ccache *cc; -+}; -+ -+static void ccdb_sec_getbyname_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_getbyname_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name) -+{ -+ errno_t ret; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_getbyname_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ uuid_t null_uuid; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_getbyname_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ uuid_clear(null_uuid); -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Getting ccache by name\n"); -+ -+ subreq = sec_get_ccache_send(state, ev, secdb, client, name, null_uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_getbyname_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_getbyname_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_getbyname_state *state = tevent_req_data(req, -+ struct ccdb_sec_getbyname_state); -+ -+ ret = sec_get_ccache_recv(subreq, state, &state->cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot retrieve the ccache [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Got ccache by UUID\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_getbyname_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ccache **_cc) -+{ -+ struct ccdb_sec_getbyname_state *state = tevent_req_data(req, -+ struct ccdb_sec_getbyname_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_cc = talloc_steal(mem_ctx, state->cc); -+ return EOK; -+} -+ -+struct ccdb_sec_name_by_uuid_state { -+ struct tevent_context *ev; -+ struct ccdb_sec *secdb; -+ struct cli_creds *client; -+ -+ uuid_t uuid; -+ -+ const char *name; -+}; -+ -+static void ccdb_sec_name_by_uuid_done(struct tevent_req *subreq); -+ -+struct tevent_req *ccdb_sec_name_by_uuid_send(TALLOC_CTX *sec_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_name_by_uuid_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ errno_t ret; -+ -+ req = tevent_req_create(sec_ctx, &state, struct ccdb_sec_name_by_uuid_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->secdb = secdb; -+ state->client = client; -+ uuid_copy(state->uuid, uuid); -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Translating UUID to name\n"); -+ -+ subreq = sec_list_send(state, state->ev, state->secdb, state->client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_name_by_uuid_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_name_by_uuid_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_name_by_uuid_state *state = tevent_req_data(req, -+ struct ccdb_sec_name_by_uuid_state); -+ const char **sec_key_list; -+ const char *name; -+ size_t sec_key_list_len; -+ size_t i; -+ -+ ret = sec_list_recv(subreq, state, &sec_key_list, &sec_key_list_len); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ for (i = 0; i < sec_key_list_len; i++) { -+ if (sec_key_match_uuid(sec_key_list[i], state->uuid) == true) { -+ /* Match, copy name */ -+ name = sec_key_get_name(sec_key_list[i]); -+ if (name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Malformed key, cannot get name\n"); -+ tevent_req_error(req, EINVAL); -+ return; -+ } -+ -+ state->name = talloc_strdup(state, name); -+ if (state->name == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Got ccache by UUID\n"); -+ tevent_req_done(req); -+ return; -+ } -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "No such UUID\n"); -+ tevent_req_error(req, ERR_NO_CREDS); -+ return; -+} -+ -+errno_t ccdb_sec_name_by_uuid_recv(struct tevent_req *req, -+ TALLOC_CTX *sec_ctx, -+ const char **_name) -+{ -+ struct ccdb_sec_name_by_uuid_state *state = tevent_req_data(req, -+ struct ccdb_sec_name_by_uuid_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_name = talloc_steal(sec_ctx, state->name); -+ return EOK; -+} -+ -+struct ccdb_sec_uuid_by_name_state { -+ struct tevent_context *ev; -+ struct ccdb_sec *secdb; -+ struct cli_creds *client; -+ -+ const char *name; -+ -+ uuid_t uuid; -+}; -+ -+static void ccdb_sec_uuid_by_name_done(struct tevent_req *subreq); -+ -+struct tevent_req *ccdb_sec_uuid_by_name_send(TALLOC_CTX *sec_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ const char *name) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_uuid_by_name_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ errno_t ret; -+ -+ req = tevent_req_create(sec_ctx, &state, struct ccdb_sec_uuid_by_name_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->secdb = secdb; -+ state->client = client; -+ state->name = name; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Translating name to UUID\n"); -+ -+ subreq = sec_list_send(state, state->ev, state->secdb, state->client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_uuid_by_name_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_uuid_by_name_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_uuid_by_name_state *state = tevent_req_data(req, -+ struct ccdb_sec_uuid_by_name_state); -+ const char **sec_key_list; -+ size_t sec_key_list_len; -+ size_t i; -+ -+ ret = sec_list_recv(subreq, state, &sec_key_list, &sec_key_list_len); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ for (i = 0; i < sec_key_list_len; i++) { -+ if (sec_key_match_name(sec_key_list[i], state->name) == true) { -+ /* Match, copy UUID */ -+ ret = sec_key_get_uuid(sec_key_list[i], state->uuid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Malformed key, cannot get UUID\n"); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Got ccache by name\n"); -+ tevent_req_done(req); -+ return; -+ } -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "No such name\n"); -+ tevent_req_error(req, ERR_NO_CREDS); -+ return; -+} -+ -+errno_t ccdb_sec_uuid_by_name_recv(struct tevent_req *req, -+ TALLOC_CTX *sec_ctx, -+ uuid_t _uuid) -+{ -+ struct ccdb_sec_uuid_by_name_state *state = tevent_req_data(req, -+ struct ccdb_sec_uuid_by_name_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ uuid_copy(_uuid, state->uuid); -+ return EOK; -+} -+ -+/* HTTP POST $base to create the container */ -+/* HTTP PUT $base to create the container. Since PUT errors out on duplicates, at least -+ * we fail consistently here and don't overwrite the ccache on concurrent requests -+ */ -+struct ccdb_sec_create_state { -+ struct tevent_context *ev; -+ struct ccdb_sec *secdb; -+ -+ const char *key_url; -+ struct sss_iobuf *ccache_payload; -+}; -+ -+static void ccdb_sec_container_done(struct tevent_req *subreq); -+static void ccdb_sec_ccache_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_create_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ struct kcm_ccache *cc) -+{ -+ struct tevent_req *subreq = NULL; -+ struct tevent_req *req = NULL; -+ struct ccdb_sec_create_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ errno_t ret; -+ const char *container_url; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_create_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->secdb = secdb; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Creating ccache storage for %s\n", cc->name); -+ -+ /* Do the encoding asap so that if we fail, we don't even attempt any -+ * writes */ -+ ret = kcm_ccache_to_sec_input(state, cc, client, &state->key_url, &state->ccache_payload); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot convert cache %s to JSON [%d]: %s\n", -+ cc->name, ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ container_url = sec_container_url_create(state, client); -+ if (container_url == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Creating the ccache container\n"); -+ subreq = tcurl_http_send(state, ev, secdb->tctx, -+ TCURL_HTTP_POST, -+ SSSD_SECRETS_SOCKET, -+ container_url, -+ sec_headers, -+ NULL, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_container_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_container_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ int http_code; -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct ccdb_sec_create_state *state = tevent_req_data(req, -+ struct ccdb_sec_create_state); -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, NULL); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Communication with the secrets responder failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Conflict is not an error as multiple ccaches are under the same -+ * container */ -+ if (http_code == 409) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Container already exists, ignoring\n"); -+ } else if (http_code != 200) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to create the ccache container\n"); -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "ccache container created\n"); -+ DEBUG(SSSDBG_TRACE_INTERNAL, "creating empty ccache payload\n"); -+ -+ subreq = tcurl_http_send(state, -+ state->ev, -+ state->secdb->tctx, -+ TCURL_HTTP_PUT, -+ SSSD_SECRETS_SOCKET, -+ state->key_url, -+ sec_headers, -+ state->ccache_payload, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_ccache_done, req); -+} -+ -+static void ccdb_sec_ccache_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ int http_code; -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct ccdb_sec_create_state *state = tevent_req_data(req, -+ struct ccdb_sec_create_state); -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, NULL); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Communication with the secrets responder failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code != 200) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to add the payload\n"); -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "payload created\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_create_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+struct ccdb_sec_mod_cred_state { -+ struct tevent_context *ev; -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ struct kcm_mod_ctx *mod_cc; -+ -+ struct ccdb_sec *secdb; -+}; -+ -+static void ccdb_sec_mod_cred_get_done(struct tevent_req *subreq); -+static void ccdb_sec_mod_cred_patch_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_mod_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct kcm_mod_ctx *mod_cc) -+{ -+ errno_t ret; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_mod_cred_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_mod_cred_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->db =db; -+ state->client = client; -+ state->secdb = secdb; -+ state->mod_cc = mod_cc; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Modifying ccache\n"); -+ -+ subreq = sec_get_ccache_send(state, ev, secdb, client, NULL, uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, *ccdb_sec_mod_cred_get_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_mod_cred_get_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_mod_cred_state *state = tevent_req_data(req, -+ struct ccdb_sec_mod_cred_state); -+ struct kcm_ccache *cc; -+ const char *url; -+ struct sss_iobuf *payload; -+ -+ ret = sec_get_ccache_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot retrieve the ccache [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (cc == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "No such ccache\n"); -+ tevent_req_error(req, ERR_NO_CREDS); -+ return; -+ } -+ -+ kcm_mod_cc(cc, state->mod_cc); -+ -+ ret = kcm_ccache_to_sec_input(state, cc, state->client, &url, &payload); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to marshall modified ccache to payload [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = sec_patch_send(state, -+ state->ev, -+ state->secdb, -+ state->client, -+ url, -+ payload); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_mod_cred_patch_done, req); -+} -+ -+static void ccdb_sec_mod_cred_patch_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ -+ ret = sec_patch_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sec_patch request failed [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "ccache modified\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_mod_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+struct ccdb_sec_store_cred_state { -+ struct tevent_context *ev; -+ struct kcm_ccdb *db; -+ struct cli_creds *client; -+ struct sss_iobuf *cred_blob; -+ -+ struct ccdb_sec *secdb; -+}; -+ -+static void ccdb_sec_store_cred_get_done(struct tevent_req *subreq); -+static void ccdb_sec_store_cred_patch_done(struct tevent_req *subreq); -+ -+/* HTTP DEL/PUT $base/ccache/uuid:name */ -+static struct tevent_req *ccdb_sec_store_cred_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid, -+ struct sss_iobuf *cred_blob) -+{ -+ errno_t ret; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_store_cred_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_store_cred_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->db =db; -+ state->client = client; -+ state->cred_blob = cred_blob; -+ state->secdb = secdb; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Storing creds in ccache\n"); -+ -+ subreq = sec_get_ccache_send(state, ev, secdb, client, NULL, uuid); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, *ccdb_sec_store_cred_get_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_store_cred_get_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_store_cred_state *state = tevent_req_data(req, -+ struct ccdb_sec_store_cred_state); -+ struct kcm_ccache *cc; -+ const char *url; -+ struct sss_iobuf *payload; -+ -+ ret = sec_get_ccache_recv(subreq, state, &cc); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = kcm_cc_store_cred_blob(cc, state->cred_blob); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot store credentials to ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = kcm_ccache_to_sec_input(state, cc, state->client, &url, &payload); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to marshall modified ccache to payload [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = sec_patch_send(state, -+ state->ev, -+ state->secdb, -+ state->client, -+ url, -+ payload); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_store_cred_patch_done, req); -+} -+ -+static void ccdb_sec_store_cred_patch_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ -+ ret = sec_patch_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sec_patch request failed [%d]: %s\n", ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "ccache creds stored\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_store_cred_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+/* HTTP DELETE $base/ccache/uuid:name */ -+struct ccdb_sec_delete_state { -+ struct tevent_context *ev; -+ struct ccdb_sec *secdb; -+ struct cli_creds *client; -+ uuid_t uuid; -+ -+ size_t sec_key_list_len; -+}; -+ -+static void ccdb_sec_delete_list_done(struct tevent_req *subreq); -+static void ccdb_sec_delete_cc_done(struct tevent_req *subreq); -+static void ccdb_sec_delete_container_done(struct tevent_req *subreq); -+ -+static struct tevent_req *ccdb_sec_delete_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ccdb *db, -+ struct cli_creds *client, -+ uuid_t uuid) -+{ -+ errno_t ret; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct ccdb_sec_delete_state *state = NULL; -+ struct ccdb_sec *secdb = talloc_get_type(db->db_handle, struct ccdb_sec); -+ -+ req = tevent_req_create(mem_ctx, &state, struct ccdb_sec_delete_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->secdb = secdb; -+ state->client = client; -+ uuid_copy(state->uuid, uuid); -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Deleting ccache\n"); -+ -+ subreq = sec_list_send(state, ev, secdb, client); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_delete_list_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ccdb_sec_delete_list_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_delete_state *state = tevent_req_data(req, -+ struct ccdb_sec_delete_state); -+ const char **sec_key_list; -+ const char *sec_key; -+ const char *cc_url; -+ -+ ret = sec_list_recv(subreq, -+ state, -+ &sec_key_list, -+ &state->sec_key_list_len); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (sec_key_list == 0) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "No ccaches to delete\n"); -+ tevent_req_done(req); -+ return; -+ } -+ -+ sec_key = find_by_uuid(sec_key_list, state->uuid); -+ if (sec_key == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot find ccache by UUID\n"); -+ tevent_req_done(req); -+ return; -+ } -+ -+ cc_url = sec_cc_url_create(state, state->client, sec_key); -+ if (cc_url == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ subreq = tcurl_http_send(state, state->ev, -+ state->secdb->tctx, -+ TCURL_HTTP_DELETE, -+ SSSD_SECRETS_SOCKET, -+ cc_url, -+ sec_headers, -+ NULL, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_delete_cc_done, req); -+} -+ -+static void ccdb_sec_delete_cc_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_delete_state *state = tevent_req_data(req, -+ struct ccdb_sec_delete_state); -+ int http_code; -+ const char *container_url; -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, NULL); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot delete ccache [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code != 200) { -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (state->sec_key_list_len != 1) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, "There are other ccaches, done\n"); -+ tevent_req_done(req); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Removing ccache container\n"); -+ -+ container_url = sec_container_url_create(state, state->client); -+ if (container_url == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ subreq = tcurl_http_send(state, state->ev, -+ state->secdb->tctx, -+ TCURL_HTTP_DELETE, -+ SSSD_SECRETS_SOCKET, -+ container_url, -+ sec_headers, -+ NULL, -+ SEC_TIMEOUT); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, ccdb_sec_delete_container_done, req); -+} -+ -+static void ccdb_sec_delete_container_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ccdb_sec_delete_state *state = tevent_req_data(req, -+ struct ccdb_sec_delete_state); -+ int http_code; -+ -+ ret = tcurl_http_recv(state, subreq, &http_code, NULL); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot delete ccache container [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (http_code != 200) { -+ ret = http2errno(http_code); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Removed ccache container\n"); -+ tevent_req_done(req); -+} -+ -+static errno_t ccdb_sec_delete_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} -+ -+const struct kcm_ccdb_ops ccdb_sec_ops = { -+ .init = ccdb_sec_init, -+ -+ .nextid_send = ccdb_sec_nextid_send, -+ .nextid_recv = ccdb_sec_nextid_recv, -+ -+ .set_default_send = ccdb_sec_set_default_send, -+ .set_default_recv = ccdb_sec_set_default_recv, -+ -+ .get_default_send = ccdb_sec_get_default_send, -+ .get_default_recv = ccdb_sec_get_default_recv, -+ -+ .list_send = ccdb_sec_list_send, -+ .list_recv = ccdb_sec_list_recv, -+ -+ .getbyname_send = ccdb_sec_getbyname_send, -+ .getbyname_recv = ccdb_sec_getbyname_recv, -+ -+ .getbyuuid_send = ccdb_sec_getbyuuid_send, -+ .getbyuuid_recv = ccdb_sec_getbyuuid_recv, -+ -+ .name_by_uuid_send = ccdb_sec_name_by_uuid_send, -+ .name_by_uuid_recv = ccdb_sec_name_by_uuid_recv, -+ -+ .uuid_by_name_send = ccdb_sec_uuid_by_name_send, -+ .uuid_by_name_recv = ccdb_sec_uuid_by_name_recv, -+ -+ .create_send = ccdb_sec_create_send, -+ .create_recv = ccdb_sec_create_recv, -+ -+ .mod_send = ccdb_sec_mod_send, -+ .mod_recv = ccdb_sec_mod_recv, -+ -+ .store_cred_send = ccdb_sec_store_cred_send, -+ .store_cred_recv = ccdb_sec_store_cred_recv, -+ -+ .delete_send = ccdb_sec_delete_send, -+ .delete_recv = ccdb_sec_delete_recv, -+}; -diff --git a/src/tests/cmocka/test_kcm_json_marshalling.c b/src/tests/cmocka/test_kcm_json_marshalling.c -new file mode 100644 -index 0000000000000000000000000000000000000000..8eff2f501066c70a8730cd3d4dc41b92d7a03e4c ---- /dev/null -+++ b/src/tests/cmocka/test_kcm_json_marshalling.c -@@ -0,0 +1,234 @@ -+/* -+ Copyright (C) 2017 Red Hat -+ -+ SSSD tests: Test KCM JSON marshalling -+ -+ 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 -+ -+#include "util/util_creds.h" -+#include "responder/kcm/kcmsrv_ccache.h" -+#include "responder/kcm/kcmsrv_ccache_be.h" -+#include "tests/cmocka/common_mock.h" -+ -+#define TEST_REALM "TESTREALM" -+#define TEST_PRINC_COMPONENT "PRINC_NAME" -+ -+#define TEST_CREDS "TESTCREDS" -+ -+const struct kcm_ccdb_ops ccdb_mem_ops; -+const struct kcm_ccdb_ops ccdb_sec_ops; -+ -+struct kcm_marshalling_test_ctx { -+ krb5_context kctx; -+ krb5_principal princ; -+}; -+ -+static int setup_kcm_marshalling(void **state) -+{ -+ struct kcm_marshalling_test_ctx *test_ctx; -+ krb5_error_code kerr; -+ -+ test_ctx = talloc_zero(NULL, struct kcm_marshalling_test_ctx); -+ assert_non_null(test_ctx); -+ -+ kerr = krb5_init_context(&test_ctx->kctx); -+ assert_int_equal(kerr, 0); -+ -+ kerr = krb5_build_principal(test_ctx->kctx, -+ &test_ctx->princ, -+ sizeof(TEST_REALM)-1, TEST_REALM, -+ TEST_PRINC_COMPONENT, NULL); -+ assert_int_equal(kerr, 0); -+ -+ *state = test_ctx; -+ return 0; -+} -+ -+static int teardown_kcm_marshalling(void **state) -+{ -+ struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state, -+ struct kcm_marshalling_test_ctx); -+ assert_non_null(test_ctx); -+ -+ krb5_free_principal(test_ctx->kctx, test_ctx->princ); -+ krb5_free_context(test_ctx->kctx); -+ talloc_free(test_ctx); -+ return 0; -+} -+ -+static void assert_cc_name_equal(struct kcm_ccache *cc1, -+ struct kcm_ccache *cc2) -+{ -+ const char *name1, *name2; -+ -+ name1 = kcm_cc_get_name(cc1); -+ name2 = kcm_cc_get_name(cc2); -+ assert_string_equal(name1, name2); -+} -+ -+static void assert_cc_uuid_equal(struct kcm_ccache *cc1, -+ struct kcm_ccache *cc2) -+{ -+ uuid_t u1, u2; -+ errno_t ret; -+ -+ ret = kcm_cc_get_uuid(cc1, u1); -+ assert_int_equal(ret, EOK); -+ ret = kcm_cc_get_uuid(cc2, u2); -+ assert_int_equal(ret, EOK); -+ ret = uuid_compare(u1, u2); -+ assert_int_equal(ret, 0); -+} -+ -+static void assert_cc_princ_equal(struct kcm_ccache *cc1, -+ struct kcm_ccache *cc2) -+{ -+ krb5_principal p1; -+ krb5_principal p2; -+ char *name1; -+ char *name2; -+ krb5_error_code kerr; -+ -+ p1 = kcm_cc_get_client_principal(cc1); -+ p2 = kcm_cc_get_client_principal(cc1); -+ -+ kerr = krb5_unparse_name(NULL, p1, &name1); -+ assert_int_equal(kerr, 0); -+ kerr = krb5_unparse_name(NULL, p2, &name2); -+ assert_int_equal(kerr, 0); -+ -+ assert_string_equal(name1, name2); -+ krb5_free_unparsed_name(NULL, name1); -+ krb5_free_unparsed_name(NULL, name2); -+} -+ -+static void assert_cc_offset_equal(struct kcm_ccache *cc1, -+ struct kcm_ccache *cc2) -+{ -+ int32_t off1; -+ int32_t off2; -+ -+ off1 = kcm_cc_get_offset(cc1); -+ off2 = kcm_cc_get_offset(cc2); -+ assert_int_equal(off1, off2); -+} -+ -+static void assert_cc_equal(struct kcm_ccache *cc1, -+ struct kcm_ccache *cc2) -+{ -+ assert_cc_name_equal(cc1, cc2); -+ assert_cc_uuid_equal(cc1, cc2); -+ assert_cc_princ_equal(cc1, cc2); -+ assert_cc_offset_equal(cc1, cc2); -+} -+ -+static void test_kcm_ccache_marshall_unmarshall(void **state) -+{ -+ struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state, -+ struct kcm_marshalling_test_ctx); -+ errno_t ret; -+ struct cli_creds owner; -+ struct kcm_ccache *cc; -+ struct kcm_ccache *cc2; -+ const char *url; -+ struct sss_iobuf *payload; -+ const char *name; -+ const char *key; -+ uint8_t *data; -+ -+ owner.ucred.uid = getuid(); -+ owner.ucred.gid = getuid(); -+ -+ name = talloc_asprintf(test_ctx, "%"SPRIuid, getuid()); -+ assert_non_null(name); -+ -+ ret = kcm_cc_new(test_ctx, -+ test_ctx->kctx, -+ &owner, -+ name, -+ test_ctx->princ, -+ &cc); -+ assert_int_equal(ret, EOK); -+ -+ ret = kcm_ccache_to_sec_input(test_ctx, -+ cc, -+ &owner, -+ &url, -+ &payload); -+ assert_int_equal(ret, EOK); -+ -+ key = strrchr(url, '/') + 1; -+ assert_non_null(key); -+ -+ data = sss_iobuf_get_data(payload); -+ assert_non_null(data); -+ -+ ret = sec_kv_to_ccache(test_ctx, -+ key, -+ (const char *) data, -+ &owner, -+ &cc2); -+ assert_int_equal(ret, EOK); -+ -+ assert_cc_equal(cc, cc2); -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ poptContext pc; -+ int opt; -+ int rv; -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ SSSD_DEBUG_OPTS -+ POPT_TABLEEND -+ }; -+ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall, -+ setup_kcm_marshalling, -+ teardown_kcm_marshalling), -+ }; -+ -+ /* 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); -+ -+ /* Even though normally the tests should clean up after themselves -+ * they might not after a failed run. Remove the old db to be sure */ -+ tests_set_cwd(); -+ -+ rv = cmocka_run_group_tests(tests, NULL, NULL); -+ -+ return rv; -+} -diff --git a/src/tests/intg/test_kcm.py b/src/tests/intg/test_kcm.py -index ad1e4923bfe339cb040464757431d2ef3bf57ce1..11f80a1803b4ad9b8e8857bf9a8a244d4816f0a2 100644 ---- a/src/tests/intg/test_kcm.py -+++ b/src/tests/intg/test_kcm.py -@@ -27,7 +27,8 @@ import signal - import kdc - import krb5utils - import config --from util import unindent, run_shell -+from util import unindent -+from test_secrets import create_sssd_secrets_fixture - - class KcmTestEnv(object): - def __init__(self, k5kdc, k5util): -@@ -107,15 +108,8 @@ def create_sssd_kcm_fixture(sock_path, request): - return kcm_pid - - --@pytest.fixture --def setup_for_kcm(request, kdc_instance): -- """ -- Just set up the local provider for tests and enable the KCM -- responder -- """ -- kcm_path = os.path.join(config.RUNSTATEDIR, "kcm.socket") -- -- sssd_conf = unindent("""\ -+def create_sssd_conf(kcm_path, ccache_storage): -+ return unindent("""\ - [sssd] - domains = local - services = nss -@@ -125,8 +119,11 @@ def setup_for_kcm(request, kdc_instance): - - [kcm] - socket_path = {kcm_path} -+ ccache_storage = {ccache_storage} - """).format(**locals()) - -+ -+def common_setup_for_kcm_mem(request, kdc_instance, kcm_path, sssd_conf): - kcm_socket_include = unindent(""" - [libdefaults] - default_ccache_name = KCM: -@@ -142,11 +139,35 @@ def setup_for_kcm(request, kdc_instance): - return KcmTestEnv(kdc_instance, k5util) - - --def test_kcm_init_list_destroy(setup_for_kcm): -+@pytest.fixture -+def setup_for_kcm_mem(request, kdc_instance): -+ """ -+ Just set up the local provider for tests and enable the KCM -+ responder -+ """ -+ kcm_path = os.path.join(config.RUNSTATEDIR, "kcm.socket") -+ sssd_conf = create_sssd_conf(kcm_path, "memory") -+ return common_setup_for_kcm_mem(request, kdc_instance, kcm_path, sssd_conf) -+ -+@pytest.fixture -+def setup_secrets(request): -+ create_sssd_secrets_fixture(request) -+ -+@pytest.fixture -+def setup_for_kcm_sec(request, kdc_instance): -+ """ -+ Just set up the local provider for tests and enable the KCM -+ responder -+ """ -+ kcm_path = os.path.join(config.RUNSTATEDIR, "kcm.socket") -+ sssd_conf = create_sssd_conf(kcm_path, "secrets") -+ return common_setup_for_kcm_mem(request, kdc_instance, kcm_path, sssd_conf) -+ -+ -+def kcm_init_list_destroy(testenv): - """ - Test that kinit, kdestroy and klist work with KCM - """ -- testenv = setup_for_kcm - testenv.k5kdc.add_principal("kcmtest", "Secret123") - - ok = testenv.k5util.has_principal("kcmtest@KCMTEST") -@@ -172,12 +193,22 @@ def test_kcm_init_list_destroy(setup_for_kcm): - assert nprincs == 0 - - --def test_kcm_overwrite(setup_for_kcm): -+def test_kcm_mem_init_list_destroy(setup_for_kcm_mem): -+ testenv = setup_for_kcm_mem -+ kcm_init_list_destroy(testenv) -+ -+ -+def test_kcm_sec_init_list_destroy(setup_for_kcm_sec, -+ setup_secrets): -+ testenv = setup_for_kcm_sec -+ kcm_init_list_destroy(testenv) -+ -+ -+def kcm_overwrite(testenv): - """ - That that reusing a ccache reinitializes the cache and doesn't - add the same principal twice - """ -- testenv = setup_for_kcm - testenv.k5kdc.add_principal("kcmtest", "Secret123") - exp_ccache = {'kcmtest@KCMTEST': ['krbtgt/KCMTEST@KCMTEST']} - -@@ -192,12 +223,22 @@ def test_kcm_overwrite(setup_for_kcm): - assert exp_ccache == testenv.k5util.list_all_princs() - - --def test_collection_init_list_destroy(setup_for_kcm): -+def test_kcm_mem_overwrite(setup_for_kcm_mem): -+ testenv = setup_for_kcm_mem -+ kcm_overwrite(testenv) -+ -+ -+def test_kcm_sec_overwrite(setup_for_kcm_sec, -+ setup_secrets): -+ testenv = setup_for_kcm_sec -+ kcm_overwrite(testenv) -+ -+ -+def collection_init_list_destroy(testenv): - """ - Test that multiple principals and service tickets can be stored - in a collection. - """ -- testenv = setup_for_kcm - testenv.k5kdc.add_principal("alice", "alicepw") - testenv.k5kdc.add_principal("bob", "bobpw") - testenv.k5kdc.add_principal("carol", "carolpw") -@@ -241,7 +282,11 @@ def test_collection_init_list_destroy(setup_for_kcm): - - out = testenv.k5util.kdestroy() - assert out == 0 -- assert testenv.k5util.default_principal() == 'bob@KCMTEST' -+ # If the default is removed, KCM just uses whetever is the first entry -+ # in the collection as the default. And sine the KCM back ends don't -+ # guarantee if they are FIFO or LIFO, just check for either alice or bob -+ assert testenv.k5util.default_principal() in \ -+ ['alice@KCMTEST', 'bob@KCMTEST'] - cc_coll = testenv.k5util.list_all_princs() - assert len(cc_coll) == 2 - assert cc_coll['alice@KCMTEST'] == ['krbtgt/KCMTEST@KCMTEST'] -@@ -255,11 +300,21 @@ def test_collection_init_list_destroy(setup_for_kcm): - #assert len(cc_coll) == 0 - - --def test_kswitch(setup_for_kcm): -+def test_kcm_mem_collection_init_list_destroy(setup_for_kcm_mem): -+ testenv = setup_for_kcm_mem -+ collection_init_list_destroy(testenv) -+ -+ -+def test_kcm_sec_collection_init_list_destroy(setup_for_kcm_sec, -+ setup_secrets): -+ testenv = setup_for_kcm_sec -+ collection_init_list_destroy(testenv) -+ -+ -+def exercise_kswitch(testenv): - """ - Test switching between principals - """ -- testenv = setup_for_kcm - testenv.k5kdc.add_principal("alice", "alicepw") - testenv.k5kdc.add_principal("bob", "bobpw") - testenv.k5kdc.add_principal("host/somehostname") -@@ -301,12 +356,22 @@ def test_kswitch(setup_for_kcm): - 'host/differenthostname@KCMTEST']) - - --def test_subsidiaries(setup_for_kcm): -+def test_kcm_mem_kswitch(setup_for_kcm_mem): -+ testenv = setup_for_kcm_mem -+ exercise_kswitch(testenv) -+ -+ -+def test_kcm_sec_kswitch(setup_for_kcm_sec, -+ setup_secrets): -+ testenv = setup_for_kcm_sec -+ exercise_kswitch(testenv) -+ -+ -+def exercise_subsidiaries(testenv): - """ - Test that subsidiary caches are usable and KCM: without specifying UID - can be used to identify the collection - """ -- testenv = setup_for_kcm - testenv.k5kdc.add_principal("alice", "alicepw") - testenv.k5kdc.add_principal("bob", "bobpw") - testenv.k5kdc.add_principal("host/somehostname") -@@ -346,11 +411,21 @@ def test_subsidiaries(setup_for_kcm): - 'host/differenthostname@KCMTEST']) - - --def test_kdestroy_nocache(setup_for_kcm): -+def test_kcm_mem_subsidiaries(setup_for_kcm_mem): -+ testenv = setup_for_kcm_mem -+ exercise_subsidiaries(testenv) -+ -+ -+def test_kcm_sec_subsidiaries(setup_for_kcm_sec, -+ setup_secrets): -+ testenv = setup_for_kcm_sec -+ exercise_subsidiaries(testenv) -+ -+ -+def kdestroy_nocache(testenv): - """ - Destroying a non-existing ccache should not throw an error - """ -- testenv = setup_for_kcm - testenv.k5kdc.add_principal("alice", "alicepw") - out, _, _ = testenv.k5util.kinit("alice", "alicepw") - assert out == 0 -@@ -359,3 +434,14 @@ def test_kdestroy_nocache(setup_for_kcm): - assert out == 0 - out = testenv.k5util.kdestroy() - assert out == 0 -+ -+ -+def test_kcm_mem_kdestroy_nocache(setup_for_kcm_mem): -+ testenv = setup_for_kcm_mem -+ exercise_subsidiaries(testenv) -+ -+ -+def test_kcm_sec_kdestroy_nocache(setup_for_kcm_sec, -+ setup_secrets): -+ testenv = setup_for_kcm_sec -+ exercise_subsidiaries(testenv) -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 23cfdf9c6116a2c8e569a041e8289b65a112fd08..60c2f439b3e39b1dbff353e429114cb5a3070052 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -109,6 +109,8 @@ struct err_string error_to_str[] = { - { "KCM operation not implemented" }, /* ERR_KCM_OP_NOT_IMPLEMENTED */ - { "End of credential cache reached" }, /* ERR_KCM_CC_END */ - { "Credential cache name not allowed" }, /* ERR_KCM_WRONG_CCNAME_FORMAT */ -+ { "Cannot encode a JSON object to string" }, /* ERR_JSON_ENCODING */ -+ { "Cannot decode a JSON object from string" }, /* ERR_JSON_DECODING */ - { "ERR_LAST" } /* ERR_LAST */ - }; - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 387d481616db1ed5e22b73fae82632a582fae946..4e9da814702e2cd46edc52fd5c2ae5f640602609 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -131,6 +131,8 @@ enum sssd_errors { - ERR_KCM_OP_NOT_IMPLEMENTED, - ERR_KCM_CC_END, - ERR_KCM_WRONG_CCNAME_FORMAT, -+ ERR_JSON_ENCODING, -+ ERR_JSON_DECODING, - ERR_LAST /* ALWAYS LAST */ - }; - --- -2.12.2 - diff --git a/0036-KCM-Make-the-secrets-ccache-back-end-configurable-ma.patch b/0036-KCM-Make-the-secrets-ccache-back-end-configurable-ma.patch deleted file mode 100644 index b938530..0000000 --- a/0036-KCM-Make-the-secrets-ccache-back-end-configurable-ma.patch +++ /dev/null @@ -1,219 +0,0 @@ -From 35c9dfe9ba78d3a635cd1af0fb6349ba44344623 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 14 Mar 2017 11:17:05 +0100 -Subject: [PATCH 36/97] KCM: Make the secrets ccache back end configurable, - make secrets the default -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Adds a new option 'ccache_storage' that allows to select either the -memory back end or the secrets back end. The secrets back end is the -default one and this option is even undocumented. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/confdb/confdb.h | 1 + - src/config/cfg_rules.ini | 1 + - src/responder/kcm/kcm.c | 49 ++++++++++++++++++++++++++++++++---- - src/responder/kcm/kcmsrv_ccache.c | 2 +- - src/responder/kcm/kcmsrv_ccache.h | 6 +---- - src/responder/kcm/kcmsrv_ccache_be.h | 1 + - src/responder/kcm/kcmsrv_pvt.h | 7 ++++++ - 7 files changed, 56 insertions(+), 11 deletions(-) - -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index c443e869a7a6782265b42c4ad122867c4e3dd8e0..fb60675ca8beb2c2a157bf021ed9cad362742988 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -234,6 +234,7 @@ - /* KCM Service */ - #define CONFDB_KCM_CONF_ENTRY "config/kcm" - #define CONFDB_KCM_SOCKET "socket_path" -+#define CONFDB_KCM_DB "ccache_storage" /* Undocumented on purpose */ - - struct confdb_ctx; - struct config_file_ctx; -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 5e789c51658c51c0af1338d23d6c0f30f40bf119..67a5d1f5ad447a942b437ffd04a7f5d7cfe77d7f 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -280,6 +280,7 @@ option = fd_limit - option = client_idle_timeout - option = description - option = socket_path -+option = ccache_storage - - [rule/allowed_domain_options] - validator = ini_allowed_options -diff --git a/src/responder/kcm/kcm.c b/src/responder/kcm/kcm.c -index 2c12ef215ce3967df183e51c20590c5f439d278f..063c27b915b4b92f6259496feee891aa94a498b6 100644 ---- a/src/responder/kcm/kcm.c -+++ b/src/responder/kcm/kcm.c -@@ -47,6 +47,37 @@ static int kcm_responder_ctx_destructor(void *ptr) - return 0; - } - -+static errno_t kcm_get_ccdb_be(struct kcm_ctx *kctx) -+{ -+ errno_t ret; -+ char *str_db; -+ -+ ret = confdb_get_string(kctx->rctx->cdb, -+ kctx->rctx, -+ kctx->rctx->confdb_service_path, -+ CONFDB_KCM_DB, -+ "secrets", -+ &str_db); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get the KCM database type [%d]: %s\n", -+ ret, strerror(ret)); -+ return ret; -+ } -+ -+ DEBUG(SSSDBG_CONF_SETTINGS, "KCM database type: %s\n", str_db); -+ if (strcasecmp(str_db, "memory") == 0) { -+ kctx->cc_be = CCDB_BE_MEMORY; -+ return EOK; -+ } else if (strcasecmp(str_db, "secrets") == 0) { -+ kctx->cc_be = CCDB_BE_SECRETS; -+ return EOK; -+ } -+ -+ DEBUG(SSSDBG_FATAL_FAILURE, "Unexpected KCM database type %s\n", str_db); -+ return EOK; -+} -+ - static int kcm_get_config(struct kcm_ctx *kctx) - { - int ret; -@@ -88,14 +119,21 @@ static int kcm_get_config(struct kcm_ctx *kctx) - &sock_name); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, -- "Cannot get the client idle timeout [%d]: %s\n", -+ "Cannot get KCM socket path [%d]: %s\n", - ret, strerror(ret)); - goto done; - } - kctx->rctx->sock_name = sock_name; - -+ ret = kcm_get_ccdb_be(kctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get KCM ccache DB [%d]: %s\n", -+ ret, strerror(ret)); -+ goto done; -+ } -+ - ret = EOK; -- - done: - return ret; - } -@@ -111,7 +149,8 @@ static int kcm_data_destructor(void *ptr) - } - - static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev) -+ struct tevent_context *ev, -+ enum kcm_ccdb_be cc_be) - { - struct kcm_resp_ctx *kcm_data; - krb5_error_code kret; -@@ -122,7 +161,7 @@ static struct kcm_resp_ctx *kcm_data_setup(TALLOC_CTX *mem_ctx, - return NULL; - } - -- kcm_data->db = kcm_ccdb_init(kcm_data, ev, CCDB_BE_MEMORY); -+ kcm_data->db = kcm_ccdb_init(kcm_data, ev, cc_be); - if (kcm_data->db == NULL) { - talloc_free(kcm_data); - return NULL; -@@ -176,7 +215,7 @@ static int kcm_process_init(TALLOC_CTX *mem_ctx, - goto fail; - } - -- kctx->kcm_data = kcm_data_setup(kctx, ev); -+ kctx->kcm_data = kcm_data_setup(kctx, ev, kctx->cc_be); - if (kctx->kcm_data == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, - "fatal error initializing responder data\n"); -diff --git a/src/responder/kcm/kcmsrv_ccache.c b/src/responder/kcm/kcmsrv_ccache.c -index 2ae120269b0c62275ba2acdff6d6daa8b7077708..a22184e0f2b1300f3678bb343b6a110bf144a36b 100644 ---- a/src/responder/kcm/kcmsrv_ccache.c -+++ b/src/responder/kcm/kcmsrv_ccache.c -@@ -244,7 +244,7 @@ struct kcm_ccdb *kcm_ccdb_init(TALLOC_CTX *mem_ctx, - break; - case CCDB_BE_SECRETS: - DEBUG(SSSDBG_FUNC_DATA, "KCM back end: sssd-secrets\n"); -- /* Not implemented yet */ -+ ccdb->ops = &ccdb_sec_ops; - break; - default: - DEBUG(SSSDBG_CRIT_FAILURE, "Unknown ccache database\n"); -diff --git a/src/responder/kcm/kcmsrv_ccache.h b/src/responder/kcm/kcmsrv_ccache.h -index 18c8c47ad4ecb24521a85a1833b239c7a2a8bb45..36c481c5335d557318f0ed0204d93e533b4b6c41 100644 ---- a/src/responder/kcm/kcmsrv_ccache.h -+++ b/src/responder/kcm/kcmsrv_ccache.h -@@ -29,6 +29,7 @@ - #include "util/util.h" - #include "util/sss_iobuf.h" - #include "util/util_creds.h" -+#include "responder/kcm/kcmsrv_pvt.h" - - #define UUID_BYTES 16 - #define UUID_STR_SIZE 37 -@@ -113,11 +114,6 @@ errno_t kcm_cc_store_cred_blob(struct kcm_ccache *cc, - struct kcm_cred *kcm_cc_get_cred(struct kcm_ccache *cc); - struct kcm_cred *kcm_cc_next_cred(struct kcm_cred *crd); - --enum kcm_ccdb_be { -- CCDB_BE_MEMORY, -- CCDB_BE_SECRETS, --}; -- - /* An opaque database that contains all the ccaches */ - struct kcm_ccdb; - -diff --git a/src/responder/kcm/kcmsrv_ccache_be.h b/src/responder/kcm/kcmsrv_ccache_be.h -index 1bd2b6981e227675866e82e0a5389445cac4df66..a0796c298bae15a01adf612a6195a494ba6b4d23 100644 ---- a/src/responder/kcm/kcmsrv_ccache_be.h -+++ b/src/responder/kcm/kcmsrv_ccache_be.h -@@ -200,5 +200,6 @@ struct kcm_ccdb_ops { - }; - - extern const struct kcm_ccdb_ops ccdb_mem_ops; -+extern const struct kcm_ccdb_ops ccdb_sec_ops; - - #endif /* _KCMSRV_CCACHE_BE_ */ -diff --git a/src/responder/kcm/kcmsrv_pvt.h b/src/responder/kcm/kcmsrv_pvt.h -index a29680246c1e616da75e1bbff951ce2fad66fb65..74f30c00014105ed533744779b02c5d42523722d 100644 ---- a/src/responder/kcm/kcmsrv_pvt.h -+++ b/src/responder/kcm/kcmsrv_pvt.h -@@ -49,6 +49,12 @@ struct kcm_resp_ctx { - struct kcm_ccdb *db; - }; - -+/* Supported ccache back ends */ -+enum kcm_ccdb_be { -+ CCDB_BE_MEMORY, -+ CCDB_BE_SECRETS, -+}; -+ - /* - * responder context that contains both the responder data, - * like the ccaches and the sssd-specific stuff like the -@@ -58,6 +64,7 @@ struct kcm_ctx { - struct resp_ctx *rctx; - int fd_limit; - char *socket_path; -+ enum kcm_ccdb_be cc_be; - - struct kcm_resp_ctx *kcm_data; - }; --- -2.12.2 - diff --git a/0037-KCM-Queue-requests-by-the-same-UID.patch b/0037-KCM-Queue-requests-by-the-same-UID.patch deleted file mode 100644 index a68a467..0000000 --- a/0037-KCM-Queue-requests-by-the-same-UID.patch +++ /dev/null @@ -1,909 +0,0 @@ -From 2b5518eeaacc6245cfa77ee4a7086f16208060fc Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 21 Mar 2017 13:25:11 +0100 -Subject: [PATCH 37/97] KCM: Queue requests by the same UID -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In order to avoid race conditions, we queue requests towards the KCM -responder coming from the same client UID. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 21 ++- - src/responder/kcm/kcm.c | 7 + - src/responder/kcm/kcmsrv_cmd.c | 10 +- - src/responder/kcm/kcmsrv_op_queue.c | 264 ++++++++++++++++++++++++++ - src/responder/kcm/kcmsrv_ops.c | 44 ++++- - src/responder/kcm/kcmsrv_ops.h | 1 + - src/responder/kcm/kcmsrv_pvt.h | 20 ++ - src/tests/cmocka/test_kcm_queue.c | 365 ++++++++++++++++++++++++++++++++++++ - 8 files changed, 721 insertions(+), 11 deletions(-) - create mode 100644 src/responder/kcm/kcmsrv_op_queue.c - create mode 100644 src/tests/cmocka/test_kcm_queue.c - -diff --git a/Makefile.am b/Makefile.am -index e9eaa312c91e3aee40bcf13c90a0ad8c683045d5..91afdd669aa11a3cc316588d3b51d7e8e9c91cb8 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -304,7 +304,10 @@ non_interactive_cmocka_based_tests += test_inotify - endif # HAVE_INOTIFY - - if BUILD_KCM --non_interactive_cmocka_based_tests += test_kcm_json -+non_interactive_cmocka_based_tests += \ -+ test_kcm_json \ -+ test_kcm_queue \ -+ $(NULL) - endif # BUILD_KCM - - if BUILD_SAMBA -@@ -1501,6 +1504,7 @@ sssd_kcm_SOURCES = \ - src/responder/kcm/kcmsrv_ccache_json.c \ - src/responder/kcm/kcmsrv_ccache_secrets.c \ - src/responder/kcm/kcmsrv_ops.c \ -+ src/responder/kcm/kcmsrv_op_queue.c \ - src/util/sss_sockets.c \ - src/util/sss_krb5.c \ - src/util/sss_iobuf.c \ -@@ -3402,6 +3406,21 @@ test_kcm_json_LDADD = \ - $(SSSD_INTERNAL_LTLIBS) \ - libsss_test_common.la \ - $(NULL) -+ -+test_kcm_queue_SOURCES = \ -+ src/tests/cmocka/test_kcm_queue.c \ -+ src/responder/kcm/kcmsrv_op_queue.c \ -+ $(NULL) -+test_kcm_queue_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(NULL) -+test_kcm_queue_LDADD = \ -+ $(CMOCKA_LIBS) \ -+ $(SSSD_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_test_common.la \ -+ $(NULL) -+ - endif # BUILD_KCM - - endif # HAVE_CMOCKA -diff --git a/src/responder/kcm/kcm.c b/src/responder/kcm/kcm.c -index 063c27b915b4b92f6259496feee891aa94a498b6..3ee978066c589a5cc38b0ae358f741d389d00e7a 100644 ---- a/src/responder/kcm/kcm.c -+++ b/src/responder/kcm/kcm.c -@@ -133,6 +133,13 @@ static int kcm_get_config(struct kcm_ctx *kctx) - goto done; - } - -+ kctx->qctx = kcm_ops_queue_create(kctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot create KCM request queue [%d]: %s\n", -+ ret, strerror(ret)); -+ goto done; -+ } - ret = EOK; - done: - return ret; -diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c -index 537e88953fd1a190a9a73bcdd430d8e0db8f9291..81015de4a91617de3dca444cde95b636c8d5c0d1 100644 ---- a/src/responder/kcm/kcmsrv_cmd.c -+++ b/src/responder/kcm/kcmsrv_cmd.c -@@ -353,14 +353,18 @@ struct kcm_req_ctx { - - static void kcm_cmd_request_done(struct tevent_req *req); - --static errno_t kcm_cmd_dispatch(struct kcm_req_ctx *req_ctx) -+static errno_t kcm_cmd_dispatch(struct kcm_ctx *kctx, -+ struct kcm_req_ctx *req_ctx) - { - struct tevent_req *req; - struct cli_ctx *cctx; - - cctx = req_ctx->cctx; - -- req = kcm_cmd_send(req_ctx, cctx->ev, req_ctx->kctx->kcm_data, -+ req = kcm_cmd_send(req_ctx, -+ cctx->ev, -+ kctx->qctx, -+ req_ctx->kctx->kcm_data, - req_ctx->cctx->creds, - &req_ctx->op_io.request, - req_ctx->op_io.op); -@@ -505,7 +509,7 @@ static void kcm_recv(struct cli_ctx *cctx) - /* do not read anymore, client is done sending */ - TEVENT_FD_NOT_READABLE(cctx->cfde); - -- ret = kcm_cmd_dispatch(req); -+ ret = kcm_cmd_dispatch(kctx, req); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Failed to dispatch KCM operation [%d]: %s\n", -diff --git a/src/responder/kcm/kcmsrv_op_queue.c b/src/responder/kcm/kcmsrv_op_queue.c -new file mode 100644 -index 0000000000000000000000000000000000000000..f6c425dd5b64877c8b7401e488dd6565157fc9b5 ---- /dev/null -+++ b/src/responder/kcm/kcmsrv_op_queue.c -@@ -0,0 +1,264 @@ -+/* -+ SSSD -+ -+ KCM Server - the KCM operations wait queue -+ -+ Copyright (C) Red Hat, 2017 -+ -+ 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 "util/util.h" -+#include "util/util_creds.h" -+#include "responder/kcm/kcmsrv_pvt.h" -+ -+#define QUEUE_HASH_SIZE 32 -+ -+struct kcm_ops_queue_entry { -+ struct tevent_req *req; -+ uid_t uid; -+ -+ hash_table_t *wait_queue_hash; -+ -+ struct kcm_ops_queue_entry *head; -+ struct kcm_ops_queue_entry *next; -+ struct kcm_ops_queue_entry *prev; -+}; -+ -+struct kcm_ops_queue_ctx { -+ /* UID: dlist of kcm_ops_queue_entry */ -+ hash_table_t *wait_queue_hash; -+}; -+ -+/* -+ * Per-UID wait queue -+ * -+ * They key in the hash table is the UID of the peer. The value of each -+ * hash table entry is a linked list of kcm_ops_queue_entry structures -+ * which primarily hold the tevent request being queued. -+ */ -+struct kcm_ops_queue_ctx *kcm_ops_queue_create(TALLOC_CTX *mem_ctx) -+{ -+ errno_t ret; -+ struct kcm_ops_queue_ctx *queue_ctx; -+ -+ queue_ctx = talloc_zero(mem_ctx, struct kcm_ops_queue_ctx); -+ if (queue_ctx == NULL) { -+ return NULL; -+ } -+ -+ ret = sss_hash_create_ex(mem_ctx, QUEUE_HASH_SIZE, -+ &queue_ctx->wait_queue_hash, 0, 0, 0, 0, -+ NULL, NULL); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "sss_hash_create failed [%d]: %s\n", ret, sss_strerror(ret)); -+ talloc_free(queue_ctx); -+ return NULL; -+ } -+ -+ return queue_ctx; -+} -+ -+static int kcm_op_queue_entry_destructor(struct kcm_ops_queue_entry *entry) -+{ -+ int ret; -+ struct kcm_ops_queue_entry *next_entry; -+ hash_key_t key; -+ -+ if (entry == NULL) { -+ return 1; -+ } -+ -+ /* Take the next entry from the queue */ -+ next_entry = entry->next; -+ -+ /* Remove the current entry from the queue */ -+ DLIST_REMOVE(entry->head, entry); -+ -+ if (next_entry == NULL) { -+ key.type = HASH_KEY_ULONG; -+ key.ul = entry->uid; -+ -+ /* If this was the last entry, remove the key (the UID) from the -+ * hash table to signal the queue is empty -+ */ -+ ret = hash_delete(entry->wait_queue_hash, &key); -+ if (ret != HASH_SUCCESS) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to remove wait queue for user %"SPRIuid"\n", -+ entry->uid); -+ return 1; -+ } -+ return 0; -+ } -+ -+ /* Otherwise, mark the current head as done to run the next request */ -+ tevent_req_done(next_entry->req); -+ return 0; -+} -+ -+static errno_t kcm_op_queue_add(hash_table_t *wait_queue_hash, -+ struct kcm_ops_queue_entry *entry, -+ uid_t uid) -+{ -+ errno_t ret; -+ hash_key_t key; -+ hash_value_t value; -+ struct kcm_ops_queue_entry *head = NULL; -+ -+ key.type = HASH_KEY_ULONG; -+ key.ul = uid; -+ -+ ret = hash_lookup(wait_queue_hash, &key, &value); -+ switch (ret) { -+ case HASH_SUCCESS: -+ /* The key with this UID already exists. Its value is request queue -+ * for the UID, so let's just add the current request to the end -+ * of the queue and wait for the previous requests to finish -+ */ -+ if (value.type != HASH_VALUE_PTR) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected hash value type.\n"); -+ return EINVAL; -+ } -+ -+ head = talloc_get_type(value.ptr, struct kcm_ops_queue_entry); -+ if (head == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid queue pointer\n"); -+ return EINVAL; -+ } -+ -+ entry->head = head; -+ DLIST_ADD_END(head, entry, struct kcm_ops_queue_entry *); -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Waiting in queue\n"); -+ ret = EAGAIN; -+ break; -+ -+ case HASH_ERROR_KEY_NOT_FOUND: -+ /* No request for this UID yet. Enqueue this request in case -+ * another one comes in and return EOK to run the current request -+ * immediatelly -+ */ -+ entry->head = entry; -+ -+ value.type = HASH_VALUE_PTR; -+ value.ptr = entry; -+ -+ ret = hash_enter(wait_queue_hash, &key, &value); -+ if (ret != HASH_SUCCESS) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "hash_enter failed.\n"); -+ return EIO; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Added a first request to the queue, running immediately\n"); -+ ret = EOK; -+ break; -+ -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "hash_lookup failed.\n"); -+ return EIO; -+ } -+ -+ talloc_steal(wait_queue_hash, entry); -+ talloc_set_destructor(entry, kcm_op_queue_entry_destructor); -+ return ret; -+} -+ -+struct kcm_op_queue_state { -+ struct kcm_ops_queue_entry *entry; -+}; -+ -+/* -+ * Enqueue a request. -+ * -+ * If the request queue /for the given ID/ is empty, that is, if this -+ * request is the first one in the queue, run the request immediatelly. -+ * -+ * Otherwise just add it to the queue and wait until the previous request -+ * finishes and only at that point mark the current request as done, which -+ * will trigger calling the recv function and allow the request to continue. -+ */ -+struct tevent_req *kcm_op_queue_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ops_queue_ctx *qctx, -+ struct cli_creds *client) -+{ -+ errno_t ret; -+ struct tevent_req *req; -+ struct kcm_op_queue_state *state; -+ uid_t uid; -+ -+ uid = cli_creds_get_uid(client); -+ -+ req = tevent_req_create(mem_ctx, &state, struct kcm_op_queue_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ state->entry = talloc_zero(state, struct kcm_ops_queue_entry); -+ if (state->entry == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ state->entry->req = req; -+ state->entry->uid = uid; -+ state->entry->wait_queue_hash = qctx->wait_queue_hash; -+ -+ DEBUG(SSSDBG_FUNC_DATA, -+ "Adding request by %"SPRIuid" to the wait queue\n", uid); -+ -+ ret = kcm_op_queue_add(qctx->wait_queue_hash, state->entry, uid); -+ if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Wait queue was empty, running immediately\n"); -+ goto immediate; -+ } else if (ret != EAGAIN) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot enqueue request [%d]: %s\n", ret, sss_strerror(ret)); -+ goto immediate; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Waiting our turn in the queue\n"); -+ return req; -+ -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+/* -+ * The queue recv function is called when this request is 'activated'. The queue -+ * entry should be allocated on the same memory context as the enqueued request -+ * to trigger freeing the kcm_ops_queue_entry structure destructor when the -+ * parent request is done and its tevent_req freed. This would in turn unblock -+ * the next request in the queue -+ */ -+errno_t kcm_op_queue_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ops_queue_entry **_entry) -+{ -+ struct kcm_op_queue_state *state = tevent_req_data(req, -+ struct kcm_op_queue_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *_entry = talloc_steal(mem_ctx, state->entry); -+ return EOK; -+} -diff --git a/src/responder/kcm/kcmsrv_ops.c b/src/responder/kcm/kcmsrv_ops.c -index 50e8cc635424e15d53e3c8d122c5525044f59c8a..2feaf51f227ce9d90f706229ce7ac201b282dc6f 100644 ---- a/src/responder/kcm/kcmsrv_ops.c -+++ b/src/responder/kcm/kcmsrv_ops.c -@@ -67,17 +67,21 @@ struct kcm_op { - - struct kcm_cmd_state { - struct kcm_op *op; -+ struct tevent_context *ev; - -+ struct kcm_ops_queue_entry *queue_entry; - struct kcm_op_ctx *op_ctx; - struct sss_iobuf *reply; - - uint32_t op_ret; - }; - -+static void kcm_cmd_queue_done(struct tevent_req *subreq); - static void kcm_cmd_done(struct tevent_req *subreq); - - struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, -+ struct kcm_ops_queue_ctx *qctx, - struct kcm_resp_ctx *kcm_data, - struct cli_creds *client, - struct kcm_data *input, -@@ -93,6 +97,7 @@ struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx, - return NULL; - } - state->op = op; -+ state->ev = ev; - - if (op == NULL) { - ret = EINVAL; -@@ -154,18 +159,43 @@ struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx, - goto immediate; - } - -- subreq = op->fn_send(state, ev, state->op_ctx); -+ subreq = kcm_op_queue_send(state, ev, qctx, client); - if (subreq == NULL) { - ret = ENOMEM; - goto immediate; - } -+ tevent_req_set_callback(subreq, kcm_cmd_queue_done, req); -+ return req; -+ -+immediate: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void kcm_cmd_queue_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); -+ struct kcm_cmd_state *state = tevent_req_data(req, struct kcm_cmd_state); -+ errno_t ret; -+ -+ /* When this request finishes, it frees the queue_entry which unblocks -+ * other requests by the same UID -+ */ -+ ret = kcm_op_queue_recv(subreq, state, &state->queue_entry); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot acquire queue slot\n"); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = state->op->fn_send(state, state->ev, state->op_ctx); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } - tevent_req_set_callback(subreq, kcm_cmd_done, req); -- return req; -- --immediate: -- tevent_req_error(req, ret); -- tevent_req_post(req, ev); -- return req; - } - - static void kcm_cmd_done(struct tevent_req *subreq) -diff --git a/src/responder/kcm/kcmsrv_ops.h b/src/responder/kcm/kcmsrv_ops.h -index 8e6feaf56a10b73c8b6375aea9ef26c392b5b492..67d9f86026bf949548471f2280c130ebefd2f865 100644 ---- a/src/responder/kcm/kcmsrv_ops.h -+++ b/src/responder/kcm/kcmsrv_ops.h -@@ -34,6 +34,7 @@ const char *kcm_opt_name(struct kcm_op *op); - - struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, -+ struct kcm_ops_queue_ctx *qctx, - struct kcm_resp_ctx *kcm_data, - struct cli_creds *client, - struct kcm_data *input, -diff --git a/src/responder/kcm/kcmsrv_pvt.h b/src/responder/kcm/kcmsrv_pvt.h -index 74f30c00014105ed533744779b02c5d42523722d..f081a6bf0c6e40d2f8a83b07f9bbc2abacff359d 100644 ---- a/src/responder/kcm/kcmsrv_pvt.h -+++ b/src/responder/kcm/kcmsrv_pvt.h -@@ -25,6 +25,7 @@ - #include "config.h" - - #include -+#include - #include "responder/common/responder.h" - - /* -@@ -65,6 +66,7 @@ struct kcm_ctx { - int fd_limit; - char *socket_path; - enum kcm_ccdb_be cc_be; -+ struct kcm_ops_queue_ctx *qctx; - - struct kcm_resp_ctx *kcm_data; - }; -@@ -78,4 +80,22 @@ int kcm_connection_setup(struct cli_ctx *cctx); - */ - krb5_error_code sss2krb5_error(errno_t err); - -+/* We enqueue all requests by the same UID to avoid concurrency issues -+ * especially when performing multiple round-trips to sssd-secrets. In -+ * future, we should relax the queue to allow multiple read-only operations -+ * if no write operations are in progress. -+ */ -+struct kcm_ops_queue_entry; -+ -+struct kcm_ops_queue_ctx *kcm_ops_queue_create(TALLOC_CTX *mem_ctx); -+ -+struct tevent_req *kcm_op_queue_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ops_queue_ctx *qctx, -+ struct cli_creds *client); -+ -+errno_t kcm_op_queue_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ struct kcm_ops_queue_entry **_entry); -+ - #endif /* __KCMSRV_PVT_H__ */ -diff --git a/src/tests/cmocka/test_kcm_queue.c b/src/tests/cmocka/test_kcm_queue.c -new file mode 100644 -index 0000000000000000000000000000000000000000..ba0d2405629960df5c623848f3207b7c80fa948d ---- /dev/null -+++ b/src/tests/cmocka/test_kcm_queue.c -@@ -0,0 +1,365 @@ -+/* -+ Copyright (C) 2017 Red Hat -+ -+ SSSD tests: Test KCM wait queue -+ -+ 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 -+ -+#include "util/util.h" -+#include "util/util_creds.h" -+#include "tests/cmocka/common_mock.h" -+#include "responder/kcm/kcmsrv_pvt.h" -+ -+#define INVALID_ID -1 -+#define FAST_REQ_ID 0 -+#define SLOW_REQ_ID 1 -+ -+#define FAST_REQ_DELAY 1 -+#define SLOW_REQ_DELAY 2 -+ -+struct timed_request_state { -+ struct tevent_context *ev; -+ struct kcm_ops_queue_ctx *qctx; -+ struct cli_creds *client; -+ int delay; -+ int req_id; -+ -+ struct kcm_ops_queue_entry *queue_entry; -+}; -+ -+static void timed_request_start(struct tevent_req *subreq); -+static void timed_request_done(struct tevent_context *ev, -+ struct tevent_timer *te, -+ struct timeval current_time, -+ void *pvt); -+ -+static struct tevent_req *timed_request_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct kcm_ops_queue_ctx *qctx, -+ struct cli_creds *client, -+ int delay, -+ int req_id) -+{ -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct timed_request_state *state; -+ -+ req = tevent_req_create(mem_ctx, &state, struct timed_request_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->qctx = qctx; -+ state->client = client; -+ state->delay = delay; -+ state->req_id = req_id; -+ -+ DEBUG(SSSDBG_TRACE_ALL, "Request %p with delay %d\n", req, delay); -+ -+ subreq = kcm_op_queue_send(state, ev, qctx, client); -+ if (subreq == NULL) { -+ return NULL; -+ } -+ tevent_req_set_callback(subreq, timed_request_start, req); -+ -+ return req; -+} -+ -+static void timed_request_start(struct tevent_req *subreq) -+{ -+ struct timeval tv; -+ struct tevent_timer *timeout = NULL; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct timed_request_state *state = tevent_req_data(req, -+ struct timed_request_state); -+ errno_t ret; -+ -+ ret = kcm_op_queue_recv(subreq, state, &state->queue_entry); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tv = tevent_timeval_current_ofs(state->delay, 0); -+ timeout = tevent_add_timer(state->ev, state, tv, timed_request_done, req); -+ if (timeout == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ return; -+} -+ -+static void timed_request_done(struct tevent_context *ev, -+ struct tevent_timer *te, -+ struct timeval current_time, -+ void *pvt) -+{ -+ struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); -+ DEBUG(SSSDBG_TRACE_ALL, "Request %p done\n", req); -+ tevent_req_done(req); -+} -+ -+static errno_t timed_request_recv(struct tevent_req *req, -+ int *req_id) -+{ -+ struct timed_request_state *state = tevent_req_data(req, -+ struct timed_request_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ *req_id = state->req_id; -+ return EOK; -+} -+ -+struct test_ctx { -+ struct kcm_ops_queue_ctx *qctx; -+ struct tevent_context *ev; -+ -+ int *req_ids; -+ -+ int num_requests; -+ int finished_requests; -+ bool done; -+ errno_t error; -+}; -+ -+static int setup_kcm_queue(void **state) -+{ -+ struct test_ctx *tctx; -+ -+ tctx = talloc_zero(NULL, struct test_ctx); -+ assert_non_null(tctx); -+ -+ tctx->ev = tevent_context_init(tctx); -+ assert_non_null(tctx->ev); -+ -+ tctx->qctx = kcm_ops_queue_create(tctx); -+ assert_non_null(tctx->qctx); -+ -+ *state = tctx; -+ return 0; -+} -+ -+static int teardown_kcm_queue(void **state) -+{ -+ struct test_ctx *tctx = talloc_get_type(*state, struct test_ctx); -+ talloc_free(tctx); -+ return 0; -+} -+ -+static void test_kcm_queue_done(struct tevent_req *req) -+{ -+ struct test_ctx *test_ctx = tevent_req_callback_data(req, -+ struct test_ctx); -+ int req_id = INVALID_ID; -+ -+ test_ctx->error = timed_request_recv(req, &req_id); -+ talloc_zfree(req); -+ if (test_ctx->error != EOK) { -+ test_ctx->done = true; -+ return; -+ } -+ -+ if (test_ctx->req_ids[test_ctx->finished_requests] != req_id) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Request %d finished, expected %d\n", -+ req_id, test_ctx->req_ids[test_ctx->finished_requests]); -+ test_ctx->error = EIO; -+ test_ctx->done = true; -+ return; -+ } -+ -+ test_ctx->finished_requests++; -+ if (test_ctx->finished_requests == test_ctx->num_requests) { -+ test_ctx->done = true; -+ return; -+ } -+} -+ -+/* -+ * Just make sure that a single pass through the queue works -+ */ -+static void test_kcm_queue_single(void **state) -+{ -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ struct tevent_req *req; -+ struct cli_creds client; -+ static int req_ids[] = { 0 }; -+ -+ client.ucred.uid = getuid(); -+ client.ucred.gid = getgid(); -+ -+ req = timed_request_send(test_ctx, -+ test_ctx->ev, -+ test_ctx->qctx, -+ &client, 1, 0); -+ assert_non_null(req); -+ tevent_req_set_callback(req, test_kcm_queue_done, test_ctx); -+ -+ test_ctx->num_requests = 1; -+ test_ctx->req_ids = req_ids; -+ -+ while (test_ctx->done == false) { -+ tevent_loop_once(test_ctx->ev); -+ } -+ assert_int_equal(test_ctx->error, EOK); -+} -+ -+/* -+ * Test that multiple requests from the same ID wait for one another -+ */ -+static void test_kcm_queue_multi_same_id(void **state) -+{ -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ struct tevent_req *req; -+ struct cli_creds client; -+ /* The slow request will finish first because request from -+ * the same ID are serialized -+ */ -+ static int req_ids[] = { SLOW_REQ_ID, FAST_REQ_ID }; -+ -+ client.ucred.uid = getuid(); -+ client.ucred.gid = getgid(); -+ -+ req = timed_request_send(test_ctx, -+ test_ctx->ev, -+ test_ctx->qctx, -+ &client, -+ SLOW_REQ_DELAY, -+ SLOW_REQ_ID); -+ assert_non_null(req); -+ tevent_req_set_callback(req, test_kcm_queue_done, test_ctx); -+ -+ req = timed_request_send(test_ctx, -+ test_ctx->ev, -+ test_ctx->qctx, -+ &client, -+ FAST_REQ_DELAY, -+ FAST_REQ_ID); -+ assert_non_null(req); -+ tevent_req_set_callback(req, test_kcm_queue_done, test_ctx); -+ -+ test_ctx->num_requests = 2; -+ test_ctx->req_ids = req_ids; -+ -+ while (test_ctx->done == false) { -+ tevent_loop_once(test_ctx->ev); -+ } -+ assert_int_equal(test_ctx->error, EOK); -+} -+ -+/* -+ * Test that multiple requests from different IDs don't wait for one -+ * another and can run concurrently -+ */ -+static void test_kcm_queue_multi_different_id(void **state) -+{ -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ struct tevent_req *req; -+ struct cli_creds client; -+ /* In this test, the fast request will finish sooner because -+ * both requests are from different IDs, allowing them to run -+ * concurrently -+ */ -+ static int req_ids[] = { FAST_REQ_ID, SLOW_REQ_ID }; -+ -+ client.ucred.uid = getuid(); -+ client.ucred.gid = getgid(); -+ -+ req = timed_request_send(test_ctx, -+ test_ctx->ev, -+ test_ctx->qctx, -+ &client, -+ SLOW_REQ_DELAY, -+ SLOW_REQ_ID); -+ assert_non_null(req); -+ tevent_req_set_callback(req, test_kcm_queue_done, test_ctx); -+ -+ client.ucred.uid = getuid() + 1; -+ client.ucred.gid = getgid() + 1; -+ -+ req = timed_request_send(test_ctx, -+ test_ctx->ev, -+ test_ctx->qctx, -+ &client, -+ FAST_REQ_DELAY, -+ FAST_REQ_ID); -+ assert_non_null(req); -+ tevent_req_set_callback(req, test_kcm_queue_done, test_ctx); -+ -+ test_ctx->num_requests = 2; -+ test_ctx->req_ids = req_ids; -+ -+ while (test_ctx->done == false) { -+ tevent_loop_once(test_ctx->ev); -+ } -+ assert_int_equal(test_ctx->error, EOK); -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ poptContext pc; -+ int opt; -+ int rv; -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ SSSD_DEBUG_OPTS -+ POPT_TABLEEND -+ }; -+ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown(test_kcm_queue_single, -+ setup_kcm_queue, -+ teardown_kcm_queue), -+ cmocka_unit_test_setup_teardown(test_kcm_queue_multi_same_id, -+ setup_kcm_queue, -+ teardown_kcm_queue), -+ cmocka_unit_test_setup_teardown(test_kcm_queue_multi_different_id, -+ setup_kcm_queue, -+ teardown_kcm_queue), -+ }; -+ -+ /* 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); -+ -+ /* Even though normally the tests should clean up after themselves -+ * they might not after a failed run. Remove the old db to be sure */ -+ tests_set_cwd(); -+ -+ rv = cmocka_run_group_tests(tests, NULL, NULL); -+ -+ return rv; -+} --- -2.12.2 - diff --git a/0038-KCM-Idle-terminate-the-responder-if-the-secrets-back.patch b/0038-KCM-Idle-terminate-the-responder-if-the-secrets-back.patch deleted file mode 100644 index b08f385..0000000 --- a/0038-KCM-Idle-terminate-the-responder-if-the-secrets-back.patch +++ /dev/null @@ -1,55 +0,0 @@ -From e89ba95737202d551db2c9524127e6c4cf308796 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 21 Mar 2017 14:26:54 +0100 -Subject: [PATCH 38/97] KCM: Idle-terminate the responder if the secrets back - end is used -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Existing with memory database would be fatal as we keep the ccaches in -memory then, but if the ccaches are stored in sssd-secrets, we can just -exit on idle. - -Reviewed-by: Michal Židek -Reviewed-by: Simo Sorce ---- - src/config/cfg_rules.ini | 1 + - src/responder/kcm/kcm.c | 9 +++++++++ - 2 files changed, 10 insertions(+) - -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 67a5d1f5ad447a942b437ffd04a7f5d7cfe77d7f..933ebccd828189d923d2186753dfbc0b5c0814ce 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -281,6 +281,7 @@ option = client_idle_timeout - option = description - option = socket_path - option = ccache_storage -+option = responder_idle_timeout - - [rule/allowed_domain_options] - validator = ini_allowed_options -diff --git a/src/responder/kcm/kcm.c b/src/responder/kcm/kcm.c -index 3ee978066c589a5cc38b0ae358f741d389d00e7a..2202f96381a2622a2c5433e281172287b325f960 100644 ---- a/src/responder/kcm/kcm.c -+++ b/src/responder/kcm/kcm.c -@@ -133,6 +133,15 @@ static int kcm_get_config(struct kcm_ctx *kctx) - goto done; - } - -+ if (kctx->cc_be == CCDB_BE_SECRETS) { -+ ret = responder_setup_idle_timeout_config(kctx->rctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot set up idle responder timeout\n"); -+ /* Not fatal */ -+ } -+ } -+ - kctx->qctx = kcm_ops_queue_create(kctx); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, --- -2.12.2 - diff --git a/0039-SSSDConfig-Python-3.6-invalid-escape-sequence-deprec.patch b/0039-SSSDConfig-Python-3.6-invalid-escape-sequence-deprec.patch deleted file mode 100644 index fb429bd..0000000 --- a/0039-SSSDConfig-Python-3.6-invalid-escape-sequence-deprec.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 00172861b6908a72c41046e1b2b48d2b009127dd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ville=20Skytt=C3=A4?= -Date: Wed, 22 Mar 2017 20:32:21 +0000 -Subject: [PATCH 39/97] SSSDConfig: Python 3.6 invalid escape sequence - deprecation fix -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://docs.python.org/3/whatsnew/3.6.html#deprecated-python-behavior - -Merges: https://pagure.io/SSSD/sssd/pull-request/3346 - -Reviewed-by: Lukáš Slebodník ---- - src/config/SSSDConfig/__init__.py.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 03a1a43336604bb815626e64cb54052bdf87acf2..29e9b4fae6835db4ccb9937fd93457d462e4a15d 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -483,7 +483,7 @@ class SSSDConfigSchema(SSSDChangeConf): - self.readfp(fd) - fd.close() - # Read in the provider files -- for file in filter(lambda f: re.search('^sssd-.*\.conf$', f), -+ for file in filter(lambda f: re.search(r'^sssd-.*\.conf$', f), - os.listdir(schemaplugindir)): - fd = open(schemaplugindir+ "/" + file) - self.readfp(fd) --- -2.12.2 - diff --git a/0040-CONFIGURE-Fix-fallback-if-pkg-config-for-uuid-is-mis.patch b/0040-CONFIGURE-Fix-fallback-if-pkg-config-for-uuid-is-mis.patch deleted file mode 100644 index b62618a..0000000 --- a/0040-CONFIGURE-Fix-fallback-if-pkg-config-for-uuid-is-mis.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 7c67679ba86682d8c2afea404ec0229641a7f473 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 27 Mar 2017 11:59:01 +0200 -Subject: [PATCH 40/97] CONFIGURE: Fix fallback if pkg-config for uuid is - missing -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Fabiano Fidêncio ---- - src/external/libuuid.m4 | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/external/libuuid.m4 b/src/external/libuuid.m4 -index 55411a2118bd787c9d50ba61f9cb791e1c76088d..323521c9224e443f40a15b417038d2dcea9b66f3 100644 ---- a/src/external/libuuid.m4 -+++ b/src/external/libuuid.m4 -@@ -4,7 +4,7 @@ AC_SUBST(UUID_CFLAGS) - PKG_CHECK_MODULES([UUID], [uuid], [found_uuid=yes], [found_uuid=no]) - - SSS_AC_EXPAND_LIB_DIR() --AS_IF([test x"$found_uuid" = xyes], -+AS_IF([test x"$found_uuid" != xyes], - [AC_CHECK_HEADERS([uuid/uuid.h], - [AC_CHECK_LIB([uuid], - [uuid_generate], --- -2.12.2 - diff --git a/0041-intg-fix-configure-failure-with-strict-cflags.patch b/0041-intg-fix-configure-failure-with-strict-cflags.patch deleted file mode 100644 index e792c93..0000000 --- a/0041-intg-fix-configure-failure-with-strict-cflags.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 8e785c7478e1a79179842106a62f3f85118b6690 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 28 Mar 2017 12:18:13 +0200 -Subject: [PATCH 41/97] intg: fix configure failure with strict cflags -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The warning -Wstrict-prototypes is a part of AM_CFLAGS which was appended -for CFLAGS in make target intgcheck-prepare. And combination with -strict CFLAGS in environment variable (e.g. -Werror) caused failures. - -sh$ CFLAGS="-Werror" make intgcheck-prepare - -checking for gcc... gcc -checking whether the C compiler works... no -configure: error: in `/home/build/sssd/ci-build-debug/intg/bld': -configure: error: C compiler cannot create executables - -configure:3719: checking whether the C compiler works -configure:3741: gcc -g3 -O2 -Werror -D_FILE_OFFSET_BITS=64 - -D_LARGEFILE_SOURCE -Wall -Wshadow -Wstrict-prototypes - -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings - -Wundef -Werror-implicit-function-declaration - -Winit-self -Wmissing-include-dirs -fno-strict-aliasing - -std=gnu99 -DKCM_PEER_UID=1000 conftest.c >&5 -conftest.c:11:1: error: function declaration isn't a prototype [-Werror=strict-prototypes] - main () - ^~~~ -cc1: all warnings being treated as errors - -Reviewed-by: Pavel Březina ---- - Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Makefile.am b/Makefile.am -index 91afdd669aa11a3cc316588d3b51d7e8e9c91cb8..359feddef298b0013c726409b7ba8b86504abf09 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -3486,7 +3486,7 @@ intgcheck-prepare: - --without-semanage \ - --enable-files-domain \ - $(INTGCHECK_CONFIGURE_FLAGS) \ -- CFLAGS="$$CFLAGS $(AM_CFLAGS) -DKCM_PEER_UID=$$(id -u)"; \ -+ CFLAGS="$$CFLAGS -DKCM_PEER_UID=$$(id -u)"; \ - $(MAKE) $(AM_MAKEFLAGS) ; \ - : Force single-thread install to workaround concurrency issues; \ - $(MAKE) $(AM_MAKEFLAGS) -j1 install; \ --- -2.12.2 - diff --git a/0042-intg-Remove-bashism-from-intgcheck-prepare.patch b/0042-intg-Remove-bashism-from-intgcheck-prepare.patch deleted file mode 100644 index 4f8292f..0000000 --- a/0042-intg-Remove-bashism-from-intgcheck-prepare.patch +++ /dev/null @@ -1,54 +0,0 @@ -From f75ba99fc8dd64e45af2f642d9fb7660860fd28f Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 27 Mar 2017 14:44:29 +0200 -Subject: [PATCH 42/97] intg: Remove bashism from intgcheck-prepare - -env variable UID is not defined in all shells (eg. dash) -We also need to move invocation of "id -u" before nss_wraper -is enabled otherwise we would get root instead of real user. - -=================================== FAILURES =================================== -________________________ test_kcm_mem_init_list_destroy ________________________ -Traceback (most recent call last): - File "/home/build/sssd/src/tests/intg/test_kcm.py", line 198, in test_kcm_mem_init_list_destroy - kcm_init_list_destroy(testenv) - File "/home/build/sssd/src/tests/intg/test_kcm.py", line 183, in kcm_init_list_destroy - exp_ccname = testenv.ccname() - File "/home/build/sssd/src/tests/intg/test_kcm.py", line 45, in ccname - my_uid = self.my_uid() - File "/home/build/sssd/src/tests/intg/test_kcm.py", line 41, in my_uid - return int(s_myuid) -ValueError: invalid literal for int() with base 10: '' - -And we already use different approach in top level Makefile.am -3488) $(INTGCHECK_CONFIGURE_FLAGS) \ -3489) CFLAGS="$$CFLAGS $(AM_CFLAGS) -DKCM_PEER_UID=$$(id -u)"; \ -3490) $(MAKE) $(AM_MAKEFLAGS) ; \ - -Reviewed-by: Jakub Hrozek ---- - src/tests/intg/Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am -index 8526beace09b15c99aa27ac98d5038d1980f6a71..8566106e9017a8d3c9e7a3898a3a886e2966e346 100644 ---- a/src/tests/intg/Makefile.am -+++ b/src/tests/intg/Makefile.am -@@ -76,6 +76,7 @@ intgcheck-installed: config.py passwd group - PATH="$(abs_builddir):$(abs_srcdir):$$PATH" \ - PYTHONPATH="$(abs_builddir):$(abs_srcdir)" \ - LDB_MODULES_PATH="$(DESTDIR)$(ldblibdir)" \ -+ NON_WRAPPED_UID=$$(id -u) \ - LD_PRELOAD="$$nss_wrapper $$uid_wrapper" \ - NSS_WRAPPER_PASSWD="$(abs_builddir)/passwd" \ - NSS_WRAPPER_GROUP="$(abs_builddir)/group" \ -@@ -83,6 +84,5 @@ intgcheck-installed: config.py passwd group - NSS_WRAPPER_MODULE_FN_PREFIX="sss" \ - UID_WRAPPER=1 \ - UID_WRAPPER_ROOT=1 \ -- NON_WRAPPED_UID=$$(echo $$UID) \ - fakeroot $(PYTHON2) $(PYTEST) -v --tb=native $(INTGCHECK_PYTEST_ARGS) . - rm -f $(DESTDIR)$(logpath)/* --- -2.12.2 - diff --git a/0043-UTIL-Introduce-subdomain_create_conf_path.patch b/0043-UTIL-Introduce-subdomain_create_conf_path.patch deleted file mode 100644 index 46d56a8..0000000 --- a/0043-UTIL-Introduce-subdomain_create_conf_path.patch +++ /dev/null @@ -1,127 +0,0 @@ -From e0e038218580166648ac24f23180f0f4c2769d99 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20=C5=BDidek?= -Date: Tue, 28 Mar 2017 18:33:46 +0200 -Subject: [PATCH 43/97] UTIL: Introduce subdomain_create_conf_path() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is a utility function that replaces the create_subdom_conf_path(). -Differently than the latter, it only takes one parameter and is going to -be used in a few different places (thus adding it to util.h). - -Reviewed-by: Fabiano Fidêncio -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukas Slebodnik ---- - src/providers/ad/ad_common.c | 7 ------- - src/providers/ad/ad_common.h | 4 ---- - src/providers/ad/ad_subdomains.c | 4 +--- - src/providers/ipa/ipa_subdomains_server.c | 4 +--- - src/util/domain_info_utils.c | 15 +++++++++++++++ - src/util/util.h | 3 +++ - 6 files changed, 20 insertions(+), 17 deletions(-) - -diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c -index ec952d3bb4587516ea26fd27c212d5620e2f3dda..f893b748a2ddcff1eab6e8d919d2aa950b825446 100644 ---- a/src/providers/ad/ad_common.c -+++ b/src/providers/ad/ad_common.c -@@ -33,13 +33,6 @@ errno_t ad_set_search_bases(struct sdap_options *id_opts); - static errno_t ad_set_sdap_options(struct ad_options *ad_opts, - struct sdap_options *id_opts); - --char *create_subdom_conf_path(TALLOC_CTX *mem_ctx, -- const char *conf_path, -- const char *subdom_name) --{ -- return talloc_asprintf(mem_ctx, "%s/%s", conf_path, subdom_name); --} -- - static struct sdap_options * - ad_create_default_sdap_options(TALLOC_CTX *mem_ctx) - { -diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h -index e02b932cd2da737254de8417d5c82fcdcf14e8d7..2981550f6c390929501ec8942e861b16ea0a5cb0 100644 ---- a/src/providers/ad/ad_common.h -+++ b/src/providers/ad/ad_common.h -@@ -99,10 +99,6 @@ struct ad_options { - struct be_nsupdate_ctx *dyndns_ctx; - }; - --char *create_subdom_conf_path(TALLOC_CTX *mem_ctx, -- const char *conf_path, -- const char *subdom_name); -- - errno_t - ad_get_common_options(TALLOC_CTX *mem_ctx, - struct confdb_ctx *cdb, -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 156ecab4272029d69c8b596eff041498a7524ce4..eecae9c9ca82ad67874c13a3c7b7c617d6232d5c 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -171,9 +171,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, - return EINVAL; - } - -- subdom_conf_path = create_subdom_conf_path(id_ctx, -- be_ctx->conf_path, -- subdom->name); -+ subdom_conf_path = subdomain_create_conf_path(id_ctx, subdom); - if (subdom_conf_path == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "subdom_conf_path failed\n"); - return ENOMEM; -diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c -index ae3baf036e4278fb67d86b42742fb7e80b46724e..e8ee30392d84f84e30bcdaa3d2110ba130b1ad73 100644 ---- a/src/providers/ipa/ipa_subdomains_server.c -+++ b/src/providers/ipa/ipa_subdomains_server.c -@@ -176,9 +176,7 @@ static struct ad_options *ipa_ad_options_new(struct be_ctx *be_ctx, - forest_realm = subdom->forest_root->realm; - forest = subdom->forest_root->forest; - -- subdom_conf_path = create_subdom_conf_path(id_ctx, -- be_ctx->conf_path, -- subdom->name); -+ subdom_conf_path = subdomain_create_conf_path(id_ctx, subdom); - if (subdom_conf_path == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "subdom_conf_path failed\n"); - return NULL; -diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c -index 6ef6bcfb8c078a360673b6bdd2364fc2918cb324..a7f118842aa8ba870143b2f2b425a3e3c0ea5a78 100644 ---- a/src/util/domain_info_utils.c -+++ b/src/util/domain_info_utils.c -@@ -870,3 +870,18 @@ bool is_email_from_domain(const char *email, struct sss_domain_info *dom) - - return false; - } -+ -+char *subdomain_create_conf_path(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *subdomain) -+{ -+ if (!IS_SUBDOMAIN(subdomain)) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "The domain \"%s\" is not a subdomain.\n", -+ subdomain->name); -+ return NULL; -+ } -+ -+ return talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL "/%s", -+ subdomain->parent->name, -+ subdomain->name); -+} -diff --git a/src/util/util.h b/src/util/util.h -index a2dc89b8ddb999437eda551ac17af28672d8759c..82760940269ad8883e725e3a5cf463486c9cfd36 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -551,6 +551,9 @@ find_domain_by_object_name(struct sss_domain_info *domain, - bool subdomain_enumerates(struct sss_domain_info *parent, - const char *sd_name); - -+char *subdomain_create_conf_path(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *subdomain); -+ - errno_t sssd_domain_init(TALLOC_CTX *mem_ctx, - struct confdb_ctx *cdb, - const char *domain_name, --- -2.12.2 - diff --git a/0044-SUBDOMAINS-Allow-use_fully_qualified_names-for-subdo.patch b/0044-SUBDOMAINS-Allow-use_fully_qualified_names-for-subdo.patch deleted file mode 100644 index f883b67..0000000 --- a/0044-SUBDOMAINS-Allow-use_fully_qualified_names-for-subdo.patch +++ /dev/null @@ -1,531 +0,0 @@ -From a63d74f65db2db7389cd373cb37adcdaaa2d56ea Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20=C5=BDidek?= -Date: Thu, 23 Mar 2017 13:14:56 +0100 -Subject: [PATCH 44/97] SUBDOMAINS: Allow use_fully_qualified_names for - subdomains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Allow option use_fully_qualified_names in subdomain section. -This option was recently added to subdomain_inherit. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3337 - -Reviewed-by: Fabiano Fidêncio ---- - src/db/sysdb.h | 3 +- - src/db/sysdb_private.h | 3 +- - src/db/sysdb_subdomains.c | 63 +++++++++++++++++++++++++-- - src/man/sssd.conf.5.xml | 3 +- - src/providers/ad/ad_subdomains.c | 3 +- - src/providers/ipa/ipa_subdomains.c | 10 +++-- - src/responder/common/responder_get_domains.c | 9 ++-- - src/tests/cmocka/test_fqnames.c | 2 +- - src/tests/cmocka/test_ipa_subdomains_server.c | 2 +- - src/tests/cmocka/test_nss_srv.c | 6 ++- - src/tests/cmocka/test_sysdb_subdomains.c | 25 ++++++----- - src/tests/sysdb-tests.c | 14 +++--- - src/tools/common/sss_tools.c | 2 +- - src/tools/sss_cache.c | 2 +- - 14 files changed, 107 insertions(+), 40 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 0cbb2c5c02355e9e9a4e73b075f92d16e4855045..6762b51bee02911fb97d5d393fad2495504ee5ad 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -494,7 +494,8 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, - uint32_t trust_direction, - struct ldb_message_element *upn_suffixes); - --errno_t sysdb_update_subdomains(struct sss_domain_info *domain); -+errno_t sysdb_update_subdomains(struct sss_domain_info *domain, -+ struct confdb_ctx *confdb); - - errno_t sysdb_master_domain_update(struct sss_domain_info *domain); - -diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h -index bfd24799950ab3b31d57df11b8f91c0b2572f13a..dfddd2dda9e593bd02d52dee7d06f520a11bbdf6 100644 ---- a/src/db/sysdb_private.h -+++ b/src/db/sysdb_private.h -@@ -191,7 +191,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, - bool enumerate, - const char *forest, - const char **upn_suffixes, -- uint32_t trust_direction); -+ uint32_t trust_direction, -+ struct confdb_ctx *confdb); - - /* Helper functions to deal with the timestamp cache should not be used - * outside the sysdb itself. The timestamp cache should be completely -diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c -index 01f49763b712769f4f74df47961526e5b1514cd4..916dbba153d8c08837425f6fd29a20f5a6aa9fc9 100644 ---- a/src/db/sysdb_subdomains.c -+++ b/src/db/sysdb_subdomains.c -@@ -23,6 +23,10 @@ - #include "util/util.h" - #include "db/sysdb_private.h" - -+static errno_t -+check_subdom_config_file(struct confdb_ctx *confdb, -+ struct sss_domain_info *subdomain); -+ - struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, - struct sss_domain_info *parent, - const char *name, -@@ -33,10 +37,12 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, - bool enumerate, - const char *forest, - const char **upn_suffixes, -- uint32_t trust_direction) -+ uint32_t trust_direction, -+ struct confdb_ctx *confdb) - { - struct sss_domain_info *dom; - bool inherit_option; -+ errno_t ret; - - DEBUG(SSSDBG_TRACE_FUNC, - "Creating [%s] as subdomain of [%s]!\n", name, parent->name); -@@ -160,6 +166,17 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, - } - dom->sysdb = parent->sysdb; - -+ if (confdb != NULL) { -+ /* If confdb was provided, also check for sssd.conf */ -+ ret = check_subdom_config_file(confdb, dom); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to read subdomain configuration [%d]: %s", -+ ret, sss_strerror(ret)); -+ goto fail; -+ } -+ } -+ - return dom; - - fail: -@@ -167,6 +184,45 @@ fail: - return NULL; - } - -+static errno_t -+check_subdom_config_file(struct confdb_ctx *confdb, -+ struct sss_domain_info *subdomain) -+{ -+ char *sd_conf_path; -+ TALLOC_CTX *tmp_ctx; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ sd_conf_path = subdomain_create_conf_path(tmp_ctx, subdomain); -+ if (sd_conf_path == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* use_fully_qualified_names */ -+ ret = confdb_get_bool(confdb, sd_conf_path, CONFDB_DOMAIN_FQ, -+ true, &subdomain->fqnames); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get %s option for the subdomain: %s\n", -+ CONFDB_DOMAIN_FQ, subdomain->name); -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_CONF_SETTINGS, "%s/%s has value %s\n", -+ sd_conf_path, CONFDB_DOMAIN_FQ, -+ subdomain->fqnames ? "TRUE" : "FALSE"); -+ -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ - static bool is_forest_root(struct sss_domain_info *d) - { - if (d->forest == NULL) { -@@ -232,7 +288,8 @@ static void link_forest_roots(struct sss_domain_info *domain) - } - } - --errno_t sysdb_update_subdomains(struct sss_domain_info *domain) -+errno_t sysdb_update_subdomains(struct sss_domain_info *domain, -+ struct confdb_ctx *confdb) - { - int i; - errno_t ret; -@@ -451,7 +508,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) - if (dom == NULL) { - dom = new_subdomain(domain, domain, name, realm, - flat, id, mpg, enumerate, forest, -- upn_suffixes, trust_direction); -+ upn_suffixes, trust_direction, confdb); - if (dom == NULL) { - ret = ENOMEM; - goto done; -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 284402bc00d37c6c33bf195d2bd719300f265851..1c27742cf0c1b6ffad23ab5b044bf4a168ed8f69 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -2780,7 +2780,8 @@ subdomain_inherit = ldap_purge_cache_timeout - ldap_service_search_base, - ad_server, - ad_backup_server, -- ad_site. -+ ad_site, -+ use_fully_qualified_names - - For more details about these options see their individual description - in the manual page. -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index eecae9c9ca82ad67874c13a3c7b7c617d6232d5c..bc659b2cb0a02723437d24d0021ec3592381e84c 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -656,7 +656,8 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *subdoms_ctx) - /* Just continue */ - } - -- ret = sysdb_update_subdomains(subdoms_ctx->be_ctx->domain); -+ ret = sysdb_update_subdomains(subdoms_ctx->be_ctx->domain, -+ subdoms_ctx->be_ctx->cdb); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n"); - return ret; -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 7537550606ef09c0b87a80932c75aa4f93c0efab..a07b88fe2f499353293ba90345552413c9792f4b 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -126,7 +126,7 @@ ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx) - return ret; - } - -- ret = sysdb_update_subdomains(ctx->be_ctx->domain); -+ ret = sysdb_update_subdomains(ctx->be_ctx->domain, ctx->be_ctx->cdb); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n"); - return ret; -@@ -780,7 +780,8 @@ done: - static errno_t ipa_apply_view(struct sss_domain_info *domain, - struct ipa_id_ctx *ipa_id_ctx, - const char *view_name, -- bool read_at_init) -+ bool read_at_init, -+ struct confdb_ctx *confdb) - { - const char *current = ipa_id_ctx->view_name; - struct sysdb_ctx *sysdb = domain->sysdb; -@@ -876,7 +877,7 @@ static errno_t ipa_apply_view(struct sss_domain_info *domain, - goto done; - } - -- ret = sysdb_update_subdomains(domain); -+ ret = sysdb_update_subdomains(domain, confdb); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed " - "[%d]: %s\n", ret, sss_strerror(ret)); -@@ -1654,7 +1655,8 @@ static void ipa_subdomains_view_name_done(struct tevent_req *subreq) - - ret = ipa_apply_view(state->sd_ctx->be_ctx->domain, - state->sd_ctx->ipa_id_ctx, view_name, -- state->sd_ctx->view_read_at_init); -+ state->sd_ctx->view_read_at_init, -+ state->sd_ctx->be_ctx->cdb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set view [%d]: %s\n", - ret, sss_strerror(ret)); -diff --git a/src/responder/common/responder_get_domains.c b/src/responder/common/responder_get_domains.c -index 0f39d107dad6c458785b1b8d708e60d7c34e3901..0f9c01214631200f9687635f6302fa5c07e8a1fe 100644 ---- a/src/responder/common/responder_get_domains.c -+++ b/src/responder/common/responder_get_domains.c -@@ -126,7 +126,8 @@ get_next_domain_recv(TALLOC_CTX *mem_ctx, - } - - /* ====== Iterate over all domains, searching for their subdomains ======= */ --static errno_t process_subdomains(struct sss_domain_info *dom); -+static errno_t process_subdomains(struct sss_domain_info *dom, -+ struct confdb_ctx *confdb); - static void set_time_of_last_request(struct resp_ctx *rctx); - static errno_t check_last_request(struct resp_ctx *rctx, const char *hint); - -@@ -234,7 +235,7 @@ sss_dp_get_domains_process(struct tevent_req *subreq) - goto fail; - } - -- ret = process_subdomains(state->dom); -+ ret = process_subdomains(state->dom, state->rctx->cdb); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "process_subdomains failed, " - "trying next domain.\n"); -@@ -270,7 +271,7 @@ fail: - } - - static errno_t --process_subdomains(struct sss_domain_info *domain) -+process_subdomains(struct sss_domain_info *domain, struct confdb_ctx *confdb) - { - int ret; - -@@ -288,7 +289,7 @@ process_subdomains(struct sss_domain_info *domain) - /* Retrieve all subdomains of this domain from sysdb - * and create their struct sss_domain_info representations - */ -- ret = sysdb_update_subdomains(domain); -+ ret = sysdb_update_subdomains(domain, confdb); - if (ret != EOK) { - DEBUG(SSSDBG_FUNC_DATA, "sysdb_update_subdomains failed.\n"); - goto done; -diff --git a/src/tests/cmocka/test_fqnames.c b/src/tests/cmocka/test_fqnames.c -index 19788248a39774bb4509363145ac4ce0815b7d28..0ed42a597b7787635c4971b4f1c3d9976949ccd2 100644 ---- a/src/tests/cmocka/test_fqnames.c -+++ b/src/tests/cmocka/test_fqnames.c -@@ -309,7 +309,7 @@ static int parse_name_test_setup(void **state) - * discovered - */ - test_ctx->subdom = new_subdomain(dom, dom, SUBDOMNAME, NULL, SUBFLATNAME, -- NULL, false, false, NULL, NULL, 0); -+ NULL, false, false, NULL, NULL, 0, NULL); - assert_non_null(test_ctx->subdom); - - check_leaks_push(test_ctx); -diff --git a/src/tests/cmocka/test_ipa_subdomains_server.c b/src/tests/cmocka/test_ipa_subdomains_server.c -index 123cf11c01ef4687eecad31a9d73120a87c643e1..ca48425aca69e58358f5fd37e4b8238bfa9efe15 100644 ---- a/src/tests/cmocka/test_ipa_subdomains_server.c -+++ b/src/tests/cmocka/test_ipa_subdomains_server.c -@@ -263,7 +263,7 @@ static void add_test_subdomains(struct trust_test_ctx *test_ctx, - direction, NULL); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - } -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index 50714715cc80338640f2a77ecbe17bd5e0d6e911..3d7e0382197401cb2264671712152fe0709296b6 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -3206,7 +3206,8 @@ static int nss_subdom_test_setup(void **state) - - subdomain = new_subdomain(nss_test_ctx, nss_test_ctx->tctx->dom, - testdom[0], testdom[1], testdom[2], testdom[3], -- false, false, NULL, NULL, 0); -+ false, false, NULL, NULL, 0, -+ nss_test_ctx->tctx->confdb); - assert_non_null(subdomain); - - ret = sysdb_subdomain_store(nss_test_ctx->tctx->sysdb, -@@ -3214,7 +3215,8 @@ static int nss_subdom_test_setup(void **state) - false, false, NULL, 0, NULL); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(nss_test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(nss_test_ctx->tctx->dom, -+ nss_test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - nss_test_ctx->subdom = subdomain; -diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c -index 49f44998a06740d1df70ac354ee741824acd8f50..84bcdc17b39dbc8822097c2006f157a09ea5e466 100644 ---- a/src/tests/cmocka/test_sysdb_subdomains.c -+++ b/src/tests/cmocka/test_sysdb_subdomains.c -@@ -103,7 +103,7 @@ static void test_sysdb_subdomain_create(void **state) - false, false, NULL, 0, NULL); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - assert_non_null(test_ctx->tctx->dom->subdomains); -@@ -115,7 +115,7 @@ static void test_sysdb_subdomain_create(void **state) - false, false, NULL, 1, NULL); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - assert_non_null(test_ctx->tctx->dom->subdomains->next); -@@ -133,7 +133,7 @@ static void test_sysdb_subdomain_create(void **state) - false, false, NULL, 0, NULL); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - assert_int_equal(test_ctx->tctx->dom->subdomains->trust_direction, 1); -@@ -145,7 +145,7 @@ static void test_sysdb_subdomain_create(void **state) - ret = sysdb_subdomain_delete(test_ctx->tctx->sysdb, dom1[0]); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - assert_int_equal(sss_domain_get_state(test_ctx->tctx->dom->subdomains), -@@ -235,11 +235,11 @@ static void test_sysdb_link_forest_root_ipa(void **state) - 0, NULL); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - /* Also update dom2 */ -- ret = sysdb_update_subdomains(test_ctx->tctx->dom->next); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom->next, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - sub = find_domain_by_name(test_ctx->tctx->dom, dom1[0], true); -@@ -315,11 +315,11 @@ static void test_sysdb_link_forest_root_ad(void **state) - 0, NULL); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - /* Also update dom2 */ -- ret = sysdb_update_subdomains(test_ctx->tctx->dom->next); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom->next, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - assert_non_null(test_ctx->tctx->dom->forest_root); -@@ -395,14 +395,15 @@ static void test_sysdb_link_forest_member_ad(void **state) - ret = sysdb_master_domain_update(test_ctx->tctx->dom); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom, test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - /* Also update dom2 */ - ret = sysdb_master_domain_update(test_ctx->tctx->dom->next); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(test_ctx->tctx->dom->next); -+ ret = sysdb_update_subdomains(test_ctx->tctx->dom->next, -+ test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - - /* Checks */ -@@ -472,7 +473,7 @@ static void test_sysdb_link_ad_multidom(void **state) - ret = sysdb_master_domain_update(main_dom1); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(main_dom1); -+ ret = sysdb_update_subdomains(main_dom1, NULL); - assert_int_equal(ret, EOK); - - ret = sysdb_master_domain_add_info(main_dom2, -@@ -492,7 +493,7 @@ static void test_sysdb_link_ad_multidom(void **state) - ret = sysdb_master_domain_update(main_dom2); - assert_int_equal(ret, EOK); - -- ret = sysdb_update_subdomains(main_dom2); -+ ret = sysdb_update_subdomains(main_dom2, NULL); - assert_int_equal(ret, EOK); - - main_dom1 = find_domain_by_name(test_ctx->tctx->dom, TEST_DOM1_NAME, true); -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index 5bdd631fbfa1b4463fb169e5f07b65fb2c784096..1767dc3c734c6b2e5f74564debd603e2442f491b 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -1395,7 +1395,7 @@ START_TEST (test_sysdb_get_user_attr_subdomain) - /* Create subdomain */ - subdomain = new_subdomain(test_ctx, test_ctx->domain, - "test.sub", "TEST.SUB", "test", "S-3", -- false, false, NULL, NULL, 0); -+ false, false, NULL, NULL, 0, NULL); - fail_if(subdomain == NULL, "Failed to create new subdomain."); - - ret = sss_names_init_from_args(test_ctx, -@@ -5821,14 +5821,14 @@ START_TEST(test_sysdb_subdomain_store_user) - - subdomain = new_subdomain(test_ctx, test_ctx->domain, - testdom[0], testdom[1], testdom[2], testdom[3], -- false, false, NULL, NULL, 0); -+ false, false, NULL, NULL, 0, NULL); - fail_unless(subdomain != NULL, "Failed to create new subdomin."); - ret = sysdb_subdomain_store(test_ctx->sysdb, - testdom[0], testdom[1], testdom[2], testdom[3], - false, false, NULL, 0, NULL); - fail_if(ret != EOK, "Could not set up the test (test subdom)"); - -- ret = sysdb_update_subdomains(test_ctx->domain); -+ ret = sysdb_update_subdomains(test_ctx->domain, NULL); - fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]", - ret, strerror(ret)); - -@@ -5900,14 +5900,14 @@ START_TEST(test_sysdb_subdomain_user_ops) - - subdomain = new_subdomain(test_ctx, test_ctx->domain, - testdom[0], testdom[1], testdom[2], testdom[3], -- false, false, NULL, NULL, 0); -+ false, false, NULL, NULL, 0, NULL); - fail_unless(subdomain != NULL, "Failed to create new subdomin."); - ret = sysdb_subdomain_store(test_ctx->sysdb, - testdom[0], testdom[1], testdom[2], testdom[3], - false, false, NULL, 0, NULL); - fail_if(ret != EOK, "Could not set up the test (test subdom)"); - -- ret = sysdb_update_subdomains(test_ctx->domain); -+ ret = sysdb_update_subdomains(test_ctx->domain, NULL); - fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]", - ret, strerror(ret)); - -@@ -5973,14 +5973,14 @@ START_TEST(test_sysdb_subdomain_group_ops) - - subdomain = new_subdomain(test_ctx, test_ctx->domain, - testdom[0], testdom[1], testdom[2], testdom[3], -- false, false, NULL, NULL, 0); -+ false, false, NULL, NULL, 0, NULL); - fail_unless(subdomain != NULL, "Failed to create new subdomin."); - ret = sysdb_subdomain_store(test_ctx->sysdb, - testdom[0], testdom[1], testdom[2], testdom[3], - false, false, NULL, 0, NULL); - fail_if(ret != EOK, "Could not set up the test (test subdom)"); - -- ret = sysdb_update_subdomains(test_ctx->domain); -+ ret = sysdb_update_subdomains(test_ctx->domain, NULL); - fail_unless(ret == EOK, "sysdb_update_subdomains failed with [%d][%s]", - ret, strerror(ret)); - -diff --git a/src/tools/common/sss_tools.c b/src/tools/common/sss_tools.c -index 0f4f46894130daf722641f25a4cdfaae220252cc..97a3caab3bec88c5727eea2f08b200f1d3b23f0c 100644 ---- a/src/tools/common/sss_tools.c -+++ b/src/tools/common/sss_tools.c -@@ -154,7 +154,7 @@ static errno_t sss_tool_domains_init(TALLOC_CTX *mem_ctx, - } - - /* Update list of subdomains for this domain */ -- ret = sysdb_update_subdomains(dom); -+ ret = sysdb_update_subdomains(dom, confdb); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to update subdomains for domain %s.\n", -diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c -index 59e49a8aa92e3a08ec80e0597304f1a4af0a02be..8a40b38c07f7e76cde5b98e5916816581fea7973 100644 ---- a/src/tools/sss_cache.c -+++ b/src/tools/sss_cache.c -@@ -158,7 +158,7 @@ int main(int argc, const char *argv[]) - dinfo = get_next_domain(dinfo, SSS_GND_DESCEND)) { - if (!IS_SUBDOMAIN(dinfo)) { - /* Update list of subdomains for this domain */ -- ret = sysdb_update_subdomains(dinfo); -+ ret = sysdb_update_subdomains(dinfo, tctx->confdb); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to update subdomains for domain %s.\n", dinfo->name); --- -2.12.2 - diff --git a/0045-CACHE_REQ-Descend-into-subdomains-on-lookups.patch b/0045-CACHE_REQ-Descend-into-subdomains-on-lookups.patch deleted file mode 100644 index 6e4158d..0000000 --- a/0045-CACHE_REQ-Descend-into-subdomains-on-lookups.patch +++ /dev/null @@ -1,172 +0,0 @@ -From dcc52d9c6411528bab815351d1e6145d211a4765 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Wed, 1 Mar 2017 08:34:57 +0000 -Subject: [PATCH 45/97] CACHE_REQ: Descend into subdomains on lookups -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Let's make all plugins, but the "host_by_name", to descend into the -subdomains on lookups. - -This patch basically prepares the field for the coming up patches that -will allow group/user resolution in all domains (or a subset of the -domains) to be possible by only using the short names without the domain -component. - -The "host_by_name" plugin was not changed as it's a specific IPA plugin -and won't find anything on its subdomains. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Pavel Březina -Reviewed-by: Sumit Bose ---- - src/responder/common/cache_req/plugins/cache_req_enum_svc.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_group_by_filter.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_group_by_name.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_object_by_name.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_svc_by_name.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_svc_by_port.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_user_by_filter.c | 2 +- - src/responder/common/cache_req/plugins/cache_req_user_by_name.c | 2 +- - 10 files changed, 10 insertions(+), 10 deletions(-) - -diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_svc.c b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c -index 2c4917cde750c9063d898c16d3a58ca8c179bc70..28dea33c601f500b9c7af0de3eb9e1c342f03522 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_enum_svc.c -+++ b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c -@@ -68,7 +68,7 @@ const struct cache_req_plugin cache_req_enum_svc = { - .allow_missing_fqn = true, - .allow_switch_to_upn = false, - .upn_equivalent = CACHE_REQ_SENTINEL, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = NULL, -diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c -index 88e1137a3976308aaf404b684c6d88cc43708bca..6ce6ae0d63967ac50b813a47ac938251619948da 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c -+++ b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c -@@ -123,7 +123,7 @@ const struct cache_req_plugin cache_req_group_by_filter = { - .allow_missing_fqn = false, - .allow_switch_to_upn = false, - .upn_equivalent = CACHE_REQ_SENTINEL, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_group_by_filter_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_name.c b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c -index be1eb9bd8552156d777e934b0be397b0e66df7cc..af6f23ccfd68f952027462ba3e74ed7219d04651 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_group_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c -@@ -186,7 +186,7 @@ const struct cache_req_plugin cache_req_group_by_name = { - .allow_missing_fqn = false, - .allow_switch_to_upn = false, - .upn_equivalent = CACHE_REQ_SENTINEL, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_group_by_name_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c -index 10fb67cbf6e78cfae33bc7208585cb80ea6a9bc4..307b65a24282838b99c472b50a71f06865aed3f0 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c -@@ -201,7 +201,7 @@ const struct cache_req_plugin cache_req_initgroups_by_name = { - .allow_missing_fqn = false, - .allow_switch_to_upn = true, - .upn_equivalent = CACHE_REQ_INITGROUPS_BY_UPN, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_initgroups_by_name_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c -index bc6fc9a8f476f97cc4bc5004bc19ba35258a2b6d..e49d6d84a41ce8dabf18c87373826f8e7b684bda 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c -@@ -120,7 +120,7 @@ const struct cache_req_plugin cache_req_netgroup_by_name = { - .allow_missing_fqn = true, - .allow_switch_to_upn = false, - .upn_equivalent = CACHE_REQ_SENTINEL, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_netgroup_by_name_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c -index 2b2caeea172b23b1b1b226def5d926e26c5c0090..74d2b3dea287e890b38e4d5bb176ad2dc6337b7e 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c -@@ -196,7 +196,7 @@ const struct cache_req_plugin cache_req_object_by_name = { - .allow_missing_fqn = false, - .allow_switch_to_upn = true, - .upn_equivalent = CACHE_REQ_USER_BY_UPN, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = cache_req_object_by_name_well_known, - .prepare_domain_data_fn = cache_req_object_by_name_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c -index cbb186df04c7ca7c02dceb98bd5700c984285a4d..ef13f097a8ae78ec9db5b7f6e14924b511578b34 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c -@@ -144,7 +144,7 @@ const struct cache_req_plugin cache_req_svc_by_name = { - .allow_missing_fqn = false, - .allow_switch_to_upn = false, - .upn_equivalent = CACHE_REQ_SENTINEL, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_svc_by_name_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c -index 1da23d4505a1dad3b2425a996134f8298c03518a..afa2eeeda12794de26e798aee4b88900bc87ed93 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c -+++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c -@@ -117,7 +117,7 @@ const struct cache_req_plugin cache_req_svc_by_port = { - .allow_missing_fqn = false, - .allow_switch_to_upn = false, - .upn_equivalent = CACHE_REQ_SENTINEL, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_svc_by_port_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c -index ee7e69399e318b9835f1623bddc635bf09aa7a1c..eb71b42dad3a805298df0c8425409d571befb31b 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c -+++ b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c -@@ -123,7 +123,7 @@ const struct cache_req_plugin cache_req_user_by_filter = { - .allow_missing_fqn = false, - .allow_switch_to_upn = false, - .upn_equivalent = CACHE_REQ_SENTINEL, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_user_by_filter_prepare_domain_data, -diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_name.c b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c -index 4289f5fd4c79f0e512f0249abe4422589fa800a0..0670febdce2d51e0373045570dd07f56255db7bc 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_user_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c -@@ -191,7 +191,7 @@ const struct cache_req_plugin cache_req_user_by_name = { - .allow_missing_fqn = false, - .allow_switch_to_upn = true, - .upn_equivalent = CACHE_REQ_USER_BY_UPN, -- .get_next_domain_flags = 0, -+ .get_next_domain_flags = SSS_GND_DESCEND, - - .is_well_known_fn = NULL, - .prepare_domain_data_fn = cache_req_user_by_name_prepare_domain_data, --- -2.12.2 - diff --git a/0046-NSS-TESTS-Fix-subdomains-attribution.patch b/0046-NSS-TESTS-Fix-subdomains-attribution.patch deleted file mode 100644 index 13397b1..0000000 --- a/0046-NSS-TESTS-Fix-subdomains-attribution.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 46c99a59c8d6501aa3ad701c567fba577924b48b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 1 Mar 2017 13:21:19 +0000 -Subject: [PATCH 46/97] NSS/TESTS: Fix subdomains attribution -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Reviewed-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/tests/cmocka/test_nss_srv.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index 3d7e0382197401cb2264671712152fe0709296b6..cbe0dccdc1d883eae1a9621f12997ef43d05178e 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -3219,7 +3219,7 @@ static int nss_subdom_test_setup(void **state) - nss_test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - -- nss_test_ctx->subdom = subdomain; -+ nss_test_ctx->subdom = nss_test_ctx->tctx->dom->subdomains; - return 0; - } - --- -2.12.2 - diff --git a/0047-NSS-TESTS-Improve-setup-teardown-for-subdomains-test.patch b/0047-NSS-TESTS-Improve-setup-teardown-for-subdomains-test.patch deleted file mode 100644 index 829b40f..0000000 --- a/0047-NSS-TESTS-Improve-setup-teardown-for-subdomains-test.patch +++ /dev/null @@ -1,274 +0,0 @@ -From a3442e4a268ad2172c89d58e6daa759eb4b39e7c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Wed, 1 Mar 2017 20:46:10 +0000 -Subject: [PATCH 47/97] NSS/TESTS: Improve setup/teardown for subdomains tests -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch basically makes the getgrnam_members_subdom(), -getgrnam_mix_dom(), getgrnam_mix_dom_fqdn() and getgrnam_mix_subdom() -more independent of each other. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/tests/cmocka/test_nss_srv.c | 182 +++++++++++++++++++++++++++++++++------- - 1 file changed, 150 insertions(+), 32 deletions(-) - -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index cbe0dccdc1d883eae1a9621f12997ef43d05178e..b468204fb1729618830513322f0d901c4c801e94 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -418,6 +418,26 @@ static errno_t store_user(struct nss_test_ctx *ctx, - return ret; - } - -+static errno_t delete_user(struct nss_test_ctx *ctx, -+ struct sss_domain_info *dom, -+ struct passwd *user) -+{ -+ errno_t ret; -+ char *fqname; -+ -+ fqname = sss_create_internal_fqname(ctx, -+ user->pw_name, -+ dom->name); -+ if (fqname == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = sysdb_delete_user(dom, fqname, user->pw_uid); -+ -+ talloc_free(fqname); -+ return ret; -+} -+ - static errno_t set_user_attr(struct nss_test_ctx *ctx, - struct sss_domain_info *dom, - struct passwd *user, -@@ -491,6 +511,27 @@ static errno_t store_group(struct nss_test_ctx *ctx, - return ret; - } - -+static errno_t delete_group(struct nss_test_ctx *ctx, -+ struct sss_domain_info *dom, -+ struct group *group) -+{ -+ errno_t ret; -+ char *fqname; -+ -+ fqname = sss_create_internal_fqname(ctx, -+ group->gr_name, -+ dom->name); -+ -+ if (fqname == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = sysdb_delete_group(dom, fqname, group->gr_gid); -+ -+ talloc_free(fqname); -+ return ret; -+} -+ - static void assert_groups_equal(struct group *expected, - struct group *gr, const int nmem) - { -@@ -540,6 +581,42 @@ static errno_t store_group_member(struct nss_test_ctx *ctx, - return ret; - } - -+static errno_t remove_group_member(struct nss_test_ctx *ctx, -+ const char *shortname_group, -+ struct sss_domain_info *group_dom, -+ const char *shortname_member, -+ struct sss_domain_info *member_dom, -+ enum sysdb_member_type type) -+{ -+ errno_t ret; -+ char *group_fqname = NULL; -+ char *member_fqname = NULL; -+ -+ group_fqname = sss_create_internal_fqname(ctx, -+ shortname_group, -+ group_dom->name); -+ if (group_fqname == NULL) { -+ return ENOMEM; -+ } -+ -+ member_fqname = sss_create_internal_fqname(ctx, -+ shortname_member, -+ member_dom->name); -+ if (member_fqname == NULL) { -+ talloc_free(group_fqname); -+ return ENOMEM; -+ } -+ -+ ret = sysdb_remove_group_member(group_dom, -+ group_fqname, -+ member_fqname, -+ type, -+ false); -+ -+ talloc_free(group_fqname); -+ talloc_free(member_fqname); -+ return ret; -+} - - /* ====================== The tests =============================== */ - struct passwd getpwnam_usr = { -@@ -1599,34 +1676,6 @@ void test_nss_getgrnam_members_subdom(void **state) - { - errno_t ret; - -- ret = store_group(nss_test_ctx, nss_test_ctx->subdom, -- &testsubdomgroup, 0); -- assert_int_equal(ret, EOK); -- -- ret = store_user(nss_test_ctx, nss_test_ctx->subdom, -- &submember1, NULL, 0); -- assert_int_equal(ret, EOK); -- -- ret = store_user(nss_test_ctx, nss_test_ctx->subdom, -- &submember2, NULL, 0); -- assert_int_equal(ret, EOK); -- -- ret = store_group_member(nss_test_ctx, -- testsubdomgroup.gr_name, -- nss_test_ctx->subdom, -- submember1.pw_name, -- nss_test_ctx->subdom, -- SYSDB_MEMBER_USER); -- assert_int_equal(ret, EOK); -- -- ret = store_group_member(nss_test_ctx, -- testsubdomgroup.gr_name, -- nss_test_ctx->subdom, -- submember2.pw_name, -- nss_test_ctx->subdom, -- SYSDB_MEMBER_USER); -- assert_int_equal(ret, EOK); -- - mock_input_user_or_group("testsubdomgroup@"TEST_SUBDOM_NAME); - will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); - will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -@@ -1757,6 +1806,14 @@ void test_nss_getgrnam_mix_dom_fqdn(void **state) - { - errno_t ret; - -+ ret = store_group_member(nss_test_ctx, -+ testgroup_members.gr_name, -+ nss_test_ctx->tctx->dom, -+ submember1.pw_name, -+ nss_test_ctx->subdom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ - nss_test_ctx->tctx->dom->fqnames = true; - - mock_input_user_or_group("testgroup_members@"TEST_DOM_NAME); -@@ -3220,6 +3277,35 @@ static int nss_subdom_test_setup(void **state) - assert_int_equal(ret, EOK); - - nss_test_ctx->subdom = nss_test_ctx->tctx->dom->subdomains; -+ -+ ret = store_group(nss_test_ctx, nss_test_ctx->subdom, -+ &testsubdomgroup, 0); -+ assert_int_equal(ret, EOK); -+ -+ ret = store_user(nss_test_ctx, nss_test_ctx->subdom, -+ &submember1, NULL, 0); -+ assert_int_equal(ret, EOK); -+ -+ ret = store_user(nss_test_ctx, nss_test_ctx->subdom, -+ &submember2, NULL, 0); -+ assert_int_equal(ret, EOK); -+ -+ ret = store_group_member(nss_test_ctx, -+ testsubdomgroup.gr_name, -+ nss_test_ctx->subdom, -+ submember1.pw_name, -+ nss_test_ctx->subdom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ -+ ret = store_group_member(nss_test_ctx, -+ testsubdomgroup.gr_name, -+ nss_test_ctx->subdom, -+ submember2.pw_name, -+ nss_test_ctx->subdom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ - return 0; - } - -@@ -3241,6 +3327,38 @@ static int nss_test_teardown(void **state) - return 0; - } - -+static int nss_subdom_test_teardown(void **state) -+{ -+ errno_t ret; -+ -+ ret = remove_group_member(nss_test_ctx, -+ testsubdomgroup.gr_name, -+ nss_test_ctx->subdom, -+ submember2.pw_name, -+ nss_test_ctx->subdom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ -+ ret = remove_group_member(nss_test_ctx, -+ testsubdomgroup.gr_name, -+ nss_test_ctx->subdom, -+ submember1.pw_name, -+ nss_test_ctx->subdom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ -+ ret = delete_user(nss_test_ctx, nss_test_ctx->subdom, &submember2); -+ assert_int_equal(ret, EOK); -+ -+ ret = delete_user(nss_test_ctx, nss_test_ctx->subdom, &submember1); -+ assert_int_equal(ret, EOK); -+ -+ ret = delete_group(nss_test_ctx, nss_test_ctx->subdom, &testsubdomgroup); -+ assert_int_equal(ret, EOK); -+ -+ return nss_test_teardown(state); -+} -+ - struct passwd testbysid = { - .pw_name = discard_const("testsiduser"), - .pw_uid = 12345, -@@ -3904,16 +4022,16 @@ int main(int argc, const char *argv[]) - nss_fqdn_test_setup, nss_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_members_subdom, - nss_subdom_test_setup, -- nss_test_teardown), -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom, - nss_subdom_test_setup, -- nss_test_teardown), -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn, - nss_subdom_test_setup, -- nss_test_teardown), -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom, - nss_subdom_test_setup, -- nss_test_teardown), -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_space, - nss_test_setup, nss_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_space_sub, --- -2.12.2 - diff --git a/0048-NSS-TESTS-Include-searches-for-non-fqnames-members-o.patch b/0048-NSS-TESTS-Include-searches-for-non-fqnames-members-o.patch deleted file mode 100644 index 532c88d..0000000 --- a/0048-NSS-TESTS-Include-searches-for-non-fqnames-members-o.patch +++ /dev/null @@ -1,355 +0,0 @@ -From 5856a621ac5909ca96520ac5a809eb83fd46d8bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Wed, 1 Mar 2017 08:33:06 +0000 -Subject: [PATCH 48/97] NSS/TESTS: Include searches for non-fqnames members of - a subdomain -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Let's extend the NSS tests in order to also test looking up users, from -a subdomain, by their short names (non fully qualified names). - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/tests/cmocka/test_nss_srv.c | 246 ++++++++++++++++++++++++++++++++++------ - 1 file changed, 211 insertions(+), 35 deletions(-) - -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index b468204fb1729618830513322f0d901c4c801e94..ede72b341b60842ad470df2794aa90ea9797e999 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -1648,16 +1648,29 @@ static int test_nss_getgrnam_members_check_subdom(uint32_t status, - tmp_ctx = talloc_new(nss_test_ctx); - assert_non_null(tmp_ctx); - -- exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, submember1.pw_name); -- assert_non_null(exp_members[0]); -- exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, submember2.pw_name); -- assert_non_null(exp_members[1]); -+ if (nss_test_ctx->subdom->fqnames) { -+ exp_members[0] = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ submember1.pw_name); -+ assert_non_null(exp_members[0]); - -- expected.gr_name = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, testsubdomgroup.gr_name); -- assert_non_null(expected.gr_name); -+ exp_members[1] = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ submember2.pw_name); -+ assert_non_null(exp_members[1]); -+ -+ expected.gr_name = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ testsubdomgroup.gr_name); -+ assert_non_null(expected.gr_name); -+ } else { -+ exp_members[0] = submember1.pw_name; -+ exp_members[1] = submember2.pw_name; -+ expected.gr_name = testsubdomgroup.gr_name; -+ } - - assert_int_equal(status, EOK); - -@@ -1692,6 +1705,29 @@ void test_nss_getgrnam_members_subdom(void **state) - assert_int_equal(ret, EOK); - } - -+void test_nss_getgrnam_members_subdom_nonfqnames(void **state) -+{ -+ errno_t ret; -+ -+ nss_test_ctx->subdom->fqnames = false; -+ -+ mock_input_user_or_group("testsubdomgroup"); -+ mock_account_recv_simple(); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); -+ will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ /* Query for that group, call a callback when command finishes */ -+ set_cmd_cb(test_nss_getgrnam_members_check_subdom); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ -+ assert_int_equal(ret, EOK); -+} -+ - static int test_nss_getgrnam_check_mix_dom(uint32_t status, - uint8_t *body, size_t blen) - { -@@ -1710,9 +1746,15 @@ static int test_nss_getgrnam_check_mix_dom(uint32_t status, - tmp_ctx = talloc_new(nss_test_ctx); - assert_non_null(tmp_ctx); - -- exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, submember1.pw_name); -- assert_non_null(exp_members[0]); -+ if (nss_test_ctx->subdom->fqnames) { -+ exp_members[0] = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ submember1.pw_name); -+ assert_non_null(exp_members[0]); -+ } else { -+ exp_members[0] = submember1.pw_name; -+ } - exp_members[1] = testmember1.pw_name; - exp_members[2] = testmember2.pw_name; - -@@ -1756,6 +1798,35 @@ void test_nss_getgrnam_mix_dom(void **state) - assert_int_equal(ret, EOK); - } - -+void test_nss_getgrnam_mix_dom_nonfqnames(void **state) -+{ -+ errno_t ret; -+ -+ nss_test_ctx->subdom->fqnames = false; -+ -+ ret = store_group_member(nss_test_ctx, -+ testgroup_members.gr_name, -+ nss_test_ctx->tctx->dom, -+ submember1.pw_name, -+ nss_test_ctx->subdom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ -+ mock_input_user_or_group("testgroup_members"); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); -+ will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ /* Query for that group, call a callback when command finishes */ -+ set_cmd_cb(test_nss_getgrnam_check_mix_dom); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ - static int test_nss_getgrnam_check_mix_dom_fqdn(uint32_t status, - uint8_t *body, size_t blen) - { -@@ -1773,21 +1844,33 @@ static int test_nss_getgrnam_check_mix_dom_fqdn(uint32_t status, - tmp_ctx = talloc_new(nss_test_ctx); - assert_non_null(tmp_ctx); - -- exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, submember1.pw_name); -- assert_non_null(exp_members[0]); -- exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, -- nss_test_ctx->tctx->dom, testmember1.pw_name); -- assert_non_null(exp_members[1]); -- exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, -- nss_test_ctx->tctx->dom, testmember2.pw_name); -- assert_non_null(exp_members[2]); -+ if (nss_test_ctx->subdom->fqnames) { -+ exp_members[0] = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ submember1.pw_name); -+ assert_non_null(exp_members[0]); -+ } else { -+ exp_members[0] = submember1.pw_name; -+ } -+ if (nss_test_ctx->tctx->dom->fqnames) { -+ exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, -+ nss_test_ctx->tctx->dom, testmember1.pw_name); -+ assert_non_null(exp_members[1]); -+ exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, -+ nss_test_ctx->tctx->dom, testmember2.pw_name); -+ assert_non_null(exp_members[2]); - -- expected.gr_name = sss_tc_fqname(tmp_ctx, -- nss_test_ctx->tctx->dom->names, -- nss_test_ctx->tctx->dom, -- testgroup_members.gr_name); -- assert_non_null(expected.gr_name); -+ expected.gr_name = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->tctx->dom->names, -+ nss_test_ctx->tctx->dom, -+ testgroup_members.gr_name); -+ assert_non_null(expected.gr_name); -+ } else { -+ exp_members[1] = testmember1.pw_name; -+ exp_members[2] = testmember2.pw_name; -+ expected.gr_name = testgroup_members.gr_name; -+ } - - assert_int_equal(status, EOK); - -@@ -1834,6 +1917,40 @@ void test_nss_getgrnam_mix_dom_fqdn(void **state) - assert_int_equal(ret, EOK); - } - -+void test_nss_getgrnam_mix_dom_fqdn_nonfqnames(void **state) -+{ -+ errno_t ret; -+ -+ ret = store_group_member(nss_test_ctx, -+ testgroup_members.gr_name, -+ nss_test_ctx->tctx->dom, -+ submember1.pw_name, -+ nss_test_ctx->subdom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ -+ nss_test_ctx->tctx->dom->fqnames = false; -+ nss_test_ctx->subdom->fqnames = false; -+ -+ -+ mock_input_user_or_group("testgroup_members"); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); -+ will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ /* Query for that group, call a callback when command finishes */ -+ set_cmd_cb(test_nss_getgrnam_check_mix_dom_fqdn); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ -+ /* Restore FQDN settings */ -+ nss_test_ctx->tctx->dom->fqnames = false; -+ assert_int_equal(ret, EOK); -+} -+ - static int test_nss_getgrnam_check_mix_subdom(uint32_t status, - uint8_t *body, size_t blen) - { -@@ -1851,20 +1968,37 @@ static int test_nss_getgrnam_check_mix_subdom(uint32_t status, - tmp_ctx = talloc_new(nss_test_ctx); - assert_non_null(tmp_ctx); - -- exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, submember1.pw_name); -- assert_non_null(exp_members[0]); -- exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, submember2.pw_name); -- assert_non_null(exp_members[1]); -+ if (nss_test_ctx->subdom->fqnames) { -+ exp_members[0] = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ submember1.pw_name); -+ assert_non_null(exp_members[0]); -+ -+ exp_members[1] = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ submember2.pw_name); -+ assert_non_null(exp_members[1]); -+ } else { -+ exp_members[0] = submember1.pw_name; -+ exp_members[1] = submember2.pw_name; -+ } -+ - /* Important: this member is from a non-qualified domain, so his name will - * not be qualified either - */ - exp_members[2] = testmember1.pw_name; - -- expected.gr_name = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, -- nss_test_ctx->subdom, testsubdomgroup.gr_name); -- assert_non_null(expected.gr_name); -+ if (nss_test_ctx->subdom->fqnames) { -+ expected.gr_name = sss_tc_fqname(tmp_ctx, -+ nss_test_ctx->subdom->names, -+ nss_test_ctx->subdom, -+ testsubdomgroup.gr_name); -+ assert_non_null(expected.gr_name); -+ } else { -+ expected.gr_name = testsubdomgroup.gr_name; -+ } - - assert_int_equal(status, EOK); - -@@ -1906,6 +2040,36 @@ void test_nss_getgrnam_mix_subdom(void **state) - assert_int_equal(ret, EOK); - } - -+void test_nss_getgrnam_mix_subdom_nonfqnames(void **state) -+{ -+ errno_t ret; -+ -+ nss_test_ctx->subdom->fqnames = false; -+ -+ ret = store_group_member(nss_test_ctx, -+ testsubdomgroup.gr_name, -+ nss_test_ctx->subdom, -+ testmember1.pw_name, -+ nss_test_ctx->tctx->dom, -+ SYSDB_MEMBER_USER); -+ assert_int_equal(ret, EOK); -+ -+ mock_input_user_or_group("testsubdomgroup"); -+ mock_account_recv_simple(); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); -+ will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ /* Query for that group, call a callback when command finishes */ -+ set_cmd_cb(test_nss_getgrnam_check_mix_subdom); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ - struct group space_group = { - .gr_gid = 2123, - .gr_name = discard_const("space group"), -@@ -4023,15 +4187,27 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(test_nss_getgrnam_members_subdom, - nss_subdom_test_setup, - nss_subdom_test_teardown), -+ cmocka_unit_test_setup_teardown(test_nss_getgrnam_members_subdom_nonfqnames, -+ nss_subdom_test_setup, -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom, - nss_subdom_test_setup, - nss_subdom_test_teardown), -+ cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_nonfqnames, -+ nss_subdom_test_setup, -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn, - nss_subdom_test_setup, - nss_subdom_test_teardown), -+ cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn_nonfqnames, -+ nss_subdom_test_setup, -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom, - nss_subdom_test_setup, - nss_subdom_test_teardown), -+ cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom_nonfqnames, -+ nss_subdom_test_setup, -+ nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_space, - nss_test_setup, nss_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_space_sub, --- -2.12.2 - diff --git a/0049-SYSDB-Add-methods-to-deal-with-the-domain-s-resoluti.patch b/0049-SYSDB-Add-methods-to-deal-with-the-domain-s-resoluti.patch deleted file mode 100644 index 63b0c0e..0000000 --- a/0049-SYSDB-Add-methods-to-deal-with-the-domain-s-resoluti.patch +++ /dev/null @@ -1,289 +0,0 @@ -From 2e85b015d8dd231094a09eab69b86e8b6fcc8b2b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Fri, 24 Mar 2017 15:29:23 +0100 -Subject: [PATCH 49/97] SYSDB: Add methods to deal with the domain's resolution - order -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In the following-up patches those newly introduced methods will be used -to deal with the domainResolutionOrder attribute. - -The sysdb_update_domain_resolution_order() method is purposely not -checking whether a value has changed or not before writing to sysdb and -while may not be optimal, the readability of the code has increased a -lot by keeping it as simple as possible. - -Tests for these new methods are part of the next commit. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - Makefile.am | 2 + - src/db/sysdb.h | 2 + - src/db/sysdb_domain_resolution_order.c | 169 +++++++++++++++++++++++++++++++++ - src/db/sysdb_domain_resolution_order.h | 37 ++++++++ - 4 files changed, 210 insertions(+) - create mode 100644 src/db/sysdb_domain_resolution_order.c - create mode 100644 src/db/sysdb_domain_resolution_order.h - -diff --git a/Makefile.am b/Makefile.am -index 359feddef298b0013c726409b7ba8b86504abf09..8052150be32d89813764e9bc436dfcb211a738d6 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -736,6 +736,7 @@ dist_noinst_HEADERS = \ - src/db/sysdb_private.h \ - src/db/sysdb_services.h \ - src/db/sysdb_ssh.h \ -+ src/db/sysdb_domain_resolution_order.h \ - src/confdb/confdb.h \ - src/confdb/confdb_private.h \ - src/confdb/confdb_setup.h \ -@@ -995,6 +996,7 @@ libsss_util_la_SOURCES = \ - src/db/sysdb_idmap.c \ - src/db/sysdb_gpo.c \ - src/db/sysdb_certmap.c \ -+ src/db/sysdb_domain_resolution_order.c \ - src/monitor/monitor_sbus.c \ - src/providers/dp_auth_util.c \ - src/providers/dp_pam_data_util.c \ -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 6762b51bee02911fb97d5d393fad2495504ee5ad..42d2857ed7765c17e7d84b0da93ed07758fbe012 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -184,6 +184,8 @@ - #define SYSDB_OVERRIDE_GROUP_CLASS "groupOverride" - #define SYSDB_OVERRIDE_DN "overrideDN" - #define SYSDB_OVERRIDE_OBJECT_DN "overrideObjectDN" -+#define SYSDB_USE_DOMAIN_RESOLUTION_ORDER "useDomainResolutionOrder" -+#define SYSDB_DOMAIN_RESOLUTION_ORDER "domainResolutionOrder" - - #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)" - -diff --git a/src/db/sysdb_domain_resolution_order.c b/src/db/sysdb_domain_resolution_order.c -new file mode 100644 -index 0000000000000000000000000000000000000000..63774461a1e9f3dc863220d418e29e06d6e6e6df ---- /dev/null -+++ b/src/db/sysdb_domain_resolution_order.c -@@ -0,0 +1,169 @@ -+/* -+ Authors: -+ Fabiano Fidêncio -+ -+ Copyright (C) 2017 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 -+ -+#include "db/sysdb.h" -+#include "db/sysdb_private.h" -+ -+static errno_t -+sysdb_get_domain_resolution_order_string_attr(TALLOC_CTX *mem_ctx, -+ struct sysdb_ctx *sysdb, -+ struct ldb_dn *dn, -+ const char *const *attrs, -+ const char **_attr) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_result *res; -+ const char *attr; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, -+ NULL); -+ if (ret != LDB_SUCCESS) { -+ ret = EIO; -+ goto done; -+ } -+ -+ if (res->count > 1) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Base search returned [%d] results, expected 1.\n", res->count); -+ ret = EINVAL; -+ goto done; -+ } else if (res->count == 0) { -+ ret = ENOENT; -+ goto done; -+ } else { -+ /* res->count == 1 */ -+ attr = ldb_msg_find_attr_as_string(res->msgs[0], attrs[0], NULL); -+ if (attr == NULL) { -+ ret = ENOENT; -+ goto done; -+ } -+ } -+ -+ *_attr = talloc_steal(mem_ctx, attr); -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+errno_t -+sysdb_get_domain_resolution_order(TALLOC_CTX *mem_ctx, -+ struct sysdb_ctx *sysdb, -+ struct ldb_dn *dn, -+ const char **_domain_resolution_order) -+{ -+ TALLOC_CTX *tmp_ctx; -+ const char *domain_resolution_order = NULL; -+ const char *attrs[] = { SYSDB_DOMAIN_RESOLUTION_ORDER, NULL }; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = sysdb_get_domain_resolution_order_string_attr( -+ tmp_ctx, sysdb, dn, attrs, &domain_resolution_order); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_get_domain_resolution_order_string_attr() failed " -+ "[%d]: [%s]", -+ ret, sss_strerror(ret)); -+ goto done; -+ } else if (ret == ENOENT) { -+ *_domain_resolution_order = NULL; -+ goto done; -+ } else { -+ /* ret == EOK */ -+ *_domain_resolution_order = talloc_steal(mem_ctx, -+ domain_resolution_order); -+ } -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+errno_t -+sysdb_update_domain_resolution_order(struct sysdb_ctx *sysdb, -+ struct ldb_dn *dn, -+ const char *domain_resolution_order) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_message *msg; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ msg = ldb_msg_new(tmp_ctx); -+ if (msg == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ msg->dn = dn; -+ -+ ret = ldb_msg_add_empty(msg, SYSDB_DOMAIN_RESOLUTION_ORDER, -+ LDB_FLAG_MOD_REPLACE, NULL); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ if (domain_resolution_order != NULL) { -+ ret = ldb_msg_add_string(msg, SYSDB_DOMAIN_RESOLUTION_ORDER, -+ domain_resolution_order); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ } -+ -+ ret = ldb_modify(sysdb->ldb, msg); -+ if (ret != LDB_SUCCESS) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "ldb_modify()_failed: [%s][%d][%s]\n", -+ ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)); -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -diff --git a/src/db/sysdb_domain_resolution_order.h b/src/db/sysdb_domain_resolution_order.h -new file mode 100644 -index 0000000000000000000000000000000000000000..45d2ea63f6bc14cd3184994530846ee6f762d4d0 ---- /dev/null -+++ b/src/db/sysdb_domain_resolution_order.h -@@ -0,0 +1,37 @@ -+/* -+ Authors: -+ Fabiano Fidêncio -+ -+ Copyright (C) 2017 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 . -+*/ -+ -+#ifndef _SYSDB_DOMAIN_RESOLUTION_ORDER_H_ -+#define _SYSDB_DOMAIN_RESOLUTION_ORDER_H_ -+ -+#include "db/sysdb.h" -+ -+errno_t -+sysdb_get_domain_resolution_order(TALLOC_CTX *mem_ctx, -+ struct sysdb_ctx *sysdb, -+ struct ldb_dn *dn, -+ const char **_domain_resolution_order); -+ -+errno_t -+sysdb_update_domain_resolution_order(struct sysdb_ctx *sysdb, -+ struct ldb_dn *dn, -+ const char *domain_resolution_order); -+ -+#endif /* _SYSDB_DOMAIN_RESOLUTION_ORDER_H_ */ --- -2.12.2 - diff --git a/0050-SYSDB-TESTS-Add-tests-for-the-domain-s-resolution-or.patch b/0050-SYSDB-TESTS-Add-tests-for-the-domain-s-resolution-or.patch deleted file mode 100644 index 3be4cd4..0000000 --- a/0050-SYSDB-TESTS-Add-tests-for-the-domain-s-resolution-or.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 723d514f641e2b5a5cbfe1c6c7bdd2a6f3c5070e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Fri, 24 Mar 2017 23:15:04 +0100 -Subject: [PATCH 50/97] SYSDB/TESTS: Add tests for the domain's resolution - order methods -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Introduce a new and small set of tests for these new helper methods that -are going to be used in different parts of the code in the follow-up -patches. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - Makefile.am | 16 ++ - .../cmocka/test_sysdb_domain_resolution_order.c | 190 +++++++++++++++++++++ - 2 files changed, 206 insertions(+) - create mode 100644 src/tests/cmocka/test_sysdb_domain_resolution_order.c - -diff --git a/Makefile.am b/Makefile.am -index 8052150be32d89813764e9bc436dfcb211a738d6..450785bf4c482cce1e1440f1336879150537888e 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -263,6 +263,7 @@ if HAVE_CMOCKA - test_sysdb_certmap \ - test_sysdb_sudo \ - test_sysdb_utils \ -+ test_sysdb_domain_resolution_order \ - test_wbc_calls \ - test_be_ptask \ - test_copy_ccache \ -@@ -2875,6 +2876,21 @@ test_sysdb_utils_LDADD = \ - libsss_test_common.la \ - $(NULL) - -+test_sysdb_domain_resolution_order_SOURCES = \ -+ src/tests/cmocka/test_sysdb_domain_resolution_order.c \ -+ $(NULL) -+test_sysdb_domain_resolution_order_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(NULL) -+test_sysdb_domain_resolution_order_LDADD = \ -+ $(CMOCKA_LIBS) \ -+ $(LDB_LIBS) \ -+ $(POPT_LIBS) \ -+ $(TALLOC_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_test_common.la \ -+ $(NULL) -+ - test_wbc_calls_SOURCES = \ - src/tests/cmocka/test_wbc_calls.c \ - src/sss_client/idmap/sss_nss_idmap.c \ -diff --git a/src/tests/cmocka/test_sysdb_domain_resolution_order.c b/src/tests/cmocka/test_sysdb_domain_resolution_order.c -new file mode 100644 -index 0000000000000000000000000000000000000000..59a85ce431be9ac27c1e8e6b5e4e5f8300af549e ---- /dev/null -+++ b/src/tests/cmocka/test_sysdb_domain_resolution_order.c -@@ -0,0 +1,190 @@ -+/* -+ SSSD -+ -+ sysdb_domain_resolution_order - Tests for domain resolution order calls -+ -+ Authors: -+ Fabiano Fidêncio -+ -+ Copyright (C) 2017 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 -+#include -+#include -+#include -+#include -+ -+#include "tests/cmocka/common_mock.h" -+#include "tests/common.h" -+#include "db/sysdb_domain_resolution_order.h" -+#include "db/sysdb_private.h" /* for sysdb->ldb member */ -+ -+#define TESTS_PATH "tp_" BASE_FILE_STEM -+#define TEST_CONF_DB "test_sysdb_domain_resolution_order.ldb" -+ -+#define TEST_DOM_NAME "test_sysdb_domain_resolution_order" -+ -+#define TEST_ID_PROVIDER "ldap" -+ -+struct domain_resolution_order_test_ctx { -+ struct sss_test_ctx *tctx; -+}; -+ -+static int test_sysdb_domain_resolution_order_setup(void **state) -+{ -+ struct domain_resolution_order_test_ctx *test_ctx; -+ -+ assert_true(leak_check_setup()); -+ -+ test_ctx = talloc_zero(global_talloc_context, -+ struct domain_resolution_order_test_ctx); -+ assert_non_null(test_ctx); -+ -+ test_dom_suite_setup(TESTS_PATH); -+ -+ test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, -+ TEST_CONF_DB, TEST_DOM_NAME, -+ TEST_ID_PROVIDER, NULL); -+ assert_non_null(test_ctx->tctx); -+ -+ *state = test_ctx; -+ return 0; -+} -+ -+static int test_sysdb_domain_resolution_order_teardown(void **state) -+{ -+ struct domain_resolution_order_test_ctx *test_ctx = -+ talloc_get_type(*state, struct domain_resolution_order_test_ctx); -+ -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); -+ talloc_free(test_ctx); -+ assert_true(leak_check_teardown()); -+ return 0; -+} -+ -+static void test_sysdb_domain_resolution_order_ops(void **state) -+{ -+ errno_t ret; -+ struct domain_resolution_order_test_ctx *test_ctx = -+ talloc_get_type(*state, struct domain_resolution_order_test_ctx); -+ const char *domains_in = NULL; -+ const char *domains_out = NULL; -+ struct ldb_dn *dn; -+ -+ dn = ldb_dn_new_fmt(test_ctx, test_ctx->tctx->dom->sysdb->ldb, -+ SYSDB_DOM_BASE, test_ctx->tctx->dom->name); -+ -+ /* Adding domainResolutionOrder for the first time */ -+ domains_in = "foo:bar:foobar"; -+ ret = sysdb_update_domain_resolution_order(test_ctx->tctx->dom->sysdb, -+ dn, domains_in); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_domain_resolution_order(test_ctx, -+ test_ctx->tctx->dom->sysdb, dn, -+ &domains_out); -+ assert_int_equal(ret, EOK); -+ assert_true(strcmp(domains_in, domains_out) == 0); -+ -+ /* Setting the domainResolutionOrder to ":" ... -+ * -+ * It means, the domainResolutionOrder is set, but if there's another -+ * domainResolutionOrder with lower precedence those must be ignored. -+ */ -+ domains_in = ":"; -+ ret = sysdb_update_domain_resolution_order(test_ctx->tctx->dom->sysdb, -+ dn, domains_in); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_domain_resolution_order(test_ctx, -+ test_ctx->tctx->dom->sysdb, dn, -+ &domains_out); -+ assert_int_equal(ret, EOK); -+ assert_true(strcmp(domains_in, domains_out) == 0); -+ -+ /* Changing the domainResolutionOrder */ -+ domains_in = "bar:foobar:foo"; -+ ret = sysdb_update_domain_resolution_order(test_ctx->tctx->dom->sysdb, -+ dn, domains_in); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_domain_resolution_order(test_ctx, -+ test_ctx->tctx->dom->sysdb, dn, -+ &domains_out); -+ assert_int_equal(ret, EOK); -+ assert_true(strcmp(domains_out, domains_out) == 0); -+ -+ /* Removing the domainResolutionOrder attribute */ -+ domains_in = NULL; -+ ret = sysdb_update_domain_resolution_order(test_ctx->tctx->dom->sysdb, -+ dn, domains_in); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_get_domain_resolution_order(test_ctx, -+ test_ctx->tctx->dom->sysdb, dn, -+ &domains_out); -+ assert_int_equal(ret, ENOENT); -+ assert_true(domains_out == NULL); -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ int rv; -+ int no_cleanup = 0; -+ poptContext pc; -+ int opt; -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ SSSD_DEBUG_OPTS -+ {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0, -+ _("Do not delete the test database after a test run"), NULL }, -+ POPT_TABLEEND -+ }; -+ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown(test_sysdb_domain_resolution_order_ops, -+ test_sysdb_domain_resolution_order_setup, -+ test_sysdb_domain_resolution_order_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); -+ -+ tests_set_cwd(); -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, LOCAL_SYSDB_FILE); -+ test_dom_suite_setup(TESTS_PATH); -+ rv = cmocka_run_group_tests(tests, NULL, NULL); -+ -+ if (rv == 0 && no_cleanup == 0) { -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, LOCAL_SYSDB_FILE); -+ } -+ return rv; -+} --- -2.12.2 - diff --git a/0051-IPA-Get-ipaDomainsResolutionOrder-from-ipaConfig.patch b/0051-IPA-Get-ipaDomainsResolutionOrder-from-ipaConfig.patch deleted file mode 100644 index dfa194e..0000000 --- a/0051-IPA-Get-ipaDomainsResolutionOrder-from-ipaConfig.patch +++ /dev/null @@ -1,369 +0,0 @@ -From 3cbf0e7b63e8e6888917e9215bbdc5674c2fa852 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Wed, 22 Mar 2017 13:40:20 +0100 -Subject: [PATCH 51/97] IPA: Get ipaDomainsResolutionOrder from ipaConfig -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -ipaDomainsResolutionOrder provides a list of domains that have to be -looked up firstly during cache_req searches. - -This commit only fetches this list from the server and stores its value -at sysdb so we can make use of it later on this patch series. - -There are no tests for newly introduced sysdb methods are those are -basically only calling sysdb_update_domain_resolution_order(), -sysdb_get_domain_resolution_order() and -sysdb_get_use_domain_resolution_order() which are have tests written -for. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/db/sysdb.h | 11 +++ - src/db/sysdb_subdomains.c | 67 +++++++++++++++ - src/providers/ipa/ipa_subdomains.c | 168 ++++++++++++++++++++++++++++++++++--- - 3 files changed, 234 insertions(+), 12 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 42d2857ed7765c17e7d84b0da93ed07758fbe012..75a07d4d2effb028ec654342113f8478e1eba10e 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -489,6 +489,17 @@ int sysdb_transaction_cancel(struct sysdb_ctx *sysdb); - /* functions related to subdomains */ - errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name); - -+errno_t sysdb_domain_get_domain_resolution_order( -+ TALLOC_CTX *mem_ctx, -+ struct sysdb_ctx *sysdb, -+ const char *domain_name, -+ const char **_domain_resolution_order); -+ -+errno_t sysdb_domain_update_domain_resolution_order( -+ struct sysdb_ctx *sysdb, -+ const char *domain_name, -+ const char *domain_resolution_order); -+ - errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, - const char *name, const char *realm, - const char *flat_name, const char *domain_id, -diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c -index 916dbba153d8c08837425f6fd29a20f5a6aa9fc9..e2a4f7bb1fcdf20b6b7e04efc7f396d1c3d08f0f 100644 ---- a/src/db/sysdb_subdomains.c -+++ b/src/db/sysdb_subdomains.c -@@ -22,6 +22,7 @@ - - #include "util/util.h" - #include "db/sysdb_private.h" -+#include "db/sysdb_domain_resolution_order.h" - - static errno_t - check_subdom_config_file(struct confdb_ctx *confdb, -@@ -1210,3 +1211,69 @@ done: - talloc_free(tmp_ctx); - return ret; - } -+ -+errno_t -+sysdb_domain_get_domain_resolution_order(TALLOC_CTX *mem_ctx, -+ struct sysdb_ctx *sysdb, -+ const char *domain_name, -+ const char **_domain_resolution_order) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_dn *dn; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, domain_name); -+ if (dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_get_domain_resolution_order(mem_ctx, sysdb, dn, -+ _domain_resolution_order); -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+errno_t -+sysdb_domain_update_domain_resolution_order(struct sysdb_ctx *sysdb, -+ const char *domain_name, -+ const char *domain_resolution_order) -+{ -+ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_dn *dn; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, domain_name); -+ if (dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_update_domain_resolution_order(sysdb, dn, -+ domain_resolution_order); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_update_domain_resolution_order() failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index a07b88fe2f499353293ba90345552413c9792f4b..01a0ce812d861b24565d2f71f27d6b8ceb2965bc 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -29,6 +29,7 @@ - #include "providers/ipa/ipa_common.h" - #include "providers/ipa/ipa_id.h" - #include "providers/ipa/ipa_opts.h" -+#include "providers/ipa/ipa_config.h" - - #include - -@@ -51,6 +52,8 @@ - - #define IPA_ASSIGNED_ID_VIEW "ipaAssignedIDView" - -+#define IPA_DOMAIN_RESOLUTION_ORDER "ipaDomainResolutionOrder" -+ - /* do not refresh more often than every 5 seconds for now */ - #define IPA_SUBDOMAIN_REFRESH_LIMIT 5 - -@@ -1681,6 +1684,117 @@ static errno_t ipa_subdomains_view_name_recv(struct tevent_req *req) - return EOK; - } - -+struct ipa_domain_resolution_order_state { -+ struct sss_domain_info *domain; -+}; -+ -+static void ipa_domain_resolution_order_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+ipa_domain_resolution_order_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ipa_subdomains_ctx *sd_ctx, -+ struct sdap_handle *sh) -+{ -+ struct ipa_domain_resolution_order_state *state; -+ struct tevent_req *subreq; -+ struct tevent_req *req; -+ const char *attrs[] = {IPA_DOMAIN_RESOLUTION_ORDER, NULL}; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct ipa_domain_resolution_order_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); -+ return NULL; -+ } -+ -+ state->domain = sd_ctx->be_ctx->domain; -+ -+ subreq = ipa_get_config_send(state, ev, sh, sd_ctx->sdap_id_ctx->opts, -+ state->domain->name, attrs); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ tevent_req_set_callback(subreq, ipa_domain_resolution_order_done, req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void ipa_domain_resolution_order_done(struct tevent_req *subreq) -+{ -+ struct ipa_domain_resolution_order_state *state; -+ struct tevent_req *req; -+ struct sysdb_attrs *config = NULL; -+ const char *domain_resolution_order = NULL; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct ipa_domain_resolution_order_state); -+ -+ ret = ipa_get_config_recv(subreq, state, &config); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get the domains' resolution order configuration " -+ "from the server [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ if (config != NULL) { -+ ret = sysdb_attrs_get_string(config, IPA_DOMAIN_RESOLUTION_ORDER, -+ &domain_resolution_order); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get the domains' resolution order configuration " -+ "value [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } else if (ret == ENOENT) { -+ domain_resolution_order = NULL; -+ } -+ } -+ -+ ret = sysdb_domain_update_domain_resolution_order( -+ state->domain->sysdb, state->domain->name, -+ domain_resolution_order); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_domain_update_resolution_order() [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t ipa_domain_resolution_order_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} - - struct ipa_subdomains_refresh_state { - struct tevent_context *ev; -@@ -1695,6 +1809,7 @@ static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq); -+static void ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq); - - static struct tevent_req * - ipa_subdomains_refresh_send(TALLOC_CTX *mem_ctx, -@@ -1916,7 +2031,6 @@ static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq) - { - struct ipa_subdomains_refresh_state *state; - struct tevent_req *req; -- int dp_error; - errno_t ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); -@@ -1924,24 +2038,55 @@ static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq) - - ret = ipa_subdomains_view_name_recv(subreq); - talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Unable to get view name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = ipa_domain_resolution_order_send(state, state->ev, state->sd_ctx, -+ sdap_id_op_handle(state->sdap_op)); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ tevent_req_set_callback(subreq, -+ ipa_domain_refresh_resolution_order_done, -+ req); -+} -+ -+static void -+ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq) -+{ -+ struct ipa_subdomains_refresh_state *state; -+ struct tevent_req *req; -+ int dp_error; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct ipa_subdomains_refresh_state); -+ -+ ret = ipa_domain_resolution_order_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Unable to get the domains order resolution [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ - ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ - ret = ipa_subdomains_refresh_retry(req); -- if (ret != EOK) { -- goto done; -- } -- return; - } else if (dp_error == DP_ERR_OFFLINE) { - ret = ERR_OFFLINE; -- goto done; -- } else if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get view name " -- "[%d]: %s\n", ret, sss_strerror(ret)); -- goto done; - } - --done: - if (ret != EOK) { - DEBUG(SSSDBG_TRACE_FUNC, "Unable to refresh subdomains [%d]: %s\n", - ret, sss_strerror(ret)); -@@ -1949,7 +2094,6 @@ done: - return; - } - -- DEBUG(SSSDBG_TRACE_FUNC, "Subdomains refreshed.\n"); - tevent_req_done(req); - } - --- -2.12.2 - diff --git a/0052-IPA_SUBDOMAINS-Rename-_refresh_view-to-_refresh_view.patch b/0052-IPA_SUBDOMAINS-Rename-_refresh_view-to-_refresh_view.patch deleted file mode 100644 index b232fd9..0000000 --- a/0052-IPA_SUBDOMAINS-Rename-_refresh_view-to-_refresh_view.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 17ab121a6c69d74acf1d40f2bbcbe90d77bb6b8a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Fri, 24 Mar 2017 08:08:58 +0100 -Subject: [PATCH 52/97] IPA_SUBDOMAINS: Rename _refresh_view() to - _refresh_view_name() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This method got renamed in order to match better with what it does -currently. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/providers/ipa/ipa_subdomains.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 01a0ce812d861b24565d2f71f27d6b8ceb2965bc..bf6f6ab1fa8bfff7ea102dd219c9ddbbab065b2b 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -1808,7 +1808,7 @@ static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq); --static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq); -+static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq); - static void ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq); - - static struct tevent_req * -@@ -2023,11 +2023,12 @@ static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq) - return; - } - -- tevent_req_set_callback(subreq, ipa_subdomains_refresh_view_done, req); -+ tevent_req_set_callback(subreq, ipa_subdomains_refresh_view_name_done, -+ req); - return; - } - --static void ipa_subdomains_refresh_view_done(struct tevent_req *subreq) -+static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq) - { - struct ipa_subdomains_refresh_state *state; - struct tevent_req *req; --- -2.12.2 - diff --git a/0053-IPA-Get-ipaDomainsResolutionOrder-from-IPA-ID-View.patch b/0053-IPA-Get-ipaDomainsResolutionOrder-from-IPA-ID-View.patch deleted file mode 100644 index 3fe5e82..0000000 --- a/0053-IPA-Get-ipaDomainsResolutionOrder-from-IPA-ID-View.patch +++ /dev/null @@ -1,347 +0,0 @@ -From fb81f337b68c85471c3f5140850dccf549a2d0ac Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Fri, 24 Mar 2017 17:46:04 +0100 -Subject: [PATCH 53/97] IPA: Get ipaDomainsResolutionOrder from IPA ID View -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -ipaDomainsResolutionOrder provides a list of domains that have to be -looked up firstly during cache_req searches. - -This commit only fetches this list from the server and stores its value -at sysdb so we can make use of it later on this patch series. - -There are no tests for newly introduced sysdb methods are those are -basically only calling sysdb_update_domain_resolution_order(), -sysdb_get_domain_resolution_order() and -sysdb_get_use_domain_resolution_order() which are have tests written -for. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/db/sysdb.h | 9 ++ - src/db/sysdb_views.c | 66 ++++++++++++++ - src/providers/ipa/ipa_subdomains.c | 182 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 257 insertions(+) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 75a07d4d2effb028ec654342113f8478e1eba10e..62c561be9452a284a8ddf8ebb45720265852c8b0 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -533,6 +533,15 @@ errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb, const char *view_name); - errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, - char **view_name); - -+errno_t sysdb_update_view_domain_resolution_order( -+ struct sysdb_ctx *sysdb, -+ const char *domain_resolution_order); -+ -+errno_t sysdb_get_view_domain_resolution_order( -+ TALLOC_CTX *mem_ctx, -+ struct sysdb_ctx *sysdb, -+ const char **_domain_resolution_order); -+ - static inline bool is_default_view(const char *view_name) - { - /* NULL is treated as default */ -diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c -index 1c416dd14049237e9f35d52f154035e3ff861469..20db9b06183d68b33bb19f498513d7f5cf84b1cf 100644 ---- a/src/db/sysdb_views.c -+++ b/src/db/sysdb_views.c -@@ -22,6 +22,9 @@ - #include "util/util.h" - #include "util/cert.h" - #include "db/sysdb_private.h" -+#include "db/sysdb_domain_resolution_order.h" -+ -+#define SYSDB_VIEWS_BASE "cn=views,cn=sysdb" - - /* In general is should not be possible that there is a view container without - * a view name set. But to be on the safe side we return both information -@@ -179,6 +182,69 @@ done: - return ret; - } - -+errno_t -+sysdb_get_view_domain_resolution_order(TALLOC_CTX *mem_ctx, -+ struct sysdb_ctx *sysdb, -+ const char **_domain_resolution_order) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_dn *dn; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_VIEWS_BASE); -+ if (dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_get_domain_resolution_order(mem_ctx, sysdb, dn, -+ _domain_resolution_order); -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+errno_t -+sysdb_update_view_domain_resolution_order(struct sysdb_ctx *sysdb, -+ const char *domain_resolution_order) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_dn *dn; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_VIEWS_BASE); -+ if (dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_update_domain_resolution_order(sysdb, dn, -+ domain_resolution_order); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_update_domain_resolution_order() failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ - errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name) - { - struct ldb_dn *dn; -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index bf6f6ab1fa8bfff7ea102dd219c9ddbbab065b2b..ef348adf4a36e870f44387bd700f5c2beea3bfd6 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -1684,6 +1684,151 @@ static errno_t ipa_subdomains_view_name_recv(struct tevent_req *req) - return EOK; - } - -+struct ipa_subdomains_view_domain_resolution_order_state { -+ struct sss_domain_info *domain; -+ const char *view_name; -+}; -+ -+static void -+ipa_subdomains_view_domain_resolution_order_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+ipa_subdomains_view_domain_resolution_order_send( -+ TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ipa_subdomains_ctx *sd_ctx, -+ struct sdap_handle *sh) -+{ -+ struct ipa_subdomains_view_domain_resolution_order_state *state; -+ struct tevent_req *subreq; -+ struct tevent_req *req; -+ const char *attrs[] = { IPA_DOMAIN_RESOLUTION_ORDER, NULL }; -+ char *ldap_basedn; -+ char *base; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct ipa_subdomains_view_domain_resolution_order_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); -+ return NULL; -+ } -+ -+ state->domain = sd_ctx->be_ctx->domain; -+ state->view_name = sd_ctx->ipa_id_ctx->view_name; -+ -+ ret = domain_to_basedn(state, sd_ctx->be_ctx->domain->name, &ldap_basedn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n"); -+ goto immediately; -+ } -+ -+ base = talloc_asprintf(state, "cn=%s,cn=views,cn=accounts,%s", -+ sd_ctx->ipa_id_ctx->view_name, ldap_basedn); -+ if (base == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ subreq = sdap_get_generic_send( -+ state, ev, sd_ctx->sdap_id_ctx->opts, sh, -+ base, LDAP_SCOPE_BASE, NULL, attrs, NULL, 0, -+ dp_opt_get_int(sd_ctx->sdap_id_ctx->opts->basic, -+ SDAP_ENUM_SEARCH_TIMEOUT), -+ false); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ tevent_req_set_callback(subreq, ipa_subdomains_view_domain_resolution_order_done, -+ req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void -+ipa_subdomains_view_domain_resolution_order_done(struct tevent_req *subreq) -+{ -+ struct ipa_subdomains_view_domain_resolution_order_state *state; -+ struct tevent_req *req; -+ size_t reply_count; -+ struct sysdb_attrs **reply; -+ const char *domain_resolution_order; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, -+ struct ipa_subdomains_view_domain_resolution_order_state); -+ -+ ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unable to get view name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ if (reply_count > 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "More than one object returned.\n"); -+ ret = EINVAL; -+ goto done; -+ } else if (reply_count == 0) { -+ domain_resolution_order = NULL; -+ } else { -+ /* reply_count == 1 */ -+ ret = sysdb_attrs_get_string(reply[0], IPA_DOMAIN_RESOLUTION_ORDER, -+ &domain_resolution_order); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to get the view domains' resolution order " -+ "configuration value for view [%s] [%d]: %s\n", -+ state->view_name, ret, sss_strerror(ret)); -+ goto done; -+ } else if (ret == ENOENT) { -+ domain_resolution_order = NULL; -+ } -+ } -+ -+ ret = sysdb_update_view_domain_resolution_order(state->domain->sysdb, -+ domain_resolution_order); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_update_view_domain_resolution_order() [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t -+ipa_subdomains_view_domain_resolution_order_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -+ - struct ipa_domain_resolution_order_state { - struct sss_domain_info *domain; - }; -@@ -1809,6 +1954,8 @@ static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq); - static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq); -+static void ipa_subdomains_refresh_view_domain_resolution_order_done( -+ struct tevent_req *subreq); - static void ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq); - - static struct tevent_req * -@@ -2047,6 +2194,41 @@ static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq) - return; - } - -+ subreq = ipa_subdomains_view_domain_resolution_order_send( -+ state, -+ state->ev, -+ state->sd_ctx, -+ sdap_id_op_handle(state->sdap_op)); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ tevent_req_set_callback(subreq, -+ ipa_subdomains_refresh_view_domain_resolution_order_done, -+ req); -+} -+ -+static void -+ipa_subdomains_refresh_view_domain_resolution_order_done(struct tevent_req *subreq) -+{ -+ struct ipa_subdomains_refresh_state *state; -+ struct tevent_req *req; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct ipa_subdomains_refresh_state); -+ -+ ret = ipa_subdomains_view_domain_resolution_order_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Unable to get view domain_resolution order [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ - subreq = ipa_domain_resolution_order_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); - if (subreq == NULL) { --- -2.12.2 - diff --git a/0054-DLINKLIST-Add-DLIST_FOR_EACH_SAFE-macro.patch b/0054-DLINKLIST-Add-DLIST_FOR_EACH_SAFE-macro.patch deleted file mode 100644 index a276895..0000000 --- a/0054-DLINKLIST-Add-DLIST_FOR_EACH_SAFE-macro.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 34228050af1e25706f61ec9df648852284b61c2b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Tue, 21 Mar 2017 20:56:38 +0100 -Subject: [PATCH 54/97] DLINKLIST: Add DLIST_FOR_EACH_SAFE macro -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This macro, as DLIST_FOR_EACH, iterates over the whole list. The main -difference between both is that in the _SAFE version the pointer to the -next list node is stored, allowing us to delete the current node safely. - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/util/dlinklist.h | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/util/dlinklist.h b/src/util/dlinklist.h -index 4f6aef830e914c22654970081263d43461c1750f..017c60468e66dbec15724d5f4832da412f42136b 100644 ---- a/src/util/dlinklist.h -+++ b/src/util/dlinklist.h -@@ -147,4 +147,9 @@ do { \ - #define DLIST_FOR_EACH(p, list) \ - for ((p) = (list); (p) != NULL; (p) = (p)->next) - -+#define DLIST_FOR_EACH_SAFE(p, q, list) \ -+ for ((p) = (list), (q) = (p) != NULL ? (p)->next : NULL; \ -+ (p) != NULL; \ -+ (p) = (q), (q) = (p) != NULL ? (p)->next : NULL) -+ - #endif /* _DLINKLIST_H */ --- -2.12.2 - diff --git a/0055-CACHE_REQ-Make-use-of-domainResolutionOrder.patch b/0055-CACHE_REQ-Make-use-of-domainResolutionOrder.patch deleted file mode 100644 index c6132d8..0000000 --- a/0055-CACHE_REQ-Make-use-of-domainResolutionOrder.patch +++ /dev/null @@ -1,795 +0,0 @@ -From 66c8e92eb5a4985bb7f64c349a53b08030a000cf Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Sun, 26 Mar 2017 00:27:50 +0100 -Subject: [PATCH 55/97] CACHE_REQ: Make use of domainResolutionOrder -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -domainResolutionOrder has been introduced in the previous commits and -allows the admin to set up a specific order which the domains will be -resolved during a lookup and with this patch we can take advantage of -this. - -In order to have it working a new structure has been added -(struct domain_resolution_order) to the responder context and will be -used by the cache_req to perform the lookups based on this list. - -As the ipaDomainResolutionOrder may be set globally on IPA or per View, -SSSD does respect the following precedence order: View > Globally. - -The way the list is built is quite simple, basically having the domains -present on ipaDomainResolutionOrder as the first domains (in that -specific order) and then appending the remaining domains to this list. -The final result is a completely flat list with all the domains -respecting the specified order (it's important to remember that the -domains not specified won't follow any specific order, they're just -"random" based on the domains list present in the responder context. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - Makefile.am | 3 + - src/responder/common/cache_req/cache_req.c | 89 +++++++----- - src/responder/common/cache_req/cache_req_domain.c | 166 ++++++++++++++++++++++ - src/responder/common/cache_req/cache_req_domain.h | 46 ++++++ - src/responder/common/responder.h | 5 + - src/responder/common/responder_common.c | 153 ++++++++++++++++++++ - src/responder/common/responder_get_domains.c | 14 ++ - src/tests/cmocka/common_mock_resp.c | 6 + - src/tests/cmocka/common_mock_resp_dp.c | 7 + - src/tests/cmocka/test_nss_srv.c | 4 + - src/tests/cwrap/Makefile.am | 1 + - 11 files changed, 457 insertions(+), 37 deletions(-) - create mode 100644 src/responder/common/cache_req/cache_req_domain.c - create mode 100644 src/responder/common/cache_req/cache_req_domain.h - -diff --git a/Makefile.am b/Makefile.am -index 450785bf4c482cce1e1440f1336879150537888e..573b37c52fdeab1add4ea057e1e1844ea4d348a5 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -528,6 +528,7 @@ SSSD_CACHE_REQ_OBJ = \ - src/responder/common/cache_req/cache_req_result.c \ - src/responder/common/cache_req/cache_req_search.c \ - src/responder/common/cache_req/cache_req_data.c \ -+ src/responder/common/cache_req/cache_req_domain.c \ - src/responder/common/cache_req/plugins/cache_req_common.c \ - src/responder/common/cache_req/plugins/cache_req_enum_users.c \ - src/responder/common/cache_req/plugins/cache_req_enum_groups.c \ -@@ -689,6 +690,7 @@ dist_noinst_HEADERS = \ - src/responder/common/iface/responder_iface.h \ - src/responder/common/iface/responder_iface_generated.h \ - src/responder/common/cache_req/cache_req.h \ -+ src/responder/common/cache_req/cache_req_domain.h \ - src/responder/common/cache_req/cache_req_plugin.h \ - src/responder/common/cache_req/cache_req_private.h \ - src/responder/common/data_provider/rdp.h \ -@@ -2199,6 +2201,7 @@ responder_socket_access_tests_SOURCES = \ - src/responder/common/responder_common.c \ - src/responder/common/responder_packet.c \ - src/responder/common/responder_cmd.c \ -+ src/responder/common/cache_req/cache_req_domain.c \ - src/responder/common/data_provider/rdp_message.c \ - src/responder/common/data_provider/rdp_client.c \ - $(SSSD_RESPONDER_IFACE_OBJ) \ -diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c -index aca150d69b398ceb1a52e5cd6a87d35dbc87020b..483126396f8addbad744ae03bfc739801cd0c18b 100644 ---- a/src/responder/common/cache_req/cache_req.c -+++ b/src/responder/common/cache_req/cache_req.c -@@ -24,6 +24,7 @@ - #include - - #include "util/util.h" -+#include "responder/common/responder.h" - #include "responder/common/cache_req/cache_req_private.h" - #include "responder/common/cache_req/cache_req_plugin.h" - -@@ -316,7 +317,7 @@ struct cache_req_search_domains_state { - struct cache_req *cr; - - /* work data */ -- struct sss_domain_info *domain; -+ struct cache_req_domain *cr_domain; - struct sss_domain_info *selected_domain; - struct cache_req_result **results; - size_t num_results; -@@ -330,13 +331,14 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req); - - static void cache_req_search_domains_done(struct tevent_req *subreq); - --struct tevent_req *cache_req_search_domains_send(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct cache_req *cr, -- struct sss_domain_info *domain, -- bool check_next, -- bool bypass_cache, -- bool bypass_dp) -+struct tevent_req * -+cache_req_search_domains_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct cache_req *cr, -+ struct cache_req_domain *cr_domain, -+ bool check_next, -+ bool bypass_cache, -+ bool bypass_dp) - { - struct tevent_req *req; - struct cache_req_search_domains_state *state = NULL; -@@ -352,7 +354,7 @@ struct tevent_req *cache_req_search_domains_send(TALLOC_CTX *mem_ctx, - state->ev = ev; - state->cr = cr; - -- state->domain = domain; -+ state->cr_domain = cr_domain; - state->check_next = check_next; - state->dp_success = true; - state->bypass_cache = bypass_cache; -@@ -378,6 +380,7 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req) - struct cache_req_search_domains_state *state; - struct tevent_req *subreq; - struct cache_req *cr; -+ struct sss_domain_info *domain; - uint32_t next_domain_flag; - bool is_domain_valid; - bool allow_no_fqn; -@@ -389,11 +392,21 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req) - next_domain_flag = cr->plugin->get_next_domain_flags; - allow_no_fqn = cr->plugin->allow_missing_fqn; - -- while (state->domain != NULL) { -+ while (state->cr_domain != NULL) { -+ domain = state->cr_domain->domain; -+ /* As the cr_domain list is a flatten version of the domains -+ * list, we have to ensure to only go through the subdomains in -+ * case it's specified in the plugin to do so. -+ */ -+ if (next_domain_flag == 0 && IS_SUBDOMAIN(domain)) { -+ state->cr_domain = state->cr_domain->next; -+ continue; -+ } -+ - /* Check if this domain is valid for this request. */ -- is_domain_valid = cache_req_validate_domain(cr, state->domain); -+ is_domain_valid = cache_req_validate_domain(cr, domain); - if (!is_domain_valid) { -- state->domain = get_next_domain(state->domain, next_domain_flag); -+ state->cr_domain = state->cr_domain->next; - continue; - } - -@@ -401,18 +414,18 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req) - * qualified names on domain less search. We do not descend into - * subdomains here since those are implicitly qualified. - */ -- if (state->check_next && !allow_no_fqn && state->domain->fqnames) { -- state->domain = get_next_domain(state->domain, 0); -+ if (state->check_next && !allow_no_fqn && domain->fqnames) { -+ state->cr_domain = state->cr_domain->next; - continue; - } - -- state->selected_domain = state->domain; -+ state->selected_domain = domain; - -- if (state->domain == NULL) { -+ if (domain == NULL) { - break; - } - -- ret = cache_req_set_domain(cr, state->domain); -+ ret = cache_req_set_domain(cr, domain); - if (ret != EOK) { - return ret; - } -@@ -427,8 +440,7 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req) - - /* we will continue with the following domain the next time */ - if (state->check_next) { -- state->domain = get_next_domain(state->domain, -- cr->plugin->get_next_domain_flags); -+ state->cr_domain = state->cr_domain->next; - } - - return EAGAIN; -@@ -625,11 +637,12 @@ static void cache_req_input_parsed(struct tevent_req *subreq); - static errno_t cache_req_select_domains(struct tevent_req *req, - const char *domain_name); - --static errno_t cache_req_search_domains(struct tevent_req *req, -- struct sss_domain_info *domain, -- bool check_next, -- bool bypass_cache, -- bool bypass_dp); -+static errno_t -+cache_req_search_domains(struct tevent_req *req, -+ struct cache_req_domain *oredered_domain, -+ bool check_next, -+ bool bypass_cache, -+ bool bypass_dp); - - static void cache_req_done(struct tevent_req *subreq); - -@@ -778,7 +791,7 @@ static errno_t cache_req_select_domains(struct tevent_req *req, - const char *domain_name) - { - struct cache_req_state *state = NULL; -- struct sss_domain_info *domain; -+ struct cache_req_domain *cr_domain; - bool check_next; - bool bypass_cache; - bool bypass_dp; -@@ -798,29 +811,30 @@ static errno_t cache_req_select_domains(struct tevent_req *req, - CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, - "Performing a single domain search\n"); - -- domain = responder_get_domain(state->cr->rctx, domain_name); -- if (domain == NULL) { -+ cr_domain = cache_req_domain_get_domain_by_name( -+ state->cr->rctx->cr_domains, domain_name); -+ if (cr_domain == NULL) { - return ERR_DOMAIN_NOT_FOUND; - } -- - check_next = false; - } else { - CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, - "Performing a multi-domain search\n"); - -- domain = state->cr->rctx->domains; -+ cr_domain = state->cr->rctx->cr_domains; - check_next = true; - } - -- return cache_req_search_domains(req, domain, check_next, -+ return cache_req_search_domains(req, cr_domain, check_next, - bypass_cache, bypass_dp); - } - --static errno_t cache_req_search_domains(struct tevent_req *req, -- struct sss_domain_info *domain, -- bool check_next, -- bool bypass_cache, -- bool bypass_dp) -+static errno_t -+cache_req_search_domains(struct tevent_req *req, -+ struct cache_req_domain *cr_domain, -+ bool check_next, -+ bool bypass_cache, -+ bool bypass_dp) - { - struct tevent_req *subreq; - struct cache_req_state *state = NULL; -@@ -832,8 +846,9 @@ static errno_t cache_req_search_domains(struct tevent_req *req, - bypass_cache ? "bypass" : "check", - bypass_dp ? "bypass" : "check"); - -- subreq = cache_req_search_domains_send(state, state->ev, state->cr, domain, -- check_next, bypass_cache, bypass_dp); -+ subreq = cache_req_search_domains_send(state, state->ev, state->cr, -+ cr_domain, check_next, -+ bypass_cache, bypass_dp); - if (subreq == NULL) { - return ENOMEM; - } -diff --git a/src/responder/common/cache_req/cache_req_domain.c b/src/responder/common/cache_req/cache_req_domain.c -new file mode 100644 -index 0000000000000000000000000000000000000000..bbabd695f1c6b6c29b7e61f571382ab9adfb0ea2 ---- /dev/null -+++ b/src/responder/common/cache_req/cache_req_domain.c -@@ -0,0 +1,166 @@ -+/* -+ Authors: -+ Fabiano Fidêncio -+ -+ Copyright (C) 2017 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 "responder/common/cache_req/cache_req_domain.h" -+ -+struct cache_req_domain * -+cache_req_domain_get_domain_by_name(struct cache_req_domain *domains, -+ const char *name) -+{ -+ struct cache_req_domain *dom; -+ struct cache_req_domain *ret = NULL; -+ -+ DLIST_FOR_EACH(dom, domains) { -+ if (sss_domain_get_state(dom->domain) == DOM_DISABLED) { -+ continue; -+ } -+ -+ if (strcasecmp(dom->domain->name, name) == 0 || -+ (dom->domain->flat_name != NULL && -+ strcasecmp(dom->domain->flat_name, name) == 0)) { -+ ret = dom; -+ break; -+ } -+ } -+ -+ if (ret == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unknown domains [%s].\n", name); -+ } -+ -+ return ret; -+} -+ -+void cache_req_domain_list_zfree(struct cache_req_domain **cr_domains) -+{ -+ struct cache_req_domain *p, *q, *r; -+ -+ DLIST_FOR_EACH_SAFE(p, q, *cr_domains) { -+ r = p; -+ DLIST_REMOVE(*cr_domains, p); -+ talloc_zfree(r); -+ } -+ -+ *cr_domains = NULL; -+} -+ -+static struct cache_req_domain * -+cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, -+ char **resolution_order) -+{ -+ struct cache_req_domain *cr_domains = NULL; -+ struct cache_req_domain *cr_domain; -+ struct sss_domain_info *dom; -+ char *name; -+ int flag = SSS_GND_ALL_DOMAINS; -+ int i; -+ errno_t ret; -+ -+ if (resolution_order != NULL) { -+ for (i = 0; resolution_order[i] != NULL; i++) { -+ name = resolution_order[i]; -+ for (dom = domains; dom; dom = get_next_domain(dom, flag)) { -+ if (strcasecmp(name, dom->name) != 0) { -+ continue; -+ } -+ -+ cr_domain = talloc_zero(mem_ctx, struct cache_req_domain); -+ if (cr_domain == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ cr_domain->domain = dom; -+ -+ DLIST_ADD_END(cr_domains, cr_domain, -+ struct cache_req_domain *); -+ break; -+ } -+ } -+ } -+ -+ for (dom = domains; dom; dom = get_next_domain(dom, flag)) { -+ if (string_in_list(dom->name, resolution_order, false)) { -+ continue; -+ } -+ -+ cr_domain = talloc_zero(mem_ctx, struct cache_req_domain); -+ if (cr_domain == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ cr_domain->domain = dom; -+ -+ DLIST_ADD_END(cr_domains, cr_domain, struct cache_req_domain *); -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ cache_req_domain_list_zfree(&cr_domains); -+ } -+ -+ return cr_domains; -+} -+ -+struct cache_req_domain * -+cache_req_domain_new_list_from_domain_resolution_order( -+ TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, -+ const char *domain_resolution_order) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct cache_req_domain *cr_domains = NULL; -+ char **list = NULL; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return NULL; -+ } -+ -+ if (domain_resolution_order != NULL) { -+ if (strcmp(domain_resolution_order, ":") != 0) { -+ ret = split_on_separator(tmp_ctx, domain_resolution_order, ':', -+ true, true, &list, NULL); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "split_on_separator() failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ } -+ } -+ -+ cr_domains = cache_req_domain_new_list_from_string_list(mem_ctx, domains, -+ list); -+ if (cr_domains == NULL) { -+ ret = ENOMEM; -+ DEBUG(SSSDBG_OP_FAILURE, -+ "cache_req_domain_new_list_from_domain_resolution_order() " -+ "failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+done: -+ talloc_free(tmp_ctx); -+ return cr_domains; -+} -diff --git a/src/responder/common/cache_req/cache_req_domain.h b/src/responder/common/cache_req/cache_req_domain.h -new file mode 100644 -index 0000000000000000000000000000000000000000..41c50e8c293d7b032cb2f05482c40e93e4f723dc ---- /dev/null -+++ b/src/responder/common/cache_req/cache_req_domain.h -@@ -0,0 +1,46 @@ -+/* -+ Authors: -+ Fabiano Fidêncio -+ -+ Copyright (C) 2017 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 . -+*/ -+ -+#ifndef _CACHE_REQ_DOMAIN_H_ -+#define _CACHE_REQ_DOMAIN_H_ -+ -+#include "responder/common/responder.h" -+ -+struct cache_req_domain { -+ struct sss_domain_info *domain; -+ -+ struct cache_req_domain *prev; -+ struct cache_req_domain *next; -+}; -+ -+struct cache_req_domain * -+cache_req_domain_get_domain_by_name(struct cache_req_domain *domains, -+ const char *name); -+ -+struct cache_req_domain * -+cache_req_domain_new_list_from_domain_resolution_order( -+ TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, -+ const char *domain_resolution_order); -+ -+void cache_req_domain_list_zfree(struct cache_req_domain **cr_domains); -+ -+ -+#endif /* _CACHE_REQ_DOMAIN_H_ */ -diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h -index 4d1048a1e0c9be2cad91317d51baf670ecb3307e..29e3f95caf484f43307c9c28d4abd3f50f360a95 100644 ---- a/src/responder/common/responder.h -+++ b/src/responder/common/responder.h -@@ -37,6 +37,7 @@ - #include "sbus/sssd_dbus.h" - #include "responder/common/negcache.h" - #include "sss_client/sss_cli.h" -+#include "responder/common/cache_req/cache_req_domain.h" - - extern hash_table_t *dp_requests; - -@@ -113,6 +114,8 @@ struct resp_ctx { - int domains_timeout; - int client_idle_timeout; - -+ struct cache_req_domain *cr_domains; -+ - time_t last_request_time; - int idle_timeout; - struct tevent_timer *idle; -@@ -387,4 +390,6 @@ char *sss_resp_create_fqname(TALLOC_CTX *mem_ctx, - bool name_is_upn, - const char *orig_name); - -+errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx); -+ - #endif /* __SSS_RESPONDER_H__ */ -diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c -index 76f43609651217e537ffa515aaf5b5caa98a2e90..1792a4c3771fa326c7cca31e1981dce315c03758 100644 ---- a/src/responder/common/responder_common.c -+++ b/src/responder/common/responder_common.c -@@ -1453,3 +1453,156 @@ fail: - return ret; - - } -+ -+/* ====== Helper functions for the domain resolution order ======= */ -+static struct cache_req_domain * -+sss_resp_new_cr_domains_from_ipa_id_view(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, -+ struct sysdb_ctx *sysdb) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct cache_req_domain *cr_domains = NULL; -+ const char *domain_resolution_order = NULL; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return NULL; -+ } -+ -+ ret = sysdb_get_view_domain_resolution_order(tmp_ctx, sysdb, -+ &domain_resolution_order); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "sysdb_get_view_cache_req_domain() failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ /* Using mem_ctx (which is rctx) directly here to avoid copying -+ * this memory around. */ -+ cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -+ mem_ctx, domains, domain_resolution_order); -+ if (cr_domains == NULL) { -+ ret = ENOMEM; -+ DEBUG(SSSDBG_DEFAULT, -+ "cache_req_domain_new_list_from_domain_resolution_order() " -+ "failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+done: -+ talloc_free(tmp_ctx); -+ return cr_domains; -+} -+ -+static struct cache_req_domain * -+sss_resp_new_cr_domains_from_ipa_config(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, -+ struct sysdb_ctx *sysdb, -+ const char *domain) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct cache_req_domain *cr_domains = NULL; -+ const char *domain_resolution_order = NULL; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return NULL; -+ } -+ -+ ret = sysdb_domain_get_domain_resolution_order(tmp_ctx, sysdb, domain, -+ &domain_resolution_order); -+ -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "sysdb_domain_get_cache_req_domain() failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ /* Using mem_ctx (which is rctx) directly here to avoid copying -+ * this memory around. */ -+ cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -+ mem_ctx, domains, domain_resolution_order); -+ if (cr_domains == NULL) { -+ DEBUG(SSSDBG_DEFAULT, -+ "cache_req_domain_new_list_from_domain_resolution_order() " -+ "failed [%d]: [%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+done: -+ talloc_free(tmp_ctx); -+ return cr_domains; -+} -+ -+errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) -+{ -+ struct cache_req_domain *cr_domains = NULL; -+ struct sss_domain_info *dom; -+ errno_t ret; -+ -+ for (dom = rctx->domains; dom != NULL; dom = dom->next) { -+ if (dom->provider != NULL && strcmp(dom->provider, "ipa") == 0) { -+ break; -+ } -+ } -+ -+ if (dom == NULL) { -+ cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -+ rctx, rctx->domains, NULL); -+ if (cr_domains == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to flatten the list of domains.\n"); -+ } -+ goto done; -+ } -+ -+ if (dom->has_views) { -+ cr_domains = sss_resp_new_cr_domains_from_ipa_id_view(rctx, -+ rctx->domains, -+ dom->sysdb); -+ if (cr_domains == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Failed to use ipaDomainResolutionOrder set for the " -+ "view \"%s\".\n" -+ "Trying to fallback to use ipaDomainOrderResolution " -+ "set in ipaConfig for the domain: %s.\n", -+ dom->view_name, dom->name); -+ } else { -+ goto done; -+ } -+ } -+ -+ cr_domains = sss_resp_new_cr_domains_from_ipa_config(rctx, rctx->domains, -+ dom->sysdb, -+ dom->name); -+ if (cr_domains == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Failed to use ipaDomainResolutionOrder set in ipaConfig " -+ "for the domain: \"%s\".\n" -+ "No ipaDomainResolutionOrder will be followed.\n", -+ dom->name); -+ } else { -+ goto done; -+ } -+ -+ cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -+ rctx, rctx->domains, NULL); -+ if (cr_domains == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to flatten the list of domains.\n"); -+ goto done; -+ } -+ -+done: -+ ret = cr_domains != NULL ? EOK : ENOMEM; -+ -+ cache_req_domain_list_zfree(&rctx->cr_domains); -+ rctx->cr_domains = cr_domains; -+ -+ return ret; -+} -diff --git a/src/responder/common/responder_get_domains.c b/src/responder/common/responder_get_domains.c -index 0f9c01214631200f9687635f6302fa5c07e8a1fe..8c90b7773e248e1dd6d846c5050e1931fc50c786 100644 ---- a/src/responder/common/responder_get_domains.c -+++ b/src/responder/common/responder_get_domains.c -@@ -192,6 +192,13 @@ struct tevent_req *sss_dp_get_domains_send(TALLOC_CTX *mem_ctx, - - if (state->dom == NULL) { - /* All domains were local */ -+ ret = sss_resp_populate_cr_domains(state->rctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "sss_resp_populate_cr_domains() failed [%d]: [%s]\n", -+ ret, sss_strerror(ret)); -+ goto immediately; -+ } - ret = EOK; - goto immediately; - } -@@ -253,6 +260,13 @@ sss_dp_get_domains_process(struct tevent_req *subreq) - if (state->dom == NULL) { - /* All domains were local */ - set_time_of_last_request(state->rctx); -+ ret = sss_resp_populate_cr_domains(state->rctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "sss_resp_populate_cr_domains() failed [%d]: [%s]\n", -+ ret, sss_strerror(ret)); -+ goto fail; -+ } - tevent_req_done(req); - return; - } -diff --git a/src/tests/cmocka/common_mock_resp.c b/src/tests/cmocka/common_mock_resp.c -index 88808b1b9394b7a9ee7e58b30b4fbd9d467493d3..175101fc51fd395d792b1fccaecdb327caef2b64 100644 ---- a/src/tests/cmocka/common_mock_resp.c -+++ b/src/tests/cmocka/common_mock_resp.c -@@ -51,6 +51,12 @@ mock_rctx(TALLOC_CTX *mem_ctx, - rctx->ev = ev; - rctx->domains = domains; - rctx->pvt_ctx = pvt_ctx; -+ if (domains != NULL) { -+ ret = sss_resp_populate_cr_domains(rctx); -+ if (ret != EOK) { -+ return NULL; -+ } -+ } - return rctx; - } - -diff --git a/src/tests/cmocka/common_mock_resp_dp.c b/src/tests/cmocka/common_mock_resp_dp.c -index 5db5255ab61231870982c4b78a39504ae8954bcd..4b38a38e6f53499132f9fe14a0ec0af157cf85ca 100644 ---- a/src/tests/cmocka/common_mock_resp_dp.c -+++ b/src/tests/cmocka/common_mock_resp_dp.c -@@ -21,6 +21,7 @@ - */ - - #include "util/util.h" -+#include "responder/common/responder.h" - #include "tests/cmocka/common_mock_resp.h" - - /* Mock DP requests that finish immediatelly and return -@@ -165,6 +166,12 @@ sss_dp_get_domains_send(TALLOC_CTX *mem_ctx, - bool force, - const char *hint) - { -+ errno_t ret; -+ ret = sss_resp_populate_cr_domains(rctx); -+ if (ret != EOK) { -+ return NULL; -+ } -+ - return test_req_succeed_send(mem_ctx, rctx->ev); - } - -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index ede72b341b60842ad470df2794aa90ea9797e999..2f526660cbbbf2443dbae4e213c1336feb6c661e 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -3440,6 +3440,10 @@ static int nss_subdom_test_setup(void **state) - nss_test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - -+ ret = sss_resp_populate_cr_domains(nss_test_ctx->rctx); -+ assert_int_equal(ret, EOK); -+ assert_non_null(nss_test_ctx->rctx->cr_domains); -+ - nss_test_ctx->subdom = nss_test_ctx->tctx->dom->subdomains; - - ret = store_group(nss_test_ctx, nss_test_ctx->subdom, -diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am -index 4a4090df9296aadde308249f533e7ba246e92f93..c99ebde5f0fc18d1283392cbb307434579d5d811 100644 ---- a/src/tests/cwrap/Makefile.am -+++ b/src/tests/cwrap/Makefile.am -@@ -41,6 +41,7 @@ SSSD_CACHE_REQ_OBJ = \ - ../../../src/responder/common/cache_req/cache_req_result.c \ - ../../../src/responder/common/cache_req/cache_req_search.c \ - ../../../src/responder/common/cache_req/cache_req_data.c \ -+ ../../../src/responder/common/cache_req/cache_req_domain.c \ - ../../../src/responder/common/cache_req/plugins/cache_req_common.c \ - ../../../src/responder/common/cache_req/plugins/cache_req_enum_users.c \ - ../../../src/responder/common/cache_req/plugins/cache_req_enum_groups.c \ --- -2.12.2 - diff --git a/0056-UTIL-Expose-replace_char-as-sss_replace_char.patch b/0056-UTIL-Expose-replace_char-as-sss_replace_char.patch deleted file mode 100644 index 0090aa1..0000000 --- a/0056-UTIL-Expose-replace_char-as-sss_replace_char.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 1e437af958f59a0b8bf2f751d3c2ea28365ac64d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Sun, 26 Mar 2017 01:49:53 +0100 -Subject: [PATCH 56/97] UTIL: Expose replace_char() as sss_replace_char() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This method is going to be used in the follow-up patch for replacing ',' -by ':' so we can keep the domain resolution order option consitent with -the way it's set on IPA side and still keep consistent with the way -lists are represented on sssd.conf file. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/util/string_utils.c | 12 ++++++------ - src/util/util.h | 5 +++++ - 2 files changed, 11 insertions(+), 6 deletions(-) - -diff --git a/src/util/string_utils.c b/src/util/string_utils.c -index 872b7e29e55e8628085affd07f3363019aae5ee9..1215ec96a57089a13f455812adf5a0b0812afa6d 100644 ---- a/src/util/string_utils.c -+++ b/src/util/string_utils.c -@@ -22,10 +22,10 @@ - - #include "util/util.h" - --static char *replace_char(TALLOC_CTX *mem_ctx, -- const char *in, -- const char match, -- const char sub) -+char *sss_replace_char(TALLOC_CTX *mem_ctx, -+ const char *in, -+ const char match, -+ const char sub) - { - char *p; - char *out; -@@ -63,7 +63,7 @@ char * sss_replace_space(TALLOC_CTX *mem_ctx, - return talloc_strdup(mem_ctx, orig_name); - } - -- return replace_char(mem_ctx, orig_name, ' ', subst); -+ return sss_replace_char(mem_ctx, orig_name, ' ', subst); - } - - char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx, -@@ -81,7 +81,7 @@ char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx, - return talloc_strdup(mem_ctx, orig_name); - } - -- return replace_char(mem_ctx, orig_name, subst, ' '); -+ return sss_replace_char(mem_ctx, orig_name, subst, ' '); - } - - errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf, -diff --git a/src/util/util.h b/src/util/util.h -index 82760940269ad8883e725e3a5cf463486c9cfd36..2170c5fb7cffda3910d2b58e33ec7abe3ec4a7d4 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -600,6 +600,11 @@ errno_t name_to_well_known_sid(const char *dom, const char *name, - const char **sid); - - /* from string_utils.c */ -+char *sss_replace_char(TALLOC_CTX *mem_ctx, -+ const char *in, -+ const char match, -+ const char sub); -+ - char * sss_replace_space(TALLOC_CTX *mem_ctx, - const char *orig_name, - const char replace_char); --- -2.12.2 - diff --git a/0057-Add-domain_resolution_order-config-option.patch b/0057-Add-domain_resolution_order-config-option.patch deleted file mode 100644 index 2929afd..0000000 --- a/0057-Add-domain_resolution_order-config-option.patch +++ /dev/null @@ -1,205 +0,0 @@ -From 16385568547351b5d2c562f3081f35f3341f695b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Sun, 26 Mar 2017 03:00:14 +0200 -Subject: [PATCH 57/97] Add domain_resolution_order config option -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is the local equivalent of option of ipaDomainResolutionOrder and -has precedence over the ones set on IPA side making the precedence order -to be like: Local > View > Globally. - -As done for the IPA side configurations, the domains which were not -explicitly set up will be apennded to the final of the -domain_resolution_order list in the very same order they're presented in -the "domains" option of [sssd] section in the config file. There's no -guarantee of order for the subdomains though. - -It's also important to mention that no expansion magic is performed on -our side. It means that if 'example.com' is set it does *not* stand for -all its subdomains DNS wise (like 'foo.example.com', 'bar.example.com', -etc). - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/confdb/confdb.h | 1 + - src/config/SSSDConfig/__init__.py.in | 1 + - src/config/SSSDConfigTest.py | 7 ++++++- - src/config/cfg_rules.ini | 1 + - src/config/etc/sssd.api.conf | 1 + - src/man/sssd.conf.5.xml | 20 ++++++++++++++++++++ - src/responder/common/responder.h | 1 + - src/responder/common/responder_common.c | 27 +++++++++++++++++++++++++++ - 8 files changed, 58 insertions(+), 1 deletion(-) - -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index fb60675ca8beb2c2a157bf021ed9cad362742988..56a603652d6c8256735e7f8b125300ff7b254645 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -74,6 +74,7 @@ - #define CONFDB_MONITOR_CERT_VERIFICATION "certificate_verification" - #define CONFDB_MONITOR_DISABLE_NETLINK "disable_netlink" - #define CONFDB_MONITOR_ENABLE_FILES_DOM "enable_files_domain" -+#define CONFDB_MONITOR_DOMAIN_RESOLUTION_ORDER "domain_resolution_order" - - /* Both monitor and domains */ - #define CONFDB_NAME_REGEX "re_expression" -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 29e9b4fae6835db4ccb9937fd93457d462e4a15d..0edc3ea84a1e8fb0f797546b4c223e22e22f70e9 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -66,6 +66,7 @@ option_strings = { - 'override_space': _('All spaces in group or user names will be replaced with this character'), - 'disable_netlink' : _('Tune sssd to honor or ignore netlink state changes'), - 'enable_files_domain' : _('Enable or disable the implicit files domain'), -+ 'domain_resolution_order': _('A specific order of the domains to be looked up'), - - # [nss] - 'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'), -diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py -index 457a6f0a09e7139a05f29f8bef7e475fe3b58ec2..6899bf8ae04bf210546c8cbdba8235f094e23dc0 100755 ---- a/src/config/SSSDConfigTest.py -+++ b/src/config/SSSDConfigTest.py -@@ -94,6 +94,10 @@ class SSSDConfigTestValid(unittest.TestCase): - self.assertTrue('default_domain_suffix' in new_options) - self.assertEquals(new_options['default_domain_suffix'][0], str) - -+ self.assertTrue('domain_resolution_order' in new_options) -+ self.assertEquals(new_options['domain_resolution_order'][0], list) -+ self.assertEquals(new_options['domain_resolution_order'][1], str) -+ - del sssdconfig - - def testDomains(self): -@@ -314,7 +318,8 @@ class SSSDConfigTestSSSDService(unittest.TestCase): - 'certificate_verification', - 'override_space', - 'disable_netlink', -- 'enable_files_domain'] -+ 'enable_files_domain', -+ 'domain_resolution_order'] - - self.assertTrue(type(options) == dict, - "Options should be a dictionary") -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 933ebccd828189d923d2186753dfbc0b5c0814ce..41efcea552a82c5492a0d21a8d0797ee42cdc8c7 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -43,6 +43,7 @@ option = override_space - option = config_file_version - option = disable_netlink - option = enable_files_domain -+option = domain_resolution_order - - [rule/allowed_nss_options] - validator = ini_allowed_options -diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf -index 08cecf00367aaaab3794a48bd1e728421a996e49..6965028e1ca748f8b6677d9fc1faa66d5c307a0c 100644 ---- a/src/config/etc/sssd.api.conf -+++ b/src/config/etc/sssd.api.conf -@@ -32,6 +32,7 @@ certificate_verification = str, None, false - override_space = str, None, false - disable_netlink = bool, None, false - enable_files_domain = str, None, false -+domain_resolution_order = list, str, false - - [nss] - # Name service -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 1c27742cf0c1b6ffad23ab5b044bf4a168ed8f69..4fe13b85d511fb6a2ccc9b4de956710b05bc898c 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -542,6 +542,26 @@ - - - -+ -+ domain_resolution_order -+ -+ -+ Comma separated list of domains and subdomains -+ representing the lookup order that will be -+ followed. -+ The list doesn't have to include all possible -+ domains as the missing domains will be looked -+ up based on the order they're presented in the -+ domains configuration option. -+ The subdomains which are not listed as part of -+ lookup_order will be looked up -+ in a random order for each parent domain. -+ -+ -+ Default: Not set -+ -+ -+ - - - -diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h -index 29e3f95caf484f43307c9c28d4abd3f50f360a95..4210307489fe25829a1674f254ecc7d185029698 100644 ---- a/src/responder/common/responder.h -+++ b/src/responder/common/responder.h -@@ -115,6 +115,7 @@ struct resp_ctx { - int client_idle_timeout; - - struct cache_req_domain *cr_domains; -+ const char *domain_resolution_order; - - time_t last_request_time; - int idle_timeout; -diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c -index 1792a4c3771fa326c7cca31e1981dce315c03758..154d7dc7718c437d10e152fcba98161e2034fb14 100644 ---- a/src/responder/common/responder_common.c -+++ b/src/responder/common/responder_common.c -@@ -1163,6 +1163,19 @@ int sss_process_init(TALLOC_CTX *mem_ctx, - rctx->override_space = tmp[0]; - } - -+ ret = confdb_get_string(rctx->cdb, rctx, -+ CONFDB_MONITOR_CONF_ENTRY, -+ CONFDB_MONITOR_DOMAIN_RESOLUTION_ORDER, NULL, -+ &tmp); -+ if (ret == EOK) { -+ rctx->domain_resolution_order = sss_replace_char(rctx, tmp, ',', ':'); -+ } else { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot get the \"domain_resolution_order\" option.\n" -+ "The set up lookup_order won't be followed [%d]: %s.\n", -+ ret, sss_strerror(ret)); -+ } -+ - ret = sss_monitor_init(rctx, rctx->ev, monitor_intf, - svc_name, svc_version, MT_SVC_SERVICE, - rctx, &rctx->last_request_time, -@@ -1546,6 +1559,20 @@ errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) - struct sss_domain_info *dom; - errno_t ret; - -+ if (rctx->domain_resolution_order != NULL) { -+ cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -+ rctx, rctx->domains, rctx->domain_resolution_order); -+ -+ if (cr_domains == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Failed to use domain_resolution_order set in the config file.\n" -+ "Trying to fallback to use ipaDomainOrderResolution setup by " -+ "IPA.\n"); -+ } else { -+ goto done; -+ } -+ } -+ - for (dom = rctx->domains; dom != NULL; dom = dom->next) { - if (dom->provider != NULL && strcmp(dom->provider, "ipa") == 0) { - break; --- -2.12.2 - diff --git a/0058-ssh-handle-binary-keys-correctly.patch b/0058-ssh-handle-binary-keys-correctly.patch deleted file mode 100644 index 3608367..0000000 --- a/0058-ssh-handle-binary-keys-correctly.patch +++ /dev/null @@ -1,48 +0,0 @@ -From bd1fa0ec90be717c3b7796d74b6f243f40178d16 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 16 Mar 2017 12:38:08 +0100 -Subject: [PATCH 58/97] ssh: handle binary keys correctly - -Related to https://pagure.io/SSSD/sssd/issue/3332 - -Reviewed-by: Jakub Hrozek ---- - src/responder/ssh/ssh_reply.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/responder/ssh/ssh_reply.c b/src/responder/ssh/ssh_reply.c -index 807f4ee079128b4a3f1719de890ffac6e0d5b2e0..7093e47253b5687bab387feed5299c2d0841d43c 100644 ---- a/src/responder/ssh/ssh_reply.c -+++ b/src/responder/ssh/ssh_reply.c -@@ -32,6 +32,11 @@ - #include "responder/common/cache_req/cache_req.h" - #include "responder/ssh/ssh_private.h" - -+/* Locally used flag for libldb's ldb_message_element structure to indicate -+ * binary data. Since the related data is only used in memory it is safe. If -+ * should be used with care if libldb's I/O operations are involved. */ -+#define SSS_EL_FLAG_BIN_DATA (1<<4) -+ - static errno_t get_valid_certs_keys(TALLOC_CTX *mem_ctx, - struct ssh_ctx *ssh_ctx, - struct ldb_message_element *el_cert, -@@ -148,7 +153,7 @@ static errno_t decode_and_add_base64_data(struct sss_packet *packet, - } - - for (d = 0; d < el->num_values; d++) { -- if (skip_base64_decode) { -+ if (skip_base64_decode || (el->flags & SSS_EL_FLAG_BIN_DATA)) { - key = el->values[d].data; - key_len = el->values[d].length; - } else { -@@ -233,6 +238,7 @@ ssh_get_output_keys(TALLOC_CTX *mem_ctx, - } - - if (elements[i] != NULL) { -+ elements[i]->flags |= SSS_EL_FLAG_BIN_DATA; - num_keys += elements[i]->num_values; - i++; - } --- -2.12.2 - diff --git a/0059-ssh-add-support-for-certificates-from-non-default-vi.patch b/0059-ssh-add-support-for-certificates-from-non-default-vi.patch deleted file mode 100644 index ca2d6b6..0000000 --- a/0059-ssh-add-support-for-certificates-from-non-default-vi.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 1b5d6b1afc9c3dc696b7b45f2d73b2634f42800a Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 16 Mar 2017 13:00:48 +0100 -Subject: [PATCH 59/97] ssh: add support for certificates from non-default - views - -Reviewed-by: Jakub Hrozek ---- - src/responder/ssh/ssh_reply.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/src/responder/ssh/ssh_reply.c b/src/responder/ssh/ssh_reply.c -index 7093e47253b5687bab387feed5299c2d0841d43c..1bb9d331868cc18488718c24fd82f32af780b525 100644 ---- a/src/responder/ssh/ssh_reply.c -+++ b/src/responder/ssh/ssh_reply.c -@@ -204,7 +204,7 @@ ssh_get_output_keys(TALLOC_CTX *mem_ctx, - uint32_t i = 0; - errno_t ret; - -- elements = talloc_zero_array(mem_ctx, struct ldb_message_element *, 5); -+ elements = talloc_zero_array(mem_ctx, struct ldb_message_element *, 6); - if (elements == NULL) { - return ENOMEM; - } -@@ -244,6 +244,24 @@ ssh_get_output_keys(TALLOC_CTX *mem_ctx, - } - } - -+ if (DOM_HAS_VIEWS(domain)) { -+ user_cert = ldb_msg_find_element(msg, OVERRIDE_PREFIX SYSDB_USER_CERT); -+ if (user_cert != NULL) { -+ ret = get_valid_certs_keys(elements, ssh_ctx, user_cert, -+ &elements[i]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "get_valid_certs_keys failed.\n"); -+ goto done; -+ } -+ -+ if (elements[i] != NULL) { -+ elements[i]->flags |= SSS_EL_FLAG_BIN_DATA; -+ num_keys += elements[i]->num_values; -+ i++; -+ } -+ } -+ } -+ - *_elements = elements; - *_num_keys = num_keys; - --- -2.12.2 - diff --git a/0060-krb5-return-to-responder-that-pkinit-is-not-availabl.patch b/0060-krb5-return-to-responder-that-pkinit-is-not-availabl.patch deleted file mode 100644 index 9efc035..0000000 --- a/0060-krb5-return-to-responder-that-pkinit-is-not-availabl.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 1c551b1373799643f3e9ba4f696d21b8fc57dafd Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 16 Mar 2017 20:43:08 +0100 -Subject: [PATCH 60/97] krb5: return to responder that pkinit is not available -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If pkinit is not available for a user but other authentication methods -are SSSD should still fall back to local certificate based -authentication if Smartcard credentials are provided. - -Resolves https://pagure.io/SSSD/sssd/issue/3343 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník ---- - src/providers/krb5/krb5_child.c | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) - -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index 777a25f2a0ea434dde12d2396f6a35c2a1b86cd0..a4128dda6b0861a95dba223047d66c4158b1afb6 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -42,6 +42,10 @@ - - #define SSSD_KRB5_CHANGEPW_PRINCIPAL "kadmin/changepw" - -+#define IS_SC_AUTHTOK(tok) ( \ -+ sss_authtok_get_type((tok)) == SSS_AUTHTOK_TYPE_SC_PIN \ -+ || sss_authtok_get_type((tok)) == SSS_AUTHTOK_TYPE_SC_KEYPAD) -+ - enum k5c_fast_opt { - K5C_FAST_NEVER, - K5C_FAST_TRY, -@@ -1529,12 +1533,17 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr, - * pre-auth module is missing or no Smartcard is inserted and only - * pkinit is available KRB5_PREAUTH_FAILED is returned. - * ERR_NO_AUTH_METHOD_AVAILABLE is used to indicate to the -- * frontend that local authentication might be tried. */ -+ * frontend that local authentication might be tried. -+ * Same is true if Smartcard credentials are given but only other -+ * authentication methods are available. */ - if (kr->pd->cmd == SSS_PAM_AUTHENTICATE - && kerr == KRB5_PREAUTH_FAILED -- && kr->password_prompting == false -- && kr->otp == false -- && kr->pkinit_prompting == false) { -+ && kr->pkinit_prompting == false -+ && (( kr->password_prompting == false -+ && kr->otp == false) -+ || ((kr->otp == true -+ || kr->password_prompting == true) -+ && IS_SC_AUTHTOK(kr->pd->authtok))) ) { - return ERR_NO_AUTH_METHOD_AVAILABLE; - } - return kerr; --- -2.12.2 - diff --git a/0061-IPA-add-mapped-attributes-to-user-from-trusted-domai.patch b/0061-IPA-add-mapped-attributes-to-user-from-trusted-domai.patch deleted file mode 100644 index 83c263e..0000000 --- a/0061-IPA-add-mapped-attributes-to-user-from-trusted-domai.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 415d93196533a6fcd90889c67396ef5af5bf791a Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 22 Mar 2017 14:13:05 +0100 -Subject: [PATCH 61/97] IPA: add mapped attributes to user from trusted domains - -Allow the usage of the mapped attribute for the lookup of AD users on -IPA clients as already used for the normal LDAP lookup. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek ---- - src/providers/ipa/ipa_s2n_exop.c | 33 ++++++++++++++++++++++++--------- - 1 file changed, 24 insertions(+), 9 deletions(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index c99312274073858e5e03f3e82c069dafc839eb61..05c32a24d61947e62884f460069083fb81f40fe0 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -761,6 +761,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - struct resp_attrs *simple_attrs, - const char *view_name, - struct sysdb_attrs *override_attrs, -+ struct sysdb_attrs *mapped_attrs, - bool update_initgr_timeout); - - static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx, -@@ -1009,6 +1010,7 @@ struct ipa_s2n_get_list_state { - struct resp_attrs *attrs; - struct sss_domain_info *obj_domain; - struct sysdb_attrs *override_attrs; -+ struct sysdb_attrs *mapped_attrs; - }; - - static errno_t ipa_s2n_get_list_step(struct tevent_req *req); -@@ -1025,7 +1027,8 @@ static struct tevent_req *ipa_s2n_get_list_send(TALLOC_CTX *mem_ctx, - int entry_type, - enum request_types request_type, - enum req_input_type list_type, -- char **list) -+ char **list, -+ struct sysdb_attrs *mapped_attrs) - { - int ret; - struct ipa_s2n_get_list_state *state; -@@ -1057,6 +1060,7 @@ static struct tevent_req *ipa_s2n_get_list_send(TALLOC_CTX *mem_ctx, - state->request_type = request_type; - state->attrs = NULL; - state->override_attrs = NULL; -+ state->mapped_attrs = mapped_attrs; - - ret = ipa_s2n_get_list_step(req); - if (ret != EOK) { -@@ -1288,7 +1292,8 @@ static errno_t ipa_s2n_get_list_save_step(struct tevent_req *req) - - ret = ipa_s2n_save_objects(state->dom, &state->req_input, state->attrs, - NULL, state->ipa_ctx->view_name, -- state->override_attrs, false); -+ state->override_attrs, state->mapped_attrs, -+ false); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n"); - return ret; -@@ -1704,7 +1709,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - BE_REQ_GROUP, - REQ_FULL_WITH_MEMBERS, - REQ_INP_NAME, -- missing_list); -+ missing_list, NULL); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "ipa_s2n_get_list_send failed.\n"); -@@ -1732,7 +1737,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - BE_REQ_USER, - REQ_FULL_WITH_MEMBERS, - REQ_INP_NAME, -- missing_list); -+ missing_list, NULL); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - "ipa_s2n_get_list_send failed.\n"); -@@ -1810,7 +1815,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - - if (ret == ENOENT || is_default_view(state->ipa_ctx->view_name)) { - ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs, -- state->simple_attrs, NULL, NULL, true); -+ state->simple_attrs, NULL, NULL, NULL, true); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n"); - goto done; -@@ -1978,6 +1983,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - struct resp_attrs *simple_attrs, - const char *view_name, - struct sysdb_attrs *override_attrs, -+ struct sysdb_attrs *mapped_attrs, - bool update_initgr_timeout) - { - int ret; -@@ -2305,6 +2311,15 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - goto done; - } - -+ if (mapped_attrs != NULL) { -+ ret = sysdb_set_user_attr(dom, name, mapped_attrs, -+ SYSDB_MOD_ADD); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_user_attr failed.\n"); -+ goto done; -+ } -+ } -+ - if (gid_override_attrs != NULL) { - ret = sysdb_set_user_attr(dom, name, gid_override_attrs, - SYSDB_MOD_REP); -@@ -2487,7 +2502,7 @@ static void ipa_s2n_get_list_done(struct tevent_req *subreq) - &sid_str); - if (ret == ENOENT) { - ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs, -- state->simple_attrs, NULL, NULL, true); -+ state->simple_attrs, NULL, NULL, NULL, true); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n"); - goto fail; -@@ -2525,7 +2540,7 @@ static void ipa_s2n_get_list_done(struct tevent_req *subreq) - ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs, - state->simple_attrs, - state->ipa_ctx->view_name, -- state->override_attrs, true); -+ state->override_attrs, NULL, true); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n"); - tevent_req_error(req, ret); -@@ -2561,7 +2576,7 @@ static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq) - - ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs, - state->simple_attrs, state->ipa_ctx->view_name, -- override_attrs, true); -+ override_attrs, NULL, true); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n"); - tevent_req_error(req, ret); -@@ -2662,7 +2677,7 @@ struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx, - dp_opt_get_int(ipa_ctx->sdap_id_ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), - BE_REQ_BY_SECID, REQ_FULL, REQ_INP_SECID, -- state->missing_sids); -+ state->missing_sids, NULL); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_send failed.\n"); - ret = ENOMEM; --- -2.12.2 - diff --git a/0062-IPA-lookup-AD-users-by-certificates-on-IPA-clients.patch b/0062-IPA-lookup-AD-users-by-certificates-on-IPA-clients.patch deleted file mode 100644 index 0a360ce..0000000 --- a/0062-IPA-lookup-AD-users-by-certificates-on-IPA-clients.patch +++ /dev/null @@ -1,209 +0,0 @@ -From 2cf7becc05996eb6d8a3352d3d7b97c75652e590 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 24 Mar 2017 15:40:41 +0100 -Subject: [PATCH 62/97] IPA: lookup AD users by certificates on IPA clients - -Get a list of users mapped to a certificate back from the IPA server, -look them up and store them together with the certificate used for the -search as mapped attribute to the cache. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek ---- - src/providers/ipa/ipa_s2n_exop.c | 109 +++++++++++++++++++++++++++++++++++++-- - 1 file changed, 105 insertions(+), 4 deletions(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 05c32a24d61947e62884f460069083fb81f40fe0..8a3391b4093f1547d84fe44a0f24b1d063d1e28c 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -52,7 +52,8 @@ enum response_types { - RESP_USER, - RESP_GROUP, - RESP_USER_GROUPLIST, -- RESP_GROUP_MEMBERS -+ RESP_GROUP_MEMBERS, -+ RESP_NAME_LIST - }; - - /* ==Sid2Name Extended Operation============================================= */ -@@ -366,8 +367,8 @@ static errno_t s2n_encode_request(TALLOC_CTX *mem_ctx, - break; - case BE_REQ_BY_CERT: - if (req_input->type == REQ_INP_CERT) { -- ret = ber_printf(ber, "{ees}", INP_CERT, request_type, -- req_input->inp.cert); -+ ret = ber_printf(ber, "{ees}", INP_CERT, request_type, -+ req_input->inp.cert); - } else { - DEBUG(SSSDBG_OP_FAILURE, "Unexpected input type [%d].\n", - req_input->type); -@@ -463,6 +464,11 @@ done: - * GroupMemberList ::= SEQUENCE OF OCTET STRING - */ - -+struct name_list { -+ char *domain_name; -+ char *name; -+}; -+ - struct resp_attrs { - enum response_types response_type; - char *domain_name; -@@ -475,6 +481,7 @@ struct resp_attrs { - size_t ngroups; - char **groups; - struct sysdb_attrs *sysdb_attrs; -+ char **name_list; - }; - - static errno_t get_extra_attrs(BerElement *ber, struct resp_attrs *resp_attrs) -@@ -782,6 +789,9 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx, - struct resp_attrs *attrs = NULL; - char *sid_str; - bool is_v1 = false; -+ char **name_list = NULL; -+ ber_len_t ber_len; -+ char *fq_name = NULL; - - if (retoid == NULL || retdata == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "Missing OID or data.\n"); -@@ -947,6 +957,53 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx, - goto done; - } - break; -+ case RESP_NAME_LIST: -+ tag = ber_scanf(ber, "{"); -+ if (tag == LBER_ERROR) { -+ DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ while (ber_peek_tag(ber, &ber_len) == LBER_SEQUENCE) { -+ tag = ber_scanf(ber, "{aa}", &domain_name, &name); -+ if (tag == LBER_ERROR) { -+ DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ fq_name = sss_create_internal_fqname(attrs, name, domain_name); -+ if (fq_name == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sss_create_internal_fqname failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ DEBUG(SSSDBG_TRACE_ALL, "[%s][%s][%s].\n", domain_name, name, -+ fq_name); -+ -+ ret = add_string_to_list(attrs, fq_name, &name_list); -+ ber_memfree(domain_name); -+ ber_memfree(name); -+ talloc_free(fq_name); -+ domain_name = NULL; -+ name = NULL; -+ fq_name = NULL; -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "add_to_name_list failed.\n"); -+ goto done; -+ } -+ } -+ -+ tag = ber_scanf(ber, "}}"); -+ if (tag == LBER_ERROR) { -+ DEBUG(SSSDBG_OP_FAILURE, "ber_scanf failed.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ attrs->name_list = name_list; -+ break; - default: - DEBUG(SSSDBG_OP_FAILURE, "Unexpected response type [%d].\n", - type); -@@ -955,7 +1012,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx, - } - - attrs->response_type = type; -- if (type != RESP_SID) { -+ if (type != RESP_SID && type != RESP_NAME_LIST) { - attrs->domain_name = talloc_strdup(attrs, domain_name); - if (attrs->domain_name == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -@@ -969,6 +1026,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx, - done: - ber_memfree(domain_name); - ber_memfree(name); -+ talloc_free(fq_name); - ber_free(ber, 1); - - if (ret == EOK) { -@@ -1332,6 +1390,7 @@ struct ipa_s2n_get_user_state { - struct resp_attrs *attrs; - struct resp_attrs *simple_attrs; - struct sysdb_attrs *override_attrs; -+ struct sysdb_attrs *mapped_attrs; - int exop_timeout; - }; - -@@ -1384,6 +1443,11 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx, - goto fail; - } - -+ if (entry_type == BE_REQ_BY_CERT) { -+ /* Only REQ_SIMPLE is supported for BE_REQ_BY_CERT */ -+ state->request_type = REQ_SIMPLE; -+ } -+ - ret = s2n_encode_request(state, dom->name, entry_type, state->request_type, - req_input, &bv_req); - if (ret != EOK) { -@@ -1785,6 +1849,43 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - goto done; - } - -+ if (state->simple_attrs->response_type == RESP_NAME_LIST -+ && state->req_input->type == REQ_INP_CERT) { -+ state->mapped_attrs = sysdb_new_attrs(state); -+ if (state->mapped_attrs == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_attrs_add_base64_blob(state->mapped_attrs, -+ SYSDB_USER_MAPPED_CERT, -+ state->req_input->inp.cert); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_base64_blob failed.\n"); -+ goto done; -+ } -+ -+ subreq = ipa_s2n_get_list_send(state, state->ev, -+ state->ipa_ctx, state->dom, -+ state->sh, state->exop_timeout, -+ BE_REQ_USER, -+ REQ_FULL_WITH_MEMBERS, -+ REQ_INP_NAME, -+ state->simple_attrs->name_list, -+ state->mapped_attrs); -+ if (subreq == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "ipa_s2n_get_list_send failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ tevent_req_set_callback(subreq, ipa_s2n_get_list_done, -+ req); -+ -+ return; -+ } -+ - break; - default: - DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected request type.\n"); --- -2.12.2 - diff --git a/0063-IPA-enable-AD-user-lookup-by-certificate.patch b/0063-IPA-enable-AD-user-lookup-by-certificate.patch deleted file mode 100644 index 120c808..0000000 --- a/0063-IPA-enable-AD-user-lookup-by-certificate.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 82843754193b177275ce16f2901edac2060a3998 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 24 Mar 2017 15:41:37 +0100 -Subject: [PATCH 63/97] IPA: enable AD user lookup by certificate - -Without this the lookup by certificate for AD users on an IPA client -will just error out. - -Related to https://pagure.io/SSSD/sssd/issue/3050 - -Reviewed-by: Jakub Hrozek ---- - src/providers/ipa/ipa_subdomains_id.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 4777d7cfd97fed39b807a659fd1f9000c7ff8625..3530af94ef59397db72465fcb0c4a03117a4d8bd 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -399,6 +399,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, - case BE_REQ_USER: - case BE_REQ_GROUP: - case BE_REQ_BY_SECID: -+ case BE_REQ_BY_CERT: - case BE_REQ_USER_AND_GROUP: - ret = EOK; - break; --- -2.12.2 - diff --git a/0064-CONFDB-Introduce-SSSD-domain-type-to-distinguish-POS.patch b/0064-CONFDB-Introduce-SSSD-domain-type-to-distinguish-POS.patch deleted file mode 100644 index 6386120..0000000 --- a/0064-CONFDB-Introduce-SSSD-domain-type-to-distinguish-POS.patch +++ /dev/null @@ -1,242 +0,0 @@ -From 6324eaf1fb321c41ca9883966118df6d45259b7e Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Mar 2017 12:53:17 +0100 -Subject: [PATCH 64/97] CONFDB: Introduce SSSD domain type to distinguish POSIX - and application domains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -Adds a new option that allows to distinguish domains that do contain -POSIX users and groups and those that don't. The POSIX domains are the -default. The non-POSIX domains are selected by selecting an -"application" type domain. - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/confdb/confdb.c | 18 +++++++++++++++++- - src/confdb/confdb.h | 15 +++++++++++++++ - src/config/SSSDConfig/__init__.py.in | 1 + - src/config/SSSDConfigTest.py | 2 ++ - src/config/cfg_rules.ini | 1 + - src/config/etc/sssd.api.conf | 1 + - src/man/sssd.conf.5.xml | 33 +++++++++++++++++++++++++++++++++ - src/util/domain_info_utils.c | 14 ++++++++++++++ - src/util/util.h | 1 + - 9 files changed, 85 insertions(+), 1 deletion(-) - -diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c -index d82fd98ee02928b3c20df014528bd869ec946f92..70a1eb7b2c7e83dfa9d217a15c7d3d4c8580b891 100644 ---- a/src/confdb/confdb.c -+++ b/src/confdb/confdb.c -@@ -1367,6 +1367,22 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, - } - } - -+ domain->type = DOM_TYPE_POSIX; -+ tmp = ldb_msg_find_attr_as_string(res->msgs[0], -+ CONFDB_DOMAIN_TYPE, -+ CONFDB_DOMAIN_TYPE_POSIX); -+ if (tmp != NULL) { -+ if (strcasecmp(tmp, CONFDB_DOMAIN_TYPE_POSIX) == 0) { -+ domain->type = DOM_TYPE_POSIX; -+ } else if (strcasecmp(tmp, CONFDB_DOMAIN_TYPE_APP) == 0) { -+ domain->type = DOM_TYPE_APPLICATION; -+ } else { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Invalid value %s for [%s]\n", tmp, CONFDB_DOMAIN_TYPE); -+ goto done; -+ } -+ } -+ - ret = get_entry_as_uint32(res->msgs[0], &domain->subdomain_refresh_interval, - CONFDB_DOMAIN_SUBDOMAIN_REFRESH, 14400); - if (ret != EOK || domain->subdomain_refresh_interval == 0) { -@@ -1444,7 +1460,7 @@ int confdb_get_domains(struct confdb_ctx *cdb, - if (ret) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Error (%d [%s]) retrieving domain [%s], skipping!\n", -- ret, sss_strerror(ret), domlist[i]); -+ ret, sss_strerror(ret), domlist[i]); - continue; - } - -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index 56a603652d6c8256735e7f8b125300ff7b254645..a4046610f3cdbdb832de8924bf4397fb0018f2db 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -209,6 +209,9 @@ - #define CONFDB_DOMAIN_OFFLINE_TIMEOUT "offline_timeout" - #define CONFDB_DOMAIN_SUBDOMAIN_INHERIT "subdomain_inherit" - #define CONFDB_DOMAIN_CACHED_AUTH_TIMEOUT "cached_auth_timeout" -+#define CONFDB_DOMAIN_TYPE "domain_type" -+#define CONFDB_DOMAIN_TYPE_POSIX "posix" -+#define CONFDB_DOMAIN_TYPE_APP "application" - - /* Local Provider */ - #define CONFDB_LOCAL_DEFAULT_SHELL "default_shell" -@@ -261,11 +264,23 @@ enum sss_domain_state { - DOM_INCONSISTENT, - }; - -+/** Whether the domain only supports looking up POSIX entries */ -+enum sss_domain_type { -+ /** This is the default domain type. It resolves only entries -+ * with the full POSIX set of attributes -+ */ -+ DOM_TYPE_POSIX, -+ /** In this mode, entries are typically resolved only by name */ -+ DOM_TYPE_APPLICATION, -+}; -+ - /** - * Data structure storing all of the basic features - * of a domain. - */ - struct sss_domain_info { -+ enum sss_domain_type type; -+ - char *name; - char *conn_name; - char *provider; -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 0edc3ea84a1e8fb0f797546b4c223e22e22f70e9..070994bcd04604777019d264d12cb126d6638bfd 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -148,6 +148,7 @@ option_strings = { - 'selinux_provider' : _('SELinux provider'), - - # [domain] -+ 'domain_type' : _('Whether the domain is usable by the OS or by applications'), - 'min_id' : _('Minimum user ID'), - 'max_id' : _('Maximum user ID'), - 'enumerate' : _('Enable enumerating all users/groups'), -diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py -index 6899bf8ae04bf210546c8cbdba8235f094e23dc0..9b3175962c697e314b3d5d94c2bc5beda537b66e 100755 ---- a/src/config/SSSDConfigTest.py -+++ b/src/config/SSSDConfigTest.py -@@ -510,6 +510,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): - 'debug', - 'debug_level', - 'debug_timestamps', -+ 'domain_type', - 'min_id', - 'max_id', - 'timeout', -@@ -878,6 +879,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): - 'debug', - 'debug_level', - 'debug_timestamps', -+ 'domain_type', - 'min_id', - 'max_id', - 'timeout', -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 41efcea552a82c5492a0d21a8d0797ee42cdc8c7..3c857236eaa55b313d176bc4bb479918163b60d5 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -311,6 +311,7 @@ option = subdomains_provider - option = selinux_provider - - # Options available to all domains -+option = domain_type - option = min_id - option = max_id - option = timeout -diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf -index 6965028e1ca748f8b6677d9fc1faa66d5c307a0c..a38b24208f89e4502e41625c540ea9958d5bbffe 100644 ---- a/src/config/etc/sssd.api.conf -+++ b/src/config/etc/sssd.api.conf -@@ -129,6 +129,7 @@ selinux_provider = str, None, false - [domain] - # Options available to all domains - description = str, None, false -+domain_type = str, None, false - debug = int, None, false - debug_level = int, None, false - debug_timestamps = bool, None, false -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 4fe13b85d511fb6a2ccc9b4de956710b05bc898c..9abcff84a95ea1b27e36845e830cc125fdc89f90 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -1512,6 +1512,39 @@ pam_account_locked_message = Account locked, please contact help desk. - [domain/NAME] - - -+ domain_type (string) -+ -+ -+ Specifies whether the domain is meant to be used -+ by POSIX-aware clients such as the Name Service Switch -+ or by applications that do not need POSIX data to be -+ present or generated. Only objects from POSIX domains -+ are available to the operating system interfaces and -+ utilities. -+ -+ -+ Allowed values for this option are posix -+ and application. -+ -+ -+ POSIX domains are reachable by all services. Application -+ domains are only reachable from the InfoPipe responder (see -+ -+ sssd-ifp -+ 5 -+ ) and the PAM responder. -+ -+ -+ NOTE: The application domains are currently well tested with -+ id_provider=ldap only. -+ -+ -+ Default: posix -+ -+ -+ -+ -+ - min_id,max_id (integer) - - -diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c -index a7f118842aa8ba870143b2f2b425a3e3c0ea5a78..2af7852f03f89b61f5b9fd8a244e98fb27b7e6a2 100644 ---- a/src/util/domain_info_utils.c -+++ b/src/util/domain_info_utils.c -@@ -885,3 +885,17 @@ char *subdomain_create_conf_path(TALLOC_CTX *mem_ctx, - subdomain->parent->name, - subdomain->name); - } -+ -+const char *sss_domain_type_str(struct sss_domain_info *dom) -+{ -+ if (dom == NULL) { -+ return "BUG: Invalid domain"; -+ } -+ switch (dom->type) { -+ case DOM_TYPE_POSIX: -+ return "POSIX"; -+ case DOM_TYPE_APPLICATION: -+ return "Application"; -+ } -+ return "Unknown"; -+} -diff --git a/src/util/util.h b/src/util/util.h -index 2170c5fb7cffda3910d2b58e33ec7abe3ec4a7d4..436550f5078cc173b8ed8cb58836d366f813146b 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -539,6 +539,7 @@ enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom); - void sss_domain_set_state(struct sss_domain_info *dom, - enum sss_domain_state state); - bool is_email_from_domain(const char *email, struct sss_domain_info *dom); -+const char *sss_domain_type_str(struct sss_domain_info *dom); - - struct sss_domain_info* - sss_get_domain_by_sid_ldap_fallback(struct sss_domain_info *domain, --- -2.12.2 - diff --git a/0065-CONFDB-Allow-configuring-application-sections-as-non.patch b/0065-CONFDB-Allow-configuring-application-sections-as-non.patch deleted file mode 100644 index 7b49113..0000000 --- a/0065-CONFDB-Allow-configuring-application-sections-as-non.patch +++ /dev/null @@ -1,531 +0,0 @@ -From 825e8bf2f73a815c2eceb36ae805145fcbacf74d Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 27 Mar 2017 09:48:46 +0200 -Subject: [PATCH 65/97] CONFDB: Allow configuring [application] sections as - non-POSIX domains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -Allows to add a new section: - [application/$name] - -This section internally (on the confdb level) expands to: - [domain/$name] - domain_type = application - -The reasons to add this new section is two-fold. One, to make the -configuration of application domains more explicit and two, to make it -possible to share configuration between two domains, one POSIX and one -non-POSIX by application domain's inherit_from option: - [application/$name] - inherit_from = posix_domain_name - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/confdb/confdb.c | 288 ++++++++++++++++++++++++++++++++++++++++++++--- - src/confdb/confdb.h | 4 + - src/config/cfg_rules.ini | 9 +- - src/man/sssd.conf.5.xml | 77 +++++++++++++ - src/monitor/monitor.c | 8 ++ - 5 files changed, 368 insertions(+), 18 deletions(-) - -diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c -index 70a1eb7b2c7e83dfa9d217a15c7d3d4c8580b891..88e114457deac3ca50c291a131122624fb6f6fe4 100644 ---- a/src/confdb/confdb.c -+++ b/src/confdb/confdb.c -@@ -813,6 +813,50 @@ done: - return ret; - } - -+static int confdb_get_domain_section(TALLOC_CTX *mem_ctx, -+ struct confdb_ctx *cdb, -+ const char *section, -+ const char *name, -+ struct ldb_result **_res) -+{ -+ TALLOC_CTX *tmp_ctx; -+ int ret; -+ struct ldb_result *res; -+ struct ldb_dn *dn; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, "cn=%s,%s", name, section); -+ if (dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, -+ LDB_SCOPE_BASE, NULL, NULL); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ if (res->count == 0) { -+ ret = ENOENT; -+ goto done; -+ } else if (res->count > 1) { -+ ret = E2BIG; -+ goto done; -+ } -+ -+ *_res = talloc_steal(mem_ctx, res); -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ - static int confdb_get_domain_internal(struct confdb_ctx *cdb, - TALLOC_CTX *mem_ctx, - const char *name, -@@ -821,7 +865,6 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, - struct sss_domain_info *domain; - struct ldb_result *res; - TALLOC_CTX *tmp_ctx; -- struct ldb_dn *dn; - const char *tmp; - int ret, val; - uint32_t entry_cache_timeout; -@@ -833,23 +876,15 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, - tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) return ENOMEM; - -- dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, -- "cn=%s,%s", name, CONFDB_DOMAIN_BASEDN); -- if (!dn) { -- ret = ENOMEM; -- goto done; -- } -- -- ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, -- LDB_SCOPE_BASE, NULL, NULL); -- if (ret != LDB_SUCCESS) { -- ret = EIO; -- goto done; -- } -- -- if (res->count != 1) { -+ ret = confdb_get_domain_section(tmp_ctx, cdb, CONFDB_DOMAIN_BASEDN, -+ name, &res); -+ if (ret == ENOENT) { - DEBUG(SSSDBG_FATAL_FAILURE, "Unknown domain [%s]\n", name); -- ret = ENOENT; -+ goto done; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Error %d: %s while retrieving %s\n", -+ ret, sss_strerror(ret), name); - goto done; - } - -@@ -1841,3 +1876,222 @@ int confdb_ensure_files_domain(struct confdb_ctx *cdb, - return activate_files_domain(cdb, implicit_files_dom_name); - #endif /* ADD_FILES_DOMAIN */ - } -+ -+static int confdb_get_parent_domain(TALLOC_CTX *mem_ctx, -+ const char *name, -+ struct confdb_ctx *cdb, -+ struct ldb_result *app_dom, -+ struct ldb_result **_parent_dom) -+{ -+ const char *inherit_from; -+ -+ inherit_from = ldb_msg_find_attr_as_string(app_dom->msgs[0], -+ CONFDB_DOMAIN_INHERIT_FROM, NULL); -+ if (inherit_from == NULL) { -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ "%s does not inherit from any POSIX domain\n", name); -+ *_parent_dom = NULL; -+ return EOK; -+ } -+ -+ return confdb_get_domain_section(mem_ctx, cdb, -+ CONFDB_DOMAIN_BASEDN, inherit_from, -+ _parent_dom); -+} -+ -+static int confdb_add_app_domain(TALLOC_CTX *mem_ctx, -+ struct confdb_ctx *cdb, -+ const char *name) -+{ -+ char *cdb_path = NULL; -+ const char *val[2] = { NULL, NULL }; -+ int ret; -+ -+ cdb_path = talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL, name); -+ if (cdb_path == NULL) { -+ return ENOMEM; -+ } -+ -+ val[0] = CONFDB_DOMAIN_TYPE_APP; -+ ret = confdb_add_param(cdb, true, cdb_path, CONFDB_DOMAIN_TYPE, val); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add id_provider [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+static int confdb_merge_parent_domain(const char *name, -+ struct confdb_ctx *cdb, -+ struct ldb_result *app_section) -+{ -+ int ret; -+ int ldb_flag; -+ struct ldb_result *parent_domain = NULL; -+ struct ldb_message *replace_msg = NULL; -+ struct ldb_message *app_msg = NULL; -+ struct ldb_dn *domain_dn; -+ TALLOC_CTX *tmp_ctx = NULL; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); -+ return ENOMEM; -+ } -+ -+ domain_dn = ldb_dn_new_fmt(tmp_ctx, -+ cdb->ldb, -+ "%s=%s,%s", -+ CONFDB_DOMAIN_ATTR, -+ name, -+ CONFDB_DOMAIN_BASEDN); -+ if (domain_dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* Copy the parent domain parameters */ -+ ret = confdb_get_parent_domain(tmp_ctx, name, cdb, -+ app_section, &parent_domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot retrieve the parent domain [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ if (parent_domain != NULL) { -+ replace_msg = ldb_msg_copy(tmp_ctx, parent_domain->msgs[0]); -+ if (replace_msg == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ replace_msg->dn = domain_dn; -+ -+ for (unsigned i = 0; i < replace_msg->num_elements; i++) { -+ replace_msg->elements[i].flags = LDB_FLAG_MOD_ADD; -+ } -+ -+ ret = ldb_modify(cdb->ldb, replace_msg); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Inheriting options from parent domain failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ } -+ -+ /* Finally, add any app-domain specific overrides */ -+ app_msg = ldb_msg_new(tmp_ctx); -+ if (app_msg == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ app_msg->dn = domain_dn; -+ -+ for (unsigned i = 0; i < app_section->msgs[0]->num_elements; i++) { -+ struct ldb_message_element *el = NULL; -+ -+ if (replace_msg != NULL) { -+ el = ldb_msg_find_element(replace_msg, -+ app_section->msgs[0]->elements[i].name); -+ if (el == NULL) { -+ /* Adding an element */ -+ ldb_flag = LDB_FLAG_MOD_ADD; -+ } else { -+ /* Overriding an element */ -+ ldb_flag = LDB_FLAG_MOD_REPLACE; -+ } -+ } else { -+ /* If there was no domain to inherit from, just add all */ -+ ldb_flag = LDB_FLAG_MOD_ADD; -+ } -+ -+ ret = ldb_msg_add(app_msg, -+ &app_section->msgs[0]->elements[i], -+ ldb_flag); -+ if (ret != EOK) { -+ continue; -+ } -+ } -+ -+ ret = ldb_modify(cdb->ldb, app_msg); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Adding app-specific options failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Added a domain section for %s\n", name); -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+int confdb_expand_app_domains(struct confdb_ctx *cdb) -+{ -+ int ret; -+ char **domlist; -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_result *app_domain = NULL; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = confdb_get_string_as_list(cdb, tmp_ctx, -+ CONFDB_MONITOR_CONF_ENTRY, -+ CONFDB_MONITOR_ACTIVE_DOMAINS, -+ &domlist); -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured, fatal error!\n"); -+ goto done; -+ } else if (ret != EOK ) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n"); -+ goto done; -+ } -+ -+ for (int i = 0; domlist[i]; i++) { -+ ret = confdb_get_domain_section(tmp_ctx, cdb, -+ CONFDB_APP_DOMAIN_BASEDN, domlist[i], -+ &app_domain); -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "%s is not an app domain\n", domlist[i]); -+ continue; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Error %d: %s while retrieving %s\n", -+ ret, sss_strerror(ret), domlist[i]); -+ goto done; -+ } -+ -+ ret = confdb_add_app_domain(tmp_ctx, cdb, domlist[i]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot add the app domain section [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = confdb_merge_parent_domain(domlist[i], cdb, app_domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot add options into the app domain section [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index a4046610f3cdbdb832de8924bf4397fb0018f2db..5a8d377c312f641f544b1c7cf38826192462ea3c 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -164,6 +164,7 @@ - /* Domains */ - #define CONFDB_DOMAIN_PATH_TMPL "config/domain/%s" - #define CONFDB_DOMAIN_BASEDN "cn=domain,cn=config" -+#define CONFDB_APP_DOMAIN_BASEDN "cn=application,cn=config" - #define CONFDB_DOMAIN_ID_PROVIDER "id_provider" - #define CONFDB_DOMAIN_AUTH_PROVIDER "auth_provider" - #define CONFDB_DOMAIN_ACCESS_PROVIDER "access_provider" -@@ -212,6 +213,7 @@ - #define CONFDB_DOMAIN_TYPE "domain_type" - #define CONFDB_DOMAIN_TYPE_POSIX "posix" - #define CONFDB_DOMAIN_TYPE_APP "application" -+#define CONFDB_DOMAIN_INHERIT_FROM "inherit_from" - - /* Local Provider */ - #define CONFDB_LOCAL_DEFAULT_SHELL "default_shell" -@@ -398,6 +400,8 @@ int confdb_get_domains(struct confdb_ctx *cdb, - int confdb_ensure_files_domain(struct confdb_ctx *cdb, - const char *implicit_files_dom_name); - -+int confdb_expand_app_domains(struct confdb_ctx *cdb); -+ - /** - * Get a null-terminated linked-list of all domain names - * @param[in] mem_ctx The parent memory context for the value list -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 3c857236eaa55b313d176bc4bb479918163b60d5..8fd2d2c5236246394353a88c50d1510bd6233f77 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -12,6 +12,7 @@ section = secrets - section = kcm - section_re = ^secrets/users/[0-9]\+$ - section_re = ^domain/.*$ -+section_re = ^application/.*$ - - [rule/allowed_sssd_options] - validator = ini_allowed_options -@@ -286,7 +287,7 @@ option = responder_idle_timeout - - [rule/allowed_domain_options] - validator = ini_allowed_options --section_re = ^domain/.*$ -+section_re = ^(domain|application)/.*$ - - option = debug - option = debug_level -@@ -684,3 +685,9 @@ option = ldap_user_ssh_public_key - option = ldap_user_uid_number - option = ldap_user_uuid - option = ldap_use_tokengroups -+ -+[rule/allowed_application_options] -+validator = ini_allowed_options -+section_re = ^application/.*$ -+ -+option = inherit_from -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 9abcff84a95ea1b27e36845e830cc125fdc89f90..8294793c765bfa6bf481693c7d7f206950454681 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -1539,6 +1539,10 @@ pam_account_locked_message = Account locked, please contact help desk. - id_provider=ldap only. - - -+ For an easy way to configure a non-POSIX domains, please -+ see the Application domains section. -+ -+ - Default: posix - - -@@ -2692,6 +2696,79 @@ subdomain_inherit = ldap_purge_cache_timeout - - - -+ -+ Application domains -+ -+ SSSD, with its D-Bus interface (see -+ -+ sssd-ifp -+ 5 -+ ) is appealing to applications -+ as a gateway to an LDAP directory where users and groups -+ are stored. However, contrary to the traditional SSSD -+ deployment where all users and groups either have POSIX -+ attributes or those attributes can be inferred from the -+ Windows SIDs, in many cases the users and groups in the -+ application support scenario have no POSIX attributes. -+ Instead of setting a -+ [domain/NAME] -+ section, the administrator can set up an -+ [application/NAME] -+ section that internally represents a domain with type -+ application optionally inherits settings -+ from a tradition SSSD domain. -+ -+ -+ Please note that the application domain must still be -+ explicitly enabled in the domains parameter -+ so that the lookup order between the application domain -+ and its POSIX sibling domain is set correctly. -+ -+ -+ Application domain parameters -+ -+ inherit_from (string) -+ -+ -+ The SSSD POSIX-type domain the application -+ domain inherits all settings from. The -+ application domain can moreover add its own -+ settings to the application settings that augment -+ or override the sibling -+ domain settings. -+ -+ -+ Default: Not set -+ -+ -+ -+ -+ -+ The following example illustrates the use of an application -+ domain. In this setup, the POSIX domain is connected to an LDAP -+ server and is used by the OS through the NSS responder. In addition, -+ the application domains also requests the telephoneNumber attribute, -+ stores it as the phone attribute in the cache and makes the phone -+ attribute reachable through the D-Bus interface. -+ -+ -+[sssd] -+domains = appdom, posixdom -+ -+[ifp] -+user_attributes = +phone -+ -+[domain/posixdom] -+id_provider = ldap -+ldap_uri = ldap://ldap.example.com -+ldap_search_base = dc=example,dc=com -+ -+[application/appdom] -+inherit_from = posixdom -+ldap_user_extra_attrs = phone:telephoneNumber -+ -+ -+ - - The local domain section - -diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c -index 7e7b5a07d11aecf1c0b11592213b90d385fd5076..2753b46667f7ae0b022776862c67a327d3356d6d 100644 ---- a/src/monitor/monitor.c -+++ b/src/monitor/monitor.c -@@ -1064,6 +1064,14 @@ static int get_monitor_config(struct mt_ctx *ctx) - /* Not fatal */ - } - -+ ret = confdb_expand_app_domains(ctx->cdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to expand application domains\n"); -+ /* This must not be fatal so that SSSD keeps running and lets -+ * admin correct the error. -+ */ -+ } -+ - ret = confdb_get_domains(ctx->cdb, &ctx->domains); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured.\n"); --- -2.12.2 - diff --git a/0066-CACHE_REQ-Domain-type-selection-in-cache_req.patch b/0066-CACHE_REQ-Domain-type-selection-in-cache_req.patch deleted file mode 100644 index 7127892..0000000 --- a/0066-CACHE_REQ-Domain-type-selection-in-cache_req.patch +++ /dev/null @@ -1,976 +0,0 @@ -From cee85e8fb9534ec997e5388fce59f392cf029573 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 24 Mar 2017 10:39:12 +0100 -Subject: [PATCH 66/97] CACHE_REQ: Domain type selection in cache_req -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to: - https://pagure.io/SSSD/sssd/issue/3310 - -Adds a new enumeration cache_req_dom_type. It is a tri-state that -allows the caller to select which domains can be contacted - either only -POSIX, only application domains or any type. - -Not all plugins of cache_req have the new parameter added -- only those -that are usable/useful in a non-POSIX environment. For example, it makes -no sense to allow the selection for calls by ID because those are -inherently POSIX-specific. Also, services or netgroups are supported -only coming from POSIX domains. - -At the moment, the patch should not change any behaviour as all calls -default to contacting POSIX domains only. - -Reviewed-by: Pavel Březina ---- - src/responder/common/cache_req/cache_req.c | 80 ++++++++++++++++++++-- - src/responder/common/cache_req/cache_req.h | 19 +++++ - src/responder/common/cache_req/cache_req_private.h | 3 + - .../cache_req/plugins/cache_req_enum_groups.c | 4 +- - .../common/cache_req/plugins/cache_req_enum_svc.c | 3 +- - .../cache_req/plugins/cache_req_enum_users.c | 4 +- - .../cache_req/plugins/cache_req_group_by_filter.c | 5 +- - .../cache_req/plugins/cache_req_group_by_id.c | 4 +- - .../cache_req/plugins/cache_req_group_by_name.c | 5 +- - .../cache_req/plugins/cache_req_host_by_name.c | 4 +- - .../plugins/cache_req_initgroups_by_name.c | 5 +- - .../cache_req/plugins/cache_req_netgroup_by_name.c | 4 +- - .../cache_req/plugins/cache_req_object_by_id.c | 4 +- - .../cache_req/plugins/cache_req_object_by_name.c | 4 +- - .../cache_req/plugins/cache_req_object_by_sid.c | 4 +- - .../cache_req/plugins/cache_req_svc_by_name.c | 4 +- - .../cache_req/plugins/cache_req_svc_by_port.c | 4 +- - .../cache_req/plugins/cache_req_user_by_cert.c | 4 +- - .../cache_req/plugins/cache_req_user_by_filter.c | 5 +- - .../cache_req/plugins/cache_req_user_by_id.c | 4 +- - .../cache_req/plugins/cache_req_user_by_name.c | 9 ++- - src/responder/ifp/ifp_groups.c | 14 +++- - src/responder/ifp/ifp_users.c | 19 +++-- - src/responder/ifp/ifpsrv_cmd.c | 3 +- - src/responder/nss/nss_enum.c | 2 +- - src/responder/nss/nss_get_object.c | 3 +- - src/responder/pam/pamsrv_cmd.c | 5 +- - src/responder/sudo/sudosrv_get_sudorules.c | 3 +- - src/tests/cmocka/test_responder_cache_req.c | 62 ++++++++++++++--- - 29 files changed, 246 insertions(+), 47 deletions(-) - -diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c -index 483126396f8addbad744ae03bfc739801cd0c18b..3a5fecf34427437bbf95317e05c5bd8b07b4537d 100644 ---- a/src/responder/common/cache_req/cache_req.c -+++ b/src/responder/common/cache_req/cache_req.c -@@ -89,12 +89,31 @@ static errno_t cache_req_set_plugin(struct cache_req *cr, - return EOK; - } - -+static const char * -+cache_req_dom_type_as_str(struct cache_req *cr) -+{ -+ if (cr == NULL) { -+ return "BUG: Invalid cache_req pointer\n"; -+ } -+ switch (cr->req_dom_type) { -+ case CACHE_REQ_POSIX_DOM: -+ return "POSIX-only"; -+ case CACHE_REQ_APPLICATION_DOM: -+ return "Application-only"; -+ case CACHE_REQ_ANY_DOM: -+ return "Any"; -+ } -+ -+ return "Unknown"; -+} -+ - static struct cache_req * - cache_req_create(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct cache_req_data *data, - struct sss_nc_ctx *ncache, -- int midpoint) -+ int midpoint, -+ enum cache_req_dom_type req_dom_type) - { - struct cache_req *cr; - errno_t ret; -@@ -108,6 +127,7 @@ cache_req_create(TALLOC_CTX *mem_ctx, - cr->data = data; - cr->ncache = ncache; - cr->midpoint = midpoint; -+ cr->req_dom_type = req_dom_type; - cr->req_start = time(NULL); - - /* It is perfectly fine to just overflow here. */ -@@ -145,8 +165,8 @@ cache_req_set_name(struct cache_req *cr, const char *name) - } - - static bool --cache_req_validate_domain(struct cache_req *cr, -- struct sss_domain_info *domain) -+cache_req_validate_domain_enumeration(struct cache_req *cr, -+ struct sss_domain_info *domain) - { - if (!cr->plugin->require_enumeration) { - return true; -@@ -164,6 +184,52 @@ cache_req_validate_domain(struct cache_req *cr, - return true; - } - -+static bool -+cache_req_validate_domain_type(struct cache_req *cr, -+ struct sss_domain_info *domain) -+{ -+ bool valid = false; -+ -+ switch (cr->req_dom_type) { -+ case CACHE_REQ_POSIX_DOM: -+ valid = domain->type == DOM_TYPE_POSIX ? true : false; -+ break; -+ case CACHE_REQ_APPLICATION_DOM: -+ valid = domain->type == DOM_TYPE_APPLICATION ? true : false; -+ break; -+ case CACHE_REQ_ANY_DOM: -+ valid = true; -+ break; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Request type %s for domain %s type %s is %svalid\n", -+ cache_req_dom_type_as_str(cr), -+ domain->name, -+ sss_domain_type_str(domain), -+ valid ? "" : "not "); -+ return valid; -+} -+ -+static bool -+cache_req_validate_domain(struct cache_req *cr, -+ struct sss_domain_info *domain) -+{ -+ bool ok; -+ -+ ok = cache_req_validate_domain_enumeration(cr, domain); -+ if (ok == false) { -+ return false; -+ } -+ -+ ok = cache_req_validate_domain_type(cr, domain); -+ if (ok == false) { -+ return false; -+ } -+ -+ return true; -+} -+ - static errno_t - cache_req_is_well_known_object(TALLOC_CTX *mem_ctx, - struct cache_req *cr, -@@ -651,6 +717,7 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int midpoint, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - struct cache_req_data *data) - { -@@ -667,7 +734,8 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx, - } - - state->ev = ev; -- state->cr = cr = cache_req_create(state, rctx, data, ncache, midpoint); -+ state->cr = cr = cache_req_create(state, rctx, data, -+ ncache, midpoint, req_dom_type); - if (state->cr == NULL) { - ret = ENOMEM; - goto done; -@@ -952,13 +1020,15 @@ cache_req_steal_data_and_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - struct cache_req_data *data) - { - struct tevent_req *req; - - req = cache_req_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ req_dom_type, domain, data); - if (req == NULL) { - talloc_zfree(data); - return NULL; -diff --git a/src/responder/common/cache_req/cache_req.h b/src/responder/common/cache_req/cache_req.h -index d0e5ff43921467fc191fd5cc7d5b49cc039b7f67..c04b2fba6f0445dcfcc9cfe1b5963ac975c39118 100644 ---- a/src/responder/common/cache_req/cache_req.h -+++ b/src/responder/common/cache_req/cache_req.h -@@ -57,6 +57,18 @@ enum cache_req_type { - CACHE_REQ_SENTINEL - }; - -+/* Whether to limit the request type to a certain domain type -+ * (POSIX/non-POSIX) -+ */ -+enum cache_req_dom_type { -+ /* Only look up data in POSIX domains */ -+ CACHE_REQ_POSIX_DOM, -+ /* Only look up data in application domains */ -+ CACHE_REQ_APPLICATION_DOM, -+ /* Look up data in any domain type */ -+ CACHE_REQ_ANY_DOM -+}; -+ - /* Input data. */ - - struct cache_req_data; -@@ -172,6 +184,7 @@ struct tevent_req *cache_req_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int midpoint, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - struct cache_req_data *data); - -@@ -191,6 +204,7 @@ cache_req_user_by_name_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *name); - -@@ -228,6 +242,7 @@ cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *pem_cert); - -@@ -240,6 +255,7 @@ cache_req_group_by_name_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *name); - -@@ -264,6 +280,7 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *name); - -@@ -274,6 +291,7 @@ struct tevent_req * - cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct resp_ctx *rctx, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *filter); - -@@ -284,6 +302,7 @@ struct tevent_req * - cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct resp_ctx *rctx, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *filter); - -diff --git a/src/responder/common/cache_req/cache_req_private.h b/src/responder/common/cache_req/cache_req_private.h -index 2d3c1870795e4fd5667f603280edcee24f926220..851005c389f994b1bd2d04cda9b68df8b18492cc 100644 ---- a/src/responder/common/cache_req/cache_req_private.h -+++ b/src/responder/common/cache_req/cache_req_private.h -@@ -42,6 +42,8 @@ struct cache_req { - struct sss_domain_info *domain; - bool cache_first; - bool bypass_cache; -+ /* Only contact domains with this type */ -+ enum cache_req_dom_type req_dom_type; - - /* Debug information */ - uint32_t reqid; -@@ -108,6 +110,7 @@ cache_req_steal_data_and_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - struct cache_req_data *data); - -diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_groups.c b/src/responder/common/cache_req/plugins/cache_req_enum_groups.c -index dbb40c98339cc9295e3678e05340396aff51ac78..49ce3508e678862e4389657187b9659ce90fbd1c 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_enum_groups.c -+++ b/src/responder/common/cache_req/plugins/cache_req_enum_groups.c -@@ -96,5 +96,7 @@ cache_req_enum_groups_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_svc.c b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c -index 28dea33c601f500b9c7af0de3eb9e1c342f03522..499b994738d62707b4e86d5a8383e3e2b82e8c57 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_enum_svc.c -+++ b/src/responder/common/cache_req/plugins/cache_req_enum_svc.c -@@ -97,5 +97,6 @@ cache_req_enum_svc_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_users.c b/src/responder/common/cache_req/plugins/cache_req_enum_users.c -index 3b1a85841e3ed853cd329dfa9d762cb7a05cbd43..b635354be6e9d2e2e2af1a6f867ac68e6cf7f085 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_enum_users.c -+++ b/src/responder/common/cache_req/plugins/cache_req_enum_users.c -@@ -96,5 +96,7 @@ cache_req_enum_users_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c -index 6ce6ae0d63967ac50b813a47ac938251619948da..4377a476c36e5e03c8533bc62335b84fa1cee3ff 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c -+++ b/src/responder/common/cache_req/plugins/cache_req_group_by_filter.c -@@ -140,6 +140,7 @@ struct tevent_req * - cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct resp_ctx *rctx, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *filter) - { -@@ -151,5 +152,7 @@ cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, NULL, -- 0, domain, data); -+ 0, -+ req_dom_type, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_id.c b/src/responder/common/cache_req/plugins/cache_req_group_by_id.c -index e98f76f8cd20742b81ae247df61db159d2584a17..ad5b7d890a42f29b586ab8e0943fef3dfab1162d 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_group_by_id.c -+++ b/src/responder/common/cache_req/plugins/cache_req_group_by_id.c -@@ -166,5 +166,7 @@ cache_req_group_by_id_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_group_by_name.c b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c -index af6f23ccfd68f952027462ba3e74ed7219d04651..de1e8f9442273acf386a2278b06f28ee63a7e3c6 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_group_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_group_by_name.c -@@ -205,6 +205,7 @@ cache_req_group_by_name_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *name) - { -@@ -216,5 +217,7 @@ cache_req_group_by_name_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ req_dom_type, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_host_by_name.c b/src/responder/common/cache_req/plugins/cache_req_host_by_name.c -index 77b46831fec3abc4126ef9d9be67221469801094..1171cd63fac5cc1d36b31bf8a069f059705cae90 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_host_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_host_by_name.c -@@ -117,5 +117,7 @@ cache_req_host_by_name_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c -index 307b65a24282838b99c472b50a71f06865aed3f0..f100aefe5c92279cde7e3209c7f48f5e2b35f135 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_initgroups_by_name.c -@@ -220,6 +220,7 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *name) - { -@@ -231,5 +232,7 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ req_dom_type, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c -index e49d6d84a41ce8dabf18c87373826f8e7b684bda..ab3e553d3ecb8ae09094dcfc938ed0ac01925327 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_netgroup_by_name.c -@@ -150,5 +150,7 @@ cache_req_netgroup_by_name_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_id.c b/src/responder/common/cache_req/plugins/cache_req_object_by_id.c -index 046e313c83d1d4c75237b047be779201b8a5d3c0..9557bd15270b2eb1a0671f9ef91033efac29c3ac 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_object_by_id.c -+++ b/src/responder/common/cache_req/plugins/cache_req_object_by_id.c -@@ -134,5 +134,7 @@ cache_req_object_by_id_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c -index 74d2b3dea287e890b38e4d5bb176ad2dc6337b7e..e236d1fa4aadcd87b192d34ebaf5f9ad8908b6c2 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c -@@ -228,5 +228,7 @@ cache_req_object_by_name_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_sid.c b/src/responder/common/cache_req/plugins/cache_req_object_by_sid.c -index ab577663111cfd424e7f46308b2621af7f1ca264..dfec79da07d669165205a767cab22c2254686134 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_object_by_sid.c -+++ b/src/responder/common/cache_req/plugins/cache_req_object_by_sid.c -@@ -143,5 +143,7 @@ cache_req_object_by_sid_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c -index ef13f097a8ae78ec9db5b7f6e14924b511578b34..b2bfb26ffed1a60ed8389fa89b0e728c8c6cf76c 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_name.c -@@ -175,5 +175,7 @@ cache_req_svc_by_name_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c -index afa2eeeda12794de26e798aee4b88900bc87ed93..0e48437f4b64d26112be88af1eebc20f012b70fd 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c -+++ b/src/responder/common/cache_req/plugins/cache_req_svc_by_port.c -@@ -149,5 +149,7 @@ cache_req_svc_by_port_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_cert.c b/src/responder/common/cache_req/plugins/cache_req_user_by_cert.c -index f237c8d0fe3faf5aea553480f3f92eb279209a20..286a34db276e0098060982c572e2a68ceceebf60 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_user_by_cert.c -+++ b/src/responder/common/cache_req/plugins/cache_req_user_by_cert.c -@@ -105,6 +105,7 @@ cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *pem_cert) - { -@@ -117,5 +118,6 @@ cache_req_user_by_cert_send(TALLOC_CTX *mem_ctx, - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, - cache_refresh_percent, -- domain, data); -+ req_dom_type, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c -index eb71b42dad3a805298df0c8425409d571befb31b..c476814373cd784bf8dbbea1da7b010afe5bb4e4 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c -+++ b/src/responder/common/cache_req/plugins/cache_req_user_by_filter.c -@@ -140,6 +140,7 @@ struct tevent_req * - cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct resp_ctx *rctx, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *filter) - { -@@ -151,5 +152,7 @@ cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, NULL, -- 0, domain, data); -+ 0, -+ req_dom_type, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_id.c b/src/responder/common/cache_req/plugins/cache_req_user_by_id.c -index fa783714b7c67ca029d18a223b64a3a69e3e6929..9ba73292e5dc518e86c6e00e7e493d6871f28e70 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_user_by_id.c -+++ b/src/responder/common/cache_req/plugins/cache_req_user_by_id.c -@@ -166,5 +166,7 @@ cache_req_user_by_id_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_name.c b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c -index 0670febdce2d51e0373045570dd07f56255db7bc..15da7d0d20b1ac97511a226daecc8ef7e7d2e7e4 100644 ---- a/src/responder/common/cache_req/plugins/cache_req_user_by_name.c -+++ b/src/responder/common/cache_req/plugins/cache_req_user_by_name.c -@@ -210,6 +210,7 @@ cache_req_user_by_name_send(TALLOC_CTX *mem_ctx, - struct resp_ctx *rctx, - struct sss_nc_ctx *ncache, - int cache_refresh_percent, -+ enum cache_req_dom_type req_dom_type, - const char *domain, - const char *name) - { -@@ -221,7 +222,9 @@ cache_req_user_by_name_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ req_dom_type, domain, -+ data); - } - - struct tevent_req * -@@ -243,5 +246,7 @@ cache_req_user_by_name_attrs_send(TALLOC_CTX *mem_ctx, - } - - return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, -- cache_refresh_percent, domain, data); -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, domain, -+ data); - } -diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c -index 94d1e84cc9de75727d3c47c0a5a24790d21ce132..99908e96bd971bce4b4e9064a77d8413f837d743 100644 ---- a/src/responder/ifp/ifp_groups.c -+++ b/src/responder/ifp/ifp_groups.c -@@ -118,7 +118,9 @@ int ifp_groups_find_by_name(struct sbus_request *sbus_req, - } - - req = cache_req_group_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, -- ctx->rctx->ncache, 0, NULL, name); -+ ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, NULL, -+ name); - if (req == NULL) { - return ENOMEM; - } -@@ -271,6 +273,7 @@ static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx) - req = cache_req_group_by_filter_send(list_ctx, - list_ctx->ctx->rctx->ev, - list_ctx->ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -355,7 +358,8 @@ int ifp_groups_list_by_domain_and_name(struct sbus_request *sbus_req, - } - - req = cache_req_group_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx, -- domain, filter); -+ CACHE_REQ_POSIX_DOM, -+ domain, filter); - if (req == NULL) { - return ENOMEM; - } -@@ -522,7 +526,10 @@ static struct tevent_req *resolv_ghosts_send(TALLOC_CTX *mem_ctx, - } - - subreq = cache_req_group_by_name_send(state, ev, ctx->rctx, -- ctx->rctx->ncache, 0, domain->name, name); -+ ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, -+ domain->name, -+ name); - if (subreq == NULL) { - ret = ENOMEM; - goto immediately; -@@ -601,6 +608,7 @@ errno_t resolv_ghosts_step(struct tevent_req *req) - - subreq = cache_req_user_by_name_send(state, state->ev, state->ctx->rctx, - state->ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, - state->domain->name, - state->ghosts[state->index]); - if (subreq == NULL) { -diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c -index cc78300f31e863fcb5366e18a14abc597c6f7ddb..436bb268fa9c78d72fb744e0d338aa561a7d8764 100644 ---- a/src/responder/ifp/ifp_users.c -+++ b/src/responder/ifp/ifp_users.c -@@ -99,7 +99,9 @@ int ifp_users_find_by_name(struct sbus_request *sbus_req, - } - - req = cache_req_user_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, -- ctx->rctx->ncache, 0, NULL, name); -+ ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, -+ NULL, name); - if (req == NULL) { - return ENOMEM; - } -@@ -253,7 +255,9 @@ int ifp_users_find_by_cert(struct sbus_request *sbus_req, void *data, - } - - req = cache_req_user_by_cert_send(sbus_req, ctx->rctx->ev, ctx->rctx, -- ctx->rctx->ncache, 0, NULL, derb64); -+ ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, NULL, -+ derb64); - if (req == NULL) { - return ENOMEM; - } -@@ -367,6 +371,7 @@ static int ifp_users_list_by_cert_step(struct ifp_list_ctx *list_ctx) - list_ctx->ctx->rctx, - list_ctx->ctx->rctx->ncache, - 0, -+ CACHE_REQ_POSIX_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -532,7 +537,9 @@ int ifp_users_find_by_name_and_cert(struct sbus_request *sbus_req, void *data, - - if (name_and_cert_ctx->name != NULL) { - req = cache_req_user_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, -- ctx->rctx->ncache, 0, NULL, -+ ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, -+ NULL, - name_and_cert_ctx->name); - if (req == NULL) { - return ENOMEM; -@@ -614,6 +621,7 @@ static int ifp_users_find_by_name_and_cert_step( - list_ctx->ctx->rctx, - list_ctx->ctx->rctx->ncache, - 0, -+ CACHE_REQ_POSIX_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -774,6 +782,7 @@ static int ifp_users_list_by_name_step(struct ifp_list_ctx *list_ctx) - req = cache_req_user_by_filter_send(list_ctx, - list_ctx->ctx->rctx->ev, - list_ctx->ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -858,6 +867,7 @@ int ifp_users_list_by_domain_and_name(struct sbus_request *sbus_req, - } - - req = cache_req_user_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - domain, filter); - if (req == NULL) { - return ENOMEM; -@@ -1102,7 +1112,8 @@ int ifp_users_user_update_groups_list(struct sbus_request *sbus_req, - } - - req = cache_req_initgr_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, -- ctx->rctx->ncache, 0, domain->name, -+ ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, domain->name, - username); - if (req == NULL) { - return ENOMEM; -diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c -index 07edcddffa1091f8bbcf79a25962aadc791bb890..118b5083b14bf5692c6fdd7ba90668fe514aa89d 100644 ---- a/src/responder/ifp/ifpsrv_cmd.c -+++ b/src/responder/ifp/ifpsrv_cmd.c -@@ -509,7 +509,8 @@ ifp_user_get_attr_lookup(struct tevent_req *subreq) - } - - subreq = cache_req_send(state, state->rctx->ev, state->rctx, -- state->ncache, 0, state->domname, data); -+ state->ncache, 0, CACHE_REQ_POSIX_DOM, -+ state->domname, data); - if (subreq == NULL) { - tevent_req_error(req, ENOMEM); - return; -diff --git a/src/responder/nss/nss_enum.c b/src/responder/nss/nss_enum.c -index b1cce2cde43ece735285c132d0127c142ee83cb0..aa7d8428f37e943a6b5904495c40ad4b8011b767 100644 ---- a/src/responder/nss/nss_enum.c -+++ b/src/responder/nss/nss_enum.c -@@ -93,7 +93,7 @@ nss_setent_internal_send(TALLOC_CTX *mem_ctx, - /* Create new object. */ - state->enum_ctx->is_ready = false; - subreq = cache_req_send(req, ev, cli_ctx->rctx, cli_ctx->rctx->ncache, -- 0, NULL, data); -+ 0, CACHE_REQ_POSIX_DOM, NULL, data); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send cache request!\n"); - ret = ENOMEM; -diff --git a/src/responder/nss/nss_get_object.c b/src/responder/nss/nss_get_object.c -index f83dd393c0e333d8914802e005672a15a51d5939..9058793ea2d72b57003a7219414af6a0f0c5b89e 100644 ---- a/src/responder/nss/nss_get_object.c -+++ b/src/responder/nss/nss_get_object.c -@@ -190,7 +190,8 @@ nss_get_object_send(TALLOC_CTX *mem_ctx, - } - - subreq = cache_req_send(req, ev, cli_ctx->rctx, cli_ctx->rctx->ncache, -- state->nss_ctx->cache_refresh_percent, NULL, data); -+ state->nss_ctx->cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, NULL, data); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send cache request!\n"); - ret = ENOMEM; -diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c -index ba2563c11885ff39681c2ef432acaedf26702b64..fa6d2cc10fe1404196f9d9221a469d7a9a768211 100644 ---- a/src/responder/pam/pamsrv_cmd.c -+++ b/src/responder/pam/pamsrv_cmd.c -@@ -1315,7 +1315,9 @@ static void pam_forwarder_cert_cb(struct tevent_req *req) - - - req = cache_req_user_by_cert_send(preq, cctx->ev, cctx->rctx, -- pctx->rctx->ncache, 0, NULL, cert); -+ pctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, NULL, -+ cert); - if (req == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n"); - ret = ENOMEM; -@@ -1507,6 +1509,7 @@ static int pam_check_user_search(struct pam_auth_req *preq) - preq->cctx->rctx, - preq->cctx->rctx->ncache, - 0, -+ CACHE_REQ_POSIX_DOM, - preq->pd->domain, - data); - if (!dpreq) { -diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c -index 52dfd5c709e48f0d4610a4b384962fbc2869312b..cfdbfc9c9c66d96f774822d6a4d4aaaf1327abe3 100644 ---- a/src/responder/sudo/sudosrv_get_sudorules.c -+++ b/src/responder/sudo/sudosrv_get_sudorules.c -@@ -644,7 +644,8 @@ struct tevent_req *sudosrv_get_rules_send(TALLOC_CTX *mem_ctx, - DEBUG(SSSDBG_TRACE_FUNC, "Running initgroups for [%s]\n", username); - - subreq = cache_req_initgr_by_name_send(state, ev, sudo_ctx->rctx, -- sudo_ctx->rctx->ncache, 0, NULL, -+ sudo_ctx->rctx->ncache, 0, -+ CACHE_REQ_POSIX_DOM, NULL, - username); - if (subreq == NULL) { - ret = ENOMEM; -diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c -index 5f1e5350eaf1d85de376c94731f0bd678f884a1d..80086232fd437876c2b190fb972c2ee3194d9efd 100644 ---- a/src/tests/cmocka/test_responder_cache_req.c -+++ b/src/tests/cmocka/test_responder_cache_req.c -@@ -84,6 +84,28 @@ struct test_group { - talloc_free(req_mem_ctx); \ - } while (0) - -+#define run_cache_req_domtype(ctx, send_fn, done_fn, dom, crp, domtype, lookup, expret) do { \ -+ TALLOC_CTX *req_mem_ctx; \ -+ struct tevent_req *req; \ -+ errno_t ret; \ -+ \ -+ req_mem_ctx = talloc_new(global_talloc_context); \ -+ check_leaks_push(req_mem_ctx); \ -+ \ -+ req = send_fn(req_mem_ctx, ctx->tctx->ev, ctx->rctx, \ -+ ctx->ncache, crp, \ -+ domtype, \ -+ (dom == NULL ? NULL : dom->name), lookup); \ -+ assert_non_null(req); \ -+ tevent_req_set_callback(req, done_fn, ctx); \ -+ \ -+ ret = test_ev_loop(ctx->tctx); \ -+ assert_int_equal(ret, expret); \ -+ assert_true(check_leaks_pop(req_mem_ctx)); \ -+ \ -+ talloc_free(req_mem_ctx); \ -+} while (0) -+ - struct cache_req_test_ctx { - struct sss_test_ctx *tctx; - struct resp_ctx *rctx; -@@ -211,9 +233,11 @@ static void run_user_by_name(struct cache_req_test_ctx *test_ctx, - int cache_refresh_percent, - errno_t exp_ret) - { -- run_cache_req(test_ctx, cache_req_user_by_name_send, -- cache_req_user_by_name_test_done, domain, -- cache_refresh_percent, users[0].short_name, exp_ret); -+ run_cache_req_domtype(test_ctx, cache_req_user_by_name_send, -+ cache_req_user_by_name_test_done, domain, -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, -+ users[0].short_name, exp_ret); - } - - static void run_user_by_upn(struct cache_req_test_ctx *test_ctx, -@@ -221,9 +245,11 @@ static void run_user_by_upn(struct cache_req_test_ctx *test_ctx, - int cache_refresh_percent, - errno_t exp_ret) - { -- run_cache_req(test_ctx, cache_req_user_by_name_send, -- cache_req_user_by_name_test_done, domain, -- cache_refresh_percent, users[0].upn, exp_ret); -+ run_cache_req_domtype(test_ctx, cache_req_user_by_name_send, -+ cache_req_user_by_name_test_done, domain, -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, -+ users[0].upn, exp_ret); - } - - static void run_user_by_id(struct cache_req_test_ctx *test_ctx, -@@ -318,9 +344,11 @@ static void run_group_by_name(struct cache_req_test_ctx *test_ctx, - int cache_refresh_percent, - errno_t exp_ret) - { -- run_cache_req(test_ctx, cache_req_group_by_name_send, -- cache_req_group_by_name_test_done, domain, -- cache_refresh_percent, groups[0].short_name, exp_ret); -+ run_cache_req_domtype(test_ctx, cache_req_group_by_name_send, -+ cache_req_group_by_name_test_done, domain, -+ cache_refresh_percent, -+ CACHE_REQ_POSIX_DOM, -+ groups[0].short_name, exp_ret); - } - - static void run_group_by_id(struct cache_req_test_ctx *test_ctx, -@@ -605,7 +633,9 @@ void test_user_by_name_multiple_domains_parse(void **state) - check_leaks_push(req_mem_ctx); - - req = cache_req_user_by_name_send(req_mem_ctx, test_ctx->tctx->ev, -- test_ctx->rctx, test_ctx->ncache, 0, -+ test_ctx->rctx, test_ctx->ncache, -+ CACHE_REQ_POSIX_DOM, -+ 0, - NULL, input_fqn); - assert_non_null(req); - tevent_req_set_callback(req, cache_req_user_by_name_test_done, test_ctx); -@@ -1119,7 +1149,8 @@ void test_group_by_name_multiple_domains_parse(void **state) - - req = cache_req_group_by_name_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, test_ctx->ncache, 0, -- NULL, input_fqn); -+ CACHE_REQ_POSIX_DOM, NULL, -+ input_fqn); - assert_non_null(req); - tevent_req_set_callback(req, cache_req_group_by_name_test_done, test_ctx); - -@@ -1421,6 +1452,7 @@ void test_user_by_recent_filter_valid(void **state) - /* User TEST_USER is created with a DP callback. */ - req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - test_ctx->tctx->dom->name, - TEST_USER_PREFIX); - assert_non_null(req); -@@ -1463,6 +1495,7 @@ void test_users_by_recent_filter_valid(void **state) - /* User TEST_USER1 and TEST_USER2 are created with a DP callback. */ - req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - test_ctx->tctx->dom->name, - TEST_USER_PREFIX); - assert_non_null(req); -@@ -1524,6 +1557,7 @@ void test_users_by_filter_filter_old(void **state) - - req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - test_ctx->tctx->dom->name, - TEST_USER_PREFIX); - assert_non_null(req); -@@ -1559,6 +1593,7 @@ void test_users_by_filter_notfound(void **state) - - req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - test_ctx->tctx->dom->name, - "nosuchuser*"); - assert_non_null(req); -@@ -1592,6 +1627,7 @@ static void test_users_by_filter_multiple_domains_notfound(void **state) - - req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - domain->name, - "nosuchuser*"); - assert_non_null(req); -@@ -1636,6 +1672,7 @@ void test_group_by_recent_filter_valid(void **state) - /* Group TEST_GROUP is created with a DP callback. */ - req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - test_ctx->tctx->dom->name, - TEST_USER_PREFIX); - assert_non_null(req); -@@ -1680,6 +1717,7 @@ void test_groups_by_recent_filter_valid(void **state) - /* Group TEST_GROUP1 and TEST_GROUP2 are created with a DP callback. */ - req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - test_ctx->tctx->dom->name, - TEST_USER_PREFIX); - assert_non_null(req); -@@ -1738,6 +1776,7 @@ void test_groups_by_filter_notfound(void **state) - - req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - test_ctx->tctx->dom->name, - "nosuchgroup*"); - assert_non_null(req); -@@ -1770,6 +1809,7 @@ void test_groups_by_filter_multiple_domains_notfound(void **state) - - req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, - test_ctx->rctx, -+ CACHE_REQ_POSIX_DOM, - domain->name, - "nosuchgroup*"); - assert_non_null(req); --- -2.12.2 - diff --git a/0067-IFP-Search-both-POSIX-and-non-POSIX-domains.patch b/0067-IFP-Search-both-POSIX-and-non-POSIX-domains.patch deleted file mode 100644 index 5732fd0..0000000 --- a/0067-IFP-Search-both-POSIX-and-non-POSIX-domains.patch +++ /dev/null @@ -1,705 +0,0 @@ -From 35f0f5ff9dac790f6c947190fcdc00d01ae9077c Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 24 Mar 2017 12:44:09 +0100 -Subject: [PATCH 67/97] IFP: Search both POSIX and non-POSIX domains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -Changes the behaviour of the InfoPipe responder so that both application -and POSIX domains are searched. In general, the IFP responder uses the -CACHE_REQ_ANY_DOM lookup type because we can't presume the intention of -the caller. Therefore, deployments that combine both POSIX and non-POSIX -domains must use fully qualified names or select the right domain order -manually. - -There is one change between the POSIX and non-POSIX users or groups - -the object path. For the POSIX users, the object path includes the UID -or GID. Because we don't have that for the non-POSIX objects, the object -name is used in the path instead. - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina ---- - src/responder/ifp/ifp_groups.c | 135 ++++++++++++++++++++++------------- - src/responder/ifp/ifp_users.c | 158 ++++++++++++++++++++++++++--------------- - src/responder/ifp/ifpsrv_cmd.c | 6 +- - 3 files changed, 194 insertions(+), 105 deletions(-) - -diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c -index 99908e96bd971bce4b4e9064a77d8413f837d743..c568c62009cd4b777919dea048fd381a91bd3460 100644 ---- a/src/responder/ifp/ifp_groups.c -+++ b/src/responder/ifp/ifp_groups.c -@@ -35,25 +35,33 @@ char * ifp_groups_build_path_from_msg(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_message *msg) - { -- const char *gid; -+ const char *key = NULL; - -- gid = ldb_msg_find_attr_as_string(msg, SYSDB_GIDNUM, NULL); -+ switch (domain->type) { -+ case DOM_TYPE_APPLICATION: -+ key = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -+ break; -+ case DOM_TYPE_POSIX: -+ key = ldb_msg_find_attr_as_string(msg, SYSDB_GIDNUM, NULL); -+ break; -+ } - -- if (gid == NULL) { -+ -+ if (key == NULL) { - return NULL; - } - -- return sbus_opath_compose(mem_ctx, IFP_PATH_GROUPS, domain->name, gid); -+ return sbus_opath_compose(mem_ctx, IFP_PATH_GROUPS, domain->name, key); - } - --static errno_t ifp_groups_decompose_path(struct sss_domain_info *domains, -+static errno_t ifp_groups_decompose_path(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, - const char *path, - struct sss_domain_info **_domain, -- gid_t *_gid) -+ char **_key) - { - char **parts = NULL; - struct sss_domain_info *domain; -- gid_t gid; - errno_t ret; - - ret = sbus_opath_decompose_exact(NULL, path, IFP_PATH_GROUPS, 2, &parts); -@@ -67,14 +75,8 @@ static errno_t ifp_groups_decompose_path(struct sss_domain_info *domains, - goto done; - } - -- gid = strtouint32(parts[1], NULL, 10); -- ret = errno; -- if (ret != EOK) { -- goto done; -- } -- - *_domain = domain; -- *_gid = gid; -+ *_key = talloc_steal(mem_ctx, parts[1]); - - done: - talloc_free(parts); -@@ -119,7 +121,7 @@ int ifp_groups_find_by_name(struct sbus_request *sbus_req, - - req = cache_req_group_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, - ctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, NULL, -+ CACHE_REQ_ANY_DOM, NULL, - name); - if (req == NULL) { - return ENOMEM; -@@ -273,7 +275,7 @@ static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx) - req = cache_req_group_by_filter_send(list_ctx, - list_ctx->ctx->rctx->ev, - list_ctx->ctx->rctx, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -358,7 +360,7 @@ int ifp_groups_list_by_domain_and_name(struct sbus_request *sbus_req, - } - - req = cache_req_group_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - domain, filter); - if (req == NULL) { - return ENOMEM; -@@ -412,16 +414,65 @@ done: - } - - static errno_t -+ifp_groups_get_from_cache(struct sbus_request *sbus_req, -+ struct sss_domain_info *domain, -+ const char *key, -+ struct ldb_message **_group) -+{ -+ struct ldb_result *group_res; -+ errno_t ret; -+ gid_t gid; -+ -+ switch (domain->type) { -+ case DOM_TYPE_POSIX: -+ gid = strtouint32(key, NULL, 10); -+ ret = errno; -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid UID value\n"); -+ return ret; -+ } -+ -+ ret = sysdb_getgrgid_with_views(sbus_req, domain, gid, &group_res); -+ if (ret == EOK && group_res->count == 0) { -+ *_group = NULL; -+ return ENOENT; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup group %u@%s [%d]: %s\n", -+ gid, domain->name, ret, sss_strerror(ret)); -+ return ret; -+ } -+ break; -+ case DOM_TYPE_APPLICATION: -+ ret = sysdb_getgrnam_with_views(sbus_req, domain, key, &group_res); -+ if (ret == EOK && group_res->count == 0) { -+ *_group = NULL; -+ return ENOENT; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup group %s@%s [%d]: %s\n", -+ key, domain->name, ret, sss_strerror(ret)); -+ return ret; -+ } -+ break; -+ } -+ -+ if (group_res->count > 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "More groups matched by the single key\n"); -+ return EIO; -+ } -+ -+ *_group = group_res->msgs[0]; -+ return EOK; -+} -+ -+static errno_t - ifp_groups_group_get(struct sbus_request *sbus_req, - void *data, -- gid_t *_gid, - struct sss_domain_info **_domain, - struct ldb_message **_group) - { - struct ifp_ctx *ctx; - struct sss_domain_info *domain; -- struct ldb_result *res; -- uid_t gid; -+ char *key; - errno_t ret; - - ctx = talloc_get_type(data, struct ifp_ctx); -@@ -430,8 +481,9 @@ ifp_groups_group_get(struct sbus_request *sbus_req, - return ERR_INTERNAL; - } - -- ret = ifp_groups_decompose_path(ctx->rctx->domains, sbus_req->path, -- &domain, &gid); -+ ret = ifp_groups_decompose_path(sbus_req, -+ ctx->rctx->domains, sbus_req->path, -+ &domain, &key); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to decompose object path" - "[%s] [%d]: %s\n", sbus_req->path, ret, sss_strerror(ret)); -@@ -439,28 +491,15 @@ ifp_groups_group_get(struct sbus_request *sbus_req, - } - - if (_group != NULL) { -- ret = sysdb_getgrgid_with_views(sbus_req, domain, gid, &res); -- if (ret == EOK && res->count == 0) { -- *_group = NULL; -- ret = ENOENT; -- } -- -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup group %u@%s [%d]: %s\n", -- gid, domain->name, ret, sss_strerror(ret)); -- } else { -- *_group = res->msgs[0]; -- } -+ ret = ifp_groups_get_from_cache(sbus_req, domain, key, _group); - } - - if (ret == EOK || ret == ENOENT) { -- if (_gid != NULL) { -- *_gid = gid; -- } -- - if (_domain != NULL) { - *_domain = domain; - } -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve group from cache\n"); - } - - return ret; -@@ -513,7 +552,7 @@ static struct tevent_req *resolv_ghosts_send(TALLOC_CTX *mem_ctx, - state->ctx = ctx; - state->data = data; - -- ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group); -+ ret = ifp_groups_group_get(sbus_req, data, &domain, &group); - if (ret != EOK) { - goto immediately; - } -@@ -527,7 +566,7 @@ static struct tevent_req *resolv_ghosts_send(TALLOC_CTX *mem_ctx, - - subreq = cache_req_group_by_name_send(state, ev, ctx->rctx, - ctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - domain->name, - name); - if (subreq == NULL) { -@@ -561,7 +600,7 @@ static void resolv_ghosts_group_done(struct tevent_req *subreq) - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct resolv_ghosts_state); - -- ret = ifp_groups_group_get(state->sbus_req, state->data, NULL, -+ ret = ifp_groups_group_get(state->sbus_req, state->data, - &state->domain, &group); - if (ret != EOK) { - goto done; -@@ -608,7 +647,7 @@ errno_t resolv_ghosts_step(struct tevent_req *req) - - subreq = cache_req_user_by_name_send(state, state->ev, state->ctx->rctx, - state->ctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - state->domain->name, - state->ghosts[state->index]); - if (subreq == NULL) { -@@ -719,7 +758,7 @@ void ifp_groups_group_get_name(struct sbus_request *sbus_req, - return; - } - -- ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &msg); -+ ret = ifp_groups_group_get(sbus_req, data, &domain, &msg); - if (ret != EOK) { - *_out = NULL; - return; -@@ -744,7 +783,7 @@ void ifp_groups_group_get_gid_number(struct sbus_request *sbus_req, - struct sss_domain_info *domain; - errno_t ret; - -- ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &msg); -+ ret = ifp_groups_group_get(sbus_req, data, &domain, &msg); - if (ret != EOK) { - *_out = 0; - return; -@@ -763,7 +802,7 @@ void ifp_groups_group_get_unique_id(struct sbus_request *sbus_req, - struct sss_domain_info *domain; - errno_t ret; - -- ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &msg); -+ ret = ifp_groups_group_get(sbus_req, data, &domain, &msg); - if (ret != EOK) { - *_out = 0; - return; -@@ -803,7 +842,7 @@ ifp_groups_group_get_members(TALLOC_CTX *mem_ctx, - return ENOMEM; - } - -- ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group); -+ ret = ifp_groups_group_get(sbus_req, data, &domain, &group); - if (ret != EOK) { - goto done; - } -@@ -954,7 +993,7 @@ int ifp_cache_object_store_group(struct sbus_request *sbus_req, - struct ldb_message *group; - errno_t ret; - -- ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group); -+ ret = ifp_groups_group_get(sbus_req, data, &domain, &group); - if (ret != EOK) { - error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " - "group [%d]: %s\n", ret, sss_strerror(ret)); -@@ -973,7 +1012,7 @@ int ifp_cache_object_remove_group(struct sbus_request *sbus_req, - struct ldb_message *group; - errno_t ret; - -- ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group); -+ ret = ifp_groups_group_get(sbus_req, data, &domain, &group); - if (ret != EOK) { - error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " - "group [%d]: %s\n", ret, sss_strerror(ret)); -diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c -index 436bb268fa9c78d72fb744e0d338aa561a7d8764..ce9557f94351b730ee46f3cbce31613cb5901942 100644 ---- a/src/responder/ifp/ifp_users.c -+++ b/src/responder/ifp/ifp_users.c -@@ -37,25 +37,33 @@ char * ifp_users_build_path_from_msg(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_message *msg) - { -- const char *uid; -+ const char *key = NULL; - -- uid = ldb_msg_find_attr_as_string(msg, SYSDB_UIDNUM, NULL); -+ switch (domain->type) { -+ case DOM_TYPE_APPLICATION: -+ key = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -+ break; -+ case DOM_TYPE_POSIX: -+ key = ldb_msg_find_attr_as_string(msg, SYSDB_UIDNUM, NULL); -+ break; -+ } - -- if (uid == NULL) { -+ -+ if (key == NULL) { - return NULL; - } - -- return sbus_opath_compose(mem_ctx, IFP_PATH_USERS, domain->name, uid); -+ return sbus_opath_compose(mem_ctx, IFP_PATH_USERS, domain->name, key); - } - --static errno_t ifp_users_decompose_path(struct sss_domain_info *domains, -+static errno_t ifp_users_decompose_path(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, - const char *path, - struct sss_domain_info **_domain, -- uid_t *_uid) -+ char **_key) - { - char **parts = NULL; - struct sss_domain_info *domain; -- uid_t uid; - errno_t ret; - - ret = sbus_opath_decompose_exact(NULL, path, IFP_PATH_USERS, 2, &parts); -@@ -69,14 +77,8 @@ static errno_t ifp_users_decompose_path(struct sss_domain_info *domains, - goto done; - } - -- uid = strtouint32(parts[1], NULL, 10); -- ret = errno; -- if (ret != EOK) { -- goto done; -- } -- - *_domain = domain; -- *_uid = uid; -+ *_key = talloc_steal(mem_ctx, parts[1]); - - done: - talloc_free(parts); -@@ -100,7 +102,7 @@ int ifp_users_find_by_name(struct sbus_request *sbus_req, - - req = cache_req_user_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, - ctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - NULL, name); - if (req == NULL) { - return ENOMEM; -@@ -256,7 +258,7 @@ int ifp_users_find_by_cert(struct sbus_request *sbus_req, void *data, - - req = cache_req_user_by_cert_send(sbus_req, ctx->rctx->ev, ctx->rctx, - ctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, NULL, -+ CACHE_REQ_ANY_DOM, NULL, - derb64); - if (req == NULL) { - return ENOMEM; -@@ -371,7 +373,7 @@ static int ifp_users_list_by_cert_step(struct ifp_list_ctx *list_ctx) - list_ctx->ctx->rctx, - list_ctx->ctx->rctx->ncache, - 0, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -538,7 +540,7 @@ int ifp_users_find_by_name_and_cert(struct sbus_request *sbus_req, void *data, - if (name_and_cert_ctx->name != NULL) { - req = cache_req_user_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, - ctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - NULL, - name_and_cert_ctx->name); - if (req == NULL) { -@@ -621,7 +623,7 @@ static int ifp_users_find_by_name_and_cert_step( - list_ctx->ctx->rctx, - list_ctx->ctx->rctx->ncache, - 0, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -782,7 +784,7 @@ static int ifp_users_list_by_name_step(struct ifp_list_ctx *list_ctx) - req = cache_req_user_by_filter_send(list_ctx, - list_ctx->ctx->rctx->ev, - list_ctx->ctx->rctx, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - list_ctx->dom->name, - list_ctx->filter); - if (req == NULL) { -@@ -867,7 +869,7 @@ int ifp_users_list_by_domain_and_name(struct sbus_request *sbus_req, - } - - req = cache_req_user_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx, -- CACHE_REQ_POSIX_DOM, -+ CACHE_REQ_ANY_DOM, - domain, filter); - if (req == NULL) { - return ENOMEM; -@@ -930,19 +932,69 @@ done: - } - - static errno_t -+ifp_users_get_from_cache(struct sbus_request *sbus_req, -+ struct sss_domain_info *domain, -+ const char *key, -+ struct ldb_message **_user) -+{ -+ struct ldb_result *user_res; -+ errno_t ret; -+ uid_t uid; -+ -+ switch (domain->type) { -+ case DOM_TYPE_POSIX: -+ uid = strtouint32(key, NULL, 10); -+ ret = errno; -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid UID value\n"); -+ return ret; -+ } -+ -+ ret = sysdb_getpwuid_with_views(sbus_req, domain, uid, &user_res); -+ if (ret == EOK && user_res->count == 0) { -+ *_user = NULL; -+ return ENOENT; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup user %u@%s [%d]: %s\n", -+ uid, domain->name, ret, sss_strerror(ret)); -+ return ret; -+ } -+ break; -+ case DOM_TYPE_APPLICATION: -+ ret = sysdb_getpwnam_with_views(sbus_req, domain, key, &user_res); -+ if (ret == EOK && user_res->count == 0) { -+ *_user = NULL; -+ return ENOENT; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup user %s@%s [%d]: %s\n", -+ key, domain->name, ret, sss_strerror(ret)); -+ return ret; -+ } -+ break; -+ } -+ -+ if (user_res->count > 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "More users matched by the single key\n"); -+ return EIO; -+ } -+ -+ *_user = user_res->msgs[0]; -+ return EOK; -+} -+ -+static errno_t - ifp_users_user_get(struct sbus_request *sbus_req, - struct ifp_ctx *ifp_ctx, -- uid_t *_uid, - struct sss_domain_info **_domain, - struct ldb_message **_user) - { - struct sss_domain_info *domain; -- struct ldb_result *res; -- uid_t uid; -+ char *key; - errno_t ret; - -- ret = ifp_users_decompose_path(ifp_ctx->rctx->domains, sbus_req->path, -- &domain, &uid); -+ ret = ifp_users_decompose_path(sbus_req, -+ ifp_ctx->rctx->domains, sbus_req->path, -+ &domain, &key); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to decompose object path" - "[%s] [%d]: %s\n", sbus_req->path, ret, sss_strerror(ret)); -@@ -950,28 +1002,15 @@ ifp_users_user_get(struct sbus_request *sbus_req, - } - - if (_user != NULL) { -- ret = sysdb_getpwuid_with_views(sbus_req, domain, uid, &res); -- if (ret == EOK && res->count == 0) { -- *_user = NULL; -- ret = ENOENT; -- } -- -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup user %u@%s [%d]: %s\n", -- uid, domain->name, ret, sss_strerror(ret)); -- } else { -- *_user = res->msgs[0]; -- } -+ ret = ifp_users_get_from_cache(sbus_req, domain, key, _user); - } - - if (ret == EOK || ret == ENOENT) { -- if (_uid != NULL) { -- *_uid = uid; -- } -- - if (_domain != NULL) { - *_domain = domain; - } -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve user from cache\n"); - } - - return ret; -@@ -1000,7 +1039,7 @@ static void ifp_users_get_as_string(struct sbus_request *sbus_req, - return; - } - -- ret = ifp_users_user_get(sbus_req, ifp_ctx, NULL, &domain, &msg); -+ ret = ifp_users_user_get(sbus_req, ifp_ctx, &domain, &msg); - if (ret != EOK) { - return; - } -@@ -1034,7 +1073,7 @@ static void ifp_users_get_name(struct sbus_request *sbus_req, - return; - } - -- ret = ifp_users_user_get(sbus_req, ifp_ctx, NULL, &domain, &msg); -+ ret = ifp_users_user_get(sbus_req, ifp_ctx, &domain, &msg); - if (ret != EOK) { - return; - } -@@ -1072,7 +1111,7 @@ static void ifp_users_get_as_uint32(struct sbus_request *sbus_req, - return; - } - -- ret = ifp_users_user_get(sbus_req, ifp_ctx, NULL, &domain, &msg); -+ ret = ifp_users_user_get(sbus_req, ifp_ctx, &domain, &msg); - if (ret != EOK) { - return; - } -@@ -1100,7 +1139,7 @@ int ifp_users_user_update_groups_list(struct sbus_request *sbus_req, - return ERR_INTERNAL; - } - -- ret = ifp_users_user_get(sbus_req, data, NULL, &domain, &user); -+ ret = ifp_users_user_get(sbus_req, data, &domain, &user); - if (ret != EOK) { - return ret; - } -@@ -1113,7 +1152,7 @@ int ifp_users_user_update_groups_list(struct sbus_request *sbus_req, - - req = cache_req_initgr_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx, - ctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, domain->name, -+ CACHE_REQ_ANY_DOM, domain->name, - username); - if (req == NULL) { - return ENOMEM; -@@ -1235,7 +1274,7 @@ void ifp_users_user_get_groups(struct sbus_request *sbus_req, - return; - } - -- ret = ifp_users_user_get(sbus_req, ifp_ctx, NULL, &domain, &user); -+ ret = ifp_users_user_get(sbus_req, ifp_ctx, &domain, &user); - if (ret != EOK) { - return; - } -@@ -1268,7 +1307,7 @@ void ifp_users_user_get_groups(struct sbus_request *sbus_req, - for (i = 0; i < res->count; i++) { - gid = sss_view_ldb_msg_find_attr_as_uint64(domain, res->msgs[i], - SYSDB_GIDNUM, 0); -- if (gid == 0) { -+ if (gid == 0 && domain->type == DOM_TYPE_POSIX) { - continue; - } - -@@ -1293,11 +1332,12 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req, - { - struct ifp_ctx *ifp_ctx; - struct sss_domain_info *domain; -+ struct ldb_message *base_user; -+ const char *name; - struct ldb_message **user; - struct ldb_message_element *el; - struct ldb_dn *basedn; - size_t count; -- uid_t uid; - const char *filter; - const char **extra; - hash_table_t *table; -@@ -1322,7 +1362,7 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req, - return; - } - -- ret = ifp_users_user_get(sbus_req, data, &uid, &domain, NULL); -+ ret = ifp_users_user_get(sbus_req, data, &domain, &base_user); - if (ret != EOK) { - return; - } -@@ -1333,9 +1373,15 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req, - return; - } - -- filter = talloc_asprintf(sbus_req, "(&(%s=%s)(%s=%u))", -+ name = ldb_msg_find_attr_as_string(base_user, SYSDB_NAME, NULL); -+ if (name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name\n"); -+ return; -+ } -+ -+ filter = talloc_asprintf(sbus_req, "(&(%s=%s)(%s=%s))", - SYSDB_OBJECTCLASS, SYSDB_USER_CLASS, -- SYSDB_UIDNUM, uid); -+ SYSDB_NAME, name); - if (filter == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); - return; -@@ -1351,7 +1397,7 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req, - } - - if (count == 0) { -- DEBUG(SSSDBG_TRACE_FUNC, "User %u not found!\n", uid); -+ DEBUG(SSSDBG_TRACE_FUNC, "User %s not found!\n", name); - return; - } else if (count > 1) { - DEBUG(SSSDBG_CRIT_FAILURE, "More than one entry found!\n"); -@@ -1421,7 +1467,7 @@ int ifp_cache_object_store_user(struct sbus_request *sbus_req, - struct ldb_message *user; - errno_t ret; - -- ret = ifp_users_user_get(sbus_req, data, NULL, &domain, &user); -+ ret = ifp_users_user_get(sbus_req, data, &domain, &user); - if (ret != EOK) { - error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " - "user [%d]: %s\n", ret, sss_strerror(ret)); -@@ -1440,7 +1486,7 @@ int ifp_cache_object_remove_user(struct sbus_request *sbus_req, - struct ldb_message *user; - errno_t ret; - -- ret = ifp_users_user_get(sbus_req, data, NULL, &domain, &user); -+ ret = ifp_users_user_get(sbus_req, data, &domain, &user); - if (ret != EOK) { - error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " - "user [%d]: %s\n", ret, sss_strerror(ret)); -diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c -index 118b5083b14bf5692c6fdd7ba90668fe514aa89d..d10f35e41dbb1623a0b9de37a4c43363cbefc1a3 100644 ---- a/src/responder/ifp/ifpsrv_cmd.c -+++ b/src/responder/ifp/ifpsrv_cmd.c -@@ -508,8 +508,12 @@ ifp_user_get_attr_lookup(struct tevent_req *subreq) - return; - } - -+ /* IFP serves both POSIX and application domains. Requests that need -+ * to differentiate between the two must be qualified -+ */ - subreq = cache_req_send(state, state->rctx->ev, state->rctx, -- state->ncache, 0, CACHE_REQ_POSIX_DOM, -+ state->ncache, 0, -+ CACHE_REQ_ANY_DOM, - state->domname, data); - if (subreq == NULL) { - tevent_req_error(req, ENOMEM); --- -2.12.2 - diff --git a/0068-IFP-ListByName-Don-t-crash-when-no-results-are-found.patch b/0068-IFP-ListByName-Don-t-crash-when-no-results-are-found.patch deleted file mode 100644 index a468555..0000000 --- a/0068-IFP-ListByName-Don-t-crash-when-no-results-are-found.patch +++ /dev/null @@ -1,57 +0,0 @@ -From b010f24f4d96d15c5c85021bb4aa83db25cd3df5 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 28 Mar 2017 14:07:29 +0200 -Subject: [PATCH 68/97] IFP: ListByName: Don't crash when no results are found -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If no results were found using the List command, the results variable -was undefined which resulted in a crash. - -Instead, only copy the results of the cache_req lookup returns EOK and -we can presume that the results are valid. - -Reviewed-by: Pavel Březina -Reviewed-by: Sumit Bose ---- - src/responder/ifp/ifp_users.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c -index ce9557f94351b730ee46f3cbce31613cb5901942..188194f2ab356d0e67b0f26b003f3a9ce48e6acd 100644 ---- a/src/responder/ifp/ifp_users.c -+++ b/src/responder/ifp/ifp_users.c -@@ -801,7 +801,7 @@ static void ifp_users_list_by_name_done(struct tevent_req *req) - DBusError *error; - struct ifp_list_ctx *list_ctx; - struct sbus_request *sbus_req; -- struct cache_req_result *result; -+ struct cache_req_result *result = NULL; - errno_t ret; - - list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx); -@@ -816,12 +816,14 @@ static void ifp_users_list_by_name_done(struct tevent_req *req) - return; - } - -- ret = ifp_users_list_copy(list_ctx, result->ldb_result); -- if (ret != EOK) { -- error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -- "Failed to copy domain result"); -- sbus_request_fail_and_finish(sbus_req, error); -- return; -+ if (ret == EOK) { -+ ret = ifp_users_list_copy(list_ctx, result->ldb_result); -+ if (ret != EOK) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -+ "Failed to copy domain result"); -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } - } - - list_ctx->dom = get_next_domain(list_ctx->dom, SSS_GND_DESCEND); --- -2.12.2 - diff --git a/0069-PAM-Remove-unneeded-memory-context.patch b/0069-PAM-Remove-unneeded-memory-context.patch deleted file mode 100644 index 611f7b3..0000000 --- a/0069-PAM-Remove-unneeded-memory-context.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 57eeec5d735c7a3bbe58299fded97414626d85f1 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 24 Mar 2017 20:36:06 +0100 -Subject: [PATCH 69/97] PAM: Remove unneeded memory context - -Since we only store data into pam_ctx in get_public_domains(), it -doesn't make sense to allow passing a separate memory context. It is -always going to be pam_ctx, otherwise the memory hierarchy will cause -issues anyway. - -Reviewed-by: Sumit Bose ---- - src/responder/pam/pamsrv.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c -index 816f2293130ff8761ca94b4a42ca93063c11ea35..ab3f4545520f3fcb2492a6089a039c46f0fb847f 100644 ---- a/src/responder/pam/pamsrv.c -+++ b/src/responder/pam/pamsrv.c -@@ -122,7 +122,7 @@ done: - return ret; - } - --static errno_t get_public_domains(TALLOC_CTX *mem_ctx, struct pam_ctx *pctx) -+static errno_t get_public_domains(struct pam_ctx *pctx) - { - char *domains_str = NULL; - errno_t ret; -@@ -137,7 +137,7 @@ static errno_t get_public_domains(TALLOC_CTX *mem_ctx, struct pam_ctx *pctx) - - if (strcmp(domains_str, ALL_DOMAIMS_ARE_PUBLIC) == 0) { /* all */ - /* copy all domains */ -- ret = get_dom_names(mem_ctx, -+ ret = get_dom_names(pctx, - pctx->rctx->domains, - &pctx->public_domains, - &pctx->public_domains_count); -@@ -149,7 +149,7 @@ static errno_t get_public_domains(TALLOC_CTX *mem_ctx, struct pam_ctx *pctx) - pctx->public_domains = NULL; - pctx->public_domains_count = 0; - } else { -- ret = split_on_separator(mem_ctx, domains_str, ',', true, false, -+ ret = split_on_separator(pctx, domains_str, ',', true, false, - &pctx->public_domains, - &pctx->public_domains_count); - if (ret != EOK) { -@@ -212,7 +212,7 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = get_public_domains(pctx, pctx); -+ ret = get_public_domains(pctx); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "get_public_domains failed: %d:[%s].\n", - ret, sss_strerror(ret)); --- -2.12.2 - diff --git a/0070-PAM-Add-application-services.patch b/0070-PAM-Add-application-services.patch deleted file mode 100644 index 87d9875..0000000 --- a/0070-PAM-Add-application-services.patch +++ /dev/null @@ -1,452 +0,0 @@ -From 3e789aa0bd6b7bb6e62f91458b76753498030fb5 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Sun, 26 Mar 2017 18:28:41 +0200 -Subject: [PATCH 70/97] PAM: Add application services - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -Adds a new PAM responder option 'pam_app_services'. This option can hold -a list of PAM services that are allowed to contact the application -non-POSIX domains. These services are NOT allowed to contact any of the -POSIX domains. - -Reviewed-by: Sumit Bose ---- - src/confdb/confdb.h | 1 + - src/config/SSSDConfig/__init__.py.in | 1 + - src/config/cfg_rules.ini | 1 + - src/config/etc/sssd.api.conf | 1 + - src/man/sssd.conf.5.xml | 12 +++ - src/responder/pam/pamsrv.c | 33 +++++++ - src/responder/pam/pamsrv.h | 5 ++ - src/responder/pam/pamsrv_cmd.c | 26 +++++- - src/tests/cmocka/test_pam_srv.c | 167 ++++++++++++++++++++++++++++++++++- - 9 files changed, 241 insertions(+), 6 deletions(-) - -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index 5a8d377c312f641f544b1c7cf38826192462ea3c..8719c239362b371fcdb1b78956bcddde871f141b 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -129,6 +129,7 @@ - #define CONFDB_PAM_CERT_AUTH "pam_cert_auth" - #define CONFDB_PAM_CERT_DB_PATH "pam_cert_db_path" - #define CONFDB_PAM_P11_CHILD_TIMEOUT "p11_child_timeout" -+#define CONFDB_PAM_APP_SERVICES "pam_app_services" - - /* SUDO */ - #define CONFDB_SUDO_CONF_ENTRY "config/sudo" -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 070994bcd04604777019d264d12cb126d6638bfd..a29d51e0ddffc520107a309d862346fb4d4f5f80 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -102,6 +102,7 @@ option_strings = { - 'pam_cert_auth' : _('Allow certificate based/Smartcard authentication.'), - 'pam_cert_db_path' : _('Path to certificate databse with PKCS#11 modules.'), - 'p11_child_timeout' : _('How many seconds will pam_sss wait for p11_child to finish'), -+ 'pam_app_services' : _('Which PAM services are permitted to contact application domains'), - - # [sudo] - 'sudo_timed' : _('Whether to evaluate the time-based attributes in sudo rules'), -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 8fd2d2c5236246394353a88c50d1510bd6233f77..1a749db754cedd87f263f7ae596d6f8238bb4357 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -119,6 +119,7 @@ option = pam_account_locked_message - option = pam_cert_auth - option = pam_cert_db_path - option = p11_child_timeout -+option = pam_app_services - - [rule/allowed_sudo_options] - validator = ini_allowed_options -diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf -index a38b24208f89e4502e41625c540ea9958d5bbffe..a1a0c2992925a4c7df86832117eec2a0cf7894c9 100644 ---- a/src/config/etc/sssd.api.conf -+++ b/src/config/etc/sssd.api.conf -@@ -73,6 +73,7 @@ pam_account_locked_message = str, None, false - pam_cert_auth = bool, None, false - pam_cert_db_path = str, None, false - p11_child_timeout = int, None, false -+pam_app_services = str, None, false - - [sudo] - # sudo service -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 8294793c765bfa6bf481693c7d7f206950454681..c4e30396f16c40db37af2f56ac218b6e37201ef7 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -1325,6 +1325,18 @@ pam_account_locked_message = Account locked, please contact help desk. - - - -+ -+ pam_app_services (string) -+ -+ -+ Which PAM services are permitted to contact -+ domains of type application -+ -+ -+ Default: Not set -+ -+ -+ - - - -diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c -index ab3f4545520f3fcb2492a6089a039c46f0fb847f..79470823d18138da6ef9235e6336a3220ead1797 100644 ---- a/src/responder/pam/pamsrv.c -+++ b/src/responder/pam/pamsrv.c -@@ -166,6 +166,32 @@ done: - return ret; - } - -+static errno_t get_app_services(struct pam_ctx *pctx) -+{ -+ errno_t ret; -+ -+ ret = confdb_get_string_as_list(pctx->rctx->cdb, pctx, -+ CONFDB_PAM_CONF_ENTRY, -+ CONFDB_PAM_APP_SERVICES, -+ &pctx->app_services); -+ if (ret == ENOENT) { -+ pctx->app_services = talloc_zero_array(pctx, char *, 1); -+ if (pctx->app_services == NULL) { -+ return ENOMEM; -+ } -+ /* Allocating an empty array makes it easier for the consumer -+ * to iterate over it -+ */ -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot read "CONFDB_PAM_APP_SERVICES" [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ -+ return EOK; -+} -+ - static int pam_process_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct confdb_ctx *cdb, -@@ -219,6 +245,13 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, - goto done; - } - -+ ret = get_app_services(pctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "get_app_services failed: %d:[%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ - /* Enable automatic reconnection to the Data Provider */ - - /* FIXME: "retries" is too generic, either get it from a global config -diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h -index b3eb56441048ecdba82866a95f1d6d6d5e786c60..b569748fe2a2005cee5df34bef55e803175492a9 100644 ---- a/src/responder/pam/pamsrv.h -+++ b/src/responder/pam/pamsrv.h -@@ -26,6 +26,7 @@ - #include "util/util.h" - #include "sbus/sssd_dbus.h" - #include "responder/common/responder.h" -+#include "responder/common/cache_req/cache_req.h" - - struct pam_auth_req; - -@@ -42,6 +43,9 @@ struct pam_ctx { - char **public_domains; - int public_domains_count; - -+ /* What services are permitted to access application domains */ -+ char **app_services; -+ - bool cert_auth; - int p11_child_debug_fd; - char *nss_db; -@@ -54,6 +58,7 @@ struct pam_auth_dp_req { - struct pam_auth_req { - struct cli_ctx *cctx; - struct sss_domain_info *domain; -+ enum cache_req_dom_type req_dom_type; - - struct pam_data *pd; - -diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c -index fa6d2cc10fe1404196f9d9221a469d7a9a768211..f2b3c74b483e527932dda42279d14a9ac184b475 100644 ---- a/src/responder/pam/pamsrv_cmd.c -+++ b/src/responder/pam/pamsrv_cmd.c -@@ -1161,6 +1161,25 @@ static bool is_domain_public(char *name, - return false; - } - -+static enum cache_req_dom_type -+get_domain_request_type(struct pam_auth_req *preq, -+ struct pam_ctx *pctx) -+{ -+ enum cache_req_dom_type req_dom_type; -+ -+ /* By default, only POSIX domains are to be contacted */ -+ req_dom_type = CACHE_REQ_POSIX_DOM; -+ -+ for (int i = 0; pctx->app_services[i]; i++) { -+ if (strcmp(pctx->app_services[i], preq->pd->service) == 0) { -+ req_dom_type = CACHE_REQ_APPLICATION_DOM; -+ break; -+ } -+ } -+ -+ return req_dom_type; -+} -+ - static errno_t check_cert(TALLOC_CTX *mctx, - struct tevent_context *ev, - struct pam_ctx *pctx, -@@ -1257,6 +1276,9 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) - goto done; - } - -+ /* Determine what domain type to contact */ -+ preq->req_dom_type = get_domain_request_type(preq, pctx); -+ - /* try backend first for authentication before doing local Smartcard - * authentication */ - if (pd->cmd != SSS_PAM_AUTHENTICATE && may_do_cert_auth(pctx, pd)) { -@@ -1316,7 +1338,7 @@ static void pam_forwarder_cert_cb(struct tevent_req *req) - - req = cache_req_user_by_cert_send(preq, cctx->ev, cctx->rctx, - pctx->rctx->ncache, 0, -- CACHE_REQ_POSIX_DOM, NULL, -+ preq->req_dom_type, NULL, - cert); - if (req == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n"); -@@ -1509,7 +1531,7 @@ static int pam_check_user_search(struct pam_auth_req *preq) - preq->cctx->rctx, - preq->cctx->rctx->ncache, - 0, -- CACHE_REQ_POSIX_DOM, -+ preq->req_dom_type, - preq->pd->domain, - data); - if (!dpreq) { -diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c -index 847419658bb983e6548722d6fa6fb22c63ee86b8..d249b8f1ea48f1c17b461c3add9e8c63774e5f88 100644 ---- a/src/tests/cmocka/test_pam_srv.c -+++ b/src/tests/cmocka/test_pam_srv.c -@@ -186,6 +186,15 @@ struct pam_ctx *mock_pctx(TALLOC_CTX *mem_ctx) - ret = sss_hash_create(pctx, 10, &pctx->id_table); - assert_int_equal(ret, EOK); - -+ /* Two NULLs so that tests can just assign a const to the first slot -+ * should they need it. The code iterates until first NULL anyway -+ */ -+ pctx->app_services = talloc_zero_array(pctx, char *, 2); -+ if (pctx->app_services == NULL) { -+ talloc_free(pctx); -+ return NULL; -+ } -+ - return pctx; - } - -@@ -495,8 +504,12 @@ int __wrap_pam_dp_send_req(struct pam_auth_req *preq, int timeout) - return EOK; - } - --static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name, -- const char *pwd, const char *fa2) -+static void mock_input_pam_ex(TALLOC_CTX *mem_ctx, -+ const char *name, -+ const char *pwd, -+ const char *fa2, -+ const char *svc, -+ bool contact_dp) - { - size_t buf_size; - uint8_t *m_buf; -@@ -536,7 +549,10 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name, - } - } - -- pi.pam_service = "pam_test_service"; -+ if (svc == NULL) { -+ svc = "pam_test_service"; -+ } -+ pi.pam_service = svc; - pi.pam_service_size = strlen(pi.pam_service) + 1; - pi.pam_tty = "/dev/tty"; - pi.pam_tty_size = strlen(pi.pam_tty) + 1; -@@ -559,7 +575,17 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name, - will_return(__wrap_sss_packet_get_body, buf_size); - - mock_parse_inp(name, NULL, EOK); -- mock_account_recv_simple(); -+ if (contact_dp) { -+ mock_account_recv_simple(); -+ } -+} -+ -+static void mock_input_pam(TALLOC_CTX *mem_ctx, -+ const char *name, -+ const char *pwd, -+ const char *fa2) -+{ -+ return mock_input_pam_ex(mem_ctx, name, pwd, fa2, NULL, true); - } - - static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name, -@@ -2097,6 +2123,127 @@ void test_filter_response(void **state) - talloc_free(pd); - } - -+static int pam_test_setup_appsvc_posix_dom(void **state) -+{ -+ int ret; -+ -+ ret = pam_test_setup(state); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ /* This config option is only read on startup, which is not executed -+ * in test, so we can't just pass in a param -+ */ -+ pam_test_ctx->pctx->app_services[0] = discard_const("app_svc"); -+ return 0; -+} -+ -+void test_appsvc_posix_dom(void **state) -+{ -+ int ret; -+ -+ /* The domain is POSIX, the request will skip over it */ -+ mock_input_pam_ex(pam_test_ctx, "pamuser", NULL, NULL, "app_svc", false); -+ pam_test_ctx->exp_pam_status = PAM_USER_UNKNOWN; -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ set_cmd_cb(test_pam_user_unknown_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_not_appsvc_posix_dom(void **state) -+{ -+ int ret; -+ -+ /* A different service than the app one can authenticate against a POSIX domain */ -+ mock_input_pam_ex(pam_test_ctx, "pamuser", NULL, NULL, "not_app_svc", true); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ set_cmd_cb(test_pam_simple_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+static int pam_test_setup_appsvc_app_dom(void **state) -+{ -+ struct sss_test_conf_param dom_params[] = { -+ { "domain_type", "application" }, -+ { NULL, NULL }, /* Sentinel */ -+ }; -+ struct sss_test_conf_param pam_params[] = { -+ { NULL, NULL }, /* Sentinel */ -+ }; -+ struct sss_test_conf_param monitor_params[] = { -+ { NULL, NULL }, /* Sentinel */ -+ }; -+ -+ -+ test_pam_setup(dom_params, pam_params, monitor_params, state); -+ pam_test_setup_common(); -+ -+ /* This config option is only read on startup, which is not executed -+ * in test, so we can't just pass in a param -+ */ -+ pam_test_ctx->pctx->app_services[0] = discard_const("app_svc"); -+ return 0; -+} -+ -+void test_appsvc_app_dom(void **state) -+{ -+ int ret; -+ -+ /* The domain is POSIX, the request will skip over it */ -+ mock_input_pam_ex(pam_test_ctx, "pamuser", NULL, NULL, "app_svc", true); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ set_cmd_cb(test_pam_simple_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_not_appsvc_app_dom(void **state) -+{ -+ int ret; -+ -+ /* A different service than the app one can authenticate against a POSIX domain */ -+ mock_input_pam_ex(pam_test_ctx, "pamuser", NULL, NULL, "not_app_svc", false); -+ -+ pam_test_ctx->exp_pam_status = PAM_USER_UNKNOWN; -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ set_cmd_cb(test_pam_user_unknown_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ - int main(int argc, const char *argv[]) - { - int rv; -@@ -2216,6 +2363,18 @@ int main(int argc, const char *argv[]) - - cmocka_unit_test_setup_teardown(test_filter_response, - pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_appsvc_posix_dom, -+ pam_test_setup_appsvc_posix_dom, -+ pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_not_appsvc_posix_dom, -+ pam_test_setup_appsvc_posix_dom, -+ pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_appsvc_app_dom, -+ pam_test_setup_appsvc_app_dom, -+ pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_not_appsvc_app_dom, -+ pam_test_setup_appsvc_posix_dom, -+ pam_test_teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.12.2 - diff --git a/0071-SYSDB-Allow-storing-non-POSIX-users.patch b/0071-SYSDB-Allow-storing-non-POSIX-users.patch deleted file mode 100644 index f212b07..0000000 --- a/0071-SYSDB-Allow-storing-non-POSIX-users.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 5f7f249f2a8a1c7284e991aa64dbf850d482b0aa Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Mar 2017 13:00:31 +0100 -Subject: [PATCH 71/97] SYSDB: Allow storing non-POSIX users - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -We already do the same for groups. If the user does not have UID number -set but does have the POSIX: false attribute set, then we save the user -with zero UID and the non-POSIX flag. - -Reviewed-by: Sumit Bose ---- - src/db/sysdb_ops.c | 32 ++++++++++++++++++++-------- - src/tests/sysdb-tests.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 79 insertions(+), 9 deletions(-) - -diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c -index 919f22370ff87eff2bf0bb569ca90f1ee699a61e..3cf9d903f25b9ccd506d7957c94040bdc7d658a3 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -1855,6 +1855,7 @@ int sysdb_add_user(struct sss_domain_info *domain, - struct sysdb_attrs *id_attrs; - uint32_t id; - int ret; -+ bool posix; - - if (domain->mpg) { - if (gid != 0) { -@@ -1926,7 +1927,28 @@ int sysdb_add_user(struct sss_domain_info *domain, - /* Not fatal */ - } - -- if (uid == 0) { -+ if (!attrs) { -+ attrs = sysdb_new_attrs(tmp_ctx); -+ if (!attrs) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix); -+ if (ret == ENOENT) { -+ posix = true; -+ ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, true); -+ if (ret) { -+ DEBUG(SSSDBG_TRACE_LIBS, "Failed to add posix attribute.\n"); -+ goto done; -+ } -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_TRACE_LIBS, "Failed to get posix attribute.\n"); -+ goto done; -+ } -+ -+ if (uid == 0 && posix == true) { - ret = sysdb_get_new_id(domain, &id); - if (ret) goto done; - -@@ -1948,14 +1970,6 @@ int sysdb_add_user(struct sss_domain_info *domain, - if (ret) goto done; - } - -- if (!attrs) { -- attrs = sysdb_new_attrs(tmp_ctx); -- if (!attrs) { -- ret = ENOMEM; -- goto done; -- } -- } -- - if (!now) { - now = time(NULL); - } -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index 1767dc3c734c6b2e5f74564debd603e2442f491b..6ec82ce4ca5c4f918bc9f3144c21f33b270ea47e 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -1428,6 +1428,59 @@ START_TEST (test_sysdb_get_user_attr_subdomain) - } - END_TEST - -+START_TEST (test_sysdb_add_nonposix_user) -+{ -+ struct sysdb_test_ctx *test_ctx; -+ const char *get_attrs[] = { SYSDB_GIDNUM, -+ SYSDB_UIDNUM, -+ SYSDB_POSIX, -+ NULL }; -+ struct ldb_result *res; -+ const char *attrval; -+ const char *username = "test_sysdb_add_nonposix_user"; -+ const char *fq_name; -+ struct sysdb_attrs *user_attrs; -+ int ret; -+ uint64_t id; -+ -+ /* Setup */ -+ ret = setup_sysdb_tests(&test_ctx); -+ fail_if(ret != EOK, "Could not set up the test"); -+ -+ /* Create user */ -+ fq_name = sss_create_internal_fqname(test_ctx, username, test_ctx->domain->name); -+ fail_if(fq_name == NULL, "Failed to create fq name."); -+ -+ user_attrs = sysdb_new_attrs(test_ctx); -+ fail_if(user_attrs == NULL); -+ -+ ret = sysdb_attrs_add_bool(user_attrs, SYSDB_POSIX, false); -+ fail_if(ret != EOK, "Could not add attribute"); -+ -+ ret = sysdb_add_user(test_ctx->domain, fq_name, 0, 0, "Gecos", -+ "/home/userhome", "/bin/bash", NULL, user_attrs, 0, 0); -+ fail_if(ret != EOK, "sysdb_add_user failed."); -+ -+ /* Test */ -+ ret = sysdb_get_user_attr(test_ctx, test_ctx->domain, fq_name, -+ get_attrs, &res); -+ fail_if(ret != EOK, "Could not get user attributes."); -+ fail_if(res->count != 1, "Invalid number of entries, expected 1, got %d", -+ res->count); -+ -+ attrval = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_POSIX, NULL); -+ fail_if(strcasecmp(attrval, "false") != 0, "Got bad attribute value."); -+ -+ id = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 123); -+ fail_unless(id == 0, "Wrong UID value"); -+ -+ id = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 123); -+ fail_unless(id == 0, "Wrong GID value"); -+ -+ talloc_free(test_ctx); -+} -+END_TEST -+ - START_TEST (test_sysdb_add_group_member) - { - struct sysdb_test_ctx *test_ctx; -@@ -7044,6 +7097,9 @@ Suite *create_sysdb_suite(void) - /* Test GetUserAttr with subdomain user */ - tcase_add_test(tc_sysdb, test_sysdb_get_user_attr_subdomain); - -+ /* Test adding a non-POSIX user */ -+ tcase_add_test(tc_sysdb, test_sysdb_add_nonposix_user); -+ - /* ===== NETGROUP TESTS ===== */ - - /* Create a new netgroup */ --- -2.12.2 - diff --git a/0072-SYSDB-Only-generate-new-UID-in-local-domain.patch b/0072-SYSDB-Only-generate-new-UID-in-local-domain.patch deleted file mode 100644 index 8bbd16d..0000000 --- a/0072-SYSDB-Only-generate-new-UID-in-local-domain.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 901396366075dc3e3fcc0894345af1b51052ac69 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 28 Mar 2017 14:49:31 +0200 -Subject: [PATCH 72/97] SYSDB: Only generate new UID in local domain - -To avoid issues where a user with no UID but without the posix=false -flag was passed to sysdb, we only allow generating the new ID in the -local domain. This might prevent bugs where non-POSIX users would get a -UID created by sysdb which might allow accessing resources owned by that -UID. - -Reviewed-by: Sumit Bose ---- - src/db/sysdb_ops.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c -index 3cf9d903f25b9ccd506d7957c94040bdc7d658a3..4d7b2abd8026c90aaf4e7be687102e459cf3690e 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -1422,6 +1422,12 @@ int sysdb_get_new_id(struct sss_domain_info *domain, - return ENOMEM; - } - -+ if (strcasecmp(domain->provider, "local") != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Generating new ID is only supported in the local domain!\n"); -+ return ENOTSUP; -+ } -+ - base_dn = sysdb_domain_dn(tmp_ctx, domain); - if (!base_dn) { - talloc_zfree(tmp_ctx); --- -2.12.2 - diff --git a/0073-LDAP-save-non-POSIX-users-in-application-domains.patch b/0073-LDAP-save-non-POSIX-users-in-application-domains.patch deleted file mode 100644 index 991adff..0000000 --- a/0073-LDAP-save-non-POSIX-users-in-application-domains.patch +++ /dev/null @@ -1,141 +0,0 @@ -From ed0cdfcacc44e4e13e1524e254efa744610a87c2 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Mar 2017 13:06:08 +0100 -Subject: [PATCH 73/97] LDAP: save non-POSIX users in application domains - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -If a user being saved by the LDAP provider does not have a UID or GID -and the domain type is application, we save the user entry as non-POSIX. - -Reviewed-by: Sumit Bose ---- - src/providers/ldap/sdap_async_users.c | 72 +++++++++++++++++++++++++++-------- - 1 file changed, 57 insertions(+), 15 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index 3d957ab584865f74499bc732395388a78965fe5f..265cd7e4f7929c295d5bdcfbd781221b74601f13 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -112,6 +112,28 @@ done: - return ret; - } - -+static errno_t sdap_set_non_posix_flag(struct sysdb_attrs *attrs, -+ const char *pkey) -+{ -+ errno_t ret; -+ -+ ret = sysdb_attrs_add_uint32(attrs, pkey, 0); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to add a zero ID to a non-posix object!\n"); -+ return ret; -+ } -+ -+ ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, false); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Error: Failed to mark objects as non-posix!\n"); -+ return ret; -+ } -+ -+ return EOK; -+} -+ - /* FIXME: support storing additional attributes */ - int sdap_save_user(TALLOC_CTX *memctx, - struct sdap_options *opts, -@@ -130,8 +152,8 @@ int sdap_save_user(TALLOC_CTX *memctx, - const char *homedir; - const char *shell; - const char *orig_dn = NULL; -- uid_t uid; -- gid_t gid; -+ uid_t uid = 0; -+ gid_t gid = 0; - struct sysdb_attrs *user_attrs; - char *upn = NULL; - size_t i; -@@ -146,6 +168,7 @@ int sdap_save_user(TALLOC_CTX *memctx, - size_t c; - char *p1; - char *p2; -+ bool is_posix = true; - - DEBUG(SSSDBG_TRACE_FUNC, "Save user\n"); - -@@ -295,19 +318,29 @@ int sdap_save_user(TALLOC_CTX *memctx, - ret = sysdb_attrs_get_uint32_t(attrs, - opts->user_map[SDAP_AT_USER_UID].sys_name, - &uid); -- if (ret != EOK) { -+ if (ret == ENOENT && dom->type == DOM_TYPE_APPLICATION) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Marking object as non-posix and setting ID=0!\n"); -+ ret = sdap_set_non_posix_flag(user_attrs, -+ opts->user_map[SDAP_AT_USER_UID].sys_name); -+ if (ret != EOK) { -+ goto done; -+ } -+ is_posix = false; -+ } else if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, -- "no uid provided for [%s] in domain [%s].\n", -+ "Cannot retrieve UID for [%s] in domain [%s].\n", - user_name, dom->name); -- ret = EINVAL; -+ ret = ERR_NO_POSIX; - goto done; - } - } -- /* check that the uid is valid for this domain */ -- if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) { -- DEBUG(SSSDBG_OP_FAILURE, -- "User [%s] filtered out! (uid out of range)\n", -- user_name); -+ -+ /* check that the uid is valid for this domain if the user is a POSIX one */ -+ if (is_posix == true && OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "User [%s] filtered out! (uid out of range)\n", -+ user_name); - ret = EINVAL; - goto done; - } -@@ -349,17 +382,26 @@ int sdap_save_user(TALLOC_CTX *memctx, - ret = sysdb_attrs_get_uint32_t(attrs, - opts->user_map[SDAP_AT_USER_GID].sys_name, - &gid); -- if (ret != EOK) { -+ if (ret == ENOENT && dom->type == DOM_TYPE_APPLICATION) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Marking object as non-posix and setting ID=0!\n"); -+ ret = sdap_set_non_posix_flag(attrs, -+ opts->user_map[SDAP_AT_USER_GID].sys_name); -+ if (ret != EOK) { -+ goto done; -+ } -+ is_posix = false; -+ } else if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, -- "no gid provided for [%s] in domain [%s].\n", -- user_name, dom->name); -- ret = EINVAL; -+ "Cannot retrieve GID for [%s] in domain [%s].\n", -+ user_name, dom->name); -+ ret = ERR_NO_POSIX; - goto done; - } - } - - /* check that the gid is valid for this domain */ -- if (IS_SUBDOMAIN(dom) == false && -+ if (is_posix == true && IS_SUBDOMAIN(dom) == false && - OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { - DEBUG(SSSDBG_CRIT_FAILURE, - "User [%s] filtered out! (primary gid out of range)\n", --- -2.12.2 - diff --git a/0074-LDAP-Relax-search-filters-in-application-domains.patch b/0074-LDAP-Relax-search-filters-in-application-domains.patch deleted file mode 100644 index 65adb68..0000000 --- a/0074-LDAP-Relax-search-filters-in-application-domains.patch +++ /dev/null @@ -1,254 +0,0 @@ -From 3e39806177e1cd383743ff596cb96df44a6ce8c9 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Mar 2017 13:06:14 +0100 -Subject: [PATCH 74/97] LDAP: Relax search filters in application domains - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -If a request comes towards an application domain, we can drop the part -of the filter that asserts that the object has a valid UID/GID. Instead, -we just search by name. - -Reviewed-by: Sumit Bose ---- - src/providers/ldap/ldap_id.c | 35 ++++++++++++++++++++++++---- - src/providers/ldap/sdap_async_enum.c | 7 +++++- - src/providers/ldap/sdap_async_initgroups.c | 37 ++++++++++++++++++++++++------ - 3 files changed, 66 insertions(+), 13 deletions(-) - -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index 0bee0ca8d71abece6749fdb8393b9ceacb64417d..7400dc1f57e30cc6ae5f939ffa628a1e9dd47e06 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -56,6 +56,7 @@ struct users_get_state { - char *filter; - const char **attrs; - bool use_id_mapping; -+ bool non_posix; - - int dp_error; - int sdap_ret; -@@ -114,6 +115,10 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - state->filter_value = filter_value; - state->filter_type = filter_type; - -+ if (state->domain->type == DOM_TYPE_APPLICATION) { -+ state->non_posix = true; -+ } -+ - state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->name, -@@ -292,7 +297,13 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - } - } - -- if (state->use_id_mapping || filter_type == BE_FILTER_SECID) { -+ if (state->non_posix) { -+ state->filter = talloc_asprintf(state, -+ "(&%s(objectclass=%s)(%s=*))", -+ user_filter, -+ ctx->opts->user_map[SDAP_OC_USER].name, -+ ctx->opts->user_map[SDAP_AT_USER_NAME].name); -+ } else 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. -@@ -304,7 +315,8 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - 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 */ -+ /* When not ID-mapping or looking up POSIX users, -+ * make sure there is a non-NULL UID */ - state->filter = talloc_asprintf(state, - "(&%s(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))", - user_filter, -@@ -380,6 +392,7 @@ static void users_get_connect_done(struct tevent_req *subreq) - * have no idea about POSIX attributes support, run a one-time check - */ - if (state->use_id_mapping == false && -+ state->non_posix == false && - state->ctx->opts->schema_type == SDAP_SCHEMA_AD && - state->ctx->srv_opts && - state->ctx->srv_opts->posix_checked == false) { -@@ -650,6 +663,7 @@ struct groups_get_state { - char *filter; - const char **attrs; - bool use_id_mapping; -+ bool non_posix; - - int dp_error; - int sdap_ret; -@@ -709,6 +723,10 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - state->filter_value = filter_value; - state->filter_type = filter_type; - -+ if (state->domain->type == DOM_TYPE_APPLICATION) { -+ state->non_posix = true; -+ } -+ - state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->name, -@@ -827,9 +845,11 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - 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 groups with a GID value -+ if (state->non_posix -+ || state->use_id_mapping -+ || filter_type == BE_FILTER_SECID) { -+ /* When mapping IDs or looking for SIDs, or when in a non-POSIX domain, -+ * we don't want to limit ourselves to groups with a GID value - */ - - state->filter = talloc_asprintf(state, -@@ -1123,6 +1143,7 @@ struct groups_by_user_state { - int filter_type; - const char *extra_value; - const char **attrs; -+ bool non_posix; - - int dp_error; - int sdap_ret; -@@ -1204,6 +1225,10 @@ static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, - state->domain = sdom->dom; - state->sysdb = sdom->dom->sysdb; - -+ if (state->domain->type == DOM_TYPE_APPLICATION) { -+ state->non_posix = true; -+ } -+ - ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP, - NULL, &state->attrs, NULL); - if (ret != EOK) goto fail; -diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c -index 3f65059e18d5c8b548da0babec867d27c3a64198..91e481c4e694126900c729e86d187fba355de0b8 100644 ---- a/src/providers/ldap/sdap_async_enum.c -+++ b/src/providers/ldap/sdap_async_enum.c -@@ -717,6 +717,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - struct enum_groups_state *state; - int ret; - bool use_mapping; -+ bool non_posix = false; - char *oc_list; - - req = tevent_req_create(memctx, &state, struct enum_groups_state); -@@ -727,6 +728,10 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - state->ctx = ctx; - state->op = op; - -+ if (sdom->dom->type == DOM_TYPE_APPLICATION) { -+ non_posix = true; -+ } -+ - use_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->name, -@@ -749,7 +754,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - goto fail; - } - -- if (use_mapping) { -+ if (!non_posix && use_mapping) { - /* If we're ID-mapping, check for the objectSID as well */ - state->filter = talloc_asprintf_append_buffer( - state->filter, "(%s=*)", -diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c -index 79af7a3eda3fe8533933535c98c2b4b4698dfda2..c926ddcbefe471daa80505e139c3f19efa33b9ba 100644 ---- a/src/providers/ldap/sdap_async_initgroups.c -+++ b/src/providers/ldap/sdap_async_initgroups.c -@@ -376,7 +376,7 @@ struct sdap_initgr_rfc2307_state { - struct sdap_handle *sh; - const char **attrs; - const char *name; -- const char *base_filter; -+ char *base_filter; - const char *orig_dn; - char *filter; - int timeout; -@@ -473,18 +473,32 @@ struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx, - } - - state->base_filter = talloc_asprintf(state, -- "(&(%s=%s)(%s)(%s=*)(&(%s=*)(!(%s=0))))", -+ "(&(%s=%s)(%s)(%s=*)", - opts->group_map[SDAP_AT_GROUP_MEMBER].name, - clean_name, oc_list, -- opts->group_map[SDAP_AT_GROUP_NAME].name, -- opts->group_map[SDAP_AT_GROUP_GID].name, -- opts->group_map[SDAP_AT_GROUP_GID].name); -+ opts->group_map[SDAP_AT_GROUP_NAME].name); - if (!state->base_filter) { - talloc_zfree(req); - return NULL; - } - talloc_zfree(clean_name); - -+ switch (domain->type) { -+ case DOM_TYPE_APPLICATION: -+ state->base_filter = talloc_asprintf_append(state->base_filter, ")"); -+ break; -+ case DOM_TYPE_POSIX: -+ state->base_filter = talloc_asprintf_append(state->base_filter, -+ "(&(%s=*)(!(%s=0))))", -+ opts->group_map[SDAP_AT_GROUP_GID].name, -+ opts->group_map[SDAP_AT_GROUP_GID].name); -+ break; -+ } -+ if (!state->base_filter) { -+ ret = ENOMEM; -+ goto done; -+ } -+ - ret = sdap_initgr_rfc2307_next_base(req); - - done: -@@ -2666,6 +2680,7 @@ struct sdap_get_initgr_state { - char *shortname; - char *filter; - int timeout; -+ bool non_posix; - - struct sysdb_attrs *orig_user; - -@@ -2724,6 +2739,10 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, - goto done; - } - -+ if (state->dom->type == DOM_TYPE_APPLICATION) { -+ state->non_posix = true; -+ } -+ - use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( - id_ctx->opts->idmap_ctx, - sdom->dom->name, -@@ -2813,7 +2832,10 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, - } - } - -- if (use_id_mapping) { -+ if (state->non_posix) { -+ state->user_base_filter = talloc_asprintf_append(state->user_base_filter, -+ ")"); -+ } else if (use_id_mapping) { - /* 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. -@@ -2822,7 +2844,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, - "(%s=*))", - id_ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name); - } else { -- /* When not ID-mapping, make sure there is a non-NULL UID */ -+ /* When not ID-mapping or looking up app users, make sure there -+ * is a non-NULL UID */ - state->user_base_filter = talloc_asprintf_append(state->user_base_filter, - "(&(%s=*)(!(%s=0))))", - id_ctx->opts->user_map[SDAP_AT_USER_UID].name, --- -2.12.2 - diff --git a/0075-KRB5-Authenticate-users-in-a-non-POSIX-domain-using-.patch b/0075-KRB5-Authenticate-users-in-a-non-POSIX-domain-using-.patch deleted file mode 100644 index 55b28ae..0000000 --- a/0075-KRB5-Authenticate-users-in-a-non-POSIX-domain-using-.patch +++ /dev/null @@ -1,353 +0,0 @@ -From 861ab44e8148208425b67c4711bc8fade10fd3ed Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Mar 2017 13:01:18 +0100 -Subject: [PATCH 75/97] KRB5: Authenticate users in a non-POSIX domain using a - MEMORY ccache - -Related to: -https://pagure.io/SSSD/sssd/issue/3310 - -The following changes were done to the Kerberos authentication code -in order to support authentication in a non-POSIX environment: - - delayed authentication is disabled in non-POSIX domains - - when a user logs in in a non-POSIX domain, SSSD uses a - MEMORY:$username ccache and destroys is then krb5_child finishes - so that just the numeric result is used - - krb5_child doesn't drop privileges in this configuration because - there is nothing to drop privileges to - -Reviewed-by: Sumit Bose ---- - src/providers/krb5/krb5_auth.c | 62 ++++++++++++++++------ - src/providers/krb5/krb5_auth.h | 2 + - src/providers/krb5/krb5_child.c | 32 +++++++++-- - src/providers/krb5/krb5_child_handler.c | 15 +++++- - .../krb5/krb5_delayed_online_authentication.c | 7 +++ - src/providers/krb5/krb5_init.c | 3 ++ - 6 files changed, 99 insertions(+), 22 deletions(-) - -diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c -index c2d6d7eeacc1f766024c4d629f25fd0f0be24e5e..2faf18d17a735476c20f9cc27b15be4a39cadc5c 100644 ---- a/src/providers/krb5/krb5_auth.c -+++ b/src/providers/krb5/krb5_auth.c -@@ -42,6 +42,8 @@ - #include "providers/krb5/krb5_utils.h" - #include "providers/krb5/krb5_ccache.h" - -+#define NON_POSIX_CCNAME_FMT "MEMORY:sssd_nonposix_dummy_%u" -+ - static int krb5_mod_ccname(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, -@@ -200,6 +202,7 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, - talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup); - - kr->pd = pd; -+ kr->dom = dom; - kr->krb5_ctx = krb5_ctx; - - ret = get_krb_primary(krb5_ctx->name_to_primary, -@@ -275,8 +278,11 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx, - return; - } - -- ret = add_user_to_delayed_online_authentication(krb5_ctx, pd, uid); -- if (ret != EOK) { -+ ret = add_user_to_delayed_online_authentication(krb5_ctx, domain, pd, uid); -+ if (ret == ENOTSUP) { -+ /* This error is not fatal */ -+ DEBUG(SSSDBG_MINOR_FAILURE, "Delayed authentication not supported\n"); -+ } else if (ret != EOK) { - /* This error is not fatal */ - DEBUG(SSSDBG_CRIT_FAILURE, - "add_user_to_delayed_online_authentication failed.\n"); -@@ -291,21 +297,43 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr, - { - const char *ccname_template; - -- ccname_template = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL); -+ switch (kr->dom->type) { -+ case DOM_TYPE_POSIX: -+ ccname_template = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL); - -- kr->ccname = expand_ccname_template(kr, kr, ccname_template, -- kr->krb5_ctx->illegal_path_re, true, -- be_ctx->domain->case_sensitive); -- if (kr->ccname == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "expand_ccname_template failed.\n"); -- return ENOMEM; -- } -+ kr->ccname = expand_ccname_template(kr, kr, ccname_template, -+ kr->krb5_ctx->illegal_path_re, true, -+ be_ctx->domain->case_sensitive); -+ if (kr->ccname == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "expand_ccname_template failed.\n"); -+ return ENOMEM; -+ } - -- kr->old_ccname = ldb_msg_find_attr_as_string(user_msg, -- SYSDB_CCACHE_FILE, NULL); -- if (kr->old_ccname == NULL) { -- DEBUG(SSSDBG_TRACE_LIBS, -- "No ccache file for user [%s] found.\n", kr->pd->user); -+ kr->old_ccname = ldb_msg_find_attr_as_string(user_msg, -+ SYSDB_CCACHE_FILE, NULL); -+ if (kr->old_ccname == NULL) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "No ccache file for user [%s] found.\n", kr->pd->user); -+ } -+ break; -+ case DOM_TYPE_APPLICATION: -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Domain type application, will use in-memory ccache\n"); -+ /* We don't care about using cryptographic randomness, just -+ * a non-predictable ccname, so using rand() here is fine -+ */ -+ kr->ccname = talloc_asprintf(kr, -+ NON_POSIX_CCNAME_FMT, -+ rand() % UINT_MAX); -+ if (kr->ccname == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n"); -+ return ENOMEM; -+ } -+ -+ break; -+ default: -+ DEBUG(SSSDBG_FATAL_FAILURE, "Unsupported domain type\n"); -+ return EINVAL; - } - - return EOK; -@@ -617,7 +645,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, - kr->uid = sss_view_ldb_msg_find_attr_as_uint64(state->domain, - res->msgs[0], - SYSDB_UIDNUM, 0); -- if (kr->uid == 0) { -+ if (kr->uid == 0 && state->domain->type == DOM_TYPE_POSIX) { - DEBUG(SSSDBG_CONF_SETTINGS, - "UID for user [%s] not known.\n", pd->user); - ret = ENOENT; -@@ -627,7 +655,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, - kr->gid = sss_view_ldb_msg_find_attr_as_uint64(state->domain, - res->msgs[0], - SYSDB_GIDNUM, 0); -- if (kr->gid == 0) { -+ if (kr->gid == 0 && state->domain->type == DOM_TYPE_POSIX) { - DEBUG(SSSDBG_CONF_SETTINGS, - "GID for user [%s] not known.\n", pd->user); - ret = ENOENT; -diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h -index 75ad916e79b29043120543ab3c4c1bd27e09d913..8ad3aeff21e58f9055ae144eaa450992c6391ba6 100644 ---- a/src/providers/krb5/krb5_auth.h -+++ b/src/providers/krb5/krb5_auth.h -@@ -50,6 +50,7 @@ - struct krb5child_req { - struct pam_data *pd; - struct krb5_ctx *krb5_ctx; -+ struct sss_domain_info *dom; - - const char *ccname; - const char *old_ccname; -@@ -118,6 +119,7 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len, - struct krb5_child_response **_res); - - errno_t add_user_to_delayed_online_authentication(struct krb5_ctx *krb5_ctx, -+ struct sss_domain_info *domain, - struct pam_data *pd, - uid_t uid); - errno_t init_delayed_online_authentication(struct krb5_ctx *krb5_ctx, -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index a4128dda6b0861a95dba223047d66c4158b1afb6..cbbc892bee0365892ac66d3654c974d325166b60 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -80,6 +80,7 @@ struct krb5_req { - char *ccname; - char *keytab; - bool validate; -+ bool posix_domain; - bool send_pac; - bool use_enterprise_princ; - char *fast_ccname; -@@ -102,6 +103,16 @@ struct krb5_req { - static krb5_context krb5_error_ctx; - #define KRB5_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error) - -+static errno_t k5c_become_user(uid_t uid, gid_t gid, bool is_posix) -+{ -+ if (is_posix == false) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Will not drop privileges for a non-POSIX user\n"); -+ return EOK; -+ } -+ return become_user(uid, gid); -+} -+ - static krb5_error_code set_lifetime_options(struct cli_opts *cli_opts, - krb5_get_init_creds_opt *options) - { -@@ -1561,6 +1572,15 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr, - DEBUG(SSSDBG_CONF_SETTINGS, "TGT validation is disabled.\n"); - } - -+ /* In a non-POSIX environment, we only care about the return code from -+ * krb5_child, so let's not even attempt to create the ccache -+ */ -+ if (kr->posix_domain == false) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Finished authentication in a non-POSIX domain\n"); -+ goto done; -+ } -+ - /* If kr->ccname is cache collection (DIR:/...), we want to work - * directly with file ccache (DIR::/...), but cache collection - * should be returned back to back end. -@@ -2146,6 +2166,7 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, - size_t p = 0; - uint32_t len; - uint32_t validate; -+ uint32_t posix_domain; - uint32_t send_pac; - uint32_t use_enterprise_princ; - struct pam_data *pd; -@@ -2167,6 +2188,8 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, - SAFEALIGN_COPY_UINT32_CHECK(&kr->gid, buf + p, size, &p); - SAFEALIGN_COPY_UINT32_CHECK(&validate, buf + p, size, &p); - kr->validate = (validate == 0) ? false : true; -+ SAFEALIGN_COPY_UINT32_CHECK(&posix_domain, buf + p, size, &p); -+ kr->posix_domain = (posix_domain == 0) ? false : true; - SAFEALIGN_COPY_UINT32_CHECK(offline, buf + p, size, &p); - SAFEALIGN_COPY_UINT32_CHECK(&send_pac, buf + p, size, &p); - kr->send_pac = (send_pac == 0) ? false : true; -@@ -2331,6 +2354,7 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx, - krb5_context ctx, - uid_t fast_uid, - gid_t fast_gid, -+ bool posix_domain, - struct cli_opts *cli_opts, - const char *primary, - const char *realm, -@@ -2420,7 +2444,7 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx, - /* Try to carry on */ - } - -- kerr = become_user(fast_uid, fast_gid); -+ kerr = k5c_become_user(fast_uid, fast_gid, posix_domain); - if (kerr != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed: %d\n", kerr); - exit(1); -@@ -2572,7 +2596,7 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand) - } - - kerr = check_fast_ccache(kr, kr->ctx, kr->fast_uid, kr->fast_gid, -- kr->cli_opts, -+ kr->posix_domain, kr->cli_opts, - fast_principal, fast_principal_realm, - kr->keytab, &kr->fast_ccname); - if (kerr != 0) { -@@ -2773,7 +2797,7 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline) - * the user who is logging in. The same applies to the offline case - * the user who is logging in. The same applies to the offline case. - */ -- kerr = become_user(kr->uid, kr->gid); -+ kerr = k5c_become_user(kr->uid, kr->gid, kr->posix_domain); - if (kerr != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n"); - return kerr; -@@ -3075,7 +3099,7 @@ int main(int argc, const char *argv[]) - if ((sss_authtok_get_type(kr->pd->authtok) != SSS_AUTHTOK_TYPE_SC_PIN - && sss_authtok_get_type(kr->pd->authtok) - != SSS_AUTHTOK_TYPE_SC_KEYPAD)) { -- kerr = become_user(kr->uid, kr->gid); -+ kerr = k5c_become_user(kr->uid, kr->gid, kr->posix_domain); - if (kerr != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n"); - ret = EFAULT; -diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c -index 680e67b089fcb32280352af24aae35af133a52f3..87e79a06e917aadb622455bccfc2e9c6769f70c2 100644 ---- a/src/providers/krb5/krb5_child_handler.c -+++ b/src/providers/krb5/krb5_child_handler.c -@@ -107,6 +107,7 @@ static errno_t create_send_buffer(struct krb5child_req *kr, - uint32_t validate; - uint32_t send_pac; - uint32_t use_enterprise_principal; -+ uint32_t posix_domain; - size_t username_len = 0; - errno_t ret; - -@@ -131,6 +132,17 @@ static errno_t create_send_buffer(struct krb5child_req *kr, - break; - } - -+ switch (kr->dom->type) { -+ case DOM_TYPE_POSIX: -+ posix_domain = 1; -+ break; -+ case DOM_TYPE_APPLICATION: -+ posix_domain = 0; -+ break; -+ default: -+ return EINVAL; -+ } -+ - if (kr->pd->cmd == SSS_CMD_RENEW || kr->is_offline) { - use_enterprise_principal = false; - } else { -@@ -151,7 +163,7 @@ static errno_t create_send_buffer(struct krb5child_req *kr, - kr->pd->cmd == SSS_CMD_RENEW || - kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM || - kr->pd->cmd == SSS_PAM_CHAUTHTOK) { -- buf->size += 4*sizeof(uint32_t) + strlen(kr->ccname) + strlen(keytab) + -+ buf->size += 5*sizeof(uint32_t) + strlen(kr->ccname) + strlen(keytab) + - sss_authtok_get_size(kr->pd->authtok); - - buf->size += sizeof(uint32_t); -@@ -182,6 +194,7 @@ static errno_t create_send_buffer(struct krb5child_req *kr, - SAFEALIGN_COPY_UINT32(&buf->data[rp], &kr->uid, &rp); - SAFEALIGN_COPY_UINT32(&buf->data[rp], &kr->gid, &rp); - SAFEALIGN_COPY_UINT32(&buf->data[rp], &validate, &rp); -+ SAFEALIGN_COPY_UINT32(&buf->data[rp], &posix_domain, &rp); - SAFEALIGN_COPY_UINT32(&buf->data[rp], &kr->is_offline, &rp); - SAFEALIGN_COPY_UINT32(&buf->data[rp], &send_pac, &rp); - SAFEALIGN_COPY_UINT32(&buf->data[rp], &use_enterprise_principal, &rp); -diff --git a/src/providers/krb5/krb5_delayed_online_authentication.c b/src/providers/krb5/krb5_delayed_online_authentication.c -index bf2ef775573ba6bad79a99ad43b5d9748516e794..1cb7eade0e4cb9afbc4d031a07b3519ba08456d6 100644 ---- a/src/providers/krb5/krb5_delayed_online_authentication.c -+++ b/src/providers/krb5/krb5_delayed_online_authentication.c -@@ -234,6 +234,7 @@ static void delayed_online_authentication_callback(void *private_data) - } - - errno_t add_user_to_delayed_online_authentication(struct krb5_ctx *krb5_ctx, -+ struct sss_domain_info *domain, - struct pam_data *pd, - uid_t uid) - { -@@ -242,6 +243,12 @@ errno_t add_user_to_delayed_online_authentication(struct krb5_ctx *krb5_ctx, - hash_value_t value; - struct pam_data *new_pd; - -+ if (domain->type != DOM_TYPE_POSIX) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Domain type does not support delayed authentication\n"); -+ return ENOTSUP; -+ } -+ - if (krb5_ctx->deferred_auth_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Missing context for delayed online authentication.\n"); -diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c -index 12c8dfcc49af75de619ec0858aaff81504698273..66ae68fb4773af3987f2062246bc6493107c74d5 100644 ---- a/src/providers/krb5/krb5_init.c -+++ b/src/providers/krb5/krb5_init.c -@@ -136,6 +136,9 @@ errno_t sssm_krb5_init(TALLOC_CTX *mem_ctx, - return ENOMEM; - } - -+ /* Only needed to generate random ccache names for non-POSIX domains */ -+ srand(time(NULL) * getpid()); -+ - ret = sss_krb5_get_options(ctx, be_ctx->cdb, be_ctx->conf_path, &ctx->opts); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get krb5 options [%d]: %s\n", --- -2.12.2 - diff --git a/0076-KCM-Fix-off-by-one-error-in-secrets-key-parsing.patch b/0076-KCM-Fix-off-by-one-error-in-secrets-key-parsing.patch deleted file mode 100644 index eed9448..0000000 --- a/0076-KCM-Fix-off-by-one-error-in-secrets-key-parsing.patch +++ /dev/null @@ -1,210 +0,0 @@ -From 7d73049884e3a96ca3b00b5bd4104f4edd6287ab Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 29 Mar 2017 22:49:09 +0200 -Subject: [PATCH 76/97] KCM: Fix off-by-one error in secrets key parsing -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When parsing the secrets key, the code tried to protect against malformed keys -or keys that are too short, but it did an error - the UUID stringified -form is 36 bytes long, so the UUID_STR_SIZE is 37 because UUID_STR_SIZE -accounts for the null terminator. - -But the code, that was trying to assert that there are two characters after -the UUID string (separator and at least a single character for the name) -didn't take the NULL terminator (which strlen() doesn't return) into -account and ended up rejecting all ccaches whose name is only a single -character. - -Reviewed-by: Fabiano Fidêncio ---- - src/responder/kcm/kcmsrv_ccache_json.c | 43 +++++++++------- - src/tests/cmocka/test_kcm_json_marshalling.c | 75 ++++++++++++++++++++++++++++ - 2 files changed, 101 insertions(+), 17 deletions(-) - -diff --git a/src/responder/kcm/kcmsrv_ccache_json.c b/src/responder/kcm/kcmsrv_ccache_json.c -index 40b64861c209206d6f60ccd0843857edee24a844..8199bc613e4204859438e1cd820f3f4b2123dd7e 100644 ---- a/src/responder/kcm/kcmsrv_ccache_json.c -+++ b/src/responder/kcm/kcmsrv_ccache_json.c -@@ -109,6 +109,28 @@ static const char *sec_key_create(TALLOC_CTX *mem_ctx, - "%s%c%s", uuid_str, SEC_KEY_SEPARATOR, name); - } - -+static bool sec_key_valid(const char *sec_key) -+{ -+ if (sec_key == NULL) { -+ return false; -+ } -+ -+ if (strlen(sec_key) < UUID_STR_SIZE + 1) { -+ /* One char for separator (at UUID_STR_SIZE, because strlen doesn't -+ * include the '\0', but UUID_STR_SIZE does) and at least one for -+ * the name */ -+ DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key); -+ return false; -+ } -+ -+ if (sec_key[UUID_STR_SIZE - 1] != SEC_KEY_SEPARATOR) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n"); -+ return false; -+ } -+ -+ return true; -+} -+ - static errno_t sec_key_parse(TALLOC_CTX *mem_ctx, - const char *sec_key, - const char **_name, -@@ -116,9 +138,7 @@ static errno_t sec_key_parse(TALLOC_CTX *mem_ctx, - { - char uuid_str[UUID_STR_SIZE]; - -- if (strlen(sec_key) < UUID_STR_SIZE + 2) { -- /* One char for separator and at least one for the name */ -- DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key); -+ if (!sec_key_valid(sec_key)) { - return EINVAL; - } - -@@ -143,14 +163,7 @@ errno_t sec_key_get_uuid(const char *sec_key, - { - char uuid_str[UUID_STR_SIZE]; - -- if (strlen(sec_key) < UUID_STR_SIZE + 2) { -- /* One char for separator and at least one for the name */ -- DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key); -- return EINVAL; -- } -- -- if (sec_key[UUID_STR_SIZE-1] != SEC_KEY_SEPARATOR) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n"); -+ if (!sec_key_valid(sec_key)) { - return EINVAL; - } - -@@ -162,9 +175,7 @@ errno_t sec_key_get_uuid(const char *sec_key, - - const char *sec_key_get_name(const char *sec_key) - { -- if (strlen(sec_key) < UUID_STR_SIZE + 2) { -- /* One char for separator and at least one for the name */ -- DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key); -+ if (!sec_key_valid(sec_key)) { - return NULL; - } - -@@ -174,9 +185,7 @@ const char *sec_key_get_name(const char *sec_key) - bool sec_key_match_name(const char *sec_key, - const char *name) - { -- if (strlen(sec_key) < UUID_STR_SIZE + 2) { -- /* One char for separator and at least one for the name */ -- DEBUG(SSSDBG_MINOR_FAILURE, "Key %s is too short\n", sec_key); -+ if (!sec_key_valid(sec_key) || name == NULL) { - return false; - } - -diff --git a/src/tests/cmocka/test_kcm_json_marshalling.c b/src/tests/cmocka/test_kcm_json_marshalling.c -index 8eff2f501066c70a8730cd3d4dc41b92d7a03e4c..108eaf55628029a6de8c23cd6486bdccc42c0364 100644 ---- a/src/tests/cmocka/test_kcm_json_marshalling.c -+++ b/src/tests/cmocka/test_kcm_json_marshalling.c -@@ -32,6 +32,12 @@ - - #define TEST_CREDS "TESTCREDS" - -+#define TEST_UUID_STR "5f8f296b-02be-4e86-9235-500e82354186" -+#define TEST_SEC_KEY_ONEDIGIT TEST_UUID_STR"-0" -+#define TEST_SEC_KEY_MULTIDIGITS TEST_UUID_STR"-123456" -+ -+#define TEST_SEC_KEY_NOSEP TEST_UUID_STR"+0" -+ - const struct kcm_ccdb_ops ccdb_mem_ops; - const struct kcm_ccdb_ops ccdb_sec_ops; - -@@ -188,6 +194,72 @@ static void test_kcm_ccache_marshall_unmarshall(void **state) - assert_int_equal(ret, EOK); - - assert_cc_equal(cc, cc2); -+ -+ /* This key is exactly one byte shorter than it should be */ -+ ret = sec_kv_to_ccache(test_ctx, -+ TEST_UUID_STR"-", -+ (const char *) data, -+ &owner, -+ &cc2); -+ assert_int_equal(ret, EINVAL); -+} -+ -+void test_sec_key_get_uuid(void **state) -+{ -+ errno_t ret; -+ uuid_t uuid; -+ char str_uuid[UUID_STR_SIZE]; -+ -+ uuid_clear(uuid); -+ ret = sec_key_get_uuid(TEST_SEC_KEY_ONEDIGIT, uuid); -+ assert_int_equal(ret, EOK); -+ uuid_unparse(uuid, str_uuid); -+ assert_string_equal(TEST_UUID_STR, str_uuid); -+ -+ ret = sec_key_get_uuid(TEST_SEC_KEY_NOSEP, uuid); -+ assert_int_equal(ret, EINVAL); -+ -+ ret = sec_key_get_uuid(TEST_UUID_STR, uuid); -+ assert_int_equal(ret, EINVAL); -+ -+ ret = sec_key_get_uuid(NULL, uuid); -+ assert_int_equal(ret, EINVAL); -+} -+ -+void test_sec_key_get_name(void **state) -+{ -+ const char *name; -+ -+ name = sec_key_get_name(TEST_SEC_KEY_ONEDIGIT); -+ assert_non_null(name); -+ assert_string_equal(name, "0"); -+ -+ name = sec_key_get_name(TEST_SEC_KEY_MULTIDIGITS); -+ assert_non_null(name); -+ assert_string_equal(name, "123456"); -+ -+ name = sec_key_get_name(TEST_UUID_STR); -+ assert_null(name); -+ -+ name = sec_key_get_name(TEST_SEC_KEY_NOSEP); -+ assert_null(name); -+ -+ name = sec_key_get_name(NULL); -+ assert_null(name); -+} -+ -+void test_sec_key_match_name(void **state) -+{ -+ assert_true(sec_key_match_name(TEST_SEC_KEY_ONEDIGIT, "0")); -+ assert_true(sec_key_match_name(TEST_SEC_KEY_MULTIDIGITS, "123456")); -+ -+ assert_false(sec_key_match_name(TEST_SEC_KEY_MULTIDIGITS, "0")); -+ assert_false(sec_key_match_name(TEST_SEC_KEY_ONEDIGIT, "123456")); -+ -+ assert_false(sec_key_match_name(TEST_UUID_STR, "0")); -+ assert_false(sec_key_match_name(TEST_SEC_KEY_NOSEP, "0")); -+ assert_false(sec_key_match_name(TEST_SEC_KEY_ONEDIGIT, NULL)); -+ assert_false(sec_key_match_name(NULL, "0")); - } - - int main(int argc, const char *argv[]) -@@ -205,6 +277,9 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall, - setup_kcm_marshalling, - teardown_kcm_marshalling), -+ cmocka_unit_test(test_sec_key_get_uuid), -+ cmocka_unit_test(test_sec_key_get_name), -+ cmocka_unit_test(test_sec_key_match_name), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.12.2 - diff --git a/0077-tcurl-add-support-for-ssl-and-raw-output.patch b/0077-tcurl-add-support-for-ssl-and-raw-output.patch deleted file mode 100644 index 35580f3..0000000 --- a/0077-tcurl-add-support-for-ssl-and-raw-output.patch +++ /dev/null @@ -1,1477 +0,0 @@ -From 300b9e9217ee1ed8d845ed2370c5ccf5c87afb36 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 24 Feb 2017 10:40:43 +0100 -Subject: [PATCH 77/97] tcurl: add support for ssl and raw output - -At first, this patch separates curl_easy handle from the multi-handle -processing and makes it encapsulated in custom tcurl_request structure. -This allows us to separate protocol initialization from its asynchonous -logic which gives us the ability to set different options for each -request without over-extending the parameter list. - -In this patch we implement options for peer verification for TLS-enabled -protocols and to return response with body and headers together. - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/tests/tcurl_test_tool.c | 41 +- - src/util/tev_curl.c | 992 +++++++++++++++++++++++++------------------- - src/util/tev_curl.h | 172 +++++++- - src/util/util_errors.c | 4 + - src/util/util_errors.h | 4 + - 5 files changed, 755 insertions(+), 458 deletions(-) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 2af950ebb76a22bdf4a6dfd58442b10486e64293..9a6266f89131ffd3a561e857af85df9854c44949 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -42,9 +42,7 @@ static void request_done(struct tevent_req *req) - struct tool_ctx *tool_ctx = tevent_req_callback_data(req, - struct tool_ctx); - -- tool_ctx->error = tcurl_http_recv(tool_ctx, req, -- &http_code, -- &outbuf); -+ tool_ctx->error = tcurl_request_recv(tool_ctx, req, &outbuf, &http_code); - talloc_zfree(req); - - if (tool_ctx->error != EOK) { -@@ -87,16 +85,17 @@ int main(int argc, const char *argv[]) - "The path to the HTTP server socket", NULL }, - { "get", 'g', POPT_ARG_NONE, NULL, 'g', "Perform a HTTP GET (default)", NULL }, - { "put", 'p', POPT_ARG_NONE, NULL, 'p', "Perform a HTTP PUT", NULL }, -- { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, - { "post", 'o', POPT_ARG_NONE, NULL, 'o', "Perform a HTTP POST", NULL }, -+ { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, - { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "Print response code and body", NULL }, - POPT_TABLEEND - }; - - struct tevent_req *req; - struct tevent_context *ev; -- enum tcurl_http_request req_type = TCURL_HTTP_GET; -+ enum tcurl_http_method method = TCURL_HTTP_GET; - struct tcurl_ctx *ctx; -+ struct tcurl_request *tcurl_req; - struct tool_ctx *tool_ctx; - - const char *urls[MAXREQ] = { 0 }; -@@ -111,16 +110,16 @@ int main(int argc, const char *argv[]) - while ((opt = poptGetNextOpt(pc)) > 0) { - switch (opt) { - case 'g': -- req_type = TCURL_HTTP_GET; -+ method = TCURL_HTTP_GET; - break; - case 'p': -- req_type = TCURL_HTTP_PUT; -- break; -- case 'd': -- req_type = TCURL_HTTP_DELETE; -+ method = TCURL_HTTP_PUT; - break; - case 'o': -- req_type = TCURL_HTTP_POST; -+ method = TCURL_HTTP_POST; -+ break; -+ case 'd': -+ method = TCURL_HTTP_DELETE; - break; - case 'v': - pc_verbose = 1; -@@ -146,7 +145,7 @@ int main(int argc, const char *argv[]) - } - - while ((extra_arg_ptr = poptGetArg(pc)) != NULL) { -- switch (req_type) { -+ switch(method) { - case TCURL_HTTP_GET: - case TCURL_HTTP_DELETE: - case TCURL_HTTP_POST: -@@ -203,14 +202,16 @@ int main(int argc, const char *argv[]) - } - - for (size_t i = 0; i < n_reqs; i++) { -- req = tcurl_http_send(tool_ctx, ev, ctx, -- req_type, -- socket_path, -- urls[i], -- headers, -- inbufs[i], -- 5); -- if (req == NULL) { -+ tcurl_req = tcurl_http(tool_ctx, method, socket_path, -+ urls[i], headers, inbufs[i]); -+ if (tcurl_req == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to create TCURL request\n"); -+ talloc_zfree(tool_ctx); -+ return 1; -+ } -+ -+ req = tcurl_request_send(tool_ctx, ev, ctx, tcurl_req, 10); -+ if (ctx == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, "Could not create request\n"); - talloc_zfree(tool_ctx); - return 1; -diff --git a/src/util/tev_curl.c b/src/util/tev_curl.c -index 645d1182d10f825f209f48e0ba7e6804dde1971c..c155f4c038d4215933ee30d41c694ad4a14ae132 100644 ---- a/src/util/tev_curl.c -+++ b/src/util/tev_curl.c -@@ -34,8 +34,8 @@ - #include "util/util.h" - #include "util/tev_curl.h" - --#define IOBUF_CHUNK 1024 --#define IOBUF_MAX 4096 -+#define TCURL_IOBUF_CHUNK 1024 -+#define TCURL_IOBUF_MAX 4096 - - static bool global_is_curl_initialized; - -@@ -71,39 +71,12 @@ struct tcurl_sock { - struct tevent_fd *fde; /* tevent tracker of the fd events */ - }; - --/** -- * @brief A state of one curl transfer -- * -- * Intentionally breaking the tevent coding style here and making the struct available -- * in the whole module so that the structure is available to curl callbacks that -- * need to access the state of the transfer. -- * -- * @see handle_curlmsg_done() -- */ --struct tcurl_http_state { -- /* Input parameters */ -- struct tcurl_ctx *tctx; -- const char *socket_path; -- const char *url; -- int timeout; -- struct sss_iobuf *inbuf; -- -- /* Internal state */ -- CURL *http_handle; -- struct curl_slist *curl_headers; -- -- /* Output data */ -- struct sss_iobuf *outbuf; -- long http_code; --}; -+static void tcurl_request_done(struct tevent_req *req, -+ errno_t process_error, -+ int response_code); - - static errno_t curl_code2errno(CURLcode crv) - { -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "curl error %d: %s\n", crv, curl_easy_strerror(crv)); -- } -- - switch (crv) { - /* HTTP error does not fail the whole request, just returns the error - * separately -@@ -121,6 +94,47 @@ static errno_t curl_code2errno(CURLcode crv) - return ENOMEM; - case CURLE_OPERATION_TIMEDOUT: - return ETIMEDOUT; -+ case CURLE_SSL_ISSUER_ERROR: -+ case CURLE_SSL_CACERT_BADFILE: -+ case CURLE_SSL_CACERT: -+ case CURLE_SSL_CERTPROBLEM: -+ return ERR_INVALID_CERT; -+ -+ case CURLE_SSL_CRL_BADFILE: -+ case CURLE_SSL_SHUTDOWN_FAILED: -+ case CURLE_SSL_ENGINE_INITFAILED: -+ case CURLE_USE_SSL_FAILED: -+ case CURLE_SSL_CIPHER: -+ case CURLE_SSL_ENGINE_SETFAILED: -+ case CURLE_SSL_ENGINE_NOTFOUND: -+ case CURLE_SSL_CONNECT_ERROR: -+ return ERR_SSL_FAILURE; -+ case CURLE_PEER_FAILED_VERIFICATION: -+ return ERR_UNABLE_TO_VERIFY_PEER; -+ case CURLE_COULDNT_RESOLVE_HOST: -+ return ERR_UNABLE_TO_RESOLVE_HOST; -+ default: -+ break; -+ } -+ -+ return EIO; -+} -+ -+static errno_t curlm_code2errno(CURLcode crv) -+{ -+ switch (crv) { -+ case CURLM_OK: -+ return EOK; -+ case CURLM_BAD_SOCKET: -+ return EPIPE; -+ case CURLM_OUT_OF_MEMORY: -+ return ENOMEM; -+ case CURLM_BAD_HANDLE: -+ case CURLM_BAD_EASY_HANDLE: -+ case CURLM_UNKNOWN_OPTION: -+ return EINVAL; -+ case CURLM_INTERNAL_ERROR: -+ return ERR_INTERNAL; - default: - break; - } -@@ -145,22 +159,6 @@ static errno_t tcurl_global_init(void) - return EOK; - } - --static const char *http_req2str(enum tcurl_http_request req) --{ -- switch (req) { -- case TCURL_HTTP_GET: -- return "GET"; -- case TCURL_HTTP_PUT: -- return "PUT"; -- case TCURL_HTTP_DELETE: -- return "DELETE"; -- case TCURL_HTTP_POST: -- return "POST"; -- } -- -- return "Uknown request type"; --} -- - static int curl2tev_flags(int curlflags) - { - int flags = 0; -@@ -185,9 +183,9 @@ static void handle_curlmsg_done(CURLMsg *message) - CURL *easy_handle; - CURLcode crv; - struct tevent_req *req; -+ long response_code = 0; - char *done_url; - errno_t ret; -- struct tcurl_http_state *state; - - easy_handle = message->easy_handle; - if (easy_handle == NULL) { -@@ -198,9 +196,8 @@ static void handle_curlmsg_done(CURLMsg *message) - if (DEBUG_IS_SET(SSSDBG_TRACE_FUNC)) { - crv = curl_easy_getinfo(easy_handle, CURLINFO_EFFECTIVE_URL, &done_url); - if (crv != CURLE_OK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- "Cannot get CURLINFO_EFFECTIVE_URL [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot get CURLINFO_EFFECTIVE_URL " -+ "[%d]: %s\n", crv, curl_easy_strerror(crv)); - /* not fatal since we need this only for debugging */ - } else { - DEBUG(SSSDBG_TRACE_FUNC, "Handled %s\n", done_url); -@@ -209,38 +206,32 @@ static void handle_curlmsg_done(CURLMsg *message) - - crv = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, (void *) &req); - if (crv != CURLE_OK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Cannot get CURLINFO_PRIVATE [%d]: %s\n", -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get CURLINFO_PRIVATE [%d]: %s\n", - crv, curl_easy_strerror(crv)); -- return; -- } -- -- state = tevent_req_data(req, struct tcurl_http_state); -- if (state == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "BUG: request has no state\n"); -- tevent_req_error(req, EFAULT); -- return; -+ ret = curl_code2errno(crv); -+ goto done; - } - - ret = curl_code2errno(message->data.result); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "curl operation failed [%d]: %s\n", ret, sss_strerror(ret)); -- tevent_req_error(req, ret); -- return; -+ DEBUG(SSSDBG_OP_FAILURE, "CURL operation failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; - } - -- /* If there was no fatal error, let's read the HTTP error code and mark -- * the request as done -- */ -- crv = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &state->http_code); -+ /* If there was no fatal error, let's read the response code -+ * and mark the request as done */ -+ crv = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &response_code); - if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, "Cannot get HTTP status code\n"); -- tevent_req_error(req, EFAULT); -- return; -+ DEBUG(SSSDBG_OP_FAILURE, "Cannot get response code\n"); -+ ret = curl_code2errno(crv); -+ goto done; - } - -- tevent_req_done(req); -+ ret = EOK; -+ -+done: -+ tcurl_request_done(req, ret, response_code); - } - - static void process_curl_activity(struct tcurl_ctx *tctx) -@@ -551,346 +542,42 @@ fail: - return NULL; - } - --static errno_t tcurl_add_headers(struct tcurl_http_state *state, -- const char *headers[]); -- --static errno_t tcurl_set_options(struct tcurl_http_state *state, -- struct tevent_req *req, -- enum tcurl_http_request req_type); -- --static int tcurl_http_cleanup_handle(TALLOC_CTX *ptr); -- --static size_t tcurl_http_write_data(char *ptr, -- size_t size, -- size_t nmemb, -- void *userdata); -- --static size_t tcurl_http_read_data(void *ptr, -- size_t size, -- size_t nmemb, -- void *userdata); -- --struct tevent_req *tcurl_http_send(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct tcurl_ctx *tctx, -- enum tcurl_http_request req_type, -- const char *socket_path, -- const char *url, -- const char *headers[], -- struct sss_iobuf *req_data, -- int timeout) --{ -- errno_t ret; -- struct tevent_req *req; -- struct tcurl_http_state *state; -- -- req = tevent_req_create(mem_ctx, &state, struct tcurl_http_state); -- if (req == NULL) { -- return NULL; -- } -- -- state->tctx = tctx; -- state->socket_path = socket_path; -- state->url = url; -- state->inbuf = req_data; -- state->timeout = timeout; -- -- state->outbuf = sss_iobuf_init_empty(state, IOBUF_CHUNK, IOBUF_MAX); -- if (state->outbuf == NULL) { -- ret = ENOMEM; -- goto fail; -- } -- -- DEBUG(SSSDBG_TRACE_FUNC, -- "HTTP request %s for URL %s\n", http_req2str(req_type), url); -- talloc_set_destructor((TALLOC_CTX *) state, tcurl_http_cleanup_handle); -- -- /* All transfer share the same multi handle, but each trasfer has its own -- * easy handle we can use to set per-transfer options -- */ -- state->http_handle = curl_easy_init(); -- if (state->http_handle == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "curl_easy_init failed\n"); -- ret = EIO; -- goto fail; -- } -- -- ret = tcurl_add_headers(state, headers); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Failed to set CURL headers [%d]: %s\n", ret, sss_strerror(ret)); -- goto fail; -- } -- -- ret = tcurl_set_options(state, req, req_type); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Failed to set CURL options [%d]: %s\n", ret, sss_strerror(ret)); -- goto fail; -- } -- -- /* Pass control to the curl handling which will mark the request as -- * done -- */ -- curl_multi_add_handle(tctx->multi_handle, state->http_handle); -- -- return req; -- --fail: -- tevent_req_error(req, ret); -- tevent_req_post(req, ev); -- return req; --} -- --static int tcurl_http_cleanup_handle(TALLOC_CTX *ptr) --{ -- struct tcurl_http_state *state = talloc_get_type(ptr, struct tcurl_http_state); -- -- if (state == NULL) { -- return 0; -- } -- -- /* it is safe to pass NULL here */ -- curl_multi_remove_handle(state->tctx->multi_handle, state->http_handle); -- curl_slist_free_all(state->curl_headers); -- curl_easy_cleanup(state->http_handle); -- return 0; --} -- --static errno_t tcurl_add_headers(struct tcurl_http_state *state, -- const char *headers[]) --{ -- if (headers == NULL) { -- return EOK; -- } -- -- /* The headers will be freed later in tcurl_http_cleanup_handle */ -- for (int i = 0; headers[i] != NULL; i++) { -- state->curl_headers = curl_slist_append(state->curl_headers, headers[i]); -- if (state->curl_headers == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add header %s\n", headers[i]); -- return ENOMEM; -- } -- } -- -- /* Add a dummy header to suppress libcurl adding Expect 100-continue which -- * was causing libcurl to always wait for the internal timeout when sending -- * a PUT/PATCH request -- */ -- state->curl_headers = curl_slist_append(state->curl_headers, "Expect:"); -- if (state->curl_headers == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add the dummy expect header\n"); -- return ENOMEM; -- } -- -- return EOK; --} -- --static errno_t tcurl_set_common_options(struct tcurl_http_state *state, -- struct tevent_req *req) --{ -- CURLcode crv; -- -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_HTTPHEADER, -- state->curl_headers); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set HTTP headers [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_UNIX_SOCKET_PATH, -- state->socket_path); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set UNIX socket path %s [%d]: %s\n", -- state->socket_path, crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- crv = curl_easy_setopt(state->http_handle, CURLOPT_URL, state->url); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set URL %s [%d]: %s\n", -- state->url, crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- crv = curl_easy_setopt(state->http_handle, CURLOPT_PRIVATE, req); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set private data [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- if (state->timeout > 0) { -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_TIMEOUT, -- state->timeout); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set timeout [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- } -- -- return EOK; --} -- --static errno_t tcurl_set_write_options(struct tcurl_http_state *state) --{ -- CURLcode crv; -- -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_WRITEFUNCTION, -- tcurl_http_write_data); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set write function [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_WRITEDATA, -- state->outbuf); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set write data [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- return EOK; --} -- --static errno_t tcurl_set_read_options(struct tcurl_http_state *state) --{ -- CURLcode crv; -- -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_READFUNCTION, -- tcurl_http_read_data); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set read function [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_READDATA, -- state->inbuf); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set read data [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- return EOK; --} -- --static errno_t tcurl_set_options(struct tcurl_http_state *state, -- struct tevent_req *req, -- enum tcurl_http_request req_type) --{ -- CURLcode crv; -- errno_t ret; -- -- ret = tcurl_set_common_options(state, req); -- if (ret != EOK) { -- return ret; -- } -- -- ret = tcurl_set_write_options(state); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Failed to set write callbacks [%d]: %s\n", -- ret, sss_strerror(ret)); -- return ret; -- } -- -- switch (req_type) { -- case TCURL_HTTP_POST: -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_CUSTOMREQUEST, -- "POST"); -- break; -- case TCURL_HTTP_PUT: -- /* CURLOPT_UPLOAD enables HTTP_PUT */ -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_UPLOAD, -- 1L); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set the uplodad option [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- /* Causes libcurl to add a sane Content-Length header */ -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_INFILESIZE_LARGE, -- (curl_off_t) sss_iobuf_get_size(state->inbuf)); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set CURLOPT_INFILESIZE_LARGE [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- -- ret = tcurl_set_read_options(state); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Failed to set write callbacks [%d]: %s\n", -- ret, sss_strerror(ret)); -- return ret; -- } -- break; -- case TCURL_HTTP_GET: -- /* GET just needs the write callbacks, nothing to do here.. */ -- break; -- case TCURL_HTTP_DELETE: -- crv = curl_easy_setopt(state->http_handle, -- CURLOPT_CUSTOMREQUEST, -- "DELETE"); -- if (crv != CURLE_OK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to set the uplodad option [%d]: %s\n", -- crv, curl_easy_strerror(crv)); -- return EIO; -- } -- break; -- default: -- return EFAULT; -- } -- -- return EOK; --} -- --static size_t tcurl_http_write_data(char *ptr, -- size_t size, -- size_t nmemb, -- void *userdata) -+#define tcurl_set_option(tcurl_req, option, value) \ -+({ \ -+ CURLcode __curl_code; \ -+ errno_t __ret; \ -+ \ -+ __curl_code = curl_easy_setopt((tcurl_req)->curl_easy_handle, \ -+ (option), (value)); \ -+ if (__curl_code == CURLE_OK) { \ -+ __ret = EOK; \ -+ } else { \ -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to set CURL option %s [%d]: %s\n", \ -+ #option, __curl_code, curl_easy_strerror(__curl_code)); \ -+ __ret = curl_code2errno(__curl_code); \ -+ } \ -+ __ret; \ -+}) -+ -+static size_t tcurl_write_data(char *ptr, -+ size_t size, -+ size_t nmemb, -+ void *userdata) - { - errno_t ret; - size_t realsize = size * nmemb; -- struct sss_iobuf *outbuf = talloc_get_type(userdata, struct sss_iobuf); -+ struct sss_iobuf *outbuf; -+ -+ outbuf = talloc_get_type(userdata, struct sss_iobuf); - - DEBUG(SSSDBG_TRACE_INTERNAL, "---> begin libcurl data\n"); - DEBUG(SSSDBG_TRACE_INTERNAL, "%s\n", ptr); - DEBUG(SSSDBG_TRACE_INTERNAL, "<--- end libcurl data\n"); - -- ret = sss_iobuf_write_len(outbuf, (uint8_t *) ptr, realsize); -+ ret = sss_iobuf_write_len(outbuf, (uint8_t *)ptr, realsize); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Failed to write data to buffer [%d]: %s\n", ret, sss_strerror(ret)); -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to write data to buffer [%d]: %s\n", -+ ret, sss_strerror(ret)); - /* zero signifies an EOF */ - return 0; - } -@@ -898,14 +585,16 @@ static size_t tcurl_http_write_data(char *ptr, - return realsize; - } - --static size_t tcurl_http_read_data(void *ptr, -- size_t size, -- size_t nmemb, -- void *userdata) -+static size_t tcurl_read_data(void *ptr, -+ size_t size, -+ size_t nmemb, -+ void *userdata) - { - errno_t ret; - size_t readbytes; -- struct sss_iobuf *inbuf = (struct sss_iobuf *) userdata; -+ struct sss_iobuf *inbuf; -+ -+ inbuf = talloc_get_type(userdata, struct sss_iobuf); - - if (inbuf == NULL) { - return CURL_READFUNC_ABORT; -@@ -919,22 +608,487 @@ static size_t tcurl_http_read_data(void *ptr, - return readbytes; - } - --int tcurl_http_recv(TALLOC_CTX *mem_ctx, -- struct tevent_req *req, -- int *_http_code, -- struct sss_iobuf **_outbuf) -+ -+struct tcurl_request { -+ CURL *curl_easy_handle; -+ -+ struct sss_iobuf *body; -+ struct curl_slist *headers; -+ -+ const char *url; -+ const char *socket; -+ -+ /* Associated tcurl context if this request is in progress. */ -+ struct tcurl_ctx *tcurl_ctx; -+}; -+ -+struct tcurl_request_state { -+ struct tcurl_request *tcurl_req; -+ struct sss_iobuf *response; -+ int response_code; -+}; -+ -+struct tevent_req * -+tcurl_request_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct tcurl_ctx *tcurl_ctx, -+ struct tcurl_request *tcurl_req, -+ long int timeout) - { -- struct tcurl_http_state *state = tevent_req_data(req, struct tcurl_http_state); -+ struct tcurl_request_state *state; -+ struct tevent_req *req; -+ CURLMcode curl_code; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct tcurl_request_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); -+ return NULL; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Sending TCURL request for %s, at socket %s\n", -+ tcurl_req->url == NULL ? "" : tcurl_req->url, -+ tcurl_req->socket == NULL ? "" : tcurl_req->socket); -+ -+ state->tcurl_req = talloc_steal(state, tcurl_req); -+ -+ state->response = sss_iobuf_init_empty(state, TCURL_IOBUF_CHUNK, TCURL_IOBUF_MAX); -+ if (state->response == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_PRIVATE, req); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_TIMEOUT, timeout); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_WRITEFUNCTION, tcurl_write_data); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_WRITEDATA, state->response); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ if (tcurl_req->body != NULL) { -+ ret = tcurl_set_option(tcurl_req, CURLOPT_READFUNCTION, tcurl_read_data); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_READDATA, tcurl_req->body); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ curl_code = curl_multi_add_handle(tcurl_ctx->multi_handle, -+ tcurl_req->curl_easy_handle); -+ if (curl_code != CURLM_OK) { -+ ret = curlm_code2errno(curl_code); -+ goto done; -+ } -+ -+ tcurl_req->tcurl_ctx = tcurl_ctx; -+ -+ ret = EAGAIN; -+ -+done: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ tevent_req_post(req, ev); -+ } else if (ret != EAGAIN) { -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ } -+ -+ return req; -+} -+ -+static void tcurl_request_done(struct tevent_req *req, -+ errno_t process_error, -+ int response_code) -+{ -+ struct tcurl_request_state *state; -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "TCURL request finished [%d]: %s\n", -+ process_error, sss_strerror(process_error)); -+ -+ if (req == NULL) { -+ /* To handle case where we fail to obtain request from private data. */ -+ DEBUG(SSSDBG_MINOR_FAILURE, "No tevent request provided!\n"); -+ return; -+ } -+ -+ state = tevent_req_data(req, struct tcurl_request_state); -+ -+ curl_multi_remove_handle(state->tcurl_req->tcurl_ctx->multi_handle, -+ state->tcurl_req->curl_easy_handle); -+ -+ /* This request is no longer associated with tcurl context. */ -+ state->tcurl_req->tcurl_ctx = NULL; -+ -+ if (process_error != EOK) { -+ tevent_req_error(req, process_error); -+ return; -+ } -+ -+ state->response_code = response_code; -+ -+ tevent_req_done(req); -+ return; -+} -+ -+errno_t tcurl_request_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ struct sss_iobuf **_response, -+ int *_response_code) -+{ -+ struct tcurl_request_state *state; -+ state = tevent_req_data(req, struct tcurl_request_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - -- if (_http_code != NULL) { -- *_http_code = state->http_code; -+ if (_response != NULL) { -+ *_response = talloc_steal(mem_ctx, state->response); - } - -- if (_outbuf != NULL) { -- *_outbuf = talloc_steal(mem_ctx, state->outbuf); -+ if (_response_code != NULL) { -+ *_response_code = state->response_code; -+ } -+ -+ return EOK; -+} -+ -+static struct curl_slist * -+tcurl_add_header(struct curl_slist *slist, const char *header) -+{ -+ struct curl_slist *new; -+ -+ new = curl_slist_append(slist, header); -+ if (new == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add header %s\n", header); -+ if (slist != NULL) { -+ curl_slist_free_all(slist); -+ } -+ -+ return NULL; -+ } -+ -+ return new; -+} -+ -+static errno_t -+tcurl_construct_headers(const char **headers, -+ struct curl_slist **_slist) -+{ -+ struct curl_slist *slist = NULL; -+ int i; -+ -+ if (headers == NULL || headers[0] == NULL) { -+ *_slist = NULL; -+ return EOK; -+ } -+ -+ for (i = 0; headers[i] != NULL; i++) { -+ slist = tcurl_add_header(slist, headers[i]); -+ if (slist == NULL) { -+ return ENOMEM; -+ } -+ } -+ -+ /* Add a dummy header to suppress libcurl adding Expect 100-continue which -+ * was causing libcurl to always wait for the internal timeout when sending -+ * a PUT/POST request because secrets responder does not implement this. -+ */ -+ slist = tcurl_add_header(slist, "Expect: "); -+ if (slist == NULL) { -+ return ENOMEM; -+ } -+ -+ *_slist = slist; -+ -+ return EOK; -+} -+ -+static int -+tcurl_request_destructor(struct tcurl_request *tcurl_req) -+{ -+ if (tcurl_req->tcurl_ctx != NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "Terminating TCURL request...\n"); -+ curl_multi_remove_handle(tcurl_req->tcurl_ctx->multi_handle, -+ tcurl_req->curl_easy_handle); -+ } -+ -+ if (tcurl_req->headers != NULL) { -+ curl_slist_free_all(tcurl_req->headers); -+ } -+ -+ if (tcurl_req->curl_easy_handle != NULL) { -+ curl_easy_cleanup(tcurl_req->curl_easy_handle); - } - - return 0; - } -+ -+static struct tcurl_request * -+tcurl_request_create(TALLOC_CTX *mem_ctx, -+ const char *socket_path, -+ const char *url, -+ const char **headers, -+ struct sss_iobuf *body) -+{ -+ struct tcurl_request *tcurl_req; -+ errno_t ret; -+ -+ tcurl_req = talloc_zero(mem_ctx, struct tcurl_request); -+ if (tcurl_req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); -+ return NULL; -+ } -+ -+ if (url == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "URL cannot be NULL!\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ /* Setup a curl easy handle. This handle contains state for the request -+ * and is later associated with curl multi handle which performs -+ * asynchronous processing. */ -+ tcurl_req->curl_easy_handle = curl_easy_init(); -+ if (tcurl_req->curl_easy_handle == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize curl easy handle!\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ tcurl_req->url = talloc_strdup(tcurl_req, url); -+ if (tcurl_req->url == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ if (socket_path != NULL) { -+ tcurl_req->socket = talloc_strdup(tcurl_req, socket_path); -+ if (tcurl_req->socket == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ ret = tcurl_construct_headers(headers, &tcurl_req->headers); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to construct headers [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ tcurl_req->body = body; -+ -+ talloc_set_destructor(tcurl_req, tcurl_request_destructor); -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_URL, url); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ if (socket_path != NULL) { -+ ret = tcurl_set_option(tcurl_req, CURLOPT_UNIX_SOCKET_PATH, socket_path); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ if (body != NULL) { -+ /* Curl will tell the underlying protocol about incoming data length. -+ * In case of HTTP it will add a sane Content-Length header. */ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_INFILESIZE_LARGE, -+ (curl_off_t)sss_iobuf_get_size(body)); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(tcurl_req); -+ return NULL; -+ } -+ -+ return tcurl_req; -+} -+ -+struct tcurl_request *tcurl_http(TALLOC_CTX *mem_ctx, -+ enum tcurl_http_method method, -+ const char *socket_path, -+ const char *url, -+ const char **headers, -+ struct sss_iobuf *body) -+{ -+ struct tcurl_request *tcurl_req; -+ errno_t ret; -+ -+ tcurl_req = tcurl_request_create(mem_ctx, socket_path, url, headers, body); -+ if (tcurl_req == NULL) { -+ return NULL; -+ } -+ -+ /* Set HTTP specific options. */ -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_HTTPHEADER, tcurl_req->headers); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ switch (method) { -+ case TCURL_HTTP_GET: -+ /* Nothing to do here. GET is default. */ -+ break; -+ case TCURL_HTTP_PUT: -+ ret = tcurl_set_option(tcurl_req, CURLOPT_UPLOAD, 1L); -+ if (ret != EOK) { -+ goto done; -+ } -+ break; -+ case TCURL_HTTP_POST: -+ ret = tcurl_set_option(tcurl_req, CURLOPT_CUSTOMREQUEST, "POST"); -+ if (ret != EOK) { -+ goto done; -+ } -+ break; -+ case TCURL_HTTP_DELETE: -+ ret = tcurl_set_option(tcurl_req, CURLOPT_CUSTOMREQUEST, "DELETE"); -+ if (ret != EOK) { -+ goto done; -+ } -+ break; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(tcurl_req); -+ return NULL; -+ } -+ -+ return tcurl_req; -+} -+ -+struct tevent_req *tcurl_http_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct tcurl_ctx *tcurl_ctx, -+ enum tcurl_http_method method, -+ const char *socket_path, -+ const char *url, -+ const char **headers, -+ struct sss_iobuf *body, -+ int timeout) -+{ -+ struct tcurl_request *tcurl_req; -+ struct tevent_req *req; -+ -+ tcurl_req = tcurl_http(mem_ctx, method, socket_path, url, headers, body); -+ if (tcurl_req == NULL) { -+ return NULL; -+ } -+ -+ req = tcurl_request_send(mem_ctx, ev, tcurl_ctx, tcurl_req, timeout); -+ if (req == NULL) { -+ talloc_free(tcurl_req); -+ } -+ -+ return req; -+} -+ -+errno_t tcurl_http_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ int *_http_code, -+ struct sss_iobuf **_response) -+{ -+ return tcurl_request_recv(mem_ctx, req, _response, _http_code); -+} -+ -+errno_t tcurl_req_enable_rawoutput(struct tcurl_request *tcurl_req) -+{ -+ return tcurl_set_option(tcurl_req, CURLOPT_HEADER, 1L); -+} -+ -+errno_t tcurl_req_verify_peer(struct tcurl_request *tcurl_req, -+ const char *capath, -+ const char *cacert, -+ bool verify_peer, -+ bool verify_host) -+{ -+ errno_t ret; -+ -+ long peer = verify_peer ? 1L : 0L; -+ long host = verify_host ? 2L : 0L; -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_SSL_VERIFYPEER, peer); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_SSL_VERIFYHOST, host); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ if (capath != NULL) { -+ ret = tcurl_set_option(tcurl_req, CURLOPT_CAPATH, capath); -+ if (ret != EOK) { -+ return ret; -+ } -+ } -+ -+ if (cacert != NULL) { -+ ret = tcurl_set_option(tcurl_req, CURLOPT_CAINFO, cacert); -+ if (ret != EOK) { -+ return ret; -+ } -+ } -+ -+ return EOK; -+} -+ -+errno_t tcurl_req_set_client_cert(struct tcurl_request *tcurl_req, -+ const char *cert, -+ const char *key) -+{ -+ errno_t ret; -+ -+ if (cert == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "You must specify client certificate!\n"); -+ return EINVAL; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_SSLCERT, cert); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ if (key != NULL) { -+ /* If client's private key is in separate file. */ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_SSLKEY, key); -+ if (ret != EOK) { -+ return ret; -+ } -+ } -+ -+ return EOK; -+} -diff --git a/src/util/tev_curl.h b/src/util/tev_curl.h -index 444eb286e09d189b4588e2b2152b5202df3914d8..933abcb9b531412737e8fcf391644d828b125cf8 100644 ---- a/src/util/tev_curl.h -+++ b/src/util/tev_curl.h -@@ -27,14 +27,16 @@ - - #include "util/sss_iobuf.h" - -+struct tcurl_request; -+ - /** -- * @brief Supported HTTP requests -+ * @brief Supported HTTP methods - */ --enum tcurl_http_request { -+enum tcurl_http_method { - TCURL_HTTP_GET, - TCURL_HTTP_PUT, -- TCURL_HTTP_DELETE, - TCURL_HTTP_POST, -+ TCURL_HTTP_DELETE, - }; - - /** -@@ -46,16 +48,95 @@ struct tcurl_ctx *tcurl_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev); - - /** -+ * @brief Run a single asynchronous TCURL request. -+ * -+ * If the libcurl processing succeeds but we obtain a protocol error we still -+ * mark the tevent request as successful. The protocol error is return from -+ * @tcurl_request_recv as an output parameter. -+ * -+ * @param[in] mem_ctx The talloc context that owns the request -+ * @param[in] ev Event loop context -+ * @param[in] tctx Use tcurl_init to get this context -+ * @param[in] tcurl_req TCURL request -+ * @param[in] timeout The request timeout in seconds. Use 0 if you want -+ * to use the default libcurl timeout. -+ * -+ * @returns A tevent request or NULL on allocation error. On other errors, we -+ * try to set the errno as event error code and run it to completion so that -+ * the programmer can use tcurl_request_recv to read the error code. -+ * -+ * @see tcurl_init -+ * @see tcurl_http -+ * @see tcurl_request_recv -+ */ -+struct tevent_req * -+tcurl_request_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct tcurl_ctx *tcurl_ctx, -+ struct tcurl_request *tcurl_req, -+ long int timeout); -+ -+/** -+ * @brief Receive a result of a single asynchronous TCURL request. -+ * -+ * @param[in] mem_ctx The talloc context that owns the response -+ * @param[in] req The request previously obtained with tcurl_request_send -+ * @param[out] _response Response to the request -+ * @param[out] _response_code Protocol response code (may indicate a protocl error) -+ * -+ * @returns The error code of the curl request (not the HTTP code!) -+ */ -+errno_t tcurl_request_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ struct sss_iobuf **_response, -+ int *_response_code); -+ -+/** -+ * @brief Create a HTTP request. -+ * -+ * Use this if you need better control over the request options. -+ * -+ * Headers are a NULL-terminated array of strings such as: -+ * static const char *headers[] = { -+ * "Content-type: application/octet-stream", -+ * NULL, -+ * }; -+ * -+ * @param[in] mem_ctx The talloc context that owns the tcurl_request -+ * @param[in] method TCURL HTTP method -+ * @param[in] socket_path The path to the UNIX socket to forward the -+ * request to, may be NULL. -+ * @param[in] url The request URL, cannot be NULL. -+ * @param[in] headers A NULL-terminated array of strings to use -+ * as additional HTTP headers. Pass NULL if you -+ * don't need any additional headers. -+ * @param[in] body The HTTP request input data. For some request -+ * types like DELETE, this is OK to leave as NULL. -+ * -+ * @returns A tcurl_request that can be later started with tcurl_request_send -+ * or NULL on error. -+ * -+ * @see tcurl_init -+ * @see tcurl_request_send -+ * @see tcurl_request_recv -+ */ -+struct tcurl_request *tcurl_http(TALLOC_CTX *mem_ctx, -+ enum tcurl_http_method method, -+ const char *socket_path, -+ const char *url, -+ const char **headers, -+ struct sss_iobuf *body); -+ -+/** - * @brief Run a single asynchronous HTTP request. - * -- * Currently only UNIX sockets at socket_path are supported. -+ * Use this if you do not need control over additional request options. - * - * If the request runs into completion, but reports a failure with HTTP return - * code, the request will be marked as done. Only if the request cannot run at - * all (if e.g. the socket is unreachable), the request will fail completely. - * -- * Headers are a NULL-terminated -- * array of strings such as: -+ * Headers are a NULL-terminated array of strings such as: - * static const char *headers[] = { - * "Content-type: application/octet-stream", - * NULL, -@@ -63,15 +144,15 @@ struct tcurl_ctx *tcurl_init(TALLOC_CTX *mem_ctx, - * - * @param[in] mem_ctx The talloc context that owns the iobuf - * @param[in] ev Event loop context -- * @param[in] tctx Use tcurl_init to get this context -- * @param[in] req_type The request type -+ * @param[in] tcurl_ctx Use tcurl_init to get this context -+ * @param[in] method HTTP method - * @param[in] socket_path The path to the UNIX socket to forward the -- * request to -- * @param[in] url The request URL -+ * request to, may be NULL. -+ * @param[in] url The request URL, cannot be NULL. - * @param[in] headers A NULL-terminated array of strings to use - * as additional HTTP headers. Pass NULL if you - * don't need any additional headers. -- * @param[in] req_data The HTTP request input data. For some request -+ * @param[in] body The HTTP request input data. For some request - * types like DELETE, this is OK to leave as NULL. - * @param[in] timeout The request timeout in seconds. Use 0 if you want - * to use the default libcurl timeout. -@@ -85,12 +166,12 @@ struct tcurl_ctx *tcurl_init(TALLOC_CTX *mem_ctx, - */ - struct tevent_req *tcurl_http_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, -- struct tcurl_ctx *tctx, -- enum tcurl_http_request req_type, -+ struct tcurl_ctx *tcurl_ctx, -+ enum tcurl_http_method method, - const char *socket_path, - const char *url, -- const char *headers[], -- struct sss_iobuf *req_data, -+ const char **headers, -+ struct sss_iobuf *body, - int timeout); - - /** -@@ -104,9 +185,62 @@ struct tevent_req *tcurl_http_send(TALLOC_CTX *mem_ctx, - * - * @returns The error code of the curl request (not the HTTP code!) - */ --int tcurl_http_recv(TALLOC_CTX *mem_ctx, -- struct tevent_req *req, -- int *_http_code, -- struct sss_iobuf **_outbuf); -+errno_t tcurl_http_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ int *_http_code, -+ struct sss_iobuf **_response); -+ -+/** -+ * @brief We are usually interested only in the reply body without protocol -+ * headers. Call this function on tcurl_request, if you want to include -+ * complete protocol response in the output buffer. -+ * -+ * @param[in] tcurl_request -+ * -+ * @returns errno code -+ * -+ * @see tcurl_http -+ */ -+errno_t tcurl_req_enable_rawoutput(struct tcurl_request *tcurl_req); -+ -+/** -+ * @brief TLS is enabled automatically by providing an URL that points to -+ * TLS-enabled protocol such as https. If you want to provide different -+ * path to CA directory or disable peer/hostname check explicitly, use -+ * this function on tcurl_request. -+ * -+ * @param[in] tcurl_request -+ * @param[in] capath Path to directory containing installed CA certificates. -+ * If not set, libcurl default is used. -+ * @param[ing cacert CA certificate. If NULL it is found in @capath. -+ * @param[in] verify_peer If false, the peer certificate is not verified. -+ * @param[in] verify_host If false, the host name provided in remote -+ * certificate may differ from the actual host name. -+ * -+ * @returns errno code -+ * -+ * @see tcurl_http -+ */ -+errno_t tcurl_req_verify_peer(struct tcurl_request *tcurl_req, -+ const char *capath, -+ const char *cacert, -+ bool verify_peer, -+ bool verify_host); -+/** -+ * @brief Some server require client verification during TLS setup. You can -+ * provide path to client's certificate file. If this file does not contain -+ * private key, you can specify a different file the holds the private key. -+ * -+ * @param[in] tcurl_request -+ * @param[in] cert Path to client's certificate. -+ * @param[in] key Path to client's private key. -+ * -+ * @returns errno code -+ * -+ * @see tcurl_http -+ */ -+errno_t tcurl_req_set_client_cert(struct tcurl_request *tcurl_req, -+ const char *cert, -+ const char *key); - - #endif /* __TEV_CURL_H */ -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 60c2f439b3e39b1dbff353e429114cb5a3070052..466a3b4062f39b29d831a5d8a62dc8d576eb2e97 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -111,6 +111,10 @@ struct err_string error_to_str[] = { - { "Credential cache name not allowed" }, /* ERR_KCM_WRONG_CCNAME_FORMAT */ - { "Cannot encode a JSON object to string" }, /* ERR_JSON_ENCODING */ - { "Cannot decode a JSON object from string" }, /* ERR_JSON_DECODING */ -+ { "Invalid certificate provided" }, /* ERR_INVALID_CERT */ -+ { "Unable to initialize SSL" }, /* ERR_SSL_FAILURE */ -+ { "Unable to verify peer" }, /* ERR_UNABLE_TO_VERIFY_PEER */ -+ { "Unable to resolve host" }, /* ERR_UNABLE_TO_RESOLVE_HOST */ - { "ERR_LAST" } /* ERR_LAST */ - }; - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 4e9da814702e2cd46edc52fd5c2ae5f640602609..2f90c0a5d65325a431a8e4d9a480170808c9198e 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -133,6 +133,10 @@ enum sssd_errors { - ERR_KCM_WRONG_CCNAME_FORMAT, - ERR_JSON_ENCODING, - ERR_JSON_DECODING, -+ ERR_INVALID_CERT, -+ ERR_SSL_FAILURE, -+ ERR_UNABLE_TO_VERIFY_PEER, -+ ERR_UNABLE_TO_RESOLVE_HOST, - ERR_LAST /* ALWAYS LAST */ - }; - --- -2.12.2 - diff --git a/0078-tcurl-test-refactor-so-new-options-can-be-added-more.patch b/0078-tcurl-test-refactor-so-new-options-can-be-added-more.patch deleted file mode 100644 index bff324f..0000000 --- a/0078-tcurl-test-refactor-so-new-options-can-be-added-more.patch +++ /dev/null @@ -1,437 +0,0 @@ -From b800a6d09244359959404aca81c6796a58cafbcb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 24 Feb 2017 12:23:01 +0100 -Subject: [PATCH 78/97] tcurl test: refactor so new options can be added more - easily - -Just to make the tool a little bit nicer and more flexible. - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/tests/tcurl_test_tool.c | 334 +++++++++++++++++++++++++++----------------- - 1 file changed, 209 insertions(+), 125 deletions(-) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 9a6266f89131ffd3a561e857af85df9854c44949..e5fc9705db415650d849b89c3d18e41574b7e28b 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -28,26 +28,39 @@ - - struct tool_ctx { - bool verbose; -- -- errno_t error; - bool done; - - size_t nreqs; - }; - -+struct tool_options { -+ int debug; -+ int verbose; -+ -+ enum tcurl_http_method method; -+ const char *socket_path; -+}; -+ - static void request_done(struct tevent_req *req) - { -- int http_code; -+ struct tool_ctx *tool_ctx; - struct sss_iobuf *outbuf; -- struct tool_ctx *tool_ctx = tevent_req_callback_data(req, -- struct tool_ctx); -+ int http_code; -+ errno_t ret; - -- tool_ctx->error = tcurl_request_recv(tool_ctx, req, &outbuf, &http_code); -+ tool_ctx = tevent_req_callback_data(req, struct tool_ctx); -+ -+ ret = tcurl_request_recv(tool_ctx, req, &outbuf, &http_code); - talloc_zfree(req); - -- if (tool_ctx->error != EOK) { -- DEBUG(SSSDBG_FATAL_FAILURE, "HTTP request failed: %d\n", tool_ctx->error); -+ tool_ctx->nreqs--; -+ if (tool_ctx->nreqs == 0) { - tool_ctx->done = true; -+ } -+ -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "HTTP request failed [%d]: %s\n", -+ ret, sss_strerror(ret)); - return; - } else if (tool_ctx->verbose) { - printf("Request HTTP code: %d\n", http_code); -@@ -55,167 +68,171 @@ static void request_done(struct tevent_req *req) - (const char *) sss_iobuf_get_data(outbuf)); - talloc_zfree(outbuf); - } -- -- tool_ctx->nreqs--; -- if (tool_ctx->nreqs == 0) { -- tool_ctx->done = true; -- } - } - --int main(int argc, const char *argv[]) -+static errno_t -+parse_options(poptContext pc, struct tool_options *opts) - { - int opt; -- poptContext pc; -- -- int pc_debug = 0; -- int pc_verbose = 0; -- const char *socket_path = NULL; -- const char *extra_arg_ptr; -- -- static const char *headers[] = { -- "Content-type: application/octet-stream", -- NULL, -- }; -- -- struct poptOption long_options[] = { -- POPT_AUTOHELP -- { "debug", '\0', POPT_ARG_INT, &pc_debug, 0, -- "The debug level to run with", NULL }, -- { "socket-path", 's', POPT_ARG_STRING, &socket_path, 0, -- "The path to the HTTP server socket", NULL }, -- { "get", 'g', POPT_ARG_NONE, NULL, 'g', "Perform a HTTP GET (default)", NULL }, -- { "put", 'p', POPT_ARG_NONE, NULL, 'p', "Perform a HTTP PUT", NULL }, -- { "post", 'o', POPT_ARG_NONE, NULL, 'o', "Perform a HTTP POST", NULL }, -- { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, -- { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "Print response code and body", NULL }, -- POPT_TABLEEND -- }; -- -- struct tevent_req *req; -- struct tevent_context *ev; -- enum tcurl_http_method method = TCURL_HTTP_GET; -- struct tcurl_ctx *ctx; -- struct tcurl_request *tcurl_req; -- struct tool_ctx *tool_ctx; -- -- const char *urls[MAXREQ] = { 0 }; -- struct sss_iobuf **inbufs; -- -- size_t n_reqs = 0; -- -- debug_prg_name = argv[0]; -- pc = poptGetContext(NULL, argc, argv, long_options, 0); -- poptSetOtherOptionHelp(pc, "HTTPDATA"); - - while ((opt = poptGetNextOpt(pc)) > 0) { - switch (opt) { - case 'g': -- method = TCURL_HTTP_GET; -+ opts->method = TCURL_HTTP_GET; - break; - case 'p': -- method = TCURL_HTTP_PUT; -+ opts->method = TCURL_HTTP_PUT; - break; - case 'o': -- method = TCURL_HTTP_POST; -+ opts->method = TCURL_HTTP_POST; - break; - case 'd': -- method = TCURL_HTTP_DELETE; -- break; -- case 'v': -- pc_verbose = 1; -+ opts->method = TCURL_HTTP_DELETE; - break; - default: - DEBUG(SSSDBG_FATAL_FAILURE, "Unexpected option\n"); -- return 1; -+ return EINVAL; - } - } - -- DEBUG_CLI_INIT(pc_debug); -- -- tool_ctx = talloc_zero(NULL, struct tool_ctx); -- if (tool_ctx == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Could not init tool context\n"); -- return 1; -+ if (opt != -1) { -+ poptPrintUsage(pc, stderr, 0); -+ fprintf(stderr, "%s", poptStrerror(opt)); -+ return EINVAL; - } - -- inbufs = talloc_zero_array(tool_ctx, struct sss_iobuf *, MAXREQ); -- if (inbufs == NULL) { -- talloc_zfree(tool_ctx); -- return 1; -+ return EOK; -+} -+ -+static errno_t -+prepare_requests(TALLOC_CTX *mem_ctx, -+ poptContext pc, -+ struct tool_options *opts, -+ struct tcurl_request ***_requests, -+ size_t *_num_requests) -+{ -+ struct tcurl_request **requests; -+ const char *arg; -+ const char *url; -+ struct sss_iobuf *body; -+ errno_t ret; -+ size_t i; -+ -+ static const char *headers[] = { -+ "Content-type: application/octet-stream", -+ NULL, -+ }; -+ -+ requests = talloc_zero_array(mem_ctx, struct tcurl_request *, MAXREQ + 1); -+ if (requests == NULL) { -+ return ENOMEM; - } - -- while ((extra_arg_ptr = poptGetArg(pc)) != NULL) { -- switch(method) { -+ i = 0; -+ while ((arg = poptGetArg(pc)) != NULL) { -+ if (i >= MAXREQ) { -+ fprintf(stderr, _("Too many requests!\n")); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ switch (opts->method) { - case TCURL_HTTP_GET: - case TCURL_HTTP_DELETE: -- case TCURL_HTTP_POST: -- urls[n_reqs++] = extra_arg_ptr; -+ url = arg; -+ body = NULL; - break; - case TCURL_HTTP_PUT: -- if (urls[n_reqs] == NULL) { -- urls[n_reqs] = extra_arg_ptr; -- } else { -- inbufs[n_reqs] = sss_iobuf_init_readonly( -- inbufs, -- (uint8_t *) discard_const(extra_arg_ptr), -- strlen(extra_arg_ptr)); -- if (inbufs[n_reqs] == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Could not init input buffer\n"); -- talloc_zfree(tool_ctx); -- return 1; -- } -- n_reqs++; -+ case TCURL_HTTP_POST: -+ url = arg; -+ -+ arg = poptGetArg(pc); -+ if (arg == NULL) { -+ body = NULL; -+ break; -+ } -+ -+ body = sss_iobuf_init_readonly(requests, -+ discard_const_p(uint8_t, arg), -+ strlen(arg)); -+ if (body == NULL) { -+ ret = ENOMEM; -+ goto done; - } - break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid method!\n"); -+ ret = EINVAL; -+ goto done; - } -+ -+ requests[i] = tcurl_http(requests, opts->method, opts->socket_path, -+ url, headers, body); -+ if (requests[i] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ i++; - } - -- if (opt != -1) { -- poptPrintUsage(pc, stderr, 0); -- fprintf(stderr, "%s", poptStrerror(opt)); -- talloc_zfree(tool_ctx); -- return 1; -+ *_requests = requests; -+ *_num_requests = i; -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(requests); - } - -- if (!socket_path) { -- DEBUG(SSSDBG_FATAL_FAILURE, "Please specify the socket path\n"); -- poptPrintUsage(pc, stderr, 0); -- talloc_zfree(tool_ctx); -- return 1; -+ return ret; -+} -+ -+static errno_t -+run_requests(struct tool_ctx *tool_ctx, -+ struct tcurl_request **requests) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct tcurl_ctx *tcurl_ctx; -+ struct tevent_context *ev; -+ struct tevent_req *req; -+ errno_t ret; -+ int i; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n"); -+ return ENOMEM; - } - -- tool_ctx->nreqs = n_reqs; -- tool_ctx->verbose = !!pc_verbose; -+ if (requests == NULL || requests[0] == NULL) { -+ ret = EOK; -+ goto done; -+ } - -- ev = tevent_context_init(tool_ctx); -+ ev = tevent_context_init(tmp_ctx); - if (ev == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not init tevent context\n"); -- talloc_zfree(tool_ctx); -- return 1; -+ ret = ENOMEM; -+ goto done; - } - -- ctx = tcurl_init(tool_ctx, ev); -- if (ctx == NULL) { -+ tcurl_ctx = tcurl_init(tmp_ctx, ev); -+ if (tcurl_ctx == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, "Could not init tcurl context\n"); -- talloc_zfree(tool_ctx); -- return 1; -+ ret = ENOMEM; -+ goto done; - } - -- for (size_t i = 0; i < n_reqs; i++) { -- tcurl_req = tcurl_http(tool_ctx, method, socket_path, -- urls[i], headers, inbufs[i]); -- if (tcurl_req == NULL) { -- DEBUG(SSSDBG_FATAL_FAILURE, "Unable to create TCURL request\n"); -- talloc_zfree(tool_ctx); -- return 1; -+ for (i = 0; requests[i] != NULL; i++) { -+ req = tcurl_request_send(tmp_ctx, ev, tcurl_ctx, requests[i], 5); -+ if (req == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Could not create tevent request\n"); -+ ret = ENOMEM; -+ goto done; - } - -- req = tcurl_request_send(tool_ctx, ev, ctx, tcurl_req, 10); -- if (ctx == NULL) { -- DEBUG(SSSDBG_FATAL_FAILURE, "Could not create request\n"); -- talloc_zfree(tool_ctx); -- return 1; -- } - tevent_req_set_callback(req, request_done, tool_ctx); - } - -@@ -226,11 +243,78 @@ int main(int argc, const char *argv[]) - if (tool_ctx->nreqs > 0) { - DEBUG(SSSDBG_FATAL_FAILURE, - "The tool finished with some pending requests, fail!\n"); -- talloc_zfree(tool_ctx); -- return 1; -+ ret = EEXIST; -+ goto done; - } - -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ struct tool_options opts = { 0 }; -+ struct tool_ctx *tool_ctx; -+ struct tcurl_request **requests; -+ poptContext pc; -+ errno_t ret; -+ -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ { "debug", '\0', POPT_ARG_INT, &opts.debug, 0, "The debug level to run with", NULL }, -+ { "socket-path", 's', POPT_ARG_STRING, &opts.socket_path, 0, "The path to the HTTP server socket", NULL }, -+ { "get", 'g', POPT_ARG_NONE, NULL, 'g', "Perform a HTTP GET (default)", NULL }, -+ { "put", 'p', POPT_ARG_NONE, NULL, 'p', "Perform a HTTP PUT", NULL }, -+ { "post", 'o', POPT_ARG_NONE, NULL, 'o', "Perform a HTTP POST", NULL }, -+ { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, -+ { "verbose", 'v', POPT_ARG_NONE, &opts.verbose, '\0', "Print response code and body", NULL }, -+ POPT_TABLEEND -+ }; -+ -+ pc = poptGetContext(NULL, argc, argv, long_options, 0); -+ poptSetOtherOptionHelp(pc, "[URL HTTPDATA]*"); -+ -+ tool_ctx = talloc_zero(NULL, struct tool_ctx); -+ if (tool_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not init tool context\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = parse_options(pc, &opts); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to parse options [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ DEBUG_CLI_INIT(opts.debug); -+ tool_ctx->verbose = opts.verbose; -+ -+ ret = prepare_requests(tool_ctx, pc, &opts, &requests, &tool_ctx->nreqs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to prepare requests [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = run_requests(tool_ctx, requests); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to issue requests [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+done: - talloc_free(tool_ctx); - poptFreeContext(pc); -- return 0; -+ -+ if (ret != EOK) { -+ return EXIT_FAILURE; -+ } -+ -+ return EXIT_SUCCESS; - } --- -2.12.2 - diff --git a/0079-tcurl-test-add-support-for-raw-output.patch b/0079-tcurl-test-add-support-for-raw-output.patch deleted file mode 100644 index ad7b09d..0000000 --- a/0079-tcurl-test-add-support-for-raw-output.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 36e49a842e257ac9bde71728ee3bef4299b6e6e2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 24 Feb 2017 12:23:22 +0100 -Subject: [PATCH 79/97] tcurl test: add support for raw output - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/tests/tcurl_test_tool.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index e5fc9705db415650d849b89c3d18e41574b7e28b..7d3bc19f0ec7e118e251247536d25c58fe009f54 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -36,6 +36,7 @@ struct tool_ctx { - struct tool_options { - int debug; - int verbose; -+ int raw; - - enum tcurl_http_method method; - const char *socket_path; -@@ -173,6 +174,13 @@ prepare_requests(TALLOC_CTX *mem_ctx, - goto done; - } - -+ if (opts->raw) { -+ ret = tcurl_req_enable_rawoutput(requests[i]); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ - i++; - } - -@@ -270,6 +278,7 @@ int main(int argc, const char *argv[]) - { "put", 'p', POPT_ARG_NONE, NULL, 'p', "Perform a HTTP PUT", NULL }, - { "post", 'o', POPT_ARG_NONE, NULL, 'o', "Perform a HTTP POST", NULL }, - { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, -+ { "raw", 'r', POPT_ARG_NONE, &opts.raw, '\0', "Print raw protocol output", NULL }, - { "verbose", 'v', POPT_ARG_NONE, &opts.verbose, '\0', "Print response code and body", NULL }, - POPT_TABLEEND - }; --- -2.12.2 - diff --git a/0080-tcurl-test-add-support-for-tls-settings.patch b/0080-tcurl-test-add-support-for-tls-settings.patch deleted file mode 100644 index b5355c6..0000000 --- a/0080-tcurl-test-add-support-for-tls-settings.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 886e0f75e6f4c7877a23a3625f8a20c09109b09d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 27 Feb 2017 12:58:06 +0100 -Subject: [PATCH 80/97] tcurl test: add support for tls settings - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/tests/tcurl_test_tool.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 7d3bc19f0ec7e118e251247536d25c58fe009f54..9cec000fbf2e4eca2fdc5213c8b3b4cb10f1df1b 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -37,9 +37,14 @@ struct tool_options { - int debug; - int verbose; - int raw; -+ int tls; -+ int verify_peer; -+ int verify_host; - - enum tcurl_http_method method; - const char *socket_path; -+ const char *capath; -+ const char *cacert; - }; - - static void request_done(struct tevent_req *req) -@@ -181,6 +186,14 @@ prepare_requests(TALLOC_CTX *mem_ctx, - } - } - -+ if (opts->tls) { -+ ret = tcurl_req_verify_peer(requests[i], opts->capath, opts->cacert, -+ opts->verify_peer, opts->verify_host); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ - i++; - } - -@@ -280,6 +293,12 @@ int main(int argc, const char *argv[]) - { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, - { "raw", 'r', POPT_ARG_NONE, &opts.raw, '\0', "Print raw protocol output", NULL }, - { "verbose", 'v', POPT_ARG_NONE, &opts.verbose, '\0', "Print response code and body", NULL }, -+ /* TLS */ -+ { "tls", '\0', POPT_ARG_NONE, &opts.tls, '\0', "Enable TLS", NULL }, -+ { "verify-peer", '\0', POPT_ARG_NONE, &opts.verify_peer, '\0', "Verify peer when TLS is enabled", NULL }, -+ { "verify-host", '\0', POPT_ARG_NONE, &opts.verify_host, '\0', "Verify host when TLS is enabled", NULL }, -+ { "capath", '\0', POPT_ARG_STRING, &opts.capath, '\0', "Path to CA directory where peer certificate is stored", NULL }, -+ { "cacert", '\0', POPT_ARG_STRING, &opts.cacert, '\0', "Path to CA certificate", NULL }, - POPT_TABLEEND - }; - --- -2.12.2 - diff --git a/0081-tcurl-add-support-for-http-basic-auth.patch b/0081-tcurl-add-support-for-http-basic-auth.patch deleted file mode 100644 index f497fa0..0000000 --- a/0081-tcurl-add-support-for-http-basic-auth.patch +++ /dev/null @@ -1,111 +0,0 @@ -From c2ea75da72b426d98ba489039e220d417bfb4c2a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 28 Feb 2017 13:32:31 +0100 -Subject: [PATCH 81/97] tcurl: add support for http basic auth - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/tests/tcurl_test_tool.c | 14 ++++++++++++++ - src/util/tev_curl.c | 24 ++++++++++++++++++++++++ - src/util/tev_curl.h | 15 +++++++++++++++ - 3 files changed, 53 insertions(+) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 9cec000fbf2e4eca2fdc5213c8b3b4cb10f1df1b..4ceef8e06040ea0abd4d112a5b7845f436c69488 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -45,6 +45,9 @@ struct tool_options { - const char *socket_path; - const char *capath; - const char *cacert; -+ -+ const char *username; -+ const char *password; - }; - - static void request_done(struct tevent_req *req) -@@ -194,6 +197,14 @@ prepare_requests(TALLOC_CTX *mem_ctx, - } - } - -+ if (opts->username != NULL && opts->password != NULL) { -+ ret = tcurl_req_http_basic_auth(requests[i], opts->username, -+ opts->password); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ - i++; - } - -@@ -299,6 +310,9 @@ int main(int argc, const char *argv[]) - { "verify-host", '\0', POPT_ARG_NONE, &opts.verify_host, '\0', "Verify host when TLS is enabled", NULL }, - { "capath", '\0', POPT_ARG_STRING, &opts.capath, '\0', "Path to CA directory where peer certificate is stored", NULL }, - { "cacert", '\0', POPT_ARG_STRING, &opts.cacert, '\0', "Path to CA certificate", NULL }, -+ /* BASIC AUTH */ -+ { "username", '\0', POPT_ARG_STRING, &opts.username, '\0', "Username for basic authentication", NULL }, -+ { "password", '\0', POPT_ARG_STRING, &opts.password, '\0', "Password for basic authentication", NULL }, - POPT_TABLEEND - }; - -diff --git a/src/util/tev_curl.c b/src/util/tev_curl.c -index c155f4c038d4215933ee30d41c694ad4a14ae132..8faf07c714b636a0351be365597de68d2f68a1be 100644 ---- a/src/util/tev_curl.c -+++ b/src/util/tev_curl.c -@@ -1092,3 +1092,27 @@ errno_t tcurl_req_set_client_cert(struct tcurl_request *tcurl_req, - - return EOK; - } -+ -+errno_t tcurl_req_http_basic_auth(struct tcurl_request *tcurl_req, -+ const char *username, -+ const char *password) -+{ -+ errno_t ret; -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_USERNAME, username); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ ret = tcurl_set_option(tcurl_req, CURLOPT_PASSWORD, password); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ return EOK; -+} -diff --git a/src/util/tev_curl.h b/src/util/tev_curl.h -index 933abcb9b531412737e8fcf391644d828b125cf8..c733127b3686b5665f53cf53ea72674e0d7af64e 100644 ---- a/src/util/tev_curl.h -+++ b/src/util/tev_curl.h -@@ -243,4 +243,19 @@ errno_t tcurl_req_set_client_cert(struct tcurl_request *tcurl_req, - const char *cert, - const char *key); - -+/** -+ * @brief Force HTTP basic authentication with @username and @password. -+ * -+ * @param[in] tcurl_request -+ * @param[in] username -+ * @param[in] password -+ * -+ * @returns errno code -+ * -+ * @see tcurl_http -+ */ -+errno_t tcurl_req_http_basic_auth(struct tcurl_request *tcurl_req, -+ const char *username, -+ const char *password); -+ - #endif /* __TEV_CURL_H */ --- -2.12.2 - diff --git a/0082-tcurl-test-allow-to-set-custom-headers.patch b/0082-tcurl-test-allow-to-set-custom-headers.patch deleted file mode 100644 index 749d4cd..0000000 --- a/0082-tcurl-test-allow-to-set-custom-headers.patch +++ /dev/null @@ -1,62 +0,0 @@ -From d1ed11fc50922aab2332758a9300f3fbf814f112 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 10 Mar 2017 12:11:12 +0100 -Subject: [PATCH 82/97] tcurl test: allow to set custom headers - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/tests/tcurl_test_tool.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 4ceef8e06040ea0abd4d112a5b7845f436c69488..63a3e26b561781795873c2a4d72ac071a4da9939 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -40,6 +40,7 @@ struct tool_options { - int tls; - int verify_peer; - int verify_host; -+ const char **headers; - - enum tcurl_http_method method; - const char *socket_path; -@@ -121,13 +122,14 @@ prepare_requests(TALLOC_CTX *mem_ctx, - size_t *_num_requests) - { - struct tcurl_request **requests; -+ struct sss_iobuf *body; -+ const char **headers; - const char *arg; - const char *url; -- struct sss_iobuf *body; - errno_t ret; - size_t i; - -- static const char *headers[] = { -+ static const char *default_headers[] = { - "Content-type: application/octet-stream", - NULL, - }; -@@ -137,6 +139,8 @@ prepare_requests(TALLOC_CTX *mem_ctx, - return ENOMEM; - } - -+ headers = opts->headers == NULL ? default_headers : opts->headers; -+ - i = 0; - while ((arg = poptGetArg(pc)) != NULL) { - if (i >= MAXREQ) { -@@ -302,6 +306,9 @@ int main(int argc, const char *argv[]) - { "put", 'p', POPT_ARG_NONE, NULL, 'p', "Perform a HTTP PUT", NULL }, - { "post", 'o', POPT_ARG_NONE, NULL, 'o', "Perform a HTTP POST", NULL }, - { "del", 'd', POPT_ARG_NONE, NULL, 'd', "Perform a HTTP DELETE", NULL }, -+#ifdef POPT_ARG_ARGV -+ { "header", 'h', POPT_ARG_ARGV, &opts.headers, '\0', "Add HTTP header", NULL }, -+#endif - { "raw", 'r', POPT_ARG_NONE, &opts.raw, '\0', "Print raw protocol output", NULL }, - { "verbose", 'v', POPT_ARG_NONE, &opts.verbose, '\0', "Print response code and body", NULL }, - /* TLS */ --- -2.12.2 - diff --git a/0083-tcurl-test-add-support-for-client-certificate.patch b/0083-tcurl-test-add-support-for-client-certificate.patch deleted file mode 100644 index d089392..0000000 --- a/0083-tcurl-test-add-support-for-client-certificate.patch +++ /dev/null @@ -1,52 +0,0 @@ -From ae6b11229d9961e26922918183c7c1de7780b8d6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 13 Mar 2017 13:30:48 +0100 -Subject: [PATCH 83/97] tcurl test: add support for client certificate - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/tests/tcurl_test_tool.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/src/tests/tcurl_test_tool.c b/src/tests/tcurl_test_tool.c -index 63a3e26b561781795873c2a4d72ac071a4da9939..fbc2790357b131ebb21b4be041688e5f699d73e7 100644 ---- a/src/tests/tcurl_test_tool.c -+++ b/src/tests/tcurl_test_tool.c -@@ -47,6 +47,9 @@ struct tool_options { - const char *capath; - const char *cacert; - -+ const char *clientcert; -+ const char *clientkey; -+ - const char *username; - const char *password; - }; -@@ -201,6 +204,14 @@ prepare_requests(TALLOC_CTX *mem_ctx, - } - } - -+ if (opts->clientcert != NULL) { -+ ret = tcurl_req_set_client_cert(requests[i], opts->clientcert, -+ opts->clientkey); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ - if (opts->username != NULL && opts->password != NULL) { - ret = tcurl_req_http_basic_auth(requests[i], opts->username, - opts->password); -@@ -317,6 +328,8 @@ int main(int argc, const char *argv[]) - { "verify-host", '\0', POPT_ARG_NONE, &opts.verify_host, '\0', "Verify host when TLS is enabled", NULL }, - { "capath", '\0', POPT_ARG_STRING, &opts.capath, '\0', "Path to CA directory where peer certificate is stored", NULL }, - { "cacert", '\0', POPT_ARG_STRING, &opts.cacert, '\0', "Path to CA certificate", NULL }, -+ { "clientcert", '\0', POPT_ARG_STRING, &opts.clientcert, '\0', "Path to client's certificate", NULL }, -+ { "clientkey", '\0', POPT_ARG_STRING, &opts.clientkey, '\0', "Path to client's private key", NULL }, - /* BASIC AUTH */ - { "username", '\0', POPT_ARG_STRING, &opts.username, '\0', "Username for basic authentication", NULL }, - { "password", '\0', POPT_ARG_STRING, &opts.password, '\0', "Password for basic authentication", NULL }, --- -2.12.2 - diff --git a/0084-ci-do-not-build-secrets-on-rhel6.patch b/0084-ci-do-not-build-secrets-on-rhel6.patch deleted file mode 100644 index f626ff4..0000000 --- a/0084-ci-do-not-build-secrets-on-rhel6.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 6698d40512e55e7c2d03e14c227c51b1edc77ffa Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 28 Mar 2017 15:24:01 +0200 -Subject: [PATCH 84/97] ci: do not build secrets on rhel6 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We require newer libcurl version than is available on rhel6. We don't -ship secrets responder in rhel6 so we just disable its build. - -Reviewed-by: Lukáš Slebodník ---- - contrib/ci/configure.sh | 1 + - contrib/sssd.spec.in | 15 +++++++++++++++ - src/tests/intg/test_secrets.py | 4 ++++ - 3 files changed, 20 insertions(+) - -diff --git a/contrib/ci/configure.sh b/contrib/ci/configure.sh -index 7590743c2aa5fe31bcdf1a3e92a3f482dbec699b..9d18d0c187561a2dc3bc47d3e8913626e7ff3046 100644 ---- a/contrib/ci/configure.sh -+++ b/contrib/ci/configure.sh -@@ -38,6 +38,7 @@ if [[ "$DISTRO_BRANCH" == -redhat-redhatenterprise*-6.*- || - "--disable-cifs-idmap-plugin" - "--with-syslog=syslog" - "--without-python3-bindings" -+ "--without-secrets" - "--without-kcm" - ) - fi -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index af14d4e3d6b9ffeb4696f1517113b8daa575cb99..39a974edebba3dbcd7625d1729b4a7330eaa8a27 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -112,6 +112,12 @@ - %global enable_systemtap_opt --enable-systemtap - %endif - -+%if (0%{?fedora} || 0%{?epel} >= 7) -+ %global with_secrets 1 -+%else -+ %global with_secret_responder --without-secrets -+%endif -+ - %if (0%{?fedora} >= 23 || 0%{?rhel} >= 7) - %global with_kcm 1 - %global with_kcm_option --with-kcm -@@ -220,8 +226,10 @@ BuildRequires: libsmbclient-devel - %if (0%{?enable_systemtap} == 1) - BuildRequires: systemtap-sdt-devel - %endif -+%if (0%{?with_secrets} == 1) - BuildRequires: http-parser-devel - BuildRequires: jansson-devel -+%endif - BuildRequires: libuuid-devel - BuildRequires: libcurl-devel - -@@ -727,6 +735,7 @@ autoreconf -ivf - %{?with_python3_option} \ - %{?enable_polkit_rules_option} \ - %{?enable_systemtap_opt} \ -+ %{?with_secret_responder} \ - %{?with_kcm_option} \ - %{?experimental} - -@@ -865,7 +874,9 @@ done - %{_libexecdir}/%{servicename}/sssd_nss - %{_libexecdir}/%{servicename}/sssd_pam - %{_libexecdir}/%{servicename}/sssd_autofs -+%if (0%{?with_secrets} == 1) - %{_libexecdir}/%{servicename}/sssd_secrets -+%endif - %{_libexecdir}/%{servicename}/sssd_ssh - %{_libexecdir}/%{servicename}/sssd_sudo - %{_libexecdir}/%{servicename}/p11_child -@@ -900,7 +911,9 @@ done - %dir %{_localstatedir}/cache/krb5rcache - %attr(700,sssd,sssd) %dir %{dbpath} - %attr(755,sssd,sssd) %dir %{mcpath} -+%if (0%{?with_secrets} == 1) - %attr(700,root,root) %dir %{secdbpath} -+%endif - %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/passwd - %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/group - %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/initgroups -@@ -933,7 +946,9 @@ done - %{_mandir}/man5/sssd.conf.5* - %{_mandir}/man5/sssd-simple.5* - %{_mandir}/man5/sssd-sudo.5* -+%if (0%{?with_secrets} == 1) - %{_mandir}/man5/sssd-secrets.5* -+%endif - %{_mandir}/man5/sss_rpcidmapd.5* - %{_mandir}/man8/sssd.8* - %{_mandir}/man8/sss_cache.8* -diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py -index d71c1904558cc6f8a6eee36c4049582705bc30ac..202f43e61cb0e4986394ad2b32da5abdcb0be3e9 100644 ---- a/src/tests/intg/test_secrets.py -+++ b/src/tests/intg/test_secrets.py -@@ -46,6 +46,10 @@ def create_sssd_secrets_fixture(request): - raise Exception("failed to regenerate confdb") - - resp_path = os.path.join(config.LIBEXEC_PATH, "sssd", "sssd_secrets") -+ if not os.access(resp_path, os.X_OK): -+ # It would be cleaner to use pytest.mark.skipif on the package level -+ # but upstream insists on supporting RHEL-6. -+ pytest.skip("No Secrets responder, skipping") - - secpid = os.fork() - assert secpid >= 0 --- -2.12.2 - diff --git a/0085-build-make-curl-required-by-secrets.patch b/0085-build-make-curl-required-by-secrets.patch deleted file mode 100644 index acc2498..0000000 --- a/0085-build-make-curl-required-by-secrets.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 793f2573b2beaf8b48eab850429482acf68ec2b1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 22 Mar 2017 12:32:31 +0100 -Subject: [PATCH 85/97] build: make curl required by secrets -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Also remove --disable-libcurl since it doesn't make sense. - -Reviewed-by: Lukáš Slebodník -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - configure.ac | 6 +++++- - src/external/libcurl.m4 | 16 ++-------------- - 2 files changed, 7 insertions(+), 15 deletions(-) - -diff --git a/configure.ac b/configure.ac -index cf5e2557ef0a1bd6374200aa33abea6c509d03aa..80d8ea9ff5785b0d76edbb04f454d0dd8c8a1e6d 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -201,9 +201,13 @@ if test x$with_secrets = xyes; then - fi - - if test x$with_kcm = xyes; then -- m4_include([src/external/libcurl.m4]) - m4_include([src/external/libuuid.m4]) - fi -+ -+if test x$with_kcm = xyes -o x$with_secrets = xyes; then -+ m4_include([src/external/libcurl.m4]) -+fi -+ - # This variable is defined by external/libcurl.m4, but conditionals - # must be always evaluated - AM_CONDITIONAL([BUILD_WITH_LIBCURL], -diff --git a/src/external/libcurl.m4 b/src/external/libcurl.m4 -index b420b04ad806bd1251f086b773ffe480d39f8bd3..42be308cd1e4b04e736daf887be9b75ea92db80e 100644 ---- a/src/external/libcurl.m4 -+++ b/src/external/libcurl.m4 -@@ -1,17 +1,5 @@ --AC_ARG_ENABLE([curl], -- [AS_HELP_STRING([--disable-curl-support], -- [do not build with libcurl support])], -- [enable_libcurl=$enableval], -- [enable_libcurl=yes]) -- --found_libcurl="no" --AS_IF([test x$enable_libcurl = xyes], -- [PKG_CHECK_MODULES([CURL], -- [libcurl], -- [found_libcurl=yes], -- [AC_MSG_ERROR([ --The libcurl development library was not found.]) -- ])]) -+PKG_CHECK_MODULES([CURL], [libcurl], [found_libcurl=yes], -+ [AC_MSG_ERROR([The libcurl development library was not found.])]) - - AS_IF([test x"$found_libcurl" = xyes], - CFLAGS="$CFLAGS $CURL_CFLAGS" --- -2.12.2 - diff --git a/0086-secrets-use-tcurl-in-proxy-provider.patch b/0086-secrets-use-tcurl-in-proxy-provider.patch deleted file mode 100644 index 1442c2f..0000000 --- a/0086-secrets-use-tcurl-in-proxy-provider.patch +++ /dev/null @@ -1,458 +0,0 @@ -From df99d709c8cbef3c378c111944d83b7345e4c1ea Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 22 Feb 2017 10:38:56 +0100 -Subject: [PATCH 86/97] secrets: use tcurl in proxy provider - -We switch from http-parser to libcurl for an http client. This gaves us many -features for free such as tls and http basic authentication support instead -of implementing it on our own. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3192 - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 3 + - src/responder/secrets/providers.c | 20 +++ - src/responder/secrets/proxy.c | 246 ++++++++++++++++++++++----------- - src/responder/secrets/secsrv_private.h | 5 + - 4 files changed, 191 insertions(+), 83 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 573b37c52fdeab1add4ea057e1e1844ea4d348a5..4a414f77df999b8b1d81f663fcc18dbd2d6d2dc4 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1486,6 +1486,8 @@ sssd_secrets_SOURCES = \ - src/responder/secrets/local.c \ - src/responder/secrets/proxy.c \ - src/util/sss_sockets.c \ -+ src/util/sss_iobuf.c \ -+ src/util/tev_curl.c \ - $(SSSD_RESPONDER_OBJ) \ - $(SSSD_RESOLV_OBJ) \ - $(NULL) -@@ -1497,6 +1499,7 @@ sssd_secrets_LDADD = \ - $(SYSTEMD_DAEMON_LIBS) \ - $(CARES_LIBS) \ - $(SSSD_INTERNAL_LTLIBS) \ -+ $(CURL_LIBS) \ - $(NULL) - endif - -diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c -index 94831c73036d269addca45c0117811a2c68873fd..80a443d91135447ec8ce8d424b692a6d7e26a907 100644 ---- a/src/responder/secrets/providers.c -+++ b/src/responder/secrets/providers.c -@@ -22,6 +22,7 @@ - #include "responder/secrets/secsrv_private.h" - #include "responder/secrets/secsrv_local.h" - #include "responder/secrets/secsrv_proxy.h" -+#include "util/sss_iobuf.h" - #include - - typedef int (*url_mapper_fn)(struct sec_req_ctx *secreq, -@@ -387,6 +388,25 @@ int sec_http_reply_with_headers(TALLOC_CTX *mem_ctx, struct sec_data *reply, - return EOK; - } - -+errno_t sec_http_reply_iobuf(TALLOC_CTX *mem_ctx, -+ struct sec_data *reply, -+ int response_code, -+ struct sss_iobuf *response) -+{ -+ DEBUG(SSSDBG_TRACE_LIBS, "HTTP reply %d\n", response_code); -+ -+ reply->data = (char *)sss_iobuf_get_data(response); -+ reply->length = sss_iobuf_get_len(response); -+ -+ talloc_steal(mem_ctx, reply->data); -+ -+ if (reply->data == NULL) { -+ return EINVAL; -+ } -+ -+ return EOK; -+} -+ - enum sec_http_status_codes sec_errno_to_http_status(errno_t err) - { - DEBUG(SSSDBG_TRACE_LIBS, "Request errno: %d\n", err); -diff --git a/src/responder/secrets/proxy.c b/src/responder/secrets/proxy.c -index 3ed03e6086d0de0f6f80de227ffc65ef4067db4f..fe2f0134e233d9a98f499fe563abe0af69762514 100644 ---- a/src/responder/secrets/proxy.c -+++ b/src/responder/secrets/proxy.c -@@ -23,10 +23,15 @@ - #include "util/crypto/sss_crypto.h" - #include "resolv/async_resolv.h" - #include "util/sss_sockets.h" -+#include "util/sss_iobuf.h" -+#include "util/tev_curl.h" -+ -+#define SEC_PROXY_TIMEOUT 5 - - struct proxy_context { - struct resolv_ctx *resctx; - struct confdb_ctx *cdb; -+ struct tcurl_ctx *tcurl; - }; - - enum proxy_auth_type { -@@ -216,103 +221,177 @@ int proxy_sec_map_url(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq, - return EOK; - } - --int proxy_sec_map_headers(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq, -- struct proxy_cfg *pcfg, char **req_headers) -+static errno_t proxy_http_append_header(TALLOC_CTX *mem_ctx, -+ const char *name, -+ const char *value, -+ const char ***_headers, -+ size_t *_num_headers) - { -- int ret; -- -- for (int i = 0; i < secreq->num_headers; i++) { -- bool forward = false; -- for (int j = 0; pcfg->fwd_headers[j]; j++) { -- if (strcasecmp(secreq->headers[i].name, -- pcfg->fwd_headers[j]) == 0) { -- forward = true; -+ const char **headers = *_headers; -+ size_t num_headers = *_num_headers; -+ -+ num_headers++; -+ headers = talloc_realloc(mem_ctx, headers, const char *, -+ num_headers + 1); -+ if (headers == NULL) { -+ return ENOMEM; -+ } -+ -+ headers[num_headers - 1] = talloc_asprintf(headers, "%s: %s", name, value); -+ if (headers[num_headers - 1] == NULL) { -+ return ENOMEM; -+ } -+ -+ headers[num_headers] = NULL; -+ -+ *_headers = headers; -+ *_num_headers = num_headers; -+ -+ return EOK; -+} -+ -+static const char ** -+proxy_http_create_headers(TALLOC_CTX *mem_ctx, -+ struct sec_req_ctx *secreq, -+ struct proxy_cfg *pcfg) -+{ -+ TALLOC_CTX *tmp_ctx; -+ const char **headers; -+ size_t num_headers; -+ errno_t ret; -+ int i, j; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n"); -+ return NULL; -+ } -+ -+ headers = talloc_zero_array(tmp_ctx, const char *, 1); -+ if (headers == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ num_headers = 0; -+ for (i = 0; i < secreq->num_headers; i++) { -+ for (j = 0; pcfg->fwd_headers[j]; j++) { -+ if (strcasecmp(secreq->headers[i].name, pcfg->fwd_headers[j]) == 0) { -+ DEBUG(SSSDBG_TRACE_LIBS, "Forwarding header %s: %s\n", -+ secreq->headers[i].name, secreq->headers[i].value); -+ -+ ret = proxy_http_append_header(tmp_ctx, secreq->headers[i].name, -+ secreq->headers[i].value, -+ &headers, &num_headers); -+ if (ret != EOK) { -+ goto done; -+ } -+ - break; - } - } -- if (forward) { -- DEBUG(SSSDBG_TRACE_LIBS, "Forwarding header %s:%s\n", -- secreq->headers[i].name, secreq->headers[i].value); -- -- ret = sec_http_append_header(mem_ctx, req_headers, -- secreq->headers[i].name, -- secreq->headers[i].value); -- if (ret) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Couldn't append header %s\n", secreq->headers[i].name); -- return ret; -- } -- } - } - - if (pcfg->auth_type == PAT_HEADER) { -- DEBUG(SSSDBG_TRACE_LIBS, -- "Forwarding header %s\n", pcfg->auth.header.name); -+ DEBUG(SSSDBG_TRACE_LIBS, "Forwarding header %s\n", -+ pcfg->auth.header.name); - -- ret = sec_http_append_header(mem_ctx, req_headers, -- pcfg->auth.header.name, -- pcfg->auth.header.value); -- if (ret) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Couldn't append header %s\n", pcfg->auth.header.name); -- return ret; -+ ret = proxy_http_append_header(tmp_ctx, pcfg->auth.header.name, -+ pcfg->auth.header.value, -+ &headers, &num_headers); -+ if (ret != EOK) { -+ goto done; - } - } - -- return EOK; -+ talloc_steal(mem_ctx, headers); -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ if (ret != EOK) { -+ return NULL; -+ } -+ -+ return headers; - } - --static int proxy_http_create_request(TALLOC_CTX *mem_ctx, -- struct sec_req_ctx *secreq, -- struct proxy_cfg *pcfg, -- const char *http_uri, -- struct sec_data **http_req) -+static errno_t proxy_http_create_request(TALLOC_CTX *mem_ctx, -+ struct sec_req_ctx *secreq, -+ struct proxy_cfg *pcfg, -+ const char *url, -+ struct tcurl_request **_tcurl_req) - { -- struct sec_data *req; -- int ret; -+ TALLOC_CTX *tmp_ctx; -+ struct tcurl_request *tcurl_req; -+ enum tcurl_http_method method; -+ struct sss_iobuf *body; -+ const char **headers; -+ errno_t ret; - -- req = talloc_zero(mem_ctx, struct sec_data); -- if (!req) return ENOMEM; -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n"); -+ return ENOMEM; -+ } - -- /* Request-Line */ -- req->data = talloc_asprintf(req, "%s %s HTTP/1.1\r\n", -- http_method_str(secreq->method), http_uri); -- if (!req->data) { -+ headers = proxy_http_create_headers(tmp_ctx, secreq, pcfg); -+ if (headers == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to construct HTTP headers!\n"); - ret = ENOMEM; - goto done; - } - -- /* Headers */ -- ret = proxy_sec_map_headers(req, secreq, pcfg, &req->data); -- if (ret) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Couldn't map headers\n"); -+ body = sss_iobuf_init_readonly(tmp_ctx, (uint8_t *)secreq->body.data, -+ secreq->body.length); -+ if (body == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create HTTP body!\n"); -+ ret = ENOMEM; - goto done; - } - -- /* CRLF separator before body */ -- req->data = talloc_strdup_append_buffer(req->data, "\r\n"); -- -- req->length = strlen(req->data); -+ switch (secreq->method) { -+ case HTTP_GET: -+ method = TCURL_HTTP_GET; -+ break; -+ case HTTP_PUT: -+ method = TCURL_HTTP_PUT; -+ break; -+ case HTTP_POST: -+ method = TCURL_HTTP_POST; -+ break; -+ case HTTP_DELETE: -+ method = TCURL_HTTP_DELETE; -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected HTTP method: %d\n", -+ secreq->method); -+ ret = EINVAL; -+ goto done; -+ } - -- /* Message-Body */ -- if (secreq->body.length > 0) { -- req->data = talloc_realloc_size(req, req->data, -- req->length + secreq->body.length); -- if (!req->data) { -- ret = ENOMEM; -- goto done; -- } -+ tcurl_req = tcurl_http(tmp_ctx, method, NULL, url, headers, body); -+ if (tcurl_req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create TCURL request!\n"); -+ ret = ENOMEM; -+ goto done; -+ } - -- memcpy(&req->data[req->length], -- secreq->body.data, secreq->body.length); -- req->length += secreq->body.length; -+ /* TCURL will return response buffer also with headers. */ -+ ret = tcurl_req_enable_rawoutput(tcurl_req); -+ if (ret != EOK) { -+ goto done; - } - -- *http_req = req; -+ talloc_steal(tcurl_req, body); -+ *_tcurl_req = talloc_steal(mem_ctx, tcurl_req); -+ - ret = EOK; - - done: -- if (ret) talloc_free(req); -+ talloc_free(tmp_ctx); - return ret; - } - -@@ -911,8 +990,8 @@ struct tevent_req *proxy_secret_req(TALLOC_CTX *mem_ctx, - { - struct tevent_req *req, *subreq; - struct proxy_secret_state *state; -+ struct tcurl_request *tcurl_req; - struct proxy_context *pctx; -- struct sec_data *http_req; - char *http_uri; - int ret; - -@@ -942,9 +1021,8 @@ struct tevent_req *proxy_secret_req(TALLOC_CTX *mem_ctx, - goto done; - } - -- - ret = proxy_http_create_request(state, state->secreq, state->pcfg, -- http_uri, &http_req); -+ http_uri, &tcurl_req); - if (ret) { - DEBUG(SSSDBG_CRIT_FAILURE, - "proxy_http_create_request failed [%d]: %s\n", -@@ -952,10 +1030,9 @@ struct tevent_req *proxy_secret_req(TALLOC_CTX *mem_ctx, - goto done; - } - -- -- subreq = proxy_http_req_send(pctx, state, ev, state->secreq, -- http_uri, http_req); -- if (!subreq) { -+ subreq = tcurl_request_send(mem_ctx, ev, pctx->tcurl, tcurl_req, -+ SEC_PROXY_TIMEOUT); -+ if (subreq == NULL) { - ret = ENOMEM; - goto done; - } -@@ -981,32 +1058,30 @@ static void proxy_secret_req_done(struct tevent_req *subreq) - { - struct tevent_req *req; - struct proxy_secret_state *state; -- struct proxy_http_reply *reply = NULL; -+ struct sss_iobuf *response; -+ int http_code; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct proxy_secret_state); - -- ret = proxy_http_req_recv(subreq, state, &reply); -+ ret = tcurl_request_recv(state, subreq, &response, &http_code); - talloc_zfree(subreq); - - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "proxy_http request failed [%d]: %s\n", -+ DEBUG(SSSDBG_OP_FAILURE, "proxy_http request failed [%d]: %s\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ret); - return; - } - -- ret = sec_http_reply_with_headers(state->secreq, &state->secreq->reply, -- reply->status_code, reply->reason_phrase, -- reply->headers, reply->num_headers, -- &reply->body); -+ ret = sec_http_reply_iobuf(state->secreq, &state->secreq->reply, -+ http_code, response); - if (ret == EOK) { - tevent_req_done(req); - } else { - DEBUG(SSSDBG_OP_FAILURE, -- "sec_http_reply_with_headers request failed [%d]: %s\n", -+ "sec_http_reply_iobuf request failed [%d]: %s\n", - ret, sss_strerror(ret)); - tevent_req_error(req, ret); - } -@@ -1034,6 +1109,11 @@ int proxy_secrets_provider_handle(struct sec_ctx *sctx, - - pctx->resctx = sctx->resctx; - pctx->cdb = sctx->rctx->cdb; -+ pctx->tcurl = tcurl_init(pctx, sctx->rctx->ev); -+ if (pctx->tcurl == NULL) { -+ talloc_free(pctx); -+ return ENOMEM; -+ } - - handle->context = pctx; - -diff --git a/src/responder/secrets/secsrv_private.h b/src/responder/secrets/secsrv_private.h -index a8544f656517a17fe4576247779bff4850beaf97..2e68628f61a0a8e79cd48fb5a510221e6fc36c70 100644 ---- a/src/responder/secrets/secsrv_private.h -+++ b/src/responder/secrets/secsrv_private.h -@@ -25,6 +25,7 @@ - #include "config.h" - #include "responder/common/responder.h" - #include "responder/secrets/secsrv.h" -+#include "util/sss_iobuf.h" - #include - - struct sec_kvp { -@@ -129,6 +130,10 @@ int sec_http_reply_with_headers(TALLOC_CTX *mem_ctx, struct sec_data *reply, - int status_code, const char *reason, - struct sec_kvp *headers, int num_headers, - struct sec_data *body); -+errno_t sec_http_reply_iobuf(TALLOC_CTX *mem_ctx, -+ struct sec_data *reply, -+ int response_code, -+ struct sss_iobuf *response); - enum sec_http_status_codes sec_errno_to_http_status(errno_t err); - - int sec_json_to_simple_secret(TALLOC_CTX *mem_ctx, --- -2.12.2 - diff --git a/0087-secrets-remove-http-parser-code-in-proxy-provider.patch b/0087-secrets-remove-http-parser-code-in-proxy-provider.patch deleted file mode 100644 index 85ea690..0000000 --- a/0087-secrets-remove-http-parser-code-in-proxy-provider.patch +++ /dev/null @@ -1,611 +0,0 @@ -From 06744bf5a47d5971a338281c8243b11cf72dac90 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 28 Feb 2017 14:14:40 +0100 -Subject: [PATCH 87/97] secrets: remove http-parser code in proxy provider - -We switche to libcurl in previous patch. This just removes the unused code. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3192 - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/responder/secrets/proxy.c | 581 ------------------------------------------ - 1 file changed, 581 deletions(-) - -diff --git a/src/responder/secrets/proxy.c b/src/responder/secrets/proxy.c -index fe2f0134e233d9a98f499fe563abe0af69762514..3c495716010ac468c9e2f1fb6356529a8dbdc614 100644 ---- a/src/responder/secrets/proxy.c -+++ b/src/responder/secrets/proxy.c -@@ -395,587 +395,6 @@ done: - return ret; - } - --struct proxy_http_request { -- struct sec_data *data; -- size_t written; --}; -- --struct proxy_http_reply { -- http_parser parser; -- bool complete; -- -- int status_code; -- char *reason_phrase; -- struct sec_kvp *headers; -- int num_headers; -- struct sec_data body; -- -- size_t received; --}; -- --struct proxy_http_req_state { -- struct tevent_context *ev; -- -- char *proxyname; -- int port; -- -- struct resolv_hostent *hostent; -- int hostidx; -- -- int sd; -- struct tevent_fd *fde; -- -- struct proxy_http_request request; -- struct proxy_http_reply *reply; --}; -- --static int proxy_http_req_state_destroy(void *data); --static void proxy_http_req_gethostname_done(struct tevent_req *subreq); --static void proxy_http_req_connect_step(struct tevent_req *req); --static void proxy_http_req_connect_done(struct tevent_req *subreq); --static void proxy_fd_handler(struct tevent_context *ev, struct tevent_fd *fde, -- uint16_t flags, void *ptr); -- --struct tevent_req *proxy_http_req_send(struct proxy_context *pctx, -- TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct sec_req_ctx *secreq, -- const char *http_uri, -- struct sec_data *http_req) --{ -- struct proxy_http_req_state *state; -- struct http_parser_url parsed; -- struct tevent_req *req, *subreq; -- int ret; -- -- req = tevent_req_create(mem_ctx, &state, struct proxy_http_req_state); -- if (!req) return NULL; -- -- state->ev = ev; -- state->request.data = http_req; -- state->sd = -1; -- talloc_set_destructor((TALLOC_CTX *)state, -- proxy_http_req_state_destroy); -- -- /* STEP1: reparse URL to get hostname and port */ -- ret = http_parser_parse_url(http_uri, strlen(http_uri), 0, &parsed); -- if (ret) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse URL [%s]: %d: %s\n", -- http_uri, ret, sss_strerror(ret)); -- goto done; -- } -- -- if (!(parsed.field_set & (1 << UF_HOST))) { -- DEBUG(SSSDBG_CRIT_FAILURE, "No UF_HOST flag found\n"); -- ret = EINVAL; -- goto done; -- } -- state->proxyname = -- talloc_strndup(state, -- &http_uri[parsed.field_data[UF_HOST].off], -- parsed.field_data[UF_HOST].len); -- if (!state->proxyname) { -- ret = ENOMEM; -- goto done; -- } -- DEBUG(SSSDBG_TRACE_LIBS, "proxy name: %s\n", state->proxyname); -- -- if (parsed.field_set & (1 << UF_PORT)) { -- state->port = parsed.port; -- } else if (parsed.field_set & (1 << UF_SCHEMA)) { -- uint16_t off = parsed.field_data[UF_SCHEMA].off; -- uint16_t len = parsed.field_data[UF_SCHEMA].len; -- -- if ((len == 5) && -- (strncmp("https", &http_uri[off], len) == 0)) { -- state->port = 443; -- } else if ((len == 4) && -- (strncmp("http", &http_uri[off], len) == 0)) { -- state->port = 80; -- } -- } -- DEBUG(SSSDBG_TRACE_LIBS, "proxy port: %d\n", state->port); -- -- /* STEP2: resolve hostname first */ -- subreq = resolv_gethostbyname_send(state, ev, pctx->resctx, -- state->proxyname, IPV4_FIRST, -- default_host_dbs); -- if (subreq == NULL) { -- ret = ENOMEM; -- goto done; -- } -- -- tevent_req_set_callback(subreq, proxy_http_req_gethostname_done, req); -- -- return req; -- --done: -- if (ret == EOK) { -- tevent_req_done(req); -- } else { -- tevent_req_error(req, ret); -- } -- tevent_req_post(req, ev); -- -- return req; --} -- --static void proxy_http_req_gethostname_done(struct tevent_req *subreq) --{ -- struct tevent_req *req; -- struct proxy_http_req_state *state; -- int resolv_status; -- int ret; -- -- req = tevent_req_callback_data(subreq, struct tevent_req); -- state = tevent_req_data(req, struct proxy_http_req_state); -- -- ret = resolv_gethostbyname_recv(subreq, state, &resolv_status, NULL, -- &state->hostent); -- talloc_zfree(subreq); -- if (ret != EOK) { -- if (ret == ENOENT) { -- /* Empty result, just quit */ -- DEBUG(SSSDBG_TRACE_INTERNAL, "No hostent found\n"); -- } else { -- DEBUG(SSSDBG_OP_FAILURE, -- "Could not resolve fqdn for this machine, error [%d]: %s, " -- "resolver returned: [%d]: %s\n", ret, strerror(ret), -- resolv_status, resolv_strerror(resolv_status)); -- } -- goto done; -- } -- -- /* EOK */ -- DEBUG(SSSDBG_TRACE_INTERNAL, "Found fqdn: %s\n", state->hostent->name); -- -- /* STEP3: connect to one of the servers */ -- proxy_http_req_connect_step(req); -- return; -- --done: -- if (ret == EOK) { -- tevent_req_done(req); -- } else { -- tevent_req_error(req, ret); -- } --} -- --static void proxy_http_req_connect_step(struct tevent_req *req) --{ -- struct proxy_http_req_state *state; -- struct sockaddr_storage *sockaddr; -- char *ipaddr; -- struct tevent_req *subreq; -- int ret; -- -- state = tevent_req_data(req, struct proxy_http_req_state); -- -- if (!state->hostent->addr_list[state->hostidx]) { -- DEBUG(SSSDBG_CRIT_FAILURE, "No more addresses to try.\n"); -- ret = ERR_SEC_NO_PROXY; -- goto done; -- } -- -- sockaddr = resolv_get_sockaddr_address_index(state, state->hostent, -- state->port, state->hostidx); -- if (sockaddr == NULL) { -- DEBUG(SSSDBG_OP_FAILURE, "resolv_get_sockaddr_address() failed\n"); -- ret = EIO; -- goto done; -- } -- -- if (DEBUG_IS_SET(SSSDBG_TRACE_FUNC)) { -- ipaddr = resolv_get_string_address_index(state, state->hostent, -- state->hostidx); -- if (!ipaddr) { -- ret = EFAULT; -- goto done; -- } -- DEBUG(SSSDBG_TRACE_FUNC, "Connecting to %s:%d\n", -- ipaddr, state->port); -- } -- -- /* increase idx for next attempt */ -- state->hostidx++; -- -- subreq = sssd_async_socket_init_send(state, state->ev, sockaddr, -- sizeof(struct sockaddr_storage), -- SEC_NET_TIMEOUT); -- if (!subreq) { -- ret = EIO; -- goto done; -- } -- tevent_req_set_callback(subreq, proxy_http_req_connect_done, req); -- return; -- --done: -- if (ret == EOK) { -- tevent_req_done(req); -- } else { -- tevent_req_error(req, ret); -- } --} -- --static void proxy_http_req_connect_done(struct tevent_req *subreq) --{ -- struct tevent_req *req; -- struct proxy_http_req_state *state; -- int ret; -- -- req = tevent_req_callback_data(subreq, struct tevent_req); -- state = tevent_req_data(req, struct proxy_http_req_state); -- -- ret = sssd_async_socket_init_recv(subreq, &state->sd); -- talloc_zfree(subreq); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "sssd_async_socket_init request failed: [%d]: %s.\n", -- ret, sss_strerror(ret)); -- -- /* try next server if any */ -- proxy_http_req_connect_step(req); -- return; -- } -- -- /* EOK */ -- DEBUG(SSSDBG_TRACE_FUNC, "Connected to %s\n", state->hostent->name); -- -- state->fde = tevent_add_fd(state->ev, state, state->sd, -- TEVENT_FD_WRITE, proxy_fd_handler, -- req); -- if (!state->fde) { -- ret = EIO; -- goto done; -- } -- -- return; -- --done: -- if (ret == EOK) { -- tevent_req_done(req); -- } else { -- tevent_req_error(req, ret); -- } --} -- -- --int proxy_http_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, -- struct proxy_http_reply **reply) --{ -- struct proxy_http_req_state *state = -- tevent_req_data(req, struct proxy_http_req_state); -- -- TEVENT_REQ_RETURN_ON_ERROR(req); -- -- *reply = talloc_move(mem_ctx, &state->reply); -- -- return EOK; --} -- --static int proxy_http_req_state_destroy(void *data) --{ -- struct proxy_http_req_state *state = -- talloc_get_type(data, struct proxy_http_req_state); -- -- if (!state) return 0; -- -- if (state->sd != -1) { -- DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd); -- close(state->sd); -- state->sd = -1; -- } -- -- return 0; --} -- --static int proxy_wire_send(int fd, struct proxy_http_request *req) --{ -- struct sec_data data; -- int ret; -- -- data.data = req->data->data + req->written; -- data.length = req->data->length - req->written; -- -- ret = sec_send_data(fd, &data); -- if (ret != EOK && ret != EAGAIN) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "sec_send_data failed [%d]: %s\n", ret, sss_strerror(ret)); -- return ret; -- } -- -- req->written = req->data->length - data.length; -- return ret; --} -- --static void proxy_fd_send(void *data) --{ -- struct proxy_http_req_state *state; -- struct tevent_req * req; -- int ret; -- -- req = talloc_get_type(data, struct tevent_req); -- state = tevent_req_data(req, struct proxy_http_req_state); -- -- ret = proxy_wire_send(state->sd, &state->request); -- if (ret == EAGAIN) { -- /* not all data was sent, loop again */ -- return; -- } -- if (ret != EOK) { -- DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting!\n"); -- tevent_req_error(req, ret); -- return; -- } -- -- /* ok all sent, wait for reply now */ -- TEVENT_FD_NOT_WRITEABLE(state->fde); -- TEVENT_FD_READABLE(state->fde); -- return; --} -- --static bool ph_received_data(struct proxy_http_reply *reply, size_t length) --{ -- reply->received += length; -- if (reply->received > SEC_REQUEST_MAX_SIZE) { -- DEBUG(SSSDBG_FATAL_FAILURE, "Request too big, aborting!\n"); -- return true; -- } -- return false; --} -- --static void ph_append_string(TALLOC_CTX *memctx, char **dest, -- const char *src, size_t len) --{ -- if (*dest) { -- *dest = talloc_strndup_append_buffer(*dest, src, len); -- } else { -- *dest = talloc_strndup(memctx, src, len); -- } --} -- --static int ph_on_message_begin(http_parser *parser) --{ -- DEBUG(SSSDBG_TRACE_INTERNAL, "HTTP Message parsing begins\n"); -- return 0; --} -- --#if ((HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)) --static int ph_on_status(http_parser *parser, const char *at, size_t length) --{ -- struct proxy_http_reply *reply = -- talloc_get_type(parser->data, struct proxy_http_reply); -- -- if (ph_received_data(reply, length)) return -1; -- -- ph_append_string(reply, &reply->reason_phrase, at, length); -- if (!reply->reason_phrase) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Failed to store reason phrase, aborting client!\n"); -- return -1; -- } -- -- return 0; --} --#endif -- --static int ph_on_header_field(http_parser *parser, -- const char *at, size_t length) --{ -- struct proxy_http_reply *reply = -- talloc_get_type(parser->data, struct proxy_http_reply); -- int n = reply->num_headers; -- -- if (ph_received_data(reply, length)) return -1; -- -- if (!reply->headers) { -- reply->headers = talloc_zero_array(reply, struct sec_kvp, 10); -- } else if ((n % 10 == 0) && -- (reply->headers[n - 1].value)) { -- reply->headers = talloc_realloc(reply, reply->headers, -- struct sec_kvp, n + 10); -- if (reply->headers) { -- memset(&reply->headers[n], 0, sizeof(struct sec_kvp) * 10); -- } -- } -- if (!reply->headers) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Failed to store headers, aborting client!\n"); -- return -1; -- } -- -- if (!n || reply->headers[n - 1].value) { -- /* new field */ -- n++; -- } -- ph_append_string(reply->headers, &reply->headers[n - 1].name, at, length); -- if (!reply->headers[n - 1].name) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Failed to store header name, aborting client!\n"); -- return -1; -- } -- -- return 0; --} -- --static int ph_on_header_value(http_parser *parser, -- const char *at, size_t length) --{ -- struct proxy_http_reply *reply = -- talloc_get_type(parser->data, struct proxy_http_reply); -- int n = reply->num_headers; -- -- if (ph_received_data(reply, length)) return -1; -- -- if (!reply->headers) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Invalid headers pointer, aborting client!\n"); -- return -1; -- } -- -- if (reply->headers[n].name && !reply->headers[n].value) { -- /* we increment on new value */ -- n = ++reply->num_headers; -- } -- -- ph_append_string(reply->headers, &reply->headers[n - 1].value, at, length); -- if (!reply->headers[n - 1].value) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Failed to store header value, aborting client!\n"); -- return -1; -- } -- -- return 0; --} -- --static int ph_on_headers_complete(http_parser *parser) --{ -- /* TODO: if message has no body we should return 1 */ -- return 0; --} -- --static int ph_on_body(http_parser *parser, const char *at, size_t length) --{ -- struct proxy_http_reply *reply = -- talloc_get_type(parser->data, struct proxy_http_reply); -- -- if (ph_received_data(reply, length)) return -1; -- -- /* FIXME: body may be binary */ -- ph_append_string(reply, &reply->body.data, at, length); -- if (!reply->body.data) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Failed to store body, aborting!\n"); -- return -1; -- } -- reply->body.length += length; -- -- return 0; --} -- --static int ph_on_message_complete(http_parser *parser) --{ -- struct proxy_http_reply *reply = -- talloc_get_type(parser->data, struct proxy_http_reply); -- -- reply->status_code = parser->status_code; -- reply->complete = true; -- -- return 0; --} -- --static http_parser_settings ph_callbacks = { -- .on_message_begin = ph_on_message_begin, --#if ((HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2)) -- .on_status = ph_on_status, --#endif -- .on_header_field = ph_on_header_field, -- .on_header_value = ph_on_header_value, -- .on_headers_complete = ph_on_headers_complete, -- .on_body = ph_on_body, -- .on_message_complete = ph_on_message_complete --}; -- --static void proxy_fd_recv(void *data) --{ -- char buffer[SEC_PACKET_MAX_RECV_SIZE]; -- struct sec_data packet = { buffer, -- SEC_PACKET_MAX_RECV_SIZE }; -- struct proxy_http_req_state *state; -- struct tevent_req *req; -- bool must_complete = false; -- int ret; -- -- req = talloc_get_type(data, struct tevent_req); -- state = tevent_req_data(req, struct proxy_http_req_state); -- -- if (!state->reply) { -- /* A new reply */ -- state->reply = talloc_zero(state, struct proxy_http_reply); -- if (!state->reply) { -- DEBUG(SSSDBG_FATAL_FAILURE, "Failed to allocate reply, aborting!\n"); -- tevent_req_error(req, ENOMEM); -- return; -- } -- http_parser_init(&state->reply->parser, HTTP_RESPONSE); -- state->reply->parser.data = state->reply; -- } -- -- ret = sec_recv_data(state->sd, &packet); -- switch (ret) { -- case ENODATA: -- DEBUG(SSSDBG_TRACE_ALL, "Server closed connection.\n"); -- /* if we got no content length and the request is not complete, -- * then 0 length will indicate EOF to the parser, otherwise we -- * have an error */ -- must_complete = true; -- break; -- case EAGAIN: -- DEBUG(SSSDBG_TRACE_ALL, -- "Interrupted before any data could be read, retry later\n"); -- return; -- case EOK: -- /* all fine */ -- break; -- default: -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Failed to receive data (%d, %s), aborting\n", -- ret, sss_strerror(ret)); -- tevent_req_error(req, EIO); -- return; -- } -- -- ret = http_parser_execute(&state->reply->parser, &ph_callbacks, -- packet.data, packet.length); -- if (ret != packet.length) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- "Failed to parse request, aborting!\n"); -- tevent_req_error(req, EIO); -- return; -- } -- -- if (!state->reply->complete) { -- if (must_complete) { -- tevent_req_error(req, EIO); -- } -- return; -- } -- -- /* do not read anymore, server is done sending */ -- TEVENT_FD_NOT_READABLE(state->fde); -- tevent_req_done(req); --} -- --static void proxy_fd_handler(struct tevent_context *ev, struct tevent_fd *fde, -- uint16_t flags, void *data) --{ -- if (flags & TEVENT_FD_READ) { -- proxy_fd_recv(data); -- } else if (flags & TEVENT_FD_WRITE) { -- proxy_fd_send(data); -- } --} -- - struct proxy_secret_state { - struct tevent_context *ev; - struct sec_req_ctx *secreq; --- -2.12.2 - diff --git a/0088-secrets-allow-to-configure-certificate-check.patch b/0088-secrets-allow-to-configure-certificate-check.patch deleted file mode 100644 index f62252e..0000000 --- a/0088-secrets-allow-to-configure-certificate-check.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 28 Feb 2017 11:47:32 +0100 -Subject: [PATCH 88/97] secrets: allow to configure certificate check - -Some users may want to use TLS with unverified peer (for example if -they use self-signed certificate) or if unverified hostname (if -certificate hostname does not match with the real hostname). On the -other side it may be useful to point to a directory containing custom -certificate authorities. - -This patch add three new options to secrets responder: -verify_peer => peer's certificate must be valid -verify_host => hostnames must match -capath => path to directory containing CA certs -cacert => ca certificate -cert => client certificate -key => client private key - -Resolves: -https://pagure.io/SSSD/sssd/issue/3192 - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/config/SSSDConfig/__init__.py.in | 6 +++ - src/config/cfg_rules.ini | 6 +++ - src/config/etc/sssd.api.conf | 6 +++ - src/man/sssd-secrets.5.xml | 76 ++++++++++++++++++++++++++++++++++++ - src/responder/secrets/proxy.c | 55 ++++++++++++++++++++++++++ - 5 files changed, 149 insertions(+) - -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index a29d51e0ddffc520107a309d862346fb4d4f5f80..54ad722f07ef91a13a0df278ffd2b1c166bc8d36 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -137,6 +137,12 @@ option_strings = { - 'forward_headers': _('The list of the headers to forward to the Custodia server together with the request'), - 'username': _('The username to use when authenticating to a Custodia server using basic_auth'), - 'password': _('The password to use when authenticating to a Custodia server using basic_auth'), -+ 'verify_peer': _('If true peer\'s certificate is verified if proxy_url uses https protocol'), -+ 'verify_host': _('If false peer\'s certificate may contain different hostname then proxy_url when https protocol is used'), -+ 'capath': _('Path to directory where certificate authority certificates are stored'), -+ 'cacert': _('Path to file containing server\'s CA certificate'), -+ 'cert': _('Path to file containing client\'s certificate'), -+ 'key': _('Path to file containing client\'s private key'), - - # [provider] - 'id_provider' : _('Identity provider'), -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index 1a749db754cedd87f263f7ae596d6f8238bb4357..e47ff33242d6a9e5979fe0eb8eea14c2af28685a 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -265,6 +265,12 @@ option = auth_header_value - option = forward_headers - option = username - option = password -+option = verify_peer -+option = verify_host -+option = capath -+option = cacert -+option = cert -+option = key - - # KCM responder - [rule/allowed_kcm_options] -diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf -index a1a0c2992925a4c7df86832117eec2a0cf7894c9..f86589ecefa0b9e046aba781ded107f8e94395d6 100644 ---- a/src/config/etc/sssd.api.conf -+++ b/src/config/etc/sssd.api.conf -@@ -114,6 +114,12 @@ auth_header_value = str, None, false - forward_headers = list, None, false - username = str, None, false - password = str, None, false -+verify_peer = bool, None, false -+verify_host = bool, None, false -+capath = str, None, false -+cacert = str, None, false -+cert = str, None, false -+key = str, None, false - - [provider] - #Available provider types -diff --git a/src/man/sssd-secrets.5.xml b/src/man/sssd-secrets.5.xml -index 80e9c405921e1fb46a3d172d9873deebfa5ed2ce..44a86c3fb56a8bdebebd01e9f49ad171986282a4 100644 ---- a/src/man/sssd-secrets.5.xml -+++ b/src/man/sssd-secrets.5.xml -@@ -273,6 +273,82 @@ systemctl enable sssd-secrets.service - - - -+ -+ verify_peer (boolean) -+ -+ -+ Whether peer's certificate should be verified and valid -+ if HTTPS protocol is used with the proxy provider. -+ -+ -+ Default: true -+ -+ -+ -+ -+ verify_host (boolean) -+ -+ -+ Whether peer's hostname must match with hostname in -+ its certificate if HTTPS protocol is used with the -+ proxy provider. -+ -+ -+ Default: true -+ -+ -+ -+ -+ capath (string) -+ -+ -+ Path to directory containing stored certificate authority -+ certificates. System default path is used if this option is -+ not set. -+ -+ -+ Default: not set -+ -+ -+ -+ -+ cacert (string) -+ -+ -+ Path to file containing server's certificate authority -+ certificate. If this option is not set then the CA's -+ certificate is looked up in capath. -+ -+ -+ Default: not set -+ -+ -+ -+ -+ cert (string) -+ -+ -+ Path to file containing client's certificate if required -+ by the server. This file may also contain private key or -+ the private key may be in separate file set with -+ key. -+ -+ -+ Default: not set -+ -+ -+ -+ -+ key (string) -+ -+ -+ Path to file containing client's private key. -+ -+ -+ Default: not set -+ -+ -+ - - - -diff --git a/src/responder/secrets/proxy.c b/src/responder/secrets/proxy.c -index 3c495716010ac468c9e2f1fb6356529a8dbdc614..240a1de1e431d511a1eca24d8b463c37ba893e7b 100644 ---- a/src/responder/secrets/proxy.c -+++ b/src/responder/secrets/proxy.c -@@ -59,6 +59,13 @@ struct proxy_cfg { - struct pat_basic_auth basic; - struct pat_header header; - } auth; -+ -+ char *key; -+ char *cert; -+ char *cacert; -+ char *capath; -+ bool verify_peer; -+ bool verify_host; - }; - - static int proxy_get_config_string(struct proxy_context *pctx, -@@ -129,6 +136,38 @@ static int proxy_sec_get_cfg(struct proxy_context *pctx, - } - } - -+ ret = confdb_get_bool(pctx->cdb, secreq->cfg_section, "verify_peer", -+ true, &cfg->verify_peer); -+ if (ret) goto done; -+ DEBUG(SSSDBG_CONF_SETTINGS, "verify_peer: %s\n", -+ (&cfg->verify_peer ? "true" : "false")); -+ -+ ret = confdb_get_bool(pctx->cdb, secreq->cfg_section, "verify_host", -+ true, &cfg->verify_host); -+ if (ret) goto done; -+ DEBUG(SSSDBG_CONF_SETTINGS, "verify_host: %s\n", -+ (&cfg->verify_host ? "true" : "false")); -+ -+ ret = proxy_get_config_string(pctx, cfg, false, secreq, -+ "capath", &cfg->capath); -+ if (ret) goto done; -+ DEBUG(SSSDBG_CONF_SETTINGS, "capath: %s\n", cfg->capath); -+ -+ ret = proxy_get_config_string(pctx, cfg, false, secreq, -+ "cacert", &cfg->cacert); -+ if (ret) goto done; -+ DEBUG(SSSDBG_CONF_SETTINGS, "cacert: %s\n", cfg->cacert); -+ -+ ret = proxy_get_config_string(pctx, cfg, false, secreq, -+ "cert", &cfg->cert); -+ if (ret) goto done; -+ DEBUG(SSSDBG_CONF_SETTINGS, "cert: %s\n", cfg->cert); -+ -+ ret = proxy_get_config_string(pctx, cfg, false, secreq, -+ "key", &cfg->key); -+ if (ret) goto done; -+ DEBUG(SSSDBG_CONF_SETTINGS, "key: %s\n", cfg->key); -+ - ret = confdb_get_string_as_list(pctx->cdb, cfg, secreq->cfg_section, - "forward_headers", &cfg->fwd_headers); - if ((ret != 0) && (ret != ENOENT)) goto done; -@@ -385,6 +424,22 @@ static errno_t proxy_http_create_request(TALLOC_CTX *mem_ctx, - goto done; - } - -+ /* Set TLS settings to verify peer. -+ * This has no effect for HTTP protocol so we can set it anyway. */ -+ ret = tcurl_req_verify_peer(tcurl_req, pcfg->capath, pcfg->cacert, -+ pcfg->verify_peer, pcfg->verify_host); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ /* Set client's certificate if required. */ -+ if (pcfg->cert != NULL) { -+ ret = tcurl_req_set_client_cert(tcurl_req, pcfg->cert, pcfg->key); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ - talloc_steal(tcurl_req, body); - *_tcurl_req = talloc_steal(mem_ctx, tcurl_req); - --- -2.12.2 - diff --git a/0089-secrets-support-HTTP-basic-authentication-with-proxy.patch b/0089-secrets-support-HTTP-basic-authentication-with-proxy.patch deleted file mode 100644 index fbfd6d5..0000000 --- a/0089-secrets-support-HTTP-basic-authentication-with-proxy.patch +++ /dev/null @@ -1,38 +0,0 @@ -From af026ea6a6e812b7d6c5c889dda64ba7b7c433ee Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 28 Feb 2017 13:58:20 +0100 -Subject: [PATCH 89/97] secrets: support HTTP basic authentication with proxy - provider - -Even though configuration options auth_type = basic, username and password -are read they were not used anywhere prior this patch. - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/responder/secrets/proxy.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/src/responder/secrets/proxy.c b/src/responder/secrets/proxy.c -index 240a1de1e431d511a1eca24d8b463c37ba893e7b..fd96e985c897e2cb470a9b5d6eecbd34350fb7d2 100644 ---- a/src/responder/secrets/proxy.c -+++ b/src/responder/secrets/proxy.c -@@ -440,6 +440,15 @@ static errno_t proxy_http_create_request(TALLOC_CTX *mem_ctx, - } - } - -+ /* Set basic authentication if required. */ -+ if (pcfg->auth_type == PAT_BASIC_AUTH) { -+ ret = tcurl_req_http_basic_auth(tcurl_req, pcfg->auth.basic.username, -+ pcfg->auth.basic.password); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ - talloc_steal(tcurl_req, body); - *_tcurl_req = talloc_steal(mem_ctx, tcurl_req); - --- -2.12.2 - diff --git a/0090-secrets-fix-debug-message.patch b/0090-secrets-fix-debug-message.patch deleted file mode 100644 index bf6c20b..0000000 --- a/0090-secrets-fix-debug-message.patch +++ /dev/null @@ -1,28 +0,0 @@ -From db826f57b4c2ee814823057cc536386889f7aa1d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 15 Mar 2017 13:27:59 +0100 -Subject: [PATCH 90/97] secrets: fix debug message - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/responder/secrets/secsrv_cmd.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/responder/secrets/secsrv_cmd.c b/src/responder/secrets/secsrv_cmd.c -index 70679ec0398fca25cfb0525772f539526a0eb3ff..b88680c3d7c3105d160de5c78e6d981b852318b9 100644 ---- a/src/responder/secrets/secsrv_cmd.c -+++ b/src/responder/secrets/secsrv_cmd.c -@@ -451,7 +451,8 @@ int sec_send_data(int fd, struct sec_data *data) - - data->length -= len; - data->data += len; -- DEBUG(SSSDBG_TRACE_INTERNAL, "sent %zu bytes\n", data->length); -+ DEBUG(SSSDBG_TRACE_INTERNAL, "sent %zu bytes, %zu bytes remaining\n", -+ len, data->length); - return EOK; - } - --- -2.12.2 - diff --git a/0091-secrets-always-add-Content-Length-header.patch b/0091-secrets-always-add-Content-Length-header.patch deleted file mode 100644 index e99c262..0000000 --- a/0091-secrets-always-add-Content-Length-header.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 13d720de13e490850c1139eea865bcd5195a2630 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 15 Mar 2017 15:15:08 +0100 -Subject: [PATCH 91/97] secrets: always add Content-Length header - -If custodia server does not reply with Content-Length header, curl may -wait for non-existing body of http reply if such body does not exist -(for example during POST operation when creating a container). - -Reviewed-by: Simo Sorce -Reviewed-by: Jakub Hrozek ---- - src/responder/secrets/providers.c | 72 ++++++++++++++++++++++++++++++++++++--- - 1 file changed, 68 insertions(+), 4 deletions(-) - -diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c -index 80a443d91135447ec8ce8d424b692a6d7e26a907..a27fb720b394e7c76d1b65f656146bcd00755449 100644 ---- a/src/responder/secrets/providers.c -+++ b/src/responder/secrets/providers.c -@@ -388,20 +388,84 @@ int sec_http_reply_with_headers(TALLOC_CTX *mem_ctx, struct sec_data *reply, - return EOK; - } - -+static errno_t -+sec_http_iobuf_split(struct sss_iobuf *response, -+ const char **headers, -+ const char **body) -+{ -+ const char *data = (const char *)sss_iobuf_get_data(response); -+ char *delim; -+ -+ /* The last header ends with \r\n and then comes \r\n again as a separator -+ * of body from headers. We can use this to find this point. */ -+ delim = strstr(data, "\r\n\r\n"); -+ if (delim == NULL) { -+ return EINVAL; -+ } -+ -+ /* Skip to the body delimiter. */ -+ delim = delim + sizeof("\r\n") - 1; -+ -+ /* Replace \r\n with zeros turning data into: -+ * from HEADER\r\nBODY into HEADER\0\0BODY format. */ -+ delim[0] = '\0'; -+ delim[1] = '\0'; -+ -+ /* Split the buffer. */ -+ *headers = data; -+ *body = delim + 2; -+ -+ return 0; -+} -+ -+static const char * -+sec_http_iobuf_add_content_length(TALLOC_CTX *mem_ctx, -+ const char *headers, -+ size_t body_len) -+{ -+ /* If Content-Length is already present we do nothing. */ -+ if (strstr(headers, "Content-Length:") != NULL) { -+ return headers; -+ } -+ -+ return talloc_asprintf(mem_ctx, "%sContent-Length: %zu\r\n", -+ headers, body_len); -+} -+ - errno_t sec_http_reply_iobuf(TALLOC_CTX *mem_ctx, - struct sec_data *reply, - int response_code, - struct sss_iobuf *response) - { -+ const char *headers; -+ const char *body; -+ size_t body_len; -+ errno_t ret; -+ - DEBUG(SSSDBG_TRACE_LIBS, "HTTP reply %d\n", response_code); - -- reply->data = (char *)sss_iobuf_get_data(response); -- reply->length = sss_iobuf_get_len(response); -+ ret = sec_http_iobuf_split(response, &headers, &body); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Unexpected HTTP reply, returning what we got from server\n"); -+ reply->data = (char *)sss_iobuf_get_data(response); -+ reply->length = sss_iobuf_get_len(response); - -- talloc_steal(mem_ctx, reply->data); -+ return EOK; -+ } - -+ /* Add Content-Length header if not present so client does not await -+ * not-existing incoming data. */ -+ body_len = strlen(body); -+ headers = sec_http_iobuf_add_content_length(mem_ctx, headers, body_len); -+ if (headers == NULL) { -+ return ENOMEM; -+ } -+ -+ reply->length = strlen(headers) + sizeof("\r\n") - 1 + body_len; -+ reply->data = talloc_asprintf(mem_ctx, "%s\r\n%s", headers, body); - if (reply->data == NULL) { -- return EINVAL; -+ return ENOMEM; - } - - return EOK; --- -2.12.2 - diff --git a/0092-sss_iobuf-fix-read-shadows-a-global-declaration.patch b/0092-sss_iobuf-fix-read-shadows-a-global-declaration.patch deleted file mode 100644 index c4e483f..0000000 --- a/0092-sss_iobuf-fix-read-shadows-a-global-declaration.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 18e4fe9d836e8f7bee52724374ffc0011172329f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 28 Mar 2017 15:26:52 +0200 -Subject: [PATCH 92/97] sss_iobuf: fix 'read' shadows a global declaration -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Lukáš Slebodník ---- - src/util/sss_iobuf.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/util/sss_iobuf.c b/src/util/sss_iobuf.c -index fc288d2df2bfaaba393dd490d4da8976de804cb5..518713e4cc3dd99627a3a4450f235cbbc69ed3a2 100644 ---- a/src/util/sss_iobuf.c -+++ b/src/util/sss_iobuf.c -@@ -188,15 +188,15 @@ errno_t sss_iobuf_read_len(struct sss_iobuf *iobuf, - size_t len, - uint8_t *_buf) - { -- size_t read; -+ size_t read_bytes; - errno_t ret; - -- ret = sss_iobuf_read(iobuf, len, _buf, &read); -+ ret = sss_iobuf_read(iobuf, len, _buf, &read_bytes); - if (ret != EOK) { - return ret; - } - -- if (read != len) { -+ if (read_bytes != len) { - return ENOBUFS; - } - --- -2.12.2 - diff --git a/0093-configure-fix-typo.patch b/0093-configure-fix-typo.patch deleted file mode 100644 index f12dbbd..0000000 --- a/0093-configure-fix-typo.patch +++ /dev/null @@ -1,28 +0,0 @@ -From dc186bfe90665c13d589b3b4efd9009293e62c46 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 29 Mar 2017 13:28:49 +0200 -Subject: [PATCH 93/97] configure: fix typo -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Lukáš Slebodník ---- - src/external/libhttp_parser.m4 | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/external/libhttp_parser.m4 b/src/external/libhttp_parser.m4 -index 504bdf0f66c95b3d224c677a205a46e6f8b44726..3a5ef0dbbc63423ad8e960d72e97ec4fb4481dd1 100644 ---- a/src/external/libhttp_parser.m4 -+++ b/src/external/libhttp_parser.m4 -@@ -17,6 +17,6 @@ AS_IF([test x"$found_http_parser" != xyes], - ], - [-L$sss_extra_libdir -lhttp_parser_strict])], - [AC_MSG_ERROR([ --You must have the header file http_parse.h installed to build sssd -+You must have the header file http_parser.h installed to build sssd - with secrets responder. If you want to build sssd without secret responder - then specify --without-secrets when running configure.])])]) --- -2.12.2 - diff --git a/0094-libsss_certmap-Accept-certificate-with-data-before-h.patch b/0094-libsss_certmap-Accept-certificate-with-data-before-h.patch deleted file mode 100644 index 74500a9..0000000 --- a/0094-libsss_certmap-Accept-certificate-with-data-before-h.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 5231ba679402eeb0705a3ecd41f97fdd67d42a69 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Fri, 31 Mar 2017 21:31:23 +0200 -Subject: [PATCH 94/97] libsss_certmap: Accept certificate with data before - header -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -According to RFC 7468 parser must not fail when some data are present -before the encapsulation boundary. sss_cert_pem_to_der didn't respect -this and refused valid input. Changing it's code to first locate -the certificate header fixes the issue. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3354 - -Reviewed-by: Sumit Bose -Reviewed-by: Fabiano Fidêncio ---- - src/tests/cmocka/test_cert_utils.c | 16 ++++++++++++++++ - src/util/cert/nss/cert.c | 9 +++++---- - 2 files changed, 21 insertions(+), 4 deletions(-) - -diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c -index 5830131754e4cf318273151b586ef36d6a349829..8003d8daa7063773cf8b37c46ac8759e3a38736f 100644 ---- a/src/tests/cmocka/test_cert_utils.c -+++ b/src/tests/cmocka/test_cert_utils.c -@@ -128,6 +128,13 @@ const uint8_t test_cert_der[] = { - "lBPDhfTVcWXQwN385uycW/ARtSzzSME2jKKWSIQ=\n" \ - "-----END CERTIFICATE-----\n" - -+#define TEST_CERT_PEM_WITH_METADATA "Bag Attributes\n" \ -+" friendlyName: ipa-devel\n" \ -+" localKeyID: 8E 0D 04 1F BC 13 73 54 00 8F 65 57 D7 A8 AF 34 0C 18 B3 99\n" \ -+"subject= /O=IPA.DEVEL/CN=ipa-devel.ipa.devel\n" \ -+"issuer= /O=IPA.DEVEL/CN=Certificate Authority\n" \ -+TEST_CERT_PEM -+ - #define TEST_CERT_DERB64 \ - "MIIECTCCAvGgAwIBAgIBCTANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \ - "REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA0Mjgx" \ -@@ -219,6 +226,15 @@ void test_sss_cert_pem_to_der(void **state) - assert_memory_equal(der, test_cert_der, der_size); - - talloc_free(der); -+ -+ /* https://pagure.io/SSSD/sssd/issue/3354 -+ https://tools.ietf.org/html/rfc7468#section-2 */ -+ ret = sss_cert_pem_to_der(ts, TEST_CERT_PEM_WITH_METADATA, &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) -diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c -index 9d31cfe9b584aa4f87a60ffec03dcf391fe43067..93d4e04220be71ce5823b077525d9f6676e5b763 100644 ---- a/src/util/cert/nss/cert.c -+++ b/src/util/cert/nss/cert.c -@@ -147,16 +147,17 @@ errno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem, - return EINVAL; - } - -+ if ((pem = strstr(pem, NS_CERT_HEADER)) == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing PEM header."); -+ return EINVAL; -+ } -+ - pem_len = strlen(pem); - if (pem_len <= NS_CERT_HEADER_LEN + NS_CERT_TRAILER_LEN) { - DEBUG(SSSDBG_CRIT_FAILURE, "PEM data too short.\n"); - return EINVAL; - } - -- if (strncmp(pem, NS_CERT_HEADER, NS_CERT_HEADER_LEN) != 0) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM header.\n"); -- return EINVAL; -- } - if (pem[NS_CERT_HEADER_LEN] != '\n') { - DEBUG(SSSDBG_CRIT_FAILURE, "Missing newline in PEM data.\n"); - return EINVAL; --- -2.12.2 - diff --git a/0095-BUILD-Fix-compilation-of-libsss_certmap-with-libcryp.patch b/0095-BUILD-Fix-compilation-of-libsss_certmap-with-libcryp.patch deleted file mode 100644 index d44a4a4..0000000 --- a/0095-BUILD-Fix-compilation-of-libsss_certmap-with-libcryp.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 84fecc2fd535030bc56b5046ba2a1ba95c46bc34 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 24 Mar 2017 10:37:50 +0100 -Subject: [PATCH 95/97] BUILD: Fix compilation of libsss_certmap with libcrypto - - CC src/lib/certmap/libsss_certmap_la-sss_cert_content_nss.lo - src/lib/certmap/sss_cert_content_nss.c:25:18: - fatal error: cert.h: No such file or directory - #include - ^ -compilation terminated. - -Reviewed-by: Sumit Bose ---- - Makefile.am | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/Makefile.am b/Makefile.am -index 4a414f77df999b8b1d81f663fcc18dbd2d6d2dc4..5264183cd199be464e5e99d2ab31ba4fcd77c5ec 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1787,7 +1787,6 @@ libsss_certmap_la_DEPENDENCIES = src/lib/certmap/sss_certmap.exports - libsss_certmap_la_SOURCES = \ - src/lib/certmap/sss_certmap.c \ - src/lib/certmap/sss_certmap_attr_names.c \ -- src/lib/certmap/sss_cert_content_nss.c \ - src/lib/certmap/sss_certmap_krb5_match.c \ - src/lib/certmap/sss_certmap_ldap_mapping.c \ - src/util/util_ext.c \ -@@ -1806,6 +1805,7 @@ libsss_certmap_la_LDFLAGS = \ - - if HAVE_NSS - libsss_certmap_la_SOURCES += \ -+ src/lib/certmap/sss_cert_content_nss.c \ - src/util/crypto/nss/nss_base64.c \ - src/util/cert/nss/cert.c \ - src/util/crypto/nss/nss_util.c \ -@@ -1814,6 +1814,7 @@ libsss_certmap_la_CFLAGS += $(NSS_CFLAGS) - libsss_certmap_la_LIBADD += $(NSS_LIBS) - else - libsss_certmap_la_SOURCES += \ -+ src/lib/certmap/sss_cert_content_crypto.c \ - src/util/crypto/libcrypto/crypto_base64.c \ - src/util/cert/libcrypto/cert.c \ - $(NULL) --- -2.12.2 - diff --git a/0096-responders-do-not-leak-selinux-context-on-clients-de.patch b/0096-responders-do-not-leak-selinux-context-on-clients-de.patch deleted file mode 100644 index 587adca..0000000 --- a/0096-responders-do-not-leak-selinux-context-on-clients-de.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 05c2c3047912fca1c1a35ab1c8d3157b05383495 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 3 Apr 2017 12:56:01 +0200 -Subject: [PATCH 96/97] responders: do not leak selinux context on clients - destruction -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The SELinux context created in get_client_cred is not talloc bound and -we were leaking it if available with each client's destruction. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3360 - -Reviewed-by: Lukáš Slebodník ---- - src/responder/common/responder_common.c | 20 +++++++++++++++++++- - 1 file changed, 19 insertions(+), 1 deletion(-) - -diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c -index 154d7dc7718c437d10e152fcba98161e2034fb14..67e1deefdfde19c95a68029b11099579d851513f 100644 ---- a/src/responder/common/responder_common.c -+++ b/src/responder/common/responder_common.c -@@ -97,7 +97,7 @@ static errno_t get_client_cred(struct cli_ctx *cctx) - SEC_CTX secctx; - int ret; - -- cctx->creds = talloc(cctx, struct cli_creds); -+ cctx->creds = talloc_zero(cctx, struct cli_creds); - if (!cctx->creds) return ENOMEM; - - #ifdef HAVE_UCRED -@@ -464,6 +464,22 @@ static void client_fd_handler(struct tevent_context *ev, - - static errno_t setup_client_idle_timer(struct cli_ctx *cctx); - -+static int cli_ctx_destructor(struct cli_ctx *cctx) -+{ -+ if (cctx->creds == NULL) { -+ return 0; -+ } -+ -+ if (cctx->creds->selinux_ctx == NULL) { -+ return 0; -+ } -+ -+ SELINUX_context_free(cctx->creds->selinux_ctx); -+ cctx->creds->selinux_ctx = NULL; -+ -+ return 0; -+} -+ - struct accept_fd_ctx { - struct resp_ctx *rctx; - bool is_private; -@@ -520,6 +536,8 @@ static void accept_fd_handler(struct tevent_context *ev, - return; - } - -+ talloc_set_destructor(cctx, cli_ctx_destructor); -+ - len = sizeof(cctx->addr); - cctx->cfd = accept(fd, (struct sockaddr *)&cctx->addr, &len); - if (cctx->cfd == -1) { --- -2.12.2 - diff --git a/0097-ipa_s2n_get_acct_info_send-provide-correct-req_input.patch b/0097-ipa_s2n_get_acct_info_send-provide-correct-req_input.patch deleted file mode 100644 index b8fde8a..0000000 --- a/0097-ipa_s2n_get_acct_info_send-provide-correct-req_input.patch +++ /dev/null @@ -1,88 +0,0 @@ -From b07bcd8b99590bd404733fa7ff1add37c55126bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 3 Apr 2017 12:09:44 +0200 -Subject: [PATCH 97/97] ipa_s2n_get_acct_info_send: provide correct req_input - name -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -To avoid crash. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3358 - -Reviewed-by: Sumit Bose -Reviewed-by: Lukáš Slebodník ---- - src/providers/ipa/ipa_s2n_exop.c | 40 ++++++++++++++++++++++++++++++++++++---- - 1 file changed, 36 insertions(+), 4 deletions(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 8a3391b4093f1547d84fe44a0f24b1d063d1e28c..2173db357700499a6140aa61841e443139981483 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -1054,6 +1054,33 @@ static const char *ipa_s2n_reqtype2str(enum request_types request_type) - return "Unknown request type"; - } - -+static const char *ipa_s2n_reqinp2str(TALLOC_CTX *mem_ctx, -+ struct req_input *req_input) -+{ -+ const char *str = NULL; -+ -+ switch (req_input->type) { -+ case REQ_INP_NAME: -+ str = talloc_strdup(mem_ctx, req_input->inp.name); -+ break; -+ case REQ_INP_SECID: -+ str = talloc_strdup(mem_ctx, req_input->inp.secid); -+ break; -+ case REQ_INP_CERT: -+ str = talloc_strdup(mem_ctx, req_input->inp.cert); -+ break; -+ case REQ_INP_ID: -+ str = talloc_asprintf(mem_ctx, "%u", req_input->inp.id); -+ break; -+ } -+ -+ if (str == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); -+ } -+ -+ return str; -+} -+ - struct ipa_s2n_get_list_state { - struct tevent_context *ev; - struct ipa_id_ctx *ipa_ctx; -@@ -1410,6 +1437,7 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx, - struct tevent_req *req; - struct tevent_req *subreq; - struct berval *bv_req = NULL; -+ const char *input; - int ret = EFAULT; - bool is_v1 = false; - -@@ -1454,10 +1482,14 @@ struct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx, - goto fail; - } - -- DEBUG(SSSDBG_TRACE_FUNC, "Sending request_type: [%s] for trust user [%s] " -- "to IPA server\n", -- ipa_s2n_reqtype2str(state->request_type), -- req_input->inp.name); -+ if (DEBUG_IS_SET(SSSDBG_TRACE_FUNC)) { -+ input = ipa_s2n_reqinp2str(state, req_input); -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Sending request_type: [%s] for trust user [%s] to IPA server\n", -+ ipa_s2n_reqtype2str(state->request_type), -+ input); -+ talloc_zfree(input); -+ } - - subreq = ipa_s2n_exop_send(state, state->ev, state->sh, is_v1, - state->exop_timeout, bv_req); --- -2.12.2 - diff --git a/0098-selinux-Do-not-fail-if-SELinux-is-not-managed.patch b/0098-selinux-Do-not-fail-if-SELinux-is-not-managed.patch deleted file mode 100644 index f93ad38..0000000 --- a/0098-selinux-Do-not-fail-if-SELinux-is-not-managed.patch +++ /dev/null @@ -1,210 +0,0 @@ -From 78a08d30b5fbf6e1e3b589e0cf67022e0c1faa33 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20=C5=BDidek?= -Date: Wed, 8 Feb 2017 12:01:37 +0100 -Subject: [PATCH] selinux: Do not fail if SELinux is not managed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Previously we failed if semanage_is_managed returned 0 or -1 (not -managed or error). With this patch we only fail in case of error and -continue normally if selinux is not managed by libsemanage at all. - -Resolves: -https://fedorahosted.org/sssd/ticket/3297 - -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 1 + - src/providers/ipa/selinux_child.c | 9 ++++-- - src/util/sss_semanage.c | 61 +++++++++++++++++++++++++-------------- - src/util/util_errors.c | 1 + - src/util/util_errors.h | 1 + - 5 files changed, 49 insertions(+), 24 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 5264183cd..d45c0ff75 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -4040,6 +4040,7 @@ selinux_child_SOURCES = \ - src/util/atomic_io.c \ - src/util/util.c \ - src/util/util_ext.c \ -+ src/util/util_errors.c - $(NULL) - selinux_child_CFLAGS = \ - $(AM_CFLAGS) \ -diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c -index 380005c7a..f8dd3954a 100644 ---- a/src/providers/ipa/selinux_child.c -+++ b/src/providers/ipa/selinux_child.c -@@ -174,14 +174,19 @@ static bool seuser_needs_update(struct input_buffer *ibuf) - - ret = get_seuser(ibuf, ibuf->username, &db_seuser, &db_mls_range); - DEBUG(SSSDBG_TRACE_INTERNAL, -- "get_seuser: ret: %d seuser: %s mls: %s\n", -- ret, db_seuser ? db_seuser : "unknown", -+ "get_seuser: ret: %d msg: [%s] seuser: %s mls: %s\n", -+ ret, sss_strerror(ret), -+ db_seuser ? db_seuser : "unknown", - db_mls_range ? db_mls_range : "unknown"); - if (ret == EOK && db_seuser && db_mls_range && - strcmp(db_seuser, ibuf->seuser) == 0 && - strcmp(db_mls_range, ibuf->mls_range) == 0) { - needs_update = false; - } -+ /* OR */ -+ if (ret == ERR_SELINUX_NOT_MANAGED) { -+ needs_update = false; -+ } - - talloc_free(db_seuser); - talloc_free(db_mls_range); -diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c -index fe06bee1d..0da97aad4 100644 ---- a/src/util/sss_semanage.c -+++ b/src/util/sss_semanage.c -@@ -73,7 +73,7 @@ static void sss_semanage_close(semanage_handle_t *handle) - semanage_handle_destroy(handle); - } - --static semanage_handle_t *sss_semanage_init(void) -+static int sss_semanage_init(semanage_handle_t **_handle) - { - int ret; - semanage_handle_t *handle = NULL; -@@ -81,7 +81,8 @@ static semanage_handle_t *sss_semanage_init(void) - handle = semanage_handle_create(); - if (!handle) { - DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux management handle\n"); -- return NULL; -+ ret = EIO; -+ goto done; - } - - semanage_msg_set_callback(handle, -@@ -89,28 +90,41 @@ static semanage_handle_t *sss_semanage_init(void) - NULL); - - ret = semanage_is_managed(handle); -- if (ret != 1) { -- DEBUG(SSSDBG_CRIT_FAILURE, "SELinux policy not managed\n"); -- goto fail; -+ if (ret == 0) { -+ DEBUG(SSSDBG_TRACE_FUNC, "SELinux policy not managed via libsemanage\n"); -+ ret = ERR_SELINUX_NOT_MANAGED; -+ goto done; -+ } else if (ret == -1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Call to semanage_is_managed failed\n"); -+ ret = EIO; -+ goto done; - } - - ret = semanage_access_check(handle); - if (ret < SEMANAGE_CAN_READ) { - DEBUG(SSSDBG_CRIT_FAILURE, "Cannot read SELinux policy store\n"); -- goto fail; -+ ret = EACCES; -+ goto done; - } - - ret = semanage_connect(handle); - if (ret != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Cannot estabilish SELinux management connection\n"); -- goto fail; -+ ret = EIO; -+ goto done; - } - -- return handle; --fail: -- sss_semanage_close(handle); -- return NULL; -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ sss_semanage_close(handle); -+ } else { -+ *_handle = handle; -+ } -+ -+ return ret; - } - - static int sss_semanage_user_add(semanage_handle_t *handle, -@@ -228,10 +242,11 @@ int set_seuser(const char *login_name, const char *seuser_name, - return EOK; - } - -- handle = sss_semanage_init(); -- if (!handle) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init SELinux management\n"); -- ret = EIO; -+ ret = sss_semanage_init(&handle); -+ if (ret == ERR_SELINUX_NOT_MANAGED) { -+ goto done; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux handle\n"); - goto done; - } - -@@ -295,10 +310,11 @@ int del_seuser(const char *login_name) - int ret; - int exists = 0; - -- handle = sss_semanage_init(); -- if (!handle) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init SELinux management\n"); -- ret = EIO; -+ ret = sss_semanage_init(&handle); -+ if (ret == ERR_SELINUX_NOT_MANAGED) { -+ goto done; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux handle\n"); - goto done; - } - -@@ -377,10 +393,11 @@ int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name, - semanage_seuser_t *sm_user = NULL; - semanage_seuser_key_t *sm_key = NULL; - -- sm_handle = sss_semanage_init(); -- if (sm_handle == NULL) { -+ ret = sss_semanage_init(&sm_handle); -+ if (ret == ERR_SELINUX_NOT_MANAGED) { -+ goto done; -+ } else if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux handle\n"); -- ret = EIO; - goto done; - } - -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 466a3b406..97eaf160f 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -75,6 +75,7 @@ struct err_string error_to_str[] = { - { "Cannot connect to system bus" }, /* ERR_NO_SYSBUS */ - { "LDAP search returned a referral" }, /* ERR_REFERRAL */ - { "Error setting SELinux user context" }, /* ERR_SELINUX_CONTEXT */ -+ { "SELinux is not managed by libsemanage" }, /* ERR_SELINUX_NOT_MANAGED */ - { "Username format not allowed by re_expression" }, /* ERR_REGEX_NOMATCH */ - { "Time specification not supported" }, /* ERR_TIMESPEC_NOT_SUPPORTED */ - { "Invalid SSSD configuration detected" }, /* ERR_INVALID_CONFIG */ -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 2f90c0a5d..4a250bf03 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -97,6 +97,7 @@ enum sssd_errors { - ERR_NO_SYSBUS, - ERR_REFERRAL, - ERR_SELINUX_CONTEXT, -+ ERR_SELINUX_NOT_MANAGED, - ERR_REGEX_NOMATCH, - ERR_TIMESPEC_NOT_SUPPORTED, - ERR_INVALID_CONFIG, --- -2.12.2 - diff --git a/0099-DP-Fix-typo.patch b/0099-DP-Fix-typo.patch deleted file mode 100644 index 131aad2..0000000 --- a/0099-DP-Fix-typo.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 6a611406e805a1707ca0b9e86b6aa96e02e43ecc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Thu, 6 Apr 2017 11:23:43 +0200 -Subject: [PATCH 099/135] DP: Fix typo -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Lukáš Slebodník ---- - src/providers/data_provider/dp_target_id.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c -index 0bca9bac27b68a8b905a668992cb8f7650023f65..2088f9529cab83794ac793c7fd5a320f479dbf11 100644 ---- a/src/providers/data_provider/dp_target_id.c -+++ b/src/providers/data_provider/dp_target_id.c -@@ -210,7 +210,7 @@ static errno_t dp_initgroups(struct sbus_request *sbus_req, - - ret = sysdb_initgroups(sbus_req, domain, data->filter_value, &res); - if (ret == ENOENT || (ret == EOK && res->count == 0)) { -- /* There is no point in concacting NSS responder. Proceed as usual. */ -+ /* There is no point in contacting NSS responder. Proceed as usual. */ - return EAGAIN; - } else if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get initgroups [%d]: %s\n", -@@ -274,7 +274,7 @@ errno_t dp_get_account_info_handler(struct sbus_request *sbus_req, - } - - if ((data->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_INITGROUPS) { -- ret = dp_initgroups(sbus_req, dp_cli, key, dp_flags, data); -+ ret = dp_initgroups(sbus_req, dp_cli, key, dp_flags, data); - if (ret != EAGAIN) { - goto done; - } --- -2.12.2 - diff --git a/0100-CONFDB-Fix-handling-of-enable_files_domain.patch b/0100-CONFDB-Fix-handling-of-enable_files_domain.patch deleted file mode 100644 index 4abe713..0000000 --- a/0100-CONFDB-Fix-handling-of-enable_files_domain.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 3509bb03ecef49264820c9e287e8b2c7e0a8a508 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 5 Apr 2017 14:04:46 +0200 -Subject: [PATCH 100/135] CONFDB: Fix handling of enable_files_domain -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The option enable_files_domain worked only if sssd -was compiled with --enable-files-domain. But manual page described -something else. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3340 - -Reviewed-by: Michal Židek ---- - src/confdb/confdb.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c -index 88e114457deac3ca50c291a131122624fb6f6fe4..68693e8382c0fbf1015ee47f14fa7c6f64ae98b2 100644 ---- a/src/confdb/confdb.c -+++ b/src/confdb/confdb.c -@@ -1695,7 +1695,6 @@ done: - return ret; - } - --#ifdef ADD_FILES_DOMAIN - static int confdb_has_files_domain(struct confdb_ctx *cdb) - { - TALLOC_CTX *tmp_ctx = NULL; -@@ -1830,25 +1829,27 @@ done: - talloc_free(tmp_ctx); - return ret; - } --#endif /* ADD_FILES_DOMAIN */ - - int confdb_ensure_files_domain(struct confdb_ctx *cdb, - const char *implicit_files_dom_name) - { --#ifndef ADD_FILES_DOMAIN -- return EOK; -+#ifdef ADD_FILES_DOMAIN -+ const bool default_enable_files = true; - #else -+ const bool default_enable_files = false; -+#endif - errno_t ret; - bool enable_files; - - ret = confdb_get_bool(cdb, - CONFDB_MONITOR_CONF_ENTRY, - CONFDB_MONITOR_ENABLE_FILES_DOM, -- true, &enable_files); -+ default_enable_files, &enable_files); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, -- "Cannot get the value of %s assuming true\n", -- CONFDB_MONITOR_ENABLE_FILES_DOM); -+ "Cannot get the value of %s assuming %s\n", -+ CONFDB_MONITOR_ENABLE_FILES_DOM, -+ default_enable_files ? "true" : "false"); - return ret; - } - -@@ -1874,7 +1875,6 @@ int confdb_ensure_files_domain(struct confdb_ctx *cdb, - } - - return activate_files_domain(cdb, implicit_files_dom_name); --#endif /* ADD_FILES_DOMAIN */ - } - - static int confdb_get_parent_domain(TALLOC_CTX *mem_ctx, --- -2.12.2 - diff --git a/0101-pam_test_client-add-service-and-environment-to-PAM-t.patch b/0101-pam_test_client-add-service-and-environment-to-PAM-t.patch deleted file mode 100644 index a854e24..0000000 --- a/0101-pam_test_client-add-service-and-environment-to-PAM-t.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 7be6624d9eda369e9a4d70c8ee4939b3622229b3 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 24 Jan 2017 14:50:20 +0100 -Subject: [PATCH 101/135] pam_test_client: add service and environment to PAM - test client -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to https://pagure.io/SSSD/sssd/issue/3292 - -Reviewed-by: Pavel Březina ---- - src/sss_client/pam_test_client.c | 50 ++++++++++++++++++++++++++++++---------- - 1 file changed, 38 insertions(+), 12 deletions(-) - -diff --git a/src/sss_client/pam_test_client.c b/src/sss_client/pam_test_client.c -index 29d1fcbf01682668d51bf154736aec673bd46501..ea032a75b195a9bf8078ed7d248da154ab0c8430 100644 ---- a/src/sss_client/pam_test_client.c -+++ b/src/sss_client/pam_test_client.c -@@ -48,34 +48,44 @@ static struct pam_conv conv = { - # error "Missing text based pam conversation function" - #endif - -+#define DEFAULT_ACTION "acct" -+#define DEFAULT_SERVICE "system-auth" -+ - int main(int argc, char *argv[]) { - - pam_handle_t *pamh; - char *user; - char *action; -+ char *service; - int ret; -+ size_t c; -+ char **pam_env; - - if (argc == 1) { -- fprintf(stderr, "missing action and user name, using default\n"); -- action = strdup("auth"); -- user = strdup("dummy"); -+ fprintf(stderr, "Usage: pam_test_client USERNAME " -+ "[auth|acct|setc|chau|open|clos] [pam_service]\n"); -+ return 0; - } else if (argc == 2) { -- fprintf(stdout, "using first argument as action and default user name\n"); -- action = strdup(argv[1]); -- user = strdup("dummy"); -- } else { -- action = strdup(argv[1]); -- user = strdup(argv[2]); -+ fprintf(stderr, "using first argument as user name and default action " -+ "and service\n"); -+ } else if (argc == 3) { -+ fprintf(stderr, "using first argument as user name, second as action " -+ "and default service\n"); - } - -- if (action == NULL || user == NULL) { -+ user = strdup(argv[1]); -+ action = argc > 2 ? strdup(argv[2]) : strdup(DEFAULT_ACTION); -+ service = argc > 3 ? strdup(argv[3]) : strdup(DEFAULT_SERVICE); -+ -+ if (action == NULL || user == NULL || service == NULL) { - fprintf(stderr, "Out of memory!\n"); - return 1; - } - -- fprintf(stdout, "action: %s\nuser: %s\n", action,user); -+ fprintf(stdout, "user: %s\naction: %s\nservice: %s\n", -+ user, action, service); - -- ret = pam_start("sss_test", user, &conv, &pamh); -+ ret = pam_start(service, user, &conv, &pamh); - if (ret != PAM_SUCCESS) { - fprintf(stderr, "pam_start failed: %s\n", pam_strerror(pamh, ret)); - return 1; -@@ -109,7 +119,23 @@ int main(int argc, char *argv[]) { - fprintf(stderr, "unknown action\n"); - } - -+ fprintf(stderr, "PAM Environment:\n"); -+ pam_env = pam_getenvlist(pamh); -+ if (pam_env != NULL && pam_env[0] != NULL) { -+ for (c = 0; pam_env[c] != NULL; c++) { -+ fprintf(stderr, " - %s\n", pam_env[c]); -+ free(pam_env[c]); -+ } -+ } else { -+ fprintf(stderr, " - no env -\n"); -+ } -+ free(pam_env); -+ - pam_end(pamh, ret); - -+ free(user); -+ free(action); -+ free(service); -+ - return 0; - } --- -2.12.2 - diff --git a/0102-pam_test_client-add-SSSD-getpwnam-lookup.patch b/0102-pam_test_client-add-SSSD-getpwnam-lookup.patch deleted file mode 100644 index 624fcae..0000000 --- a/0102-pam_test_client-add-SSSD-getpwnam-lookup.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 435b3678de25d22eb8a6e892109d26c32f0760a4 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 25 Jan 2017 16:50:00 +0100 -Subject: [PATCH 102/135] pam_test_client: add SSSD getpwnam lookup -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to https://pagure.io/SSSD/sssd/issue/3292 - -Reviewed-by: Pavel Březina ---- - Makefile.am | 10 ++++-- - src/sss_client/pam_test_client.c | 76 ++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 84 insertions(+), 2 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index d45c0ff757dfae378c71c6f8850fddce2c61cad8..7aca5b86f1275e89ae73f5594887f515773c2058 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -3461,8 +3461,14 @@ if BUILD_WITH_LIBCURL - noinst_PROGRAMS += tcurl-test-tool - endif - --pam_test_client_SOURCES = src/sss_client/pam_test_client.c --pam_test_client_LDADD = $(PAM_LIBS) $(PAM_MISC_LIBS) -+pam_test_client_SOURCES = \ -+ src/sss_client/pam_test_client.c \ -+ $(NULL) -+pam_test_client_LDADD = \ -+ $(PAM_LIBS) \ -+ $(PAM_MISC_LIBS) \ -+ $(LIBADD_DL) \ -+ $(NULL) - - if BUILD_AUTOFS - autofs_test_client_SOURCES = \ -diff --git a/src/sss_client/pam_test_client.c b/src/sss_client/pam_test_client.c -index ea032a75b195a9bf8078ed7d248da154ab0c8430..69af612270492968b56d1c11de2bf56ebf57471f 100644 ---- a/src/sss_client/pam_test_client.c -+++ b/src/sss_client/pam_test_client.c -@@ -25,6 +25,11 @@ - #include - #include - #include -+#include -+#include -+#include -+#include -+#include - - #include - -@@ -51,6 +56,70 @@ static struct pam_conv conv = { - #define DEFAULT_ACTION "acct" - #define DEFAULT_SERVICE "system-auth" - -+#define DEFAULT_BUFSIZE 4096 -+ -+static int sss_getpwnam_check(const char *user) -+{ -+ void *dl_handle = NULL; -+ enum nss_status (*sss_getpwnam_r)(const char *name, struct passwd *result, -+ char *buffer, size_t buflen, -+ int *errnop); -+ struct passwd pwd = { 0 }; -+ enum nss_status status; -+ char *buffer = NULL; -+ size_t buflen; -+ int nss_errno; -+ int ret; -+ -+ dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW); -+ if (dl_handle == NULL) { -+ fprintf(stderr, "dlopen failed with [%s].\n", dlerror()); -+ ret = EIO; -+ goto done; -+ } -+ -+ sss_getpwnam_r = dlsym(dl_handle, "_nss_sss_getpwnam_r"); -+ if (sss_getpwnam_r == NULL) { -+ fprintf(stderr, "dlsym failed with [%s].\n", dlerror()); -+ ret = EIO; -+ goto done; -+ } -+ -+ buflen = DEFAULT_BUFSIZE; -+ buffer = malloc(buflen); -+ if (buffer == NULL) { -+ fprintf(stderr, "malloc failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ status = sss_getpwnam_r(user, &pwd, buffer, buflen, &nss_errno); -+ if (status != NSS_STATUS_SUCCESS) { -+ fprintf(stderr, "sss_getpwnam_r failed with [%d].\n", status); -+ ret = EIO; -+ goto done; -+ } -+ -+ fprintf(stdout, "SSSD nss user lookup result:\n"); -+ fprintf(stdout, " - user name: %s\n", pwd.pw_name); -+ fprintf(stdout, " - user id: %d\n", pwd.pw_uid); -+ fprintf(stdout, " - group id: %d\n", pwd.pw_gid); -+ fprintf(stdout, " - gecos: %s\n", pwd.pw_gecos); -+ fprintf(stdout, " - home directory: %s\n", pwd.pw_dir); -+ fprintf(stdout, " - shell: %s\n", pwd.pw_shell); -+ -+ ret = 0; -+ -+done: -+ if (dl_handle != NULL) { -+ dlclose(dl_handle); -+ } -+ -+ free(buffer); -+ -+ return ret; -+} -+ - int main(int argc, char *argv[]) { - - pam_handle_t *pamh; -@@ -85,6 +154,13 @@ int main(int argc, char *argv[]) { - fprintf(stdout, "user: %s\naction: %s\nservice: %s\n", - user, action, service); - -+ if (*user != '\0') { -+ ret = sss_getpwnam_check(user); -+ if (ret != 0) { -+ fprintf(stderr, "User name lookup with [%s] failed.\n", user); -+ } -+ } -+ - ret = pam_start(service, user, &conv, &pamh); - if (ret != PAM_SUCCESS) { - fprintf(stderr, "pam_start failed: %s\n", pam_strerror(pamh, ret)); --- -2.12.2 - diff --git a/0103-sss_sifp-update-method-names.patch b/0103-sss_sifp-update-method-names.patch deleted file mode 100644 index 752c46c..0000000 --- a/0103-sss_sifp-update-method-names.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 40ff10d73063949ca699670ca212e96b809d5fcd Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 16 Mar 2017 11:37:41 +0100 -Subject: [PATCH 103/135] sss_sifp: update method names -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to https://pagure.io/SSSD/sssd/issue/3292 - -Reviewed-by: Pavel Březina ---- - Makefile.am | 2 +- - src/lib/sifp/sss_sifp_common.c | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 7aca5b86f1275e89ae73f5594887f515773c2058..6f143000c2459d25f18b013b155248c9ddf93120 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1221,7 +1221,7 @@ libsss_simpleifp_la_LIBADD = \ - $(DHASH_LIBS) - libsss_simpleifp_la_LDFLAGS = \ - -Wl,--version-script,$(srcdir)/src/lib/sifp/sss_simpleifp.exports \ -- -version-info 1:0:1 -+ -version-info 1:1:1 - - dist_noinst_DATA += src/lib/sifp/sss_simpleifp.exports - -diff --git a/src/lib/sifp/sss_sifp_common.c b/src/lib/sifp/sss_sifp_common.c -index bd1dc6a3108329d2c795dc0a259637e71964be9f..8913d0be3d43bd8707829001a5b476d9ab864fd8 100644 ---- a/src/lib/sifp/sss_sifp_common.c -+++ b/src/lib/sifp/sss_sifp_common.c -@@ -168,7 +168,7 @@ sss_sifp_fetch_user_by_uid(sss_sifp_ctx *ctx, - uint64_t _uid = uid; - - return sss_sifp_fetch_object_by_attr(ctx, IFP_PATH_USERS, IFACE_IFP_USERS, -- IFACE_IFP_USERS_USER, "UserByID", -+ IFACE_IFP_USERS_USER, "ByID", - DBUS_TYPE_UINT64, &_uid, _user); - } - -@@ -178,6 +178,6 @@ sss_sifp_fetch_user_by_name(sss_sifp_ctx *ctx, - sss_sifp_object **_user) - { - return sss_sifp_fetch_object_by_name(ctx, IFP_PATH_USERS, IFACE_IFP_USERS, -- IFACE_IFP_USERS_USER, "UserByName", -+ IFACE_IFP_USERS_USER, "ByName", - name, _user); - } --- -2.12.2 - diff --git a/0104-pam_test_client-add-InfoPipe-user-lookup.patch b/0104-pam_test_client-add-InfoPipe-user-lookup.patch deleted file mode 100644 index 6c69b3e..0000000 --- a/0104-pam_test_client-add-InfoPipe-user-lookup.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 9be97c9cc69e5e6e568d7e21f61a46c3ae2dc387 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 16 Mar 2017 11:38:20 +0100 -Subject: [PATCH 104/135] pam_test_client: add InfoPipe user lookup -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to https://pagure.io/SSSD/sssd/issue/3292 - -Reviewed-by: Pavel Březina ---- - Makefile.am | 1 + - src/sss_client/pam_test_client.c | 71 ++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 72 insertions(+) - -diff --git a/Makefile.am b/Makefile.am -index 6f143000c2459d25f18b013b155248c9ddf93120..05a5ae89cbe5dccf39ce9bdfd95c1b115a64c768 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -3468,6 +3468,7 @@ pam_test_client_LDADD = \ - $(PAM_LIBS) \ - $(PAM_MISC_LIBS) \ - $(LIBADD_DL) \ -+ libsss_simpleifp.la \ - $(NULL) - - if BUILD_AUTOFS -diff --git a/src/sss_client/pam_test_client.c b/src/sss_client/pam_test_client.c -index 69af612270492968b56d1c11de2bf56ebf57471f..40ef3f6d480c0108c985fce7e34e983d145f237e 100644 ---- a/src/sss_client/pam_test_client.c -+++ b/src/sss_client/pam_test_client.c -@@ -30,9 +30,12 @@ - #include - #include - #include -+#include - - #include - -+#include "lib/sifp/sss_sifp.h" -+ - #ifdef HAVE_SECURITY_PAM_MISC_H - # include - #elif defined(HAVE_SECURITY_OPENPAM_H) -@@ -58,6 +61,69 @@ static struct pam_conv conv = { - - #define DEFAULT_BUFSIZE 4096 - -+static int get_ifp_user(const char *user) -+{ -+ sss_sifp_ctx *sifp; -+ sss_sifp_error error; -+ sss_sifp_object *user_obj; -+ const char *tmp_str; -+ uint32_t tmp_uint32; -+ size_t c; -+ -+ struct ifp_user_attr { -+ const char *name; -+ bool is_string; -+ } ifp_user_attr[] = { -+ { "name", true }, -+ { "uidNumber", false }, -+ { "gidNumber", false }, -+ { "gecos", true }, -+ { "homeDirectory", true }, -+ { "loginShell", true }, -+ { NULL, false } -+ }; -+ -+ error = sss_sifp_init(&sifp); -+ if (error != SSS_SIFP_OK) { -+ fprintf(stderr, "Unable to connect to the InfoPipe"); -+ return EFAULT; -+ } -+ -+ error = sss_sifp_fetch_user_by_name(sifp, user, &user_obj); -+ if (error != SSS_SIFP_OK) { -+ fprintf(stderr, "Unable to get user object"); -+ return EIO; -+ } -+ -+ fprintf(stdout, "SSSD InfoPipe user lookup result:\n"); -+ for (c = 0; ifp_user_attr[c].name != NULL; c++) { -+ if (ifp_user_attr[c].is_string) { -+ error = sss_sifp_find_attr_as_string(user_obj->attrs, -+ ifp_user_attr[c].name, -+ &tmp_str); -+ } else { -+ error = sss_sifp_find_attr_as_uint32(user_obj->attrs, -+ ifp_user_attr[c].name, -+ &tmp_uint32); -+ } -+ if (error != SSS_SIFP_OK) { -+ fprintf(stderr, "Unable to get user name attr"); -+ return EIO; -+ } -+ -+ if (ifp_user_attr[c].is_string) { -+ fprintf(stdout, " - %s: %s\n", ifp_user_attr[c].name, tmp_str); -+ } else { -+ fprintf(stdout, " - %s: %"PRIu32"\n", ifp_user_attr[c].name, -+ tmp_uint32); -+ } -+ } -+ -+ sss_sifp_free_object(sifp, &user_obj); -+ sss_sifp_free(&sifp); -+ return 0; -+} -+ - static int sss_getpwnam_check(const char *user) - { - void *dl_handle = NULL; -@@ -159,6 +225,11 @@ int main(int argc, char *argv[]) { - if (ret != 0) { - fprintf(stderr, "User name lookup with [%s] failed.\n", user); - } -+ -+ ret = get_ifp_user(user); -+ if (ret != 0) { -+ fprintf(stderr, "InforPipe User lookup with [%s] failed.\n", user); -+ } - } - - ret = pam_start(service, user, &conv, &pamh); --- -2.12.2 - diff --git a/0105-sssctl-integrate-pam_test_client-into-sssctl.patch b/0105-sssctl-integrate-pam_test_client-into-sssctl.patch deleted file mode 100644 index 36063fa..0000000 --- a/0105-sssctl-integrate-pam_test_client-into-sssctl.patch +++ /dev/null @@ -1,358 +0,0 @@ -From 4a9160e2b3b9c531e2b4a7884f49bfbb4a07a992 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 30 Mar 2017 16:21:15 +0200 -Subject: [PATCH 105/135] sssctl: integrate pam_test_client into sssctl -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina ---- - Makefile.am | 16 +-- - po/POTFILES.in | 1 - - src/tools/sssctl/sssctl.c | 1 + - src/tools/sssctl/sssctl.h | 4 + - .../sssctl/sssctl_user_checks.c} | 122 +++++++++++---------- - 5 files changed, 72 insertions(+), 72 deletions(-) - rename src/{sss_client/pam_test_client.c => tools/sssctl/sssctl_user_checks.c} (62%) - -diff --git a/Makefile.am b/Makefile.am -index 05a5ae89cbe5dccf39ce9bdfd95c1b115a64c768..c947e31e5530c842d0d0024a5825ddd7b593d518 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1724,11 +1724,15 @@ sssctl_SOURCES = \ - src/tools/sssctl/sssctl_domains.c \ - src/tools/sssctl/sssctl_sifp.c \ - src/tools/sssctl/sssctl_config.c \ -+ src/tools/sssctl/sssctl_user_checks.c \ - $(SSSD_TOOLS_OBJ) \ - $(NULL) - sssctl_LDADD = \ - $(TOOLS_LIBS) \ - $(SSSD_INTERNAL_LTLIBS) \ -+ $(PAM_LIBS) \ -+ $(PAM_MISC_LIBS) \ -+ $(LIBADD_DL) \ - libsss_simpleifp.la \ - $(NULL) - sssctl_CFLAGS = \ -@@ -3450,7 +3454,7 @@ endif # BUILD_KCM - - endif # HAVE_CMOCKA - --noinst_PROGRAMS = pam_test_client -+noinst_PROGRAMS = - if BUILD_SUDO - noinst_PROGRAMS += sss_sudo_cli - endif -@@ -3461,16 +3465,6 @@ if BUILD_WITH_LIBCURL - noinst_PROGRAMS += tcurl-test-tool - endif - --pam_test_client_SOURCES = \ -- src/sss_client/pam_test_client.c \ -- $(NULL) --pam_test_client_LDADD = \ -- $(PAM_LIBS) \ -- $(PAM_MISC_LIBS) \ -- $(LIBADD_DL) \ -- libsss_simpleifp.la \ -- $(NULL) -- - if BUILD_AUTOFS - autofs_test_client_SOURCES = \ - src/sss_client/autofs/autofs_test_client.c \ -diff --git a/po/POTFILES.in b/po/POTFILES.in -index ee532def223fdd5db632ad98fd11a57e38d0e125..f4e4e095f9e4025d129b6b13422bdd0bc07c8e1a 100644 ---- a/po/POTFILES.in -+++ b/po/POTFILES.in -@@ -9,7 +9,6 @@ src/sss_client/common.c - src/sss_client/nss_group.c - src/sss_client/nss_passwd.c - src/sss_client/pam_sss.c --src/sss_client/pam_test_client.c - src/sss_client/ssh/sss_ssh_authorizedkeys.c - src/sss_client/ssh/sss_ssh_knownhostsproxy.c - src/tools/sss_useradd.c -diff --git a/src/tools/sssctl/sssctl.c b/src/tools/sssctl/sssctl.c -index e1cf46382cd1dee54cd372ca500368f149411b78..509d2e1a00d3b57b541590ce7db5f94d2ff43add 100644 ---- a/src/tools/sssctl/sssctl.c -+++ b/src/tools/sssctl/sssctl.c -@@ -263,6 +263,7 @@ int main(int argc, const char **argv) - SSS_TOOL_DELIMITER("SSSD Status:"), - SSS_TOOL_COMMAND("domain-list", "List available domains", 0, sssctl_domain_list), - SSS_TOOL_COMMAND("domain-status", "Print information about domain", 0, sssctl_domain_status), -+ SSS_TOOL_COMMAND("user-checks", "Print information about a user and check authentication", 0, sssctl_user_checks), - SSS_TOOL_DELIMITER("Information about cached content:"), - SSS_TOOL_COMMAND("user-show", "Information about cached user", 0, sssctl_user_show), - SSS_TOOL_COMMAND("group-show", "Information about cached group", 0, sssctl_group_show), -diff --git a/src/tools/sssctl/sssctl.h b/src/tools/sssctl/sssctl.h -index 5270a9ec62dfb288511af179a99e9a542ea26ec4..22626e2210252e5e3fadeb6c5d01d4620cd60e5b 100644 ---- a/src/tools/sssctl/sssctl.h -+++ b/src/tools/sssctl/sssctl.h -@@ -121,4 +121,8 @@ errno_t sssctl_netgroup_show(struct sss_cmdline *cmdline, - errno_t sssctl_config_check(struct sss_cmdline *cmdline, - struct sss_tool_ctx *tool_ctx, - void *pvt); -+ -+errno_t sssctl_user_checks(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt); - #endif /* _SSSCTL_H_ */ -diff --git a/src/sss_client/pam_test_client.c b/src/tools/sssctl/sssctl_user_checks.c -similarity index 62% -rename from src/sss_client/pam_test_client.c -rename to src/tools/sssctl/sssctl_user_checks.c -index 40ef3f6d480c0108c985fce7e34e983d145f237e..7c7b564bd29100382c9bbef7a3131c379e9aa97e 100644 ---- a/src/sss_client/pam_test_client.c -+++ b/src/tools/sssctl/sssctl_user_checks.c -@@ -35,6 +35,9 @@ - #include - - #include "lib/sifp/sss_sifp.h" -+#include "util/util.h" -+#include "tools/common/sss_tools.h" -+#include "tools/sssctl/sssctl.h" - - #ifdef HAVE_SECURITY_PAM_MISC_H - # include -@@ -85,17 +88,17 @@ static int get_ifp_user(const char *user) - - error = sss_sifp_init(&sifp); - if (error != SSS_SIFP_OK) { -- fprintf(stderr, "Unable to connect to the InfoPipe"); -+ fprintf(stderr, _("Unable to connect to the InfoPipe")); - return EFAULT; - } - - error = sss_sifp_fetch_user_by_name(sifp, user, &user_obj); - if (error != SSS_SIFP_OK) { -- fprintf(stderr, "Unable to get user object"); -+ fprintf(stderr, _("Unable to get user object")); - return EIO; - } - -- fprintf(stdout, "SSSD InfoPipe user lookup result:\n"); -+ fprintf(stdout, _("SSSD InfoPipe user lookup result:\n")); - for (c = 0; ifp_user_attr[c].name != NULL; c++) { - if (ifp_user_attr[c].is_string) { - error = sss_sifp_find_attr_as_string(user_obj->attrs, -@@ -107,7 +110,7 @@ static int get_ifp_user(const char *user) - &tmp_uint32); - } - if (error != SSS_SIFP_OK) { -- fprintf(stderr, "Unable to get user name attr"); -+ fprintf(stderr, _("Unable to get user name attr")); - return EIO; - } - -@@ -118,6 +121,7 @@ static int get_ifp_user(const char *user) - tmp_uint32); - } - } -+ fprintf(stdout, "\n"); - - sss_sifp_free_object(sifp, &user_obj); - sss_sifp_free(&sifp); -@@ -139,14 +143,14 @@ static int sss_getpwnam_check(const char *user) - - dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW); - if (dl_handle == NULL) { -- fprintf(stderr, "dlopen failed with [%s].\n", dlerror()); -+ fprintf(stderr, _("dlopen failed with [%s].\n"), dlerror()); - ret = EIO; - goto done; - } - - sss_getpwnam_r = dlsym(dl_handle, "_nss_sss_getpwnam_r"); - if (sss_getpwnam_r == NULL) { -- fprintf(stderr, "dlsym failed with [%s].\n", dlerror()); -+ fprintf(stderr, _("dlsym failed with [%s].\n"), dlerror()); - ret = EIO; - goto done; - } -@@ -154,25 +158,25 @@ static int sss_getpwnam_check(const char *user) - buflen = DEFAULT_BUFSIZE; - buffer = malloc(buflen); - if (buffer == NULL) { -- fprintf(stderr, "malloc failed.\n"); -+ fprintf(stderr, _("malloc failed.\n")); - ret = ENOMEM; - goto done; - } - - status = sss_getpwnam_r(user, &pwd, buffer, buflen, &nss_errno); - if (status != NSS_STATUS_SUCCESS) { -- fprintf(stderr, "sss_getpwnam_r failed with [%d].\n", status); -+ fprintf(stderr, _("sss_getpwnam_r failed with [%d].\n"), status); - ret = EIO; - goto done; - } - -- fprintf(stdout, "SSSD nss user lookup result:\n"); -- fprintf(stdout, " - user name: %s\n", pwd.pw_name); -- fprintf(stdout, " - user id: %d\n", pwd.pw_uid); -- fprintf(stdout, " - group id: %d\n", pwd.pw_gid); -- fprintf(stdout, " - gecos: %s\n", pwd.pw_gecos); -- fprintf(stdout, " - home directory: %s\n", pwd.pw_dir); -- fprintf(stdout, " - shell: %s\n", pwd.pw_shell); -+ fprintf(stdout, _("SSSD nss user lookup result:\n")); -+ fprintf(stdout, _(" - user name: %s\n"), pwd.pw_name); -+ fprintf(stdout, _(" - user id: %d\n"), pwd.pw_uid); -+ fprintf(stdout, _(" - group id: %d\n"), pwd.pw_gid); -+ fprintf(stdout, _(" - gecos: %s\n"), pwd.pw_gecos); -+ fprintf(stdout, _(" - home directory: %s\n"), pwd.pw_dir); -+ fprintf(stdout, _(" - shell: %s\n\n"), pwd.pw_shell); - - ret = 0; - -@@ -186,87 +190,89 @@ done: - return ret; - } - --int main(int argc, char *argv[]) { -+errno_t sssctl_user_checks(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ - - pam_handle_t *pamh; -- char *user; -- char *action; -- char *service; -+ const char *user = NULL; -+ const char *action = DEFAULT_ACTION; -+ const char *service = DEFAULT_SERVICE; - int ret; - size_t c; - char **pam_env; - -- if (argc == 1) { -- fprintf(stderr, "Usage: pam_test_client USERNAME " -- "[auth|acct|setc|chau|open|clos] [pam_service]\n"); -- return 0; -- } else if (argc == 2) { -- fprintf(stderr, "using first argument as user name and default action " -- "and service\n"); -- } else if (argc == 3) { -- fprintf(stderr, "using first argument as user name, second as action " -- "and default service\n"); -- } -- -- user = strdup(argv[1]); -- action = argc > 2 ? strdup(argv[2]) : strdup(DEFAULT_ACTION); -- service = argc > 3 ? strdup(argv[3]) : strdup(DEFAULT_SERVICE); -+ /* Parse command line. */ -+ struct poptOption options[] = { -+ { "action", 'a', POPT_ARG_STRING, &action, 0, -+ _("PAM action [auth|acct|setc|chau|open|clos], default: " -+ DEFAULT_ACTION), NULL }, -+ { "service", 's', POPT_ARG_STRING, &service, 0, -+ _("PAM service, default: " DEFAULT_SERVICE), NULL }, -+ POPT_TABLEEND -+ }; - -- if (action == NULL || user == NULL || service == NULL) { -- fprintf(stderr, "Out of memory!\n"); -- return 1; -+ ret = sss_tool_popt_ex(cmdline, options, SSS_TOOL_OPT_OPTIONAL, -+ NULL, NULL, "USERNAME", _("Specify user name."), -+ &user, NULL); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); -+ return ret; - } - -- fprintf(stdout, "user: %s\naction: %s\nservice: %s\n", -+ fprintf(stdout, _("user: %s\naction: %s\nservice: %s\n\n"), - user, action, service); - - if (*user != '\0') { - ret = sss_getpwnam_check(user); - if (ret != 0) { -- fprintf(stderr, "User name lookup with [%s] failed.\n", user); -+ fprintf(stderr, _("User name lookup with [%s] failed.\n"), user); - } - - ret = get_ifp_user(user); - if (ret != 0) { -- fprintf(stderr, "InforPipe User lookup with [%s] failed.\n", user); -+ fprintf(stderr, _("InforPipe User lookup with [%s] failed.\n"), -+ user); - } - } - - ret = pam_start(service, user, &conv, &pamh); - if (ret != PAM_SUCCESS) { -- fprintf(stderr, "pam_start failed: %s\n", pam_strerror(pamh, ret)); -+ fprintf(stderr, _("pam_start failed: %s\n"), pam_strerror(pamh, ret)); - return 1; - } - - if ( strncmp(action, "auth", 4)== 0 ) { -- fprintf(stdout, "testing pam_authenticate\n"); -+ fprintf(stdout, _("testing pam_authenticate\n\n")); - ret = pam_authenticate(pamh, 0); -- fprintf(stderr, "pam_authenticate: %s\n", pam_strerror(pamh, ret)); -+ fprintf(stderr, _("pam_authenticate: %s\n\n"), pam_strerror(pamh, ret)); - } else if ( strncmp(action, "chau", 4)== 0 ) { -- fprintf(stdout, "testing pam_chauthtok\n"); -+ fprintf(stdout, _("testing pam_chauthtok\n\n")); - ret = pam_chauthtok(pamh, 0); -- fprintf(stderr, "pam_chauthtok: %s\n", pam_strerror(pamh, ret)); -+ fprintf(stderr, _("pam_chauthtok: %s\n\n"), pam_strerror(pamh, ret)); - } else if ( strncmp(action, "acct", 4)== 0 ) { -- fprintf(stdout, "testing pam_acct_mgmt\n"); -+ fprintf(stdout, _("testing pam_acct_mgmt\n\n")); - ret = pam_acct_mgmt(pamh, 0); -- fprintf(stderr, "pam_acct_mgmt: %s\n", pam_strerror(pamh, ret)); -+ fprintf(stderr, _("pam_acct_mgmt: %s\n\n"), pam_strerror(pamh, ret)); - } else if ( strncmp(action, "setc", 4)== 0 ) { -- fprintf(stdout, "testing pam_setcred\n"); -+ fprintf(stdout, _("testing pam_setcred\n\n")); - ret = pam_setcred(pamh, 0); -- fprintf(stderr, "pam_setcred: %d[%s]\n", ret, pam_strerror(pamh, ret)); -+ fprintf(stderr, _("pam_setcred: [%s]\n\n"), pam_strerror(pamh, ret)); - } else if ( strncmp(action, "open", 4)== 0 ) { -- fprintf(stdout, "testing pam_open_session\n"); -+ fprintf(stdout, _("testing pam_open_session\n\n")); - ret = pam_open_session(pamh, 0); -- fprintf(stderr, "pam_open_session: %s\n", pam_strerror(pamh, ret)); -+ fprintf(stderr, _("pam_open_session: %s\n\n"), pam_strerror(pamh, ret)); - } else if ( strncmp(action, "clos", 4)== 0 ) { -- fprintf(stdout, "testing pam_close_session\n"); -+ fprintf(stdout, _("testing pam_close_session\n\n")); - ret = pam_close_session(pamh, 0); -- fprintf(stderr, "pam_close_session: %s\n", pam_strerror(pamh, ret)); -+ fprintf(stderr, _("pam_close_session: %s\n\n"), -+ pam_strerror(pamh, ret)); - } else { -- fprintf(stderr, "unknown action\n"); -+ fprintf(stderr, _("unknown action\n")); - } - -- fprintf(stderr, "PAM Environment:\n"); -+ fprintf(stderr, _("PAM Environment:\n")); - pam_env = pam_getenvlist(pamh); - if (pam_env != NULL && pam_env[0] != NULL) { - for (c = 0; pam_env[c] != NULL; c++) { -@@ -274,15 +280,11 @@ int main(int argc, char *argv[]) { - free(pam_env[c]); - } - } else { -- fprintf(stderr, " - no env -\n"); -+ fprintf(stderr, _(" - no env -\n")); - } - free(pam_env); - - pam_end(pamh, ret); - -- free(user); -- free(action); -- free(service); -- - return 0; - } --- -2.12.2 - diff --git a/0106-i18n-adding-sssctl-files.patch b/0106-i18n-adding-sssctl-files.patch deleted file mode 100644 index 6a4be02..0000000 --- a/0106-i18n-adding-sssctl-files.patch +++ /dev/null @@ -1,33 +0,0 @@ -From dbeae483464e42238a84c6a5b8c3c4f5312ae643 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 7 Apr 2017 14:24:10 +0200 -Subject: [PATCH 106/135] i18n: adding sssctl files -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina ---- - po/POTFILES.in | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/po/POTFILES.in b/po/POTFILES.in -index f4e4e095f9e4025d129b6b13422bdd0bc07c8e1a..33e7ed7f9e9bc19f33fca8a1f2649b69b79a882f 100644 ---- a/po/POTFILES.in -+++ b/po/POTFILES.in -@@ -23,4 +23,12 @@ src/tools/sss_cache.c - src/tools/sss_debuglevel.c - src/tools/tools_util.c - src/tools/tools_util.h -+src/tools/sssctl/sssctl.c -+src/tools/sssctl/sssctl_cache.c -+src/tools/sssctl/sssctl_config.c -+src/tools/sssctl/sssctl_data.c -+src/tools/sssctl/sssctl_domains.c -+src/tools/sssctl/sssctl_logs.c -+src/tools/sssctl/sssctl_sifp.c -+src/tools/sssctl/sssctl_user_checks.c - src/util/util.h --- -2.12.2 - diff --git a/0107-config-check-Message-when-sssd.conf-is-missing.patch b/0107-config-check-Message-when-sssd.conf-is-missing.patch deleted file mode 100644 index 9d992e9..0000000 --- a/0107-config-check-Message-when-sssd.conf-is-missing.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 955574eeb3a3b937abc3df150e9bbbb79b75c889 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20=C5=BDidek?= -Date: Tue, 14 Mar 2017 15:43:41 +0100 -Subject: [PATCH 107/135] config-check: Message when sssd.conf is missing -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -sssctl config-check should print a message for user -if no sssd.conf was found. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3330 - -Reviewed-by: Lukáš Slebodník ---- - src/tools/sssctl/sssctl_config.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/tools/sssctl/sssctl_config.c b/src/tools/sssctl/sssctl_config.c -index 630df3c8ff5368ef253bb9753380e94c8c0a307d..7e3ebf5428ce3fef232eee7334c7fd90e904b2d3 100644 ---- a/src/tools/sssctl/sssctl_config.c -+++ b/src/tools/sssctl/sssctl_config.c -@@ -63,7 +63,10 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline, - - /* Open config file */ - ret = sss_ini_config_file_open(init_data, SSSD_CONFIG_FILE); -- if (ret != EOK) { -+ if (ret == ENOENT) { -+ ERROR("File %1$s does not exist.\n", SSSD_CONFIG_FILE); -+ goto done; -+ } else if (ret != EOK) { - DEBUG(SSSDBG_TRACE_FUNC, - "sss_ini_config_file_open failed: %s [%d]\n", - sss_strerror(ret), --- -2.12.2 - diff --git a/0108-KRB5_LOCATOR-add-env-variable-to-disable-plugin.patch b/0108-KRB5_LOCATOR-add-env-variable-to-disable-plugin.patch deleted file mode 100644 index ceddb75..0000000 --- a/0108-KRB5_LOCATOR-add-env-variable-to-disable-plugin.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 1193f20a8267e506d863b27c74870c86c085902b Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 17 Nov 2016 10:55:43 +0100 -Subject: [PATCH 108/135] KRB5_LOCATOR: add env variable to disable plugin -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If the new environment variable SSSD_KRB5_LOCATOR_DISABLE is set to any -value SSSD's krb5 locator plugin is disabled. The variable is needed -because there is currently no other way than removing the plugin -completely to disable it. For a use-case see e.g. -https://bugzilla.redhat.com/show_bug.cgi?id=1072939. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3359 - -Reviewed-by: Lukáš Slebodník ---- - src/krb5_plugin/sssd_krb5_locator_plugin.c | 15 +++++++++++++++ - src/man/sssd_krb5_locator_plugin.8.xml | 5 +++++ - 2 files changed, 20 insertions(+) - -diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c -index aa8d387a5d0be302e5cc98ddcf10ebce6957f3a5..7c17fcb33373293fbbbe2be967dca57b31ef13de 100644 ---- a/src/krb5_plugin/sssd_krb5_locator_plugin.c -+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c -@@ -45,6 +45,7 @@ - #define BUFSIZE 512 - #define PORT_STR_SIZE 7 - #define SSSD_KRB5_LOCATOR_DEBUG "SSSD_KRB5_LOCATOR_DEBUG" -+#define SSSD_KRB5_LOCATOR_DISABLE "SSSD_KRB5_LOCATOR_DISABLE" - #define DEBUG_KEY "[sssd_krb5_locator] " - #define PLUGIN_DEBUG(body) do { \ - if (ctx->debug) { \ -@@ -59,6 +60,7 @@ struct sssd_ctx { - char *kpasswd_addr; - uint16_t kpasswd_port; - bool debug; -+ bool disabled; - }; - - void plugin_debug_fn(const char *format, ...) -@@ -232,6 +234,14 @@ krb5_error_code sssd_krb5_locator_init(krb5_context context, - PLUGIN_DEBUG(("sssd_krb5_locator_init called\n")); - } - -+ dummy = getenv(SSSD_KRB5_LOCATOR_DISABLE); -+ if (dummy == NULL) { -+ ctx->disabled = false; -+ } else { -+ ctx->disabled = true; -+ PLUGIN_DEBUG(("SSSD KRB5 locator plugin is disabled.\n")); -+ } -+ - *private_data = ctx; - - return 0; -@@ -273,6 +283,11 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data, - if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE; - ctx = (struct sssd_ctx *) private_data; - -+ if (ctx->disabled) { -+ PLUGIN_DEBUG(("Plugin disabled, nothing to do.\n")); -+ return KRB5_PLUGIN_NO_HANDLE; -+ } -+ - if (ctx->sssd_realm == NULL || strcmp(ctx->sssd_realm, realm) != 0) { - free(ctx->sssd_realm); - ctx->sssd_realm = strdup(realm); -diff --git a/src/man/sssd_krb5_locator_plugin.8.xml b/src/man/sssd_krb5_locator_plugin.8.xml -index 25a20c88fcd4c2b3f644da24b34a4d5e9eb80ed3..d28546012802955c2594680e53698518f0178ab1 100644 ---- a/src/man/sssd_krb5_locator_plugin.8.xml -+++ b/src/man/sssd_krb5_locator_plugin.8.xml -@@ -69,6 +69,11 @@ - If the environment variable SSSD_KRB5_LOCATOR_DEBUG is set to any - value debug messages will be sent to stderr. - -+ -+ If the environment variable SSSD_KRB5_LOCATOR_DISABLE is set to any -+ value the plugin is disabled and will just return -+ KRB5_PLUGIN_NO_HANDLE to the caller. -+ - - - --- -2.12.2 - diff --git a/0109-sbus-check-connection-for-NULL-before-unregister-it.patch b/0109-sbus-check-connection-for-NULL-before-unregister-it.patch deleted file mode 100644 index 2f6e728..0000000 --- a/0109-sbus-check-connection-for-NULL-before-unregister-it.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 35186217d44d0138a1aedf7a4db72249b2c40e66 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 10 Apr 2017 13:45:27 +0200 -Subject: [PATCH 109/135] sbus: check connection for NULL before unregister it -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There seem to be code paths where the data is a added to the hash before -the connection is properly initialized, to avoid core dump during shut -down we only call dbus_conection_unregister_object_path() if there is a -connection. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3367 - -Reviewed-by: Pavel Březina ---- - src/sbus/sssd_dbus_interface.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/sbus/sssd_dbus_interface.c b/src/sbus/sssd_dbus_interface.c -index 1a11c6abcf23053e3b8c77f4d469d7c202a88eb8..c9007a4814e09e26fedaf605ca7313234d5ebf2c 100644 ---- a/src/sbus/sssd_dbus_interface.c -+++ b/src/sbus/sssd_dbus_interface.c -@@ -490,7 +490,13 @@ sbus_opath_hash_delete_cb(hash_entry_t *item, - conn = talloc_get_type(pvt, struct sbus_connection); - path = sbus_opath_get_base_path(NULL, item->key.str); - -- dbus_connection_unregister_object_path(conn->dbus.conn, path); -+ /* There seem to be code paths where the data is added to the hash -+ * before the connection is properly initialized, to avoid core dump -+ * during shut down we only call dbus_connection_unregister_object_path() -+ * if there is a connection. */ -+ if (conn->dbus.conn != NULL) { -+ dbus_connection_unregister_object_path(conn->dbus.conn, path); -+ } - } - - hash_table_t * --- -2.12.2 - diff --git a/0110-UTIL-Use-max-15-characters-for-AD-host-UPN.patch b/0110-UTIL-Use-max-15-characters-for-AD-host-UPN.patch deleted file mode 100644 index 29f1a1f..0000000 --- a/0110-UTIL-Use-max-15-characters-for-AD-host-UPN.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c6f1bc32774a7cf2f8678499dfbced420be3a3a1 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 14 Mar 2017 10:34:00 +0100 -Subject: [PATCH 110/135] UTIL: Use max 15 characters for AD host UPN -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We do not want to use host principal with AD -"host/name.domain.tld@DOMAIN.TLD" because it does not work. -We need to use correct user principal for AD hosts. And we cannot -rely all fallback "*$" because of other principals in keytab. - -The NetBIOS naming convention allows for 16 characters in a NetBIOS -name. Microsoft, however, limits NetBIOS names to 15 characters and -uses the 16th character as a NetBIOS suffix. -https://support.microsoft.com/en-us/help/163409/netbios-suffixes-16th-character-of-the-netbios-name - -Resolves: -https://pagure.io/SSSD/sssd/issue/3329 - -Reviewed-by: Michal Židek ---- - src/util/sss_krb5.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c -index d461cf881566af37f31524c16f6a5f1511a5dc89..a3f066e8add5b7d7575c1e0f537c5729e4a0dad0 100644 ---- a/src/util/sss_krb5.c -+++ b/src/util/sss_krb5.c -@@ -51,7 +51,13 @@ sss_krb5_get_primary(TALLOC_CTX *mem_ctx, - *c = toupper(*c); - } - -- primary = talloc_asprintf(mem_ctx, "%s$", shortname); -+ /* The samAccountName is recommended to be less than 20 characters. -+ * This is only for users and groups. For machine accounts, -+ * the real limit is caused by NetBIOS protocol. -+ * NetBIOS names are limited to 16 (15 + $) -+ * https://support.microsoft.com/en-us/help/163409/netbios-suffixes-16th-character-of-the-netbios-name -+ */ -+ primary = talloc_asprintf(mem_ctx, "%.15s$", shortname); - talloc_free(shortname); - return primary; - } --- -2.12.2 - diff --git a/0111-minor-typo-fixes.patch b/0111-minor-typo-fixes.patch deleted file mode 100644 index 08958fd..0000000 --- a/0111-minor-typo-fixes.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0a86dede8773ecce91b5bd2ae75a02f9ff89a358 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ren=C3=A9=20Genz?= -Date: Wed, 19 Apr 2017 08:36:12 +0000 -Subject: [PATCH 111/135] minor typo fixes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Merges: https://pagure.io/SSSD/sssd/pull-request/3374 - -Reviewed-by: Lukáš Slebodník -Reviewed-by: Justin Stephenson ---- - src/man/idmap_sss.8.xml | 2 +- - src/man/sssd-kcm.8.xml | 2 +- - src/man/sssd-ldap.5.xml | 8 ++++---- - src/man/sssd.conf.5.xml | 18 +++++++++--------- - src/tests/intg/test_files_provider.py | 2 +- - 5 files changed, 16 insertions(+), 16 deletions(-) - -diff --git a/src/man/idmap_sss.8.xml b/src/man/idmap_sss.8.xml -index 4c26a17f958fbf7251ad64de916db9de02c48364..0b73966e5952705a0f340ac169775c30153c392d 100644 ---- a/src/man/idmap_sss.8.xml -+++ b/src/man/idmap_sss.8.xml -@@ -32,7 +32,7 @@ - - range = low - high - -- Defines the available matching uid and gid range for which the -+ Defines the available matching UID and GID range for which the - backend is authoritative. - - -diff --git a/src/man/sssd-kcm.8.xml b/src/man/sssd-kcm.8.xml -index 5dc93838e48723bdb470c0a9c8575bd17c7593e8..db50ed8b49294057da99b01655a4b158f2908dcb 100644 ---- a/src/man/sssd-kcm.8.xml -+++ b/src/man/sssd-kcm.8.xml -@@ -48,7 +48,7 @@ - - - -- since the process runs in userspace, it is subject to UID namespacing, ulike the kernel keyring -+ since the process runs in userspace, it is subject to UID namespacing, unlike the kernel keyring - - - -diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml -index fae669a8d0c1119b68e087bb16def7bd9a4464d3..739ae15c359da4e8dad9bc225ea60cff9dc96b91 100644 ---- a/src/man/sssd-ldap.5.xml -+++ b/src/man/sssd-ldap.5.xml -@@ -965,7 +965,7 @@ - domains. - - -- Default: groupType in the AD provider, othewise not -+ Default: groupType in the AD provider, otherwise not - set - - -@@ -1591,7 +1591,7 @@ - - - -- ldap_min_id, ldap_max_id (interger) -+ ldap_min_id, ldap_max_id (integer) - - - In contrast to the SID based ID mapping which is -@@ -1939,7 +1939,7 @@ ldap_access_filter = (employeeType=admin) - was granted access permission. If they were - granted access during their last login, they will - continue to be granted access while offline and -- vice-versa. -+ vice versa. - - - Default: Empty -@@ -2633,7 +2633,7 @@ ldap_access_filter = (employeeType=admin) - If the option ldap_use_tokengroups is - enabled. The searches against Active Directory will - not be restricted and return all groups memberships, -- even with no gid mapping. It is recommended to disable -+ even with no GID mapping. It is recommended to disable - this feature, if group names are not being displayed - correctly. - -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index c4e30396f16c40db37af2f56ac218b6e37201ef7..c71287029f132906e4f17ff6618d5234a27617f1 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -246,7 +246,7 @@ - information. SSSD can use more domains - at the same time, but at least one - must be configured or SSSD won't start. -- This parameter described the list of domains -+ This parameter describes the list of domains - in the order you want them to be queried. - A domain name should only consist of alphanumeric - ASCII characters, dashes, dots and underscores. -@@ -264,7 +264,7 @@ - - Each domain can have an individual regular - expression configured. For some ID providers -- there are also default regular expressions. See -+ there are also default regular expressions. See - DOMAIN SECTIONS for more info on these regular - expressions. - -@@ -490,7 +490,7 @@ - The nickname of the cert to trust - (expected) to sign the OCSP responses. - The certificate with the given nickname -- must be availble in the systems NSS -+ must be available in the systems NSS - database. - This option must be used together - with ocsp_default_responder. -@@ -1253,7 +1253,7 @@ fallback_homedir = /home/%u - - - Note: Please be aware that message is only -- printed for the SSH service unless pam_verbostiy -+ printed for the SSH service unless pam_verbosity - is set to 3 (show all messages and debug - information). - -@@ -1456,13 +1456,13 @@ pam_account_locked_message = Account locked, please contact help desk. - authentication to the PAC responder. The sub-domain provider - collects domain SID and ID ranges of the domain the client is - joined to and of remote trusted domains from the local domain -- controller. If the PAC is decoded and evaluated some of the -+ controller. If the PAC is decoded and evaluated some of the - following operations are done: - - If the remote user does not exist in the -- cache, it is created. The uid is determined with the help -- of the SID, trusted domains will have UPGs and the gid -- will have the same value as the uid. The home directory is -+ cache, it is created. The UID is determined with the help -+ of the SID, trusted domains will have UPGs and the GID -+ will have the same value as the UID. The home directory is - set based on the subdomain_homedir parameter. The shell will - be empty by default, i.e. the system defaults are used, but - can be overwritten with the default_shell parameter. -@@ -2110,7 +2110,7 @@ pam_account_locked_message = Account locked, please contact help desk. - - - ldap to change a password stored -- in a LDAP server. See -+ in a LDAP server. See - - sssd-ldap - 5 -diff --git a/src/tests/intg/test_files_provider.py b/src/tests/intg/test_files_provider.py -index 8748ac10b089087056b1b93950c8d890a190c8d0..eced3997cd061b155f68ec5b2d15552061ffe3e3 100644 ---- a/src/tests/intg/test_files_provider.py -+++ b/src/tests/intg/test_files_provider.py -@@ -433,7 +433,7 @@ def test_incomplete_user_fail(setup_pw_with_canary, files_domain_only): - Test resolving an incomplete user where the missing field is required - to be present in the user record and thus the user shouldn't resolve. - -- We cannot test uid and gid missing because nss_wrapper doesn't even -+ We cannot test UID and GID missing because nss_wrapper doesn't even - load the malformed passwd file, then. - """ - bad_incomplete_user_setup(setup_pw_with_canary, 'name') --- -2.12.2 - diff --git a/0112-SPEC-Drop-conditional-build-for-krb5_local_auth_plug.patch b/0112-SPEC-Drop-conditional-build-for-krb5_local_auth_plug.patch deleted file mode 100644 index 338a595..0000000 --- a/0112-SPEC-Drop-conditional-build-for-krb5_local_auth_plug.patch +++ /dev/null @@ -1,46 +0,0 @@ -From bf8f119774dc2eabc5b9bc9f348cd95063ab2199 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 15 Mar 2017 12:07:37 +0100 -Subject: [PATCH 112/135] SPEC: Drop conditional build for - krb5_local_auth_plugin - -It was mainly aimed for time when stable CentOS and -rhel nightly had different versions of krb5. - -Anyway, rhel7.0 and rhel <= 6.6 are already out of support - -Reviewed-by: Jakub Hrozek ---- - contrib/sssd.spec.in | 6 ------ - 1 file changed, 6 deletions(-) - -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 39a974edebba3dbcd7625d1729b4a7330eaa8a27..84400e03e3fa6ead6d6cac57b3843ef79ef9ee6b 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -97,10 +97,6 @@ - %global with_cifs_utils_plugin_option --disable-cifs-idmap-plugin - %endif - --%if (0%{?fedora} || (0%{?rhel} == 7 && 0%{?rhel7_minor} >= 1) || (0%{?rhel} == 6 && 0%{?rhel6_minor} >= 7)) -- %global with_krb5_localauth_plugin 1 --%endif -- - %if (0%{?fedora}) - %global with_python3 1 - %else -@@ -1046,11 +1042,9 @@ done - %dir %{_sysconfdir}/cifs-utils - %ghost %{_sysconfdir}/cifs-utils/idmap-plugin - %endif --%if (0%{?with_krb5_localauth_plugin} == 1) - %dir %{_libdir}/%{name} - %dir %{_libdir}/%{name}/modules - %{_libdir}/%{name}/modules/sssd_krb5_localauth_plugin.so --%endif - %{_mandir}/man8/pam_sss.8* - %{_mandir}/man8/sssd_krb5_locator_plugin.8* - --- -2.12.2 - diff --git a/0114-Move-sized_output_name-and-sized_domain_name-into-re.patch b/0114-Move-sized_output_name-and-sized_domain_name-into-re.patch deleted file mode 100644 index 3f2a3c7..0000000 --- a/0114-Move-sized_output_name-and-sized_domain_name-into-re.patch +++ /dev/null @@ -1,299 +0,0 @@ -From 7c074ba2f923985ab0d4f9d6a5e01ff3f2f0a7a8 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 19 Apr 2017 17:44:40 +0200 -Subject: [PATCH 114/135] Move sized_output_name() and sized_domain_name() into - responder common code -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -These functions are used to format a name into a format that the user -configured for output, including case sensitiveness, replacing -whitespace and qualified format. They were used only in the NSS -responder, which typically returns strings to the NSS client library and -then the user. - -But it makes sense to just reuse the same code in the IFP responder as -well, since it does essentially the same job. - -The patch also renames sized_member_name to sized_domain_name. -Previously, the function was only used to format a group member, the IFP -responder would use the same function to format a group the user is a -member of. - -Related to: - https://pagure.io/SSSD/sssd/issue/3268 - -Reviewed-by: Pavel Březina ---- - src/responder/common/responder.h | 21 ++++++++ - src/responder/common/responder_common.c | 90 +++++++++++++++++++++++++++++++++ - src/responder/nss/nss_private.h | 11 ---- - src/responder/nss/nss_protocol_grent.c | 2 +- - src/responder/nss/nss_utils.c | 87 ------------------------------- - 5 files changed, 112 insertions(+), 99 deletions(-) - -diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h -index 4210307489fe25829a1674f254ecc7d185029698..dfe1ec455e355de263c3550306e53fea3ada85df 100644 ---- a/src/responder/common/responder.h -+++ b/src/responder/common/responder.h -@@ -393,4 +393,25 @@ char *sss_resp_create_fqname(TALLOC_CTX *mem_ctx, - - errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx); - -+/** -+ * Helper functions to format output names -+ */ -+ -+/* Format orig_name into a sized_string in output format as prescribed -+ * by the name_dom domain -+ */ -+int sized_output_name(TALLOC_CTX *mem_ctx, -+ struct resp_ctx *rctx, -+ const char *orig_name, -+ struct sss_domain_info *name_dom, -+ struct sized_string **_name); -+ -+/* Format orig_name into a sized_string in output format as prescribed -+ * by the domain read from the fully qualified name. -+ */ -+int sized_domain_name(TALLOC_CTX *mem_ctx, -+ struct resp_ctx *rctx, -+ const char *member_name, -+ struct sized_string **_name); -+ - #endif /* __SSS_RESPONDER_H__ */ -diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c -index 67e1deefdfde19c95a68029b11099579d851513f..ac6320b08de09bc6c7e8dd1af72e0a493a449f7a 100644 ---- a/src/responder/common/responder_common.c -+++ b/src/responder/common/responder_common.c -@@ -1651,3 +1651,93 @@ done: - - return ret; - } -+ -+/** -+ * Helper functions to format output names -+ */ -+int sized_output_name(TALLOC_CTX *mem_ctx, -+ struct resp_ctx *rctx, -+ const char *orig_name, -+ struct sss_domain_info *name_dom, -+ struct sized_string **_name) -+{ -+ TALLOC_CTX *tmp_ctx = NULL; -+ errno_t ret; -+ char *username; -+ struct sized_string *name; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ username = sss_output_name(tmp_ctx, orig_name, name_dom->case_preserve, -+ rctx->override_space); -+ if (username == NULL) { -+ ret = EIO; -+ goto done; -+ } -+ -+ if (name_dom->fqnames) { -+ username = sss_tc_fqname(tmp_ctx, name_dom->names, name_dom, username); -+ if (username == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "sss_replace_space failed\n"); -+ ret = EIO; -+ goto done; -+ } -+ } -+ -+ name = talloc_zero(tmp_ctx, struct sized_string); -+ if (name == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ to_sized_string(name, username); -+ name->str = talloc_steal(name, username); -+ *_name = talloc_steal(mem_ctx, name); -+ ret = EOK; -+done: -+ talloc_zfree(tmp_ctx); -+ return ret; -+} -+ -+int sized_domain_name(TALLOC_CTX *mem_ctx, -+ struct resp_ctx *rctx, -+ const char *member_name, -+ struct sized_string **_name) -+{ -+ TALLOC_CTX *tmp_ctx = NULL; -+ errno_t ret; -+ char *domname; -+ struct sss_domain_info *member_dom; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = sss_parse_internal_fqname(tmp_ctx, member_name, NULL, &domname); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "sss_parse_internal_fqname failed\n"); -+ goto done; -+ } -+ -+ if (domname == NULL) { -+ ret = ERR_WRONG_NAME_FORMAT; -+ goto done; -+ } -+ -+ member_dom = find_domain_by_name(get_domains_head(rctx->domains), -+ domname, true); -+ if (member_dom == NULL) { -+ ret = ERR_DOMAIN_NOT_FOUND; -+ goto done; -+ } -+ -+ ret = sized_output_name(mem_ctx, rctx, member_name, -+ member_dom, _name); -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -diff --git a/src/responder/nss/nss_private.h b/src/responder/nss/nss_private.h -index acb3c4aa504e538ca56dca8d43ee04b0f60954a9..13de83226177bbaa8b8237e3e27b7e72da369194 100644 ---- a/src/responder/nss/nss_private.h -+++ b/src/responder/nss/nss_private.h -@@ -140,17 +140,6 @@ const char * - nss_get_name_from_msg(struct sss_domain_info *domain, - struct ldb_message *msg); - --int sized_output_name(TALLOC_CTX *mem_ctx, -- struct resp_ctx *rctx, -- const char *orig_name, -- struct sss_domain_info *name_dom, -- struct sized_string **_name); -- --int sized_member_name(TALLOC_CTX *mem_ctx, -- struct resp_ctx *rctx, -- const char *member_name, -- struct sized_string **_name); -- - const char * - nss_get_pwfield(struct nss_ctx *nctx, - struct sss_domain_info *dom); -diff --git a/src/responder/nss/nss_protocol_grent.c b/src/responder/nss/nss_protocol_grent.c -index 283ab9f6731bc4c8261ca79075ab030005bf70db..fae1d47d7b217beafba75740e2e6d9cb8cdbc1d0 100644 ---- a/src/responder/nss/nss_protocol_grent.c -+++ b/src/responder/nss/nss_protocol_grent.c -@@ -163,7 +163,7 @@ nss_protocol_fill_members(struct sss_packet *packet, - } - } - -- ret = sized_member_name(tmp_ctx, rctx, member_name, &name); -+ ret = sized_domain_name(tmp_ctx, rctx, member_name, &name); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unable to get sized name [%d]: %s\n", - ret, sss_strerror(ret)); -diff --git a/src/responder/nss/nss_utils.c b/src/responder/nss/nss_utils.c -index f839930a275db56e8d729888af870562d7b6f260..2cd9c33b42f7e018ea89d2df206637f35646489e 100644 ---- a/src/responder/nss/nss_utils.c -+++ b/src/responder/nss/nss_utils.c -@@ -53,93 +53,6 @@ nss_get_name_from_msg(struct sss_domain_info *domain, - return ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); - } - --int sized_output_name(TALLOC_CTX *mem_ctx, -- struct resp_ctx *rctx, -- const char *orig_name, -- struct sss_domain_info *name_dom, -- struct sized_string **_name) --{ -- TALLOC_CTX *tmp_ctx = NULL; -- errno_t ret; -- char *username; -- struct sized_string *name; -- -- tmp_ctx = talloc_new(NULL); -- if (tmp_ctx == NULL) { -- return ENOMEM; -- } -- -- username = sss_output_name(tmp_ctx, orig_name, name_dom->case_preserve, -- rctx->override_space); -- if (username == NULL) { -- ret = EIO; -- goto done; -- } -- -- if (name_dom->fqnames) { -- username = sss_tc_fqname(tmp_ctx, name_dom->names, name_dom, username); -- if (username == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "sss_replace_space failed\n"); -- ret = EIO; -- goto done; -- } -- } -- -- name = talloc_zero(tmp_ctx, struct sized_string); -- if (name == NULL) { -- ret = ENOMEM; -- goto done; -- } -- -- to_sized_string(name, username); -- name->str = talloc_steal(name, username); -- *_name = talloc_steal(mem_ctx, name); -- ret = EOK; --done: -- talloc_zfree(tmp_ctx); -- return ret; --} -- --int sized_member_name(TALLOC_CTX *mem_ctx, -- struct resp_ctx *rctx, -- const char *member_name, -- struct sized_string **_name) --{ -- TALLOC_CTX *tmp_ctx = NULL; -- errno_t ret; -- char *domname; -- struct sss_domain_info *member_dom; -- -- tmp_ctx = talloc_new(NULL); -- if (tmp_ctx == NULL) { -- return ENOMEM; -- } -- -- ret = sss_parse_internal_fqname(tmp_ctx, member_name, NULL, &domname); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "sss_parse_internal_fqname failed\n"); -- goto done; -- } -- -- if (domname == NULL) { -- ret = ERR_WRONG_NAME_FORMAT; -- goto done; -- } -- -- member_dom = find_domain_by_name(get_domains_head(rctx->domains), -- domname, true); -- if (member_dom == NULL) { -- ret = ERR_DOMAIN_NOT_FOUND; -- goto done; -- } -- -- ret = sized_output_name(mem_ctx, rctx, member_name, -- member_dom, _name); --done: -- talloc_free(tmp_ctx); -- return ret; --} -- - const char * - nss_get_pwfield(struct nss_ctx *nctx, - struct sss_domain_info *dom) --- -2.12.2 - diff --git a/0115-IFP-Use-sized_domain_name-to-format-the-groups-the-u.patch b/0115-IFP-Use-sized_domain_name-to-format-the-groups-the-u.patch deleted file mode 100644 index 2394f0b..0000000 --- a/0115-IFP-Use-sized_domain_name-to-format-the-groups-the-u.patch +++ /dev/null @@ -1,94 +0,0 @@ -From c9a73bb6ffa010ef206896a0d1c2801bc056fa45 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 19 Apr 2017 17:46:03 +0200 -Subject: [PATCH 115/135] IFP: Use sized_domain_name to format the groups the - user is a member of -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves: - https://pagure.io/SSSD/sssd/issue/3268 - -Uses the common function sized_domain_name() to format a group the user -is a member of to the appropriate format. - -To see the code is working correctly, run: - dbus-send --system --print-reply --dest=org.freedesktop.sssd.infopipe - /org/freedesktop/sssd/infopipe - org.freedesktop.sssd.infopipe.GetUserGroups - string:trusted_user - -Where trusted_user is a user from a trusted domain that is a member of groups -from the joined domain and a trusted domain as well. The groups from the -joined domain should not be qualified, the groups from the trusted -domain should be qualified. - -Reviewed-by: Pavel Březina ---- - src/responder/ifp/ifpsrv_cmd.c | 29 +++++++++++++++-------------- - 1 file changed, 15 insertions(+), 14 deletions(-) - -diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c -index d10f35e41dbb1623a0b9de37a4c43363cbefc1a3..e4d6c42ef35ef372472803d3d26b17d4181021a8 100644 ---- a/src/responder/ifp/ifpsrv_cmd.c -+++ b/src/responder/ifp/ifpsrv_cmd.c -@@ -369,10 +369,11 @@ ifp_user_get_groups_reply(struct sss_domain_info *domain, - struct ifp_req *ireq, - struct ldb_result *res) - { -- int i, num; -+ int i, gri, num; - const char *name; - const char **groupnames; -- char *out_name; -+ struct sized_string *group_name; -+ errno_t ret; - - /* one less, the first one is the user entry */ - num = res->count - 1; -@@ -381,6 +382,7 @@ ifp_user_get_groups_reply(struct sss_domain_info *domain, - return sbus_request_finish(ireq->dbus_req, NULL); - } - -+ gri = 0; - for (i = 0; i < num; i++) { - name = sss_view_ldb_msg_find_attr_as_string(domain, - res->msgs[i + 1], -@@ -390,22 +392,21 @@ ifp_user_get_groups_reply(struct sss_domain_info *domain, - continue; - } - -- out_name = sss_output_name(ireq, name, domain->case_preserve, -- ireq->ifp_ctx->rctx->override_space); -- if (out_name == NULL) { -+ ret = sized_domain_name(ireq, ireq->ifp_ctx->rctx, name, &group_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Unable to get sized name for %s [%d]: %s\n", -+ name, ret, sss_strerror(ret)); - continue; - } - -- if (domain->fqnames) { -- groupnames[i] = sss_tc_fqname(groupnames, domain->names, -- domain, out_name); -- if (out_name == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "sss_tc_fqname failed\n"); -- continue; -- } -- } else { -- groupnames[i] = talloc_steal(groupnames, out_name); -+ groupnames[gri] = talloc_strndup(groupnames, -+ group_name->str, group_name->len); -+ if (groupnames[gri] == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "talloc_strndup failed\n"); -+ continue; - } -+ gri++; - - DEBUG(SSSDBG_TRACE_FUNC, "Adding group %s\n", groupnames[i]); - } --- -2.12.2 - diff --git a/0116-SECRETS-remove-unused-variable.patch b/0116-SECRETS-remove-unused-variable.patch deleted file mode 100644 index 83d7d8d..0000000 --- a/0116-SECRETS-remove-unused-variable.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0e8f0c06cad5805b1a1161f60e3f2cdb7a5a2921 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 19 Apr 2017 17:56:20 +0200 -Subject: [PATCH 116/135] SECRETS: remove unused variable -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina ---- - src/responder/secrets/proxy.c | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/src/responder/secrets/proxy.c b/src/responder/secrets/proxy.c -index fd96e985c897e2cb470a9b5d6eecbd34350fb7d2..9c2aa425d414728d10aa830f640632e98def3c1c 100644 ---- a/src/responder/secrets/proxy.c -+++ b/src/responder/secrets/proxy.c -@@ -570,11 +570,6 @@ static void proxy_secret_req_done(struct tevent_req *subreq) - } - } - --struct provider_handle proxy_secrets_handle = { -- .fn = proxy_secret_req, -- .context = NULL, --}; -- - int proxy_secrets_provider_handle(struct sec_ctx *sctx, - struct provider_handle **out_handle) - { --- -2.12.2 - diff --git a/0117-IPA-Improve-DEBUG-message-if-a-group-has-no-ipaNTSec.patch b/0117-IPA-Improve-DEBUG-message-if-a-group-has-no-ipaNTSec.patch deleted file mode 100644 index 2d8edd5..0000000 --- a/0117-IPA-Improve-DEBUG-message-if-a-group-has-no-ipaNTSec.patch +++ /dev/null @@ -1,41 +0,0 @@ -From ef019268d2d112ebff3577e551cd19478d73d93b Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 21 Apr 2017 12:39:44 +0200 -Subject: [PATCH 117/135] IPA: Improve DEBUG message if a group has no - ipaNTSecurityIdentifier -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There was an issue in a production deployment where the admin selected a -GID outside the IDM range for a group that contained a user from the -trusted domain. This resulted in not adding a SID for the IPA group, -which in turn meant the group couldn't be resolved on the client. - -This patch just improves the DEBUG message so that it's clearer for the -admins where the issue is. - -Reviewed-by: Lukáš Slebodník ---- - src/providers/ipa/ipa_s2n_exop.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 2173db357700499a6140aa61841e443139981483..55ec904ca3188c7cf10ac41972e9ecf94ebf44bb 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -1308,7 +1308,10 @@ static void ipa_s2n_get_list_next(struct tevent_req *subreq) - ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR, - &sid_str); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Object [%s] has no SID, please check the " -+ "ipaNTSecurityIdentifier attribute on the server-side", -+ state->attrs->a.name); - goto fail; - } - --- -2.12.2 - diff --git a/0118-RESPONDER-Fallback-to-global-domain-resolution-order.patch b/0118-RESPONDER-Fallback-to-global-domain-resolution-order.patch deleted file mode 100644 index 9b52466..0000000 --- a/0118-RESPONDER-Fallback-to-global-domain-resolution-order.patch +++ /dev/null @@ -1,312 +0,0 @@ -From a3faad0e4dc1ca4473746c3822ecfc5aed876e6d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Wed, 12 Apr 2017 10:43:25 +0200 -Subject: [PATCH 118/135] RESPONDER: Fallback to global domain resolution order - in case the view doesn't have this option set -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The current code has been ignoring the domain resolution order set -globally on IPA in case there's a view but this doesn't have any domain -resolution order set. - -It happens because we haven't been checking whether the view attribute -didn't exist and then we ended up populating the list cache_req domains' -list assuming that no order has been set instead of falling back to the -next preferred method. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Pavel Březina ---- - src/responder/common/cache_req/cache_req_domain.c | 14 ++- - src/responder/common/cache_req/cache_req_domain.h | 5 +- - src/responder/common/responder_common.c | 108 +++++++++++++--------- - 3 files changed, 74 insertions(+), 53 deletions(-) - -diff --git a/src/responder/common/cache_req/cache_req_domain.c b/src/responder/common/cache_req/cache_req_domain.c -index bbabd695f1c6b6c29b7e61f571382ab9adfb0ea2..86a88efd54ca0f4a0748b44ece1b8515438d4628 100644 ---- a/src/responder/common/cache_req/cache_req_domain.c -+++ b/src/responder/common/cache_req/cache_req_domain.c -@@ -120,20 +120,21 @@ done: - return cr_domains; - } - --struct cache_req_domain * -+errno_t - cache_req_domain_new_list_from_domain_resolution_order( - TALLOC_CTX *mem_ctx, - struct sss_domain_info *domains, -- const char *domain_resolution_order) -+ const char *domain_resolution_order, -+ struct cache_req_domain **_cr_domains) - { - TALLOC_CTX *tmp_ctx; -- struct cache_req_domain *cr_domains = NULL; -+ struct cache_req_domain *cr_domains; - char **list = NULL; - errno_t ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { -- return NULL; -+ return ENOMEM; - } - - if (domain_resolution_order != NULL) { -@@ -160,7 +161,10 @@ cache_req_domain_new_list_from_domain_resolution_order( - goto done; - } - -+ *_cr_domains = cr_domains; -+ ret = EOK; -+ - done: - talloc_free(tmp_ctx); -- return cr_domains; -+ return ret; - } -diff --git a/src/responder/common/cache_req/cache_req_domain.h b/src/responder/common/cache_req/cache_req_domain.h -index 41c50e8c293d7b032cb2f05482c40e93e4f723dc..000087e5ca2074f22169a4af627810f4f287e430 100644 ---- a/src/responder/common/cache_req/cache_req_domain.h -+++ b/src/responder/common/cache_req/cache_req_domain.h -@@ -34,11 +34,12 @@ struct cache_req_domain * - cache_req_domain_get_domain_by_name(struct cache_req_domain *domains, - const char *name); - --struct cache_req_domain * -+errno_t - cache_req_domain_new_list_from_domain_resolution_order( - TALLOC_CTX *mem_ctx, - struct sss_domain_info *domains, -- const char *domain_resolution_order); -+ const char *domain_resolution_order, -+ struct cache_req_domain **_cr_domains); - - void cache_req_domain_list_zfree(struct cache_req_domain **cr_domains); - -diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c -index ac6320b08de09bc6c7e8dd1af72e0a493a449f7a..62b71b5104fdbb585d086d44d2ca2ab9717dd788 100644 ---- a/src/responder/common/responder_common.c -+++ b/src/responder/common/responder_common.c -@@ -1486,10 +1486,11 @@ fail: - } - - /* ====== Helper functions for the domain resolution order ======= */ --static struct cache_req_domain * -+static errno_t - sss_resp_new_cr_domains_from_ipa_id_view(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domains, -- struct sysdb_ctx *sysdb) -+ struct sysdb_ctx *sysdb, -+ struct cache_req_domain **_cr_domains) - { - TALLOC_CTX *tmp_ctx; - struct cache_req_domain *cr_domains = NULL; -@@ -1498,7 +1499,7 @@ sss_resp_new_cr_domains_from_ipa_id_view(TALLOC_CTX *mem_ctx, - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { -- return NULL; -+ return ENOMEM; - } - - ret = sysdb_get_view_domain_resolution_order(tmp_ctx, sysdb, -@@ -1510,12 +1511,13 @@ sss_resp_new_cr_domains_from_ipa_id_view(TALLOC_CTX *mem_ctx, - goto done; - } - -- /* Using mem_ctx (which is rctx) directly here to avoid copying -- * this memory around. */ -- cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -- mem_ctx, domains, domain_resolution_order); -- if (cr_domains == NULL) { -- ret = ENOMEM; -+ if (ret == ENOENT) { -+ goto done; -+ } -+ -+ ret = cache_req_domain_new_list_from_domain_resolution_order( -+ mem_ctx, domains, domain_resolution_order, &cr_domains); -+ if (ret != EOK) { - DEBUG(SSSDBG_DEFAULT, - "cache_req_domain_new_list_from_domain_resolution_order() " - "failed [%d]: [%s].\n", -@@ -1523,25 +1525,31 @@ sss_resp_new_cr_domains_from_ipa_id_view(TALLOC_CTX *mem_ctx, - goto done; - } - -+ *_cr_domains = cr_domains; -+ -+ ret = EOK; -+ - done: - talloc_free(tmp_ctx); -- return cr_domains; -+ return ret; - } - --static struct cache_req_domain * -+static errno_t - sss_resp_new_cr_domains_from_ipa_config(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domains, - struct sysdb_ctx *sysdb, -- const char *domain) -+ const char *domain, -+ struct cache_req_domain **_cr_domains) - { - TALLOC_CTX *tmp_ctx; -- struct cache_req_domain *cr_domains = NULL; - const char *domain_resolution_order = NULL; - errno_t ret; - -+ *_cr_domains = NULL; -+ - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { -- return NULL; -+ return ENOMEM; - } - - ret = sysdb_domain_get_domain_resolution_order(tmp_ctx, sysdb, domain, -@@ -1554,11 +1562,13 @@ sss_resp_new_cr_domains_from_ipa_config(TALLOC_CTX *mem_ctx, - goto done; - } - -- /* Using mem_ctx (which is rctx) directly here to avoid copying -- * this memory around. */ -- cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -- mem_ctx, domains, domain_resolution_order); -- if (cr_domains == NULL) { -+ if (ret == ENOENT) { -+ goto done; -+ } -+ -+ ret = cache_req_domain_new_list_from_domain_resolution_order( -+ mem_ctx, domains, domain_resolution_order, _cr_domains); -+ if (ret != EOK) { - DEBUG(SSSDBG_DEFAULT, - "cache_req_domain_new_list_from_domain_resolution_order() " - "failed [%d]: [%s].\n", -@@ -1566,9 +1576,11 @@ sss_resp_new_cr_domains_from_ipa_config(TALLOC_CTX *mem_ctx, - goto done; - } - -+ ret = EOK; -+ - done: - talloc_free(tmp_ctx); -- return cr_domains; -+ return ret; - } - - errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) -@@ -1578,16 +1590,16 @@ errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) - errno_t ret; - - if (rctx->domain_resolution_order != NULL) { -- cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -- rctx, rctx->domains, rctx->domain_resolution_order); -- -- if (cr_domains == NULL) { -+ ret = cache_req_domain_new_list_from_domain_resolution_order( -+ rctx, rctx->domains, -+ rctx->domain_resolution_order, &cr_domains); -+ if (ret == EOK) { -+ goto done; -+ } else { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to use domain_resolution_order set in the config file.\n" - "Trying to fallback to use ipaDomainOrderResolution setup by " - "IPA.\n"); -- } else { -- goto done; - } - } - -@@ -1598,9 +1610,9 @@ errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) - } - - if (dom == NULL) { -- cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -- rctx, rctx->domains, NULL); -- if (cr_domains == NULL) { -+ ret = cache_req_domain_new_list_from_domain_resolution_order( -+ rctx, rctx->domains, NULL, &cr_domains); -+ if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to flatten the list of domains.\n"); - } -@@ -1608,44 +1620,48 @@ errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) - } - - if (dom->has_views) { -- cr_domains = sss_resp_new_cr_domains_from_ipa_id_view(rctx, -- rctx->domains, -- dom->sysdb); -- if (cr_domains == NULL) { -+ ret = sss_resp_new_cr_domains_from_ipa_id_view(rctx, rctx->domains, -+ dom->sysdb, -+ &cr_domains); -+ if (ret == EOK) { -+ goto done; -+ } -+ -+ if (ret != ENOENT) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to use ipaDomainResolutionOrder set for the " - "view \"%s\".\n" - "Trying to fallback to use ipaDomainOrderResolution " - "set in ipaConfig for the domain: %s.\n", - dom->view_name, dom->name); -- } else { -- goto done; - } - } - -- cr_domains = sss_resp_new_cr_domains_from_ipa_config(rctx, rctx->domains, -- dom->sysdb, -- dom->name); -- if (cr_domains == NULL) { -+ ret = sss_resp_new_cr_domains_from_ipa_config(rctx, rctx->domains, -+ dom->sysdb, dom->name, -+ &cr_domains); -+ if (ret == EOK) { -+ goto done; -+ } -+ -+ if (ret != ENOENT) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to use ipaDomainResolutionOrder set in ipaConfig " - "for the domain: \"%s\".\n" - "No ipaDomainResolutionOrder will be followed.\n", - dom->name); -- } else { -- goto done; - } - -- cr_domains = cache_req_domain_new_list_from_domain_resolution_order( -- rctx, rctx->domains, NULL); -- if (cr_domains == NULL) { -+ ret = cache_req_domain_new_list_from_domain_resolution_order( -+ rctx, rctx->domains, NULL, &cr_domains); -+ if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to flatten the list of domains.\n"); - goto done; - } - --done: -- ret = cr_domains != NULL ? EOK : ENOMEM; -+ ret = EOK; - -+done: - cache_req_domain_list_zfree(&rctx->cr_domains); - rctx->cr_domains = cr_domains; - --- -2.12.2 - diff --git a/0119-NSS-TESTS-Improve-non-fqnames-tests.patch b/0119-NSS-TESTS-Improve-non-fqnames-tests.patch deleted file mode 100644 index 6af99d8..0000000 --- a/0119-NSS-TESTS-Improve-non-fqnames-tests.patch +++ /dev/null @@ -1,163 +0,0 @@ -From ed518f61f1a5d4cf5d87eec492c158725a73d6a1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 17 Apr 2017 09:32:39 +0200 -Subject: [PATCH 119/135] NSS/TESTS: Improve non-fqnames tests -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With the changes that are about to happen we have to have the subdomain's -fqnames flag set by the time we populate the cr_domains list (as it -actually occurs with the real code), as this list may set its own fqnames -flag based on the subdomain's fqnames flag. - -Currently the flag is set to false only when running the tests itself so -the cr_domains list doesn't get populate properly (although it still -works with the current code). - -For the changes that are comming, let's introduce a new setup function -that ensures that the subdomain's fqnames flag is set up in the right -time. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Pavel Březina ---- - src/tests/cmocka/test_nss_srv.c | 45 +++++++++++++++++++++++++++-------------- - 1 file changed, 30 insertions(+), 15 deletions(-) - -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index 2f526660cbbbf2443dbae4e213c1336feb6c661e..8c72f44f1869558893627e1f2f91b5f3b96c6317 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -1709,8 +1709,6 @@ void test_nss_getgrnam_members_subdom_nonfqnames(void **state) - { - errno_t ret; - -- nss_test_ctx->subdom->fqnames = false; -- - mock_input_user_or_group("testsubdomgroup"); - mock_account_recv_simple(); - will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); -@@ -1802,8 +1800,6 @@ void test_nss_getgrnam_mix_dom_nonfqnames(void **state) - { - errno_t ret; - -- nss_test_ctx->subdom->fqnames = false; -- - ret = store_group_member(nss_test_ctx, - testgroup_members.gr_name, - nss_test_ctx->tctx->dom, -@@ -1917,6 +1913,7 @@ void test_nss_getgrnam_mix_dom_fqdn(void **state) - assert_int_equal(ret, EOK); - } - -+ - void test_nss_getgrnam_mix_dom_fqdn_nonfqnames(void **state) - { - errno_t ret; -@@ -1929,10 +1926,6 @@ void test_nss_getgrnam_mix_dom_fqdn_nonfqnames(void **state) - SYSDB_MEMBER_USER); - assert_int_equal(ret, EOK); - -- nss_test_ctx->tctx->dom->fqnames = false; -- nss_test_ctx->subdom->fqnames = false; -- -- - mock_input_user_or_group("testgroup_members"); - will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM); - will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -@@ -2044,8 +2037,6 @@ void test_nss_getgrnam_mix_subdom_nonfqnames(void **state) - { - errno_t ret; - -- nss_test_ctx->subdom->fqnames = false; -- - ret = store_group_member(nss_test_ctx, - testsubdomgroup.gr_name, - nss_test_ctx->subdom, -@@ -3417,9 +3408,11 @@ static int nss_test_setup_extra_attr(void **state) - return 0; - } - --static int nss_subdom_test_setup(void **state) -+static int nss_subdom_test_setup_common(void **state, bool nonfqnames) - { - const char *const testdom[4] = { TEST_SUBDOM_NAME, "TEST.SUB", "test", "S-3" }; -+ struct sss_domain_info *dom; -+ - struct sss_domain_info *subdomain; - errno_t ret; - -@@ -3440,6 +3433,17 @@ static int nss_subdom_test_setup(void **state) - nss_test_ctx->tctx->confdb); - assert_int_equal(ret, EOK); - -+ if (nonfqnames) { -+ for (dom = nss_test_ctx->rctx->domains; -+ dom != NULL; -+ dom = get_next_domain(dom, SSS_GND_ALL_DOMAINS)) { -+ if (strcmp(dom->name, subdomain->name) == 0) { -+ dom->fqnames = false; -+ break; -+ } -+ } -+ } -+ - ret = sss_resp_populate_cr_domains(nss_test_ctx->rctx); - assert_int_equal(ret, EOK); - assert_non_null(nss_test_ctx->rctx->cr_domains); -@@ -3475,6 +3479,17 @@ static int nss_subdom_test_setup(void **state) - assert_int_equal(ret, EOK); - - return 0; -+ -+} -+ -+static int nss_subdom_test_setup(void **state) -+{ -+ return nss_subdom_test_setup_common(state, false); -+} -+ -+static int nss_subdom_test_setup_nonfqnames(void **state) -+{ -+ return nss_subdom_test_setup_common(state, true); - } - - static int nss_fqdn_fancy_test_setup(void **state) -@@ -4192,25 +4207,25 @@ int main(int argc, const char *argv[]) - nss_subdom_test_setup, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_members_subdom_nonfqnames, -- nss_subdom_test_setup, -+ nss_subdom_test_setup_nonfqnames, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom, - nss_subdom_test_setup, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_nonfqnames, -- nss_subdom_test_setup, -+ nss_subdom_test_setup_nonfqnames, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn, - nss_subdom_test_setup, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn_nonfqnames, -- nss_subdom_test_setup, -+ nss_subdom_test_setup_nonfqnames, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom, - nss_subdom_test_setup, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_mix_subdom_nonfqnames, -- nss_subdom_test_setup, -+ nss_subdom_test_setup_nonfqnames, - nss_subdom_test_teardown), - cmocka_unit_test_setup_teardown(test_nss_getgrnam_space, - nss_test_setup, nss_test_teardown), --- -2.12.2 - diff --git a/0120-CACHE_REQ-Allow-configurationless-shortname-lookups.patch b/0120-CACHE_REQ-Allow-configurationless-shortname-lookups.patch deleted file mode 100644 index de5d757..0000000 --- a/0120-CACHE_REQ-Allow-configurationless-shortname-lookups.patch +++ /dev/null @@ -1,138 +0,0 @@ -From dae798231fc2c575f213785768bc24ed765ba243 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Tue, 11 Apr 2017 17:19:29 +0200 -Subject: [PATCH 120/135] CACHE_REQ: Allow configurationless shortname lookups -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Configurationless shortnames lookups must be allowed when a domains' -resolution order is present and the (head) domain is not enforcing the -usage of fully-qualified-names. - -With this patch SSSD does not require any kind of changes from client -side for taking advantage of shortname lookups. - -Related: -https://pagure.io/SSSD/sssd/issue/3001 - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Pavel Březina ---- - src/responder/common/cache_req/cache_req.c | 2 +- - src/responder/common/cache_req/cache_req_domain.c | 48 +++++++++++++++++++++++ - src/responder/common/cache_req/cache_req_domain.h | 1 + - 3 files changed, 50 insertions(+), 1 deletion(-) - -diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c -index 3a5fecf34427437bbf95317e05c5bd8b07b4537d..797325a30e6c1ed5f1d4b4c147c65391d5204b52 100644 ---- a/src/responder/common/cache_req/cache_req.c -+++ b/src/responder/common/cache_req/cache_req.c -@@ -480,7 +480,7 @@ static errno_t cache_req_search_domains_next(struct tevent_req *req) - * qualified names on domain less search. We do not descend into - * subdomains here since those are implicitly qualified. - */ -- if (state->check_next && !allow_no_fqn && domain->fqnames) { -+ if (state->check_next && !allow_no_fqn && state->cr_domain->fqnames) { - state->cr_domain = state->cr_domain->next; - continue; - } -diff --git a/src/responder/common/cache_req/cache_req_domain.c b/src/responder/common/cache_req/cache_req_domain.c -index 86a88efd54ca0f4a0748b44ece1b8515438d4628..bfdd2b7f640178f6d0a0d92f2fed329c856b478c 100644 ---- a/src/responder/common/cache_req/cache_req_domain.c -+++ b/src/responder/common/cache_req/cache_req_domain.c -@@ -60,6 +60,48 @@ void cache_req_domain_list_zfree(struct cache_req_domain **cr_domains) - *cr_domains = NULL; - } - -+static bool -+cache_req_domain_use_fqnames(struct sss_domain_info *domain, -+ bool enforce_non_fqnames) -+{ -+ struct sss_domain_info *head; -+ -+ head = get_domains_head(domain); -+ -+ /* -+ * In order to decide whether fully_qualified_names must be used on the -+ * lookups we have to take into consideration: -+ * - use_fully_qualified_name value of the head of the domains; -+ * (head->fqnames) -+ * - the presence of a domains' resolution order list; -+ * (non_fqnames_enforced) -+ * -+ * The relationship between those two can be described by: -+ * - head->fqnames: -+ * - true: in this case doesn't matter whether it's enforced or not, -+ * fully-qualified-names will _always_ be used -+ * - false: in this case (which is also the default case), the usage -+ * depends on it being enforced; -+ * -+ * - enforce_non_fqnames: -+ * - true: in this case, the usage of fully-qualified-names is not -+ * needed; -+ * - false: in this case, the usage of fully-qualified-names will be -+ * done accordingly to what's set for the domain itself. -+ */ -+ switch (head->fqnames) { -+ case true: -+ return true; -+ case false: -+ switch (enforce_non_fqnames) { -+ case true: -+ return false; -+ case false: -+ return domain->fqnames; -+ } -+ } -+} -+ - static struct cache_req_domain * - cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domains, -@@ -71,9 +113,11 @@ cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, - char *name; - int flag = SSS_GND_ALL_DOMAINS; - int i; -+ bool enforce_non_fqnames = false; - errno_t ret; - - if (resolution_order != NULL) { -+ enforce_non_fqnames = true; - for (i = 0; resolution_order[i] != NULL; i++) { - name = resolution_order[i]; - for (dom = domains; dom; dom = get_next_domain(dom, flag)) { -@@ -87,6 +131,8 @@ cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, - goto done; - } - cr_domain->domain = dom; -+ cr_domain->fqnames = -+ cache_req_domain_use_fqnames(dom, enforce_non_fqnames); - - DLIST_ADD_END(cr_domains, cr_domain, - struct cache_req_domain *); -@@ -106,6 +152,8 @@ cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, - goto done; - } - cr_domain->domain = dom; -+ cr_domain->fqnames = -+ cache_req_domain_use_fqnames(dom, enforce_non_fqnames); - - DLIST_ADD_END(cr_domains, cr_domain, struct cache_req_domain *); - } -diff --git a/src/responder/common/cache_req/cache_req_domain.h b/src/responder/common/cache_req/cache_req_domain.h -index 000087e5ca2074f22169a4af627810f4f287e430..5bcbb9b493caf05bf71aac5cf7633ded91f22e73 100644 ---- a/src/responder/common/cache_req/cache_req_domain.h -+++ b/src/responder/common/cache_req/cache_req_domain.h -@@ -25,6 +25,7 @@ - - struct cache_req_domain { - struct sss_domain_info *domain; -+ bool fqnames; - - struct cache_req_domain *prev; - struct cache_req_domain *next; --- -2.12.2 - diff --git a/0121-CACHE_REQ_DOMAIN-Add-some-comments-to-cache_req_doma.patch b/0121-CACHE_REQ_DOMAIN-Add-some-comments-to-cache_req_doma.patch deleted file mode 100644 index 2d76440..0000000 --- a/0121-CACHE_REQ_DOMAIN-Add-some-comments-to-cache_req_doma.patch +++ /dev/null @@ -1,41 +0,0 @@ -From f9bac02756aa05cc9c6ac07ae581dba67240c1a4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 24 Apr 2017 21:04:58 +0200 -Subject: [PATCH 121/135] CACHE_REQ_DOMAIN: Add some comments to - cache_req_domain_new_list_from_string_list() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Pavel Březina ---- - src/responder/common/cache_req/cache_req_domain.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/responder/common/cache_req/cache_req_domain.c b/src/responder/common/cache_req/cache_req_domain.c -index bfdd2b7f640178f6d0a0d92f2fed329c856b478c..6d37db0f109d5343eb6d7f4272bea522d4c34cf7 100644 ---- a/src/responder/common/cache_req/cache_req_domain.c -+++ b/src/responder/common/cache_req/cache_req_domain.c -@@ -116,6 +116,8 @@ cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, - bool enforce_non_fqnames = false; - errno_t ret; - -+ /* Firstly, in case a domains' resolution order is passed ... iterate over -+ * the list adding its domains to the flatten cache req domains' list */ - if (resolution_order != NULL) { - enforce_non_fqnames = true; - for (i = 0; resolution_order[i] != NULL; i++) { -@@ -141,6 +143,8 @@ cache_req_domain_new_list_from_string_list(TALLOC_CTX *mem_ctx, - } - } - -+ /* Then iterate through all the other domains (and subdomains) and add them -+ * to the flatten cache req domains' list */ - for (dom = domains; dom; dom = get_next_domain(dom, flag)) { - if (string_in_list(dom->name, resolution_order, false)) { - continue; --- -2.12.2 - diff --git a/0122-RESPONDER_COMMON-Improve-domaiN_resolution_order-deb.patch b/0122-RESPONDER_COMMON-Improve-domaiN_resolution_order-deb.patch deleted file mode 100644 index f8a37b3..0000000 --- a/0122-RESPONDER_COMMON-Improve-domaiN_resolution_order-deb.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 213048fd9a5e800deb74cb5b7f0eaf465945c640 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Mon, 24 Apr 2017 21:09:02 +0200 -Subject: [PATCH 122/135] RESPONDER_COMMON: Improve domaiN_resolution_order - debug messages -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Indicate whether a domain_resolution_order has been used and where -it came from. - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Pavel Březina ---- - src/responder/common/responder_common.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c -index 62b71b5104fdbb585d086d44d2ca2ab9717dd788..7496d293fddb3e947d59a4f2aaeb2c83234dfcc7 100644 ---- a/src/responder/common/responder_common.c -+++ b/src/responder/common/responder_common.c -@@ -1594,6 +1594,8 @@ errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) - rctx, rctx->domains, - rctx->domain_resolution_order, &cr_domains); - if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Using domain_resolution_order from sssd.conf\n"); - goto done; - } else { - DEBUG(SSSDBG_MINOR_FAILURE, -@@ -1624,6 +1626,8 @@ errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) - dom->sysdb, - &cr_domains); - if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Using domain_resolution_order from IPA ID View\n"); - goto done; - } - -@@ -1641,6 +1645,8 @@ errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx) - dom->sysdb, dom->name, - &cr_domains); - if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Using domain_resolution_order from IPA Config\n"); - goto done; - } - --- -2.12.2 - diff --git a/0123-CACHE_REQ_DOMAIN-debug-the-set-domain-resolution-ord.patch b/0123-CACHE_REQ_DOMAIN-debug-the-set-domain-resolution-ord.patch deleted file mode 100644 index 6bc04ba..0000000 --- a/0123-CACHE_REQ_DOMAIN-debug-the-set-domain-resolution-ord.patch +++ /dev/null @@ -1,49 +0,0 @@ -From b78febe4c579f86f8007a27599605d1eb9f97a62 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= -Date: Tue, 25 Apr 2017 14:25:12 +0200 -Subject: [PATCH 123/135] CACHE_REQ_DOMAIN: debug the set domain resolution - order -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Fabiano Fidêncio - -Reviewed-by: Pavel Březina ---- - src/responder/common/cache_req/cache_req_domain.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/src/responder/common/cache_req/cache_req_domain.c b/src/responder/common/cache_req/cache_req_domain.c -index 6d37db0f109d5343eb6d7f4272bea522d4c34cf7..2c238c9966d322bb542fa2047313ee9e5144edee 100644 ---- a/src/responder/common/cache_req/cache_req_domain.c -+++ b/src/responder/common/cache_req/cache_req_domain.c -@@ -191,6 +191,10 @@ cache_req_domain_new_list_from_domain_resolution_order( - - if (domain_resolution_order != NULL) { - if (strcmp(domain_resolution_order, ":") != 0) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Domain resolution order list (split by ':'): \"%s\"\n", -+ domain_resolution_order); -+ - ret = split_on_separator(tmp_ctx, domain_resolution_order, ':', - true, true, &list, NULL); - if (ret != EOK) { -@@ -199,7 +203,14 @@ cache_req_domain_new_list_from_domain_resolution_order( - ret, sss_strerror(ret)); - goto done; - } -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Domain resolution order list: ':' " -+ "(do not use any specific order)\n"); - } -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Domain resolution order list: not set\n"); - } - - cr_domains = cache_req_domain_new_list_from_string_list(mem_ctx, domains, --- -2.12.2 - diff --git a/0124-LDAP-Allow-passing-a-NULL-map-to-sdap_search_bases_e.patch b/0124-LDAP-Allow-passing-a-NULL-map-to-sdap_search_bases_e.patch deleted file mode 100644 index 546d1b4..0000000 --- a/0124-LDAP-Allow-passing-a-NULL-map-to-sdap_search_bases_e.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 53e9a5aef4a688f7c81a4a1e77013e05313e5f9a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 21 Apr 2017 15:30:37 +0200 -Subject: [PATCH 124/135] LDAP: Allow passing a NULL map to - sdap_search_bases_ex_send -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -NULL attribute map and a NULL list of attributes should translate into -"fetch all entry attributes" - -Required for: - https://pagure.io/SSSD/sssd/issue/3378 - -Reviewed-by: Pavel Březina ---- - src/providers/ldap/sdap_ops.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ldap/sdap_ops.c b/src/providers/ldap/sdap_ops.c -index 3fc968f0bf6782f91a5f5620bfe34eeeebcdc832..a90857469a4ed6f2cecb935ea70340060952c9df 100644 ---- a/src/providers/ldap/sdap_ops.c -+++ b/src/providers/ldap/sdap_ops.c -@@ -101,7 +101,7 @@ sdap_search_bases_ex_send(TALLOC_CTX *mem_ctx, - state->map_num_attrs = 0; - } - -- if (state->attrs == NULL) { -+ if (state->attrs == NULL && state->map != NULL) { - ret = build_attrs_from_map(state, state->map, state->map_num_attrs, - NULL, &state->attrs, NULL); - if (ret != EOK) { --- -2.12.2 - diff --git a/0125-IPA-Use-search-bases-instead-of-domain_to_basedn-whe.patch b/0125-IPA-Use-search-bases-instead-of-domain_to_basedn-whe.patch deleted file mode 100644 index 29435e9..0000000 --- a/0125-IPA-Use-search-bases-instead-of-domain_to_basedn-whe.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 337dd8a87cd774ac20d15c16ec3d9a6c4d2defc7 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 18 Apr 2017 11:47:30 +0200 -Subject: [PATCH 125/135] IPA: Use search bases instead of domain_to_basedn - when fetching external groups -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Instead of deriving the search base from the IPA domain name, actually -use the search base from the sdap_domain structure. - -This has primarily the advantage of not matching groups in the compat -tree. - -Resolves: - https://pagure.io/SSSD/sssd/issue/3378 - -Reviewed-by: Pavel Březina ---- - src/providers/ipa/ipa_subdomains_ext_groups.c | 30 ++++++++++++--------------- - 1 file changed, 13 insertions(+), 17 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c -index d5727cc46eb9834abeab1d15cada692f81754b2e..505d89a51423489a5e2c0e09c9aa49d93c15231b 100644 ---- a/src/providers/ipa/ipa_subdomains_ext_groups.c -+++ b/src/providers/ipa/ipa_subdomains_ext_groups.c -@@ -27,6 +27,7 @@ - #include "db/sysdb.h" - #include "providers/ldap/ldap_common.h" - #include "providers/ldap/sdap_async.h" -+#include "providers/ldap/sdap_ops.h" - #include "providers/ipa/ipa_id.h" - #include "providers/ad/ad_id.h" - #include "providers/ipa/ipa_subdomains.h" -@@ -529,7 +530,6 @@ static void ipa_get_ad_memberships_connect_done(struct tevent_req *subreq) - struct get_ad_membership_state *state = tevent_req_data(req, - struct get_ad_membership_state); - int ret; -- char *basedn; - - ret = sdap_id_op_connect_recv(subreq, &state->dp_error); - talloc_zfree(subreq); -@@ -546,20 +546,14 @@ static void ipa_get_ad_memberships_connect_done(struct tevent_req *subreq) - goto fail; - } - -- -- ret = domain_to_basedn(state, state->domain, &basedn); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n"); -- goto fail; -- } -- -- subreq = sdap_get_generic_send(state, state->ev, state->sdap_id_ctx->opts, -- sdap_id_op_handle(state->sdap_op), basedn, -- LDAP_SCOPE_SUBTREE, -- IPA_EXT_GROUPS_FILTER, NULL, NULL, 0, -- dp_opt_get_int(state->sdap_id_ctx->opts->basic, -- SDAP_ENUM_SEARCH_TIMEOUT), -- false); -+ subreq = sdap_search_bases_send(state, state->ev, state->sdap_id_ctx->opts, -+ sdap_id_op_handle(state->sdap_op), -+ state->sdap_id_ctx->opts->sdom->group_search_bases, -+ NULL, false, -+ dp_opt_get_int(state->sdap_id_ctx->opts->basic, -+ SDAP_ENUM_SEARCH_TIMEOUT), -+ IPA_EXT_GROUPS_FILTER, -+ NULL); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n"); - ret = ENOMEM; -@@ -583,8 +577,10 @@ static void ipa_get_ext_groups_done(struct tevent_req *subreq) - int ret; - hash_table_t *ext_group_hash; - -- ret = sdap_get_generic_recv(subreq, state, -- &state->reply_count, &state->reply); -+ ret = sdap_search_bases_recv(subreq, -+ state, -+ &state->reply_count, -+ &state->reply); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ext_groups request failed.\n"); --- -2.12.2 - diff --git a/0126-CONFDB-Fix-standalone-application-domains.patch b/0126-CONFDB-Fix-standalone-application-domains.patch deleted file mode 100644 index f9d824e..0000000 --- a/0126-CONFDB-Fix-standalone-application-domains.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 734e73257fff1c1884b72b8cf988f6d75c3a7567 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 31 Mar 2017 17:12:56 +0200 -Subject: [PATCH 126/135] CONFDB: Fix standalone application domains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When a standalone application domain was configured, for example: - -------------------------------------------------- -[sssd] -domains = appdomain - -[application/appdomain] -id_provider=ldap -ldap_uri = ldap://dc.ipa.test -ldap_search_base = cn=accounts,dc=ipa,dc=test -ldap_schema = rfc2307bis -sudo_provider = none - -ldap_sasl_mech = gssapi -krb5_realm = IPA.TEST -krb5_server = dc.ipa.test - -ldap_user_uid_number = telephonenumber -ldap_user_gid_number = mobile -ldap_user_extra_attrs = location:l -------------------------------------------------- - -We would, when unrolling the application section into a domain section, -first add a domain stub, equivalent to: ------------------------------ -[domain/appdomain] -domain_type = application ------------------------------ - -Which in config.ldb also contains cn. Then, whem we would add the parameters -from the [application] section, but try to add the cn again. - -This didn't happen when inheriting from a POSIX domain, because there we -would set LDB_FLAG_REPLACE for any attributes that exist in the inherited -domain. - -This patch skips the cn attribute both when replacing an inherited -domain's attributes and when writing a standalone application domain. - -Resolves: -https://pagure.io/SSSD/sssd/issue/3355 - -Reviewed-by: Pavel Březina ---- - src/confdb/confdb.c | 26 ++++++++++++++++++++++---- - 1 file changed, 22 insertions(+), 4 deletions(-) - -diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c -index 68693e8382c0fbf1015ee47f14fa7c6f64ae98b2..286dbb24377c6d0fdf2c2d070da04918c591ce05 100644 ---- a/src/confdb/confdb.c -+++ b/src/confdb/confdb.c -@@ -1909,7 +1909,7 @@ static int confdb_add_app_domain(TALLOC_CTX *mem_ctx, - - cdb_path = talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL, name); - if (cdb_path == NULL) { -- return ENOMEM; -+ return ENOMEM; - } - - val[0] = CONFDB_DOMAIN_TYPE_APP; -@@ -1933,6 +1933,7 @@ static int confdb_merge_parent_domain(const char *name, - struct ldb_message *replace_msg = NULL; - struct ldb_message *app_msg = NULL; - struct ldb_dn *domain_dn; -+ struct ldb_message_element *el = NULL; - TALLOC_CTX *tmp_ctx = NULL; - - tmp_ctx = talloc_new(NULL); -@@ -1974,6 +1975,12 @@ static int confdb_merge_parent_domain(const char *name, - replace_msg->elements[i].flags = LDB_FLAG_MOD_ADD; - } - -+ el = ldb_msg_find_element(replace_msg, "cn"); -+ if (el != NULL) { -+ /* Don't add second cn */ -+ ldb_msg_remove_element(replace_msg, el); -+ } -+ - ret = ldb_modify(cdb->ldb, replace_msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); -@@ -1993,7 +2000,14 @@ static int confdb_merge_parent_domain(const char *name, - app_msg->dn = domain_dn; - - for (unsigned i = 0; i < app_section->msgs[0]->num_elements; i++) { -- struct ldb_message_element *el = NULL; -+ struct ldb_message_element *app_el = &app_section->msgs[0]->elements[i]; -+ -+ /* These elements will be skipped when replacing attributes in -+ * a domain to avoid EEXIST errors -+ */ -+ if (strcasecmp(app_el->name, "cn") == 0) { -+ continue; -+ } - - if (replace_msg != NULL) { - el = ldb_msg_find_element(replace_msg, -@@ -2013,12 +2027,16 @@ static int confdb_merge_parent_domain(const char *name, - ret = ldb_msg_add(app_msg, - &app_section->msgs[0]->elements[i], - ldb_flag); -- if (ret != EOK) { -+ if (ret != LDB_SUCCESS) { - continue; - } - } - -- ret = ldb_modify(cdb->ldb, app_msg); -+ /* We use permissive modification here because adding cn or -+ * distinguishedName from the app_section to the application -+ * message would throw EEXIST -+ */ -+ ret = sss_ldb_modify_permissive(cdb->ldb, app_msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - DEBUG(SSSDBG_OP_FAILURE, --- -2.12.2 - diff --git a/0127-utils-add-sss_domain_is_forest_root.patch b/0127-utils-add-sss_domain_is_forest_root.patch deleted file mode 100644 index d5f4839..0000000 --- a/0127-utils-add-sss_domain_is_forest_root.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 712e5b2e4465812c00a8667c75813322373bc657 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 4 Apr 2017 14:35:47 +0200 -Subject: [PATCH 127/135] utils: add sss_domain_is_forest_root() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related to https://pagure.io/SSSD/sssd/issue/3361 - -Reviewed-by: Pavel Březina ---- - src/util/domain_info_utils.c | 5 +++++ - src/util/util.h | 1 + - 2 files changed, 6 insertions(+) - -diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c -index 2af7852f03f89b61f5b9fd8a244e98fb27b7e6a2..541058a16d585155b3b51511740f7db45281e2fd 100644 ---- a/src/util/domain_info_utils.c -+++ b/src/util/domain_info_utils.c -@@ -844,6 +844,11 @@ void sss_domain_set_state(struct sss_domain_info *dom, - "Domain %s is %s\n", dom->name, domain_state_str(dom)); - } - -+bool sss_domain_is_forest_root(struct sss_domain_info *dom) -+{ -+ return (dom->forest_root == dom); -+} -+ - bool is_email_from_domain(const char *email, struct sss_domain_info *dom) - { - const char *p; -diff --git a/src/util/util.h b/src/util/util.h -index 436550f5078cc173b8ed8cb58836d366f813146b..4ef13ced48addc19403402d7d880176da24ceec6 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -539,6 +539,7 @@ enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom); - void sss_domain_set_state(struct sss_domain_info *dom, - enum sss_domain_state state); - bool is_email_from_domain(const char *email, struct sss_domain_info *dom); -+bool sss_domain_is_forest_root(struct sss_domain_info *dom); - const char *sss_domain_type_str(struct sss_domain_info *dom); - - struct sss_domain_info* --- -2.12.2 - diff --git a/0128-ad-handle-forest-root-not-listed-in-ad_enabled_domai.patch b/0128-ad-handle-forest-root-not-listed-in-ad_enabled_domai.patch deleted file mode 100644 index c944478..0000000 --- a/0128-ad-handle-forest-root-not-listed-in-ad_enabled_domai.patch +++ /dev/null @@ -1,103 +0,0 @@ -From feeabf273aa7af580552366ce58655e6a482a0cd Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 3 Apr 2017 21:27:32 +0200 -Subject: [PATCH 128/135] ad: handle forest root not listed in - ad_enabled_domains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Although users and groups from the forest root should be ignored SSSD -will still try to get information about the forest topology from a DC -from the forest root. So even if the forest root domain is disabled we -should makes sure it is usable for those searches. - -Resolves https://pagure.io/SSSD/sssd/issue/3361 - -Reviewed-by: Pavel Březina ---- - src/providers/ad/ad_subdomains.c | 39 ++++++++++++++++++++++++++++++++++++--- - 1 file changed, 36 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index bc659b2cb0a02723437d24d0021ec3592381e84c..ef166446e837c3f7cd824c1abf4b5cc587aec9da 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -433,6 +433,14 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx, - if (c >= num_subdomains) { - /* ok this subdomain does not exist anymore, let's clean up */ - sss_domain_set_state(dom, DOM_DISABLED); -+ -+ /* Just disable the forest root but do not remove sdap data */ -+ if (sss_domain_is_forest_root(dom)) { -+ DEBUG(SSSDBG_TRACE_ALL, -+ "Skipping removal of forest root sdap data.\n"); -+ continue; -+ } -+ - ret = sysdb_subdomain_delete(dom->sysdb, dom->name); - if (ret != EOK) { - goto done; -@@ -633,6 +641,7 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *subdoms_ctx) - const char *path; - errno_t ret; - bool canonicalize = false; -+ struct sss_domain_info *dom; - - path = dp_opt_get_string(subdoms_ctx->ad_id_ctx->ad_options->basic, - AD_KRB5_CONFD_PATH); -@@ -675,6 +684,17 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *subdoms_ctx) - return ret; - } - -+ /* Make sure disabled domains are not re-enabled accidentially */ -+ if (subdoms_ctx->ad_enabled_domains != NULL) { -+ for (dom = subdoms_ctx->be_ctx->domain->subdomains; dom; -+ dom = get_next_domain(dom, false)) { -+ if (!is_domain_enabled(dom->name, -+ subdoms_ctx->ad_enabled_domains)) { -+ sss_domain_set_state(dom, DOM_DISABLED); -+ } -+ } -+ } -+ - return EOK; - } - -@@ -898,7 +918,7 @@ static errno_t ad_get_slave_domain_recv(struct tevent_req *req) - static struct sss_domain_info * - ads_get_root_domain(struct be_ctx *be_ctx, struct sysdb_attrs *attrs) - { -- struct sss_domain_info *root; -+ struct sss_domain_info *dom; - const char *name; - errno_t ret; - -@@ -909,9 +929,22 @@ ads_get_root_domain(struct be_ctx *be_ctx, struct sysdb_attrs *attrs) - } - - /* With a subsequent run, the root should already be known */ -- root = find_domain_by_name(be_ctx->domain, name, false); -+ for (dom = be_ctx->domain; dom != NULL; -+ dom = get_next_domain(dom, SSS_GND_ALL_DOMAINS)) { - -- return root; -+ if (strcasecmp(dom->name, name) == 0) { -+ /* The forest root is special, although it might be disabled for -+ * general lookups we still want to try to get the domains in the -+ * forest from a DC of the forest root */ -+ if (sss_domain_get_state(dom) == DOM_DISABLED -+ && !sss_domain_is_forest_root(dom)) { -+ return NULL; -+ } -+ return dom; -+ } -+ } -+ -+ return NULL; - } - - static struct ad_id_ctx * --- -2.12.2 - diff --git a/0129-overrides-add-certificates-to-mapped-attribute.patch b/0129-overrides-add-certificates-to-mapped-attribute.patch deleted file mode 100644 index c428c25..0000000 --- a/0129-overrides-add-certificates-to-mapped-attribute.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 2e5fc89ef25434fab7febe2c52e97ef989b50d5b Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 27 Apr 2017 09:28:55 +0200 -Subject: [PATCH 129/135] overrides: add certificates to mapped attribute -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Certificates in overrides are explicitly used to map users to -certificates, so we add them to SYSDB_USER_MAPPED_CERT as well. - -Resolves https://pagure.io/SSSD/sssd/issue/3373 - -Reviewed-by: Pavel Březina ---- - src/db/sysdb_views.c | 41 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 41 insertions(+) - -diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c -index 20db9b06183d68b33bb19f498513d7f5cf84b1cf..3773dda77e16b35fa217be0aa7974da7e34c09f4 100644 ---- a/src/db/sysdb_views.c -+++ b/src/db/sysdb_views.c -@@ -777,6 +777,7 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain, - int ret; - TALLOC_CTX *tmp_ctx; - struct sysdb_attrs *attrs; -+ struct sysdb_attrs *mapped_attrs = NULL; - size_t c; - size_t d; - size_t num_values; -@@ -791,6 +792,7 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain, - SYSDB_USER_CERT, - NULL }; - bool override_attrs_found = false; -+ bool is_cert = false; - - if (override_attrs == NULL) { - /* nothing to do */ -@@ -846,6 +848,24 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain, - num_values = 1; - } - -+ is_cert = false; -+ if (strcmp(allowed_attrs[c], SYSDB_USER_CERT) == 0) { -+ /* Certificates in overrides are explicitly used to map -+ * users to certificates, so we add them to -+ * SYSDB_USER_MAPPED_CERT as well. */ -+ is_cert = true; -+ -+ if (mapped_attrs == NULL) { -+ mapped_attrs = sysdb_new_attrs(tmp_ctx); -+ if (mapped_attrs == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_new_attrs failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ } -+ - for (d = 0; d < num_values; d++) { - ret = sysdb_attrs_add_val(attrs, allowed_attrs[c], - &el->values[d]); -@@ -854,6 +874,18 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain, - "sysdb_attrs_add_val failed.\n"); - goto done; - } -+ -+ if (is_cert) { -+ ret = sysdb_attrs_add_val(mapped_attrs, -+ SYSDB_USER_MAPPED_CERT, -+ &el->values[d]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_attrs_add_val failed.\n"); -+ goto done; -+ } -+ } -+ - DEBUG(SSSDBG_TRACE_ALL, - "Override [%s] with [%.*s] for [%s].\n", - allowed_attrs[c], (int) el->values[d].length, -@@ -878,6 +910,15 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain, - DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n"); - goto done; - } -+ -+ if (mapped_attrs != NULL) { -+ ret = sysdb_set_entry_attr(domain->sysdb, obj_dn, mapped_attrs, -+ SYSDB_MOD_ADD); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_set_entry_attr failed, ignored.\n"); -+ } -+ } - } - - ret = EOK; --- -2.12.2 - diff --git a/0130-IPA-Improve-s2n-debug-message-for-missing-ipaNTSecur.patch b/0130-IPA-Improve-s2n-debug-message-for-missing-ipaNTSecur.patch deleted file mode 100644 index 1f3abf6..0000000 --- a/0130-IPA-Improve-s2n-debug-message-for-missing-ipaNTSecur.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0c5f463e9629ac08d647c70cffb30bccdd57ae96 Mon Sep 17 00:00:00 2001 -From: Justin Stephenson -Date: Tue, 25 Apr 2017 13:02:10 -0400 -Subject: [PATCH 130/135] IPA: Improve s2n debug message for missing - ipaNTSecurityIdentifier -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch improves the log message to be more information for -the SSSD user troubleshooting issues. - -If the IDM POSIX group used for AD trust HBAC/SUDO operation is missing -the ipaNTSecurityIdentifier it can cause client s2n operations failures -resolving the group which resulted in the inability to login for the AD -user. - -Reviewed-by: Pavel Březina ---- - src/providers/ipa/ipa_s2n_exop.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 55ec904ca3188c7cf10ac41972e9ecf94ebf44bb..f5f4401f86615dc7f81f844e1096ad43e965c384 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -2580,7 +2580,13 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - ret = sysdb_attrs_get_string(attrs->sysdb_attrs, SYSDB_SID_STR, &sid_str); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, -- "Cannot find SID of object with override.\n"); -+ "Cannot find SID of object.\n"); -+ if (name != NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Object [%s] has no SID, please check the " -+ "ipaNTSecurityIdentifier attribute on the server-side.\n", -+ name); -+ } - goto done; - } - --- -2.12.2 - diff --git a/0131-Use-correct-spelling-of-override.patch b/0131-Use-correct-spelling-of-override.patch deleted file mode 100644 index 251c4d4..0000000 --- a/0131-Use-correct-spelling-of-override.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 352f4832324839d358235de1236090b1fd4ddc0f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ren=C3=A9=20Genz?= -Date: Tue, 25 Apr 2017 20:33:58 +0000 -Subject: [PATCH 131/135] Use correct spelling of override - -Reviewed-by: Jakub Hrozek ---- - src/config/SSSDConfig/__init__.py.in | 2 +- - src/config/cfg_rules.ini | 2 +- - src/config/etc/sssd.api.d/sssd-ipa.conf | 2 +- - src/db/sysdb_views.c | 6 +++--- - src/man/sssd-ipa.5.xml | 2 +- - src/providers/ipa/ipa_opts.c | 2 +- - 6 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 54ad722f07ef91a13a0df278ffd2b1c166bc8d36..5ca31cfefccbb09438d261d4287cd8db736d348e 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -211,7 +211,7 @@ option_strings = { - 'ipa_views_search_base': _("Search base for view containers"), - 'ipa_view_class': _("Objectclass for view containers"), - 'ipa_view_name': _("Attribute with the name of the view"), -- 'ipa_overide_object_class': _("Objectclass for override objects"), -+ 'ipa_override_object_class': _("Objectclass for override objects"), - 'ipa_anchor_uuid': _("Attribute with the reference to the original object"), - 'ipa_user_override_object_class': _("Objectclass for user override objects"), - 'ipa_group_override_object_class': _("Objectclass for group override objects"), -diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini -index e47ff33242d6a9e5979fe0eb8eea14c2af28685a..64cb1474fadba5d5372470a17cd9cd7c7cec7835 100644 ---- a/src/config/cfg_rules.ini -+++ b/src/config/cfg_rules.ini -@@ -457,7 +457,7 @@ option = ipa_netgroup_member_user - option = ipa_netgroup_name - option = ipa_netgroup_object_class - option = ipa_netgroup_uuid --option = ipa_overide_object_class -+option = ipa_override_object_class - option = ipa_ranges_search_base - option = ipa_selinux_refresh - option = ipa_selinux_usermap_enabled -diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf -index 88da36ef4a0a067530dfd44b7a231f4f74c800f2..f36b568c3ea813db3f46fdd69059957f6373801e 100644 ---- a/src/config/etc/sssd.api.d/sssd-ipa.conf -+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf -@@ -143,7 +143,7 @@ ldap_pwdlockout_dn = str, None, false - ipa_views_search_base = str, None, false - ipa_view_class = str, None, false - ipa_view_name = str, None, false --ipa_overide_object_class = str, None, false -+ipa_override_object_class = str, None, false - ipa_anchor_uuid = str, None, false - ipa_user_override_object_class = str, None, false - ipa_group_override_object_class = str, None, false -diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c -index 3773dda77e16b35fa217be0aa7974da7e34c09f4..afc7852ecf402ef144beca9c1b94fbe3cc4bbb6a 100644 ---- a/src/db/sysdb_views.c -+++ b/src/db/sysdb_views.c -@@ -521,7 +521,7 @@ errno_t sysdb_store_override(struct sss_domain_info *domain, - NULL); - if (obj_override_dn != NULL) { - /* obj_override_dn can either point to the object itself, i.e there is -- * no override, or to a overide object. This means it can change from -+ * no override, or to a override object. This means it can change from - * the object DN to a override DN and back but not from one override - * DN to a different override DN. If the new and the old DN are the - * same we do not need to update the original object. */ -@@ -931,7 +931,7 @@ done: - - #define SYSDB_USER_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" - #define SYSDB_USER_UID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")("SYSDB_UIDNUM"=%lu))" --#define SYSDB_USER_CERT_OVERIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")%s)" -+#define SYSDB_USER_CERT_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")%s)" - #define SYSDB_GROUP_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" - #define SYSDB_GROUP_GID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")("SYSDB_GIDNUM"=%lu))" - -@@ -978,7 +978,7 @@ errno_t sysdb_search_override_by_cert(TALLOC_CTX *mem_ctx, - } - - ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn, -- LDB_SCOPE_SUBTREE, attrs, SYSDB_USER_CERT_OVERIDE_FILTER, -+ LDB_SCOPE_SUBTREE, attrs, SYSDB_USER_CERT_OVERRIDE_FILTER, - cert_filter); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); -diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml -index fee644186c9ed11eee18cd27450e56aea38d05bf..98db5b96d9abf157440440eab0882e49595efa5f 100644 ---- a/src/man/sssd-ipa.5.xml -+++ b/src/man/sssd-ipa.5.xml -@@ -546,7 +546,7 @@ - - - -- ipa_overide_object_class (string) -+ ipa_override_object_class (string) - - - Objectclass of the override objects. -diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c -index cd3fe9ae4302ff4837a500b9a0c834dadb11f87d..f9f3a2a6992be6cf5cb3c699b30c45ca9dbb42ab 100644 ---- a/src/providers/ipa/ipa_opts.c -+++ b/src/providers/ipa/ipa_opts.c -@@ -277,7 +277,7 @@ struct sdap_attr_map ipa_view_map[] = { - }; - - struct sdap_attr_map ipa_override_map[] = { -- { "ipa_overide_object_class", "ipaOverrideAnchor", SYSDB_OVERRIDE_CLASS, NULL}, -+ { "ipa_override_object_class", "ipaOverrideAnchor", SYSDB_OVERRIDE_CLASS, NULL}, - { "ipa_anchor_uuid", "ipaAnchorUUID", SYSDB_OVERRIDE_ANCHOR_UUID, NULL}, - { "ipa_user_override_object_class", "ipaUserOverride", SYSDB_OVERRIDE_USER_CLASS, NULL}, - { "ipa_group_override_object_class", "ipaGroupOverride", SYSDB_OVERRIDE_GROUP_CLASS, NULL}, --- -2.12.2 - diff --git a/0132-cache_req-Avoid-bool-in-switch-case.patch b/0132-cache_req-Avoid-bool-in-switch-case.patch deleted file mode 100644 index 080042e..0000000 --- a/0132-cache_req-Avoid-bool-in-switch-case.patch +++ /dev/null @@ -1,49 +0,0 @@ -From b70ec63cca034ce9c638f2dcefbd4358b654d2e1 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 27 Apr 2017 10:45:30 +0200 -Subject: [PATCH 132/135] cache_req: Avoid bool in switch/case -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Pair-Programmed-With: Michal Židek - -Reviewed-by: Fabiano Fidêncio -Reviewed-by: Pavel Březina -Reviewed-by: Michal Židek ---- - src/responder/common/cache_req/cache_req_domain.c | 18 +++++++----------- - 1 file changed, 7 insertions(+), 11 deletions(-) - -diff --git a/src/responder/common/cache_req/cache_req_domain.c b/src/responder/common/cache_req/cache_req_domain.c -index 2c238c9966d322bb542fa2047313ee9e5144edee..8bf7fc6dc155123b5525127d6ee23ce98a50f490 100644 ---- a/src/responder/common/cache_req/cache_req_domain.c -+++ b/src/responder/common/cache_req/cache_req_domain.c -@@ -89,17 +89,13 @@ cache_req_domain_use_fqnames(struct sss_domain_info *domain, - * - false: in this case, the usage of fully-qualified-names will be - * done accordingly to what's set for the domain itself. - */ -- switch (head->fqnames) { -- case true: -- return true; -- case false: -- switch (enforce_non_fqnames) { -- case true: -- return false; -- case false: -- return domain->fqnames; -- } -- } -+ if (head->fqnames) { -+ return true; -+ } else if (enforce_non_fqnames) { -+ return false; -+ } else { -+ return domain->fqnames; -+ } - } - - static struct cache_req_domain * --- -2.12.2 - diff --git a/0133-ssh-tools-The-ai-structure-is-not-an-array.patch b/0133-ssh-tools-The-ai-structure-is-not-an-array.patch deleted file mode 100644 index 2718f47..0000000 --- a/0133-ssh-tools-The-ai-structure-is-not-an-array.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 08084b1179bb9fc38bc22b464b3d44907107bfd3 Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Tue, 25 Apr 2017 12:39:32 +0000 -Subject: [PATCH 133/135] ssh tools: The ai structure is not an array, -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This structure is actually a linked list, so do not mislead readers by -treating it as an array. - -Resolves: -https://pagure.io/SSSD/sssd/issue/1498 - -Merges: https://pagure.io/SSSD/sssd/pull-request/3383 - -Signed-off-by: Simo Sorce -Reviewed-by: Lukáš Slebodník ---- - src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -index adb82288d435cefccf7e23e6ed2b2c551798a7f8..310243c2fc8091f711559d4afb412e619af687ad 100644 ---- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -+++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -@@ -268,10 +268,10 @@ int main(int argc, const char **argv) - DEBUG(SSSDBG_OP_FAILURE, - "getaddrinfo() failed (%d): %s\n", ret, gai_strerror(ret)); - } else { -- host = ai[0].ai_canonname; -+ host = ai->ai_canonname; - } - } else { -- ret = getnameinfo(ai[0].ai_addr, ai[0].ai_addrlen, -+ ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, - canonhost, NI_MAXHOST, NULL, 0, NI_NAMEREQD); - if (ret) { - DEBUG(SSSDBG_OP_FAILURE, -@@ -295,7 +295,7 @@ int main(int argc, const char **argv) - if (pc_args) { - ret = connect_proxy_command(discard_const(pc_args)); - } else if (ai) { -- ret = connect_socket(ai[0].ai_family, ai[0].ai_addr, ai[0].ai_addrlen); -+ ret = connect_socket(ai->ai_family, ai->ai_addr, ai->ai_addrlen); - } else { - ret = EFAULT; - } --- -2.12.2 - diff --git a/0134-ssh-tools-Fix-issues-with-multiple-IP-addresses.patch b/0134-ssh-tools-Fix-issues-with-multiple-IP-addresses.patch deleted file mode 100644 index ff53910..0000000 --- a/0134-ssh-tools-Fix-issues-with-multiple-IP-addresses.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 5f6232c7e6d9635c1d6b6b09f799309b6094b143 Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Tue, 25 Apr 2017 14:00:15 +0000 -Subject: [PATCH 134/135] ssh tools: Fix issues with multiple IP addresses -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Cycle through all resolved address until one succeed or all fail. -This is needed for dual stack systems where either IPv4 or IPv6 are -improperly configured or selectively filtered at some point along the -route. - -Resolves: -https://pagure.io/SSSD/sssd/issue/1498 - -Merges: https://pagure.io/SSSD/sssd/pull-request/3383 - -Signed-off-by: Simo Sorce -Reviewed-by: Lukáš Slebodník ---- - src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -index 310243c2fc8091f711559d4afb412e619af687ad..b7b0c3bb66226be1c6453332a0b3af9fdf4e5a29 100644 ---- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -+++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -@@ -295,7 +295,13 @@ int main(int argc, const char **argv) - if (pc_args) { - ret = connect_proxy_command(discard_const(pc_args)); - } else if (ai) { -- ret = connect_socket(ai->ai_family, ai->ai_addr, ai->ai_addrlen); -+ /* Try all IP addresses before giving up */ -+ for (struct addrinfo *ti = ai; ti != NULL; ti = ti->ai_next) { -+ ret = connect_socket(ti->ai_family, ti->ai_addr, ti->ai_addrlen); -+ if (ret == 0) { -+ break; -+ } -+ } - } else { - ret = EFAULT; - } --- -2.12.2 - diff --git a/0135-ssh-tools-Split-connect-and-communication-phases.patch b/0135-ssh-tools-Split-connect-and-communication-phases.patch deleted file mode 100644 index bcc71c1..0000000 --- a/0135-ssh-tools-Split-connect-and-communication-phases.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 244adc327f7e29ba2c7ef60bc9f732d8fe3e68c9 Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Tue, 25 Apr 2017 19:19:13 +0000 -Subject: [PATCH 135/135] ssh tools: Split connect and communication phases -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We can fallback after a connect error, but we cannot easily fall back -once we start sending data as we may have consumed part of the buffer so -reconnecting and sending what's left would not make sense. - -Therefore we now fallback on connect errors, but we issue a hard fail if -error happens after communication has been established. - -Resolves: -https://pagure.io/SSSD/sssd/issue/1498 - -Merges: https://pagure.io/SSSD/sssd/pull-request/3383 - -Signed-off-by: Simo Sorce -Reviewed-by: Lukáš Slebodník ---- - src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 30 ++++++++++++++++++++-------- - 1 file changed, 22 insertions(+), 8 deletions(-) - -diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -index b7b0c3bb66226be1c6453332a0b3af9fdf4e5a29..976ba86b321923cecad0703214e22b0a773ef585 100644 ---- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -+++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c -@@ -40,14 +40,10 @@ - - /* connect to server using socket */ - static int --connect_socket(int family, struct sockaddr *addr, size_t addr_len) -+connect_socket(int family, struct sockaddr *addr, size_t addr_len, int *sd) - { - int flags; - int sock = -1; -- struct pollfd fds[2]; -- char buffer[BUFFER_SIZE]; -- int i; -- ssize_t res; - int ret; - - /* set O_NONBLOCK on standard input */ -@@ -85,6 +81,22 @@ connect_socket(int family, struct sockaddr *addr, size_t addr_len) - goto done; - } - -+ *sd = sock; -+ -+done: -+ if (ret != 0 && sock >= 0) close(sock); -+ return ret; -+} -+ -+static int proxy_data(int sock) -+{ -+ int flags; -+ struct pollfd fds[2]; -+ char buffer[BUFFER_SIZE]; -+ int i; -+ ssize_t res; -+ int ret; -+ - /* set O_NONBLOCK on the socket */ - flags = fcntl(sock, F_GETFL); - if (flags == -1) { -@@ -158,8 +170,7 @@ connect_socket(int family, struct sockaddr *addr, size_t addr_len) - } - - done: -- if (sock >= 0) close(sock); -- -+ close(sock); - return ret; - } - -@@ -297,8 +308,11 @@ int main(int argc, const char **argv) - } else if (ai) { - /* Try all IP addresses before giving up */ - for (struct addrinfo *ti = ai; ti != NULL; ti = ti->ai_next) { -- ret = connect_socket(ti->ai_family, ti->ai_addr, ti->ai_addrlen); -+ int socket_descriptor = -1; -+ ret = connect_socket(ti->ai_family, ti->ai_addr, ti->ai_addrlen, -+ &socket_descriptor); - if (ret == 0) { -+ ret = proxy_data(socket_descriptor); - break; - } - } --- -2.12.2 - diff --git a/0136-KCM-include-missing-header-file.patch b/0136-KCM-include-missing-header-file.patch deleted file mode 100644 index 72cb330..0000000 --- a/0136-KCM-include-missing-header-file.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 2186f88e0449f2303dc84e98c88379ccf8e55714 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 8 May 2017 11:56:55 +0200 -Subject: [PATCH] KCM: include missing header file -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -man 2 readv says that the header file "sys/uio.h" must be included -for the functions readv/writev - -Previously, "sys/uio.h" was included in "sys/socket.h" in glibc. -It worked just by a change. But it will be changed in glibc-2.26. -https://sourceware.org/bugzilla/show_bug.cgi?id=21426 - -src/responder/kcm/kcmsrv_cmd.c: In function 'kcm_iovec_op': -src/responder/kcm/kcmsrv_cmd.c:75:15: error: implicit declaration of function - 'readv'; did you mean 'read'? [-Werror=implicit-function-declaration] - -src/responder/kcm/kcmsrv_cmd.c:77:15: error: implicit declaration of function - 'writev'; did you mean 'write'? [-Werror=implicit-function-declaration] - -Reviewed-by: Fabiano Fidêncio ---- - src/responder/kcm/kcmsrv_cmd.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c -index 81015de4a91617de3dca444cde95b636c8d5c0d1..0b933f0b41e41dae1a6c14b1c1298d428c016d24 100644 ---- a/src/responder/kcm/kcmsrv_cmd.c -+++ b/src/responder/kcm/kcmsrv_cmd.c -@@ -19,6 +19,7 @@ - along with this program. If not, see . - */ - -+#include - #include - - #include "config.h" --- -2.13.0 - diff --git a/0501-libwbclient-sssd-update-interface-to-version-0.14.patch b/0501-libwbclient-sssd-update-interface-to-version-0.14.patch new file mode 100644 index 0000000..0e36604 --- /dev/null +++ b/0501-libwbclient-sssd-update-interface-to-version-0.14.patch @@ -0,0 +1,86 @@ +From 213dac21410f3c7aaeac660c5fc9c09bd1ab3d59 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 7 Jul 2017 11:15:20 +0200 +Subject: [PATCH] libwbclient-sssd: update interface to version 0.14 + +The main change is a new member of the wbcAuthErrorInfo struct. +--- + src/conf_macros.m4 | 4 ++-- + src/sss_client/libwbclient/wbclient.exports | 3 +++ + src/sss_client/libwbclient/wbclient_sssd.h | 9 +++++++-- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/src/conf_macros.m4 b/src/conf_macros.m4 +index 420997229cb3c244afd8fb21b074e43a21de0eda..bd33d3aee194c23ceac01b3729ba3152d9de9f89 100644 +--- a/src/conf_macros.m4 ++++ b/src/conf_macros.m4 +@@ -727,10 +727,10 @@ AC_DEFUN([WITH_LIBWBCLIENT], + if test x"$with_libwbclient" = xyes; then + AC_DEFINE(BUILD_LIBWBCLIENT, 1, [whether to build SSSD implementation of libwbclient]) + +- libwbclient_version="0.13" ++ libwbclient_version="0.14" + AC_SUBST(libwbclient_version) + +- libwbclient_version_info="13:0:13" ++ libwbclient_version_info="14:0:14" + AC_SUBST(libwbclient_version_info) + fi + AM_CONDITIONAL([BUILD_LIBWBCLIENT], [test x"$with_libwbclient" = xyes]) +diff --git a/src/sss_client/libwbclient/wbclient.exports b/src/sss_client/libwbclient/wbclient.exports +index 9d3c2040e7d393c0057d44864826cefc2e3f7a31..7abbaba6036c604177f247521e877c86720a1b4d 100644 +--- a/src/sss_client/libwbclient/wbclient.exports ++++ b/src/sss_client/libwbclient/wbclient.exports +@@ -150,3 +150,6 @@ WBCLIENT_0.13 { + wbcUnixIdsToSids; + wbcCtxUnixIdsToSids; + } WBCLIENT_0.12; ++ ++WBCLIENT_0.14 { ++} WBCLIENT_0.13; +diff --git a/src/sss_client/libwbclient/wbclient_sssd.h b/src/sss_client/libwbclient/wbclient_sssd.h +index 50ba7f84304df5f24a31cbbad857f22d1c70964d..f2fe8fe60e2ff55399e408056ccfbbfff044b88b 100644 +--- a/src/sss_client/libwbclient/wbclient_sssd.h ++++ b/src/sss_client/libwbclient/wbclient_sssd.h +@@ -74,9 +74,11 @@ const char *wbcErrorString(wbcErr error); + * 0.11: Extended wbcAuthenticateUserEx to provide PAC parsing + * 0.12: Added wbcCtxCreate and friends + * 0.13: Added wbcCtxUnixIdsToSids and wbcUnixIdsToSids ++ * 0.14: Added "authoritative" to wbcAuthErrorInfo ++ * Added WBC_SID_NAME_LABEL + **/ + #define WBCLIENT_MAJOR_VERSION 0 +-#define WBCLIENT_MINOR_VERSION 13 ++#define WBCLIENT_MINOR_VERSION 14 + #define WBCLIENT_VENDOR_VERSION "Samba libwbclient" + struct wbcLibraryDetails { + uint16_t major_version; +@@ -138,7 +140,8 @@ enum wbcSidType { + WBC_SID_NAME_DELETED=6, + WBC_SID_NAME_INVALID=7, + WBC_SID_NAME_UNKNOWN=8, +- WBC_SID_NAME_COMPUTER=9 ++ WBC_SID_NAME_COMPUTER=9, ++ WBC_SID_NAME_LABEL=10 + }; + + /** +@@ -316,6 +319,7 @@ struct wbcChangePasswordParams { + #define WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT 0x00000020 + #define WBC_MSV1_0_RETURN_PROFILE_PATH 0x00000200 + #define WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 0x00000800 ++#define WBC_MSV1_0_ALLOW_MSVCHAPV2 0x00010000 + + /* wbcAuthUserParams->flags */ + +@@ -418,6 +422,7 @@ struct wbcAuthErrorInfo { + char *nt_string; + int32_t pam_error; + char *display_string; ++ uint8_t authoritative; + }; + + /** +-- +2.13.2 + diff --git a/0510-BUILD-Disable-tests-with-expired-certificates.patch b/0510-BUILD-Disable-tests-with-expired-certificates.patch deleted file mode 100644 index bfb2f29..0000000 --- a/0510-BUILD-Disable-tests-with-expired-certificates.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 5ecc5585fbe2cf8b3f1efb7fe3473dbcb67ff160 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 27 Jun 2017 15:12:27 +0200 -Subject: [PATCH] BUILD: Disable tests with expired certificates - ---- - Makefile.am | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 5635a8c8fd681c4a17d003487e9ea440ab431407..c230d5e69320206778637ee3d30bedf9fe2e000a 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -273,11 +273,9 @@ if HAVE_CMOCKA - responder_cache_req-tests \ - test_sbus_opath \ - test_fo_srv \ -- pam-srv-tests \ - test_ipa_subdom_util \ - test_tools_colondb \ - test_krb5_wait_queue \ -- test_cert_utils \ - test_ldap_id_cleanup \ - test_data_provider_be \ - test_dp_request_table \ --- -2.13.0 - diff --git a/sources b/sources index d0afde1..7a1c8b1 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (sssd-1.15.2.tar.gz) = e0ed648155641261e53cff338aaa1bad72bd8051170b6f42e9c9427d46d747902a828cbbab680e16e5c248b901f01303678540ec9621f33bb8dcf60d7a4d1921 +SHA512 (sssd-1.15.3.tar.gz) = 92478205ee1b1cebc3d35b733576180db51cee8cc84d0c2cb78386924ffa90ae355b6ad9b7b51e5e5f5a7a4588764d1c7afb0673c035b1fe9b1a283beb79a428 diff --git a/sssd.spec b/sssd.spec index b348d30..b4a9d3a 100644 --- a/sssd.spec +++ b/sssd.spec @@ -25,7 +25,7 @@ %global with_kcm 1 -%global libwbc_alternatives_version 0.13 +%global libwbc_alternatives_version 0.14 %global libwbc_lib_version %{libwbc_alternatives_version}.0 %global libwbc_alternatives_suffix %nil %if 0%{?__isa_bits} == 64 @@ -34,153 +34,17 @@ Name: sssd Version: 1.15.3 -Release: 0.beta.5%{?dist} +Release: 1%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ URL: https://pagure.io/SSSD/sssd/ -Source0: https://releases.pagure.org/SSSD/sssd/%{name}-1.15.2.tar.gz -BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-1.15.2-%{release}-XXXXXX) +Source0: https://releases.pagure.org/SSSD/sssd/%{name}-%{version}.tar.gz +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) ### Patches ### -Patch0001: 0001-Updating-the-version-for-the-1.15.3-release.patch -Patch0002: 0002-UTIL-Typo-in-comment.patch -Patch0003: 0003-MAN-Mention-sssd-secrets-in-SEE-ALSO-section.patch -Patch0004: 0004-split_on_separator-move-to-a-separate-file.patch -Patch0005: 0005-util-move-string_in_list-to-util_ext.patch -Patch0006: 0006-certmap-add-new-library-libsss_certmap.patch -Patch0007: 0007-certmap-add-placeholder-for-OpenSSL-implementation.patch -Patch0008: 0008-sysdb-add-sysdb_attrs_copy.patch -Patch0009: 0009-sdap_get_users_send-new-argument-mapped_attrs.patch -Patch0010: 0010-LDAP-always-store-the-certificate-from-the-request.patch -Patch0011: 0011-sss_cert_derb64_to_ldap_filter-add-sss_certmap-suppo.patch -Patch0012: 0012-sysdb-add-certmap-related-calls.patch -Patch0013: 0013-IPA-add-certmap-support.patch -Patch0014: 0014-nss-idmap-add-sss_nss_getlistbycert.patch -Patch0015: 0015-nss-allow-larger-buffer-for-certificate-based-reques.patch -Patch0016: 0016-IPA-Add-s2n-request-to-string-function.patch -Patch0017: 0017-IPA-Enhance-debug-logging-for-ipa-s2n-operations.patch -Patch0018: 0018-UTIL-iobuf-Make-input-parameter-for-the-readonly-ope.patch -Patch0019: 0019-UTIL-Fix-a-typo-in-the-tcurl-test-tool.patch -Patch0020: 0020-UTIL-Add-SAFEALIGN_COPY_UINT8_CHECK.patch -Patch0021: 0021-UTIL-Add-utility-macro-cli_creds_get_gid.patch -Patch0022: 0022-UTIL-Add-type-specific-getsetters-to-sss_iobuf.patch -Patch0023: 0023-UTIL-krb5-principal-un-marshalling.patch -Patch0024: 0024-KCM-Initial-responder-build-and-packaging.patch -Patch0025: 0025-KCM-request-parsing-and-sending-a-reply.patch -Patch0026: 0026-KCM-Implement-an-internal-ccache-storage-and-retriev.patch -Patch0027: 0027-KCM-Add-a-in-memory-credential-storage.patch -Patch0028: 0028-KCM-Implement-KCM-server-operations.patch -Patch0029: 0029-MAN-Add-a-manual-page-for-sssd-kcm.patch -Patch0030: 0030-TESTS-Add-integration-tests-for-the-KCM-responder.patch -Patch0031: 0031-SECRETS-Create-DB-path-before-the-operation-itself.patch -Patch0032: 0032-SECRETS-Return-a-nicer-error-message-on-request-with.patch -Patch0033: 0033-SECRETS-Store-ccaches-in-secrets-for-the-KCM-respond.patch -Patch0034: 0034-TCURL-Support-HTTP-POST-for-creating-containers.patch -Patch0035: 0035-KCM-Store-ccaches-in-secrets.patch -Patch0036: 0036-KCM-Make-the-secrets-ccache-back-end-configurable-ma.patch -Patch0037: 0037-KCM-Queue-requests-by-the-same-UID.patch -Patch0038: 0038-KCM-Idle-terminate-the-responder-if-the-secrets-back.patch -Patch0039: 0039-SSSDConfig-Python-3.6-invalid-escape-sequence-deprec.patch -Patch0040: 0040-CONFIGURE-Fix-fallback-if-pkg-config-for-uuid-is-mis.patch -Patch0041: 0041-intg-fix-configure-failure-with-strict-cflags.patch -Patch0042: 0042-intg-Remove-bashism-from-intgcheck-prepare.patch -Patch0043: 0043-UTIL-Introduce-subdomain_create_conf_path.patch -Patch0044: 0044-SUBDOMAINS-Allow-use_fully_qualified_names-for-subdo.patch -Patch0045: 0045-CACHE_REQ-Descend-into-subdomains-on-lookups.patch -Patch0046: 0046-NSS-TESTS-Fix-subdomains-attribution.patch -Patch0047: 0047-NSS-TESTS-Improve-setup-teardown-for-subdomains-test.patch -Patch0048: 0048-NSS-TESTS-Include-searches-for-non-fqnames-members-o.patch -Patch0049: 0049-SYSDB-Add-methods-to-deal-with-the-domain-s-resoluti.patch -Patch0050: 0050-SYSDB-TESTS-Add-tests-for-the-domain-s-resolution-or.patch -Patch0051: 0051-IPA-Get-ipaDomainsResolutionOrder-from-ipaConfig.patch -Patch0052: 0052-IPA_SUBDOMAINS-Rename-_refresh_view-to-_refresh_view.patch -Patch0053: 0053-IPA-Get-ipaDomainsResolutionOrder-from-IPA-ID-View.patch -Patch0054: 0054-DLINKLIST-Add-DLIST_FOR_EACH_SAFE-macro.patch -Patch0055: 0055-CACHE_REQ-Make-use-of-domainResolutionOrder.patch -Patch0056: 0056-UTIL-Expose-replace_char-as-sss_replace_char.patch -Patch0057: 0057-Add-domain_resolution_order-config-option.patch -Patch0058: 0058-ssh-handle-binary-keys-correctly.patch -Patch0059: 0059-ssh-add-support-for-certificates-from-non-default-vi.patch -Patch0060: 0060-krb5-return-to-responder-that-pkinit-is-not-availabl.patch -Patch0061: 0061-IPA-add-mapped-attributes-to-user-from-trusted-domai.patch -Patch0062: 0062-IPA-lookup-AD-users-by-certificates-on-IPA-clients.patch -Patch0063: 0063-IPA-enable-AD-user-lookup-by-certificate.patch -Patch0064: 0064-CONFDB-Introduce-SSSD-domain-type-to-distinguish-POS.patch -Patch0065: 0065-CONFDB-Allow-configuring-application-sections-as-non.patch -Patch0066: 0066-CACHE_REQ-Domain-type-selection-in-cache_req.patch -Patch0067: 0067-IFP-Search-both-POSIX-and-non-POSIX-domains.patch -Patch0068: 0068-IFP-ListByName-Don-t-crash-when-no-results-are-found.patch -Patch0069: 0069-PAM-Remove-unneeded-memory-context.patch -Patch0070: 0070-PAM-Add-application-services.patch -Patch0071: 0071-SYSDB-Allow-storing-non-POSIX-users.patch -Patch0072: 0072-SYSDB-Only-generate-new-UID-in-local-domain.patch -Patch0073: 0073-LDAP-save-non-POSIX-users-in-application-domains.patch -Patch0074: 0074-LDAP-Relax-search-filters-in-application-domains.patch -Patch0075: 0075-KRB5-Authenticate-users-in-a-non-POSIX-domain-using-.patch -Patch0076: 0076-KCM-Fix-off-by-one-error-in-secrets-key-parsing.patch -Patch0077: 0077-tcurl-add-support-for-ssl-and-raw-output.patch -Patch0078: 0078-tcurl-test-refactor-so-new-options-can-be-added-more.patch -Patch0079: 0079-tcurl-test-add-support-for-raw-output.patch -Patch0080: 0080-tcurl-test-add-support-for-tls-settings.patch -Patch0081: 0081-tcurl-add-support-for-http-basic-auth.patch -Patch0082: 0082-tcurl-test-allow-to-set-custom-headers.patch -Patch0083: 0083-tcurl-test-add-support-for-client-certificate.patch -Patch0084: 0084-ci-do-not-build-secrets-on-rhel6.patch -Patch0085: 0085-build-make-curl-required-by-secrets.patch -Patch0086: 0086-secrets-use-tcurl-in-proxy-provider.patch -Patch0087: 0087-secrets-remove-http-parser-code-in-proxy-provider.patch -Patch0088: 0088-secrets-allow-to-configure-certificate-check.patch -Patch0089: 0089-secrets-support-HTTP-basic-authentication-with-proxy.patch -Patch0090: 0090-secrets-fix-debug-message.patch -Patch0091: 0091-secrets-always-add-Content-Length-header.patch -Patch0092: 0092-sss_iobuf-fix-read-shadows-a-global-declaration.patch -Patch0093: 0093-configure-fix-typo.patch -Patch0094: 0094-libsss_certmap-Accept-certificate-with-data-before-h.patch -Patch0095: 0095-BUILD-Fix-compilation-of-libsss_certmap-with-libcryp.patch -Patch0096: 0096-responders-do-not-leak-selinux-context-on-clients-de.patch -Patch0097: 0097-ipa_s2n_get_acct_info_send-provide-correct-req_input.patch -Patch0098: 0098-selinux-Do-not-fail-if-SELinux-is-not-managed.patch -Patch0099: 0099-DP-Fix-typo.patch -Patch0100: 0100-CONFDB-Fix-handling-of-enable_files_domain.patch -Patch0101: 0101-pam_test_client-add-service-and-environment-to-PAM-t.patch -Patch0102: 0102-pam_test_client-add-SSSD-getpwnam-lookup.patch -Patch0103: 0103-sss_sifp-update-method-names.patch -Patch0104: 0104-pam_test_client-add-InfoPipe-user-lookup.patch -Patch0105: 0105-sssctl-integrate-pam_test_client-into-sssctl.patch -Patch0106: 0106-i18n-adding-sssctl-files.patch -Patch0107: 0107-config-check-Message-when-sssd.conf-is-missing.patch -Patch0108: 0108-KRB5_LOCATOR-add-env-variable-to-disable-plugin.patch -Patch0109: 0109-sbus-check-connection-for-NULL-before-unregister-it.patch -Patch0110: 0110-UTIL-Use-max-15-characters-for-AD-host-UPN.patch -Patch0111: 0111-minor-typo-fixes.patch -Patch0112: 0112-SPEC-Drop-conditional-build-for-krb5_local_auth_plug.patch -Patch0114: 0114-Move-sized_output_name-and-sized_domain_name-into-re.patch -Patch0115: 0115-IFP-Use-sized_domain_name-to-format-the-groups-the-u.patch -Patch0116: 0116-SECRETS-remove-unused-variable.patch -Patch0117: 0117-IPA-Improve-DEBUG-message-if-a-group-has-no-ipaNTSec.patch -Patch0118: 0118-RESPONDER-Fallback-to-global-domain-resolution-order.patch -Patch0119: 0119-NSS-TESTS-Improve-non-fqnames-tests.patch -Patch0120: 0120-CACHE_REQ-Allow-configurationless-shortname-lookups.patch -Patch0121: 0121-CACHE_REQ_DOMAIN-Add-some-comments-to-cache_req_doma.patch -Patch0122: 0122-RESPONDER_COMMON-Improve-domaiN_resolution_order-deb.patch -Patch0123: 0123-CACHE_REQ_DOMAIN-debug-the-set-domain-resolution-ord.patch -Patch0124: 0124-LDAP-Allow-passing-a-NULL-map-to-sdap_search_bases_e.patch -Patch0125: 0125-IPA-Use-search-bases-instead-of-domain_to_basedn-whe.patch -Patch0126: 0126-CONFDB-Fix-standalone-application-domains.patch -Patch0127: 0127-utils-add-sss_domain_is_forest_root.patch -Patch0128: 0128-ad-handle-forest-root-not-listed-in-ad_enabled_domai.patch -Patch0129: 0129-overrides-add-certificates-to-mapped-attribute.patch -Patch0130: 0130-IPA-Improve-s2n-debug-message-for-missing-ipaNTSecur.patch -Patch0131: 0131-Use-correct-spelling-of-override.patch -Patch0132: 0132-cache_req-Avoid-bool-in-switch-case.patch -Patch0133: 0133-ssh-tools-The-ai-structure-is-not-an-array.patch -Patch0134: 0134-ssh-tools-Fix-issues-with-multiple-IP-addresses.patch -Patch0135: 0135-ssh-tools-Split-connect-and-communication-phases.patch -Patch0136: 0136-KCM-include-missing-header-file.patch - -Patch0502: 0502-SYSTEMD-Use-capabilities.patch -Patch0510: 0510-BUILD-Disable-tests-with-expired-certificates.patch +Patch0501: 0501-libwbclient-sssd-update-interface-to-version-0.14.patch +Patch0502: 0502-SYSTEMD-Use-capabilities.patch ### Dependencies ### @@ -256,10 +120,8 @@ BuildRequires: samba4-devel BuildRequires: libsmbclient-devel BuildRequires: systemtap-sdt-devel BuildRequires: http-parser-devel -BuildRequires: jansson-devel -BuildRequires: libcurl-devel -BuildRequires: jansson-devel BuildRequires: libuuid-devel +BuildRequires: jansson-devel BuildRequires: libcurl-devel %description @@ -280,6 +142,8 @@ License: GPLv3+ Conflicts: selinux-policy < 3.10.0-46 Conflicts: sssd < 1.10.0-8%{?dist}.beta2 # Requires +# due to ABI changes in 1.1.30/1.2.0 +Requires: libldb >= %{ldb_version} Requires: sssd-client%{?_isa} = %{version}-%{release} Recommends: libsss_sudo = %{version}-%{release} Recommends: libsss_autofs%{?_isa} = %{version}-%{release} @@ -731,7 +595,7 @@ UpdateTimestamps() { done } -%setup -q -n sssd-1.15.2 +%setup -q for p in %patches ; do %__patch -p1 -i $p @@ -759,7 +623,6 @@ autoreconf -ivf --with-syslog=journald \ --enable-sss-default-nss-plugin \ --enable-files-domain \ - --enable-ldb-version-check \ %{?with_cifs_utils_plugin_option} \ %{?enable_systemtap_opt} \ @@ -1250,8 +1113,8 @@ done %files kcm -f sssd_kcm.lang %{_libexecdir}/%{servicename}/sssd_kcm -%dir %{_sysconfdir}/krb5.conf.d -%config(noreplace) %{_sysconfdir}/krb5.conf.d/kcm_default_ccache +%dir %{_datadir}/sssd-kcm +%{_datadir}/sssd-kcm/kcm_default_ccache %{_unitdir}/sssd-kcm.socket %{_unitdir}/sssd-kcm.service %{_mandir}/man8/sssd-kcm.8* @@ -1380,6 +1243,10 @@ fi %{_libdir}/%{name}/modules/libwbclient.so %changelog +* Tue Jul 25 2017 Lukas Slebodnik - 1.15.3-1 +- New upstream release 1.15.3 +- https://docs.pagure.org/SSSD.sssd/users/relnotes/notes_1_15_3.html + * Tue Jun 27 2017 Lukas Slebodnik - 1.15.3-0.beta.5 - Rebuild with libldb-1.2.0