summaryrefslogtreecommitdiff
path: root/source/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'source/nsswitch')
-rw-r--r--source/nsswitch/pam_winbind.c64
-rw-r--r--source/nsswitch/pam_winbind.h1
-rw-r--r--source/nsswitch/wbinfo.c41
-rw-r--r--source/nsswitch/winbind_nss_linux.c41
-rw-r--r--source/nsswitch/winbindd.c25
-rw-r--r--source/nsswitch/winbindd_cache.c4
-rw-r--r--source/nsswitch/winbindd_dual.c2
-rw-r--r--source/nsswitch/winbindd_group.c7
-rw-r--r--source/nsswitch/winbindd_sid.c78
-rw-r--r--source/nsswitch/winbindd_user.c2
-rw-r--r--source/nsswitch/winbindd_util.c8
11 files changed, 175 insertions, 98 deletions
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 123f6703665..64e21738221 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -45,6 +45,8 @@ static int _pam_parse(int argc, const char **argv)
ctrl |= WINBIND_TRY_FIRST_PASS_ARG;
else if (!strcasecmp(*argv, "unknown_ok"))
ctrl |= WINBIND_UNKNOWN_OK_ARG;
+ else if (!strncasecmp(*argv, "required_membership", strlen("required_membership")))
+ ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
else {
_pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
}
@@ -148,7 +150,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
switch (retval) {
case PAM_AUTH_ERR:
/* incorrect password */
- _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user);
+ _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid membership)", user);
return retval;
case PAM_ACCT_EXPIRED:
/* account expired */
@@ -174,7 +176,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
case PAM_SUCCESS:
if (req_type == WINBINDD_PAM_AUTH) {
/* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted acces", user);
+ _pam_log(LOG_NOTICE, "user '%s' granted access", user);
} else if (req_type == WINBINDD_PAM_CHAUTHTOK) {
/* Otherwise, the authentication looked good */
_pam_log(LOG_NOTICE, "user '%s' password changed", user);
@@ -192,7 +194,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
}
/* talk to winbindd */
-static int winbind_auth_request(const char *user, const char *pass, int ctrl)
+static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -204,7 +206,35 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
strncpy(request.data.auth.pass, pass,
sizeof(request.data.auth.pass)-1);
-
+
+ if (member == NULL )
+ return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+
+ /* lookup name? */
+ if (!strncmp("S-", member, 2) == 0) {
+
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (ctrl & WINBIND_DEBUG_ARG)
+ _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member);
+
+ /* fortunatly winbindd can handle non-separated names */
+ strcpy(request.data.name.name, member);
+
+ if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) {
+ _pam_log(LOG_INFO, "could not lookup name: %s\n", member);
+ return PAM_AUTH_ERR;
+ }
+
+ member = strdup(response.data.sid.sid);
+ }
+
+ strncpy(request.data.auth.required_membership_sid, member,
+ sizeof(request.data.auth.required_membership_sid)-1);
return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
}
@@ -419,7 +449,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
{
const char *username;
const char *password;
+ const char *member = NULL;
int retval = PAM_AUTH_ERR;
+ int i;
/* parse arguments */
int ctrl = _pam_parse(argc, argv);
@@ -453,8 +485,25 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
#endif
}
+ /* Retrieve membership-string here */
+ for ( i=0; i<argc; i++ ) {
+
+ if (!strncmp(argv[i], "required_membership", strlen("required_membership"))) {
+
+ char *p;
+ char *parm = strdup(argv[i]);
+
+ if ( (p = strchr( parm, '=' )) == NULL) {
+ _pam_log(LOG_INFO, "no \"=\" delimiter for \"required_membership\" found\n");
+ break;
+ }
+
+ member = strdup(p+1);
+ }
+ }
+
/* Now use the username to look up password */
- return winbind_auth_request(username, password, ctrl);
+ return winbind_auth_request(username, password, member, ctrl);
}
PAM_EXTERN
@@ -502,7 +551,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
return PAM_USER_UNKNOWN;
case 0:
/* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted acces", username);
+ _pam_log(LOG_NOTICE, "user '%s' granted access", username);
return PAM_SUCCESS;
default:
/* we don't know anything about this return value */
@@ -546,6 +595,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/* <DO NOT free() THESE> */
const char *user;
+ const char *member = NULL;
char *pass_old, *pass_new;
/* </DO NOT free() THESE> */
@@ -606,7 +656,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
}
/* verify that this is the password for this user */
- retval = winbind_auth_request(user, pass_old, ctrl);
+ retval = winbind_auth_request(user, pass_old, member, ctrl);
if (retval != PAM_ACCT_EXPIRED
&& retval != PAM_AUTHTOK_EXPIRED
diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
index 0afcceb6aa2..7cae477714b 100644
--- a/source/nsswitch/pam_winbind.h
+++ b/source/nsswitch/pam_winbind.h
@@ -82,6 +82,7 @@ do { \
#define WINBIND_TRY_FIRST_PASS_ARG (1<<3)
#define WINBIND_USE_FIRST_PASS_ARG (1<<4)
#define WINBIND__OLD_PASSWORD (1<<5)
+#define WINBIND_REQUIRED_MEMBERSHIP (1<<6)
/*
* here is the string to inform the user that the new passwords they
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 0028982d201..b6a09bf2a1f 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -398,27 +398,6 @@ static BOOL wbinfo_sid_to_uid(char *sid)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- /* First see whether the SID is actually a user -- otherwise
- * winbind might end up a uid number for a group SID and this
- * is asking for trouble later. */
-
- fstrcpy(request.data.sid, sid);
-
- if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("Could not lookup sid %s\n", sid);
- return False;
- }
-
- if (response.data.name.type != SID_NAME_USER) {
- d_printf("SID is of type %s\n",
- sid_type_lookup(response.data.name.type));
- return False;
- }
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
/* Send request */
fstrcpy(request.data.sid, sid);
@@ -442,26 +421,6 @@ static BOOL wbinfo_sid_to_gid(char *sid)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- /* First see whether the SID is actually a group -- otherwise
- * winbind might end up a gid number for a user SID and this
- * is asking for trouble later. */
-
- fstrcpy(request.data.sid, sid);
-
- if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("Could not lookup sid %s\n", sid);
- return False;
- }
-
- if ((response.data.name.type != SID_NAME_DOM_GRP) &&
- (response.data.name.type != SID_NAME_ALIAS) &&
- (response.data.name.type != SID_NAME_WKN_GRP)) {
- d_printf("SID is of type %s\n",
- sid_type_lookup(response.data.name.type));
- return False;
- }
-
/* Send request */
fstrcpy(request.data.sid, sid);
diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c
index ae2bcc7ade9..0ea5db74da6 100644
--- a/source/nsswitch/winbind_nss_linux.c
+++ b/source/nsswitch/winbind_nss_linux.c
@@ -833,25 +833,40 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
/* Skip primary group */
- if (gid_list[i] == group) continue;
-
- /* Add to buffer */
+ if (gid_list[i] == group) {
+ continue;
+ }
- if (*start == *size && limit <= 0) {
- (*groups) = realloc(
- (*groups), (2 * (*size) + 1) * sizeof(**groups));
- if (! *groups) goto done;
- *size = 2 * (*size) + 1;
+ /* Filled buffer ? If so, resize. */
+
+ if (*start == *size) {
+ long int newsize;
+ gid_t *newgroups;
+
+ newsize = 2 * (*size);
+ if (limit > 0) {
+ if (*size == limit) {
+ goto done;
+ }
+ if (newsize > limit) {
+ newsize = limit;
+ }
+ }
+
+ newgroups = realloc((*groups), newsize * sizeof(**groups));
+ if (!newgroups) {
+ *errnop = ENOMEM;
+ ret = NSS_STATUS_NOTFOUND;
+ goto done;
+ }
+ *groups = newgroups;
+ *size = newsize;
}
- if (*start == *size) goto done;
+ /* Add to buffer */
(*groups)[*start] = gid_list[i];
*start += 1;
-
- /* Filled buffer? */
-
- if (*start == limit) goto done;
}
}
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index d08aa84face..455fb74f171 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -28,6 +28,8 @@
BOOL opt_nocache = False;
BOOL opt_dual_daemon = True;
+extern BOOL override_logfile;
+
/* Reload configuration */
static BOOL reload_services_file(void)
@@ -587,6 +589,7 @@ static void process_loop(void)
int maxfd, listen_sock, listen_priv_sock, selret;
struct timeval timeout;
+ again:
/* Handle messages */
message_dispatch();
@@ -715,6 +718,15 @@ static void process_loop(void)
for (state = winbindd_client_list(); state;
state = state->next) {
+ /* Data available for writing */
+
+ if (FD_ISSET(state->sock, &w_fds))
+ client_write(state);
+ }
+
+ for (state = winbindd_client_list(); state;
+ state = state->next) {
+
/* Data available for reading */
if (FD_ISSET(state->sock, &r_fds)) {
@@ -747,13 +759,10 @@ static void process_loop(void)
if (state->read_buf_len ==
sizeof(state->request)) {
winbind_process_packet(state);
+ winbindd_demote_client(state);
+ goto again;
}
}
-
- /* Data available for writing */
-
- if (FD_ISSET(state->sock, &w_fds))
- client_write(state);
}
}
@@ -846,8 +855,10 @@ int main(int argc, char **argv)
exit(1);
}
- pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE);
- lp_set_logfile(logfile);
+ if (!override_logfile) {
+ pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE);
+ lp_set_logfile(logfile);
+ }
setup_logging("winbindd", log_stdout);
reopen_logs();
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index b81f8ecd45a..493255a5a65 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -609,7 +609,6 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
{
struct cache_entry *centry;
fstring uname;
- fstring sid_string;
centry = centry_start(domain, status);
if (!centry)
@@ -619,7 +618,8 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
fstrcpy(uname, name);
strupper_m(uname);
centry_end(centry, "NS/%s/%s", domain_name, uname);
- DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string));
+ DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname,
+ sid_string_static(sid)));
centry_free(centry);
}
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index a9796afa367..d4ec6e586db 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -155,7 +155,7 @@ void do_dual_daemon(void)
dual_daemon_pipe = fdpair[1];
state.sock = fdpair[0];
- if (fork() != 0) {
+ if (sys_fork() != 0) {
close(fdpair[0]);
return;
}
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index ca7f72d0178..a3b826278b5 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -495,8 +495,6 @@ enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state)
The dispinfo_ndx field is incremented to the index of the next group to
fetch. Return True if some groups were returned, False otherwise. */
-#define MAX_FETCH_SAM_ENTRIES 100
-
static BOOL get_sam_group_entries(struct getent_state *ent)
{
NTSTATUS status;
@@ -925,14 +923,11 @@ static void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num)
{
int i;
- if ((*num) >= groups_max())
- return;
-
for (i=0; i<*num; i++) {
if ((*gids)[i] == gid)
return;
}
-
+
*gids = Realloc(*gids, (*num+1) * sizeof(gid_t));
if (*gids == NULL)
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index 61da9b3d92f..c6e503bef39 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -119,7 +119,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 flags = 0x0;
+ NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -166,8 +166,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
/* But first check and see if we don't already have a mapping */
- flags = ID_QUERY_ONLY;
- if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) )
+ if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), ID_QUERY_ONLY)) )
return WINBINDD_OK;
/* now fall back to the hard way */
@@ -191,17 +190,37 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
}
- if ( state->request.flags & WBFLAG_QUERY_ONLY )
- flags = ID_QUERY_ONLY;
-
/* Find uid for this sid and return it */
-
- if ( !NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) {
- DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
+
+ result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
+ ID_QUERY_ONLY);
+
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ if (state->request.flags & WBFLAG_QUERY_ONLY)
return WINBINDD_ERROR;
+
+ /* The query-only did not work, allocate a new uid *if* it's a user */
+
+ {
+ fstring dom_name, name;
+ enum SID_NAME_USE type;
+
+ if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type))
+ return WINBINDD_ERROR;
+
+ if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER))
+ return WINBINDD_ERROR;
}
+
+ result = idmap_sid_to_uid(&sid, &(state->response.data.uid), 0);
- return WINBINDD_OK;
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
+ return WINBINDD_ERROR;
}
/* Convert a sid to a gid. We assume we only have one rid attached to the
@@ -210,7 +229,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 flags = 0x0;
+ NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -256,8 +275,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
/* But first check and see if we don't already have a mapping */
- flags = ID_QUERY_ONLY;
- if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) )
+ if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), ID_QUERY_ONLY)) )
return WINBINDD_OK;
/* now fall back to the hard way */
@@ -281,16 +299,38 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
}
- if ( state->request.flags & WBFLAG_QUERY_ONLY )
- flags = ID_QUERY_ONLY;
-
/* Find gid for this sid and return it */
- if ( !NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) ) {
- DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid));
+
+ result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
+ ID_QUERY_ONLY);
+
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ if (state->request.flags & WBFLAG_QUERY_ONLY)
return WINBINDD_ERROR;
+
+ /* The query-only did not work, allocate a new gid *if* it's a group */
+
+ {
+ fstring dom_name, name;
+ enum SID_NAME_USE type;
+
+ if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type))
+ return WINBINDD_ERROR;
+
+ if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP))
+ return WINBINDD_ERROR;
}
+
+ result = idmap_sid_to_gid(&sid, &(state->response.data.gid), 0);
- return WINBINDD_OK;
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid));
+ return WINBINDD_ERROR;
}
/* Convert a uid to a sid */
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 795d657aae7..6f5a86f43ae 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -385,8 +385,6 @@ enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state)
field is incremented to the index of the next user to fetch. Return True if
some users were returned, False otherwise. */
-#define MAX_FETCH_SAM_ENTRIES 100
-
static BOOL get_sam_user_entries(struct getent_state *ent)
{
NTSTATUS status;
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index faa6e8d8da4..a9197d35616 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -736,6 +736,14 @@ void winbindd_remove_client(struct winbindd_cli_state *cli)
_num_clients--;
}
+/* Demote a client to be the last in the list */
+
+void winbindd_demote_client(struct winbindd_cli_state *cli)
+{
+ struct winbindd_cli_state *tmp;
+ DLIST_DEMOTE(_client_list, cli, tmp);
+}
+
/* Close all open clients */
void winbindd_kill_all_clients(void)