summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/pam_winbind.c101
-rw-r--r--source3/nsswitch/wbinfo.c7
-rw-r--r--source3/nsswitch/winbindd_cache.c3
-rw-r--r--source3/nsswitch/winbindd_util.c19
4 files changed, 127 insertions, 3 deletions
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
index db3a089329..a9b55372e9 100644
--- a/source3/nsswitch/pam_winbind.c
+++ b/source3/nsswitch/pam_winbind.c
@@ -1614,6 +1614,89 @@ int get_warn_pwd_expire_from_config(const pam_handle_t *pamh,
return ret;
}
+/**
+ * Retrieve the winbind separator.
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ *
+ * @return string separator character. NULL on failure.
+ */
+
+static char winbind_get_separator(pam_handle_t *pamh, int ctrl)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (pam_winbind_request_log(pamh, ctrl, WINBINDD_INFO, &request, &response, NULL)) {
+ return '\0';
+ }
+
+ return response.data.info.winbind_separator;
+}
+
+/**
+ * Convert a upn to a name.
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param upn USer UPN to be trabslated.
+ *
+ * @return converted name. NULL pointer on failure. Caller needs to free.
+ */
+
+static char* winbind_upn_to_username(pam_handle_t *pamh, int ctrl, const char *upn)
+{
+ struct winbindd_request req;
+ struct winbindd_response resp;
+ int retval;
+ char *account_name;
+ int account_name_len;
+ char sep;
+
+ /* This cannot work when the winbind separator = @ */
+
+ sep = winbind_get_separator(pamh, ctrl);
+ if (!sep || sep == '@') {
+ return NULL;
+ }
+
+ /* Convert the UPN to a SID */
+
+ ZERO_STRUCT(req);
+ ZERO_STRUCT(resp);
+
+ strncpy(req.data.name.dom_name, "",
+ sizeof(req.data.name.dom_name) - 1);
+ strncpy(req.data.name.name, upn,
+ sizeof(req.data.name.name) - 1);
+ retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME,
+ &req, &resp, upn);
+ if ( retval != PAM_SUCCESS ) {
+ return NULL;
+ }
+
+ /* Convert the the SID back to the sAMAccountName */
+
+ ZERO_STRUCT(req);
+ strncpy(req.data.sid, resp.data.sid.sid, sizeof(req.data.sid)-1);
+ ZERO_STRUCT(resp);
+ retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPSID,
+ &req, &resp, upn);
+ if ( retval != PAM_SUCCESS ) {
+ return NULL;
+ }
+
+ account_name_len = asprintf(&account_name, "%s\\%s",
+ resp.data.name.dom_name,
+ resp.data.name.name);
+
+ return account_name;
+}
+
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh, int flags,
int argc, const char **argv)
@@ -1646,6 +1729,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
goto out;
}
+
#if defined(AIX)
/* Decode the user name since AIX does not support logn user
names by default. The name is encoded as _#uid. */
@@ -1670,6 +1754,19 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
}
}
+ /* Maybe this was a UPN */
+
+ if (strchr(real_username, '@') != NULL) {
+ char *samaccountname = NULL;
+
+ samaccountname = winbind_upn_to_username(pamh, ctrl,
+ real_username);
+ if (samaccountname) {
+ free(real_username);
+ real_username = samaccountname;
+ }
+ }
+
retval = _winbind_read_password(pamh, ctrl, NULL,
"Password: ", NULL,
&password);
@@ -1697,8 +1794,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
ctrl, d);
/* Now use the username to look up password */
- retval = winbind_auth_request(pamh, ctrl, username, password, member,
- cctype, warn_pwd_expire, NULL, NULL,
+ retval = winbind_auth_request(pamh, ctrl, real_username, password, member,
+ cctype, warn_pwd_expire, NULL, NULL,
&username_ret);
if (retval == PAM_NEW_AUTHTOK_REQD ||
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index e0bda948ed..be51618820 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -105,6 +105,13 @@ static BOOL parse_wbinfo_domain_user(const char *domuser, fstring domain,
char *p = strchr(domuser,winbind_separator());
if (!p) {
+ /* Maybe it was a UPN? */
+ if ((p = strchr(domuser, '@')) != NULL) {
+ fstrcpy(domain, "");
+ fstrcpy(user, domuser);
+ return True;
+ }
+
fstrcpy(user, domuser);
fstrcpy(domain, get_winbind_domain());
return True;
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 72ea7e4e78..9daee1c9f6 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -1411,7 +1411,8 @@ do_query:
wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
}
- if (NT_STATUS_IS_OK(status)) {
+ /* Only save the reverse mapping if this was not a UPN */
+ if (NT_STATUS_IS_OK(status) && !strchr(name, '@')) {
strupper_m(CONST_DISCARD(char *,domain_name));
strlower_m(CONST_DISCARD(char *,name));
wcache_save_sid_to_name(domain, status, sid, domain_name, name, *type);
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 7170e0fc6e..591d2355d9 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -1076,6 +1076,8 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
if ( assume_domain(lp_workgroup())) {
fstrcpy(domain, lp_workgroup());
+ } else if ((p = strchr(domuser, '@')) != NULL) {
+ fstrcpy(domain, "");
} else {
return False;
}
@@ -1262,6 +1264,23 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
}
}
+ /* Add any Universal groups in the other_sids list */
+
+ for (i=0; i<info3->num_other_sids; i++) {
+ /* Skip Domain local groups outside our domain.
+ We'll get these from the getsidaliases() RPC call. */
+ if (info3->other_sids_attrib[i] & SE_GROUP_RESOURCE)
+ continue;
+
+ if (!add_sid_to_array(mem_ctx, &info3->other_sids[i].sid,
+ user_sids, &num_groups))
+ {
+ TALLOC_FREE(info3);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+
TALLOC_FREE(info3);
*p_num_groups = num_groups;
status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;