1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-24 21:49:29 +03:00

winbind: Fix UPN handling in parse_domain_user()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13369

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Andreas Schneider <asn@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
(cherry picked from commit a05b63db62)
This commit is contained in:
Andreas Schneider
2018-04-26 12:17:12 +02:00
committed by Karolin Seeger
parent b5ba5da438
commit 124f0e4bda
10 changed files with 153 additions and 59 deletions

View File

@ -1,4 +1,3 @@
^samba3\.wbinfo_user_info\.user_info\.upn\.jane\.doe.ad_member
^samba3\.wbinfo_user_info\.name_to_sid\.upn\.testdenied_upn.ad_member
^samba3\.wbinfo_user_info\.user_info\.upn\.testdenied_upn.ad_member
^samba3\.wbinfo_user_info\.user_info\.domain\.alice.fl2008r2dc

View File

@ -3221,7 +3221,8 @@ bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
return NT_STATUS_IS_OK(status);
}
bool lookup_cached_name(const char *domain_name,
bool lookup_cached_name(const char *namespace,
const char *domain_name,
const char *name,
struct dom_sid *sid,
enum lsa_SidType *type)
@ -3230,7 +3231,7 @@ bool lookup_cached_name(const char *domain_name,
NTSTATUS status;
bool original_online_state;
domain = find_lookup_domain_from_name(domain_name);
domain = find_lookup_domain_from_name(namespace);
if (domain == NULL) {
return false;
}

View File

@ -43,8 +43,9 @@ static bool client_can_access_ccache_entry(uid_t client_uid,
return False;
}
static NTSTATUS do_ntlm_auth_with_stored_pw(const char *username,
static NTSTATUS do_ntlm_auth_with_stored_pw(const char *namespace,
const char *domain,
const char *username,
const char *password,
const DATA_BLOB initial_msg,
const DATA_BLOB challenge_msg,
@ -182,11 +183,12 @@ static bool check_client_uid(struct winbindd_cli_state *state, uid_t uid)
void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state)
{
struct winbindd_domain *domain;
fstring name_domain, name_user;
fstring name_namespace, name_domain, name_user;
NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
struct WINBINDD_MEMORY_CREDS *entry;
DATA_BLOB initial, challenge, auth;
uint32_t initial_blob_len, challenge_blob_len, extra_len;
bool ok;
/* Ensure null termination */
state->request->data.ccache_ntlm_auth.user[
@ -238,7 +240,11 @@ void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state)
}
/* Parse domain and username */
if (!parse_domain_user(state->request->data.ccache_ntlm_auth.user, name_domain, name_user)) {
ok = parse_domain_user(state->request->data.ccache_ntlm_auth.user,
name_namespace,
name_domain,
name_user);
if (!ok) {
DEBUG(10,("winbindd_dual_ccache_ntlm_auth: cannot parse "
"domain and user from name [%s]\n",
state->request->data.ccache_ntlm_auth.user));
@ -273,10 +279,16 @@ void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state)
state->request->data.ccache_ntlm_auth.challenge_blob_len);
result = do_ntlm_auth_with_stored_pw(
name_user, name_domain, entry->pass,
initial, challenge, talloc_tos(), &auth,
state->response->data.ccache_ntlm_auth.session_key,
&state->response->data.ccache_ntlm_auth.new_spnego);
name_namespace,
name_domain,
name_user,
entry->pass,
initial,
challenge,
talloc_tos(),
&auth,
state->response->data.ccache_ntlm_auth.session_key,
&state->response->data.ccache_ntlm_auth.new_spnego);
if (!NT_STATUS_IS_OK(result)) {
goto process_result;

View File

@ -76,7 +76,8 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain,
enum lsa_SidType type;
if (!lookup_cached_name(domain->name,
if (!lookup_cached_name(domain->name, /* namespace */
domain->name,
user,
&cred_sid,
&type)) {

View File

@ -22,7 +22,7 @@
struct winbindd_getgrnam_state {
struct tevent_context *ev;
fstring name_domain, name_group;
fstring name_namespace, name_domain, name_group;
struct dom_sid sid;
const char *domname;
const char *name;
@ -42,6 +42,7 @@ struct tevent_req *winbindd_getgrnam_send(TALLOC_CTX *mem_ctx,
struct winbindd_getgrnam_state *state;
char *tmp;
NTSTATUS nt_status;
bool ok;
req = tevent_req_create(mem_ctx, &state,
struct winbindd_getgrnam_state);
@ -66,7 +67,15 @@ struct tevent_req *winbindd_getgrnam_send(TALLOC_CTX *mem_ctx,
/* Parse domain and groupname */
parse_domain_user(tmp, state->name_domain, state->name_group);
ok = parse_domain_user(tmp,
state->name_namespace,
state->name_domain,
state->name_group);
if (!ok) {
DBG_INFO("Could not parse domain user: %s\n", tmp);
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
/* if no domain or our local domain and no local tdb group, default to
* our local domain for aliases */
@ -77,7 +86,7 @@ struct tevent_req *winbindd_getgrnam_send(TALLOC_CTX *mem_ctx,
}
subreq = wb_lookupname_send(state, ev,
state->name_domain,
state->name_namespace,
state->name_domain,
state->name_group,
0);

View File

@ -23,6 +23,7 @@
struct winbindd_getgroups_state {
struct tevent_context *ev;
fstring namespace;
fstring domname;
fstring username;
struct dom_sid sid;
@ -46,6 +47,7 @@ struct tevent_req *winbindd_getgroups_send(TALLOC_CTX *mem_ctx,
struct winbindd_getgroups_state *state;
char *domuser, *mapped_user;
NTSTATUS status;
bool ok;
req = tevent_req_create(mem_ctx, &state,
struct winbindd_getgroups_state);
@ -69,14 +71,18 @@ struct tevent_req *winbindd_getgroups_send(TALLOC_CTX *mem_ctx,
domuser = mapped_user;
}
if (!parse_domain_user(domuser, state->domname, state->username)) {
ok = parse_domain_user(domuser,
state->namespace,
state->domname,
state->username);
if (!ok) {
DEBUG(5, ("Could not parse domain user: %s\n", domuser));
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
subreq = wb_lookupname_send(state, ev,
state->domname,
state->namespace,
state->domname,
state->username,
LOOKUP_NAME_NO_NSS);

View File

@ -23,6 +23,7 @@
struct winbindd_getpwnam_state {
struct tevent_context *ev;
fstring namespace;
fstring domname;
fstring username;
struct dom_sid sid;
@ -42,6 +43,7 @@ struct tevent_req *winbindd_getpwnam_send(TALLOC_CTX *mem_ctx,
struct winbindd_getpwnam_state *state;
char *domuser, *mapped_user;
NTSTATUS status;
bool ok;
req = tevent_req_create(mem_ctx, &state,
struct winbindd_getpwnam_state);
@ -65,14 +67,18 @@ struct tevent_req *winbindd_getpwnam_send(TALLOC_CTX *mem_ctx,
domuser = mapped_user;
}
if (!parse_domain_user(domuser, state->domname, state->username)) {
ok = parse_domain_user(domuser,
state->namespace,
state->domname,
state->username);
if (!ok) {
DEBUG(5, ("Could not parse domain user: %s\n", domuser));
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
subreq = wb_lookupname_send(state, ev,
state->domname,
state->namespace,
state->domname,
state->username,
LOOKUP_NAME_NO_NSS);

View File

@ -645,7 +645,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
const char *principal_s = NULL;
const char *service = NULL;
char *realm = NULL;
fstring name_domain, name_user;
fstring name_namespace, name_domain, name_user;
time_t ticket_lifetime = 0;
time_t renewal_until = 0;
ADS_STRUCT *ads;
@ -658,6 +658,7 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
const char *local_service;
uint32_t i;
struct netr_SamInfo6 *info6_copy = NULL;
bool ok;
*info6 = NULL;
@ -693,7 +694,10 @@ static NTSTATUS winbindd_raw_kerberos_login(TALLOC_CTX *mem_ctx,
/* 3rd step:
* do kerberos auth and setup ccache as the user */
parse_domain_user(user, name_domain, name_user);
ok = parse_domain_user(user, name_namespace, name_domain, name_user);
if (!ok) {
return NT_STATUS_INVALID_PARAMETER;
}
realm = talloc_strdup(mem_ctx, domain->alt_name);
if (realm == NULL) {
@ -975,7 +979,7 @@ static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
{
NTSTATUS result = NT_STATUS_LOGON_FAILURE;
uint16_t max_allowed_bad_attempts;
fstring name_domain, name_user;
fstring name_namespace, name_domain, name_user;
struct dom_sid sid;
enum lsa_SidType type;
uchar new_nt_pass[NT_HASH_LEN];
@ -996,10 +1000,14 @@ static NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
/* Parse domain and username */
parse_domain_user(state->request->data.auth.user, name_domain, name_user);
parse_domain_user(state->request->data.auth.user,
name_namespace,
name_domain,
name_user);
if (!lookup_cached_name(name_domain,
if (!lookup_cached_name(name_namespace,
name_domain,
name_user,
&sid,
&type)) {
@ -1244,19 +1252,28 @@ static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
struct netr_SamInfo6 **info6)
{
struct winbindd_domain *contact_domain;
fstring name_domain, name_user;
fstring name_namespace, name_domain, name_user;
NTSTATUS result;
bool ok;
DEBUG(10,("winbindd_dual_pam_auth_kerberos\n"));
/* Parse domain and username */
parse_domain_user(state->request->data.auth.user, name_domain, name_user);
ok = parse_domain_user(state->request->data.auth.user,
name_namespace,
name_domain,
name_user);
if (!ok) {
result = NT_STATUS_INVALID_PARAMETER;
goto done;
}
/* what domain should we contact? */
if ( IS_DC ) {
if (!(contact_domain = find_domain_from_name(name_domain))) {
contact_domain = find_domain_from_name(name_namespace);
if (contact_domain == NULL) {
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;
@ -1270,7 +1287,7 @@ static NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
goto done;
}
contact_domain = find_domain_from_name(name_domain);
contact_domain = find_domain_from_name(name_namespace);
if (contact_domain == NULL) {
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));
@ -1662,19 +1679,23 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(
DATA_BLOB lm_resp;
DATA_BLOB nt_resp;
unsigned char local_nt_response[24];
fstring name_domain, name_user;
fstring name_namespace, name_domain, name_user;
NTSTATUS result;
uint8_t authoritative = 0;
uint32_t flags = 0;
uint16_t validation_level;
union netr_Validation *validation = NULL;
struct netr_SamBaseInfo *base_info = NULL;
bool ok;
DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
/* Parse domain and username */
parse_domain_user(user, name_domain, name_user);
ok = parse_domain_user(user, name_namespace, name_domain, name_user);
if (!ok) {
return NT_STATUS_INVALID_PARAMETER;
}
/*
* We check against domain->name instead of
@ -1869,12 +1890,13 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
{
NTSTATUS result = NT_STATUS_LOGON_FAILURE;
NTSTATUS krb5_result = NT_STATUS_OK;
fstring name_domain, name_user;
fstring name_namespace, name_domain, name_user;
char *mapped_user;
fstring domain_user;
uint16_t validation_level = UINT16_MAX;
union netr_Validation *validation = NULL;
NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
bool ok;
/* Ensure null termination */
state->request->data.auth.user[sizeof(state->request->data.auth.user)-1]='\0';
@ -1900,7 +1922,14 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
mapped_user = state->request->data.auth.user;
}
parse_domain_user(mapped_user, name_domain, name_user);
ok = parse_domain_user(mapped_user,
name_namespace,
name_domain,
name_user);
if (!ok) {
result = NT_STATUS_INVALID_PARAMETER;
goto process_result;
}
if ( mapped_user != state->request->data.auth.user ) {
fstr_sprintf( domain_user, "%s%c%s", name_domain,
@ -2490,15 +2519,20 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact
struct samr_DomInfo1 *info = NULL;
struct userPwdChangeFailureInformation *reject = NULL;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
fstring domain, user;
fstring namespace, domain, user;
struct dcerpc_binding_handle *b = NULL;
bool ok;
ZERO_STRUCT(dom_pol);
DEBUG(3, ("[%5lu]: dual pam chauthtok %s\n", (unsigned long)state->pid,
state->request->data.auth.user));
if (!parse_domain_user(state->request->data.chauthtok.user, domain, user)) {
ok = parse_domain_user(state->request->data.chauthtok.user,
namespace,
domain,
user);
if (!ok) {
goto done;
}
@ -2707,7 +2741,7 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai
DATA_BLOB old_nt_hash_enc;
DATA_BLOB new_lm_password;
DATA_BLOB old_lm_hash_enc;
fstring domain,user;
fstring namespace, domain, user;
struct policy_handle dom_pol;
struct winbindd_domain *contact_domain = domainSt;
struct rpc_pipe_client *cli = NULL;
@ -2720,8 +2754,9 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai
sizeof(state->request->data.chng_pswd_auth_crap.user)-1]=0;
state->request->data.chng_pswd_auth_crap.domain[
sizeof(state->request->data.chng_pswd_auth_crap.domain)-1]=0;
*domain = 0;
*user = 0;
domain[0] = '\0';
namespace[0] = '\0';
user[0] = '\0';
DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n",
(unsigned long)state->pid,
@ -2738,8 +2773,16 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai
if (*state->request->data.chng_pswd_auth_crap.domain) {
fstrcpy(domain,state->request->data.chng_pswd_auth_crap.domain);
} else {
parse_domain_user(state->request->data.chng_pswd_auth_crap.user,
domain, user);
bool ok;
ok = parse_domain_user(state->request->data.chng_pswd_auth_crap.user,
namespace,
domain,
user);
if (!ok) {
result = NT_STATUS_INVALID_PARAMETER;
goto done;
}
if(!*domain) {
DEBUG(3,("no domain specified with username (%s) - "

View File

@ -134,7 +134,8 @@ void close_winbindd_cache(void);
bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
char **domain_name, char **name,
enum lsa_SidType *type);
bool lookup_cached_name(const char *domain_name,
bool lookup_cached_name(const char *namespace,
const char *domain_name,
const char *name,
struct dom_sid *sid,
enum lsa_SidType *type);
@ -476,7 +477,10 @@ struct winbindd_domain *find_our_domain(void);
struct winbindd_domain *find_default_route_domain(void);
struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid);
struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name);
bool parse_domain_user(const char *domuser, fstring domain, fstring user);
bool parse_domain_user(const char *domuser,
fstring namespace,
fstring domain,
fstring user);
bool canonicalize_username(fstring username_inout, fstring domain, fstring user);
void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume);
char *fill_domain_username_talloc(TALLOC_CTX *ctx,

View File

@ -1575,28 +1575,37 @@ static bool assume_domain(const char *domain)
return False;
}
/* Parse a string of the form DOMAIN\user into a domain and a user */
bool parse_domain_user(const char *domuser, fstring domain, fstring user)
/* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
bool parse_domain_user(const char *domuser,
fstring namespace,
fstring domain,
fstring user)
{
char *p = strchr(domuser,*lp_winbind_separator());
char *p = NULL;
if ( !p ) {
fstrcpy(user, domuser);
p = strchr(domuser, '@');
if (strlen(domuser) == 0) {
return false;
}
if ( assume_domain(lp_workgroup()) && p == NULL) {
fstrcpy(domain, lp_workgroup());
} else if (p != NULL) {
fstrcpy(domain, p + 1);
user[PTR_DIFF(p, domuser)] = 0;
} else {
return False;
}
} else {
fstrcpy(user, p+1);
p = strchr(domuser, *lp_winbind_separator());
if (p != NULL) {
fstrcpy(user, p + 1);
fstrcpy(domain, domuser);
domain[PTR_DIFF(p, domuser)] = 0;
domain[PTR_DIFF(p, domuser)] = '\0';
fstrcpy(namespace, domain);
} else {
fstrcpy(user, domuser);
domain[0] = '\0';
namespace[0] = '\0';
p = strchr(domuser, '@');
if (p != NULL) {
/* upn */
fstrcpy(namespace, p + 1);
} else if (assume_domain(lp_workgroup())) {
fstrcpy(domain, lp_workgroup());
fstrcpy(namespace, domain);
}
}
return strupper_m(domain);
@ -1613,7 +1622,11 @@ bool parse_domain_user(const char *domuser, fstring domain, fstring user)
bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
{
if (!parse_domain_user(username_inout, domain, user)) {
fstring namespace;
bool ok;
ok = parse_domain_user(username_inout, namespace, domain, user);
if (!ok) {
return False;
}
slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",