[SSSD] NSS: Add config option to expand homedir template format
Lukas Slebodnik
lslebodn at redhat.com
Tue Jun 3 09:29:21 UTC 2014
On (02/06/14 19:15), Jakub Hrozek wrote:
>On Mon, Jun 02, 2014 at 06:42:05PM +0200, Jakub Hrozek wrote:
>> On Mon, Jun 02, 2014 at 05:16:05PM +0200, Lukas Slebodnik wrote:
>> > On (02/06/14 10:01), Jakub Hrozek wrote:
>> > >On Mon, Jun 02, 2014 at 07:26:49AM +0200, Lukas Slebodnik wrote:
>> > >> On (01/06/14 19:23), Jakub Hrozek wrote:
>> > >> >On Wed, May 28, 2014 at 06:22:05PM +0200, Lukas Slebodnik wrote:
>> > >> >> On (27/05/14 16:32), Jakub Hrozek wrote:
>> > >> >> >On Tue, May 27, 2014 at 01:03:42PM +0200, Pavel Reichl wrote:
>> > >> >> >> On Tue, 2014-05-27 at 11:24 +0200, Lukas Slebodnik wrote:
>> > >> >> >> > O
>> > >> >> >> > >The fact of passing pointer to the same area in memory to 2 separate
>> > >> >> >> > >arguments of sss_parse_name() is what I called potential source of bugs.
>> > >> >> >> > >You said "It seems strange to me" so I hope you know what I mean.
>> > >> >> >> > It is strange, but it isn't wrong.
>> > >> >> >> > * orig_name refers to old string
>> > >> >> >> > * homedir_ctx->username will refer to new string.
>> > >> >> >> > I need to use old string in debug message if function fails.
>> > >> >> >> I missed that.
>> > >> >> >>
>> > >> >> >> I did some testing and all seems to be working, so ACK to all patches.
>> > >> >> >>
>> > >> >> >
>> > >> >> >In the third patch, you need to add the file
>> > >> >> >src/man/include/override_homedir.xml into src/man/po/po4a.cfg to make sure
>> > >> >> You ment homedir_substring.xml
>> > >> >
>> > >> >Yes :)
>> > >> >
>> > >> >>
>> > >> >> >it's processed for translations.
>> > >> >> >
>> > >> >> Added
>> > >> >>
>> > >> >> >Can you ask some native English speaker to check the contents of the
>> > >> >> >text added?
>> > >> >> >
>> > >> >> >As a side note, it would be nice to treat any refactoring as an
>> > >> >> >opportunity for adding more unit tests. Neither expand_homedir_template
>> > >> >> >nor sss_parse_name_const have any tests.
>> > >> >> The test for expand_homedir_template is in separate commit,
>> > >> >> because patches with refactoring are complicated enough.
>> > >> >>
>> > >> >> LS
>> > >> >
>> > >> >Thanks for the unit test!
>> > >> >
>> > >> >I don't have any other comments about functionality or code, just please
>> > >> >amend the man pages as Stephen suggested.
>> > done
>> >
>> > >> will do after agreement about allocation of homedir_ctx.
>> > >> I do not want to send patchset more than once :-).
>> > >>
>> > >> >
>> > >> >One more improvement might be that you don't have to allocate the
>> > >> >homedir_ctx most of the time,
>> > >> It is just a *one* allocation and reason is to have a zero initialized
>> > >> structure. If you really want to avoid one call of talloc_zero I can replace it
>> > >> with structure allocated on stack and zeroing structure with memset.
>> > >
>> > >We have a ZERO_STRUCT call precisely for this reason.
>> > >
>> > done
>> >
>> > >This patch is targeted for sssd-1-11 and we're close to the 1.11.6
>> > >deadline. If you think you can spin up another version quickly, then
>> > >please do, otherwise let's clean up the unneeded allocation in 1.12.
>> >
>> > new version attached
>> >
>> > LS
>>
>> Perfect, thank you.
>>
>> We can decide about ZERO_STRUCT/{ 0 } later, but I'd like to include
>> these patches in 1.11.6 and the deadline is looming..
>>
>> The patches work fine and look good to me.
>>
>> ACK
>
>Pushed to master:
> 59af140ef81f6d0f10db9549089998f5e05631cb
> ae0a5011e2644eaa482ea1b9e1451eff05c676b9
> 5cd660aaa885bca95ac3dca660bb77e5786d5f8e
> be7eabee6b7eb8def2441bf5de4c6d4950c155bf
>
>Can you also send a version that applies cleanly on top of sssd-1-11 ?
>(or point out patches that need backporting before yours)
Two simple patches was necessary to backport.
0001-Add-a-unit-test-for-sss_parse_name_for_domains.patch
0003-refactor-calls-of-sss_parse_name.patch
patchset for 1-11 is attached
LS
-------------- next part --------------
>From b28454b778c3da1ff3dd743cd413bbfe2ec33c7d Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 16 Apr 2014 10:55:13 +0200
Subject: [PATCH 1/6] Add a unit test for sss_parse_name_for_domains
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The code of sss_parse_name_for_domains is really complex and hard to
read. This patch adds a unit test to be able to see the function being
used.
Reviewed-by: Pavel Březina <pbrezina at redhat.com>
---
src/tests/cmocka/test_fqnames.c | 203 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 199 insertions(+), 4 deletions(-)
diff --git a/src/tests/cmocka/test_fqnames.c b/src/tests/cmocka/test_fqnames.c
index 1c628a5092630bb7ccceda8227a53ffb0f4a1349..3b3dad2c084c3d59a773f91c42332a2fdb78eaab 100644
--- a/src/tests/cmocka/test_fqnames.c
+++ b/src/tests/cmocka/test_fqnames.c
@@ -22,11 +22,45 @@
#include <popt.h>
+#include "db/sysdb_private.h"
#include "tests/cmocka/common_mock.h"
#define NAME "name"
#define DOMNAME "domname"
#define FLATNAME "flatname"
+#define PROVIDER "local"
+#define CONNNAME "conn"
+
+#define DOMNAME2 "domname2"
+#define FLATNAME2 "flatname2"
+
+#define SUBDOMNAME "subdomname"
+#define SUBFLATNAME "subflatname"
+
+static struct sss_domain_info *create_test_domain(TALLOC_CTX *mem_ctx,
+ const char *name,
+ const char *flatname,
+ struct sss_domain_info *parent,
+ struct sss_names_ctx *nctx)
+{
+ struct sss_domain_info *dom;
+
+ dom = talloc_zero(mem_ctx, struct sss_domain_info);
+ assert_non_null(dom);
+
+ /* just to make new_subdomain happy */
+ dom->sysdb = talloc_zero(dom, struct sysdb_ctx);
+ assert_non_null(dom->sysdb);
+
+ dom->name = discard_const(name);
+ dom->flat_name = discard_const(flatname);
+ dom->parent = parent;
+ dom->names = nctx;
+ dom->provider = discard_const(PROVIDER);
+ dom->conn_name = discard_const(CONNNAME);
+
+ return dom;
+}
struct fqdn_test_ctx {
struct sss_domain_info *dom;
@@ -43,10 +77,8 @@ void fqdn_test_setup(void **state)
test_ctx = talloc_zero(global_talloc_context, struct fqdn_test_ctx);
assert_non_null(test_ctx);
- test_ctx->dom = talloc_zero(test_ctx, struct sss_domain_info);
- assert_non_null(test_ctx->dom);
- test_ctx->dom->name = discard_const(DOMNAME);
- test_ctx->dom->flat_name = discard_const(FLATNAME);
+ test_ctx->dom = create_test_domain(test_ctx, DOMNAME, FLATNAME,
+ NULL, NULL);
check_leaks_push(test_ctx);
*state = test_ctx;
@@ -221,6 +253,153 @@ void test_flat_fallback(void **state)
talloc_free(test_ctx->nctx);
}
+struct parse_name_test_ctx {
+ struct sss_domain_info *dom;
+ struct sss_domain_info *subdom;
+ struct sss_names_ctx *nctx;
+};
+
+void parse_name_check(struct parse_name_test_ctx *test_ctx,
+ const char *full_name,
+ const char *default_domain,
+ const char exp_ret,
+ const char *exp_name,
+ const char *exp_domain)
+{
+ errno_t ret;
+ char *domain = NULL;
+ char *name = NULL;
+
+ check_leaks_push(test_ctx);
+ ret = sss_parse_name_for_domains(test_ctx, test_ctx->dom, default_domain,
+ full_name, &domain, &name);
+ assert_int_equal(ret, exp_ret);
+
+ if (exp_name) {
+ assert_non_null(name);
+ assert_string_equal(name, exp_name);
+ }
+
+ if (exp_domain) {
+ assert_non_null(domain);
+ assert_string_equal(domain, exp_domain);
+ }
+
+ talloc_free(name);
+ talloc_free(domain);
+ assert_true(check_leaks_pop(test_ctx) == true);
+}
+
+void parse_name_test_setup(void **state)
+{
+ struct parse_name_test_ctx *test_ctx;
+ struct sss_domain_info *dom;
+ errno_t ret;
+
+ assert_true(leak_check_setup());
+
+ test_ctx = talloc_zero(global_talloc_context, struct parse_name_test_ctx);
+ assert_non_null(test_ctx);
+
+ /* Init with an AD-style regex to be able to test flat name */
+ ret = sss_names_init_from_args(test_ctx,
+ "(((?P<domain>[^\\\\]+)\\\\(?P<name>.+$))|" \
+ "((?P<name>[^@]+)@(?P<domain>.+$))|" \
+ "(^(?P<name>[^@\\\\]+)$))",
+ "%1$s@%2$s", &test_ctx->nctx);
+ assert_int_equal(ret, EOK);
+
+ /* The setup is two domains, first one with no subdomains,
+ * second one with a single subdomain
+ */
+ dom = create_test_domain(test_ctx, DOMNAME, FLATNAME,
+ NULL, test_ctx->nctx);
+ assert_non_null(dom);
+ DLIST_ADD_END(test_ctx->dom, dom, struct sss_domain_info *);
+
+ dom = create_test_domain(test_ctx, DOMNAME2,
+ FLATNAME2, NULL, test_ctx->nctx);
+ assert_non_null(dom);
+ DLIST_ADD_END(test_ctx->dom, dom, struct sss_domain_info *);
+
+ /* Create the subdomain, but don't add it yet, we want to be able to
+ * test sss_parse_name_for_domains() signaling that domains must be
+ * discovered
+ */
+ test_ctx->subdom = new_subdomain(dom, dom, SUBDOMNAME, NULL, SUBFLATNAME,
+ NULL, false, false, NULL);
+ assert_non_null(test_ctx->subdom);
+
+ check_leaks_push(test_ctx);
+ *state = test_ctx;
+}
+
+void parse_name_test_teardown(void **state)
+{
+ struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
+ struct parse_name_test_ctx);
+
+ assert_true(check_leaks_pop(test_ctx) == true);
+ talloc_free(test_ctx);
+ assert_true(leak_check_teardown());
+}
+
+void parse_name_plain(void **state)
+{
+ struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
+ struct parse_name_test_ctx);
+ parse_name_check(test_ctx, NAME, NULL, EOK, NAME, NULL);
+}
+
+void parse_name_fqdn(void **state)
+{
+ struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
+ struct parse_name_test_ctx);
+ parse_name_check(test_ctx, NAME"@"DOMNAME, NULL, EOK, NAME, DOMNAME);
+ parse_name_check(test_ctx, NAME"@"DOMNAME2, NULL, EOK, NAME, DOMNAME2);
+}
+
+void parse_name_sub(void **state)
+{
+ struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
+ struct parse_name_test_ctx);
+ /* The subdomain name is valid, but not known */
+ parse_name_check(test_ctx, NAME"@"SUBDOMNAME, NULL, EAGAIN, NULL, NULL);
+
+ /* Link the subdomain (simulating subdom handler) and retry */
+ test_ctx->dom->subdomains = test_ctx->subdom;
+ parse_name_check(test_ctx, NAME"@"SUBDOMNAME, NULL, EOK, NAME, SUBDOMNAME);
+}
+
+void parse_name_flat(void **state)
+{
+ struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
+ struct parse_name_test_ctx);
+
+ /* Link the subdomain (simulating subdom handler) */
+ parse_name_check(test_ctx, FLATNAME"\\"NAME, NULL, EOK, NAME, DOMNAME);
+ parse_name_check(test_ctx, FLATNAME2"\\"NAME, NULL, EOK, NAME, DOMNAME2);
+
+ /* The subdomain name is valid, but not known */
+ parse_name_check(test_ctx, SUBFLATNAME"\\"NAME, NULL, EAGAIN, NULL, NULL);
+ test_ctx->dom->subdomains = test_ctx->subdom;
+ parse_name_check(test_ctx, SUBFLATNAME"\\"NAME, NULL, EOK, NAME, SUBDOMNAME);
+}
+
+void parse_name_default(void **state)
+{
+ struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
+ struct parse_name_test_ctx);
+ struct sss_domain_info *dom2;
+
+ parse_name_check(test_ctx, NAME, DOMNAME2, EOK, NAME, DOMNAME2);
+ dom2 = test_ctx->dom->next;
+
+ /* Simulate uknown default domain */
+ DLIST_REMOVE(test_ctx->dom, dom2);
+ parse_name_check(test_ctx, NAME, DOMNAME2, EAGAIN, NULL, NULL);
+}
+
void test_init_nouser(void **state)
{
struct fqdn_test_ctx *test_ctx = talloc_get_type(*state,
@@ -260,6 +439,22 @@ int main(int argc, const char *argv[])
fqdn_test_setup, fqdn_test_teardown),
unit_test_setup_teardown(test_init_nouser,
fqdn_test_setup, fqdn_test_teardown),
+
+ unit_test_setup_teardown(parse_name_plain,
+ parse_name_test_setup,
+ parse_name_test_teardown),
+ unit_test_setup_teardown(parse_name_fqdn,
+ parse_name_test_setup,
+ parse_name_test_teardown),
+ unit_test_setup_teardown(parse_name_sub,
+ parse_name_test_setup,
+ parse_name_test_teardown),
+ unit_test_setup_teardown(parse_name_flat,
+ parse_name_test_setup,
+ parse_name_test_teardown),
+ unit_test_setup_teardown(parse_name_default,
+ parse_name_test_setup,
+ parse_name_test_teardown),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
--
1.9.3
-------------- next part --------------
>From 799e5f7631976e4d8280f997f08d5d49c316b414 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Fri, 28 Feb 2014 23:42:19 +0100
Subject: [PATCH 2/6] UTIL: Add function sss_parse_name_const
Variable with type 'const char *' can be used as output argument in function
sss_parse_name, but there will be warning.
warning: passing 'const char **' to parameter of type 'char **'
discards qualifiers in nested pointer types
[-Wincompatible-pointer-types-discards-qualifiers]
---
src/tests/cmocka/test_fqnames.c | 86 +++++++++++++++++++++++++++++++++++++++++
src/util/usertools.c | 24 ++++++++++++
src/util/util.h | 4 ++
3 files changed, 114 insertions(+)
diff --git a/src/tests/cmocka/test_fqnames.c b/src/tests/cmocka/test_fqnames.c
index 3b3dad2c084c3d59a773f91c42332a2fdb78eaab..cf80777b88069b15a6f786cf41d94e7197a4b727 100644
--- a/src/tests/cmocka/test_fqnames.c
+++ b/src/tests/cmocka/test_fqnames.c
@@ -28,6 +28,7 @@
#define NAME "name"
#define DOMNAME "domname"
#define FLATNAME "flatname"
+#define SPECIALNAME "[]{}();:'|\",<.>/?!#$%^&*_+~`"
#define PROVIDER "local"
#define CONNNAME "conn"
@@ -344,11 +345,74 @@ void parse_name_test_teardown(void **state)
assert_true(leak_check_teardown());
}
+void sss_parse_name_check(struct parse_name_test_ctx *test_ctx,
+ const char *input_name,
+ const char exp_ret,
+ const char *exp_name,
+ const char *exp_domain)
+{
+ errno_t ret;
+ char *domain = NULL;
+ char *name = NULL;
+ const char *domain_const = NULL;
+ const char *name_const = NULL;
+
+
+ check_leaks_push(test_ctx);
+ ret = sss_parse_name(test_ctx, test_ctx->nctx, input_name,
+ &domain, &name);
+ assert_int_equal(ret, exp_ret);
+
+ if (exp_name) {
+ assert_non_null(name);
+ assert_string_equal(name, exp_name);
+ }
+
+ if (exp_domain) {
+ assert_non_null(domain);
+ assert_string_equal(domain, exp_domain);
+ }
+
+ talloc_zfree(name);
+ talloc_zfree(domain);
+
+ ret = sss_parse_name_const(test_ctx, test_ctx->nctx, input_name,
+ &domain_const, &name_const);
+ assert_int_equal(ret, exp_ret);
+
+ if (exp_name) {
+ assert_non_null(name_const);
+ assert_string_equal(name_const, exp_name);
+ }
+
+ if (exp_domain) {
+ assert_non_null(domain_const);
+ assert_string_equal(domain_const, exp_domain);
+ }
+
+ talloc_free(discard_const(name_const));
+ talloc_free(discard_const(domain_const));
+
+ assert_true(check_leaks_pop(test_ctx) == true);
+}
+
void parse_name_plain(void **state)
{
struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
struct parse_name_test_ctx);
+ int ret;
+
parse_name_check(test_ctx, NAME, NULL, EOK, NAME, NULL);
+
+ ret = sss_parse_name(test_ctx, test_ctx->nctx, NAME,
+ NULL, NULL);
+ assert_int_equal(ret, EOK);
+ ret = sss_parse_name_const(test_ctx, test_ctx->nctx, NAME,
+ NULL, NULL);
+ assert_int_equal(ret, EOK);
+
+ sss_parse_name_check(test_ctx, NAME, EOK, NAME, NULL);
+ sss_parse_name_check(test_ctx, SPECIALNAME, EOK, SPECIALNAME, NULL);
}
void parse_name_fqdn(void **state)
@@ -357,6 +421,11 @@ void parse_name_fqdn(void **state)
struct parse_name_test_ctx);
parse_name_check(test_ctx, NAME"@"DOMNAME, NULL, EOK, NAME, DOMNAME);
parse_name_check(test_ctx, NAME"@"DOMNAME2, NULL, EOK, NAME, DOMNAME2);
+
+ sss_parse_name_check(test_ctx, NAME"@"DOMNAME, EOK, NAME, DOMNAME);
+ sss_parse_name_check(test_ctx, NAME"@"DOMNAME2, EOK, NAME, DOMNAME2);
+ sss_parse_name_check(test_ctx, DOMNAME"\\"NAME, EOK, NAME, DOMNAME);
+ sss_parse_name_check(test_ctx, DOMNAME2"\\"NAME, EOK, NAME, DOMNAME2);
}
void parse_name_sub(void **state)
@@ -418,6 +487,20 @@ void test_init_nouser(void **state)
assert_int_not_equal(ret, EOK);
}
+void sss_parse_name_fail(void **state)
+{
+ struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
+ struct parse_name_test_ctx);
+
+ sss_parse_name_check(test_ctx, "", EINVAL, NULL, NULL);
+ sss_parse_name_check(test_ctx, "@", EINVAL, NULL, NULL);
+ sss_parse_name_check(test_ctx, "\\", EINVAL, NULL, NULL);
+ sss_parse_name_check(test_ctx, "\\"NAME, EINVAL, NULL, NULL);
+ sss_parse_name_check(test_ctx, "@"NAME, EINVAL, NULL, NULL);
+ sss_parse_name_check(test_ctx, NAME"@", EINVAL, NULL, NULL);
+ sss_parse_name_check(test_ctx, NAME"\\", EINVAL, NULL, NULL);
+}
+
int main(int argc, const char *argv[])
{
poptContext pc;
@@ -455,6 +538,9 @@ int main(int argc, const char *argv[])
unit_test_setup_teardown(parse_name_default,
parse_name_test_setup,
parse_name_test_teardown),
+ unit_test_setup_teardown(sss_parse_name_fail,
+ parse_name_test_setup,
+ parse_name_test_teardown),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
diff --git a/src/util/usertools.c b/src/util/usertools.c
index 2b36128797d276e14a993086e89b7dc50913a7f1..172095c271d183d9f2146acf6ec84e364ae6434b 100644
--- a/src/util/usertools.c
+++ b/src/util/usertools.c
@@ -385,6 +385,30 @@ int sss_parse_name(TALLOC_CTX *memctx,
return EOK;
}
+int sss_parse_name_const(TALLOC_CTX *memctx,
+ struct sss_names_ctx *snctx, const char *orig,
+ const char **_domain, const char **_name)
+{
+ char *domain;
+ char *name;
+ int ret;
+
+ ret = sss_parse_name(memctx, snctx, orig,
+ (_domain == NULL) ? NULL : &domain,
+ (_name == NULL) ? NULL : &name);
+ if (ret == EOK) {
+ if (_domain != NULL) {
+ *_domain = domain;
+ }
+
+ if (_name != NULL) {
+ *_name = name;
+ }
+ }
+
+ return ret;
+}
+
static struct sss_domain_info * match_any_domain_or_subdomain_name(
struct sss_domain_info *dom,
const char *dmatch)
diff --git a/src/util/util.h b/src/util/util.h
index cdbe0be95981983912ab08dc2c95148741de5655..35eea11531adeb0372ed2baf8d34583d5ec04431 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -277,6 +277,10 @@ int sss_parse_name(TALLOC_CTX *memctx,
struct sss_names_ctx *snctx,
const char *orig, char **_domain, char **_name);
+int sss_parse_name_const(TALLOC_CTX *memctx,
+ struct sss_names_ctx *snctx, const char *orig,
+ const char **_domain, const char **_name);
+
int sss_parse_name_for_domains(TALLOC_CTX *memctx,
struct sss_domain_info *domains,
const char *default_domain,
--
1.9.3
-------------- next part --------------
>From e43896211f70749eb9a61a00558780824fa3976d Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl at redhat.com>
Date: Tue, 28 Jan 2014 17:19:07 +0000
Subject: [PATCH 3/6] refactor calls of sss_parse_name
sss_parse_name now supports NULL as output parameters so existing calls passing
arguments which were never read were substituted by NULL.
Reviewed-by: Jakub Hrozek <jhrozek at redhat.com>
---
src/providers/krb5/krb5_common.c | 3 +--
src/providers/ldap/sdap_access.c | 3 +--
src/responder/nss/nsssrv_cmd.c | 3 +--
src/util/domain_info_utils.c | 3 +--
4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index 48cb6908061347d7fae9d58fe5ce683113cdca7f..4eafe366acf831bc648feb748f94a2b8de02ff59 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -1005,7 +1005,6 @@ errno_t krb5_get_simple_upn(TALLOC_CTX *mem_ctx, struct krb5_ctx *krb5_ctx,
char *uc_dom = NULL;
char *upn;
char *name;
- char *domname;
TALLOC_CTX *tmp_ctx = NULL;
errno_t ret;
@@ -1035,7 +1034,7 @@ errno_t krb5_get_simple_upn(TALLOC_CTX *mem_ctx, struct krb5_ctx *krb5_ctx,
/* Subdomains already have a fully qualified name, which contains
* the domain name. We need to replace it with the realm name
*/
- ret = sss_parse_name(tmp_ctx, dom->names, username, &domname, &name);
+ ret = sss_parse_name(tmp_ctx, dom->names, username, NULL, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Could not parse [%s] into name and "
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index db0e878d86f32e5eb6f30d1c99e21ed999733051..4e17090281309f3ba41651566d043bcf842d530b 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -666,7 +666,6 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
char *clean_username;
errno_t ret = ERR_INTERNAL;
char *name;
- char *domname;
req = tevent_req_create(mem_ctx, &state, struct sdap_access_filter_req_ctx);
if (req == NULL) {
@@ -720,7 +719,7 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
/* Construct the filter */
/* Subdomain users are identified by FQDN. We need to use just the username */
- ret = sss_parse_name(state, domain->names, username, &domname, &name);
+ ret = sss_parse_name(state, domain->names, username, NULL, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Could not parse [%s] into name and "
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index d273d8040affb35b3608106f12ba5f620902d428..59f2c577915b45ec089eb92f08ddeeaf4cb714d7 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -177,13 +177,12 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx,
{
const char *homedir;
char *name;
- char *domname;
errno_t ret;
homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL);
/* Subdomain users store FQDN in their name attribute */
- ret = sss_parse_name(mem_ctx, dom->names, orig_name, &domname, &name);
+ ret = sss_parse_name(mem_ctx, dom->names, orig_name, NULL, &name);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Could not parse [%s] into "
"name-value components.\n", orig_name);
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 472011c73bf3478da79ff02b54d35f0119c33018..bd45a11cdb30fb7dcc3decb2d8020a19b56efcc7 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -156,7 +156,6 @@ find_subdomain_by_object_name(struct sss_domain_info *domain,
TALLOC_CTX *tmp_ctx;
struct sss_domain_info *dom = NULL;
char *domainname = NULL;
- char *name = NULL;
errno_t ret;
tmp_ctx = talloc_new(NULL);
@@ -166,7 +165,7 @@ find_subdomain_by_object_name(struct sss_domain_info *domain,
}
ret = sss_parse_name(tmp_ctx, domain->names, object_name,
- &domainname, &name);
+ &domainname, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n",
object_name, ret, sss_strerror(ret));
--
1.9.3
-------------- next part --------------
>From f07b54e7b6527ed419980bfdae74cd9b3da6fb34 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Mon, 2 Dec 2013 13:03:33 +0100
Subject: [PATCH 4/6] NSS: Refactor expand_homedir_template
Function expand_homedir_template had lot of parameters.
After adding new expand option, all function call should be rewritten,
(usually argument NULL will be added)
This patch wraps all necessary arguments to structure.
---
src/providers/ipa/ipa_s2n_exop.c | 17 ++++++++------
src/providers/ipa/ipa_subdomains_id.c | 23 +++++++++++--------
src/responder/nss/nsssrv_cmd.c | 29 ++++++++++++++---------
src/responder/pac/pacsrv_utils.c | 11 +++++++--
src/util/sss_nss.c | 43 ++++++++++++++++++++---------------
src/util/sss_nss.h | 12 +++++++---
6 files changed, 85 insertions(+), 50 deletions(-)
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index ac240be71019caf9a03809cac1a55d839e9b529f..6bb3384b1a75e055410e97c2eac54fe1a4522b56 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -647,6 +647,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
struct resp_attrs *simple_attrs = NULL;
time_t now;
uint64_t timeout = 10*60*60; /* FIXME: find a better timeout ! */
+ struct sss_nss_homedir_ctx homedir_ctx;
const char *homedir = NULL;
struct sysdb_attrs *user_attrs = NULL;
struct sysdb_attrs *group_attrs = NULL;
@@ -737,13 +738,15 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
switch (attrs->response_type) {
case RESP_USER:
if (state->dom->subdomain_homedir) {
- homedir = expand_homedir_template(state,
- state->dom->subdomain_homedir,
- attrs->a.user.pw_name,
- attrs->a.user.pw_uid,
- NULL,
- state->dom->name,
- state->dom->flat_name);
+ ZERO_STRUCT(homedir_ctx);
+ homedir_ctx.username = attrs->a.user.pw_name;
+ homedir_ctx.uid = attrs->a.user.pw_uid;
+ homedir_ctx.domain = state->dom->name;
+ homedir_ctx.flatname = state->dom->flat_name;
+
+ homedir = expand_homedir_template(state,
+ state->dom->subdomain_homedir,
+ &homedir_ctx);
if (homedir == NULL) {
ret = ENOMEM;
goto done;
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 2d5c3b3eef644681766185cb2b41b20e226dc774..96891b34862d1ecf1436b01c6af64093c397c53b 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -366,10 +366,10 @@ get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
const char **_homedir)
{
errno_t ret;
- char *name;
- char *lc_name;
+ const char *name;
const char *homedir;
TALLOC_CTX *tmp_ctx;
+ struct sss_nss_homedir_ctx homedir_ctx;
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) {
@@ -377,22 +377,27 @@ get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
goto done;
}
- ret = sss_parse_name(tmp_ctx, dom->names, fqname, NULL, &name);
+ ZERO_STRUCT(homedir_ctx);
+
+ homedir_ctx.uid = uid;
+ homedir_ctx.domain = dom->name;
+ homedir_ctx.flatname = dom->flat_name;
+ ret = sss_parse_name_const(tmp_ctx, dom->names, fqname,
+ NULL, &name);
if (ret != EOK) {
goto done;
}
/* To be compatible with the old winbind based user lookups and IPA
* clients the user name in the home directory path will be lower-case. */
- lc_name = sss_tc_utf8_str_tolower(tmp_ctx, name);
- if (lc_name == NULL) {
- ret =ENOMEM;
+ homedir_ctx.username = sss_tc_utf8_str_tolower(tmp_ctx, name);
+ if (homedir_ctx.username == NULL) {
+ ret = ENOMEM;
goto done;
}
- homedir = expand_homedir_template(tmp_ctx, dom->subdomain_homedir, lc_name,
- uid, NULL, dom->name, dom->flat_name);
-
+ homedir = expand_homedir_template(tmp_ctx, dom->subdomain_homedir,
+ &homedir_ctx);
if (homedir == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "expand_homedir_template failed\n");
ret = ENOMEM;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 59f2c577915b45ec089eb92f08ddeeaf4cb714d7..6022d0aaf298f8faa1cdac41b6ef8dac961689c6 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -172,17 +172,18 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx,
struct ldb_message *msg,
struct nss_ctx *nctx,
struct sss_domain_info *dom,
- const char *orig_name,
- uint32_t uid)
+ struct sss_nss_homedir_ctx *homedir_ctx)
{
const char *homedir;
- char *name;
+ const char *orig_name = homedir_ctx->username;
errno_t ret;
homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL);
+ homedir_ctx->original = homedir;
/* Subdomain users store FQDN in their name attribute */
- ret = sss_parse_name(mem_ctx, dom->names, orig_name, NULL, &name);
+ ret = sss_parse_name_const(mem_ctx, dom->names, orig_name,
+ NULL, &homedir_ctx->username);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Could not parse [%s] into "
"name-value components.\n", orig_name);
@@ -194,10 +195,10 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx,
*/
if (dom->override_homedir) {
return expand_homedir_template(mem_ctx, dom->override_homedir,
- name, uid, homedir, dom->name, NULL);
+ homedir_ctx);
} else if (nctx->override_homedir) {
return expand_homedir_template(mem_ctx, nctx->override_homedir,
- name, uid, homedir, dom->name, NULL);
+ homedir_ctx);
}
if (!homedir || *homedir == '\0') {
@@ -206,12 +207,10 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx,
*/
if (dom->fallback_homedir) {
return expand_homedir_template(mem_ctx, dom->fallback_homedir,
- name, uid, homedir,
- dom->name, NULL);
+ homedir_ctx);
} else if (nctx->fallback_homedir) {
return expand_homedir_template(mem_ctx, nctx->fallback_homedir,
- name, uid, homedir,
- dom->name, NULL);
+ homedir_ctx);
}
}
@@ -318,6 +317,7 @@ static int fill_pwent(struct sss_packet *packet,
bool packet_initialized = false;
int ncret;
TALLOC_CTX *tmp_ctx = NULL;
+ struct sss_nss_homedir_ctx homedir_ctx;
if (add_domain) {
delim = 1;
@@ -378,7 +378,14 @@ static int fill_pwent(struct sss_packet *packet,
} else {
to_sized_string(&gecos, tmpstr);
}
- tmpstr = get_homedir_override(tmp_ctx, msg, nctx, dom, name.str, uid);
+
+ ZERO_STRUCT(homedir_ctx);
+
+ homedir_ctx.username = name.str;
+ homedir_ctx.uid = uid;
+ homedir_ctx.domain = dom->name;
+
+ tmpstr = get_homedir_override(tmp_ctx, msg, nctx, dom, &homedir_ctx);
if (!tmpstr) {
to_sized_string(&homedir, "/");
} else {
diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c
index 4eca1aa0ef5298a219077365076bbb3602252af4..ee72664c2df4dc8088de4075778443398146c199 100644
--- a/src/responder/pac/pacsrv_utils.c
+++ b/src/responder/pac/pacsrv_utils.c
@@ -355,6 +355,7 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
char *upn;
hash_key_t key;
hash_value_t value;
+ struct sss_nss_homedir_ctx homedir_ctx;
pwd = talloc_zero(mem_ctx, struct passwd);
if (pwd == NULL) {
@@ -441,9 +442,15 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
/* Check if there is a special homedir template for sub-domains. If not a
* fallback will be added by the NSS responder. */
if (IS_SUBDOMAIN(dom) && dom->subdomain_homedir) {
+ ZERO_STRUCT(homedir_ctx);
+
+ homedir_ctx.username = lname;
+ homedir_ctx.uid = pwd->pw_uid;
+ homedir_ctx.domain = dom->name;
+ homedir_ctx.flatname = dom->flat_name;
+
pwd->pw_dir = expand_homedir_template(pwd, dom->subdomain_homedir,
- lname, pwd->pw_uid, NULL,
- dom->name, dom->flat_name);
+ &homedir_ctx);
if (pwd->pw_dir == NULL) {
ret = ENOMEM;
goto done;
diff --git a/src/util/sss_nss.c b/src/util/sss_nss.c
index 406c95cd0f76c9e73705bc49b4261160d26bfc58..25a030c3f7f6d6cf6baff0ca9ad73f94b3cbae8e 100644
--- a/src/util/sss_nss.c
+++ b/src/util/sss_nss.c
@@ -23,9 +23,7 @@
#include "util/sss_nss.h"
char *expand_homedir_template(TALLOC_CTX *mem_ctx, const char *template,
- const char *username, uint32_t uid,
- const char *original, const char *domain,
- const char *flatname)
+ struct sss_nss_homedir_ctx *homedir_ctx)
{
char *copy;
char *p;
@@ -40,6 +38,11 @@ char *expand_homedir_template(TALLOC_CTX *mem_ctx, const char *template,
return NULL;
}
+ if (homedir_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing home directory data.\n");
+ return NULL;
+ }
+
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return NULL;
@@ -66,67 +69,71 @@ char *expand_homedir_template(TALLOC_CTX *mem_ctx, const char *template,
}
switch( *n ) {
case 'u':
- if (username == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot expand user name template "
- "because user name is empty.\n");
+ if (homedir_ctx->username == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Cannot expand user name template because user name "
+ "is empty.\n");
goto done;
}
result = talloc_asprintf_append(result, "%s%s", p,
- username);
+ homedir_ctx->username);
break;
case 'U':
- if (uid == 0) {
+ if (homedir_ctx->uid == 0) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot expand uid template "
"because uid is invalid.\n");
goto done;
}
result = talloc_asprintf_append(result, "%s%d", p,
- uid);
+ homedir_ctx->uid);
break;
case 'd':
- if (domain == NULL) {
+ if (homedir_ctx->domain == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot expand domain name "
"template because domain name "
"is empty.\n");
goto done;
}
result = talloc_asprintf_append(result, "%s%s", p,
- domain);
+ homedir_ctx->domain);
break;
case 'f':
- if (domain == NULL || username == NULL) {
+ if (homedir_ctx->domain == NULL
+ || homedir_ctx->username == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot expand fully qualified "
"name template because domain "
"or user name is empty.\n");
goto done;
}
result = talloc_asprintf_append(result, "%s%s@%s", p,
- username, domain);
+ homedir_ctx->username,
+ homedir_ctx->domain);
break;
case 'o':
- if (original == NULL) {
+ if (homedir_ctx->original == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Original home directory for %s is not available, "
- "using empty string\n", username);
+ "using empty string\n", homedir_ctx->username);
orig = "";
} else {
- orig = original;
+ orig = homedir_ctx->original;
}
result = talloc_asprintf_append(result, "%s%s", p, orig);
break;
case 'F':
- if (flatname == NULL) {
+ if (homedir_ctx->flatname == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot expand domain name "
"template because domain flat "
"name is empty.\n");
goto done;
}
- result = talloc_asprintf_append(result, "%s%s", p, flatname);
+ result = talloc_asprintf_append(result, "%s%s", p,
+ homedir_ctx->flatname);
break;
case '%':
diff --git a/src/util/sss_nss.h b/src/util/sss_nss.h
index 6dcdbaef376ffb6cc45733ce6af8aeceaabe05bb..771b9ce58db858f8cef8cac6ae3bf9fb382ef0d0 100644
--- a/src/util/sss_nss.h
+++ b/src/util/sss_nss.h
@@ -25,8 +25,14 @@
#include <sys/types.h>
#include <talloc.h>
+struct sss_nss_homedir_ctx {
+ const char *username;
+ uint32_t uid;
+ const char *original;
+ const char *domain;
+ const char *flatname;
+};
+
char *expand_homedir_template(TALLOC_CTX *mem_ctx, const char *template,
- const char *username, uint32_t uid,
- const char *original, const char *domain,
- const char *flatname);
+ struct sss_nss_homedir_ctx *homedir_ctx);
#endif
--
1.9.3
-------------- next part --------------
>From bf7eac95f6435cd2cdaff8558d5e3bd15dea4b26 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Mon, 2 Dec 2013 14:19:09 +0100
Subject: [PATCH 5/6] NSS: Add option to expand homedir template format
LDAP server can contain template for home directory instead of plain string.
This patch adds new expand option "%H", which will be replaced with value
from configuration option homedir_substring (from sssd.conf)
Resolves:
https://fedorahosted.org/sssd/ticket/1853
---
src/confdb/confdb.c | 10 ++++++++++
src/confdb/confdb.h | 3 +++
src/config/SSSDConfigTest.py | 2 ++
src/config/etc/sssd.api.conf | 2 ++
src/man/include/homedir_substring.xml | 18 ++++++++++++++++++
src/man/include/override_homedir.xml | 7 +++++++
src/man/po/po4a.cfg | 1 +
src/man/sssd-ad.5.xml | 1 +
src/man/sssd.conf.5.xml | 1 +
src/providers/ipa/ipa_s2n_exop.c | 1 +
src/providers/ipa/ipa_subdomains_id.c | 1 +
src/responder/nss/nsssrv.c | 6 ++++++
src/responder/nss/nsssrv.h | 1 +
src/responder/nss/nsssrv_cmd.c | 11 +++++++++--
src/responder/pac/pacsrv_utils.c | 1 +
src/util/domain_info_utils.c | 1 +
src/util/sss_nss.c | 11 +++++++++++
src/util/sss_nss.h | 1 +
18 files changed, 77 insertions(+), 2 deletions(-)
create mode 100644 src/man/include/homedir_substring.xml
diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index c93c6659e051cd077bb58f4ec1ed52d40e534e0e..19d8884772cec6d000703bec3f523284af198f6c 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -1114,6 +1114,16 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
}
tmp = ldb_msg_find_attr_as_string(res->msgs[0],
+ CONFDB_NSS_HOMEDIR_SUBSTRING, NULL);
+ if (tmp != NULL) {
+ domain->homedir_substr = talloc_strdup(domain, tmp);
+ if (domain->homedir_substr == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ tmp = ldb_msg_find_attr_as_string(res->msgs[0],
CONFDB_NSS_OVERRIDE_SHELL, NULL);
if (tmp != NULL) {
domain->override_shell = talloc_strdup(domain, tmp);
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index c997e6e942b0fe57effc7ca602bac9f4647ffa3e..4c0281f13018eed757717b742fda61ee9f215dd8 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -96,6 +96,8 @@
#define CONFDB_NSS_SHELL_FALLBACK "shell_fallback"
#define CONFDB_NSS_DEFAULT_SHELL "default_shell"
#define CONFDB_MEMCACHE_TIMEOUT "memcache_timeout"
+#define CONFDB_NSS_HOMEDIR_SUBSTRING "homedir_substring"
+#define CONFDB_DEFAULT_HOMEDIR_SUBSTRING "/home"
/* PAM */
#define CONFDB_PAM_CONF_ENTRY "config/pam"
@@ -217,6 +219,7 @@ struct sss_domain_info {
const char *override_homedir;
const char *fallback_homedir;
const char *subdomain_homedir;
+ const char *homedir_substr;
const char *override_shell;
const char *default_shell;
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 98b2fee63d519201047b0c576295863d59b0a37a..a539b805f8d638d75b41d7df2fb3364f0250f60f 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -521,6 +521,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'case_sensitive',
'override_homedir',
'fallback_homedir',
+ 'homedir_substring',
'override_shell',
'default_shell',
'pwd_expiration_warning',
@@ -877,6 +878,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'case_sensitive',
'override_homedir',
'fallback_homedir',
+ 'homedir_substring',
'override_shell',
'default_shell',
'pwd_expiration_warning',
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index ed65d2d7821c882bcb8e00f975961af6ef994220..9805dddfe0a93e2d8af9f528dd69dbf4d861824f 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -36,6 +36,7 @@ filter_users_in_groups = bool, None, false
pwfield = str, None, false
override_homedir = str, None, false
fallback_homedir = str, None, false
+homedir_substring = str, None, false, /home
override_shell = str, None, false
allowed_shells = list, str, false
vetoed_shells = list, str, false
@@ -112,6 +113,7 @@ override_gid = int, None, false
case_sensitive = bool, None, false
override_homedir = str, None, false
fallback_homedir = str, None, false
+homedir_substring = str, None, false
override_shell = str, None, false
default_shell = str, None, false
description = str, None, false
diff --git a/src/man/include/homedir_substring.xml b/src/man/include/homedir_substring.xml
new file mode 100644
index 0000000000000000000000000000000000000000..54d9bc94b9d6ae90e4e450691e79805c1eb83ba7
--- /dev/null
+++ b/src/man/include/homedir_substring.xml
@@ -0,0 +1,18 @@
+<varlistentry>
+ <term>homedir_substring (string)</term>
+ <listitem>
+ <para>
+ The value of this option will be used in the expansion of the
+ <emphasis>override_homedir</emphasis> option if the template
+ contains the format string <emphasis>%H</emphasis>. An LDAP
+ directory entry can directly contain this template so that this
+ option can be used to expand the home directory path for each
+ client machine (or operating system). It can be set per-domain or
+ globally in the [nss] section. A value specified in a domain
+ section will override one set in the [nss] section.
+ </para>
+ <para>
+ Default: /home
+ </para>
+ </listitem>
+</varlistentry>
diff --git a/src/man/include/override_homedir.xml b/src/man/include/override_homedir.xml
index 773d0b6616858ab5c0139033255bc60076857651..552d7eb9d3c8c4ec01cface4e062723ef9c29e1f 100644
--- a/src/man/include/override_homedir.xml
+++ b/src/man/include/override_homedir.xml
@@ -31,6 +31,13 @@
</para></listitem>
</varlistentry>
<varlistentry>
+ <term>%H</term>
+ <listitem><para>
+ The value of configure option
+ <emphasis>homedir_substring</emphasis>.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
<term>%%</term>
<listitem><para>a literal '%'</para>
</listitem>
diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg
index 7939eac754fae8318efb38069e1ccda743231f07..88f997baecbb3ecf67bd7c2a902a0541f2b0b4dc 100644
--- a/src/man/po/po4a.cfg
+++ b/src/man/po/po4a.cfg
@@ -37,3 +37,4 @@
[type:docbook] include/ldap_search_bases_experimental.xml $lang:$(builddir)/$lang/include/ldap_search_bases_experimental.xml opt:"-k 0"
[type:docbook] include/autofs_restart.xml $lang:$(builddir)/$lang/include/autofs_restart.xml opt:"-k 0"
[type:docbook] include/override_homedir.xml $lang:$(builddir)/$lang/include/override_homedir.xml opt:"-k 0"
+[type:docbook] include/homedir_substring.xml $lang:$(builddir)/$lang/include/homedir_substring.xml opt:"-k 0"
diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
index 0554317f533f2309d9fad60dfe5543f8546a6bbc..4dd657716de9c12fcdbbc6eeae8205a2dfc1b5e6 100644
--- a/src/man/sssd-ad.5.xml
+++ b/src/man/sssd-ad.5.xml
@@ -349,6 +349,7 @@ FOREST:EXAMPLE.COM:(memberOf=cn=admins,ou=groups,dc=example,dc=com)
</varlistentry>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/override_homedir.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/homedir_substring.xml" />
<varlistentry>
<term>krb5_use_enterprise_principal (boolean)</term>
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 52a1851b1355dd7277beaecc43684db70d846b88..ec58b0b9d40f7eb1f769f32749959f2a7655dafa 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -474,6 +474,7 @@
</listitem>
</varlistentry>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/override_homedir.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/homedir_substring.xml" />
<varlistentry>
<term>fallback_homedir (string)</term>
<listitem>
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 6bb3384b1a75e055410e97c2eac54fe1a4522b56..c86cf84a99fa03c010d248d7d6eebbbe4f037c5a 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -743,6 +743,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
homedir_ctx.uid = attrs->a.user.pw_uid;
homedir_ctx.domain = state->dom->name;
homedir_ctx.flatname = state->dom->flat_name;
+ homedir_ctx.config_homedir_substr = state->dom->homedir_substr;
homedir = expand_homedir_template(state,
state->dom->subdomain_homedir,
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 96891b34862d1ecf1436b01c6af64093c397c53b..c5fe1463493c3df3026ade1fbfb349316957b554 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -382,6 +382,7 @@ get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
homedir_ctx.uid = uid;
homedir_ctx.domain = dom->name;
homedir_ctx.flatname = dom->flat_name;
+ homedir_ctx.config_homedir_substr = dom->homedir_substr;
ret = sss_parse_name_const(tmp_ctx, dom->names, fqname,
NULL, &name);
if (ret != EOK) {
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index c6e7cb402d5bade600b36442d096d14d505b30a9..d74558b621eb65b4bb6a4546685fc709a0a0e241 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -291,6 +291,12 @@ static int nss_get_config(struct nss_ctx *nctx,
&nctx->default_shell);
if (ret != EOK) goto done;
+ ret = confdb_get_string(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
+ CONFDB_NSS_HOMEDIR_SUBSTRING,
+ CONFDB_DEFAULT_HOMEDIR_SUBSTRING,
+ &nctx->homedir_substr);
+ if (ret != EOK) goto done;
+
ret = 0;
done:
return ret;
diff --git a/src/responder/nss/nsssrv.h b/src/responder/nss/nsssrv.h
index b279f8a766db88d61dbbb1eb0e3c658cec723c4b..0f0a75a8f5d0eeb64d734e69ecb8b3c07922b11b 100644
--- a/src/responder/nss/nsssrv.h
+++ b/src/responder/nss/nsssrv.h
@@ -60,6 +60,7 @@ struct nss_ctx {
char *override_homedir;
char *fallback_homedir;
+ char *homedir_substr;
char **allowed_shells;
char *override_shell;
char **vetoed_shells;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 6022d0aaf298f8faa1cdac41b6ef8dac961689c6..26f61a64b609945afe4ace6957f03a635f29d859 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -190,6 +190,13 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx,
return NULL;
}
+ /* Check to see which homedir_prefix to use. */
+ if (dom->homedir_substr != NULL) {
+ homedir_ctx->config_homedir_substr = dom->homedir_substr;
+ } else if (nctx->homedir_substr != NULL) {
+ homedir_ctx->config_homedir_substr = nctx->homedir_substr;
+ }
+
/* Check whether we are unconditionally overriding the server
* for home directory locations.
*/
@@ -214,8 +221,8 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx,
}
}
- /* Return the value we got from the provider */
- return talloc_strdup(mem_ctx, homedir);
+ /* Provider can also return template, try to expand it.*/
+ return expand_homedir_template(mem_ctx, homedir, homedir_ctx);
}
static const char *get_shell_override(TALLOC_CTX *mem_ctx,
diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c
index ee72664c2df4dc8088de4075778443398146c199..52f8ec1a62a4a47640cc21273aebbf32b50fca15 100644
--- a/src/responder/pac/pacsrv_utils.c
+++ b/src/responder/pac/pacsrv_utils.c
@@ -448,6 +448,7 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
homedir_ctx.uid = pwd->pw_uid;
homedir_ctx.domain = dom->name;
homedir_ctx.flatname = dom->flat_name;
+ homedir_ctx.config_homedir_substr = dom->homedir_substr;
pwd->pw_dir = expand_homedir_template(pwd, dom->subdomain_homedir,
&homedir_ctx);
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index bd45a11cdb30fb7dcc3decb2d8020a19b56efcc7..033297a92f7b7c0441350a386a2922bda6b51a34 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -277,6 +277,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
dom->subdomain_homedir = parent->subdomain_homedir;
dom->override_shell = parent->override_shell;
dom->default_shell = parent->default_shell;
+ dom->homedir_substr = parent->homedir_substr;
if (parent->sysdb == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "Missing sysdb context in parent domain.\n");
diff --git a/src/util/sss_nss.c b/src/util/sss_nss.c
index 25a030c3f7f6d6cf6baff0ca9ad73f94b3cbae8e..8cc1416d714a2486e07fcc0c1c43f112428806c5 100644
--- a/src/util/sss_nss.c
+++ b/src/util/sss_nss.c
@@ -136,6 +136,17 @@ char *expand_homedir_template(TALLOC_CTX *mem_ctx, const char *template,
homedir_ctx->flatname);
break;
+ case 'H':
+ if (homedir_ctx->config_homedir_substr == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Cannot expand home directory substring template "
+ "substring is empty.\n");
+ goto done;
+ }
+ result = talloc_asprintf_append(result, "%s%s", p,
+ homedir_ctx->config_homedir_substr);
+ break;
+
case '%':
result = talloc_asprintf_append(result, "%s%%", p);
break;
diff --git a/src/util/sss_nss.h b/src/util/sss_nss.h
index 771b9ce58db858f8cef8cac6ae3bf9fb382ef0d0..19bf26589a9a5d76369f56ef9ecf7bedbb29e07b 100644
--- a/src/util/sss_nss.h
+++ b/src/util/sss_nss.h
@@ -31,6 +31,7 @@ struct sss_nss_homedir_ctx {
const char *original;
const char *domain;
const char *flatname;
+ const char *config_homedir_substr;
};
char *expand_homedir_template(TALLOC_CTX *mem_ctx, const char *template,
--
1.9.3
-------------- next part --------------
>From 7c5046cedb924434607ff415cff764e66d7a3a89 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Wed, 28 May 2014 12:54:52 +0200
Subject: [PATCH 6/6] TEST: Add test for expand homedir
---
src/tests/cmocka/test_utils.c | 190 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 190 insertions(+)
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index 2d9094307976bfb9f6f0f6eaabd72a141272d256..1bb095bdbb06b723b6b0b3850c9d553cbe4078dc 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -23,12 +23,26 @@
#include <popt.h>
#include "tests/cmocka/common_mock.h"
+#include "util/sss_nss.h"
#define DOM_COUNT 10
#define DOMNAME_TMPL "name_%zu.dom"
#define FLATNAME_TMPL "name_%zu"
#define SID_TMPL "S-1-5-21-1-2-%zu"
+#define MACRO_EXPAND(tok) #tok
+#define STR(tok) MACRO_EXPAND(tok)
+
+#define USERNAME "sssduser"
+#define UID 1234
+#define DOMAIN "sssddomain"
+#define ORIGINAL_HOME "/home/user"
+#define FLATNAME "flatname"
+#define HOMEDIR_SUBSTR "/mnt/home"
+
+#define DUMMY "dummy"
+#define DUMMY2 "dummy2"
+
struct dom_list_test_ctx {
size_t dom_count;
struct sss_domain_info *dom_list;
@@ -212,6 +226,178 @@ void test_sss_filter_sanitize_for_dom(void **state)
talloc_free(lc_sanitized);
}
+void check_expanded_value(TALLOC_CTX *tmp_ctx,
+ struct sss_nss_homedir_ctx *homedir_ctx,
+ const char *template, const char *exp_val)
+{
+ char *homedir;
+
+ homedir = expand_homedir_template(tmp_ctx, template, homedir_ctx);
+ if (exp_val != NULL) {
+ assert_string_equal(homedir, exp_val);
+ } else {
+ assert_null(homedir);
+ }
+
+ talloc_free(homedir);
+}
+
+void setup_homedir_ctx(void **state)
+{
+ struct sss_nss_homedir_ctx *homedir_ctx;
+
+ assert_true(leak_check_setup());
+
+ homedir_ctx= talloc_zero(global_talloc_context,
+ struct sss_nss_homedir_ctx);
+ assert_non_null(homedir_ctx);
+
+ homedir_ctx->username = USERNAME;
+ homedir_ctx->uid = UID;
+ homedir_ctx->original = ORIGINAL_HOME;
+ homedir_ctx->domain = DOMAIN;
+ homedir_ctx->flatname = FLATNAME;
+ homedir_ctx->config_homedir_substr = HOMEDIR_SUBSTR;
+
+ check_leaks_push(homedir_ctx);
+ *state = homedir_ctx;
+}
+
+void teardown_homedir_ctx(void **state)
+{
+ struct sss_nss_homedir_ctx *homedir_ctx = talloc_get_type(*state,
+ struct sss_nss_homedir_ctx);
+ if (homedir_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Type mismatch\n");
+ return;
+ }
+
+ assert_true(check_leaks_pop(homedir_ctx) == true);
+ talloc_free(homedir_ctx);
+ assert_true(leak_check_teardown());
+}
+
+void test_expand_homedir_template_NULL(void **state)
+{
+ TALLOC_CTX *tmp_ctx;
+ char *homedir;
+ struct sss_nss_homedir_ctx *homedir_ctx;
+
+ /* following format strings requires data in homedir_ctx */
+ const char *format_strings[] = { "%u", "%U", "%d", "%f", "%F", "%H",
+ NULL };
+ int i;
+
+ tmp_ctx = talloc_new(NULL);
+ assert_non_null(tmp_ctx);
+
+ homedir_ctx = talloc_zero(tmp_ctx, struct sss_nss_homedir_ctx);
+ assert_non_null(homedir_ctx);
+
+ homedir = expand_homedir_template(tmp_ctx, NULL, NULL);
+ assert_null(homedir);
+
+ homedir = expand_homedir_template(tmp_ctx, "template", NULL);
+ assert_null(homedir);
+
+ /* missing data in homedir_ctx */
+ check_expanded_value(tmp_ctx, homedir_ctx, "%%", "%");
+ check_expanded_value(tmp_ctx, homedir_ctx, "%o", "");
+
+ for (i = 0; format_strings[i] != NULL; ++i) {
+ check_expanded_value(tmp_ctx, homedir_ctx, format_strings[i], NULL);
+ }
+
+ /* flatname requires domain and username */
+ homedir_ctx->username = DUMMY;
+ check_expanded_value(tmp_ctx, homedir_ctx, "%f", NULL);
+
+ homedir_ctx->username = NULL;
+ homedir_ctx->domain = DUMMY;
+ check_expanded_value(tmp_ctx, homedir_ctx, "%f", NULL);
+
+ /* test unknown format string */
+ check_expanded_value(tmp_ctx, homedir_ctx, "%x", NULL);
+
+ /* test malformed format string */
+ check_expanded_value(tmp_ctx, homedir_ctx, "%", NULL);
+
+ talloc_free(tmp_ctx);
+}
+
+void test_expand_homedir_template(void **state)
+{
+ struct sss_nss_homedir_ctx *homedir_ctx = talloc_get_type(*state,
+ struct sss_nss_homedir_ctx);
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(NULL);
+ assert_non_null(tmp_ctx);
+
+ /* string without template */
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY, DUMMY);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%u", USERNAME);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%u", DUMMY USERNAME);
+ check_expanded_value(tmp_ctx, homedir_ctx, "%u"DUMMY, USERNAME DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%u"DUMMY2,
+ DUMMY USERNAME DUMMY2);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%U", STR(UID));
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%U", DUMMY STR(UID));
+ check_expanded_value(tmp_ctx, homedir_ctx, "%U"DUMMY, STR(UID) DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%U"DUMMY2,
+ DUMMY STR(UID) DUMMY2);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%d", DOMAIN);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%d", DUMMY DOMAIN);
+ check_expanded_value(tmp_ctx, homedir_ctx, "%d"DUMMY, DOMAIN DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%d"DUMMY2,
+ DUMMY DOMAIN DUMMY2);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%f", USERNAME"@"DOMAIN);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%f",
+ DUMMY USERNAME"@"DOMAIN);
+ check_expanded_value(tmp_ctx, homedir_ctx, "%f"DUMMY,
+ USERNAME"@"DOMAIN DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%f"DUMMY2,
+ DUMMY USERNAME"@"DOMAIN DUMMY2);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%o", ORIGINAL_HOME);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%o", DUMMY ORIGINAL_HOME);
+ check_expanded_value(tmp_ctx, homedir_ctx, "%o"DUMMY, ORIGINAL_HOME DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%o"DUMMY2,
+ DUMMY ORIGINAL_HOME DUMMY2);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%F", FLATNAME);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%F", DUMMY FLATNAME);
+ check_expanded_value(tmp_ctx, homedir_ctx, "%F"DUMMY, FLATNAME DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%F"DUMMY2,
+ DUMMY FLATNAME DUMMY2);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%H", HOMEDIR_SUBSTR);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%H",
+ DUMMY HOMEDIR_SUBSTR);
+ check_expanded_value(tmp_ctx, homedir_ctx, "%H"DUMMY,
+ HOMEDIR_SUBSTR DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%H"DUMMY2,
+ DUMMY HOMEDIR_SUBSTR DUMMY2);
+
+ check_expanded_value(tmp_ctx, homedir_ctx, "%%", "%");
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%%", DUMMY"%");
+ check_expanded_value(tmp_ctx, homedir_ctx, "%%"DUMMY, "%"DUMMY);
+ check_expanded_value(tmp_ctx, homedir_ctx, DUMMY"%%"DUMMY2,
+ DUMMY"%"DUMMY2);
+
+ /* test all format strings */
+ check_expanded_value(tmp_ctx, homedir_ctx,
+ DUMMY"/%u/%U/%d/%f/%o/%F/%%/%H/"DUMMY2,
+ DUMMY"/"USERNAME"/" STR(UID) "/"DOMAIN"/"
+ USERNAME"@"DOMAIN"/"ORIGINAL_HOME"/"FLATNAME"/%/"
+ HOMEDIR_SUBSTR"/"DUMMY2);
+ talloc_free(tmp_ctx);
+}
+
int main(int argc, const char *argv[])
{
poptContext pc;
@@ -232,6 +418,10 @@ int main(int argc, const char *argv[])
unit_test_setup_teardown(test_sss_filter_sanitize_for_dom,
setup_dom_list, teardown_dom_list),
+
+ unit_test(test_expand_homedir_template_NULL),
+ unit_test_setup_teardown(test_expand_homedir_template,
+ setup_homedir_ctx, teardown_homedir_ctx),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
--
1.9.3
More information about the sssd-devel
mailing list