summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2018-04-26 12:17:12 +0200
committerKarolin Seeger <kseeger@samba.org>2018-05-24 11:29:23 +0200
commit124f0e4bdaabd082cffc403b747a8f5eb2b2a4ef (patch)
tree6f6afd48c67ae9558a689e02a4106d39e432a7a1 /source3
parentb5ba5da438c415d2542434e95463bad4519e6310 (diff)
downloadsamba-124f0e4bdaabd082cffc403b747a8f5eb2b2a4ef.tar.gz
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 a05b63db627fdbe0bdea4d144dfaeedb39025592)
Diffstat (limited to 'source3')
-rw-r--r--source3/winbindd/winbindd_cache.c5
-rw-r--r--source3/winbindd/winbindd_ccache_access.c26
-rw-r--r--source3/winbindd/winbindd_creds.c3
-rw-r--r--source3/winbindd/winbindd_getgrnam.c15
-rw-r--r--source3/winbindd/winbindd_getgroups.c10
-rw-r--r--source3/winbindd/winbindd_getpwnam.c10
-rw-r--r--source3/winbindd/winbindd_pam.c83
-rw-r--r--source3/winbindd/winbindd_proto.h8
-rw-r--r--source3/winbindd/winbindd_util.c47
9 files changed, 151 insertions, 56 deletions
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index 9f9e8781c21..2778e27374f 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -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;
}
diff --git a/source3/winbindd/winbindd_ccache_access.c b/source3/winbindd/winbindd_ccache_access.c
index 039e6534013..6bcf9a3552c 100644
--- a/source3/winbindd/winbindd_ccache_access.c
+++ b/source3/winbindd/winbindd_ccache_access.c
@@ -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;
diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c
index 15cca554d45..2d7aacf36a9 100644
--- a/source3/winbindd/winbindd_creds.c
+++ b/source3/winbindd/winbindd_creds.c
@@ -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)) {
diff --git a/source3/winbindd/winbindd_getgrnam.c b/source3/winbindd/winbindd_getgrnam.c
index 1d9a8b94d48..37c205ddba4 100644
--- a/source3/winbindd/winbindd_getgrnam.c
+++ b/source3/winbindd/winbindd_getgrnam.c
@@ -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);
diff --git a/source3/winbindd/winbindd_getgroups.c b/source3/winbindd/winbindd_getgroups.c
index 68b470d6dad..f7f2df5f7b1 100644
--- a/source3/winbindd/winbindd_getgroups.c
+++ b/source3/winbindd/winbindd_getgroups.c
@@ -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);
diff --git a/source3/winbindd/winbindd_getpwnam.c b/source3/winbindd/winbindd_getpwnam.c
index 26686bf9f0f..8da66c25141 100644
--- a/source3/winbindd/winbindd_getpwnam.c
+++ b/source3/winbindd/winbindd_getpwnam.c
@@ -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);
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 8403d7d57b6..9c66c6bdb82 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -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) - "
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 0cbcbad2a96..c4b27575b32 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -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,
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 1317dfe422d..068be91dca5 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -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 (strlen(domuser) == 0) {
+ return false;
+ }
- if ( !p ) {
+ p = strchr(domuser, *lp_winbind_separator());
+ if (p != NULL) {
+ fstrcpy(user, p + 1);
+ fstrcpy(domain, domuser);
+ domain[PTR_DIFF(p, domuser)] = '\0';
+ fstrcpy(namespace, domain);
+ } else {
fstrcpy(user, domuser);
- p = strchr(domuser, '@');
- if ( assume_domain(lp_workgroup()) && p == NULL) {
+ 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());
- } else if (p != NULL) {
- fstrcpy(domain, p + 1);
- user[PTR_DIFF(p, domuser)] = 0;
- } else {
- return False;
+ fstrcpy(namespace, domain);
}
- } else {
- fstrcpy(user, p+1);
- fstrcpy(domain, domuser);
- domain[PTR_DIFF(p, domuser)] = 0;
}
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",