mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
Change our Domain controller lookup routines to more carefully seperate
DNS names (realms) from NetBIOS domain names. Until now, we would experience delays as we broadcast lookups for DNS names onto the local network segments. Now if DNS comes back negative, we fall straight back to looking up the short name. Andrew Bartlett
This commit is contained in:
parent
d22313998a
commit
32397c8b01
@ -165,6 +165,9 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
|
||||
|
||||
if ( !NT_STATUS_IS_OK(nt_status) ) {
|
||||
DEBUG(0,("domain_client_validate: Domain password server not available.\n"));
|
||||
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
|
||||
return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
|
||||
}
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
@ -290,7 +293,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
|
||||
|
||||
/* we need our DC to send the net_sam_logon() request to */
|
||||
|
||||
if ( !get_dc_name(domain, dc_name, &dc_ip) ) {
|
||||
if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
|
||||
DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n",
|
||||
user_info->domain.str));
|
||||
return NT_STATUS_NO_LOGON_SERVERS;
|
||||
@ -385,7 +388,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
|
||||
/* use get_dc_name() for consistency even through we know that it will be
|
||||
a netbios name */
|
||||
|
||||
if ( !get_dc_name(user_info->domain.str, dc_name, &dc_ip) ) {
|
||||
if ( !get_dc_name(user_info->domain.str, NULL, dc_name, &dc_ip) ) {
|
||||
DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n",
|
||||
user_info->domain.str));
|
||||
return NT_STATUS_NO_LOGON_SERVERS;
|
||||
|
@ -29,27 +29,23 @@
|
||||
Find the name and IP address for a server in he realm/domain
|
||||
*************************************************************************/
|
||||
|
||||
static BOOL ads_dc_name(const char *domain, struct in_addr *dc_ip, fstring srv_name)
|
||||
static BOOL ads_dc_name(const char *domain, const char *realm, struct in_addr *dc_ip, fstring srv_name)
|
||||
{
|
||||
ADS_STRUCT *ads;
|
||||
const char *realm = domain;
|
||||
|
||||
if (strequal(realm, lp_workgroup()))
|
||||
if (!realm && strequal(domain, lp_workgroup()))
|
||||
realm = lp_realm();
|
||||
|
||||
ads = ads_init(realm, domain, NULL);
|
||||
if (!ads)
|
||||
return False;
|
||||
|
||||
/* we don't need to bind, just connect */
|
||||
ads->auth.flags |= ADS_AUTH_NO_BIND;
|
||||
|
||||
DEBUG(4,("ads_dc_name: domain=%s\n", domain));
|
||||
|
||||
#ifdef HAVE_ADS
|
||||
/* a full ads_connect() is actually overkill, as we don't srictly need
|
||||
to do the SASL auth in order to get the info we need, but libads
|
||||
doesn't offer a better way right now */
|
||||
/* we don't need to bind, just connect */
|
||||
ads->auth.flags |= ADS_AUTH_NO_BIND;
|
||||
|
||||
ads_connect(ads);
|
||||
#endif
|
||||
|
||||
@ -157,7 +153,7 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip
|
||||
wrapper around ads and rpc methods of finds DC's
|
||||
**********************************************************************/
|
||||
|
||||
BOOL get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
|
||||
BOOL get_dc_name(const char *domain, const char *realm, fstring srv_name, struct in_addr *ip_out)
|
||||
{
|
||||
struct in_addr dc_ip;
|
||||
BOOL ret;
|
||||
@ -167,15 +163,14 @@ BOOL get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
|
||||
|
||||
ret = False;
|
||||
|
||||
if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), domain) )
|
||||
if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), realm) )
|
||||
our_domain = True;
|
||||
|
||||
/* always try to obey what the admin specified in smb.conf.
|
||||
If it is not our domain, assume that domain names with periods
|
||||
in them are realm names */
|
||||
/* always try to obey what the admin specified in smb.conf
|
||||
(for the local domain) */
|
||||
|
||||
if ( (our_domain && lp_security()==SEC_ADS) || strchr_m(domain, '.') ) {
|
||||
ret = ads_dc_name(domain, &dc_ip, srv_name);
|
||||
if ( (our_domain && lp_security()==SEC_ADS) || realm ) {
|
||||
ret = ads_dc_name(domain, realm, &dc_ip, srv_name);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
|
@ -144,7 +144,7 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
|
||||
|
||||
/* lookup a DC first */
|
||||
|
||||
if ( !get_dc_name(domain, dc_name, &dc_ip) ) {
|
||||
if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
|
||||
DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
|
||||
domain));
|
||||
return False;
|
||||
|
@ -842,7 +842,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
struct cli_state *cli = NULL;
|
||||
/* i think we only need our forest and downlevel trusted domains */
|
||||
uint32 flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND;
|
||||
char *contact_domain_name;
|
||||
|
||||
DEBUG(3,("ads: trusted_domains\n"));
|
||||
|
||||
@ -851,8 +850,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
*names = NULL;
|
||||
*dom_sids = NULL;
|
||||
|
||||
contact_domain_name = *domain->alt_name ? domain->alt_name : domain->name;
|
||||
if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(contact_domain_name, PI_NETLOGON, &cli)) ) {
|
||||
if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(domain, PI_NETLOGON, &cli)) ) {
|
||||
DEBUG(5, ("trusted_domains: Could not open a connection to %s for PIPE_NETLOGON (%s)\n",
|
||||
domain->name, nt_errstr(result)));
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
|
@ -113,8 +113,8 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password)
|
||||
|
||||
/* Open a connction to the remote server, cache failures for 30 seconds */
|
||||
|
||||
static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
|
||||
struct winbindd_cm_conn *new_conn)
|
||||
static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index,
|
||||
struct winbindd_cm_conn *new_conn)
|
||||
{
|
||||
NTSTATUS result;
|
||||
char *machine_password;
|
||||
@ -125,21 +125,22 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
|
||||
|
||||
ZERO_STRUCT(dc_ip);
|
||||
|
||||
fstrcpy(new_conn->domain, domain);
|
||||
fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
|
||||
fstrcpy(new_conn->domain, domain->name);
|
||||
|
||||
/* connection failure cache has been moved inside of get_dc_name
|
||||
so we can deal with half dead DC's --jerry */
|
||||
|
||||
if (!get_dc_name(domain, new_conn->controller, &dc_ip)) {
|
||||
if (!get_dc_name(domain->name, domain->alt_name[0] ? domain->alt_name : NULL,
|
||||
new_conn->controller, &dc_ip)) {
|
||||
result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
|
||||
add_failed_connection_entry(domain, "", result);
|
||||
add_failed_connection_entry(domain->name, "", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Initialise SMB connection */
|
||||
fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
|
||||
|
||||
/* grab stored passwords */
|
||||
/* 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) {
|
||||
@ -181,7 +182,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
|
||||
|
||||
if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal,
|
||||
machine_password,
|
||||
domain))) {
|
||||
domain->name))) {
|
||||
DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
|
||||
}
|
||||
}
|
||||
@ -201,7 +202,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
|
||||
if (!cli_session_setup(new_conn->cli, ipc_username,
|
||||
ipc_password, strlen(ipc_password)+1,
|
||||
ipc_password, strlen(ipc_password)+1,
|
||||
domain)) {
|
||||
domain->name)) {
|
||||
result = cli_nt_error(new_conn->cli);
|
||||
DEBUG(4,("failed authenticated session setup with %s\n", nt_errstr(result)));
|
||||
if (NT_STATUS_IS_OK(result))
|
||||
@ -258,13 +259,13 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
|
||||
SAFE_FREE(machine_password);
|
||||
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
add_failed_connection_entry(domain, new_conn->controller, result);
|
||||
add_failed_connection_entry(domain->name, new_conn->controller, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* set the domain if empty; needed for schannel connections */
|
||||
if ( !*new_conn->cli->domain )
|
||||
fstrcpy( new_conn->cli->domain, domain );
|
||||
fstrcpy( new_conn->cli->domain, domain->name );
|
||||
|
||||
|
||||
if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
|
||||
@ -278,7 +279,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
|
||||
* specific UUID right now, i'm not going to bother. --jerry
|
||||
*/
|
||||
if ( !is_win2k_pipe(pipe_index) )
|
||||
add_failed_connection_entry(domain, new_conn->controller, result);
|
||||
add_failed_connection_entry(domain->name, new_conn->controller, result);
|
||||
cli_shutdown(new_conn->cli);
|
||||
return result;
|
||||
}
|
||||
@ -291,7 +292,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
|
||||
setup cli_state struct
|
||||
************************************************************************/
|
||||
|
||||
NTSTATUS cm_fresh_connection(const char *domain, const int pipe_index,
|
||||
NTSTATUS cm_fresh_connection(struct winbindd_domain *domain, const int pipe_index,
|
||||
struct cli_state **cli)
|
||||
{
|
||||
NTSTATUS result;
|
||||
@ -338,13 +339,13 @@ static BOOL connection_ok(struct winbindd_cm_conn *conn)
|
||||
/* Search the cache for a connection. If there is a broken one,
|
||||
shut it down properly and return NULL. */
|
||||
|
||||
static void find_cm_connection(const char *domain, const char *pipe_name,
|
||||
static void find_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
|
||||
struct winbindd_cm_conn **conn_out)
|
||||
{
|
||||
struct winbindd_cm_conn *conn;
|
||||
|
||||
for (conn = cm_conns; conn; ) {
|
||||
if (strequal(conn->domain, domain) &&
|
||||
if (strequal(conn->domain, domain->name) &&
|
||||
strequal(conn->pipe_name, pipe_name)) {
|
||||
if (!connection_ok(conn)) {
|
||||
/* Dead connection - remove it. */
|
||||
@ -367,7 +368,7 @@ static void find_cm_connection(const char *domain, const char *pipe_name,
|
||||
|
||||
/* Initialize a new connection up to the RPC BIND. */
|
||||
|
||||
static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name,
|
||||
static NTSTATUS new_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
|
||||
struct winbindd_cm_conn **conn_out)
|
||||
{
|
||||
struct winbindd_cm_conn *conn;
|
||||
@ -380,7 +381,7 @@ static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name,
|
||||
|
||||
if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
|
||||
DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
|
||||
domain, pipe_name, nt_errstr(result)));
|
||||
domain->name, pipe_name, nt_errstr(result)));
|
||||
SAFE_FREE(conn);
|
||||
return result;
|
||||
}
|
||||
@ -392,7 +393,7 @@ static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name,
|
||||
|
||||
/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
|
||||
|
||||
static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name,
|
||||
static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const char *pipe_name,
|
||||
struct winbindd_cm_conn **conn_out)
|
||||
{
|
||||
find_cm_connection(domain, pipe_name, conn_out);
|
||||
@ -406,7 +407,7 @@ static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_n
|
||||
/**********************************************************************************
|
||||
**********************************************************************************/
|
||||
|
||||
BOOL cm_check_for_native_mode_win2k( const char *domain )
|
||||
BOOL cm_check_for_native_mode_win2k( struct winbindd_domain *domain )
|
||||
{
|
||||
NTSTATUS result;
|
||||
struct winbindd_cm_conn conn;
|
||||
@ -419,7 +420,7 @@ BOOL cm_check_for_native_mode_win2k( const char *domain )
|
||||
|
||||
if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
|
||||
DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
|
||||
domain, nt_errstr(result)));
|
||||
domain->name, nt_errstr(result)));
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -450,7 +451,7 @@ done:
|
||||
|
||||
/* Return a LSA policy handle on a domain */
|
||||
|
||||
NTSTATUS cm_get_lsa_handle(const char *domain, CLI_POLICY_HND **return_hnd)
|
||||
NTSTATUS cm_get_lsa_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
|
||||
{
|
||||
struct winbindd_cm_conn *conn;
|
||||
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
|
||||
@ -503,7 +504,7 @@ NTSTATUS cm_get_lsa_handle(const char *domain, CLI_POLICY_HND **return_hnd)
|
||||
|
||||
/* Return a SAM policy handle on a domain */
|
||||
|
||||
NTSTATUS cm_get_sam_handle(char *domain, CLI_POLICY_HND **return_hnd)
|
||||
NTSTATUS cm_get_sam_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
|
||||
{
|
||||
struct winbindd_cm_conn *conn;
|
||||
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
|
||||
@ -561,7 +562,7 @@ NTSTATUS cm_get_sam_handle(char *domain, CLI_POLICY_HND **return_hnd)
|
||||
/* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
|
||||
netlogon pipe as no handle is returned. */
|
||||
|
||||
NTSTATUS cm_get_netlogon_cli(const char *domain,
|
||||
NTSTATUS cm_get_netlogon_cli(struct winbindd_domain *domain,
|
||||
const unsigned char *trust_passwd,
|
||||
uint32 sec_channel_type,
|
||||
BOOL fresh,
|
||||
@ -571,7 +572,6 @@ NTSTATUS cm_get_netlogon_cli(const char *domain,
|
||||
struct winbindd_cm_conn *conn;
|
||||
fstring lock_name;
|
||||
BOOL got_mutex;
|
||||
struct winbindd_domain *wb_domain = NULL;
|
||||
|
||||
if (!cli)
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
@ -613,16 +613,9 @@ NTSTATUS cm_get_netlogon_cli(const char *domain,
|
||||
if ( sec_channel_type == SEC_CHAN_DOMAIN )
|
||||
fstr_sprintf(conn->cli->mach_acct, "%s$", lp_workgroup());
|
||||
|
||||
/* we need the short form of the domain name for the schanel
|
||||
rpc bind. What if we fail? I don't think we should ever get
|
||||
a request for a domain name not in our list but I'm not bailing
|
||||
out if we do since I'm not 10% certain about this --jerry */
|
||||
|
||||
if ( (wb_domain = find_domain_from_name( domain )) != NULL ) {
|
||||
DEBUG(5,("cm_get_netlogon_cli: Using short for of domain name [%s] for netlogon rpc bind\n",
|
||||
wb_domain->name));
|
||||
fstrcpy( conn->cli->domain, wb_domain->name);
|
||||
}
|
||||
|
||||
fstrcpy( conn->cli->domain, domain->name);
|
||||
|
||||
|
||||
result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd);
|
||||
|
||||
|
@ -37,7 +37,8 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
|
||||
struct cli_state *cli;
|
||||
uint32 sec_channel_type;
|
||||
const char *contact_domain_name = NULL;
|
||||
|
||||
struct winbindd_domain *contact_domain;
|
||||
|
||||
DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
|
||||
|
||||
/* Get trust account password */
|
||||
@ -57,12 +58,19 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
|
||||
|
||||
if ( !contact_domain_name || !*contact_domain_name )
|
||||
contact_domain_name = lp_workgroup();
|
||||
|
||||
|
||||
contact_domain = find_domain_from_name(contact_domain_name);
|
||||
if (!contact_domain) {
|
||||
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
DEBUG(1, ("%s is not a trusted domain\n", contact_domain_name));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* This call does a cli_nt_setup_creds() which implicitly checks
|
||||
the trust account password. */
|
||||
/* Don't shut this down - it belongs to the connection cache code */
|
||||
|
||||
result = cm_get_netlogon_cli(contact_domain_name,
|
||||
result = cm_get_netlogon_cli(contact_domain,
|
||||
trust_passwd, sec_channel_type, True, &cli);
|
||||
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
|
@ -75,7 +75,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
|
||||
int attempts = 0;
|
||||
unsigned char local_lm_response[24];
|
||||
unsigned char local_nt_response[24];
|
||||
const char *contact_domain;
|
||||
struct winbindd_domain *contact_domain;
|
||||
BOOL retry;
|
||||
|
||||
/* Ensure null termination */
|
||||
@ -107,21 +107,15 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
|
||||
lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
|
||||
nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
|
||||
|
||||
if ( !get_trust_pw(name_domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
|
||||
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* what domain should we contact? */
|
||||
|
||||
if ( IS_DC ) {
|
||||
if (!find_domain_from_name(name_domain)) {
|
||||
DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
|
||||
if (!(contact_domain = find_domain_from_name(name_domain))) {
|
||||
DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
|
||||
state->request.data.auth.user, name_domain, name_user, name_domain));
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
contact_domain = name_domain;
|
||||
|
||||
} else {
|
||||
if (is_myname(name_domain)) {
|
||||
@ -129,8 +123,20 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
contact_domain = lp_workgroup();
|
||||
|
||||
if (!(contact_domain = find_our_domain())) {
|
||||
DEBUG(1, ("Authenticatoin for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n",
|
||||
state->request.data.auth.user, name_domain, name_user));
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
|
||||
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* check authentication loop */
|
||||
|
||||
do {
|
||||
@ -194,7 +200,10 @@ done:
|
||||
|
||||
state->response.data.auth.nt_status = NT_STATUS_V(result);
|
||||
fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
|
||||
fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
|
||||
|
||||
/* we might have given a more useful error above */
|
||||
if (!*state->response.data.auth.error_string)
|
||||
fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
|
||||
state->response.data.auth.pam_error = nt_status_to_pam(result);
|
||||
|
||||
DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n",
|
||||
@ -221,10 +230,10 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
NET_USER_INFO_3 info3;
|
||||
struct cli_state *cli = NULL;
|
||||
TALLOC_CTX *mem_ctx = NULL;
|
||||
char *user = NULL;
|
||||
const char *domain = NULL;
|
||||
char *name_user = NULL;
|
||||
const char *name_domain = NULL;
|
||||
const char *workstation;
|
||||
const char *contact_domain;
|
||||
struct winbindd_domain *contact_domain;
|
||||
DOM_CRED ret_creds;
|
||||
int attempts = 0;
|
||||
BOOL retry;
|
||||
@ -255,7 +264,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) == (size_t)-1) {
|
||||
if (pull_utf8_talloc(mem_ctx, &name_user, state->request.data.auth_crap.user) == (size_t)-1) {
|
||||
DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n"));
|
||||
result = NT_STATUS_UNSUCCESSFUL;
|
||||
goto done;
|
||||
@ -268,24 +277,19 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
result = NT_STATUS_UNSUCCESSFUL;
|
||||
goto done;
|
||||
}
|
||||
domain = dom;
|
||||
name_domain = dom;
|
||||
} else if (lp_winbind_use_default_domain()) {
|
||||
domain = lp_workgroup();
|
||||
name_domain = lp_workgroup();
|
||||
} else {
|
||||
DEBUG(5,("no domain specified with username (%s) - failing auth\n",
|
||||
user));
|
||||
result = NT_STATUS_INVALID_PARAMETER;
|
||||
name_user));
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid,
|
||||
domain, user));
|
||||
name_domain, name_user));
|
||||
|
||||
if ( !get_trust_pw(domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
|
||||
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (*state->request.data.auth_crap.workstation) {
|
||||
char *wrk = NULL;
|
||||
if (pull_utf8_talloc(mem_ctx, &wrk, state->request.data.auth_crap.workstation) == (size_t)-1) {
|
||||
@ -310,25 +314,39 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len);
|
||||
nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len);
|
||||
|
||||
/* what domain should we contact? */
|
||||
|
||||
|
||||
/* what domain should we contact? */
|
||||
|
||||
if ( IS_DC ) {
|
||||
if (!find_domain_from_name(domain)) {
|
||||
DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
|
||||
state->request.data.auth.user, domain, user, domain));
|
||||
if (!(contact_domain = find_domain_from_name(name_domain))) {
|
||||
DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
|
||||
state->request.data.auth.user, name_domain, name_user, name_domain));
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
contact_domain = domain;
|
||||
|
||||
} else {
|
||||
if (is_myname(domain)) {
|
||||
DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", domain));
|
||||
if (is_myname(name_domain)) {
|
||||
DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
contact_domain = lp_workgroup();
|
||||
|
||||
if (!(contact_domain = find_our_domain())) {
|
||||
DEBUG(1, ("Authenticatoin for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n",
|
||||
state->request.data.auth.user, name_domain, name_user));
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
|
||||
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
do {
|
||||
ZERO_STRUCT(info3);
|
||||
ZERO_STRUCT(ret_creds);
|
||||
@ -345,7 +363,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
|
||||
result = cli_netlogon_sam_network_logon(cli, mem_ctx,
|
||||
&ret_creds,
|
||||
user, domain,
|
||||
name_user, name_domain,
|
||||
workstation,
|
||||
state->request.data.auth_crap.chal,
|
||||
lm_resp, nt_resp,
|
||||
@ -369,7 +387,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) {
|
||||
DEBUG(3,("winbindd_pam_auth_crap: sam_logon returned ACCESS_DENIED. Maybe the trust account "
|
||||
"password was changed and we didn't know it. Killing connections to domain %s\n",
|
||||
domain));
|
||||
contact_domain->name));
|
||||
winbindd_cm_flush();
|
||||
retry = True;
|
||||
cli = NULL;
|
||||
@ -381,7 +399,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
|
||||
if (NT_STATUS_IS_OK(result)) {
|
||||
netsamlogon_cache_store( cli->mem_ctx, &info3 );
|
||||
wcache_invalidate_samlogon(find_domain_from_name(domain), &info3);
|
||||
wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
|
||||
|
||||
if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
|
||||
result = append_info3_as_ndr(mem_ctx, state, &info3);
|
||||
@ -393,12 +411,12 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
|
||||
const char *nt_username, *nt_domain;
|
||||
if (!(nt_username = unistr2_tdup(mem_ctx, &(info3.uni_user_name)))) {
|
||||
/* If the server didn't give us one, just use the one we sent them */
|
||||
nt_username = user;
|
||||
nt_username = name_user;
|
||||
}
|
||||
|
||||
if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3.uni_logon_dom)))) {
|
||||
/* If the server didn't give us one, just use the one we sent them */
|
||||
nt_domain = domain;
|
||||
nt_domain = name_domain;
|
||||
}
|
||||
|
||||
fill_domain_username(username_out, nt_domain, nt_username);
|
||||
@ -437,8 +455,8 @@ done:
|
||||
|
||||
DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
|
||||
("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n",
|
||||
domain,
|
||||
user,
|
||||
name_domain,
|
||||
name_user,
|
||||
state->response.data.auth.nt_status_string,
|
||||
state->response.data.auth.pam_error));
|
||||
|
||||
@ -456,10 +474,19 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
|
||||
char *oldpass, *newpass;
|
||||
fstring domain, user;
|
||||
CLI_POLICY_HND *hnd;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
struct winbindd_domain *contact_domain;
|
||||
|
||||
DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
|
||||
state->request.data.chauthtok.user));
|
||||
|
||||
if (!(mem_ctx = talloc_init("winbind password change for (utf8) %s",
|
||||
state->request.data.chauthtok.user))) {
|
||||
DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
|
||||
result = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Setup crap */
|
||||
|
||||
if (state == NULL)
|
||||
@ -467,7 +494,7 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
|
||||
|
||||
parse_domain_user(state->request.data.chauthtok.user, domain, user);
|
||||
|
||||
if (!find_domain_from_name(domain)) {
|
||||
if (!(contact_domain = find_domain_from_name(domain))) {
|
||||
DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
|
||||
state->request.data.chauthtok.user, domain, user, domain));
|
||||
result = NT_STATUS_NO_SUCH_USER;
|
||||
@ -481,17 +508,15 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
|
||||
|
||||
/* Get sam handle */
|
||||
|
||||
if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(domain, &hnd)) ) {
|
||||
if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(contact_domain, &hnd)) ) {
|
||||
DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!cli_oem_change_password(hnd->cli, user, newpass, oldpass)) {
|
||||
if (!NT_STATUS_IS_OK(result = cli_samr_chgpasswd_user(hnd->cli, mem_ctx,
|
||||
user, newpass, oldpass))) {
|
||||
DEBUG(1, ("password change failed for user %s/%s\n", domain,
|
||||
user));
|
||||
result = NT_STATUS_WRONG_PASSWORD;
|
||||
} else {
|
||||
result = NT_STATUS_OK;
|
||||
}
|
||||
|
||||
done:
|
||||
@ -507,5 +532,8 @@ done:
|
||||
state->response.data.auth.nt_status_string,
|
||||
state->response.data.auth.pam_error));
|
||||
|
||||
if (mem_ctx)
|
||||
talloc_destroy(mem_ctx);
|
||||
|
||||
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
do {
|
||||
/* Get sam handle */
|
||||
|
||||
if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) )
|
||||
if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
|
||||
return result;
|
||||
|
||||
/* Get domain handle */
|
||||
@ -163,7 +163,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
|
||||
|
||||
retry = 0;
|
||||
do {
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
|
||||
return result;
|
||||
|
||||
status = cli_samr_open_domain(hnd->cli, mem_ctx,
|
||||
@ -228,7 +228,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
|
||||
|
||||
retry = 0;
|
||||
do {
|
||||
if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) )
|
||||
if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
|
||||
return result;
|
||||
|
||||
result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol,
|
||||
@ -300,7 +300,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
|
||||
|
||||
retry = 0;
|
||||
do {
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd))) {
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -340,7 +340,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
|
||||
|
||||
retry = 0;
|
||||
do {
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
|
||||
return result;
|
||||
|
||||
result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
|
||||
@ -409,7 +409,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
do {
|
||||
/* Get sam handle; if we fail here there is no hope */
|
||||
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
|
||||
goto done;
|
||||
|
||||
/* Get domain handle */
|
||||
@ -510,7 +510,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
|
||||
do {
|
||||
/* Get sam handle; if we fail here there is no hope */
|
||||
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
|
||||
goto done;
|
||||
|
||||
/* Get domain handle */
|
||||
@ -598,7 +598,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
|
||||
retry = 0;
|
||||
do {
|
||||
/* Get sam handle */
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
|
||||
goto done;
|
||||
|
||||
/* Get domain handle */
|
||||
@ -876,7 +876,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
|
||||
}
|
||||
#endif /* HAVE_LDAP */
|
||||
/* Get sam handle */
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
|
||||
goto done;
|
||||
|
||||
/* Get domain handle */
|
||||
@ -932,7 +932,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
|
||||
retry = 0;
|
||||
do {
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(lp_workgroup(), &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
|
||||
goto done;
|
||||
|
||||
result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
|
||||
@ -961,7 +961,7 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
|
||||
retry = 0;
|
||||
do {
|
||||
/* Get lsa handle */
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd)))
|
||||
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
|
||||
goto done;
|
||||
|
||||
result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
|
||||
|
@ -82,7 +82,6 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
|
||||
DOM_SID *sid)
|
||||
{
|
||||
struct winbindd_domain *domain;
|
||||
char *contact_name;
|
||||
const char *alternative_name = NULL;
|
||||
|
||||
/* ignore alt_name if we are not in an AD domain */
|
||||
@ -135,12 +134,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
|
||||
sid_copy(&domain->sid, sid);
|
||||
}
|
||||
|
||||
/* see if this is a native mode win2k domain (use realm name if possible) */
|
||||
/* see if this is a native mode win2k domain */
|
||||
|
||||
contact_name = *domain->alt_name ? domain->alt_name : domain->name;
|
||||
domain->native_mode = cm_check_for_native_mode_win2k( contact_name );
|
||||
domain->native_mode = cm_check_for_native_mode_win2k( domain );
|
||||
|
||||
DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", contact_name,
|
||||
DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain->name,
|
||||
domain->native_mode ? "native" : "mixed (or NT4)" ));
|
||||
|
||||
/* Link to domain list */
|
||||
@ -298,7 +296,7 @@ BOOL init_domain_list(void)
|
||||
*
|
||||
* @note Do *not* pass lp_workgroup() to this function. domain_list
|
||||
* may modify it's value, and free that pointer. Instead, our local
|
||||
* domain may be found by looking at the first entry in domain_list()
|
||||
* domain may be found by calling find_our_domain().
|
||||
* directly.
|
||||
*
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user