diff options
Diffstat (limited to 'source/nsswitch')
-rw-r--r-- | source/nsswitch/idmap.c | 39 | ||||
-rw-r--r-- | source/nsswitch/idmap_ldap.c | 3 | ||||
-rw-r--r-- | source/nsswitch/pam_winbind.c | 3 | ||||
-rw-r--r-- | source/nsswitch/wb_common.c | 47 | ||||
-rw-r--r-- | source/nsswitch/winbind_client.h | 7 | ||||
-rw-r--r-- | source/nsswitch/winbind_nss_irix.c | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd.c | 17 | ||||
-rw-r--r-- | source/nsswitch/winbindd.h | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd_ads.c | 18 | ||||
-rw-r--r-- | source/nsswitch/winbindd_cred_cache.c | 1 | ||||
-rw-r--r-- | source/nsswitch/winbindd_dual.c | 4 | ||||
-rw-r--r-- | source/nsswitch/winbindd_group.c | 10 | ||||
-rw-r--r-- | source/nsswitch/winbindd_pam.c | 34 | ||||
-rw-r--r-- | source/nsswitch/winbindd_rpc.c | 6 | ||||
-rw-r--r-- | source/nsswitch/winbindd_user.c | 8 |
15 files changed, 147 insertions, 54 deletions
diff --git a/source/nsswitch/idmap.c b/source/nsswitch/idmap.c index a58959afe4c..c2a38fa9797 100644 --- a/source/nsswitch/idmap.c +++ b/source/nsswitch/idmap.c @@ -297,7 +297,6 @@ NTSTATUS idmap_init(void) char *p = NULL; const char *q = NULL; - DEBUG(0, ("WARNING: idmap backend is deprecated!\n")); compat = 1; if ( (compat_backend = talloc_strdup( idmap_ctx, *compat_list )) == NULL ) { @@ -337,6 +336,15 @@ NTSTATUS idmap_init(void) const char *parm_backend; char *config_option; + /* ignore BUILTIN and local MACHINE domains */ + if ( strequal(dom_list[i], "BUILTIN") + || strequal(dom_list[i], get_global_sam_name() ) ) + { + DEBUG(0,("idmap_init: Ignoring invalid domain %s\n", + dom_list[i])); + continue; + } + if (strequal(dom_list[i], lp_workgroup())) { pri_dom_is_in_list = True; } @@ -577,17 +585,22 @@ NTSTATUS idmap_init(void) alloc_methods = get_alloc_methods(alloc_backends, alloc_backend); } } - if ( ! alloc_methods) { - DEBUG(0, ("ERROR: Could not get methods for alloc backend %s\n", alloc_backend)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - ret = alloc_methods->init(compat_params); - if ( ! NT_STATUS_IS_OK(ret)) { - DEBUG(0, ("ERROR: Initialization failed for alloc backend %s\n", alloc_backend)); - ret = NT_STATUS_UNSUCCESSFUL; - goto done; + if ( alloc_methods) { + ret = alloc_methods->init(compat_params); + if ( ! NT_STATUS_IS_OK(ret)) { + DEBUG(0, ("idmap_init: Initialization failed for alloc " + "backend %s\n", alloc_backend)); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + } else { + DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n", + alloc_backend)); + /* certain compat backends are just readonly */ + if ( compat ) + ret = NT_STATUS_OK; + else + ret = NT_STATUS_UNSUCCESSFUL; } /* cleanpu temporary strings */ @@ -595,7 +608,7 @@ NTSTATUS idmap_init(void) backend_init_status = NT_STATUS_OK; - return NT_STATUS_OK; + return ret; done: DEBUG(0, ("Aborting IDMAP Initialization ...\n")); diff --git a/source/nsswitch/idmap_ldap.c b/source/nsswitch/idmap_ldap.c index 8cccbcecf4c..f74372eceab 100644 --- a/source/nsswitch/idmap_ldap.c +++ b/source/nsswitch/idmap_ldap.c @@ -1283,6 +1283,9 @@ static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id sid, (unsigned long)map->xid.id, type)); DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", ld_error ? ld_error : "(NULL)", ldap_err2string (rc))); + if (ld_error) { + ldap_memfree(ld_error); + } ret = NT_STATUS_UNSUCCESSFUL; goto done; } diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c index d21c985feee..66f9a093144 100644 --- a/source/nsswitch/pam_winbind.c +++ b/source/nsswitch/pam_winbind.c @@ -436,7 +436,7 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, /* Fill in request and send down pipe */ init_request(request, req_type); - if (write_sock(request, sizeof(*request), 0) == -1) { + if (write_sock(request, sizeof(*request), 0, 1) == -1) { _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); close_sock(); return PAM_SERVICE_ERR; @@ -1517,7 +1517,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, dictionary *d = NULL; char *username_ret = NULL; char *new_authtok_required = NULL; - char *combined_member = NULL; const char *real_username = NULL; /* parse arguments */ diff --git a/source/nsswitch/wb_common.c b/source/nsswitch/wb_common.c index 05d2a660e73..fb84373aa63 100644 --- a/source/nsswitch/wb_common.c +++ b/source/nsswitch/wb_common.c @@ -33,6 +33,7 @@ BOOL winbind_on( void ); /* Global variables. These are effectively the client state information */ int winbindd_fd = -1; /* fd for winbindd socket */ +static int is_privileged = 0; /* Free a response structure */ @@ -287,7 +288,7 @@ static int winbind_named_pipe_sock(const char *dir) /* Connect to winbindd socket */ -static int winbind_open_pipe_sock(int recursing) +static int winbind_open_pipe_sock(int recursing, int need_priv) { #ifdef HAVE_UNIXSOCKET static pid_t our_pid; @@ -300,6 +301,10 @@ static int winbind_open_pipe_sock(int recursing) close_sock(); our_pid = getpid(); } + + if ((need_priv != 0) && (is_privileged == 0)) { + close_sock(); + } if (winbindd_fd != -1) { return winbindd_fd; @@ -313,6 +318,8 @@ static int winbind_open_pipe_sock(int recursing) return -1; } + is_privileged = 0; + /* version-check the socket */ request.flags = WBFLAG_RECURSE; @@ -329,9 +336,14 @@ static int winbind_open_pipe_sock(int recursing) if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) { close(winbindd_fd); winbindd_fd = fd; + is_privileged = 1; } } + if ((need_priv != 0) && (is_privileged == 0)) { + return -1; + } + SAFE_FREE(response.extra_data.data); return winbindd_fd; @@ -342,7 +354,7 @@ static int winbind_open_pipe_sock(int recursing) /* Write data to winbindd socket */ -int write_sock(void *buffer, int count, int recursing) +int write_sock(void *buffer, int count, int recursing, int need_priv) { int result, nwritten; @@ -350,7 +362,7 @@ int write_sock(void *buffer, int count, int recursing) restart: - if (winbind_open_pipe_sock(recursing) == -1) { + if (winbind_open_pipe_sock(recursing, need_priv) == -1) { return -1; } @@ -536,7 +548,8 @@ BOOL winbind_env_set( void ) * send simple types of requests */ -NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) +NSS_STATUS winbindd_send_request(int req_type, int need_priv, + struct winbindd_request *request) { struct winbindd_request lrequest; @@ -555,12 +568,14 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) init_request(request, req_type); - if (write_sock(request, sizeof(*request), request->flags & WBFLAG_RECURSE) == -1) { + if (write_sock(request, sizeof(*request), + request->flags & WBFLAG_RECURSE, need_priv) == -1) { return NSS_STATUS_UNAVAIL; } if ((request->extra_len != 0) && - (write_sock(request->extra_data.data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) { + (write_sock(request->extra_data.data, request->extra_len, + request->flags & WBFLAG_RECURSE, need_priv) == -1)) { return NSS_STATUS_UNAVAIL; } @@ -610,7 +625,25 @@ NSS_STATUS winbindd_request_response(int req_type, int count = 0; while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { - status = winbindd_send_request(req_type, request); + status = winbindd_send_request(req_type, 0, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + status = winbindd_get_response(response); + count += 1; + } + + return status; +} + +NSS_STATUS winbindd_priv_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + NSS_STATUS status = NSS_STATUS_UNAVAIL; + int count = 0; + + while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { + status = winbindd_send_request(req_type, 1, request); if (status != NSS_STATUS_SUCCESS) return(status); status = winbindd_get_response(response); diff --git a/source/nsswitch/winbind_client.h b/source/nsswitch/winbind_client.h index 1d3d379af00..d80aff37fa1 100644 --- a/source/nsswitch/winbind_client.h +++ b/source/nsswitch/winbind_client.h @@ -2,13 +2,16 @@ #include "winbindd_nss.h" void init_request(struct winbindd_request *req,int rq_type); -NSS_STATUS winbindd_send_request(int req_type, +NSS_STATUS winbindd_send_request(int req_type, int need_priv, struct winbindd_request *request); NSS_STATUS winbindd_get_response(struct winbindd_response *response); NSS_STATUS winbindd_request_response(int req_type, struct winbindd_request *request, struct winbindd_response *response); -int write_sock(void *buffer, int count, int recursing); +NSS_STATUS winbindd_priv_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response); +int write_sock(void *buffer, int count, int recursing, int need_priv); int read_reply(struct winbindd_response *response); void close_sock(void); void free_response(struct winbindd_response *response); diff --git a/source/nsswitch/winbind_nss_irix.c b/source/nsswitch/winbind_nss_irix.c index 2fbf3e0df82..5c6679f0442 100644 --- a/source/nsswitch/winbind_nss_irix.c +++ b/source/nsswitch/winbind_nss_irix.c @@ -454,7 +454,7 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request) nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) %d, timeout = %d sec\n", rq->f_cmd_data, timeout); - status = winbindd_send_request((int)rq->f_cmd_data,request); + status = winbindd_send_request((int)rq->f_cmd_data,request,0); SAFE_FREE(request); if (status != NSS_STATUS_SUCCESS) { diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index 3ddb041ba07..3b518fe3206 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -726,6 +726,15 @@ static void process_loop(void) int maxfd, listen_sock, listen_priv_sock, selret; struct timeval timeout, ev_timeout; + /* Open Sockets here to get stuff going ASAP */ + listen_sock = open_winbindd_socket(); + listen_priv_sock = open_winbindd_priv_socket(); + + if (listen_sock == -1 || listen_priv_sock == -1) { + perror("open_winbind_socket"); + exit(1); + } + /* We'll be doing this a lot */ /* Handle messages */ @@ -745,14 +754,6 @@ static void process_loop(void) /* Initialise fd lists for select() */ - listen_sock = open_winbindd_socket(); - listen_priv_sock = open_winbindd_priv_socket(); - - if (listen_sock == -1 || listen_priv_sock == -1) { - perror("open_winbind_socket"); - exit(1); - } - maxfd = MAX(listen_sock, listen_priv_sock); FD_ZERO(&r_fds); diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h index b9e07a2321b..198c655b2d3 100644 --- a/source/nsswitch/winbindd.h +++ b/source/nsswitch/winbindd.h @@ -40,6 +40,8 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +#define WB_REPLACE_CHAR '_' + /* bits for fd_event.flags */ #define EVENT_FD_READ 1 #define EVENT_FD_WRITE 2 diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c index ea6dc2870a0..3925228efc6 100644 --- a/source/nsswitch/winbindd_ads.c +++ b/source/nsswitch/winbindd_ads.c @@ -40,6 +40,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) { ADS_STRUCT *ads; ADS_STATUS status; + fstring dc_name; + struct in_addr dc_ip; DEBUG(10,("ads_cached_connection\n")); @@ -114,6 +116,12 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME; + /* Setup the server affinity cache. We don't reaally care + about the name. Just setup affinity and the KRB5_CONFIG + file. */ + + get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ip ); + status = ads_connect(ads); if (!ADS_ERR_OK(status) || !ads->config.realm) { DEBUG(1,("ads_connect for domain %s failed: %s\n", @@ -607,7 +615,6 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, const char *attrs[] = {"memberOf", NULL}; size_t num_groups = 0; DOM_SID *group_sids = NULL; - char *escaped_dn; int i; DEBUG(3,("ads: lookup_usergroups_memberof\n")); @@ -619,16 +626,9 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain, goto done; } - if (!(escaped_dn = escape_ldap_string_alloc(user_dn))) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - rc = ads_search_retry_extended_dn(ads, &res, escaped_dn, attrs, + rc = ads_search_retry_extended_dn(ads, &res, user_dn, attrs, ADS_EXTENDED_DN_HEX_STRING); - SAFE_FREE(escaped_dn); - if (!ADS_ERR_OK(rc) || !res) { DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); diff --git a/source/nsswitch/winbindd_cred_cache.c b/source/nsswitch/winbindd_cred_cache.c index d0904002dd9..f161587e7aa 100644 --- a/source/nsswitch/winbindd_cred_cache.c +++ b/source/nsswitch/winbindd_cred_cache.c @@ -517,6 +517,7 @@ static NTSTATUS store_memory_creds(struct WINBINDD_MEMORY_CREDS *memcredp, const if ((mlock(memcredp->nt_hash, memcredp->len)) == -1) { DEBUG(0,("failed to mlock memory: %s (%d)\n", strerror(errno), errno)); + SAFE_FREE(memcredp->nt_hash); return map_nt_error_from_unix(errno); } diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c index 6324de9a2d9..26debd26745 100644 --- a/source/nsswitch/winbindd_dual.c +++ b/source/nsswitch/winbindd_dual.c @@ -573,8 +573,8 @@ void winbind_msg_online(int msg_type, struct process_id src, winbindd_flush_negative_conn_cache(domain); set_domain_online_request(domain); - /* Send an offline message to the idmap child when our - primary domain goes offline */ + /* Send an online message to the idmap child when our + primary domain comes back online */ if ( domain->primary ) { struct winbindd_child *idmap = idmap_child(); diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c index 7edb755f1c0..9cf6cc12e0f 100644 --- a/source/nsswitch/winbindd_group.c +++ b/source/nsswitch/winbindd_group.c @@ -228,10 +228,12 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, * from more than one domain, ie aliases. Thus we have to work it out * ourselves in a special routine. */ - if (domain->internal) - return fill_passdb_alias_grmem(domain, group_sid, + if (domain->internal) { + result = fill_passdb_alias_grmem(domain, group_sid, num_gr_mem, gr_mem, gr_mem_len); + goto done; + } if ( !((group_name_type==SID_NAME_DOM_GRP) || ((group_name_type==SID_NAME_ALIAS) && domain->primary)) ) @@ -506,7 +508,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state) /* Get rid and name type from name */ - ws_name_replace( name_group, '_' ); + ws_name_replace( name_group, WB_REPLACE_CHAR ); if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, domain->name, name_group, &group_sid, &name_type)) { @@ -1273,6 +1275,8 @@ void winbindd_getgroups(struct winbindd_cli_state *state) s->state = state; + ws_name_return( state->request.data.username, WB_REPLACE_CHAR ); + if (!parse_domain_user_talloc(state->mem_ctx, state->request.data.username, &s->domname, &s->username)) { diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index 2e679c37dcf..6ee548292cc 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -744,6 +744,8 @@ void winbindd_pam_auth(struct winbindd_cli_state *state) /* Parse domain and username */ + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + if (!canonicalize_username(state->request.data.auth.user, name_domain, name_user)) { set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER); @@ -1332,6 +1334,8 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, /* Parse domain and username */ + ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR ); + parse_domain_user(state->request.data.auth.user, name_domain, name_user); if (domain->online == False) { @@ -2088,7 +2092,9 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state) { struct winbindd_domain *domain; fstring name_domain, user; - + uid_t caller_uid = (uid_t)-1; + uid_t request_uid = state->request.data.logoff.uid; + DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid, state->request.data.logoff.user)); @@ -2099,6 +2105,10 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state) state->request.data.logoff.krb5ccname [sizeof(state->request.data.logoff.krb5ccname)-1]='\0'; + if (request_uid == (gid_t)-1) { + goto failed; + } + if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) { goto failed; } @@ -2107,6 +2117,28 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state) goto failed; } + if ((sys_getpeereid(state->sock, &caller_uid)) != 0) { + DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", + strerror(errno))); + goto failed; + } + + switch (caller_uid) { + case -1: + goto failed; + case 0: + /* root must be able to logoff any user - gd */ + state->request.data.logoff.uid = request_uid; + break; + default: + if (caller_uid != request_uid) { + DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n")); + goto failed; + } + state->request.data.logoff.uid = caller_uid; + break; + } + sendto_domain(state, domain); return; diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c index 11d9fe0dbbd..3707f0311f8 100644 --- a/source/nsswitch/winbindd_rpc.c +++ b/source/nsswitch/winbindd_rpc.c @@ -262,7 +262,7 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - ws_name_return( full_name, '_' ); + ws_name_return( full_name, WB_REPLACE_CHAR ); DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name )); @@ -317,7 +317,7 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain, *domain_name = domains[0]; *name = names[0]; - ws_name_replace( *name, '_' ); + ws_name_replace( *name, WB_REPLACE_CHAR ); DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); return NT_STATUS_OK; @@ -369,7 +369,7 @@ NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain, ret_names = *names; for (i=0; i<num_rids; i++) { if ((*types)[i] != SID_NAME_UNKNOWN) { - ws_name_replace( ret_names[i], '_' ); + ws_name_replace( ret_names[i], WB_REPLACE_CHAR ); *domain_name = domains[i]; } } diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c index 47a7364e3a7..ce677198fff 100644 --- a/source/nsswitch/winbindd_user.c +++ b/source/nsswitch/winbindd_user.c @@ -243,7 +243,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success, strlower_m( username ); s->username = talloc_strdup(s->state->mem_ctx, username); - ws_name_replace( s->username, '_' ); + ws_name_replace( s->username, WB_REPLACE_CHAR ); s->fullname = talloc_strdup(s->state->mem_ctx, full_name); s->homedir = talloc_strdup(s->state->mem_ctx, homedir); @@ -262,7 +262,7 @@ static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid) talloc_get_type_abort(private_data, struct getpwsid_state); if (!success) { - DEBUG(5, ("Could not query user's %s\\%s uid\n", + DEBUG(5, ("Could not query uid for user %s\\%s\n", s->domain->name, s->username)); request_error(s->state); return; @@ -289,7 +289,7 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) if ( s->gid == (gid_t)-1 ) { if (!success) { - DEBUG(5, ("Could not query user's %s\\%s\n gid", + DEBUG(5, ("Could not query gid for user %s\\%s\n", s->domain->name, s->username)); goto failed; } @@ -345,6 +345,8 @@ void winbindd_getpwnam(struct winbindd_cli_state *state) DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid, state->request.data.username)); + ws_name_return( state->request.data.username, WB_REPLACE_CHAR ); + if (!parse_domain_user(state->request.data.username, domname, username)) { DEBUG(5, ("Could not parse domain user: %s\n", |