2016-03-29 17:03:04 +03:00
/*
* idmap_ad : map between Active Directory and RFC 2307 or " Services for Unix " ( SFU ) Accounts
*
* Unix SMB / CIFS implementation .
*
* Winbind ADS backend functions
*
* Copyright ( C ) Andrew Tridgell 2001
* Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2003
* Copyright ( C ) Gerald ( Jerry ) Carter 2004 - 2007
* Copyright ( C ) Luke Howard 2001 - 2004
* Copyright ( C ) Michael Adam 2008 , 2010
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program 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 General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "winbindd.h"
# include "../libds/common/flags.h"
2017-05-11 22:38:50 +03:00
# include "winbindd_ads.h"
2016-03-29 17:03:04 +03:00
# include "libads/ldap_schema.h"
# include "nss_info.h"
# include "idmap.h"
# include "../libcli/ldap/ldap_ndr.h"
# include "../libcli/security/security.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
# define CHECK_ALLOC_DONE(mem) do { \
if ( ! mem ) { \
DEBUG ( 0 , ( " Out of memory! \n " ) ) ; \
ret = NT_STATUS_NO_MEMORY ; \
goto done ; \
} \
} while ( 0 )
struct idmap_ad_context {
ADS_STRUCT * ads ;
struct posix_schema * ad_schema ;
enum wb_posix_mapping ad_map_type ; /* WB_POSIX_MAP_UNKNOWN */
} ;
/************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static ADS_STATUS ad_idmap_cached_connection ( struct idmap_domain * dom )
{
ADS_STATUS status ;
struct idmap_ad_context * ctx ;
DEBUG ( 10 , ( " ad_idmap_cached_connection: called for domain '%s' \n " ,
dom - > name ) ) ;
ctx = talloc_get_type ( dom - > private_data , struct idmap_ad_context ) ;
status = ads_idmap_cached_connection ( & ctx - > ads , dom - > name ) ;
if ( ! ADS_ERR_OK ( status ) ) {
return status ;
}
ctx = talloc_get_type ( dom - > private_data , struct idmap_ad_context ) ;
/* if we have a valid ADS_STRUCT and the schema model is
defined , then we can return here . */
if ( ctx - > ad_schema ) {
return ADS_SUCCESS ;
}
/* Otherwise, set the schema model */
if ( ( ctx - > ad_map_type = = WB_POSIX_MAP_SFU ) | |
( ctx - > ad_map_type = = WB_POSIX_MAP_SFU20 ) | |
( ctx - > ad_map_type = = WB_POSIX_MAP_RFC2307 ) )
{
status = ads_check_posix_schema_mapping (
ctx , ctx - > ads , ctx - > ad_map_type , & ctx - > ad_schema ) ;
if ( ! ADS_ERR_OK ( status ) ) {
DEBUG ( 2 , ( " ad_idmap_cached_connection: Failed to obtain schema details! \n " ) ) ;
}
}
return status ;
}
/*
* nss_info_ { sfu , sfu20 , rfc2307 }
*/
/************************************************************************
Initialize the { sfu , sfu20 , rfc2307 } state
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * wb_posix_map_unknown_string = " WB_POSIX_MAP_UNKNOWN " ;
static const char * wb_posix_map_template_string = " WB_POSIX_MAP_TEMPLATE " ;
static const char * wb_posix_map_sfu_string = " WB_POSIX_MAP_SFU " ;
static const char * wb_posix_map_sfu20_string = " WB_POSIX_MAP_SFU20 " ;
static const char * wb_posix_map_rfc2307_string = " WB_POSIX_MAP_RFC2307 " ;
static const char * wb_posix_map_unixinfo_string = " WB_POSIX_MAP_UNIXINFO " ;
static const char * ad_map_type_string ( enum wb_posix_mapping map_type )
{
switch ( map_type ) {
case WB_POSIX_MAP_TEMPLATE :
return wb_posix_map_template_string ;
case WB_POSIX_MAP_SFU :
return wb_posix_map_sfu_string ;
case WB_POSIX_MAP_SFU20 :
return wb_posix_map_sfu20_string ;
case WB_POSIX_MAP_RFC2307 :
return wb_posix_map_rfc2307_string ;
case WB_POSIX_MAP_UNIXINFO :
return wb_posix_map_unixinfo_string ;
default :
return wb_posix_map_unknown_string ;
}
}
static NTSTATUS nss_ad_generic_init ( struct nss_domain_entry * e ,
enum wb_posix_mapping new_ad_map_type )
{
struct idmap_domain * dom ;
struct idmap_ad_context * ctx ;
if ( e - > state ! = NULL ) {
dom = talloc_get_type ( e - > state , struct idmap_domain ) ;
} else {
dom = talloc_zero ( e , struct idmap_domain ) ;
if ( dom = = NULL ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
e - > state = dom ;
}
if ( e - > domain ! = NULL ) {
dom - > name = talloc_strdup ( dom , e - > domain ) ;
if ( dom - > name = = NULL ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
}
if ( dom - > private_data ! = NULL ) {
ctx = talloc_get_type ( dom - > private_data ,
struct idmap_ad_context ) ;
} else {
ctx = talloc_zero ( dom , struct idmap_ad_context ) ;
if ( ctx = = NULL ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
ctx - > ad_map_type = WB_POSIX_MAP_RFC2307 ;
dom - > private_data = ctx ;
}
if ( ( ctx - > ad_map_type ! = WB_POSIX_MAP_UNKNOWN ) & &
( ctx - > ad_map_type ! = new_ad_map_type ) )
{
DEBUG ( 2 , ( " nss_ad_generic_init: "
" Warning: overriding previously set posix map type "
" %s for domain %s with map type %s. \n " ,
ad_map_type_string ( ctx - > ad_map_type ) ,
dom - > name ,
ad_map_type_string ( new_ad_map_type ) ) ) ;
}
ctx - > ad_map_type = new_ad_map_type ;
return NT_STATUS_OK ;
}
static NTSTATUS nss_sfu_init ( struct nss_domain_entry * e )
{
return nss_ad_generic_init ( e , WB_POSIX_MAP_SFU ) ;
}
static NTSTATUS nss_sfu20_init ( struct nss_domain_entry * e )
{
return nss_ad_generic_init ( e , WB_POSIX_MAP_SFU20 ) ;
}
static NTSTATUS nss_rfc2307_init ( struct nss_domain_entry * e )
{
return nss_ad_generic_init ( e , WB_POSIX_MAP_RFC2307 ) ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS nss_ad_map_to_alias ( TALLOC_CTX * mem_ctx ,
struct nss_domain_entry * e ,
const char * name ,
char * * alias )
{
const char * attrs [ ] = { NULL , /* attr_uid */
NULL } ;
char * filter = NULL ;
LDAPMessage * msg = NULL ;
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
struct idmap_domain * dom ;
struct idmap_ad_context * ctx = NULL ;
/* Check incoming parameters */
if ( ! e | | ! e - > domain | | ! name | | ! * alias ) {
nt_status = NT_STATUS_INVALID_PARAMETER ;
goto done ;
}
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
nt_status = NT_STATUS_FILE_IS_OFFLINE ;
goto done ;
}
dom = talloc_get_type ( e - > state , struct idmap_domain ) ;
ctx = talloc_get_type ( dom - > private_data , struct idmap_ad_context ) ;
ads_status = ad_idmap_cached_connection ( dom ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
if ( ! ctx - > ad_schema ) {
nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
goto done ;
}
attrs [ 0 ] = ctx - > ad_schema - > posix_uid_attr ;
filter = talloc_asprintf ( mem_ctx ,
" (sAMAccountName=%s) " ,
name ) ;
if ( ! filter ) {
nt_status = NT_STATUS_NO_MEMORY ;
goto done ;
}
ads_status = ads_search_retry ( ctx - > ads , & msg , filter , attrs ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
nt_status = ads_ntstatus ( ads_status ) ;
goto done ;
}
* alias = ads_pull_string ( ctx - > ads , mem_ctx , msg , ctx - > ad_schema - > posix_uid_attr ) ;
if ( ! * alias ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
nt_status = NT_STATUS_OK ;
done :
if ( filter ) {
talloc_destroy ( filter ) ;
}
if ( msg ) {
ads_msgfree ( ctx - > ads , msg ) ;
}
return nt_status ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS nss_ad_map_from_alias ( TALLOC_CTX * mem_ctx ,
struct nss_domain_entry * e ,
const char * alias ,
char * * name )
{
const char * attrs [ ] = { " sAMAccountName " ,
NULL } ;
char * filter = NULL ;
LDAPMessage * msg = NULL ;
ADS_STATUS ads_status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
2018-04-06 12:04:24 +03:00
char * username = NULL ;
2016-03-29 17:03:04 +03:00
struct idmap_domain * dom ;
struct idmap_ad_context * ctx = NULL ;
/* Check incoming parameters */
if ( ! alias | | ! name ) {
nt_status = NT_STATUS_INVALID_PARAMETER ;
goto done ;
}
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
nt_status = NT_STATUS_FILE_IS_OFFLINE ;
goto done ;
}
dom = talloc_get_type ( e - > state , struct idmap_domain ) ;
ctx = talloc_get_type ( dom - > private_data , struct idmap_ad_context ) ;
ads_status = ad_idmap_cached_connection ( dom ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
if ( ! ctx - > ad_schema ) {
nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
goto done ;
}
filter = talloc_asprintf ( mem_ctx ,
" (%s=%s) " ,
ctx - > ad_schema - > posix_uid_attr ,
alias ) ;
if ( ! filter ) {
nt_status = NT_STATUS_NO_MEMORY ;
goto done ;
}
ads_status = ads_search_retry ( ctx - > ads , & msg , filter , attrs ) ;
if ( ! ADS_ERR_OK ( ads_status ) ) {
nt_status = ads_ntstatus ( ads_status ) ;
goto done ;
}
username = ads_pull_string ( ctx - > ads , mem_ctx , msg ,
" sAMAccountName " ) ;
if ( ! username ) {
2018-04-06 12:04:24 +03:00
nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
goto done ;
2016-03-29 17:03:04 +03:00
}
* name = talloc_asprintf ( mem_ctx , " %s \\ %s " ,
lp_workgroup ( ) ,
username ) ;
if ( ! * name ) {
nt_status = NT_STATUS_NO_MEMORY ;
goto done ;
}
nt_status = NT_STATUS_OK ;
done :
2018-04-06 12:04:24 +03:00
TALLOC_FREE ( username ) ;
2018-04-06 12:02:48 +03:00
TALLOC_FREE ( filter ) ;
2016-03-29 17:03:04 +03:00
if ( msg ) {
ads_msgfree ( ctx - > ads , msg ) ;
}
return nt_status ;
}
/************************************************************************
Function dispatch tables for the idmap and nss plugins
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* The SFU and RFC2307 NSS plugins share everything but the init
function which sets the intended schema model to use */
static struct nss_info_methods nss_rfc2307_methods = {
. init = nss_rfc2307_init ,
. map_to_alias = nss_ad_map_to_alias ,
. map_from_alias = nss_ad_map_from_alias ,
} ;
static struct nss_info_methods nss_sfu_methods = {
. init = nss_sfu_init ,
. map_to_alias = nss_ad_map_to_alias ,
. map_from_alias = nss_ad_map_from_alias ,
} ;
static struct nss_info_methods nss_sfu20_methods = {
. init = nss_sfu20_init ,
. map_to_alias = nss_ad_map_to_alias ,
. map_from_alias = nss_ad_map_from_alias ,
} ;
/************************************************************************
Initialize the plugins
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-04-20 22:24:43 +03:00
NTSTATUS idmap_ad_nss_init ( TALLOC_CTX * mem_ctx )
2016-03-29 17:03:04 +03:00
{
2016-12-17 17:03:59 +03:00
NTSTATUS status ;
2016-03-29 17:03:04 +03:00
2016-12-17 17:03:59 +03:00
status = smb_register_idmap_nss ( SMB_NSS_INFO_INTERFACE_VERSION ,
" rfc2307 " , & nss_rfc2307_methods ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2016-03-29 17:03:04 +03:00
}
2016-12-17 17:03:59 +03:00
status = smb_register_idmap_nss ( SMB_NSS_INFO_INTERFACE_VERSION ,
" sfu " , & nss_sfu_methods ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2016-03-29 17:03:04 +03:00
}
2016-12-17 17:03:59 +03:00
status = smb_register_idmap_nss ( SMB_NSS_INFO_INTERFACE_VERSION ,
" sfu20 " , & nss_sfu20_methods ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2016-03-29 17:03:04 +03:00
}
return NT_STATUS_OK ;
}