diff options
| -rw-r--r-- | source3/include/nss_info.h | 10 | ||||
| -rw-r--r-- | source3/winbindd/nss_info.c | 41 | ||||
| -rw-r--r-- | source3/winbindd/nss_info_template.c | 32 | ||||
| -rw-r--r-- | source3/winbindd/winbindd_cache.c | 249 | ||||
| -rw-r--r-- | source3/winbindd/winbindd_proto.h | 18 | ||||
| -rw-r--r-- | source3/winbindd/winbindd_util.c | 107 | 
6 files changed, 435 insertions, 22 deletions
diff --git a/source3/include/nss_info.h b/source3/include/nss_info.h index 1ff9ebcd55..e756136b76 100644 --- a/source3/include/nss_info.h +++ b/source3/include/nss_info.h @@ -66,6 +66,10 @@ struct nss_info_methods {  				  TALLOC_CTX *ctx,   				  ADS_STRUCT *ads, LDAPMessage *msg,  				  char **homedir, char **shell, char **gecos, gid_t *p_gid); +	NTSTATUS (*map_to_alias)( TALLOC_CTX *mem_ctx, const char *domain, +				  const char *name, char **alias ); +	NTSTATUS (*map_from_alias)( TALLOC_CTX *mem_ctx, const char *domain, +				    const char *alias, char **name );  	NTSTATUS (*close_fn)( void );  }; @@ -84,6 +88,12 @@ NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid,                         char **homedir, char **shell, char **gecos,                         gid_t *p_gid); +NTSTATUS nss_map_to_alias( TALLOC_CTX *mem_ctx, const char *domain, +			   const char *name, char **alias ); + +NTSTATUS nss_map_from_alias( TALLOC_CTX *mem_ctx, const char *domain, +			     const char *alias, char **name ); +  NTSTATUS nss_close( const char *parameters );  #endif /* _IDMAP_NSS_H_ */ diff --git a/source3/winbindd/nss_info.c b/source3/winbindd/nss_info.c index daa3dd037d..0e8cb60257 100644 --- a/source3/winbindd/nss_info.c +++ b/source3/winbindd/nss_info.c @@ -281,6 +281,47 @@ static struct nss_domain_entry *find_nss_domain( const char *domain )  /********************************************************************   *******************************************************************/ + NTSTATUS nss_map_to_alias( TALLOC_CTX *mem_ctx, const char *domain, +			    const char *name, char **alias ) +{ +	struct nss_domain_entry *p; +	struct nss_info_methods *m; + +	if ( (p = find_nss_domain( domain )) == NULL ) { +		DEBUG(4,("nss_map_to_alias: Failed to find nss domain pointer for %s\n", +			 domain )); +		return NT_STATUS_NOT_FOUND; +	} + +	m = p->backend->methods; + +	return m->map_to_alias( mem_ctx, domain, name, alias ); +} + + +/******************************************************************** + *******************************************************************/ + + NTSTATUS nss_map_from_alias( TALLOC_CTX *mem_ctx, const char *domain, +			      const char *alias, char **name ) +{ +	struct nss_domain_entry *p; +	struct nss_info_methods *m; + +	if ( (p = find_nss_domain( domain )) == NULL ) { +		DEBUG(4,("nss_map_from_alias: Failed to find nss domain pointer for %s\n", +			 domain )); +		return NT_STATUS_NOT_FOUND; +	} + +	m = p->backend->methods; + +	return m->map_from_alias( mem_ctx, domain, alias, name ); +} + +/******************************************************************** + *******************************************************************/ +   NTSTATUS nss_close( const char *parameters )  {  	struct nss_domain_entry *p = nss_domain_list; diff --git a/source3/winbindd/nss_info_template.c b/source3/winbindd/nss_info_template.c index aaf02e4abe..d8f903ddd0 100644 --- a/source3/winbindd/nss_info_template.c +++ b/source3/winbindd/nss_info_template.c @@ -45,6 +45,8 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e,  	if ( !homedir || !shell || !gecos )  		return NT_STATUS_INVALID_PARAMETER; +	/* protect against home directories using whitespace in the +	  username */  	*homedir = talloc_strdup( ctx, lp_template_homedir() );  	*shell   = talloc_strdup( ctx, lp_template_shell() );  	*gecos   = NULL; @@ -56,6 +58,28 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e,  	return NT_STATUS_OK;  } +/********************************************************************** + *********************************************************************/ + +static NTSTATUS nss_template_map_to_alias( TALLOC_CTX *mem_ctx, +					   const char *domain, +					   const char *name, +					   char **alias ) +{ +	return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS nss_template_map_from_alias( TALLOC_CTX *mem_ctx, +					     const char *domain, +					     const char *alias, +					     char **name ) +{ +	return NT_STATUS_NOT_IMPLEMENTED; +} +  /************************************************************************   ***********************************************************************/ @@ -69,9 +93,11 @@ static NTSTATUS nss_template_close( void )   ***********************************************************************/  static struct nss_info_methods nss_template_methods = { -	.init         = nss_template_init, -	.get_nss_info = nss_template_get_info, -	.close_fn     = nss_template_close +	.init           = nss_template_init, +	.get_nss_info   = nss_template_get_info, +	.map_to_alias   = nss_template_map_to_alias, +	.map_from_alias = nss_template_map_from_alias, +	.close_fn       = nss_template_close  };  NTSTATUS nss_info_template_init( void ) diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 2fbb01b623..360e915bc4 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -934,6 +934,8 @@ static void wcache_save_lockout_policy(struct winbindd_domain *domain,  	centry_free(centry);  } + +  static void wcache_save_password_policy(struct winbindd_domain *domain,  					NTSTATUS status,  					struct samr_DomInfo1 *policy) @@ -957,6 +959,209 @@ static void wcache_save_password_policy(struct winbindd_domain *domain,  	centry_free(centry);  } +/*************************************************************************** + ***************************************************************************/ + +static void wcache_save_username_alias(struct winbindd_domain *domain, +				       NTSTATUS status, +				       const char *name, const char *alias) +{ +	struct cache_entry *centry; +	fstring uname; + +	if ( (centry = centry_start(domain, status)) == NULL ) +		return; + +	centry_put_string( centry, alias ); + +	fstrcpy(uname, name); +	strupper_m(uname); +	centry_end(centry, "NSS/NA/%s", uname); + +	DEBUG(10,("wcache_save_username_alias: %s -> %s\n", name, alias )); + +	centry_free(centry); +} + +static void wcache_save_alias_username(struct winbindd_domain *domain, +				       NTSTATUS status, +				       const char *alias, const char *name) +{ +	struct cache_entry *centry; +	fstring uname; + +	if ( (centry = centry_start(domain, status)) == NULL ) +		return; + +	centry_put_string( centry, name ); + +	fstrcpy(uname, alias); +	strupper_m(uname); +	centry_end(centry, "NSS/AN/%s", uname); + +	DEBUG(10,("wcache_save_alias_username: %s -> %s\n", alias, name )); + +	centry_free(centry); +} + +/*************************************************************************** + ***************************************************************************/ + +NTSTATUS resolve_username_to_alias( TALLOC_CTX *mem_ctx, +				    struct winbindd_domain *domain, +				    const char *name, char **alias ) +{ +	struct winbind_cache *cache = get_cache(domain); +	struct cache_entry *centry = NULL; +	NTSTATUS status; +	char *upper_name; + +	if ( domain->internal ) +		return NT_STATUS_NOT_SUPPORTED; + +	if (!cache->tdb) +		goto do_query; + +	if ( (upper_name = SMB_STRDUP(name)) == NULL ) +		return NT_STATUS_NO_MEMORY; +	strupper_m(upper_name); + +	centry = wcache_fetch(cache, domain, "NSS/NA/%s", upper_name); + +	SAFE_FREE( upper_name ); + +	if (!centry) +		goto do_query; + +	status = centry->status; + +	if (!NT_STATUS_IS_OK(status)) { +		centry_free(centry); +		return status; +	} + +	*alias = centry_string( centry, mem_ctx ); + +	centry_free(centry); + +	DEBUG(10,("resolve_username_to_alias: [Cached] - mapped %s to %s\n", +		  name, *alias ? *alias : "(none)")); + +	return (*alias) ? NT_STATUS_OK : NT_STATUS_OBJECT_NAME_NOT_FOUND; + +do_query: + +	/* If its not in cache and we are offline, then fail */ + +	if ( get_global_winbindd_state_offline() || !domain->online ) { +		DEBUG(8,("resolve_username_to_alias: rejecting query " +			 "in offline mode\n")); +		return NT_STATUS_NOT_FOUND; +	} + +	status = nss_map_to_alias( mem_ctx, domain->name, name, alias ); + +	if ( NT_STATUS_IS_OK( status ) ) { +		wcache_save_username_alias(domain, status, name, *alias); +	} + +	if ( NT_STATUS_EQUAL( status, NT_STATUS_NONE_MAPPED ) ) { +		wcache_save_username_alias(domain, status, name, "(NULL)"); +	} + +	DEBUG(5,("resolve_username_to_alias: backend query returned %s\n", +		 nt_errstr(status))); + +	if ( NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ) { +		set_domain_offline( domain ); +	} + +	return status; +} + +/*************************************************************************** + ***************************************************************************/ + +NTSTATUS resolve_alias_to_username( TALLOC_CTX *mem_ctx, +				    struct winbindd_domain *domain, +				    const char *alias, char **name ) +{ +	struct winbind_cache *cache = get_cache(domain); +	struct cache_entry *centry = NULL; +	NTSTATUS status; +	char *upper_name; + +	if ( domain->internal ) +		return  NT_STATUS_NOT_SUPPORTED; + +	if (!cache->tdb) +		goto do_query; + +	if ( (upper_name = SMB_STRDUP(alias)) == NULL ) +		return NT_STATUS_NO_MEMORY; +	strupper_m(upper_name); + +	centry = wcache_fetch(cache, domain, "NSS/AN/%s", upper_name); + +	SAFE_FREE( upper_name ); + +	if (!centry) +		goto do_query; + +	status = centry->status; + +	if (!NT_STATUS_IS_OK(status)) { +		centry_free(centry); +		return status; +	} + +	*name = centry_string( centry, mem_ctx ); + +	centry_free(centry); + +	DEBUG(10,("resolve_alias_to_username: [Cached] - mapped %s to %s\n", +		  alias, *name ? *name : "(none)")); + +	return (*name) ? NT_STATUS_OK : NT_STATUS_OBJECT_NAME_NOT_FOUND; + +do_query: + +	/* If its not in cache and we are offline, then fail */ + +	if ( get_global_winbindd_state_offline() || !domain->online ) { +		DEBUG(8,("resolve_alias_to_username: rejecting query " +			 "in offline mode\n")); +		return NT_STATUS_NOT_FOUND; +	} + +	/* an alias cannot contain a domain prefix or '@' */ + +	if (strchr(alias, '\\') || strchr(alias, '@')) { +		DEBUG(10,("resolve_alias_to_username: skipping fully " +			  "qualified name %s\n", alias)); +		return NT_STATUS_OBJECT_NAME_INVALID; +	} + +	status = nss_map_from_alias( mem_ctx, domain->name, alias, name ); + +	if ( NT_STATUS_IS_OK( status ) ) { +		wcache_save_alias_username( domain, status, alias, *name ); +	} + +	if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { +		wcache_save_alias_username(domain, status, alias, "(NULL)"); +	} + +	DEBUG(5,("resolve_alias_to_username: backend query returned %s\n", +		 nt_errstr(status))); + +	if ( NT_STATUS_EQUAL(status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ) { +		set_domain_offline( domain ); +	} + +	return status; +} +  NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid)  {  	struct winbind_cache *cache = get_cache(domain); @@ -3257,6 +3462,48 @@ static int validate_pwinfo(TALLOC_CTX *mem_ctx, const char *keystr,  	return 0;  } +static int validate_nss_an(TALLOC_CTX *mem_ctx, const char *keystr, +			   TDB_DATA dbuf, +			   struct tdb_validation_status *state) +{ +	struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + +	if (!centry) { +		return 1; +	} + +	(void)centry_string( centry, mem_ctx ); + +	centry_free(centry); + +	if (!(state->success)) { +		return 1; +	} +	DEBUG(10,("validate_pwinfo: %s ok\n", keystr)); +	return 0; +} + +static int validate_nss_na(TALLOC_CTX *mem_ctx, const char *keystr, +			   TDB_DATA dbuf, +			   struct tdb_validation_status *state) +{ +	struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); + +	if (!centry) { +		return 1; +	} + +	(void)centry_string( centry, mem_ctx ); + +	centry_free(centry); + +	if (!(state->success)) { +		return 1; +	} +	DEBUG(10,("validate_pwinfo: %s ok\n", keystr)); +	return 0; +} +  static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,  			      struct tdb_validation_status *state)  { @@ -3358,6 +3605,8 @@ struct key_val_struct {  	{"NSS/PWINFO/", validate_pwinfo},  	{"TRUSTDOMS/", validate_trustdoms},  	{"TRUSTDOMCACHE/", validate_trustdomcache}, +	{"NSS/NA/", validate_nss_na}, +	{"NSS/AN/", validate_nss_an},  	{"WINBINDD_OFFLINE", validate_offline},  	{WINBINDD_CACHE_VERSION_KEYSTR, validate_cache_version},  	{NULL, NULL} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index e0fc073a0a..4774bc8106 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -583,8 +583,22 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,  				  TALLOC_CTX *mem_ctx,  				  const DOM_SID *user_sid,  				  uint32 *p_num_groups, DOM_SID **user_sids); -void ws_name_replace( char *name, char replace ); -void ws_name_return( char *name, char replace ); + +NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx, +			    struct winbindd_domain *domain, +			    char *name, +			    char **normalized); +NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx, +			      char *name, +			      char **normalized); + +NTSTATUS resolve_username_to_alias(TALLOC_CTX *mem_ctx, +				   struct winbindd_domain *domain, +				   const char *name, char **alias); +NTSTATUS resolve_alias_to_username(TALLOC_CTX *mem_ctx, +				   struct winbindd_domain *domain, +				   const char *alias, char **name); +  bool winbindd_can_contact_domain(struct winbindd_domain *domain);  bool winbindd_internal_child(struct winbindd_child *child);  void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain); diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 132c96f1ee..e7b6576317 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1378,34 +1378,107 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,   We use this to remove spaces from user and group names  ********************************************************************/ -void ws_name_replace( char *name, char replace ) +NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx, +			     struct winbindd_domain *domain, +			     char *name, +			     char **normalized)  { -	char replace_char[2] = { 0x0, 0x0 }; -     -	if ( !lp_winbind_normalize_names() || (replace == '\0') )  -		return; +	NTSTATUS nt_status; -	replace_char[0] = replace;	 -	all_string_sub( name, " ", replace_char, 0 ); +	if (!name || !normalized) { +		return NT_STATUS_INVALID_PARAMETER; +	} -	return;	 +	if (!lp_winbind_normalize_names()) { +		return NT_STATUS_PROCEDURE_NOT_FOUND; +	} + +	/* Alias support and whitespace replacement are mutually +	   exclusive */ + +	nt_status = resolve_username_to_alias(mem_ctx, domain, +					      name, normalized ); +	if (NT_STATUS_IS_OK(nt_status)) { +		/* special return code to let the caller know we +		   mapped to an alias */ +		return NT_STATUS_FILE_RENAMED; +	} + +	/* check for an unreachable domain */ + +	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { +		DEBUG(5,("normalize_name_map: Setting domain %s offline\n", +			 domain->name)); +		set_domain_offline(domain); +		return nt_status; +	} + +	/* deal with whitespace */ + +	*normalized = talloc_strdup(mem_ctx, name); +	if (!(*normalized)) { +		return NT_STATUS_NO_MEMORY; +	} + +	all_string_sub( *normalized, " ", "_", 0 ); + +	return NT_STATUS_OK;  }  /********************************************************************* - We use this to do the inverse of ws_name_replace() + We use this to do the inverse of normalize_name_map()  ********************************************************************/ -void ws_name_return( char *name, char replace ) +NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx, +			      char *name, +			      char **normalized)  { -	char replace_char[2] = { 0x0, 0x0 }; -     -	if ( !lp_winbind_normalize_names() || (replace == '\0') )  -		return; +	NTSTATUS nt_status; +	struct winbindd_domain *domain = find_our_domain(); + +	if (!name || !normalized) { +		return NT_STATUS_INVALID_PARAMETER; +	} -	replace_char[0] = replace;	 -	all_string_sub( name, replace_char, " ", 0 ); +	if (!lp_winbind_normalize_names()) { +		return NT_STATUS_PROCEDURE_NOT_FOUND; +	} -	return;	 +	/* Alias support and whitespace replacement are mutally +	   exclusive */ + +	/* When mapping from an alias to a username, we don't know the +	   domain.  But we only need a domain structure to cache +	   a successful lookup , so just our own domain structure for +	   the seqnum. */ + +	nt_status = resolve_alias_to_username(mem_ctx, domain, +					      name, normalized); +	if (NT_STATUS_IS_OK(nt_status)) { +		/* Special return code to let the caller know we mapped +		   from an alias */ +		return NT_STATUS_FILE_RENAMED; +	} + +	/* check for an unreachable domain */ + +	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { +		DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n", +			 domain->name)); +		set_domain_offline(domain); +		return nt_status; +	} + +	/* deal with whitespace */ + +	*normalized = talloc_strdup(mem_ctx, name); +	if (!(*normalized)) { +		return NT_STATUS_NO_MEMORY; +	} + +	all_string_sub(*normalized, "_", " ", 0); + +	return NT_STATUS_OK;  }  /*********************************************************************  | 
