diff options
author | Gerald Carter <jerry@samba.org> | 2004-01-13 17:55:43 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2004-01-13 17:55:43 +0000 |
commit | 0c9adb69858c7572320d18c0fd187dd6e885f17d (patch) | |
tree | d58b1ad6bbc5ca0e9f71d17ebdaa9905268fa1d4 /source3/nsswitch | |
parent | 60079bd15bee7fe71dd43cb131f6198ca28f74eb (diff) | |
download | samba-0c9adb69858c7572320d18c0fd187dd6e885f17d.tar.gz samba-0c9adb69858c7572320d18c0fd187dd6e885f17d.tar.bz2 samba-0c9adb69858c7572320d18c0fd187dd6e885f17d.zip |
sync HEAD with recent changes in 3.0
(This used to be commit c98399e3c9d74e19b7c9d806ca8028b48866931e)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/wbinfo.c | 26 | ||||
-rw-r--r-- | source3/nsswitch/winbind_nss_freebsd.c | 81 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.h | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 6 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 103 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 62 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_misc.c | 16 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_nss.h | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 13 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_sid.c | 8 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 52 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 45 | ||||
-rw-r--r-- | source3/nsswitch/wins.c | 4 |
15 files changed, 298 insertions, 128 deletions
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 7d25524f8e..c7dc89d43f 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -298,18 +298,20 @@ static BOOL wbinfo_domain_info(const char *domain_name) /* Display response */ - d_printf("Name : %s\n", response.data.domain_info.name); - d_printf("Alt_Name: %s\n", response.data.domain_info.alt_name); + d_printf("Name : %s\n", response.data.domain_info.name); + d_printf("Alt_Name : %s\n", response.data.domain_info.alt_name); - d_printf("SID : %s\n", response.data.domain_info.sid); + d_printf("SID : %s\n", response.data.domain_info.sid); - d_printf("Native : %s\n", + d_printf("Active Directory : %s\n", + response.data.domain_info.active_directory ? "Yes" : "No"); + d_printf("Native : %s\n", response.data.domain_info.native_mode ? "Yes" : "No"); - d_printf("Primary : %s\n", + d_printf("Primary : %s\n", response.data.domain_info.primary ? "Yes" : "No"); - d_printf("Sequence: %d\n", response.data.domain_info.sequence_number); + d_printf("Sequence : %d\n", response.data.domain_info.sequence_number); return True; } @@ -909,14 +911,14 @@ static void wbinfo_get_auth_user(void) char *user, *domain, *password; /* Lift data from secrets file */ + + secrets_fetch_ipc_userpass(&user, &domain, &password); - secrets_init(); - - user = secrets_fetch(SECRETS_AUTH_USER, NULL); - domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); - password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); + if ((!user || !*user) && (!domain || !*domain ) && (!password || !*password)){ - if (!user && !domain && !password) { + SAFE_FREE(user); + SAFE_FREE(domain); + SAFE_FREE(password); d_printf("No authorised user configured\n"); return; } diff --git a/source3/nsswitch/winbind_nss_freebsd.c b/source3/nsswitch/winbind_nss_freebsd.c new file mode 100644 index 0000000000..b73a4ce44f --- /dev/null +++ b/source3/nsswitch/winbind_nss_freebsd.c @@ -0,0 +1,81 @@ +/* + Unix SMB/CIFS implementation. + + AIX loadable authentication module, providing identification + routines against Samba winbind/Windows NT Domain + + Copyright (C) Aaron Collins 2003 + + 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_client.h" + +/* Make sure that the module gets registered needed by freebsd 5.1 */ + +extern enum nss_status _nss_winbind_getgrent_r(struct group *, char *, size_t, + int *); +extern enum nss_status _nss_winbind_getgrnam_r(const char *, struct group *, + char *, size_t, int *); +extern enum nss_status _nss_winbind_getgrgid_r(gid_t gid, struct group *, char *, + size_t, int *); +extern enum nss_status _nss_winbind_setgrent(void); +extern enum nss_status _nss_winbind_endgrent(void); + +extern enum nss_status _nss_winbind_getpwent_r(struct passwd *, char *, size_t, + int *); +extern enum nss_status _nss_winbind_getpwnam_r(const char *, struct passwd *, + char *, size_t, int *); +extern enum nss_status _nss_winbind_getpwuid_r(gid_t gid, struct passwd *, char *, + size_t, int *); +extern enum nss_status _nss_winbind_setpwent(void); +extern enum nss_status _nss_winbind_endpwent(void); + +NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r); +NSS_METHOD_PROTOTYPE(__nss_compat_setgrent); +NSS_METHOD_PROTOTYPE(__nss_compat_endgrent); + +NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r); +NSS_METHOD_PROTOTYPE(__nss_compat_setpwent); +NSS_METHOD_PROTOTYPE(__nss_compat_endpwent); + +static ns_mtab methods[] = { +{ NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_winbind_getgrnam_r }, +{ NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_winbind_getgrgid_r }, +{ NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_winbind_getgrent_r }, +{ NSDB_GROUP, "endgrent", __nss_compat_setgrent, _nss_winbind_setgrent }, +{ NSDB_GROUP, "setgrent", __nss_compat_endgrent, _nss_winbind_endgrent }, + +{ NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_winbind_getpwnam_r }, +{ NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_winbind_getpwuid_r }, +{ NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_winbind_getpwent_r }, +{ NSDB_PASSWD, "endpwent", __nss_compat_setpwent, _nss_winbind_setpwent }, +{ NSDB_PASSWD, "setpwent", __nss_compat_endpwent, _nss_winbind_endpwent }, + +}; + +ns_mtab * +nss_module_register(const char *source, unsigned int *mtabsize, + nss_module_unregister_fn *unreg) +{ + *mtabsize = sizeof(methods)/sizeof(methods[0]); + *unreg = NULL; + return (methods); +} diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 4c03522461..3124ef6378 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -935,6 +935,8 @@ int main(int argc, char **argv) netsamlogon_cache_init(); /* Non-critical */ + init_domain_list(); + /* Loop waiting for requests */ process_loop(); diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 5dbe422bc1..7c8e6256e1 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -95,7 +95,8 @@ struct winbindd_domain { fstring alt_name; /* alt Domain name (if any) */ DOM_SID sid; /* SID for this domain */ BOOL native_mode; /* is this a win2k domain in native mode ? */ - BOOL primary; /* is this our primary domain ? */ + BOOL active_directory; /* is this a win2k active directory ? */ + BOOL primary; /* is this our primary domain ? */ /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index ec93d494d0..e6b857f406 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -112,7 +112,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, goto done; } - rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); + rc = ads_search_retry(ads, &res, "(objectClass=user)", attrs); if (!ADS_ERR_OK(rc) || !res) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index a3c1706b75..8dec89a6aa 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -107,12 +107,14 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) case SEC_ADS: { extern struct winbindd_methods ads_methods; /* always obey the lp_security parameter for our domain */ - if ( strequal(lp_realm(), domain->alt_name) || strequal(lp_workgroup(), domain->name) ) { + if (domain->primary) { domain->backend = &ads_methods; break; } - if ( domain->native_mode ) { + /* if it have either of the indications of ADS, + use ads_methods */ + if ( domain->active_directory || domain->native_mode ) { domain->backend = &ads_methods; break; } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 2b561be31d..44fc06fe54 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -174,16 +174,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i if ((lp_security() == SEC_ADS) && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) { + ADS_STATUS ads_status; new_conn->cli->use_kerberos = True; DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n", new_conn->controller, global_myname(), machine_krb5_principal)); - result = NT_STATUS_OK; - - if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, - machine_password, - lp_workgroup()))) { - DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result))); + ads_status = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, + machine_password, + lp_workgroup()); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4,("failed kerberos session setup with %s\n", ads_errstr(ads_status))); + result = ads_ntstatus(ads_status); + } else { + result = NT_STATUS_OK; } } new_conn->cli->use_kerberos = False; @@ -405,46 +408,116 @@ static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const } /********************************************************************************** + We can 'sense' certain things about the DC by it's replies to certain questions. + + This tells us if this particular remote server is Active Directory, and if it is + native mode. **********************************************************************************/ -BOOL cm_check_for_native_mode_win2k( struct winbindd_domain *domain ) +void set_dc_type_and_flags( struct winbindd_domain *domain ) { NTSTATUS result; struct winbindd_cm_conn conn; DS_DOMINFO_CTR ctr; - BOOL ret = False; + TALLOC_CTX *mem_ctx = NULL; ZERO_STRUCT( conn ); ZERO_STRUCT( ctr ); + domain->native_mode = False; + domain->active_directory = False; if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) { - DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", + DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n", domain->name, nt_errstr(result))); - return False; + return; } if ( conn.cli ) { if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) { - ret = False; goto done; } } if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) - ret = True; + domain->native_mode = True; -done: + /* Cheat - shut down the DS pipe, and open LSA */ + + cli_nt_session_close(conn.cli); + + if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) { + char *domain_name = NULL; + char *dns_name = NULL; + DOM_SID *dom_sid = NULL; + + mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name); + if (!mem_ctx) { + DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n")); + return; + } + + result = cli_lsa_open_policy2(conn.cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn.pol); + + if (NT_STATUS_IS_OK(result)) { + /* This particular query is exactly what Win2k clients use + to determine that the DC is active directory */ + result = cli_lsa_query_info_policy2(conn.cli, mem_ctx, + &conn.pol, + 12, &domain_name, + &dns_name, NULL, + NULL, &dom_sid); + } + + if (NT_STATUS_IS_OK(result)) { + if (domain_name) + fstrcpy(domain->name, domain_name); + + if (dns_name) + fstrcpy(domain->alt_name, dns_name); + if (dom_sid) + sid_copy(&domain->sid, dom_sid); + + domain->active_directory = True; + } else { + + result = cli_lsa_open_policy(conn.cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, + &conn.pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + result = cli_lsa_query_info_policy(conn.cli, mem_ctx, + &conn.pol, 5, &domain_name, + &dom_sid); + + if (NT_STATUS_IS_OK(result)) { + if (domain_name) + fstrcpy(domain->name, domain_name); + + if (dom_sid) + sid_copy(&domain->sid, dom_sid); + } + } + } + +done: + /* close the connection; no other cals use this pipe and it is called only on reestablishing the domain list --jerry */ - + if ( conn.cli ) cli_shutdown( conn.cli ); - return ret; + talloc_destroy(mem_ctx); + + return; } diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 180a3db8e2..b31dc92b38 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -106,7 +106,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, *num_gr_mem = 0; if ( !((group_name_type==SID_NAME_DOM_GRP) || - ((group_name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + ((group_name_type==SID_NAME_ALIAS) && domain->primary)) ) { DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", sid_to_string(sid_string, group_sid), domain->name, @@ -152,15 +152,10 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, occur in Universal groups on a Windows 2000 native mode server. */ - if (name_types[i] != SID_NAME_USER) { - DEBUG(3, ("name %s isn't a domain user\n", the_name)); - continue; - } + /* make sure to allow machine accounts */ - /* Don't bother with machine accounts */ - - if (the_name[strlen(the_name) - 1] == '$') { - DEBUG(10, ("%s is machine account\n", the_name)); + if (name_types[i] != SID_NAME_USER && name_types[i] != SID_NAME_COMPUTER) { + DEBUG(3, ("name %s isn't a domain user\n", the_name)); continue; } @@ -265,22 +260,20 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) return WINBINDD_OK; } - /* should we deal with users for our domain? */ - - if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) { - DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n", - name_domain, name_group)); - return WINBINDD_ERROR; - } - - /* Get info for the domain */ if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not get domain sid for domain %s\n", + DEBUG(3, ("could not get domain sid for domain %s\n", name_domain)); return WINBINDD_ERROR; } + /* should we deal with users for our domain? */ + + if ( lp_winbind_trusted_domains_only() && domain->primary) { + DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n", + name_domain, name_group)); + return WINBINDD_ERROR; + } /* Get rid and name type from name */ @@ -292,7 +285,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) } if ( !((name_type==SID_NAME_DOM_GRP) || - ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + ((name_type==SID_NAME_ALIAS) && domain->primary)) ) { DEBUG(1, ("name '%s' is not a local or domain group: %d\n", name_group, name_type)); @@ -383,7 +376,7 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) } if ( !((name_type==SID_NAME_DOM_GRP) || - ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + ((name_type==SID_NAME_ALIAS) && domain->primary) )) { DEBUG(1, ("name '%s' is not a local or domain group: %d\n", group_name, name_type)); @@ -441,7 +434,7 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state) are a member of a Samba domain */ if ( (IS_DC || lp_winbind_trusted_domains_only()) - && strequal(domain->name, lp_workgroup()) ) + && domain->primary ) { continue; } @@ -547,7 +540,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent) and are not using LDAP to get the groups */ if ( lp_security() != SEC_ADS && domain->native_mode - && strequal(lp_workgroup(), domain->name) ) + && domain->primary ) { DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n")); @@ -887,7 +880,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) extra_data[extra_data_len++] = ','; } - free(groups.sam_entries); + SAFE_FREE(groups.sam_entries); } /* Assign extra_data fields in response structure */ @@ -938,21 +931,22 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) /* Parse domain and username */ parse_domain_user(state->request.data.username, - name_domain, name_user); - - /* bail if there is no domain */ + name_domain, name_user); - if ( !*name_domain ) - goto done; - /* Get info for the domain */ if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not find domain entry for domain %s\n", + DEBUG(7, ("could not find domain entry for domain %s\n", name_domain)); goto done; } + if ( domain->primary && lp_winbind_trusted_domains_only()) { + DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getgroups() for %s\\%s.\n", + name_domain, name_user)); + return WINBINDD_ERROR; + } + /* Get rid and name type from name. The following costs 1 packet */ if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, @@ -961,7 +955,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) goto done; } - if (name_type != SID_NAME_USER) { + if (name_type != SID_NAME_USER && name_type != SID_NAME_COMPUTER) { DEBUG(1, ("name '%s' is not a user name: %d\n", name_user, name_type)); goto done; @@ -1000,7 +994,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) in a win2k native mode domain. */ if ( !((sid_type==SID_NAME_DOM_GRP) || - ((sid_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + ((sid_type==SID_NAME_ALIAS) && domain->primary)) ) { DEBUG(10, ("winbindd_getgroups: sid type %d " "for %s is not a domain group\n", @@ -1127,7 +1121,7 @@ enum winbindd_result winbindd_getusersids(struct winbindd_cli_state *state) sid_string_static(&user_sid))); goto done; } - + status = domain->methods->lookup_usergroups(domain, mem_ctx, &user_sid, &num_groups, &user_grpsids); diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 08b5be827d..18478992f3 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -36,7 +36,6 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat int num_retries = 0; struct cli_state *cli; uint32 sec_channel_type; - const char *contact_domain_name = NULL; struct winbindd_domain *contact_domain; DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid)); @@ -51,18 +50,10 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat } - /* use the realm name if appropriate and possible */ - - if ( lp_security() == SEC_ADS ) - contact_domain_name = lp_realm(); - - if ( !contact_domain_name || !*contact_domain_name ) - contact_domain_name = lp_workgroup(); - - contact_domain = find_domain_from_name(contact_domain_name); + contact_domain = find_our_domain(); if (!contact_domain) { result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - DEBUG(1, ("%s is not a trusted domain\n", contact_domain_name)); + DEBUG(1, ("Cannot find our own domain!\n")); goto done; } @@ -132,7 +123,7 @@ enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state /* Skip own domain */ - if (strequal(domain->name, lp_workgroup())) continue; + if (domain->primary) continue; /* Add domain to list */ @@ -232,6 +223,7 @@ enum winbindd_result winbindd_domain_info(struct winbindd_cli_state *state) sid_string_static(&domain->sid)); state->response.data.domain_info.native_mode = domain->native_mode; + state->response.data.domain_info.active_directory = domain->active_directory; state->response.data.domain_info.primary = domain->primary; state->response.data.domain_info.sequence_number = diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index 0dd00e9b39..0d110b8afa 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -36,7 +36,7 @@ /* Update this when you change the interface. */ -#define WINBIND_INTERFACE_VERSION 8 +#define WINBIND_INTERFACE_VERSION 9 /* Socket commands */ @@ -272,6 +272,7 @@ struct winbindd_response { fstring alt_name; fstring sid; BOOL native_mode; + BOOL active_directory; BOOL primary; uint32 sequence_number; } domain_info; diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index f619aa3564..21e0c3092e 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -950,7 +950,8 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) NTSTATUS result = NT_STATUS_UNSUCCESSFUL; TALLOC_CTX *mem_ctx; CLI_POLICY_HND *hnd; - fstring level5_dom; + char *level5_dom; + DOM_SID *alloc_sid; int retry; DEBUG(3,("rpc: domain_sid\n")); @@ -965,9 +966,17 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) goto done; result = cli_lsa_query_info_policy(hnd->cli, mem_ctx, - &hnd->pol, 0x05, level5_dom, sid); + &hnd->pol, 0x05, &level5_dom, &alloc_sid); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + if (NT_STATUS_IS_OK(result)) { + if (alloc_sid) { + sid_copy(sid, alloc_sid); + } else { + result = NT_STATUS_NO_MEMORY; + } + } + done: talloc_destroy(mem_ctx); return result; diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index 7c4c8d804a..9fbf47046d 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/nsswitch/winbindd_sid.c @@ -152,7 +152,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) DOM_SID sid2; uint32 rid; - domain = find_domain_from_name( lp_workgroup() ); + domain = find_our_domain(); if ( !domain ) { DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n")); return WINBINDD_ERROR; @@ -244,7 +244,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) uint32 rid; unid_t id; - domain = find_domain_from_name( lp_workgroup() ); + domain = find_our_domain(); if ( !domain ) { DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n")); return WINBINDD_ERROR; @@ -341,7 +341,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) if ( !(pw = getpwuid(state->request.data.uid)) ) return WINBINDD_ERROR; - if ( !(domain = find_domain_from_name(lp_workgroup())) ) { + if ( !(domain = find_our_domain()) ) { DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n")); return WINBINDD_ERROR; } @@ -411,7 +411,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) if ( !(grp = getgrgid(state->request.data.gid)) ) return WINBINDD_ERROR; - if ( !(domain = find_domain_from_name(lp_workgroup())) ) { + if ( !(domain = find_our_domain()) ) { DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n")); return WINBINDD_ERROR; } diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index 903a2a8bfa..d08377c888 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -37,7 +37,8 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, char *full_name, struct winbindd_pw *pw) { fstring output_username; - pstring homedir; + char *homedir; + char *shell; fstring sid_string; if (!pw || !dom_name || !user_name) @@ -72,24 +73,32 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, shell. */ /* The substitution of %U and %D in the 'template homedir' is done - by lp_string() calling standard_sub_basic(). */ + by alloc_sub_specified() below. */ - fstrcpy(current_user_info.smb_name, user_name); - sub_set_smb_name(user_name); fstrcpy(current_user_info.domain, dom_name); - pstrcpy(homedir, lp_template_homedir()); + homedir = alloc_sub_specified(lp_template_homedir(), user_name, dom_name, pw->pw_uid, pw->pw_gid); + + if (!homedir) + return False; safe_strcpy(pw->pw_dir, homedir, sizeof(pw->pw_dir) - 1); - safe_strcpy(pw->pw_shell, lp_template_shell(), + SAFE_FREE(homedir); + + shell = alloc_sub_specified(lp_template_shell(), user_name, dom_name, pw->pw_uid, pw->pw_gid); + + if (!shell) + return False; + + safe_strcpy(pw->pw_shell, shell, sizeof(pw->pw_shell) - 1); /* Password - set to "x" as we can't generate anything useful here. Authentication can be done using the pam_winbind module. */ safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1); - + return True; } @@ -115,7 +124,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) /* Parse domain and username */ parse_domain_user(state->request.data.username, - name_domain, name_user); + name_domain, name_user); /* if this is our local domain (or no domain), the do a local tdb search */ @@ -131,17 +140,17 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) /* should we deal with users for our domain? */ - if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) { - DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", - name_domain, name_user)); - return WINBINDD_ERROR; - } - if ((domain = find_domain_from_name(name_domain)) == NULL) { DEBUG(5, ("no such domain: %s\n", name_domain)); return WINBINDD_ERROR; } + if ( domain->primary && lp_winbind_trusted_domains_only()) { + DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", + name_domain, name_user)); + return WINBINDD_ERROR; + } + /* Get rid and name type from name */ if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) { @@ -149,15 +158,13 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - if (name_type != SID_NAME_USER) { + if (name_type != SID_NAME_USER && name_type != SID_NAME_COMPUTER) { DEBUG(1, ("name '%s' is not a user name: %d\n", name_user, name_type)); return WINBINDD_ERROR; } - /* Get some user info. Split the user rid from the sid obtained - from the winbind_lookup_by_name() call and use it in a - winbind_lookup_userinfo() */ + /* Get some user info. */ if (!(mem_ctx = talloc_init("winbindd_getpwnam([%s]\\[%s])", name_domain, name_user))) { @@ -530,15 +537,6 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state) name_list = ent->sam_entries; - /* Skip machine accounts */ - - if (name_list[ent->sam_entry_index]. - name[strlen(name_list[ent->sam_entry_index].name) - 1] - == '$') { - ent->sam_entry_index++; - continue; - } - /* Lookup user info */ result = winbindd_fill_pwent( diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 4cc43e85d6..076ab1a2fc 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -49,6 +49,14 @@ static const fstring name_deadbeef = "<deadbeef>"; static struct winbindd_domain *_domain_list; +/** + When was the last scan of trusted domains done? + + 0 == not ever +*/ + +static time_t last_trustdom_scan; + struct winbindd_domain *domain_list(void) { /* Initialise list */ @@ -83,6 +91,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const { struct winbindd_domain *domain; const char *alternative_name = NULL; + static const DOM_SID null_sid; /* ignore alt_name if we are not in an AD domain */ @@ -103,6 +112,13 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const return domain; } } + if (sid) { + if (sid_equal(sid, &null_sid) ) { + + } else if (sid_equal(sid, &domain->sid)) { + return domain; + } + } } /* Create new domain entry */ @@ -133,12 +149,14 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const sid_copy(&domain->sid, sid); } - /* see if this is a native mode win2k domain */ + /* set flags about native_mode, active_directory */ - domain->native_mode = cm_check_for_native_mode_win2k( domain ); + set_dc_type_and_flags( domain ); - DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain->name, - domain->native_mode ? "native" : "mixed (or NT4)" )); + DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name, + domain->active_directory ? "ADS" : "NT4", + domain->native_mode ? "native mode" : + ((domain->active_directory && !domain->native_mode) ? "mixed mode" : ""))); /* Link to domain list */ DLIST_ADD(_domain_list, domain); @@ -156,13 +174,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const void rescan_trusted_domains( void ) { - static time_t last_scan; time_t now = time(NULL); struct winbindd_domain *mydomain = NULL; /* see if the time has come... */ - if ( (now > last_scan) && ((now-last_scan) < WINBINDD_RESCAN_FREQ) ) + if ( (now > last_trustdom_scan) && ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) ) return; if ( (mydomain = find_our_domain()) == NULL ) { @@ -174,7 +191,7 @@ void rescan_trusted_domains( void ) add_trusted_domains( mydomain ); - last_scan = now; + last_trustdom_scan = now; return; } @@ -200,7 +217,7 @@ void add_trusted_domains( struct winbindd_domain *domain ) return; } - DEBUG(1, ("scanning trusted domain list\n")); + DEBUG(5, ("scanning trusted domain list\n")); if (!(mem_ctx = talloc_init("init_domain_list"))) return; @@ -221,7 +238,7 @@ void add_trusted_domains( struct winbindd_domain *domain ) for(i = 0; i < num_domains; i++) { DEBUG(10,("Found domain %s\n", names[i])); add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, - domain->methods, &dom_sids[i]); + domain->methods, &dom_sids[i]); /* if the SID was empty, we better set it now */ @@ -263,7 +280,7 @@ BOOL init_domain_list(void) /* Free existing list */ free_domain_list(); - /* Add ourselves as the first entry. It *must* be the first entry */ + /* Add ourselves as the first entry. */ domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL); @@ -286,7 +303,9 @@ BOOL init_domain_list(void) /* do an initial scan for trusted domains */ add_trusted_domains(domain); - + + /* avoid rescanning this right away */ + last_trustdom_scan = time(NULL); return True; } @@ -364,10 +383,6 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, { NTSTATUS result; TALLOC_CTX *mem_ctx; - /* Don't bother with machine accounts */ - - if (name[strlen(name) - 1] == '$') - return False; mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name); if (!mem_ctx) diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c index 779d1b2c6c..100a103924 100644 --- a/source3/nsswitch/wins.c +++ b/source3/nsswitch/wins.c @@ -194,7 +194,7 @@ int lookup(nsd_file_t *rq) * response needs to be a string of the following format * ip_address[ ip_address]*\tname[ alias]* */ - if (strcasecmp(map,"hosts.byaddr") == 0) { + if (StrCaseCmp(map,"hosts.byaddr") == 0) { if ( status = lookup_byaddr_backend(key, &count)) { size = strlen(key) + 1; if (size > len) { @@ -222,7 +222,7 @@ int lookup(nsd_file_t *rq) response[strlen(response)-1] = '\n'; free(status); } - } else if (strcasecmp(map,"hosts.byname") == 0) { + } else if (StrCaseCmp(map,"hosts.byname") == 0) { if (ip_list = lookup_byname_backend(key, &count)) { for (i = count; i ; i--) { addr = inet_ntoa(ip_list[i-1]); |