diff options
-rw-r--r-- | source/nsswitch/winbindd.c | 705 | ||||
-rw-r--r-- | source/nsswitch/winbindd_group.c | 372 | ||||
-rw-r--r-- | source/nsswitch/winbindd_user.c | 316 |
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 */ |