From 64299375b544de91dab75d62610d7dc7f1f8328d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 10 Jul 2000 05:40:43 +0000 Subject: Moved winbind client functions from various odd locations to nsswitch/wb_client.c Merge of nsswitch/common.c rename to nsswitch/wb_common.c from TNG. (This used to be commit f866c18f6be65db67d9d2a6c0b42e1af3b421e6c) --- source3/Makefile.in | 9 +- source3/include/proto.h | 18 +- source3/lib/util_seaccess.c | 64 -------- source3/nsswitch/common.c | 347 --------------------------------------- source3/nsswitch/wb_client.c | 174 ++++++++++++++++++++ source3/nsswitch/wb_common.c | 347 +++++++++++++++++++++++++++++++++++++++ source3/nsswitch/winbindd_util.c | 59 ++++++- source3/printing/nt_printing.c | 25 --- source3/rpc_server/srv_lsa.c | 59 ------- 9 files changed, 587 insertions(+), 515 deletions(-) delete mode 100644 source3/nsswitch/common.c create mode 100644 source3/nsswitch/wb_client.c create mode 100644 source3/nsswitch/wb_common.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index f8e41fffaa..d5cfcc82d4 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -178,7 +178,8 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \ smbd/unix_acls.o lib/msrpc-client.o lib/msrpc_use.o \ smbd/process.o smbd/service.o smbd/error.o \ - printing/printfsp.o nsswitch/common.o lib/util_seaccess.o + printing/printfsp.o nsswitch/wb_common.o lib/util_seaccess.o \ + nsswitch/wb_client.o PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_cups.o printing/load.o @@ -251,7 +252,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) -PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/common.po +PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po SMBW_OBJ = smbwrapper/smbw.o \ smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \ @@ -330,9 +331,9 @@ WINBINDD_OBJ = \ $(LIBNMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ $(NSSWINS_OBJ) $(SIDDB_OBJ) $(LIBSMB_OBJ) -WBINFO_OBJ = nsswitch/wbinfo.o nsswitch/common.o +WBINFO_OBJ = nsswitch/wbinfo.o nsswitch/wb_common.o -WINBIND_NSS_OBJ = nsswitch/winbind.o nsswitch/common.o +WINBIND_NSS_OBJ = nsswitch/winbind.o nsswitch/wb_common.o WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.po) diff --git a/source3/include/proto.h b/source3/include/proto.h index cd0331e391..9e871bb761 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -665,8 +665,6 @@ void file_lines_slashcont(char **lines); /*The following definitions come from lib/util_seaccess.c */ -BOOL winbind_uid_to_sid(uid_t uid, DOM_SID *sid); -BOOL winbind_gid_to_sid(gid_t gid, DOM_SID *sid); BOOL se_access_check(SEC_DESC *sd, uid_t uid, gid_t gid, int ngroups, gid_t *groups, uint32 acc_desired, uint32 *acc_granted, uint32 *status); @@ -1263,14 +1261,23 @@ void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_reco void dump_workgroups(BOOL force_write); void expire_workgroups_and_servers(time_t t); -/*The following definitions come from nsswitch/common.c */ +/*The following definitions come from nsswitch/wb_client.c */ + +BOOL winbind_lookup_name(char *name, DOM_SID *sid, uint8 *name_type); +BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, + uint8 *name_type); +BOOL winbind_uid_to_sid(uid_t uid, DOM_SID *sid); +BOOL winbind_gid_to_sid(gid_t gid, DOM_SID *sid); + +/*The following definitions come from nsswitch/wb_common.c */ void init_request(struct winbindd_request *req,int rq_type); void close_sock(void); int write_sock(void *buffer, int count); int read_reply(struct winbindd_response *response); void free_response(struct winbindd_response *response); -enum nss_status winbindd_request(int req_type, struct winbindd_request *request, +enum nss_status winbindd_request(int req_type, + struct winbindd_request *request, struct winbindd_response *response); /*The following definitions come from param/loadparm.c */ @@ -1670,7 +1677,6 @@ BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, fstring value, uint8 **data, uint32 *type, uint32 *len); uint32 nt_printing_setsec(char *printername, struct current_user *user, SEC_DESC_BUF *secdesc_ctr); -BOOL winbind_lookup_name(char *name, DOM_SID *sid, uint8 *name_type); BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr); BOOL print_access_check(struct current_user *user, int snum, uint32 required_access); @@ -2916,8 +2922,6 @@ BOOL api_netdfs_rpc(pipes_struct *p); /*The following definitions come from rpc_server/srv_lsa.c */ #if OLD_NTDOMAIN -BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, - uint8 *name_type); BOOL api_ntlsa_rpc(pipes_struct *p); #endif diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index 6c38300bb3..128cbffc0c 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -25,70 +25,6 @@ extern int DEBUGLEVEL; -/* Call winbindd to convert uid to sid */ - -BOOL winbind_uid_to_sid(uid_t uid, DOM_SID *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - int result; - - if (!sid) return False; - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.uid = uid; - - /* Make request */ - - result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response); - - /* Copy out result */ - - if (result == NSS_STATUS_SUCCESS) { - string_to_sid(sid, response.data.sid.sid); - } else { - sid_copy(sid, &global_sid_NULL); - } - - return (result == NSS_STATUS_SUCCESS); -} - -/* Call winbindd to convert uid to sid */ - -BOOL winbind_gid_to_sid(gid_t gid, DOM_SID *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - int result; - - if (!sid) return False; - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.gid = gid; - - /* Make request */ - - result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response); - - /* Copy out result */ - - if (result == NSS_STATUS_SUCCESS) { - string_to_sid(sid, response.data.sid.sid); - } else { - sid_copy(sid, &global_sid_NULL); - } - - return (result == NSS_STATUS_SUCCESS); -} - /* Process an access allowed ACE */ static BOOL ace_grant(uint32 mask, uint32 *acc_desired, uint32 *acc_granted) diff --git a/source3/nsswitch/common.c b/source3/nsswitch/common.c deleted file mode 100644 index 5d1f3431cc..0000000000 --- a/source3/nsswitch/common.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 2.0 - - winbind client common code - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Tridgell 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. -*/ - -#include "winbind_nss_config.h" -#include "winbindd_nss.h" - -/* Global variables. These are effectively the client state information */ - -static int established_socket = -1; /* fd for winbindd socket */ - -/* - * Utility and helper functions - */ - -void init_request(struct winbindd_request *req,int rq_type) -{ - static char *domain_env; - static BOOL initialised; - - req->cmd = rq_type; - req->pid = getpid(); - req->domain[0] = '\0'; - - if (!initialised) { - initialised = True; - domain_env = getenv(WINBINDD_DOMAIN_ENV); - } - - if (domain_env) { - strncpy(req->domain, domain_env, - sizeof(req->domain) - 1); - req->domain[sizeof(req->domain) - 1] = '\0'; - } -} - -/* Close established socket */ - -void close_sock(void) -{ - if (established_socket != -1) { - close(established_socket); - established_socket = -1; - } -} - -/* Connect to winbindd socket */ - -static int open_pipe_sock(void) -{ - struct sockaddr_un sunaddr; - static pid_t our_pid; - struct stat st; - pstring path; - - if (our_pid != getpid()) { - if (established_socket != -1) { - close(established_socket); - } - established_socket = -1; - our_pid = getpid(); - } - - if (established_socket != -1) { - return established_socket; - } - - /* Check permissions on unix socket directory */ - - if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) { - return -1; - } - - if (!S_ISDIR(st.st_mode) || (st.st_uid != 0)) { - return -1; - } - - /* Connect to socket */ - - strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - strncat(path, "/", sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - 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)) { - return -1; - } - - /* Connect to socket */ - - if ((established_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - return -1; - } - - if (connect(established_socket, (struct sockaddr *)&sunaddr, - sizeof(sunaddr)) == -1) { - close_sock(); - return -1; - } - - return established_socket; -} - -/* Write data to winbindd socket with timeout */ - -int write_sock(void *buffer, int count) -{ - int result, nwritten; - - /* Open connection to winbind daemon */ - - restart: - - if (open_pipe_sock() == -1) { - return -1; - } - - /* Write data to socket */ - - nwritten = 0; - - while(nwritten < count) { - struct timeval tv; - fd_set r_fds; - int selret; - - /* Catch pipe close on other end by checking if a read() - call would not block by calling select(). */ - - FD_ZERO(&r_fds); - FD_SET(established_socket, &r_fds); - ZERO_STRUCT(tv); - - if ((selret = select(established_socket + 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(established_socket, &r_fds)) { - - /* Do the write */ - - result = write(established_socket, - (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 with timeout */ - -static int read_sock(void *buffer, int count) -{ - int result = 0, nread = 0; - - /* Read data from socket */ - - while(nread < count) { - - result = read(established_socket, (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) { - return -1; - } - } - - /* Return total amount of data read */ - - return result1 + result2; -} - -/* Free a response structure */ - -void free_response(struct winbindd_response *response) -{ - /* Free any allocated extra_data */ - - if (response && response->extra_data) { - free(response->extra_data); - response->extra_data = NULL; - } -} - -/* Handle simple types of requests */ - -enum nss_status winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - struct winbindd_request lrequest; - struct winbindd_response lresponse; - - /* Check for our tricky environment variable */ - - if (getenv(WINBINDD_DONT_ENV)) { - return NSS_STATUS_NOTFOUND; - } - - if (!response) { - ZERO_STRUCT(lresponse); - response = &lresponse; - } - - 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; - } - - /* 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; -} diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c new file mode 100644 index 0000000000..0fe8b977f2 --- /dev/null +++ b/source3/nsswitch/wb_client.c @@ -0,0 +1,174 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + + winbind client code + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Tridgell 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. +*/ + +#include "includes.h" + +/* Call winbindd to convert a name to a sid */ + +BOOL winbind_lookup_name(char *name, DOM_SID *sid, uint8 *name_type) +{ + struct winbindd_request request; + struct winbindd_response response; + enum nss_status result; + + if (!sid || !name_type) return False; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.data.name, name); + if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request, + &response)) == NSS_STATUS_SUCCESS) { + string_to_sid(sid, response.data.sid.sid); + *name_type = response.data.sid.type; + } + + return result == NSS_STATUS_SUCCESS; +} + +/* Call winbindd to convert sid to name */ + +BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, + uint8 *name_type) +{ + struct winbindd_request request; + struct winbindd_response response; + enum nss_status result; + DOM_SID tmp_sid; + uint32 rid; + fstring sid_str; + + if (!name_type) return False; + + /* Check if this is our own sid. This should perhaps be done by + winbind? For the moment handle it here. */ + + if (sid->num_auths == 5) { + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + + if (sid_equal(&global_sam_sid, &tmp_sid)) { + + return map_domain_sid_to_name(&tmp_sid, dom_name) && + lookup_local_rid(rid, name, name_type); + } + } + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + sid_to_string(sid_str, sid); + fstrcpy(request.data.sid, sid_str); + + /* Make request */ + + result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response); + + /* Copy out result */ + + if (result == NSS_STATUS_SUCCESS) { + parse_domain_user(response.data.name.name, dom_name, name); + *name_type = response.data.name.type; + } else { + + DEBUG(10,("winbind_lookup_sid: winbind lookup for %s failed - trying builtin.\n", + sid_str)); + + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + return map_domain_sid_to_name(&tmp_sid, dom_name) && + lookup_known_rid(&tmp_sid, rid, name, name_type); + } + + return (result == NSS_STATUS_SUCCESS); +} + +/* Call winbindd to convert uid to sid */ + +BOOL winbind_uid_to_sid(uid_t uid, DOM_SID *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + int result; + + if (!sid) return False; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.uid = uid; + + /* Make request */ + + result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response); + + /* Copy out result */ + + if (result == NSS_STATUS_SUCCESS) { + string_to_sid(sid, response.data.sid.sid); + } else { + sid_copy(sid, &global_sid_NULL); + } + + return (result == NSS_STATUS_SUCCESS); +} + +/* Call winbindd to convert uid to sid */ + +BOOL winbind_gid_to_sid(gid_t gid, DOM_SID *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + int result; + + if (!sid) return False; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.gid = gid; + + /* Make request */ + + result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response); + + /* Copy out result */ + + if (result == NSS_STATUS_SUCCESS) { + string_to_sid(sid, response.data.sid.sid); + } else { + sid_copy(sid, &global_sid_NULL); + } + + return (result == NSS_STATUS_SUCCESS); +} diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c new file mode 100644 index 0000000000..5d1f3431cc --- /dev/null +++ b/source3/nsswitch/wb_common.c @@ -0,0 +1,347 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + + winbind client common code + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Tridgell 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. +*/ + +#include "winbind_nss_config.h" +#include "winbindd_nss.h" + +/* Global variables. These are effectively the client state information */ + +static int established_socket = -1; /* fd for winbindd socket */ + +/* + * Utility and helper functions + */ + +void init_request(struct winbindd_request *req,int rq_type) +{ + static char *domain_env; + static BOOL initialised; + + req->cmd = rq_type; + req->pid = getpid(); + req->domain[0] = '\0'; + + if (!initialised) { + initialised = True; + domain_env = getenv(WINBINDD_DOMAIN_ENV); + } + + if (domain_env) { + strncpy(req->domain, domain_env, + sizeof(req->domain) - 1); + req->domain[sizeof(req->domain) - 1] = '\0'; + } +} + +/* Close established socket */ + +void close_sock(void) +{ + if (established_socket != -1) { + close(established_socket); + established_socket = -1; + } +} + +/* Connect to winbindd socket */ + +static int open_pipe_sock(void) +{ + struct sockaddr_un sunaddr; + static pid_t our_pid; + struct stat st; + pstring path; + + if (our_pid != getpid()) { + if (established_socket != -1) { + close(established_socket); + } + established_socket = -1; + our_pid = getpid(); + } + + if (established_socket != -1) { + return established_socket; + } + + /* Check permissions on unix socket directory */ + + if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) { + return -1; + } + + if (!S_ISDIR(st.st_mode) || (st.st_uid != 0)) { + return -1; + } + + /* Connect to socket */ + + strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + + strncat(path, "/", sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + + strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + + 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)) { + return -1; + } + + /* Connect to socket */ + + if ((established_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return -1; + } + + if (connect(established_socket, (struct sockaddr *)&sunaddr, + sizeof(sunaddr)) == -1) { + close_sock(); + return -1; + } + + return established_socket; +} + +/* Write data to winbindd socket with timeout */ + +int write_sock(void *buffer, int count) +{ + int result, nwritten; + + /* Open connection to winbind daemon */ + + restart: + + if (open_pipe_sock() == -1) { + return -1; + } + + /* Write data to socket */ + + nwritten = 0; + + while(nwritten < count) { + struct timeval tv; + fd_set r_fds; + int selret; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(established_socket, &r_fds); + ZERO_STRUCT(tv); + + if ((selret = select(established_socket + 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(established_socket, &r_fds)) { + + /* Do the write */ + + result = write(established_socket, + (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 with timeout */ + +static int read_sock(void *buffer, int count) +{ + int result = 0, nread = 0; + + /* Read data from socket */ + + while(nread < count) { + + result = read(established_socket, (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) { + return -1; + } + } + + /* Return total amount of data read */ + + return result1 + result2; +} + +/* Free a response structure */ + +void free_response(struct winbindd_response *response) +{ + /* Free any allocated extra_data */ + + if (response && response->extra_data) { + free(response->extra_data); + response->extra_data = NULL; + } +} + +/* Handle simple types of requests */ + +enum nss_status winbindd_request(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + struct winbindd_request lrequest; + struct winbindd_response lresponse; + + /* Check for our tricky environment variable */ + + if (getenv(WINBINDD_DONT_ENV)) { + return NSS_STATUS_NOTFOUND; + } + + if (!response) { + ZERO_STRUCT(lresponse); + response = &lresponse; + } + + 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; + } + + /* 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; +} diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 1eea8f8fc7..80d6955e6c 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -45,10 +45,10 @@ static BOOL resolve_dc_name(char *domain_name, fstring domain_controller) if (!resolve_name(domain_name, &ip, 0x1B)) return False; - return lookup_pdc_name(global_myname, domain_name, &ip, domain_controller); + return lookup_pdc_name(global_myname, domain_name, &ip, + domain_controller); } - static struct winbindd_domain *add_trusted_domain(char *domain_name) { struct winbindd_domain *domain; @@ -90,7 +90,8 @@ static BOOL get_trusted_domains(void) /* Add our workgroup - keep handle to look up trusted domains */ if (!add_trusted_domain(lp_workgroup())) { - DEBUG(0, ("could not add record for domain %s\n", lp_workgroup())); + DEBUG(0, ("could not add record for domain %s\n", + lp_workgroup())); return False; } @@ -103,7 +104,8 @@ static BOOL get_trusted_domains(void) /* Add each domain to the trusted domain list */ for(i = 0; i < num_doms; i++) { if (!add_trusted_domain(domains[i])) { - DEBUG(0, ("could not add record for domain %s\n", domains[i])); + DEBUG(0, ("could not add record for domain %s\n", + domains[i])); result = False; } } @@ -126,7 +128,9 @@ static BOOL open_sam_handles(struct winbindd_domain *domain) } if ((domain->sam_handle_open && !rpc_hnd_ok(&domain->sam_handle)) || - (domain->sam_dom_handle_open && !rpc_hnd_ok(&domain->sam_dom_handle))) { + (domain->sam_dom_handle_open && + !rpc_hnd_ok(&domain->sam_dom_handle))) { + domain->got_domain_info = get_domain_info(domain); if (domain->sam_dom_handle_open) { samr_close(&domain->sam_dom_handle); @@ -139,49 +143,86 @@ static BOOL open_sam_handles(struct winbindd_domain *domain) } /* Open sam handle if it isn't already open */ + if (!domain->sam_handle_open) { + domain->sam_handle_open = - samr_connect(domain->controller, SEC_RIGHTS_MAXIMUM_ALLOWED, + samr_connect(domain->controller, + SEC_RIGHTS_MAXIMUM_ALLOWED, &domain->sam_handle); + if (!domain->sam_handle_open) return False; } /* Open sam domain handle if it isn't already open */ + if (!domain->sam_dom_handle_open) { + domain->sam_dom_handle_open = samr_open_domain(&domain->sam_handle, - SEC_RIGHTS_MAXIMUM_ALLOWED, &domain->sid, - &domain->sam_dom_handle); + SEC_RIGHTS_MAXIMUM_ALLOWED, + &domain->sid, &domain->sam_dom_handle); + if (!domain->sam_dom_handle_open) return False; } return True; } +/* Close all LSA and SAM connections */ + static void winbindd_kill_connections(void) { + struct winbindd_cli_state *cli; struct winbindd_domain *domain; DEBUG(1,("killing winbindd connections\n")); + /* Close LSA connection */ + server_state.pwdb_initialised = False; server_state.lsa_handle_open = False; lsa_close(&server_state.lsa_handle); - for (domain=domain_list; domain; domain=domain->next) { + /* Close SAM connections */ + + domain = domain_list; + + while(domain) { + struct winbindd_domain *next; + + /* Close SAM handles */ + if (domain->sam_dom_handle_open) { samr_close(&domain->sam_dom_handle); domain->sam_dom_handle_open = False; } + if (domain->sam_handle_open) { samr_close(&domain->sam_handle); domain->sam_handle_open = False; } + + /* Remove from list */ + + next = domain->next; DLIST_REMOVE(domain_list, domain); free(domain); + + domain = next; + } + + /* We also need to go through and trash any pointers to domains in + get{pw,gr}ent state records */ + + for (cli = client_list; cli; cli = cli->next) { + free_getent_state(cli->getpwent_state); + free_getent_state(cli->getgrent_state); } } +/* Try to establish connections to NT servers */ + void establish_connections(void) { struct winbindd_domain *domain; diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 83fd18da9b..3a40fdceab 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1583,31 +1583,6 @@ uint32 nt_printing_setsec(char *printername, struct current_user *user, return status; } -/* Call winbindd to convert a name to a sid */ - -BOOL winbind_lookup_name(char *name, DOM_SID *sid, uint8 *name_type) -{ - struct winbindd_request request; - struct winbindd_response response; - enum nss_status result; - - if (!sid || !name_type) return False; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - fstrcpy(request.data.name, name); - if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request, - &response)) == NSS_STATUS_SUCCESS) { - string_to_sid(sid, response.data.sid.sid); - *name_type = response.data.sid.type; - } - - return result == NSS_STATUS_SUCCESS; -} - /**************************************************************************** Construct a default security descriptor buffer for a printer. ****************************************************************************/ diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index 84d2601d2c..bfb671d167 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -279,65 +279,6 @@ static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l, r_l->status = 0x0; } -/* Call winbindd to convert sid to name */ - -BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, - uint8 *name_type) -{ - struct winbindd_request request; - struct winbindd_response response; - enum nss_status result; - DOM_SID tmp_sid; - uint32 rid; - fstring sid_str; - - if (!name_type) return False; - - /* Check if this is our own sid. This should perhaps be done by - winbind? For the moment handle it here. */ - - if (sid->num_auths == 5) { - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - - if (sid_equal(&global_sam_sid, &tmp_sid)) { - - return map_domain_sid_to_name(&tmp_sid, dom_name) && - lookup_local_rid(rid, name, name_type); - } - } - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - sid_to_string(sid_str, sid); - fstrcpy(request.data.sid, sid_str); - - /* Make request */ - - result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response); - - /* Copy out result */ - - if (result == NSS_STATUS_SUCCESS) { - parse_domain_user(response.data.name.name, dom_name, name); - *name_type = response.data.name.type; - } else { - - DEBUG(10,("winbind_lookup_sid: winbind lookup for %s failed - trying builtin.\n", - sid_str)); - - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - return map_domain_sid_to_name(&tmp_sid, dom_name) && - lookup_known_rid(&tmp_sid, rid, name, name_type); - } - - return (result == NSS_STATUS_SUCCESS); -} - /*************************************************************************** Init lsa_trans_names. ***************************************************************************/ -- cgit