From 00f4262ed0b22f6e333e5a29c5590b62c783905c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 4 Nov 2020 14:00:58 +0200 Subject: cli_credentials: add a helper to parse user or group names cli_credentials_parse_string() parses a string specified for -U option in command line tools. It has a side-effect that '%' character is always considered to be a separator after which a password is specified. Active Directory does allow to create user or group objects with '%' in the name. It means cli_credentials_parse_string() will not be able to properly parse such name. Introduce cli_credentials_parse_name() for the cases when a password is not expected in the name and call to cli_credentials_parse_name() from cli_credentials_parse_string(). Test cli_credentials_parse_name() with its intended use in lookup_name() refactoring. Signed-off-by: Alexander Bokovoy Reviewed-by: Andreas Schneider Reviewed-by: Stefan Metzmacher --- auth/credentials/credentials.c | 18 ++++++++++++ auth/credentials/credentials.h | 1 + auth/credentials/tests/test_creds.c | 56 +++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index a8d25278e9d..53bba78176b 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -836,6 +836,24 @@ _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials, cli_credentials_set_password(credentials, p+1, obtained); } + cli_credentials_parse_name(credentials, uname, obtained); +} + +/** + * Given a string, parse it into a domain, username and realm fields + * + * The format accepted is [domain\\]user or user[@realm] + * + * @param credentials Credentials structure on which to set the components + * @param data the string containing the username, prefixed or suffixed with domain or realm + * @param obtained This enum describes how 'specified' this credential name is. + */ + +_PUBLIC_ void cli_credentials_parse_name(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained) +{ + char *uname, *p; + + uname = talloc_strdup(credentials, data); if ((p = strchr_m(uname,'@'))) { /* * We also need to set username and domain diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index f468b8558dd..7c7120b9f55 100644 --- a/auth/credentials/credentials.h +++ b/auth/credentials/credentials.h @@ -155,6 +155,7 @@ bool cli_credentials_set_password(struct cli_credentials *cred, enum credentials_obtained obtained); struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx); void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained); +void cli_credentials_parse_name(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained); struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, TALLOC_CTX *mem_ctx); struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred, diff --git a/auth/credentials/tests/test_creds.c b/auth/credentials/tests/test_creds.c index 541ecc7b264..38550d6ecf9 100644 --- a/auth/credentials/tests/test_creds.c +++ b/auth/credentials/tests/test_creds.c @@ -197,6 +197,61 @@ static void torture_creds_parse_string(void **state) assert_int_equal(creds->password_obtained, CRED_SPECIFIED); } +static void _parse_name_as_lookup_name(TALLOC_CTX *mem_ctx, + const char *full_name, + const char *expected_name, + const char *expected_domain, + const char *expected_realm) +{ + struct cli_credentials *creds = NULL; + + creds = cli_credentials_init(mem_ctx); + assert_non_null(creds); + + cli_credentials_parse_name(creds, full_name, CRED_SPECIFIED); + + if (expected_name == NULL) { + assert_null(cli_credentials_get_username(creds)); + } else { + assert_string_equal(cli_credentials_get_username(creds), expected_name); + } + + if (expected_domain == NULL) { + assert_null(cli_credentials_get_domain(creds)); + } else { + assert_string_equal(cli_credentials_get_domain(creds), expected_domain); + } + + if (expected_realm == NULL) { + assert_null(cli_credentials_get_realm(creds)); + } else { + assert_string_equal(cli_credentials_get_realm(creds), expected_realm); + } + + TALLOC_FREE(creds); + +} + +static void torture_creds_parse_name(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + + _parse_name_as_lookup_name(mem_ctx, "XXL\\", + "", "XXL", NULL); + + _parse_name_as_lookup_name(mem_ctx, "XXL\\wurst", + "wurst", "XXL", NULL); + + _parse_name_as_lookup_name(mem_ctx, "wurst@brot.realm", + "wurst", "", "BROT.REALM"); + + _parse_name_as_lookup_name(mem_ctx, "wur%t", + "wur%t", NULL, NULL); + + _parse_name_as_lookup_name(mem_ctx, "wurst", + "wurst", NULL, NULL); +} + int main(int argc, char *argv[]) { int rc; @@ -206,6 +261,7 @@ int main(int argc, char *argv[]) cmocka_unit_test(torture_creds_guess), cmocka_unit_test(torture_creds_anon_guess), cmocka_unit_test(torture_creds_parse_string), + cmocka_unit_test(torture_creds_parse_name), }; if (argc == 2) { -- cgit v1.2.1