summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2003-08-19 22:47:10 +0000
committerAndrew Bartlett <abartlet@samba.org>2003-08-19 22:47:10 +0000
commitf1be3a5c5defc2df94550b90b7dd2ed4ab0cb1f2 (patch)
treee79dfbfedf8fbdaed7873463939fbe28c2b07070 /source3
parentec8b32df568260446b815619815e94a7e1b3fd4e (diff)
downloadsamba-f1be3a5c5defc2df94550b90b7dd2ed4ab0cb1f2.tar.gz
samba-f1be3a5c5defc2df94550b90b7dd2ed4ab0cb1f2.tar.bz2
samba-f1be3a5c5defc2df94550b90b7dd2ed4ab0cb1f2.zip
- Make 'net' use a single funciton for setting the 'use machine account' code.
- Make winbindd try to use kerberos for connections to DCs, so that it can access RA=2 servers, particularly for netlogon. - Make rpcclient follow the new flags for the NETLOGON pipe - Make all the code that uses schannel use the centralised functions for doing so. Andrew Bartlett (This used to be commit 96b4187963cedcfe158ff02868929b8cf81c6ebf)
Diffstat (limited to 'source3')
-rw-r--r--source3/libads/krb5_setpw.c15
-rw-r--r--source3/libsmb/trusts_util.c9
-rw-r--r--source3/nsswitch/winbindd_cm.c90
-rw-r--r--source3/rpcclient/rpcclient.c2
-rw-r--r--source3/utils/net.c38
-rw-r--r--source3/utils/net_ads.c39
6 files changed, 138 insertions, 55 deletions
diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c
index d1da118bb8..9cf15221a8 100644
--- a/source3/libads/krb5_setpw.c
+++ b/source3/libads/krb5_setpw.c
@@ -664,25 +664,22 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
* @return status of password change
**/
ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
- const char *hostname,
+ const char *machine_account,
const char *password)
{
ADS_STATUS status;
- char *host = strdup(hostname);
- char *principal;
-
- strlower_m(host);
+ char *principal = NULL;
/*
- we need to use the '$' form of the name here, as otherwise the
- server might end up setting the password for a user instead
+ we need to use the '$' form of the name here (the machine account name),
+ as otherwise the server might end up setting the password for a user
+ instead
*/
- asprintf(&principal, "%s$@%s", host, ads->config.realm);
+ asprintf(&principal, "%s@%s", machine_account, ads->config.realm);
status = ads_krb5_set_password(ads->auth.kdc_server, principal,
password, ads->auth.time_offset);
- free(host);
free(principal);
return status;
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index 610f4b3c03..4e02b29f92 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -35,16 +35,15 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
uint32 sec_channel_type)
{
NTSTATUS result;
- uint32 neg_flags = 0x000001ff;
- result = cli_nt_setup_creds(cli, sec_channel_type, orig_trust_passwd_hash, &neg_flags, 2);
-
- if (!NT_STATUS_IS_OK(result)) {
+ /* ensure that schannel uses the right domain */
+ fstrcpy(cli->domain, lp_workgroup());
+ if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, sec_channel_type, orig_trust_passwd_hash))) {
DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
nt_errstr(result)));
return result;
}
-
+
result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
if (!NT_STATUS_IS_OK(result)) {
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index f07117b5ab..eaf10168db 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -116,7 +116,8 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
struct winbindd_cm_conn *new_conn)
{
NTSTATUS result;
- char *ipc_username, *ipc_domain, *ipc_password;
+ char *machine_password;
+ char *machine_krb5_principal, *ipc_username, *ipc_domain, *ipc_password;
struct in_addr dc_ip;
int i;
BOOL retry = True;
@@ -137,10 +138,15 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
/* Initialise SMB connection */
- cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
+ /* grab stored passwords */
+ machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+
+ if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) {
+ SAFE_FREE(machine_password);
+ return NT_STATUS_NO_MEMORY;
+ }
- DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
- new_conn->controller, global_myname(), ipc_domain, ipc_username));
+ cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
for (i = 0; retry && (i < 3); i++) {
BOOL got_mutex;
@@ -150,12 +156,75 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
continue;
}
- result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller,
- &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain,
- ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK,
- Undefined, &retry);
-
- secrets_named_mutex_release(new_conn->controller);
+ new_conn->cli = NULL;
+ result = cli_start_connection(&new_conn->cli, global_myname(),
+ new_conn->controller,
+ &dc_ip, 0, Undefined,
+ CLI_FULL_CONNECTION_USE_KERBEROS,
+ &retry);
+
+ if (NT_STATUS_IS_OK(result)) {
+ if ((lp_security() == SEC_ADS)
+ && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) {
+ new_conn->cli->use_kerberos = True;
+ DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n",
+ new_conn->controller, global_myname(), machine_krb5_principal));
+
+ if (!cli_session_setup_spnego(new_conn->cli, machine_krb5_principal,
+ machine_password,
+ domain)) {
+ result = cli_nt_error(new_conn->cli);
+ DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
+ if (NT_STATUS_IS_OK(result))
+ result = NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ new_conn->cli->use_kerberos = False;
+ if (!NT_STATUS_IS_OK(result)
+ && new_conn->cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
+ DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
+ new_conn->controller, global_myname(), ipc_domain, ipc_username));
+
+ if (!cli_session_setup(new_conn->cli, ipc_username,
+ ipc_password, strlen(ipc_password)+1,
+ ipc_password, strlen(ipc_password)+1,
+ domain)) {
+ result = cli_nt_error(new_conn->cli);
+ DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
+ if (NT_STATUS_IS_OK(result))
+ result = NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ if (!cli_session_setup(new_conn->cli, "", NULL, 0,
+ NULL, 0,
+ "")) {
+ result = cli_nt_error(new_conn->cli);
+ DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
+ if (NT_STATUS_IS_OK(result))
+ result = NT_STATUS_UNSUCCESSFUL;
+ }
+
+ }
+ if (NT_STATUS_IS_OK(result) && !cli_send_tconX(new_conn->cli, "IPC$", "IPC",
+ "", 0)) {
+ result = cli_nt_error(new_conn->cli);
+ DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
+ cli_shutdown(new_conn->cli);
+ if (NT_STATUS_IS_OK(result)) {
+ result = NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+
+ if (NT_STATUS_IS_OK(result)) {
+ struct ntuser_creds creds;
+ init_creds(&creds, ipc_username, ipc_domain, ipc_password);
+ cli_init_creds(new_conn->cli, &creds);
+ }
+
+ if (got_mutex)
+ secrets_named_mutex_release(new_conn->controller);
if (NT_STATUS_IS_OK(result))
break;
@@ -164,6 +233,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
SAFE_FREE(ipc_username);
SAFE_FREE(ipc_domain);
SAFE_FREE(ipc_password);
+ SAFE_FREE(machine_password);
if (!NT_STATUS_IS_OK(result)) {
add_failed_connection_entry(domain, new_conn->controller, result);
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
index 6efa9874a0..515489292b 100644
--- a/source3/rpcclient/rpcclient.c
+++ b/source3/rpcclient/rpcclient.c
@@ -522,6 +522,8 @@ static NTSTATUS do_cmd(struct cli_state *cli,
/* some of the DsXXX commands use the netlogon pipe */
if (lp_client_schannel() && (cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) {
+ /* The 7 here seems to be required to get Win2k not to downgrade us
+ to NT4. Actually, anything other than 1ff would seem to do... */
uint32 neg_flags = 0x000001ff;
uint32 sec_channel_type;
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 8f6b09a3fa..c49c77dd50 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -181,6 +181,27 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
}
}
+/****************************************************************************
+ Use the local machine's password for this session
+****************************************************************************/
+int net_use_machine_password(void)
+{
+ char *user_name = NULL;
+
+ if (!secrets_init()) {
+ d_printf("ERROR: Unable to open secrets database\n");
+ exit(1);
+ }
+
+ user_name = NULL;
+ opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
+ if (asprintf(&user_name, "%s$@%s", global_myname(), lp_realm()) == -1) {
+ return -1;
+ }
+ opt_user_name = user_name;
+ return 0;
+}
+
BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_name)
{
@@ -321,7 +342,7 @@ static int net_join(int argc, const char **argv)
if (net_ads_join(argc, argv) == 0)
return 0;
else
- d_printf("ADS join did not work, trying RPC...\n");
+ d_printf("ADS join did not work, falling back to RPC...\n");
}
return net_rpc_join(argc, argv);
}
@@ -649,23 +670,10 @@ static struct functable net_func[] = {
sec_init();
if (opt_machine_pass) {
- char *user = NULL;
/* it is very useful to be able to make ads queries as the
machine account for testing purposes and for domain leave */
- if (!secrets_init()) {
- d_printf("ERROR: Unable to open secrets database\n");
- exit(1);
- }
-
- opt_password = secrets_fetch_machine_password(opt_workgroup, NULL, NULL);
-
- asprintf(&user,"%s$", global_myname());
- opt_user_name = user;
- if (!opt_password) {
- d_printf("ERROR: Unable to fetch machine password\n");
- exit(1);
- }
+ net_use_machine_password();
}
if (!opt_password) {
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 631e235127..352431a938 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -579,10 +579,7 @@ static int net_ads_leave(int argc, const char **argv)
}
if (!opt_password) {
- char *user_name;
- asprintf(&user_name, "%s$", global_myname());
- opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
- opt_user_name = user_name;
+ net_use_machine_password();
}
if (!(ads = ads_startup())) {
@@ -603,7 +600,6 @@ static int net_ads_leave(int argc, const char **argv)
static int net_ads_join_ok(void)
{
- char *user_name;
ADS_STRUCT *ads = NULL;
if (!secrets_init()) {
@@ -611,9 +607,7 @@ static int net_ads_join_ok(void)
return -1;
}
- asprintf(&user_name, "%s$", global_myname());
- opt_user_name = user_name;
- opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
+ net_use_machine_password();
if (!(ads = ads_startup())) {
return -1;
@@ -648,6 +642,7 @@ int net_ads_join(int argc, const char **argv)
ADS_STRUCT *ads;
ADS_STATUS rc;
char *password;
+ char *machine_account = NULL;
char *tmp_password;
const char *org_unit = "Computers";
char *dn;
@@ -669,6 +664,16 @@ int net_ads_join(int argc, const char **argv)
if (!(ads = ads_startup())) return -1;
+ if (!*lp_realm()) {
+ d_printf("realm must be set in in smb.conf for ADS join to succeed.\n");
+ return -1;
+ }
+
+ if (strcmp(ads->config.realm, lp_realm()) != 0) {
+ d_printf("realm of remote server (%s) and realm in smb.conf (%s) DO NOT match. Aborting join\n", ads->config.realm, lp_realm());
+ return -1;
+ }
+
ou_str = ads_ou_string(org_unit);
asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
free(ou_str);
@@ -696,11 +701,16 @@ int net_ads_join(int argc, const char **argv)
rc = ads_domain_sid(ads, &dom_sid);
if (!ADS_ERR_OK(rc)) {
- d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
+ d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
+ return -1;
+ }
+
+ if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
+ d_printf("asprintf failed\n");
return -1;
}
- rc = ads_set_machine_password(ads, global_myname(), password);
+ rc = ads_set_machine_password(ads, machine_account, password);
if (!ADS_ERR_OK(rc)) {
d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
return -1;
@@ -718,7 +728,8 @@ int net_ads_join(int argc, const char **argv)
d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
- free(password);
+ SAFE_FREE(password);
+ SAFE_FREE(machine_account);
return 0;
}
@@ -1020,17 +1031,13 @@ int net_ads_changetrustpw(int argc, const char **argv)
char *host_principal;
char *hostname;
ADS_STATUS ret;
- char *user_name;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
return -1;
}
- asprintf(&user_name, "%s$", global_myname());
- opt_user_name = user_name;
-
- opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
+ net_use_machine_password();
use_in_memory_ccache();