diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-10-24 23:54:00 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:04:31 -0500 |
commit | 4298624589e2b44d88d703fe7cc0e73957c7652e (patch) | |
tree | 25c340c7962ae480e6caa60573c1638c227283c9 | |
parent | d164190debf9499ffa6dbf46ee24fa98da36c14f (diff) | |
download | samba-4298624589e2b44d88d703fe7cc0e73957c7652e.tar.gz samba-4298624589e2b44d88d703fe7cc0e73957c7652e.tar.bz2 samba-4298624589e2b44d88d703fe7cc0e73957c7652e.zip |
r3170: Add winbind client support back into Samba4. This is to allow
auth_winbind to work, and to therefore use the new ntlm_auth and
GENSEC in an otherwise Samba3 setup.
I'm not quite sure what fun-and games my svn cp caused as I merged
this from samba_3_0, but anyway...
Andrew Bartlett
(This used to be commit 5925b94a59da406d7e6b8cc695c99ba112fdfcd6)
-rw-r--r-- | source4/auth/auth_winbind.c | 67 | ||||
-rw-r--r-- | source4/auth/config.m4 | 1 | ||||
-rw-r--r-- | source4/auth/config.mk | 10 | ||||
-rw-r--r-- | source4/configure.in | 1 | ||||
-rw-r--r-- | source4/nsswitch/config.m4 | 2 | ||||
-rw-r--r-- | source4/nsswitch/config.mk | 7 | ||||
-rw-r--r-- | source4/nsswitch/wb_common.c | 612 | ||||
-rw-r--r-- | source4/nsswitch/winbind_client.h | 16 | ||||
-rw-r--r-- | source4/nsswitch/winbind_nss.h | 71 | ||||
-rw-r--r-- | source4/nsswitch/winbind_nss_config.h | 142 | ||||
-rw-r--r-- | source4/nsswitch/winbind_nss_hpux.h | 139 | ||||
-rw-r--r-- | source4/nsswitch/winbind_nss_irix.h | 48 | ||||
-rw-r--r-- | source4/nsswitch/winbind_nss_linux.h | 35 | ||||
-rw-r--r-- | source4/nsswitch/winbind_nss_solaris.h | 61 | ||||
-rw-r--r-- | source4/nsswitch/winbindd_nss.h | 291 |
15 files changed, 1466 insertions, 37 deletions
diff --git a/source4/auth/auth_winbind.c b/source4/auth/auth_winbind.c index 52cd627ab0..deada025d8 100644 --- a/source4/auth/auth_winbind.c +++ b/source4/auth/auth_winbind.c @@ -26,44 +26,18 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH -static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, NET_USER_INFO_3 *info3) -{ - uint8_t *info3_ndr; - size_t len = response->length - sizeof(response); - prs_struct ps; - if (len > 0) { - info3_ndr = response->extra_data; - if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - prs_copy_data_in(&ps, info3_ndr, len); - prs_set_offset(&ps,0); - if (!net_io_user_info3("", info3, &ps, 1, 3)) { - DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - prs_mem_free(&ps); - - return NT_STATUS_OK; - } else { - DEBUG(2, ("get_info3_from_ndr: No info3 struct found!\n")); - return NT_STATUS_UNSUCCESSFUL; - } -} - /* Authenticate a user with a challenge/response */ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) + void *my_private_data, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { struct winbindd_request request; struct winbindd_response response; NSS_STATUS result; NTSTATUS nt_status; - NET_USER_INFO_3 info3; if (!user_info) { return NT_STATUS_INVALID_PARAMETER; @@ -79,14 +53,14 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, ZERO_STRUCT(request); ZERO_STRUCT(response); - +#if 0 request.data.auth_crap.flags = WINBIND_PAM_INFO3_NDR; - - push_utf8_fstring(request.data.auth_crap.user, - user_info->smb_name.str); - push_utf8_fstring(request.data.auth_crap.domain, +#endif + fstrcpy(request.data.auth_crap.user, + user_info->smb_name.str); + fstrcpy(request.data.auth_crap.domain, user_info->domain.str); - push_utf8_fstring(request.data.auth_crap.workstation, + fstrcpy(request.data.auth_crap.workstation, user_info->wksta_name.str); memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal)); @@ -106,6 +80,7 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, nt_status = NT_STATUS(response.data.auth.nt_status); if (result == NSS_STATUS_SUCCESS && response.extra_data) { +#if 0 if (NT_STATUS_IS_OK(nt_status)) { if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) { nt_status = @@ -117,6 +92,7 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, &info3); } } +#endif } else if (NT_STATUS_IS_OK(nt_status)) { nt_status = NT_STATUS_UNSUCCESSFUL; } @@ -125,7 +101,9 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, } /* module initialisation */ -NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_winbind(struct auth_context *auth_context, + const char *param, + struct auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) return NT_STATUS_NO_MEMORY; @@ -134,3 +112,18 @@ NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char *param, (*auth_method)->auth = check_winbind_security; return NT_STATUS_OK; } + +NTSTATUS auth_winbind_init(void) +{ + NTSTATUS ret; + struct auth_operations ops; + + ops.name = "winbind"; + ops.init = auth_init_winbind; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; + } +} diff --git a/source4/auth/config.m4 b/source4/auth/config.m4 index 3c4f86ecea..41e652efec 100644 --- a/source4/auth/config.m4 +++ b/source4/auth/config.m4 @@ -2,5 +2,6 @@ dnl # AUTH Server subsystem SMB_MODULE_MK(auth_sam,AUTH,STATIC,auth/config.mk) SMB_MODULE_MK(auth_builtin,AUTH,STATIC,auth/config.mk) +SMB_MODULE_MK(auth_winbind,AUTH,STATIC,auth/config.mk) SMB_SUBSYSTEM_MK(AUTH,auth/config.mk,[],[],[SAMDB]) diff --git a/source4/auth/config.mk b/source4/auth/config.mk index 223f082e6a..9272dda193 100644 --- a/source4/auth/config.mk +++ b/source4/auth/config.mk @@ -19,6 +19,16 @@ INIT_OBJ_FILES = \ ####################### ####################### +# Start MODULE auth_winbind +[MODULE::auth_winbind] +INIT_OBJ_FILES = \ + auth/auth_winbind.o +REQUIRED_SUBSYSTEMS = \ + LIB_WINBIND_CLIENT +# End MODULE auth_builtin +####################### + +####################### # Start SUBSYSTEM AUTH [SUBSYSTEM::AUTH] INIT_OBJ_FILES = \ diff --git a/source4/configure.in b/source4/configure.in index 703017ffc8..40d6e10648 100644 --- a/source4/configure.in +++ b/source4/configure.in @@ -41,6 +41,7 @@ SMB_INCLUDE_M4(utils/config.m4) SMB_INCLUDE_M4(smbd/config.m4) SMB_INCLUDE_M4(gtk/config.m4) SMB_INCLUDE_M4(lib/dcom/config.m4) +SMB_INCLUDE_M4(nsswitch/config.m4) ALLLIBS_LIBS="$LIBS" ALLLIBS_CFLAGS="$CFLAGS" diff --git a/source4/nsswitch/config.m4 b/source4/nsswitch/config.m4 new file mode 100644 index 0000000000..5ce7d4b92f --- /dev/null +++ b/source4/nsswitch/config.m4 @@ -0,0 +1,2 @@ +SMB_SUBSYSTEM_MK(LIB_WINBIND_CLIENT,nsswitch/config.mk) + diff --git a/source4/nsswitch/config.mk b/source4/nsswitch/config.mk new file mode 100644 index 0000000000..676cc2858d --- /dev/null +++ b/source4/nsswitch/config.mk @@ -0,0 +1,7 @@ +################################# +# Start SUBSYSTEM LIB_WINBIND_CLIENT +[SUBSYSTEM::LIB_WINBIND_CLIENT] +ADD_OBJ_FILES = nsswitch/wb_common.o + +# End SUBSYSTEM LIB_WINBIND_CLIENT +################################# diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c new file mode 100644 index 0000000000..2f112e8695 --- /dev/null +++ b/source4/nsswitch/wb_common.c @@ -0,0 +1,612 @@ +/* + Unix SMB/CIFS implementation. + + winbind client common code + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Tridgell 2000 + Copyright (C) Andrew Bartlett 2002 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "includes.h" + +/* Global variables. These are effectively the client state information */ + +int winbindd_fd = -1; /* fd for winbindd socket */ + +/* Free a response structure */ + +void free_response(struct winbindd_response *response) +{ + /* Free any allocated extra_data */ + + if (response) + SAFE_FREE(response->extra_data); +} + +/* Initialise a request structure */ + +void init_request(struct winbindd_request *request, int request_type) +{ + request->length = sizeof(struct winbindd_request); + + request->cmd = (enum winbindd_cmd)request_type; + request->pid = getpid(); + +} + +/* Initialise a response structure */ + +void init_response(struct winbindd_response *response) +{ + /* Initialise return value */ + + response->result = WINBINDD_ERROR; +} + +/* Close established socket */ + +void close_sock(void) +{ + if (winbindd_fd != -1) { + close(winbindd_fd); + winbindd_fd = -1; + } +} + +#define CONNECT_TIMEOUT 30 +#define WRITE_TIMEOUT CONNECT_TIMEOUT +#define READ_TIMEOUT CONNECT_TIMEOUT + +/* Make sure socket handle isn't stdin, stdout or stderr */ +#define RECURSION_LIMIT 3 + +static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) +{ + int new_fd; + if (fd >= 0 && fd <= 2) { +#ifdef F_DUPFD + if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { + return -1; + } + /* Paranoia */ + if (new_fd < 3) { + close(new_fd); + return -1; + } + close(fd); + return new_fd; +#else + if (limit <= 0) + return -1; + + new_fd = dup(fd); + if (new_fd == -1) + return -1; + + /* use the program stack to hold our list of FDs to close */ + new_fd = make_nonstd_fd_internals(new_fd, limit - 1); + close(fd); + return new_fd; +#endif + } + return fd; +} + +/**************************************************************************** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY + Set close on exec also. +****************************************************************************/ + +static int make_safe_fd(int fd) +{ + int result, flags; + int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT); + if (new_fd == -1) { + close(fd); + return -1; + } + + /* Socket should be nonblocking. */ +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if ((flags = fcntl(new_fd, F_GETFL)) == -1) { + close(new_fd); + return -1; + } + + flags |= FLAG_TO_SET; + if (fcntl(new_fd, F_SETFL, flags) == -1) { + close(new_fd); + return -1; + } + +#undef FLAG_TO_SET + + /* Socket should be closed on exec() */ +#ifdef FD_CLOEXEC + result = flags = fcntl(new_fd, F_GETFD, 0); + if (flags >= 0) { + flags |= FD_CLOEXEC; + result = fcntl( new_fd, F_SETFD, flags ); + } + if (result < 0) { + close(new_fd); + return -1; + } +#endif + return new_fd; +} + +/* Connect to winbindd socket */ + +static int winbind_named_pipe_sock(const char *dir) +{ + struct sockaddr_un sunaddr; + struct stat st; + pstring path; + int fd; + int wait_time; + int slept; + + /* Check permissions on unix socket directory */ + + if (lstat(dir, &st) == -1) { + return -1; + } + + if (!S_ISDIR(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + return -1; + } + + /* Connect to socket */ + + snprintf(path, sizeof(path), "%s%s", dir, "/" WINBINDD_SOCKET_NAME); + + ZERO_STRUCT(sunaddr); + sunaddr.sun_family = AF_UNIX; + strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); + + /* If socket file doesn't exist, don't bother trying to connect + with retry. This is an attempt to make the system usable when + the winbindd daemon is not running. */ + + if (lstat(path, &st) == -1) { + return -1; + } + + /* Check permissions on unix socket file */ + + if (!S_ISSOCK(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + return -1; + } + + /* Connect to socket */ + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return -1; + } + + /* Set socket non-blocking and close on exec. */ + + if ((fd = make_safe_fd( fd)) == -1) { + return fd; + } + + for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1; + wait_time += slept) { + struct timeval tv; + fd_set w_fds; + int ret; + int connect_errno = 0, errnosize; + + if (wait_time >= CONNECT_TIMEOUT) + goto error_out; + + switch (errno) { + case EINPROGRESS: + FD_ZERO(&w_fds); + FD_SET(fd, &w_fds); + tv.tv_sec = CONNECT_TIMEOUT - wait_time; + tv.tv_usec = 0; + + ret = select(fd + 1, NULL, &w_fds, NULL, &tv); + + if (ret > 0) { + errnosize = sizeof(connect_errno); + + ret = getsockopt(fd, SOL_SOCKET, + SO_ERROR, &connect_errno, &errnosize); + + if (ret >= 0 && connect_errno == 0) { + /* Connect succeed */ + goto out; + } + } + + slept = CONNECT_TIMEOUT; + break; + case EAGAIN: + slept = rand() % 3 + 1; + sleep(slept); + break; + default: + goto error_out; + } + + } + + out: + + return fd; + + error_out: + + close(fd); + return -1; + + if (connect(fd, (struct sockaddr *)&sunaddr, + sizeof(sunaddr)) == -1) { + close(fd); + return -1; + } + + return fd; +} + +/* Connect to winbindd socket */ + +int winbind_open_pipe_sock(void) +{ +#ifdef HAVE_UNIXSOCKET + static pid_t our_pid; + struct winbindd_request request; + struct winbindd_response response; + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (our_pid != getpid()) { + close_sock(); + our_pid = getpid(); + } + + if (winbindd_fd != -1) { + return winbindd_fd; + } + + if ((winbindd_fd = winbind_named_pipe_sock(WINBINDD_SOCKET_DIR)) == -1) { + return -1; + } + + /* version-check the socket */ + + if ((winbindd_request(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { + close_sock(); + return -1; + } + + /* try and get priv pipe */ + + if (winbindd_request(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { + int fd; + if ((fd = winbind_named_pipe_sock(response.extra_data)) != -1) { + close(winbindd_fd); + winbindd_fd = fd; + } + } + + SAFE_FREE(response.extra_data); + + return winbindd_fd; +#else + return -1; +#endif /* HAVE_UNIXSOCKET */ +} + +/* Write data to winbindd socket */ + +int write_sock(void *buffer, int count) +{ + int result, nwritten; + + /* Open connection to winbind daemon */ + + restart: + + if (winbind_open_pipe_sock() == -1) { + return -1; + } + + /* Write data to socket */ + + nwritten = 0; + + while(nwritten < count) { + struct timeval tv; + fd_set r_fds; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(winbindd_fd, &r_fds); + ZERO_STRUCT(tv); + + if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { + close_sock(); + return -1; /* Select error */ + } + + /* Write should be OK if fd not available for reading */ + + if (!FD_ISSET(winbindd_fd, &r_fds)) { + + /* Do the write */ + + result = write(winbindd_fd, + (char *)buffer + nwritten, + count - nwritten); + + if ((result == -1) || (result == 0)) { + + /* Write failed */ + + close_sock(); + return -1; + } + + nwritten += result; + + } else { + + /* Pipe has closed on remote end */ + + close_sock(); + goto restart; + } + } + + return nwritten; +} + +/* Read data from winbindd socket */ + +static int read_sock(void *buffer, int count) +{ + int result = 0, nread = 0; + int total_time = 0, selret; + + /* Read data from socket */ + while(nread < count) { + struct timeval tv; + fd_set r_fds; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(winbindd_fd, &r_fds); + ZERO_STRUCT(tv); + /* Wait for 5 seconds for a reply. May need to parameterise this... */ + tv.tv_sec = 5; + + if ((selret = select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv)) == -1) { + close_sock(); + return -1; /* Select error */ + } + + if (selret == 0) { + /* Not ready for read yet... */ + if (total_time >= 30) { + /* Timeout */ + close_sock(); + return -1; + } + total_time += 5; + continue; + } + + if (FD_ISSET(winbindd_fd, &r_fds)) { + + /* Do the Read */ + + result = read(winbindd_fd, (char *)buffer + nread, + count - nread); + + if ((result == -1) || (result == 0)) { + + /* Read failed. I think the only useful thing we + can do here is just return -1 and fail since the + transaction has failed half way through. */ + + close_sock(); + return -1; + } + + nread += result; + + } + } + + return result; +} + +/* Read reply */ + +int read_reply(struct winbindd_response *response) +{ + int result1, result2 = 0; + + if (!response) { + return -1; + } + + /* Read fixed length response */ + + if ((result1 = read_sock(response, sizeof(struct winbindd_response))) + == -1) { + + return -1; + } + + /* We actually send the pointer value of the extra_data field from + the server. This has no meaning in the client's address space + so we clear it out. */ + + response->extra_data = NULL; + + /* Read variable length response */ + + if (response->length > sizeof(struct winbindd_response)) { + int extra_data_len = response->length - + sizeof(struct winbindd_response); + + /* Mallocate memory for extra data */ + + if (!(response->extra_data = malloc(extra_data_len))) { + return -1; + } + + if ((result2 = read_sock(response->extra_data, extra_data_len)) + == -1) { + free_response(response); + return -1; + } + } + + /* Return total amount of data read */ + + return result1 + result2; +} + +/* + * send simple types of requests + */ + +NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) +{ + struct winbindd_request lrequest; + char *env; + int value; + + /* Check for our tricky environment variable */ + + if ( (env = getenv(WINBINDD_DONT_ENV)) != NULL ) { + value = atoi(env); + if ( value == 1 ) + return NSS_STATUS_NOTFOUND; + } + + if (!request) { + ZERO_STRUCT(lrequest); + request = &lrequest; + } + + /* Fill in request and send down pipe */ + + init_request(request, req_type); + + if (write_sock(request, sizeof(*request)) == -1) { + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +/* + * Get results from winbindd request + */ + +NSS_STATUS winbindd_get_response(struct winbindd_response *response) +{ + struct winbindd_response lresponse; + + if (!response) { + ZERO_STRUCT(lresponse); + response = &lresponse; + } + + init_response(response); + + /* Wait for reply */ + if (read_reply(response) == -1) { + return NSS_STATUS_UNAVAIL; + } + + /* Throw away extra data if client didn't request it */ + if (response == &lresponse) { + free_response(response); + } + + /* Copy reply data from socket */ + if (response->result != WINBINDD_OK) { + return NSS_STATUS_NOTFOUND; + } + + return NSS_STATUS_SUCCESS; +} + +/* Handle simple types of requests */ + +NSS_STATUS winbindd_request(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + NSS_STATUS status; + + status = winbindd_send_request(req_type, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + return winbindd_get_response(response); +} + +/************************************************************************* + A couple of simple functions to disable winbindd lookups and re- + enable them + ************************************************************************/ + +/* Use putenv() instead of setenv() in these functions as not all + environments have the latter. */ + +BOOL winbind_off( void ) +{ + static char *s = WINBINDD_DONT_ENV "=1"; + + return putenv(s) != -1; +} + +BOOL winbind_on( void ) +{ + static char *s = WINBINDD_DONT_ENV "=0"; + + return putenv(s) != -1; +} diff --git a/source4/nsswitch/winbind_client.h b/source4/nsswitch/winbind_client.h new file mode 100644 index 0000000000..373d56804a --- /dev/null +++ b/source4/nsswitch/winbind_client.h @@ -0,0 +1,16 @@ +#include "nsswitch/winbind_nss_config.h" +#include "nsswitch/winbindd_nss.h" + +void init_request(struct winbindd_request *req,int rq_type); +NSS_STATUS winbindd_send_request(int req_type, + struct winbindd_request *request); +NSS_STATUS winbindd_get_response(struct winbindd_response *response); +NSS_STATUS winbindd_request(int req_type, + struct winbindd_request *request, + struct winbindd_response *response); +int winbind_open_pipe_sock(void); +int write_sock(void *buffer, int count); +int read_reply(struct winbindd_response *response); +void close_sock(void); +void free_response(struct winbindd_response *response); + diff --git a/source4/nsswitch/winbind_nss.h b/source4/nsswitch/winbind_nss.h new file mode 100644 index 0000000000..5416ae211e --- /dev/null +++ b/source4/nsswitch/winbind_nss.h @@ -0,0 +1,71 @@ +/* + Unix SMB/CIFS implementation. + + A common place to work out how to define NSS_STATUS on various + platforms. + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _NSSWITCH_NSS_H +#define _NSSWITCH_NSS_H + +#ifdef HAVE_NSS_COMMON_H + +/* + * Sun Solaris + */ + +#include "nsswitch/winbind_nss_solaris.h" + +#elif HAVE_NSS_H + +/* + * Linux (glibc) + */ + +#include <nss.h> +typedef enum nss_status NSS_STATUS; + +#elif HAVE_NS_API_H + +/* + * SGI IRIX + */ + +#include "nsswitch/winbind_nss_irix.h" + +#elif defined(HPUX) && defined(HAVE_NSSWITCH_H) + +/* HP-UX 11 */ + +#include "nsswitch/winbind_nss_hpux.h" + +#else /* Nothing's defined. Neither gnu nor sun nor hp */ + +typedef enum +{ + NSS_STATUS_SUCCESS=0, + NSS_STATUS_NOTFOUND=1, + NSS_STATUS_UNAVAIL=2, + NSS_STATUS_TRYAGAIN=3 +} NSS_STATUS; + +#endif + +#endif /* _NSSWITCH_NSS_H */ diff --git a/source4/nsswitch/winbind_nss_config.h b/source4/nsswitch/winbind_nss_config.h new file mode 100644 index 0000000000..77d1dbe26e --- /dev/null +++ b/source4/nsswitch/winbind_nss_config.h @@ -0,0 +1,142 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _WINBIND_NSS_CONFIG_H +#define _WINBIND_NSS_CONFIG_H + +/* Include header files from data in config.h file */ + +#ifndef NO_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +#ifdef HAVE_UNIXSOCKET +#include <sys/un.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifdef HAVE_GRP_H +#include <grp.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#else +#ifdef HAVE_SYS_FCNTL_H +#include <sys/fcntl.h> +#endif +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <pwd.h> +#include "nsswitch/winbind_nss.h" + +/* I'm trying really hard not to include anything from smb.h with the + result of some silly looking redeclaration of structures. */ + +#ifndef _PSTRING +#define _PSTRING +#define PSTRING_LEN 1024 +#define FSTRING_LEN 256 +typedef char pstring[PSTRING_LEN]; +typedef char fstring[FSTRING_LEN]; +#endif + +#ifndef _BOOL +#define _BOOL /* So we don't typedef BOOL again in vfs.h */ +#define False (0) +#define True (1) +#define Auto (2) +typedef int BOOL; +#endif + +#if !defined(uint32) +#if (SIZEOF_INT == 4) +#define uint32 unsigned int +#elif (SIZEOF_LONG == 4) +#define uint32 unsigned long +#elif (SIZEOF_SHORT == 4) +#define uint32 unsigned short +#endif +#endif + +#if !defined(uint16) +#if (SIZEOF_SHORT == 4) +#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; +#else /* SIZEOF_SHORT != 4 */ +#define uint16 unsigned short +#endif /* SIZEOF_SHORT != 4 */ +#endif + +#ifndef uint8 +#define uint8 unsigned char +#endif + +/* zero a structure */ +#ifndef ZERO_STRUCT +#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) +#endif + +/* zero a structure given a pointer to the structure */ +#ifndef ZERO_STRUCTP +#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } +#endif + +/* Some systems (SCO) treat UNIX domain sockets as FIFOs */ + +#ifndef S_IFSOCK +#define S_IFSOCK S_IFIFO +#endif + +#ifndef S_ISSOCK +#define S_ISSOCK(mode) ((mode & S_IFSOCK) == S_IFSOCK) +#endif + +#endif diff --git a/source4/nsswitch/winbind_nss_hpux.h b/source4/nsswitch/winbind_nss_hpux.h new file mode 100644 index 0000000000..d2a5057bf5 --- /dev/null +++ b/source4/nsswitch/winbind_nss_hpux.h @@ -0,0 +1,139 @@ +/* + Unix SMB/CIFS implementation. + + Donated by HP to enable Winbindd to build on HPUX 11.x. + Copyright (C) Jeremy Allison 2002. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _WINBIND_NSS_HPUX_H +#define _WINBIND_NSS_HPUX_H + +#include <nsswitch.h> + +#define NSS_STATUS_SUCCESS NSS_SUCCESS +#define NSS_STATUS_NOTFOUND NSS_NOTFOUND +#define NSS_STATUS_UNAVAIL NSS_UNAVAIL +#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN + +#ifdef HAVE_SYNCH_H +#include <synch.h> +#endif +#ifdef HAVE_PTHREAD_H +#include <pthread.h> +#endif + +typedef enum { + NSS_SUCCESS, + NSS_NOTFOUND, + NSS_UNAVAIL, + NSS_TRYAGAIN +} nss_status_t; + +typedef nss_status_t NSS_STATUS; + +struct nss_backend; + +typedef nss_status_t (*nss_backend_op_t)(struct nss_backend *, void *args); + +struct nss_backend { + nss_backend_op_t *ops; + int n_ops; +}; +typedef struct nss_backend nss_backend_t; +typedef int nss_dbop_t; + +#include <errno.h> +#include <netdb.h> +#include <limits.h> + +#ifndef NSS_INCLUDE_UNSAFE +#define NSS_INCLUDE_UNSAFE 1 /* Build old, MT-unsafe interfaces, */ +#endif /* NSS_INCLUDE_UNSAFE */ + +enum nss_netgr_argn { + NSS_NETGR_MACHINE, + NSS_NETGR_USER, + NSS_NETGR_DOMAIN, + NSS_NETGR_N +}; + +enum nss_netgr_status { + NSS_NETGR_FOUND, + NSS_NETGR_NO, + NSS_NETGR_NOMEM +}; + +typedef unsigned nss_innetgr_argc; +typedef char **nss_innetgr_argv; + +struct nss_innetgr_1arg { + nss_innetgr_argc argc; + nss_innetgr_argv argv; +}; + +typedef struct { + void *result; /* "result" parameter to getXbyY_r() */ + char *buffer; /* "buffer" " " */ + int buflen; /* "buflen" " " */ +} nss_XbyY_buf_t; + +extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int struct_size, int buffer_size); +extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *); + +union nss_XbyY_key { + uid_t uid; + gid_t gid; + const char *name; + int number; + struct { + long net; + int type; + } netaddr; + struct { + const char *addr; + int len; + int type; + } hostaddr; + struct { + union { + const char *name; + int port; + } serv; + const char *proto; + } serv; + void *ether; +}; + +typedef struct nss_XbyY_args { + nss_XbyY_buf_t buf; + int stayopen; + /* + * Support for setXXXent(stayopen) + * Used only in hosts, protocols, + * networks, rpc, and services. + */ + int (*str2ent)(const char *instr, int instr_len, void *ent, char *buffer, int buflen); + union nss_XbyY_key key; + + void *returnval; + int erange; + int h_errno; + nss_status_t status; +} nss_XbyY_args_t; + +#endif /* _WINBIND_NSS_HPUX_H */ diff --git a/source4/nsswitch/winbind_nss_irix.h b/source4/nsswitch/winbind_nss_irix.h new file mode 100644 index 0000000000..7878abb981 --- /dev/null +++ b/source4/nsswitch/winbind_nss_irix.h @@ -0,0 +1,48 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _WINBIND_NSS_IRIX_H +#define _WINBIND_NSS_IRIX_H + +/* following required to prevent warnings of double definition + * of datum from ns_api.h +*/ +#ifdef DATUM +#define _DATUM_DEFINED +#endif + +#include <ns_api.h> + +typedef enum +{ + NSS_STATUS_SUCCESS=NS_SUCCESS, + NSS_STATUS_NOTFOUND=NS_NOTFOUND, + NSS_STATUS_UNAVAIL=NS_UNAVAIL, + NSS_STATUS_TRYAGAIN=NS_TRYAGAIN +} NSS_STATUS; + +#define NSD_MEM_STATIC 0 +#define NSD_MEM_VOLATILE 1 +#define NSD_MEM_DYNAMIC 2 + +#endif /* _WINBIND_NSS_IRIX_H */ diff --git a/source4/nsswitch/winbind_nss_linux.h b/source4/nsswitch/winbind_nss_linux.h new file mode 100644 index 0000000000..1c7e830037 --- /dev/null +++ b/source4/nsswitch/winbind_nss_linux.h @@ -0,0 +1,35 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _WINBIND_NSS_LINUX_H +#define _WINBIND_NSS_LINUX_H + +#if HAVE_NSS_H + +#include <nss.h> + +typedef enum nss_status NSS_STATUS; + +#endif /* HAVE_NSS_H */ + +#endif /* _WINBIND_NSS_LINUX_H */ diff --git a/source4/nsswitch/winbind_nss_solaris.h b/source4/nsswitch/winbind_nss_solaris.h new file mode 100644 index 0000000000..567de411aa --- /dev/null +++ b/source4/nsswitch/winbind_nss_solaris.h @@ -0,0 +1,61 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _WINBIND_NSS_SOLARIS_H +#define _WINBIND_NSS_SOLARIS_H + +#include <nss_common.h> +#include <nss_dbdefs.h> +#include <nsswitch.h> + +typedef nss_status_t NSS_STATUS; + +#define NSS_STATUS_SUCCESS NSS_SUCCESS +#define NSS_STATUS_NOTFOUND NSS_NOTFOUND +#define NSS_STATUS_UNAVAIL NSS_UNAVAIL +#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN + +/* The solaris winbind is implemented as a wrapper around the linux + version. */ + +NSS_STATUS _nss_winbind_setpwent(void); +NSS_STATUS _nss_winbind_endpwent(void); +NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer, + size_t buflen, int* errnop); +NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer, + size_t buflen, int* errnop); +NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result, + char* buffer, size_t buflen, int* errnop); + +NSS_STATUS _nss_winbind_setgrent(void); +NSS_STATUS _nss_winbind_endgrent(void); +NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer, + size_t buflen, int* errnop); +NSS_STATUS _nss_winbind_getgrnam_r(const char *name, + struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, + struct group *result, char *buffer, + size_t buflen, int *errnop); + +#endif /* _WINBIND_NSS_SOLARIS_H */ diff --git a/source4/nsswitch/winbindd_nss.h b/source4/nsswitch/winbindd_nss.h new file mode 100644 index 0000000000..9a99bad9d7 --- /dev/null +++ b/source4/nsswitch/winbindd_nss.h @@ -0,0 +1,291 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0) +#endif + +#ifndef _WINBINDD_NTDOM_H +#define _WINBINDD_NTDOM_H + +#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */ +#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */ +#define WINBINDD_PRIV_SOCKET_SUBDIR "winbindd_privileged" /* name of subdirectory of lp_lockdir() to hold the 'privileged' pipe */ +#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */ +#define WINBINDD_DONT_ENV "_NO_WINBINDD" + +/* Update this when you change the interface. */ + +#define WINBIND_INTERFACE_VERSION 10 + +/* Socket commands */ + +enum winbindd_cmd { + + WINBINDD_INTERFACE_VERSION, /* Always a well known value */ + + /* Get users and groups */ + + WINBINDD_GETPWNAM, + WINBINDD_GETPWUID, + WINBINDD_GETGRNAM, + WINBINDD_GETGRGID, + WINBINDD_GETGROUPS, + + /* Enumerate users and groups */ + + WINBINDD_SETPWENT, + WINBINDD_ENDPWENT, + WINBINDD_GETPWENT, + WINBINDD_SETGRENT, + WINBINDD_ENDGRENT, + WINBINDD_GETGRENT, + + /* PAM authenticate and password change */ + + WINBINDD_PAM_AUTH, + WINBINDD_PAM_AUTH_CRAP, + WINBINDD_PAM_CHAUTHTOK, + + /* List various things */ + + WINBINDD_LIST_USERS, /* List w/o rid->id mapping */ + WINBINDD_LIST_GROUPS, /* Ditto */ + WINBINDD_LIST_TRUSTDOM, + + /* SID conversion */ + + WINBINDD_LOOKUPSID, + WINBINDD_LOOKUPNAME, + + /* Lookup functions */ + + WINBINDD_SID_TO_UID, + WINBINDD_SID_TO_GID, + WINBINDD_UID_TO_SID, + WINBINDD_GID_TO_SID, + WINBINDD_ALLOCATE_RID, + + /* Miscellaneous other stuff */ + + WINBINDD_CHECK_MACHACC, /* Check machine account pw works */ + WINBINDD_PING, /* Just tell me winbind is running */ + WINBINDD_INFO, /* Various bit of info. Currently just tidbits */ + WINBINDD_DOMAIN_NAME, /* The domain this winbind server is a member of (lp_workgroup()) */ + + WINBINDD_DOMAIN_INFO, /* Most of what we know from + struct winbindd_domain */ + + WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */ + + /* WINS commands */ + + WINBINDD_WINS_BYIP, + WINBINDD_WINS_BYNAME, + + /* account management commands */ + + WINBINDD_CREATE_USER, + WINBINDD_CREATE_GROUP, + WINBINDD_ADD_USER_TO_GROUP, + WINBINDD_REMOVE_USER_FROM_GROUP, + WINBINDD_SET_USER_PRIMARY_GROUP, + WINBINDD_DELETE_USER, + WINBINDD_DELETE_GROUP, + + /* this is like GETGRENT but gives an empty group list */ + WINBINDD_GETGRLST, + + WINBINDD_NETBIOS_NAME, /* The netbios name of the server */ + + /* find the location of our privileged pipe */ + WINBINDD_PRIV_PIPE_DIR, + + /* return a list of group sids for a user sid */ + WINBINDD_GETUSERSIDS, + + /* Placeholder for end of cmd list */ + WINBINDD_NUM_CMDS +}; + +typedef struct winbindd_pw { + fstring pw_name; + fstring pw_passwd; + uid_t pw_uid; + gid_t pw_gid; + fstring pw_gecos; + fstring pw_dir; + fstring pw_shell; +} WINBINDD_PW; + + +typedef struct winbindd_gr { + fstring gr_name; + fstring gr_passwd; + gid_t gr_gid; + int num_gr_mem; + int gr_mem_ofs; /* offset to group membership */ + char **gr_mem; +} WINBINDD_GR; + + +#define WBFLAG_PAM_INFO3_NDR 0x0001 +#define WBFLAG_PAM_INFO3_TEXT 0x0002 +#define WBFLAG_PAM_USER_SESSION_KEY 0x0004 +#define WBFLAG_PAM_LMKEY 0x0008 +#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x0010 +#define WBFLAG_QUERY_ONLY 0x0020 +#define WBFLAG_ALLOCATE_RID 0x0040 +#define WBFLAG_PAM_UNIX_NAME 0x0080 +#define WBFLAG_PAM_AFS_TOKEN 0x0100 +#define WBFLAG_PAM_NT_STATUS_SQUASH 0x0200 + +/* Winbind request structure */ + +struct winbindd_request { + uint32 length; + enum winbindd_cmd cmd; /* Winbindd command to execute */ + pid_t pid; /* pid of calling process */ + uint32 flags; /* flags relavant to a given request */ + fstring domain_name; /* name of domain for which the request applies */ + + union { + fstring winsreq; /* WINS request */ + fstring username; /* getpwnam */ + fstring groupname; /* getgrnam */ + uid_t uid; /* getpwuid, uid_to_sid */ + gid_t gid; /* getgrgid, gid_to_sid */ + struct { + /* We deliberatedly don't split into domain/user to + avoid having the client know what the separator + character is. */ + fstring user; + fstring pass; + fstring require_membership_of_sid; + } auth; /* pam_winbind auth module */ + struct { + unsigned char chal[8]; + fstring user; + fstring domain; + fstring lm_resp; + uint16 lm_resp_len; + fstring nt_resp; + uint16 nt_resp_len; + fstring workstation; + fstring require_membership_of_sid; + } auth_crap; + struct { + fstring user; + fstring oldpass; + fstring newpass; + } chauthtok; /* pam_winbind passwd module */ + fstring sid; /* lookupsid, sid_to_[ug]id */ + struct { + fstring dom_name; /* lookupname */ + fstring name; + } name; + uint32 num_entries; /* getpwent, getgrent */ + struct { + fstring username; + fstring groupname; + } acct_mgt; + } data; + char null_term; +}; + +/* Response values */ + +enum winbindd_result { + WINBINDD_ERROR, + WINBINDD_OK +}; + +/* Winbind response structure */ + +struct winbindd_response { + + /* Header information */ + + uint32 length; /* Length of response */ + enum winbindd_result result; /* Result code */ + + /* Fixed length return data */ + + union { + int interface_version; /* Try to ensure this is always in the same spot... */ + + fstring winsresp; /* WINS response */ + + /* getpwnam, getpwuid */ + + struct winbindd_pw pw; + + /* getgrnam, getgrgid */ + + struct winbindd_gr gr; + + uint32 num_entries; /* getpwent, getgrent */ + struct winbindd_sid { + fstring sid; /* lookupname, [ug]id_to_sid */ + int type; + } sid; + struct winbindd_name { + fstring dom_name; /* lookupsid */ + fstring name; + int type; + } name; + uid_t uid; /* sid_to_uid */ + gid_t gid; /* sid_to_gid */ + struct winbindd_info { + char winbind_separator; + fstring samba_version; + } info; + fstring domain_name; + fstring netbios_name; + + struct auth_reply { + uint32 nt_status; + fstring nt_status_string; + fstring error_string; + int pam_error; + char user_session_key[16]; + char first_8_lm_hash[8]; + } auth; + uint32 rid; /* create user or group or allocate rid */ + struct { + fstring name; + fstring alt_name; + fstring sid; + BOOL native_mode; + BOOL active_directory; + BOOL primary; + uint32 sequence_number; + } domain_info; + } data; + + /* Variable length return data */ + + void *extra_data; /* getgrnam, getgrgid, getgrent */ +}; + +#endif |