cli_credentials: add a helper to parse user or group names
authorAlexander Bokovoy <ab@samba.org>
Wed, 4 Nov 2020 12:00:58 +0000 (14:00 +0200)
committerAlexander Bokovoy <ab@samba.org>
Wed, 4 Nov 2020 14:59:34 +0000 (14:59 +0000)
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 <ab@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
auth/credentials/credentials.c
auth/credentials/credentials.h
auth/credentials/tests/test_creds.c

index a8d25278e9dbd6369eb6a90889d422e27b9cacc7..53bba78176bbfd0d751287ba6bbac0d840f6e48f 100644 (file)
@@ -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
index f468b8558dd6f2132bf1e738343ddb7aef609aaf..7c7120b9f554005166b635a3c00b48ff3c5dc5da 100644 (file)
@@ -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,
index 541ecc7b264519c0f0452eedf114560fa752f3fd..38550d6ecf9fc8c95373bc118e84a477e034ea2e 100644 (file)
@@ -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) {