summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-03-24 03:32:25 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:11:15 -0500
commit038c4c4c6a4f6039e0436134de1d9c1e14c444d8 (patch)
tree0a1144858e9c920a0a13357dc8ccaf77935bebfb
parentd600b78c33cd4950073d2848f1a9a0f17f17d20e (diff)
downloadsamba-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.h10
-rw-r--r--source4/lib/cmdline/popt_common.c8
-rw-r--r--source4/lib/credentials.c107
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;