summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/nsswitch/winbindd.c705
-rw-r--r--source/nsswitch/winbindd_group.c372
-rw-r--r--source/nsswitch/winbindd_user.c316
3 files changed, 558 insertions, 835 deletions
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index 358ed9ebf03..40485560b2d 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -1,6 +1,7 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
+
Winbind daemon for ntdom nss module
Copyright (C) Tim Potter 2000
@@ -27,438 +28,412 @@
#include <unistd.h>
#include "includes.h"
-#include "sids.h"
-
-/* Connect to a domain controller and return the domain name and sid */
-
-BOOL lookup_domain_sid(fstring domain_name, DOM_SID *domain_sid,
- fstring domain_controller)
-{
- POLICY_HND lsa_handle;
- DOM_SID level3_sid, level5_sid;
- fstring level3_dom, level5_dom;
- fstring system_name;
- BOOL res;
-
- if (!get_any_dc_name(domain_name, system_name)) {
- return False;
- }
-
- if (domain_controller != NULL) {
- fstrcpy(domain_controller, system_name);
- }
- /* Get SID from domain controller */
+/* List of all connected clients */
- res = lsa_open_policy(system_name, &lsa_handle, False,
- SEC_RIGHTS_MAXIMUM_ALLOWED);
+static struct winbindd_state *client_list;
- res = res ? lsa_query_info_pol(&lsa_handle, 0x03, level3_dom,
- &level3_sid) : False;
-
- res = res ? lsa_query_info_pol(&lsa_handle, 0x05, level5_dom,
- &level5_sid) : False;
-
- lsa_close(&lsa_handle);
+/* Handle termination signals */
- /* Return domain sid if successful */
+static void termination_handler(int signum)
+{
+ /* Remove socket file */
- if (res && (domain_sid != NULL)) {
- sid_copy(domain_sid, &level5_sid);
- fstrcpy(domain_name, level5_dom);
- }
+ unlink(WINBINDD_SOCKET_DIR "/" WINBINDD_SOCKET_NAME);
- return res;
+ exit(0);
}
-/* Lookup a sid and type within a domain from a username */
+/* Create winbindd socket */
-BOOL winbindd_lookup_by_name(char *system_name, DOM_SID *level5_sid,
- fstring name, DOM_SID *sid,
- enum SID_NAME_USE *type)
+static int create_sock(void)
{
- POLICY_HND lsa_handle;
- BOOL res;
- DOM_SID *sids = NULL;
- int num_sids = 0, num_names = 1;
- uint32 *types = NULL;
-
- if (name == NULL) {
- return 0;
- }
-
- res = lsa_open_policy(system_name, &lsa_handle, True,
- SEC_RIGHTS_MAXIMUM_ALLOWED);
-
- res = res ? lsa_lookup_names(&lsa_handle, num_names, (char **)&name,
- &sids, &types, &num_sids) : False;
-
- lsa_close(&lsa_handle);
-
- /* Return rid and type if lookup successful */
-
- if (res) {
+ struct sockaddr_un sunaddr;
+ struct stat st;
+ int sock;
+ mode_t old_umask;
+ char *path = WINBINDD_SOCKET_DIR "/" WINBINDD_SOCKET_NAME;
- if ((sid != NULL) && (sids != NULL)) {
- sid_copy(sid, &sids[0]);
- }
+ /* Create the socket directory or reuse the existing one */
- if ((type != NULL) && (types != NULL)) {
- *type = types[0];
- }
+ if ((lstat(WINBINDD_SOCKET_DIR, &st) == -1) && (errno != ENOENT)) {
+ DEBUG(0, ("lstat failed on socket directory %s: %s\n",
+ WINBINDD_SOCKET_DIR, sys_errlist[errno]));
+ return -1;
}
-
- /* Free memory */
-
- if (types != NULL) { free(types); }
- if (sids != NULL) { free(sids); }
- return res;
-}
-
-/* Lookup a name and type within a domain from a sid */
-
-int winbindd_lookup_by_sid(char *system_name, DOM_SID *level5_sid,
- DOM_SID *sid, char *name,
- enum SID_NAME_USE *type)
-{
- POLICY_HND lsa_handle;
- int num_sids = 1, num_names = 0;
- uint32 *types = NULL;
- char **names;
- BOOL res;
+ if (errno == ENOENT) {
- res = lsa_open_policy(system_name, &lsa_handle, True,
- SEC_RIGHTS_MAXIMUM_ALLOWED);
+ /* Create directory */
- res = res ? lsa_lookup_sids(&lsa_handle, num_sids, &sid,
- &names, &types, &num_names) : False;
+ if (mkdir(WINBINDD_SOCKET_DIR, 0755) == -1) {
+ DEBUG(0, ("error creating socket directory %s: %s\n",
+ WINBINDD_SOCKET_DIR, sys_errlist[errno]));
+ return -1;
+ }
- lsa_close(&lsa_handle);
+ } else {
- /* Return name and type if successful */
+ /* Check ownership and permission on existing directory */
- if (res) {
- if ((names != NULL) && (name != NULL)) {
- fstrcpy(name, names[0]);
+ if (!S_ISDIR(st.st_mode)) {
+ DEBUG(0, ("socket directory %s isn't a directory\n",
+ WINBINDD_SOCKET_DIR));
+ return -1;
}
- if ((type != NULL) && (types != NULL)) {
- *type = types[0];
+ if ((st.st_uid != 0) || ((st.st_mode & 0777) != 0755)) {
+ DEBUG(0, ("invalid permissions on socket directory %s\n",
+ WINBINDD_SOCKET_DIR));
+ return -1;
}
}
- /* Free memory */
-
- if (types != NULL) { free(types); }
+ /* Create the socket file */
- if (names != NULL) {
- int i;
+ old_umask = umask(0);
- for (i = 0; i < num_names; i++) {
- if (names[i] != NULL) {
- free(names[i]);
- }
- free(names);
- }
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ if (sock == -1) {
+ perror("socket");
+ return -1;
}
-
- return res;
+
+ unlink(path);
+ memset(&sunaddr, 0, sizeof(sunaddr));
+ sunaddr.sun_family = AF_UNIX;
+ strncpy(sunaddr.sun_path, path,
+ sizeof(sunaddr.sun_path));
+
+ if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
+ DEBUG(0, ("bind failed on winbind socket %s: %s\n",
+ path,
+ sys_errlist[errno]));
+ close(sock);
+ return -1;
+ }
+
+ if (listen(sock, 5) == -1) {
+ DEBUG(0, ("listen failed on winbind socket %s: %s\n",
+ path,
+ sys_errlist[errno]));
+ close(sock);
+ return -1;
+ }
+
+ umask(old_umask);
+
+ /* Success! */
+
+ return sock;
}
-/* Lookup user information from a rid */
-int winbindd_lookup_userinfo(char *system_name, DOM_SID *dom_sid,
- uint32 user_rid, POLICY_HND *sam_dom_handle,
- SAM_USERINFO_CTR *user_info)
+static void process_request(struct winbindd_state *state)
{
- POLICY_HND sam_handle, local_sam_dom_handle;
- BOOL res = True, local_handle = False;
-
- if (sam_dom_handle == NULL) {
- sam_dom_handle = &local_sam_dom_handle;
- local_handle = True;
+ /* Process command */
+
+ state->response.result = WINBINDD_ERROR;
+
+ switch(state->request.cmd) {
+
+ /* User functions */
+
+ case WINBINDD_GETPWNAM_FROM_USER:
+ state->response.result = winbindd_getpwnam_from_user(state);
+ break;
+
+ case WINBINDD_GETPWNAM_FROM_UID:
+ state->response.result = winbindd_getpwnam_from_uid(state);
+ break;
+
+ case WINBINDD_SETPWENT:
+ fprintf(stderr, "calling setpwent()\n");
+ state->response.result = winbindd_setpwent(state);
+ break;
+
+ case WINBINDD_ENDPWENT:
+ fprintf(stderr, "calling endpwent()\n");
+ state->response.result = winbindd_endpwent(state);
+ break;
+
+ case WINBINDD_GETPWENT:
+ fprintf(stderr, "calling getpwent()\n");
+ state->response.result = winbindd_getpwent(state);
+ break;
+
+ /* Group functions */
+
+ case WINBINDD_GETGRNAM_FROM_GROUP:
+ state->response.result = winbindd_getgrnam_from_group(state);
+ break;
+
+ case WINBINDD_GETGRNAM_FROM_GID:
+ state->response.result = winbindd_getgrnam_from_gid(state);
+ break;
+
+ case WINBINDD_SETGRENT:
+ state->response.result = winbindd_setgrent(state);
+ break;
+
+ case WINBINDD_ENDGRENT:
+ state->response.result = winbindd_endgrent(state);
+ break;
+
+ case WINBINDD_GETGRENT:
+ state->response.result = winbindd_getgrent(state);
+ break;
+
+ /* Oops */
+
+ default:
+ DEBUG(0, ("oops - unknown winbindd command %d\n", state->request.cmd));
+ break;
}
+}
- /* Open connection to SAM pipe and SAM domain */
-
- if (local_handle) {
-
- res = samr_connect(system_name, SEC_RIGHTS_MAXIMUM_ALLOWED,
- &sam_handle);
+/* Process a new connection by adding it to the client connection list */
- res = res ? samr_open_domain(&sam_handle, SEC_RIGHTS_MAXIMUM_ALLOWED,
- dom_sid, sam_dom_handle) : False;
+static void new_connection(int accept_sock)
+{
+ struct sockaddr_un sunaddr;
+ struct winbindd_state *state;
+ int len, sock;
+
+ /* Accept connection */
+
+ len = sizeof(sunaddr);
+ if ((sock = accept(accept_sock, (struct sockaddr *)&sunaddr, &len))
+ == -1) {
+
+ return;
}
- /* Get user info */
-
- res = res ? get_samr_query_userinfo(sam_dom_handle, 0x15,
- user_rid, user_info) : False;
+ fprintf(stderr, "accepted socket %d\n", sock);
- /* Close up shop */
+ /* Create new connection structure */
- if (local_handle) {
- samr_close(sam_dom_handle);
- samr_close(&sam_handle);
+ if ((state = (struct winbindd_state *)malloc(sizeof(*state))) == NULL) {
+ return;
}
- return res;
-}
+ ZERO_STRUCTP(state);
+ state->sock = sock;
-/* Lookup group information from a rid */
+ /* Add to connection list */
-int winbindd_lookup_groupinfo(char *system_name, DOM_SID *dom_sid,
- uint32 group_rid, GROUP_INFO_CTR *info)
+ DLIST_ADD(client_list, state);
+}
+
+/* Remove a client connection from client connection list */
+
+static void remove_client(struct winbindd_state *state)
{
- POLICY_HND sam_handle, sam_dom_handle;
- BOOL res;
+ /* It's a dead client - hold a funeral */
- /* Open connection to SAM pipe and SAM domain */
+ close(state->sock);
+// free_state_info(state);
+ DLIST_REMOVE(client_list, state);
+ free(state);
+}
- res = samr_connect(system_name, SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_handle);
+/* Process a complete received packet from a client */
- res = res ? samr_open_domain(&sam_handle, SEC_RIGHTS_MAXIMUM_ALLOWED,
- dom_sid, &sam_dom_handle) : False;
- /* Query group info */
-
- res = res ? get_samr_query_groupinfo(&sam_dom_handle, 1,
- group_rid, info) : False;
+static void process_packet(struct winbindd_state *state)
+{
+ /* Process request */
- /* Close up shop */
+ process_request(state);
- samr_close(&sam_dom_handle);
- samr_close(&sam_handle);
+ /* Update client state */
- return res;
+ state->read_buf_len = 0;
+ state->write_buf_len = sizeof(state->response);
}
-/* Lookup group membership given a rid */
+/* Read some data from a client connection */
-int winbindd_lookup_groupmem(char *system_name, DOM_SID *dom_sid,
- uint32 group_rid, POLICY_HND *sam_dom_handle,
- uint32 *num_names, uint32 **rid_mem,
- char ***names, uint32 **name_types)
+static void client_read(struct winbindd_state *state)
{
- POLICY_HND sam_handle, local_sam_dom_handle;
- BOOL res = True, local_handle = False;
-
- if (sam_dom_handle == NULL) {
- sam_dom_handle = &local_sam_dom_handle;
- local_handle = True;
- }
+ int n;
+
+ /* Read data */
- /* Open connection to SAM pipe and SAM domain */
+ n = read(state->sock, state->read_buf_len + (char *)&state->request,
+ sizeof(state->request) - state->read_buf_len);
- if (local_handle) {
+ fprintf(stderr, "read returned %d on sock %d\n", n, state->sock);
- res = samr_connect(system_name, SEC_RIGHTS_MAXIMUM_ALLOWED,
- &sam_handle);
+ /* Read failed, kill client */
- res = res ? samr_open_domain(&sam_handle, SEC_RIGHTS_MAXIMUM_ALLOWED,
- dom_sid, sam_dom_handle) : False;
+ if ((n == -1) || (n == 0)) {
+ fprintf(stderr, "finished reading, n = %d\n", n);
+ state->finished = True;
+ return;
}
- /* Query group membership */
-
- res = res ? sam_query_groupmem(sam_dom_handle, group_rid, num_names,
- rid_mem, names, name_types) : False;
- /* Close up shop */
+ /* Update client state */
- if (local_handle) {
- samr_close(sam_dom_handle);
- samr_close(&sam_handle);
- }
-
- return res;
+ state->read_buf_len += n;
}
-/* Lookup alias membership given a rid */
+/* Write some data to a client connection */
-int winbindd_lookup_aliasmem(char *system_name, DOM_SID *dom_sid,
- uint32 alias_rid, POLICY_HND *sam_dom_handle,
- uint32 *num_names, DOM_SID ***sids,
- char ***names, uint32 **name_types)
+static void client_write(struct winbindd_state *state)
{
- POLICY_HND sam_handle, local_sam_dom_handle;
- BOOL res = True, local_handle = False;
+ int n;
- if (sam_dom_handle == NULL) {
- sam_dom_handle = &local_sam_dom_handle;
- local_handle = True;
- }
+ /* Write data */
- /* Open connection to SAM pipe and SAM domain */
+ n = write(state->sock, (sizeof(state->response) - state->write_buf_len) +
+ (char *)&state->response,
+ state->write_buf_len);
- if (local_handle) {
+ fprintf(stderr, "write returned %d on sock %d\n", n, state->sock);
- res = samr_connect(system_name, SEC_RIGHTS_MAXIMUM_ALLOWED,
- &sam_handle);
+ /* Write failed, kill cilent */
- res = res ? samr_open_domain(&sam_handle, SEC_RIGHTS_MAXIMUM_ALLOWED,
- dom_sid, sam_dom_handle) : False;
+ if (n == -1 || n == 0) {
+ fprintf(stderr, "finished writing\n");
+ state->finished = True;
+ return;
}
- /* Query alias membership */
+ /* Update client state */
- res = res ? sam_query_aliasmem(system_name, sam_dom_handle, alias_rid,
- num_names, sids, names, name_types)
- : False;
-
- /* Close up shop */
-
- if (local_handle) {
- samr_close(sam_dom_handle);
- samr_close(&sam_handle);
- }
-
- return res;
+ state->write_buf_len -= n;
}
-/* Lookup alias information given a rid */
+/* Process incoming clients on accept_sock. We use a tricky non-blocking,
+ non-forking, non-threaded model which allows us to handle many
+ simultaneous connections while remaining impervious to many denial of
+ service attacks. */
-int winbindd_lookup_aliasinfo(char *system_name, DOM_SID *dom_sid,
- uint32 alias_rid, ALIAS_INFO_CTR *info)
+static void process_loop(int accept_sock)
{
- POLICY_HND sam_handle, sam_dom_handle;
- BOOL res;
+ /* We'll be doing this a lot */
- /* Open connection to SAM pipe and SAM domain */
+ while (1) {
+ struct winbindd_state *state;
+ fd_set r_fds, w_fds;
+ int maxfd = accept_sock, selret;
- res = samr_connect(system_name, SEC_RIGHTS_MAXIMUM_ALLOWED,
- &sam_handle);
+ /* Initialise fd lists for select() */
- res = res ? samr_open_domain(&sam_handle, SEC_RIGHTS_MAXIMUM_ALLOWED,
- dom_sid, &sam_dom_handle) : False;
- /* Query group info */
-
- res = res ? get_samr_query_aliasinfo(&sam_dom_handle, 1,
- alias_rid, info) : False;
+ FD_ZERO(&r_fds);
+ FD_ZERO(&w_fds);
+ FD_SET(accept_sock, &r_fds);
- /* Close up shop */
+ /* Set up client readers and writers */
- samr_close(&sam_dom_handle);
- samr_close(&sam_handle);
+ state = client_list;
- return res;
-}
+ while (state) {
-/* Handle termination signals */
+ /* Dispose of client connection if it is marked as finished */
-static void termination_handler(int signum)
-{
- /* Remove socket file */
+ if (state->finished) {
+ struct winbindd_state *next = state->next;
- unlink(WINBINDD_SOCKET_DIR "/" WINBINDD_SOCKET_NAME);
+ fprintf(stderr, "removing client sock %d\n", state->sock);
+ remove_client(state);
+ state = next;
+ continue;
+ }
- exit(0);
-}
+ /* Select requires we know the highest fd used */
-/* Create winbindd socket */
+ if (state->sock > maxfd) maxfd = state->sock;
-int create_sock(void)
-{
- struct sockaddr_un sunaddr;
- struct stat st;
- int sock;
- mode_t old_umask;
+ /* Add fd for reading */
- /* Create the socket directory or reuse the existing one */
+ if (state->read_buf_len != sizeof(state->request)) {
- if ((lstat(WINBINDD_SOCKET_DIR, &st) < 0) && (errno != ENOENT)) {
- DEBUG(0, ("lstat failed on socket directory %s: %s\n",
- WINBINDD_SOCKET_DIR, sys_errlist[errno]));
- return -1;
- }
+ fprintf(stderr, "adding sock %d for reading\n", state->sock);
+ FD_SET(state->sock, &r_fds);
+ }
- if (errno == ENOENT) {
+ /* Add fd for writing */
- /* Create directory */
+ if (state->write_buf_len) {
- if (mkdir(WINBINDD_SOCKET_DIR, 0755) < 0) {
- DEBUG(0, ("error creating socket directory %s: %s\n",
- WINBINDD_SOCKET_DIR, sys_errlist[errno]));
- return -1;
+ fprintf(stderr, "adding sock %d for writing\n", state->sock);
+ FD_SET(state->sock, &w_fds);
+ }
+
+ state = state->next;
}
- } else {
+ /* Call select */
+
+ fprintf(stderr, "calling select\n");
+ selret = select(maxfd + 1, &r_fds, &w_fds, NULL, NULL);
+
+ if (selret == -1 || selret == 0) {
- /* Check ownership and permission on existing directory */
+ /* Select error, something is badly wrong */
- if (!S_ISDIR(st.st_mode)) {
- DEBUG(0, ("socket directory %s isn't a directory\n",
- WINBINDD_SOCKET_DIR));
- return -1;
+ DEBUG(0, ("select returned %d", selret));
+ return;
}
- if ((st.st_uid != 0) || ((st.st_mode & 0777) != 0755)) {
- DEBUG(0, ("invalid permissions on socket directory %s\n",
- WINBINDD_SOCKET_DIR));
- return -1;
+ /* Create a new connection if accept_sock readable */
+
+ if (FD_ISSET(accept_sock, &r_fds)) {
+ new_connection(accept_sock);
}
- }
- /* Create the socket file */
+ /* Process activity on client connections */
- old_umask = umask(0);
+ for (state = client_list; state ; state = state->next) {
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
-
- if (sock < 0) {
- perror("socket");
- return -1;
- }
-
- memset(&sunaddr, 0, sizeof(sunaddr));
- sunaddr.sun_family = AF_UNIX;
- strncpy(sunaddr.sun_path, WINBINDD_SOCKET_DIR "/" WINBINDD_SOCKET_NAME,
- sizeof(sunaddr.sun_path));
-
- if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
- DEBUG(0, ("bind failed on winbind socket %s: %s\n",
- WINBINDD_SOCKET_DIR "/" WINBINDD_SOCKET_NAME,
- sys_errlist[errno]));
- close(sock);
- return -1;
- }
-
- if (listen(sock, 5) < 0) {
- DEBUG(0, ("listen failed on winbind socket %s: %s\n",
- WINBINDD_SOCKET_DIR "/" WINBINDD_SOCKET_NAME,
- sys_errlist[errno]));
- close(sock);
- return -1;
+ /* Data available for reading */
+
+ if (FD_ISSET(state->sock, &r_fds)) {
+
+ /* Read data */
+
+ client_read(state);
+
+ /* A request packet might be complete */
+
+ if (state->read_buf_len == sizeof(state->request)) {
+ process_packet(state);
+ }
+ }
+
+ /* Data available for writing */
+
+ if (FD_ISSET(state->sock, &w_fds)) {
+ client_write(state);
+ }
+ }
}
-
- umask(old_umask);
-
- /* Success! */
-
- return sock;
}
-/*
- * Main function
- */
+/* Main function */
int main(int argc, char **argv)
{
extern fstring global_myname;
- int sock, sock2;
extern pstring debugf;
+ int accept_sock;
/* Initialise samba/rpc client stuff */
- setup_logging("winbindd", False); /* XXX change to false for daemon log */
+ setup_logging("winbindd", True); /* XXX change to false for daemon log */
slprintf(debugf, sizeof(debugf), "%s/log.winbindd", LOGFILEBASE);
reopen_logs();
if (!*global_myname) {
char *p;
- fstrcpy( global_myname, myhostname() );
- p = strchr( global_myname, '.' );
- if (p)
+
+ fstrcpy(global_myname, myhostname());
+ p = strchr(global_myname, '.');
+ if (p) {
*p = 0;
+ }
}
TimeInit();
@@ -472,6 +447,11 @@ int main(int argc, char **argv)
pwdb_initialise(False);
+ if (!winbindd_surs_init()) {
+ DEBUG(0, ("Could not initialise surs information\n"));
+ return 1;
+ }
+
/* Setup signal handlers */
signal(SIGINT, termination_handler);
@@ -479,109 +459,16 @@ int main(int argc, char **argv)
signal(SIGTERM, termination_handler);
signal(SIGPIPE, SIG_IGN);
- /* Loop waiting for requests */
+ /* Create UNIX domain socket */
- if ((sock = create_sock()) == -1) {
+ if ((accept_sock = create_sock()) == -1) {
DEBUG(0, ("failed to create socket\n"));
return 1;
}
- /* Get the domain sid */
-
- if (!winbindd_surs_init()) {
- DEBUG(0, ("Could not initialise surs information\n"));
- return 1;
- }
-
- while (1) {
- int len;
- struct sockaddr_un sunaddr;
- struct winbindd_request request;
- struct winbindd_response response;
-
- /* Accept connection */
-
- len = sizeof(sunaddr);
- sock2 = accept(sock, (struct sockaddr *)&sunaddr, &len);
-
- /* Read command */
-
- if (read_sock(sock2, &request, sizeof(request)) < 0) {
- close(sock2);
- continue;
- }
-
- response.result = WINBINDD_ERROR;
-
- /* Process command */
-
- switch(request.cmd) {
-
- /* User functions */
-
- case WINBINDD_GETPWNAM_FROM_USER:
- response.result =
- winbindd_getpwnam_from_user(request.data.username, NULL,
- &response.data.pw);
- break;
-
- case WINBINDD_GETPWNAM_FROM_UID:
- response.result =
- winbindd_getpwnam_from_uid(request.data.uid, &response.data.pw);
- break;
-
- case WINBINDD_SETPWENT:
- response.result = winbindd_setpwent(request.pid);
- break;
-
- case WINBINDD_ENDPWENT:
- response.result = winbindd_endpwent(request.pid);
- break;
-
- case WINBINDD_GETPWENT:
- response.result =
- winbindd_getpwent(request.pid, &response.data.pw);
- break;
-
- /* Group functions */
-
- case WINBINDD_GETGRNAM_FROM_GROUP:
- response.result =
- winbindd_getgrnam_from_group(request.data.groupname, NULL,
- &response.data.gr);
- break;
-
- case WINBINDD_GETGRNAM_FROM_GID:
- response.result =
- winbindd_getgrnam_from_gid(request.data.gid,
- &response.data.gr);
- break;
-
- case WINBINDD_SETGRENT:
- response.result = winbindd_setgrent(request.pid);
- break;
-
- case WINBINDD_ENDGRENT:
- response.result = winbindd_endgrent(request.pid);
- break;
-
- case WINBINDD_GETGRENT:
- response.result =
- winbindd_getgrent(request.pid, &response.data.gr);
- break;
-
- /* Oops */
-
- default:
- DEBUG(0, ("oops - unknown winbindd command %d\n", request.cmd));
- break;
- }
-
- /* Send response */
+ /* Loop waiting for requests */
- write_sock(sock2, &response, sizeof(response));
- close(sock2);
- }
+ process_loop(accept_sock);
return 0;
}
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index 5d2618d6b7a..d4d977780cf 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -1,7 +1,9 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
+
Winbind daemon for ntdom nss module
+
Copyright (C) Tim Potter 2000
This program is free software; you can redistribute it and/or modify
@@ -143,7 +145,7 @@ static BOOL winbindd_fill_grent_mem(char *server_name, char *domain_name,
if (!winbindd_lookup_aliasmem(server_name, &domain_sid,
current_group->group_rid,
sam_dom_handle, &num_names,
- &rid_mem, &names, &name_types) &&
+ &sids, &names, &name_types) &&
!winbindd_lookup_aliasmem(server_name, global_sid_builtin,
current_group->group_rid,
sam_dom_handle, &num_sids,
@@ -294,18 +296,16 @@ static BOOL winbindd_fill_grent_mem(char *server_name, char *domain_name,
/* Return a group structure from a group name */
-enum winbindd_result winbindd_getgrnam_from_group(char *groupname,
- POLICY_HND *sam_dom_handle,
- struct winbindd_gr *gr)
+enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_state *state)
{
DOM_SID domain_sid, domain_group_sid;
- uint32 name_type;
+ uint32 name_type, group_rid;
fstring name_domain, name_group, temp_name, domain_controller;
POSIX_ID surs_gid;
/* Look for group domain name */
- fstrcpy(temp_name, groupname);
+ fstrcpy(temp_name, state->request.data.groupname);
fstrcpy(name_domain, strtok(temp_name, "/\\"));
fstrcpy(name_group, strtok(NULL, ""));
@@ -349,19 +349,15 @@ enum winbindd_result winbindd_getgrnam_from_group(char *groupname,
}
- if (gr != NULL) {
- DOM_SID temp;
- uint32 group_rid;
-
- winbindd_fill_grent(gr, groupname, surs_gid.id);
+ winbindd_fill_grent(&state->response.data.gr,
+ state->request.data.groupname, surs_gid.id);
- sid_copy(&temp, &domain_group_sid);
- sid_split_rid(&temp, &group_rid);
+ sid_split_rid(&domain_group_sid, &group_rid);
- if (!winbindd_fill_grent_mem(domain_controller, name_domain,
- group_rid, name_type, NULL, gr)) {
- return WINBINDD_ERROR;
- }
+ if (!winbindd_fill_grent_mem(domain_controller, name_domain,
+ group_rid, name_type, NULL,
+ &state->response.data.gr)) {
+ return WINBINDD_ERROR;
}
return WINBINDD_OK;
@@ -369,18 +365,17 @@ enum winbindd_result winbindd_getgrnam_from_group(char *groupname,
/* Return a group structure from a gid number */
-enum winbindd_result winbindd_getgrnam_from_gid(gid_t gid,
- struct winbindd_gr *gr)
+enum winbindd_result winbindd_getgrnam_from_gid(struct winbindd_state *state)
{
DOM_SID domain_sid, domain_group_sid;
- uint32 name_type;
+ uint32 name_type, group_rid;
fstring group_name, domain_controller, domain_name;
POSIX_ID surs_gid;
/* Get sid from gid */
surs_gid.type = SURS_POSIX_GID_AS_GRP;
- surs_gid.id = gid;
+ surs_gid.id = state->request.data.gid;
if (!winbindd_surs_unixid_to_sam_sid(&surs_gid, &domain_group_sid,
False)) {
@@ -390,16 +385,17 @@ enum winbindd_result winbindd_getgrnam_from_gid(gid_t gid,
if (!winbindd_surs_unixid_to_sam_sid(&surs_gid, &domain_group_sid,
False)) {
DEBUG(1, ("Could not convert gid %d to domain or local sid\n",
- gid));
+ state->request.data.gid));
return WINBINDD_ERROR;
}
}
/* Find domain controller and domain sid */
- if (!find_domain_sid_from_gid(gid, &domain_sid, domain_controller,
- domain_name)) {
- DEBUG(0, ("Could not find domain for gid %d\n", gid));
+ if (!find_domain_sid_from_gid(state->request.data.gid, &domain_sid,
+ domain_controller, domain_name)) {
+ DEBUG(0, ("Could not find domain for gid %d\n",
+ state->request.data.gid));
return WINBINDD_ERROR;
}
@@ -420,19 +416,14 @@ enum winbindd_result winbindd_getgrnam_from_gid(gid_t gid,
/* Fill in group structure */
- if (gr != NULL) {
- DOM_SID temp;
- uint32 group_rid;
+ winbindd_fill_grent(&state->response.data.gr, group_name, surs_gid.id);
- winbindd_fill_grent(gr, group_name, surs_gid.id);
-
- sid_copy(&temp, &domain_group_sid);
- sid_split_rid(&temp, &group_rid);
+ sid_split_rid(&domain_group_sid, &group_rid);
- if (!winbindd_fill_grent_mem(domain_controller, domain_name,
- group_rid, name_type, NULL, gr)) {
- return WINBINDD_ERROR;
- }
+ if (!winbindd_fill_grent_mem(domain_controller, domain_name,
+ group_rid, name_type, NULL,
+ &state->response.data.gr)) {
+ return WINBINDD_ERROR;
}
return WINBINDD_OK;
@@ -442,260 +433,189 @@ enum winbindd_result winbindd_getgrnam_from_gid(gid_t gid,
* set/get/endgrent functions
*/
-/* Static data for these calls */
-
-struct winbindd_enum_grent_sam_pipes {
- BOOL valid;
- POLICY_HND sam_handle;
- POLICY_HND sam_dom_handle;
- struct acct_info *sam_entries;
- uint32 index, num_sam_entries;
- fstring domain_name;
- BOOL got_sam_entries;
-};
-
-struct winbindd_enum_grent {
- pid_t pid;
- struct winbindd_enum_grent_sam_pipes *sam_pipes;
- int num_sam_pipes, index;
- struct winbindd_enum_grent *prev, *next;
-};
-
-static struct winbindd_enum_grent *enum_grent_list = NULL;
-
-extern struct winbind_domain *domain_list;
-extern int num_domain;
-
-/* Return the winbindd_enum_grent structure for a given pid */
-
-static struct winbindd_enum_grent *get_grent_static(pid_t pid)
-{
- struct winbindd_enum_grent *tmp;
-
- for(tmp = enum_grent_list; tmp != NULL; tmp = tmp->next) {
- if (tmp->pid == pid) {
- return tmp;
- }
- }
-
- return NULL;
-}
-
/* "Rewind" file pointer for group database enumeration */
-enum winbindd_result winbindd_setgrent(pid_t pid)
+enum winbindd_result winbindd_setgrent(struct winbindd_state *state)
{
- struct winbindd_enum_grent *enum_grent = get_grent_static(pid);
- struct winbind_domain *tmp;
- int i;
-
- /* Free old static data if it exists */
-
- if (enum_grent != NULL) {
-
- DLIST_REMOVE(enum_grent_list, enum_grent);
-
- if (enum_grent->sam_pipes != NULL) {
- free(enum_grent->sam_pipes);
- }
-
- free(enum_grent);
- }
+ struct winbindd_domain *tmp;
- /* Create new static data */
+ if (state == NULL) return WINBINDD_ERROR;
- if ((enum_grent = (struct winbindd_enum_grent *)
- malloc(sizeof(*enum_grent))) == NULL) {
+ /* Free old static data if it exists */
- return WINBINDD_ERROR;
+ if (state->getgrent_state != NULL) {
+ free_getent_state(state->getgrent_state);
+ state->getgrent_state = NULL;
}
- /* Fill in fields */
-
- ZERO_STRUCTP(enum_grent);
- enum_grent->pid = pid;
+ /* Create sam pipes for each domain we know about */
- if ((enum_grent->sam_pipes = (struct winbindd_enum_grent_sam_pipes *)
- malloc(sizeof(*enum_grent->sam_pipes) * num_domain)) == NULL) {
-
- free(enum_grent);
- return WINBINDD_ERROR;
- }
+ for (tmp = domain_list; tmp != NULL; tmp = tmp->next) {
+ struct getent_state *domain_state;
+ BOOL res;
- enum_grent->num_sam_pipes = num_domain;
- memset(enum_grent->sam_pipes, 0, sizeof(*enum_grent->sam_pipes) *
- num_domain);
+ /* Create a state record for this domain */
- /* Connect to samr pipe for each domain */
+ if ((domain_state = (struct getent_state *)
+ malloc(sizeof(struct getent_state))) == NULL) {
- i = 0;
+ return WINBINDD_ERROR;
+ }
- for (tmp = domain_list; tmp != NULL; tmp = tmp->next) {
- BOOL res;
+ ZERO_STRUCTP(domain_state);
/* Connect to sam database */
res = samr_connect(tmp->domain_controller, SEC_RIGHTS_MAXIMUM_ALLOWED,
- &enum_grent->sam_pipes[i].sam_handle);
-
- res = res ? samr_open_domain(&enum_grent->sam_pipes[i].sam_handle,
- 0x304, &tmp->domain_sid,
- &enum_grent->sam_pipes[i].sam_dom_handle)
- : False;
-
- if (res) {
- fstrcpy(enum_grent->sam_pipes[i].domain_name,
- tmp->domain_name);
- enum_grent->sam_pipes[i].valid = True;
- } else {
+ &domain_state->sam_handle);
- /* Close everything */
+ {
+ fstring sid_str;
- samr_close(&enum_grent->sam_pipes[i].sam_dom_handle);
- samr_close(&enum_grent->sam_pipes[i].sam_handle);
+ sid_to_string(sid_str, &tmp->domain_sid);
+ fprintf(stderr, "opening pipe to %s, domain %s\n",
+ sid_str, tmp->domain_name);
}
- i++;
- }
-
- /* Add static data to list */
-
- DLIST_ADD(enum_grent_list, enum_grent);
-
- return WINBINDD_OK;
-}
+ res = res ? samr_open_domain(&domain_state->sam_handle,
+ 0x304, &tmp->domain_sid,
+ &domain_state->sam_dom_handle) : False;
-enum winbindd_result winbindd_endgrent(pid_t pid)
-{
- struct winbindd_enum_grent *enum_grent = get_grent_static(pid);
+ if (res) {
- /* Free handles and stuff */
+ /* Add to list of open domains */
- if (enum_grent != NULL) {
- int i;
+ fstrcpy(domain_state->domain_name, tmp->domain_name);
- /* Close handles */
+ DLIST_ADD(state->getgrent_state, domain_state);
- for(i = 0; i < enum_grent->num_sam_pipes; i++) {
- if (enum_grent->sam_pipes[i].valid) {
- samr_close(&enum_grent->sam_pipes[i].sam_dom_handle);
- samr_close(&enum_grent->sam_pipes[i].sam_handle);
- }
- }
+ } else {
- /* Free structure */
+ /* Error opening sam pipes */
- DLIST_REMOVE(enum_grent_list, enum_grent);
+ samr_close(&domain_state->sam_dom_handle);
+ samr_close(&domain_state->sam_handle);
- if (enum_grent->sam_pipes != NULL) {
- free(enum_grent->sam_pipes);
+ free(domain_state);
}
-
- free(enum_grent);
}
return WINBINDD_OK;
}
-enum winbindd_result winbindd_getgrent(pid_t pid, struct winbindd_gr *gr)
+/* Close file pointer to ntdom group database */
+
+enum winbindd_result winbindd_endgrent(struct winbindd_state *state)
{
- struct winbindd_enum_grent *enum_grent = get_grent_static(pid);
+ if (state == NULL) return WINBINDD_ERROR;
- /* Must have called setgrent() beforehand */
+ free_getent_state(state->getgrent_state);
+ state->getgrent_state = NULL;
- if (enum_grent == NULL) {
- return WINBINDD_ERROR;
- }
+ return WINBINDD_OK;
+}
- /* While we still have an unprocessed samr pipe */
+/* Fetch next group entry from netdom database */
- while (enum_grent->index < enum_grent->num_sam_pipes) {
- struct winbindd_enum_grent_sam_pipes *sam_pipe;
-
- sam_pipe = &enum_grent->sam_pipes[enum_grent->index];
+enum winbindd_result winbindd_getgrent(struct winbindd_state *state)
+{
+ if (state == NULL) return WINBINDD_ERROR;
- if (sam_pipe->valid) {
+ /* Process the current head of the getent_state list */
- /* Get list of entries if we haven't already got them */
+ while(state->getgrent_state != NULL) {
+ struct getent_state *ent = state->getgrent_state;
- if (!sam_pipe->got_sam_entries) {
- uint32 status, start_ndx = 0, start_ndx2 = 0;
+ /* Get list of entries if we haven't already got them */
+
+ if (!ent->got_sam_entries) {
+ uint32 status, start_ndx = 0, start_ndx2 = 0;
- /* Get list of groups for this domain */
+ /* Get list of groups for this domain */
- if (strcmp(sam_pipe->domain_name, "BUILTIN") == 0) {
+ if (strcmp(ent->domain_name, "BUILTIN") == 0) {
- /* Enumerate aliases */
+ /* Enumerate aliases */
- do {
-
- status =
- samr_enum_dom_aliases(&sam_pipe->sam_dom_handle,
- &start_ndx, 0x100000,
- &sam_pipe->sam_entries,
- &sam_pipe->num_sam_entries);
+ do {
+ status =
+ samr_enum_dom_aliases(&ent->sam_dom_handle,
+ &start_ndx, 0x100000,
+ &ent->sam_entries,
+ &ent->num_sam_entries);
} while (status == STATUS_MORE_ENTRIES);
- } else {
+ } else {
- /* Enumerate domain groups */
+ /* Enumerate domain groups */
- do {
- status =
- samr_enum_dom_groups(&sam_pipe->sam_dom_handle,
- &start_ndx, 0x100000,
- &sam_pipe->sam_entries,
- &sam_pipe->num_sam_entries);
- } while (status == STATUS_MORE_ENTRIES);
+ do {
+ status =
+ samr_enum_dom_groups(&ent->sam_dom_handle,
+ &start_ndx, 0x100000,
+ &ent->sam_entries,
+ &ent->num_sam_entries);
+ } while (status == STATUS_MORE_ENTRIES);
+
+ /* Enumerate domain aliases */
+
+ do {
+ status =
+ samr_enum_dom_aliases(&ent->sam_dom_handle,
+ &start_ndx2, 0x100000,
+ &ent->sam_entries,
+ &ent->num_sam_entries);
+ } while (status == STATUS_MORE_ENTRIES);
+ }
- /* Enumerate domain aliases */
-
- do {
- status =
- samr_enum_dom_aliases(&sam_pipe->sam_dom_handle,
- &start_ndx2, 0x100000,
- &sam_pipe->sam_entries,
- &sam_pipe->num_sam_entries);
- } while (status == STATUS_MORE_ENTRIES);
- }
+ fprintf(stderr, "*** read %d sam entries\n", ent->num_sam_entries);
- sam_pipe->got_sam_entries = True;
- }
+ /* Close down pipes */
+
+ samr_close(&ent->sam_dom_handle);
+ samr_close(&ent->sam_handle);
+
+ ent->got_sam_entries = True;
+ }
- /* Send back a group */
+ /* Send back a group */
- while (sam_pipe->index < sam_pipe->num_sam_entries) {
- enum winbindd_result result;
- fstring domain_group_name;
- char *group_name = (sam_pipe->sam_entries)
- [sam_pipe->index].acct_name;
+ while (ent->sam_entry_index < ent->num_sam_entries) {
+ enum winbindd_result result;
+ fstring domain_group_name;
+ char *group_name = (ent->sam_entries)
+ [ent->sam_entry_index].acct_name;
- /* Prepend domain to name */
+ /* Prepend domain to name */
- fstrcpy(domain_group_name, sam_pipe->domain_name);
- fstrcat(domain_group_name, "/");
- fstrcat(domain_group_name, group_name);
+ fstrcpy(domain_group_name, ent->domain_name);
+ fstrcat(domain_group_name, "/");
+ fstrcat(domain_group_name, group_name);
- /* Get group entry from group name */
+ /* Get group entry from group name */
+
+ fstrcpy(state->request.data.groupname, domain_group_name);
+ result = winbindd_getgrnam_from_group(state);
- result = winbindd_getgrnam_from_group(
- domain_group_name, &sam_pipe->sam_dom_handle, gr);
- sam_pipe->index++;
+ ent->sam_entry_index++;
- if (result == WINBINDD_OK) {
- return result;
- }
+ if (result == WINBINDD_OK) {
+ return result;
+ }
- /* Try next group */
+ /* Try next group */
- DEBUG(1, ("could not getgrnam_from_group for group name %s\n",
- domain_group_name));
- }
+ DEBUG(1, ("could not getgrnam_from_group for group name %s\n",
+ domain_group_name));
}
- /* Try next pipe */
-
- enum_grent->index++;
+ /* We've exhausted all users for this pipe - close it down and
+ start on the next one. */
+
+ if (ent->sam_entries != NULL) free(ent->sam_entries);
+ ent->sam_entries = NULL;
+
+ DLIST_REMOVE(state->getgrent_state, state->getgrent_state);
}
/* Out of pipes so we're done */
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index e669030dbda..d1ea38dbcac 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -1,7 +1,8 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
- Winbind daemon for ntdom nss module
+
+ Winbind daemon - user related function
Copyright (C) Tim Potter 2000
@@ -23,8 +24,7 @@
#include "includes.h"
#include "nterr.h"
-/* Fill a pwent structure with information we have obtained from the
- PDC. */
+/* Fill a pwent structure with information we have obtained */
static void winbindd_fill_pwent(struct winbindd_pw *pw, char *username,
uid_t unix_uid, gid_t unix_gid,
@@ -62,7 +62,7 @@ static void winbindd_fill_pwent(struct winbindd_pw *pw, char *username,
/* Password */
- strncpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1);
+ strncpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
/* Shell */
@@ -71,19 +71,17 @@ static void winbindd_fill_pwent(struct winbindd_pw *pw, char *username,
/* Return a password structure from a username */
-enum winbindd_result winbindd_getpwnam_from_user(char *user_name,
- POLICY_HND *sam_dom_handle,
- struct winbindd_pw *pw)
+enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_state *state)
{
uint32 name_type, user_rid;
SAM_USERINFO_CTR user_info;
DOM_SID domain_sid, user_sid, group_sid, tmp_sid;
fstring name_domain, name_user, tmp_name, domain_controller;
POSIX_ID uid, gid;
-
+
/* Look for user domain name */
- fstrcpy(tmp_name, user_name);
+ fstrcpy(tmp_name, state->request.data.username);
fstrcpy(name_domain, strtok(tmp_name, "/\\"));
fstrcpy(name_user, strtok(NULL, ""));
@@ -116,7 +114,7 @@ enum winbindd_result winbindd_getpwnam_from_user(char *user_name,
sid_split_rid(&tmp_sid, &user_rid);
if (!winbindd_lookup_userinfo(domain_controller, &domain_sid, user_rid,
- sam_dom_handle, &user_info)) {
+ NULL, &user_info)) {
DEBUG(1, ("pwnam_from_user(): error getting user info for user '%s'\n",
name_user));
return WINBINDD_ERROR;
@@ -144,9 +142,9 @@ enum winbindd_result winbindd_getpwnam_from_user(char *user_name,
/* Now take all this information and fill in a passwd structure */
- if (pw != NULL) {
- winbindd_fill_pwent(pw, user_name, uid.id, gid.id, &user_info);
- }
+ winbindd_fill_pwent(&state->response.data.pw,
+ state->request.data.username, uid.id, gid.id,
+ &user_info);
/* Free user info */
@@ -157,8 +155,7 @@ enum winbindd_result winbindd_getpwnam_from_user(char *user_name,
/* Return a password structure given a uid number */
-enum winbindd_result winbindd_getpwnam_from_uid(uid_t uid,
- struct winbindd_pw *pw)
+enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_state *state)
{
DOM_SID domain_sid, tmp_sid, domain_user_sid;
uint32 user_rid;
@@ -169,18 +166,21 @@ enum winbindd_result winbindd_getpwnam_from_uid(uid_t uid,
/* Get sid from uid */
- surs_uid.id = uid;
+ surs_uid.id = state->request.data.uid;
surs_uid.type = SURS_POSIX_UID_AS_USR;
if (!winbindd_surs_unixid_to_sam_sid(&surs_uid, &domain_user_sid, True)) {
- DEBUG(1, ("Could not convert uid %d to domain sid\n", uid));
+ DEBUG(1, ("Could not convert uid %d to domain sid\n",
+ state->request.data.uid));
return WINBINDD_ERROR;
}
/* Find domain controller and domain sid */
- if (!find_domain_sid_from_uid(uid, &domain_sid, NULL, domain_controller)) {
- DEBUG(0, ("Could not find domain for uid %d\n", uid));
+ if (!find_domain_sid_from_uid(state->request.data.uid, &domain_sid,
+ NULL, domain_controller)) {
+ DEBUG(0, ("Could not find domain for uid %d\n",
+ state->request.data.uid));
return WINBINDD_ERROR;
}
@@ -223,7 +223,8 @@ enum winbindd_result winbindd_getpwnam_from_uid(uid_t uid,
/* Fill in password structure */
- winbindd_fill_pwent(pw, username, surs_uid.id, surs_gid.id, &user_info);
+ winbindd_fill_pwent(&state->response.data.pw, username, surs_uid.id,
+ surs_gid.id, &user_info);
/* Free user info */
@@ -236,247 +237,162 @@ enum winbindd_result winbindd_getpwnam_from_uid(uid_t uid,
* set/get/endpwent functions
*/
-/* Static data for these calls */
-
-struct winbindd_enum_pwent_sam_pipes {
- BOOL valid;
- POLICY_HND sam_handle;
- POLICY_HND sam_dom_handle;
- struct acct_info *sam_entries;
- uint32 index, num_sam_entries;
- fstring domain_name;
- BOOL got_sam_entries;
-};
-
-struct winbindd_enum_pwent {
- pid_t pid;
- struct winbindd_enum_pwent_sam_pipes *sam_pipes;
- int num_sam_pipes, index;
- struct winbindd_enum_pwent *prev, *next;
-};
-
-static struct winbindd_enum_pwent *enum_pwent_list = NULL;
-
-extern int num_domain;
-extern struct winbind_domain *domain_list;
-
-/* Get static data for getpwent() and friends */
-
-static struct winbindd_enum_pwent *get_pwent_static(pid_t pid)
-{
- struct winbindd_enum_pwent *tmp;
-
- /* Look through static data list for data associated with pid */
-
- for(tmp = enum_pwent_list; tmp != NULL; tmp = tmp->next) {
- if (tmp->pid == pid) {
- return tmp;
- }
- }
-
- return NULL;
-}
-
/* Rewind file pointer for ntdom passwd database */
-enum winbindd_result winbindd_setpwent(pid_t pid)
+enum winbindd_result winbindd_setpwent(struct winbindd_state *state)
{
- struct winbindd_enum_pwent *enum_pwent = get_pwent_static(pid);
- struct winbind_domain *tmp;
- int i;
+ struct winbindd_domain *tmp;
+ if (state == NULL) return WINBINDD_ERROR;
+
/* Free old static data if it exists */
- if (enum_pwent != NULL) {
-
- DLIST_REMOVE(enum_pwent_list, enum_pwent);
-
- if (enum_pwent->sam_pipes != NULL) {
- free(enum_pwent->sam_pipes);
- }
-
- free(enum_pwent);
+ if (state->getpwent_state != NULL) {
+ free_getent_state(state->getpwent_state);
+ state->getpwent_state = NULL;
}
- /* Create new static data */
-
- if ((enum_pwent = (struct winbindd_enum_pwent *)
- malloc(sizeof(*enum_pwent))) == NULL) {
+ /* Create sam pipes for each domain we know about */
- return WINBINDD_ERROR;
- }
+ for(tmp = domain_list; tmp != NULL; tmp = tmp->next) {
+ struct getent_state *domain_state;
+ BOOL res;
- /* Fill in fields */
+ /* No point looking up BUILTIN users as they don't exist */
- ZERO_STRUCTP(enum_pwent);
- enum_pwent->pid = pid;
-
- if ((enum_pwent->sam_pipes = (struct winbindd_enum_pwent_sam_pipes *)
- malloc(sizeof(*enum_pwent->sam_pipes) * num_domain)) == NULL) {
-
- free(enum_pwent);
- return WINBINDD_ERROR;
- }
+ if (strcmp(tmp->domain_name, "BUILTIN") == 0) {
+ continue;
+ }
- enum_pwent->num_sam_pipes = num_domain;
- memset(enum_pwent->sam_pipes, 0, sizeof(*enum_pwent->sam_pipes) *
- num_domain);
+ /* Create a state record for this domain */
- /* Create sam pipes for each domain we know about */
+ if ((domain_state = (struct getent_state *)
+ malloc(sizeof(struct getent_state))) == NULL) {
- i = 0;
+ return WINBINDD_ERROR;
+ }
- for(tmp = domain_list; tmp != NULL; tmp = tmp->next) {
- BOOL res;
+ ZERO_STRUCTP(domain_state);
/* Connect to sam database */
- res = samr_connect(tmp->domain_controller,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &enum_pwent->sam_pipes[i].sam_handle);
+ res = samr_connect(tmp->domain_controller, SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &domain_state->sam_handle);
- res = res ? samr_open_domain(&enum_pwent->sam_pipes[i].sam_handle,
+ res = res ? samr_open_domain(&domain_state->sam_handle,
0x304, &tmp->domain_sid,
- &enum_pwent->sam_pipes[i].sam_dom_handle)
- : False;
+ &domain_state->sam_dom_handle) : False;
if (res) {
- fstrcpy(enum_pwent->sam_pipes[i].domain_name, tmp->domain_name);
- enum_pwent->sam_pipes[i].valid = True;
+
+ /* Add to list of open domains */
+
+ fstrcpy(domain_state->domain_name, tmp->domain_name);
+ DLIST_ADD(state->getpwent_state, domain_state);
+
} else {
- /* Ugh - failed for some reason */
+ /* Error opening sam pipes */
+
+ samr_close(&domain_state->sam_dom_handle);
+ samr_close(&domain_state->sam_handle);
- samr_close(&enum_pwent->sam_pipes[i].sam_dom_handle);
- samr_close(&enum_pwent->sam_pipes[i].sam_handle);
+ free(domain_state);
}
- i++;
}
- DLIST_ADD(enum_pwent_list, enum_pwent);
-
return WINBINDD_OK;
}
/* Close file pointer to ntdom passwd database */
-enum winbindd_result winbindd_endpwent(pid_t pid)
+enum winbindd_result winbindd_endpwent(struct winbindd_state *state)
{
- struct winbindd_enum_pwent *enum_pwent = get_pwent_static(pid);
-
- /* Free handles and stuff */
-
- if (enum_pwent != NULL) {
- int i;
+ if (state == NULL) return WINBINDD_ERROR;
- /* Close handles */
-
- for(i = 0; i < enum_pwent->num_sam_pipes; i++) {
- if (enum_pwent->sam_pipes[i].valid) {
- BOOL res;
-
- res = samr_close(&enum_pwent->sam_pipes[i].sam_dom_handle);
- res = samr_close(&enum_pwent->sam_pipes[i].sam_handle);
- }
- }
-
- /* Free structure */
-
- DLIST_REMOVE(enum_pwent_list, enum_pwent);
-
- if (enum_pwent->sam_pipes != NULL) {
- free(enum_pwent->sam_pipes);
- }
-
- free(enum_pwent);
- }
+ free_getent_state(state->getpwent_state);
+ state->getpwent_state = NULL;
return WINBINDD_OK;
}
/* Fetch next passwd entry from ntdom database */
-enum winbindd_result winbindd_getpwent(pid_t pid, struct winbindd_pw *pw)
+enum winbindd_result winbindd_getpwent(struct winbindd_state *state)
{
- struct winbindd_enum_pwent *enum_pwent = get_pwent_static(pid);
-
- /* Must have called setpwent() beforehand */
+ if (state == NULL) return WINBINDD_ERROR;
- if (enum_pwent == NULL) {
- return WINBINDD_ERROR;
- }
+ /* Process the current head of the getent_state list */
- /* While we still have an unprocessed samr pipe */
+ while(state->getpwent_state != NULL) {
+ struct getent_state *ent = state->getpwent_state;
- while (enum_pwent->index < enum_pwent->num_sam_pipes) {
- struct winbindd_enum_pwent_sam_pipes *sam_pipe;
-
- sam_pipe = &enum_pwent->sam_pipes[enum_pwent->index];
+ /* Get list of user entries for this pipe */
- if (sam_pipe->valid) {
-
- /* Get list of user entries for this pipe */
+ if (!ent->got_sam_entries) {
+ uint32 status, start_ndx = 0;
+
+ do {
+ status =
+ samr_enum_dom_users(
+ &ent->sam_dom_handle, &start_ndx, 0, 0, 0x10000,
+ &ent->sam_entries, &ent->num_sam_entries);
+ } while (status == STATUS_MORE_ENTRIES);
+
+ samr_close(&ent->sam_dom_handle);
+ samr_close(&ent->sam_handle);
- if (!sam_pipe->got_sam_entries) {
- uint32 status, start_ndx = 0;
-
- do {
- status =
- samr_enum_dom_users(
- &sam_pipe->sam_dom_handle,
- &start_ndx, 0, 0, 0x10000,
- &sam_pipe->sam_entries,
- &sam_pipe->num_sam_entries);
- } while (status == STATUS_MORE_ENTRIES);
-
- sam_pipe->got_sam_entries = 1;
- }
-
- /* Send back a user */
+ ent->got_sam_entries = True;
+ }
+
+ /* Send back a user */
- while (sam_pipe->index < sam_pipe->num_sam_entries) {
- enum winbindd_result result;
- fstring domain_user_name;
- char *user_name = (sam_pipe->sam_entries)
- [sam_pipe->index].acct_name;
+ while (ent->sam_entry_index < ent->num_sam_entries) {
+ enum winbindd_result result;
+ fstring domain_user_name;
+ char *user_name = (ent->sam_entries)
+ [ent->sam_entry_index].acct_name;
- /* Don't bother with machine accounts */
+ /* Don't bother with machine accounts */
- if (user_name[strlen(user_name) - 1] == '$') {
- sam_pipe->index++;
- continue;
- }
+ if (user_name[strlen(user_name) - 1] == '$') {
+ ent->sam_entry_index++;
+ continue;
+ }
- /* Prepend domain to name */
+ /* Prepend domain to name */
- fstrcpy(domain_user_name, sam_pipe->domain_name);
- fstrcat(domain_user_name, "/");
- fstrcat(domain_user_name, user_name);
+ fstrcpy(domain_user_name, ent->domain_name);
+ fstrcat(domain_user_name, "/");
+ fstrcat(domain_user_name, user_name);
- /* Get passwd entry from user name */
+ /* Get passwd entry from user name */
- result = winbindd_getpwnam_from_user(domain_user_name,
- &sam_pipe->sam_dom_handle,
- pw);
- sam_pipe->index++;
-
- /* Return if user lookup worked */
+ fstrcpy(state->request.data.username, domain_user_name);
+ result = winbindd_getpwnam_from_user(state);
+
+ ent->sam_entry_index++;
- if (result == WINBINDD_OK) {
- return result;
- }
+ /* Return if user lookup worked */
- /* Try next user */
-
- DEBUG(1, ("could not getpwnam_from_user for username %s\n",
- domain_user_name));
+ if (result == WINBINDD_OK) {
+ return result;
}
+
+ /* Try next user */
+
+ DEBUG(1, ("could not getpwnam_from_user for username %s\n",
+ domain_user_name));
}
- /* Try next pipe */
+ /* We've exhausted all users for this pipe - close it down and
+ start on the next one. */
+
+ if (ent->sam_entries != NULL) free(ent->sam_entries);
+ ent->sam_entries = NULL;
- enum_pwent->index++;
+ DLIST_REMOVE(state->getpwent_state, state->getpwent_state);
}
/* Out of pipes so we're done */