diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-03-24 03:32:25 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:11:15 -0500 |
commit | 038c4c4c6a4f6039e0436134de1d9c1e14c444d8 (patch) | |
tree | 0a1144858e9c920a0a13357dc8ccaf77935bebfb | |
parent | d600b78c33cd4950073d2848f1a9a0f17f17d20e (diff) | |
download | samba-038c4c4c6a4f6039e0436134de1d9c1e14c444d8.tar.gz samba-038c4c4c6a4f6039e0436134de1d9c1e14c444d8.tar.bz2 samba-038c4c4c6a4f6039e0436134de1d9c1e14c444d8.zip |
r6024: Some of the ordering constraints on the popt callbacks were getting
painful, so don't call lp_*() functions until the post stage (rather
than in the cli_credentails_init(), which is called in the pre stage),
and don't open the secrets.ldb looking for the machine account details
until we actually need them (well after popt is done, and we know we have the other things right).
Set the domain and realm, as well as the account and password for -P
(fetch machine password) operation.
Allow NETLOGON credentials to be stored in this structure - will allow
SCHANNEL to be made more generic.
Clarify why we don't do special checks for NULL pointers, particularly
in the anonymous check (it indicates a programmer error, not a
run-time condition).
Also make lib/credentials.c a little more consistant.
Andrew Bartlett
(This used to be commit 730e6056b730c15008772c30cd6f7c03fb6b7e5f)
-rw-r--r-- | source4/include/credentials.h | 10 | ||||
-rw-r--r-- | source4/lib/cmdline/popt_common.c | 8 | ||||
-rw-r--r-- | source4/lib/credentials.c | 107 |
3 files changed, 100 insertions, 25 deletions
diff --git a/source4/include/credentials.h b/source4/include/credentials.h index 7b223dad5a..d7bf8997eb 100644 --- a/source4/include/credentials.h +++ b/source4/include/credentials.h @@ -4,6 +4,7 @@ Client credentials structure Copyright (C) Jelmer Vernooij 2004-2005 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 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 @@ -49,5 +50,14 @@ struct cli_credentials { const char *(*domain_cb) (struct cli_credentials *); const char *(*realm_cb) (struct cli_credentials *); + /* Private handle for the callback routines to use */ void *priv_data; + + struct creds_CredentialState *netlogon_creds; + + /* We are flagged to get machine account details from the + * secrets.ldb when we are asked for a username or password */ + + BOOL machine_account_pending; }; + diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c index 50e07d95e9..68f491a188 100644 --- a/source4/lib/cmdline/popt_common.c +++ b/source4/lib/cmdline/popt_common.c @@ -212,10 +212,10 @@ static void popt_common_credentials_callback(poptContext con, break; case 'P': - { - cli_credentials_set_machine_account(cmdline_credentials); - } - /* machine accounts only work with kerberos */ + /* Later, after this is all over, get the machine account details from the secrets.ldb */ + cli_credentials_set_machine_account_pending(cmdline_credentials); + + /* machine accounts only work with kerberos (fall though)*/ case 'k': #ifndef HAVE_KRB5 diff --git a/source4/lib/credentials.c b/source4/lib/credentials.c index e98e261b05..da0bc4236f 100644 --- a/source4/lib/credentials.c +++ b/source4/lib/credentials.c @@ -34,15 +34,15 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) return cred; } - cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); - cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); - cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); - return cred; } const char *cli_credentials_get_username(struct cli_credentials *cred) { + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + if (cred->username_obtained == CRED_CALLBACK) { cred->username = cred->username_cb(cred); cred->username_obtained = CRED_SPECIFIED; @@ -64,6 +64,10 @@ BOOL cli_credentials_set_username(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_password(struct cli_credentials *cred) { + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + if (cred->password_obtained == CRED_CALLBACK) { cred->password = cred->password_cb(cred); cred->password_obtained = CRED_SPECIFIED; @@ -85,6 +89,10 @@ BOOL cli_credentials_set_password(struct cli_credentials *cred, const char *val, const char *cli_credentials_get_domain(struct cli_credentials *cred) { + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); + } + if (cred->domain_obtained == CRED_CALLBACK) { cred->domain = cred->domain_cb(cred); cred->domain_obtained = CRED_SPECIFIED; @@ -107,8 +115,8 @@ BOOL cli_credentials_set_domain(struct cli_credentials *cred, const char *val, e const char *cli_credentials_get_realm(struct cli_credentials *cred) { - if (cred == NULL) { - return NULL; + if (cred->machine_account_pending) { + cli_credentials_set_machine_account(cred); } if (cred->realm_obtained == CRED_CALLBACK) { @@ -119,6 +127,14 @@ const char *cli_credentials_get_realm(struct cli_credentials *cred) return cred->realm; } +char *cli_credentials_get_principal(struct cli_credentials *cred, + TALLOC_CTX *mem_ctx) +{ + return talloc_asprintf(mem_ctx, "%s@%s", + cli_credentials_get_username(cred), + cli_credentials_get_realm(cred)); +} + BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) { if (obtained >= cred->realm_obtained) { @@ -132,10 +148,6 @@ BOOL cli_credentials_set_realm(struct cli_credentials *cred, const char *val, en const char *cli_credentials_get_workstation(struct cli_credentials *cred) { - if (cred == NULL) { - return NULL; - } - if (cred->workstation_obtained == CRED_CALLBACK) { cred->workstation = cred->workstation_cb(cred); cred->workstation_obtained = CRED_SPECIFIED; @@ -287,10 +299,20 @@ void cli_credentials_parse_string(struct cli_credentials *credentials, const cha cli_credentials_set_username(credentials, uname, obtained); } +/* Initialise defaults from the lp_*() functions */ +void cli_credentials_set_conf(struct cli_credentials *cred) +{ + cli_credentials_set_domain(cred, lp_workgroup(), CRED_GUESSED); + cli_credentials_set_workstation(cred, lp_netbios_name(), CRED_GUESSED); + cli_credentials_set_realm(cred, lp_realm(), CRED_GUESSED); +} + void cli_credentials_guess(struct cli_credentials *cred) { char *p; + cli_credentials_set_conf(cred); + if (getenv("LOGNAME")) { cli_credentials_set_username(cred, getenv("LOGNAME"), CRED_GUESSED); } @@ -319,9 +341,9 @@ void cli_credentials_guess(struct cli_credentials *cred) } } -NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) +NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred) { - TALLOC_CTX *mem_ctx = talloc_named(creds, 0, "cli_credentials fetch machine password"); + TALLOC_CTX *mem_ctx; struct ldb_context *ldb; int ldb_ret; @@ -330,15 +352,24 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) const char *attrs[] = { "secret", "samAccountName", + "flatname", + "realm", NULL }; const char *machine_account; const char *password; + const char *domain; + const char *realm; + /* ok, we are going to get it now, don't recurse back here */ + cred->machine_account_pending = False; + + mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password"); /* Local secrets are stored in secrets.ldb */ ldb = secrets_db_connect(mem_ctx); if (!ldb) { + DEBUG(1, ("Could not open secrets.ldb\n")); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -346,13 +377,15 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) ldb_ret = gendb_search(ldb, mem_ctx, base_dn, &msgs, attrs, SECRETS_PRIMARY_DOMAIN_FILTER, - cli_credentials_get_domain(creds)); + cli_credentials_get_domain(cred)); if (ldb_ret == 0) { DEBUG(1, ("Could not find join record to domain: %s\n", - lp_workgroup())); + cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } else if (ldb_ret != 1) { + DEBUG(1, ("Found more than one (%d) join records to domain: %s\n", + ldb_ret, cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -360,7 +393,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) password = ldb_msg_find_string(msgs[0], "secret", NULL); if (!password) { DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n", - cli_credentials_get_domain(creds))); + cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -368,18 +401,47 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *creds) machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL); if (!machine_account) { DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n", - cli_credentials_get_domain(creds))); + cli_credentials_get_domain(cred))); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - cli_credentials_set_username(creds, machine_account, CRED_SPECIFIED); - cli_credentials_set_password(creds, password, CRED_SPECIFIED); + domain = ldb_msg_find_string(msgs[0], "flatname", NULL); + if (domain) { + cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); + } + + realm = ldb_msg_find_string(msgs[0], "realm", NULL); + if (realm) { + cli_credentials_set_realm(cred, realm, CRED_SPECIFIED); + } + + cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); + cli_credentials_set_password(cred, password, CRED_SPECIFIED); talloc_free(mem_ctx); return NT_STATUS_OK; } +void cli_credentials_set_machine_account_pending(struct cli_credentials *cred) +{ + cred->machine_account_pending = True; +} +/* Attach NETLOGON credentials for use with SCHANNEL */ + +void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, + struct creds_CredentialState *netlogon_creds) +{ + cred->netlogon_creds = talloc_reference(cred, netlogon_creds); +} + +/* Return attached NETLOGON credentials */ + +struct creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred) +{ + return cred->netlogon_creds; +} + /* Fill in a credentails structure as anonymous */ void cli_credentials_set_anonymous(struct cli_credentials *cred) { @@ -388,11 +450,14 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred) cli_credentials_set_password(cred, NULL, CRED_SPECIFIED); } -BOOL cli_credentials_is_anonymous(struct cli_credentials *credentials) +BOOL cli_credentials_is_anonymous(struct cli_credentials *cred) { - const char *username = cli_credentials_get_username(credentials); + const char *username = cli_credentials_get_username(cred); - if (!username || !username[0]) + /* Yes, it is deliberate that we die if we have a NULL pointer + * here - anymous is "", not NULL, which is 'never specified, + * never guessed', ie programmer bug */ + if (!username[0]) return True; return False; |