summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Potter <tpot@samba.org>2000-04-20 07:38:48 +0000
committerTim Potter <tpot@samba.org>2000-04-20 07:38:48 +0000
commitbd734f9d66cba70199fe79f10632e2bc3ba43b12 (patch)
treeae6969c83c490d5b32cc78a770d3c8bc15b51cfb
parentfbf96fec2aa264080e7130174273f210196fe773 (diff)
downloadsamba-bd734f9d66cba70199fe79f10632e2bc3ba43b12.tar.gz
samba-bd734f9d66cba70199fe79f10632e2bc3ba43b12.tar.xz
samba-bd734f9d66cba70199fe79f10632e2bc3ba43b12.zip
Code review by tridge.
Modified daemon architecture to manage partial reads and writes of client data properly. Also keep client socket file descriptors open for as long as possible. Moved client state back a level from inside winbindd_{user,group}.c into winbindd.c All winbindd_* functions now take a winbindd_state pointer as argument rather than selected bits of the request structure. Lots of code moved to winbind_utils.c String handling cleaned up.
-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 */