2004-10-14 13:56:04 +04:00
/*
Unix SMB / CIFS implementation .
endpoint server for the drsuapi pipe
DsCrackNames ( )
Copyright ( C ) Stefan Metzmacher 2004
2005-09-02 07:19:27 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2005
2009-07-06 01:15:34 +04:00
2004-10-14 13:56:04 +04:00
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-10-14 13:56:04 +04:00
( at your option ) any later version .
2009-07-06 01:15:34 +04:00
2004-10-14 13:56:04 +04:00
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 .
2009-07-06 01:15:34 +04:00
2004-10-14 13:56:04 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-10-14 13:56:04 +04:00
*/
# include "includes.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/drsuapi.h"
2008-06-14 19:24:17 +04:00
# include "lib/events/events.h"
2009-10-18 00:20:43 +04:00
# include "rpc_server/common/common.h"
2007-12-07 01:15:37 +03:00
# include "lib/ldb/include/ldb.h"
2005-11-08 03:11:45 +03:00
# include "lib/ldb/include/ldb_errors.h"
2005-09-02 07:19:27 +04:00
# include "system/kerberos.h"
# include "auth/kerberos/kerberos.h"
2007-12-06 23:39:49 +03:00
# include "libcli/ldap/ldap_ndr.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2005-12-28 18:38:36 +03:00
# include "auth/auth.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/util_ldb.h"
2006-03-14 18:03:25 +03:00
# include "dsdb/samdb/samdb.h"
2010-02-16 08:09:07 +03:00
# include "dsdb/common/util.h"
2007-12-02 19:09:52 +03:00
# include "param/param.h"
2005-09-02 07:19:27 +04:00
2005-10-20 15:19:52 +04:00
static WERROR DsCrackNameOneFilter ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
2005-09-02 07:19:27 +04:00
struct smb_krb5_context * smb_krb5_context ,
2010-09-20 20:41:00 +04:00
uint32_t format_flags , enum drsuapi_DsNameFormat format_offered ,
enum drsuapi_DsNameFormat format_desired ,
2006-11-22 03:59:34 +03:00
struct ldb_dn * name_dn , const char * name ,
2005-09-02 07:19:27 +04:00
const char * domain_filter , const char * result_filter ,
struct drsuapi_DsNameInfo1 * info1 ) ;
2005-10-13 08:24:49 +04:00
static WERROR DsCrackNameOneSyntactical ( TALLOC_CTX * mem_ctx ,
2010-09-20 20:41:00 +04:00
enum drsuapi_DsNameFormat format_offered ,
enum drsuapi_DsNameFormat format_desired ,
2006-11-22 03:59:34 +03:00
struct ldb_dn * name_dn , const char * name ,
2005-10-13 08:24:49 +04:00
struct drsuapi_DsNameInfo1 * info1 ) ;
2007-08-27 06:31:51 +04:00
static WERROR dns_domain_from_principal ( TALLOC_CTX * mem_ctx , struct smb_krb5_context * smb_krb5_context ,
2007-04-07 07:04:33 +04:00
const char * name ,
struct drsuapi_DsNameInfo1 * info1 )
{
krb5_error_code ret ;
krb5_principal principal ;
/* perhaps it's a principal with a realm, so return the right 'domain only' response */
2009-10-18 00:20:43 +04:00
const char * realm ;
2007-04-07 07:04:33 +04:00
ret = krb5_parse_name_flags ( smb_krb5_context - > krb5_context , name ,
2009-06-08 13:06:16 +04:00
KRB5_PRINCIPAL_PARSE_REQUIRE_REALM , & principal ) ;
2007-04-07 07:04:33 +04:00
if ( ret ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
2007-04-07 09:14:23 +04:00
2007-04-07 07:04:33 +04:00
/* This isn't an allocation assignemnt, so it is free'ed with the krb5_free_principal */
2009-06-08 13:06:16 +04:00
realm = krb5_principal_get_realm ( smb_krb5_context - > krb5_context , principal ) ;
2009-07-06 01:15:34 +04:00
2009-06-08 13:06:16 +04:00
info1 - > dns_domain_name = talloc_strdup ( mem_ctx , realm ) ;
2007-04-07 07:04:33 +04:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2009-07-06 01:15:34 +04:00
2007-04-07 07:04:33 +04:00
W_ERROR_HAVE_NO_MEMORY ( info1 - > dns_domain_name ) ;
2009-07-06 01:15:34 +04:00
2007-04-07 07:04:33 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY ;
return WERR_OK ;
}
2005-09-02 07:19:27 +04:00
static enum drsuapi_DsNameStatus LDB_lookup_spn_alias ( krb5_context context , struct ldb_context * ldb_ctx ,
2006-01-31 06:15:16 +03:00
TALLOC_CTX * mem_ctx ,
const char * alias_from ,
char * * alias_to )
2005-09-02 07:19:27 +04:00
{
2009-11-06 22:14:41 +03:00
unsigned int i ;
2005-11-08 03:11:45 +03:00
int ret ;
struct ldb_result * res ;
2005-09-02 07:19:27 +04:00
struct ldb_message_element * spnmappings ;
2006-01-31 06:15:16 +03:00
TALLOC_CTX * tmp_ctx ;
struct ldb_dn * service_dn ;
char * service_dn_str ;
2006-02-01 01:41:53 +03:00
const char * directory_attrs [ ] = {
" sPNMappings " ,
NULL
} ;
2006-01-31 06:15:16 +03:00
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( ! tmp_ctx ) {
return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
}
2007-02-15 14:53:50 +03:00
service_dn = ldb_dn_new ( tmp_ctx , ldb_ctx , " CN=Directory Service,CN=Windows NT,CN=Services " ) ;
2010-04-13 10:41:10 +04:00
if ( ! ldb_dn_add_base ( service_dn , ldb_get_config_basedn ( ldb_ctx ) ) ) {
2006-11-22 03:59:34 +03:00
return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
}
2006-11-22 05:05:19 +03:00
service_dn_str = ldb_dn_alloc_linearized ( tmp_ctx , service_dn ) ;
2006-11-22 03:59:34 +03:00
if ( ! service_dn_str ) {
return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
}
2005-09-02 07:19:27 +04:00
2008-09-23 22:30:06 +04:00
ret = ldb_search ( ldb_ctx , tmp_ctx , & res , service_dn , LDB_SCOPE_BASE ,
directory_attrs , " (objectClass=nTDSService) " ) ;
2005-09-02 07:19:27 +04:00
2007-11-15 03:12:10 +03:00
if ( ret ! = LDB_SUCCESS & & ret ! = LDB_ERR_NO_SUCH_OBJECT ) {
2005-11-08 03:11:45 +03:00
DEBUG ( 1 , ( " ldb_search: dn: %s not found: %s " , service_dn_str , ldb_errstring ( ldb_ctx ) ) ) ;
2006-01-31 06:15:16 +03:00
return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
2007-11-27 04:47:57 +03:00
} else if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
DEBUG ( 1 , ( " ldb_search: dn: %s not found " , service_dn_str ) ) ;
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
} else if ( res - > count ! = 1 ) {
2006-01-31 06:15:16 +03:00
talloc_free ( res ) ;
2007-11-15 03:12:10 +03:00
DEBUG ( 1 , ( " ldb_search: dn: %s not found " , service_dn_str ) ) ;
2005-09-02 07:19:27 +04:00
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
}
2009-07-06 01:15:34 +04:00
2005-11-08 03:11:45 +03:00
spnmappings = ldb_msg_find_element ( res - > msgs [ 0 ] , " sPNMappings " ) ;
2005-09-02 07:19:27 +04:00
if ( ! spnmappings | | spnmappings - > num_values = = 0 ) {
DEBUG ( 1 , ( " ldb_search: dn: %s no sPNMappings attribute " , service_dn_str ) ) ;
2006-01-31 06:15:16 +03:00
talloc_free ( tmp_ctx ) ;
2005-09-02 07:19:27 +04:00
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
}
for ( i = 0 ; i < spnmappings - > num_values ; i + + ) {
char * mapping , * p , * str ;
2006-01-31 06:15:16 +03:00
mapping = talloc_strdup ( tmp_ctx ,
2005-09-02 07:19:27 +04:00
( const char * ) spnmappings - > values [ i ] . data ) ;
if ( ! mapping ) {
2005-10-13 08:24:49 +04:00
DEBUG ( 1 , ( " LDB_lookup_spn_alias: ldb_search: dn: %s did not have an sPNMapping \n " , service_dn_str ) ) ;
2006-01-31 06:15:16 +03:00
talloc_free ( tmp_ctx ) ;
2005-09-02 07:19:27 +04:00
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* C string manipulation sucks */
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
p = strchr ( mapping , ' = ' ) ;
if ( ! p ) {
2005-10-13 08:24:49 +04:00
DEBUG ( 1 , ( " ldb_search: dn: %s sPNMapping malformed: %s \n " ,
2005-09-02 07:19:27 +04:00
service_dn_str , mapping ) ) ;
2006-01-31 06:15:16 +03:00
talloc_free ( tmp_ctx ) ;
2005-09-02 07:19:27 +04:00
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
}
p [ 0 ] = ' \0 ' ;
p + + ;
do {
str = p ;
p = strchr ( p , ' , ' ) ;
if ( p ) {
p [ 0 ] = ' \0 ' ;
p + + ;
}
if ( strcasecmp ( str , alias_from ) = = 0 ) {
* alias_to = mapping ;
2006-01-31 06:15:16 +03:00
talloc_steal ( mem_ctx , mapping ) ;
talloc_free ( tmp_ctx ) ;
2005-09-06 04:34:22 +04:00
return DRSUAPI_DS_NAME_STATUS_OK ;
2005-09-02 07:19:27 +04:00
}
} while ( p ) ;
}
2006-03-11 05:07:14 +03:00
DEBUG ( 4 , ( " LDB_lookup_spn_alias: no alias for service %s applicable \n " , alias_from ) ) ;
2006-01-31 06:15:16 +03:00
talloc_free ( tmp_ctx ) ;
2005-09-02 07:19:27 +04:00
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
}
2005-12-19 10:07:11 +03:00
/* When cracking a ServicePrincipalName, many services may be served
* by the host / servicePrincipalName . The incoming query is for cifs /
* but we translate it here , and search on host / . This is done after
* the cifs / entry has been searched for , making this a fallback */
2005-10-20 15:19:52 +04:00
static WERROR DsCrackNameSPNAlias ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
2005-09-02 07:19:27 +04:00
struct smb_krb5_context * smb_krb5_context ,
2010-09-20 20:41:00 +04:00
uint32_t format_flags , enum drsuapi_DsNameFormat format_offered ,
enum drsuapi_DsNameFormat format_desired ,
2005-09-02 07:19:27 +04:00
const char * name , struct drsuapi_DsNameInfo1 * info1 )
{
WERROR wret ;
krb5_error_code ret ;
krb5_principal principal ;
2007-04-07 09:14:23 +04:00
const char * service , * dns_name ;
2005-09-02 07:19:27 +04:00
char * new_service ;
char * new_princ ;
enum drsuapi_DsNameStatus namestatus ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* parse principal */
2006-11-07 09:59:56 +03:00
ret = krb5_parse_name_flags ( smb_krb5_context - > krb5_context ,
name , KRB5_PRINCIPAL_PARSE_NO_REALM , & principal ) ;
2005-09-02 07:19:27 +04:00
if ( ret ) {
DEBUG ( 2 , ( " Could not parse principal: %s: %s " ,
name , smb_get_krb5_error_message ( smb_krb5_context - > krb5_context ,
ret , mem_ctx ) ) ) ;
return WERR_NOMEM ;
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* grab cifs/, http/ etc */
2009-07-06 01:15:34 +04:00
2005-10-13 08:24:49 +04:00
/* This is checked for in callers, but be safe */
2005-09-02 07:19:27 +04:00
if ( principal - > name . name_string . len < 2 ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
service = principal - > name . name_string . val [ 0 ] ;
2007-04-07 09:14:23 +04:00
dns_name = principal - > name . name_string . val [ 1 ] ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* MAP it */
namestatus = LDB_lookup_spn_alias ( smb_krb5_context - > krb5_context ,
2005-10-20 15:19:52 +04:00
sam_ctx , mem_ctx ,
2005-09-02 07:19:27 +04:00
service , & new_service ) ;
2009-07-06 01:15:34 +04:00
2007-04-07 09:14:23 +04:00
if ( namestatus = = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY ;
info1 - > dns_domain_name = talloc_strdup ( mem_ctx , dns_name ) ;
if ( ! info1 - > dns_domain_name ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
return WERR_NOMEM ;
}
2005-09-02 07:19:27 +04:00
return WERR_OK ;
2007-04-07 09:14:23 +04:00
} else if ( namestatus ! = DRSUAPI_DS_NAME_STATUS_OK ) {
info1 - > status = namestatus ;
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2005-09-02 07:19:27 +04:00
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* ooh, very nasty playing around in the Principal... */
free ( principal - > name . name_string . val [ 0 ] ) ;
principal - > name . name_string . val [ 0 ] = strdup ( new_service ) ;
if ( ! principal - > name . name_string . val [ 0 ] ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
return WERR_NOMEM ;
}
2009-07-06 01:15:34 +04:00
2005-10-13 08:24:49 +04:00
/* reform principal */
2006-11-07 09:59:56 +03:00
ret = krb5_unparse_name_flags ( smb_krb5_context - > krb5_context , principal ,
KRB5_PRINCIPAL_UNPARSE_NO_REALM , & new_princ ) ;
2005-09-02 07:19:27 +04:00
if ( ret ) {
2007-04-07 09:14:23 +04:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2005-09-02 07:19:27 +04:00
return WERR_NOMEM ;
}
2009-07-06 01:15:34 +04:00
2005-10-20 15:19:52 +04:00
wret = DsCrackNameOneName ( sam_ctx , mem_ctx , format_flags , format_offered , format_desired ,
2005-09-02 07:19:27 +04:00
new_princ , info1 ) ;
free ( new_princ ) ;
2007-04-07 09:14:23 +04:00
if ( W_ERROR_IS_OK ( wret ) & & ( info1 - > status = = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ) ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY ;
info1 - > dns_domain_name = talloc_strdup ( mem_ctx , dns_name ) ;
if ( ! info1 - > dns_domain_name ) {
wret = WERR_NOMEM ;
}
}
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2005-09-02 07:19:27 +04:00
return wret ;
}
2005-12-19 10:07:11 +03:00
/* Subcase of CrackNames, for the userPrincipalName */
2005-10-20 15:19:52 +04:00
static WERROR DsCrackNameUPN ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
2005-09-02 07:19:27 +04:00
struct smb_krb5_context * smb_krb5_context ,
2010-09-20 20:41:00 +04:00
uint32_t format_flags , enum drsuapi_DsNameFormat format_offered ,
enum drsuapi_DsNameFormat format_desired ,
2005-09-02 07:19:27 +04:00
const char * name , struct drsuapi_DsNameInfo1 * info1 )
{
2007-04-07 07:04:33 +04:00
int ldb_ret ;
2005-09-02 07:19:27 +04:00
WERROR status ;
const char * domain_filter = NULL ;
const char * result_filter = NULL ;
krb5_error_code ret ;
krb5_principal principal ;
2009-10-18 00:20:43 +04:00
const char * realm ;
2005-09-02 07:19:27 +04:00
char * unparsed_name_short ;
2007-04-07 07:04:33 +04:00
const char * domain_attrs [ ] = { NULL } ;
2007-11-15 03:12:10 +03:00
struct ldb_result * domain_res = NULL ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* Prevent recursion */
if ( ! name ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
2006-11-07 09:59:56 +03:00
ret = krb5_parse_name_flags ( smb_krb5_context - > krb5_context , name ,
2009-06-08 13:06:16 +04:00
KRB5_PRINCIPAL_PARSE_REQUIRE_REALM , & principal ) ;
2005-09-02 07:19:27 +04:00
if ( ret ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2009-06-08 13:06:16 +04:00
realm = krb5_principal_get_realm ( smb_krb5_context - > krb5_context , principal ) ;
2007-11-15 03:12:10 +03:00
2008-09-23 22:30:06 +04:00
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res ,
2007-11-15 03:12:10 +03:00
samdb_partitions_dn ( sam_ctx , mem_ctx ) ,
LDB_SCOPE_ONELEVEL ,
domain_attrs ,
" (&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*)) " ,
2009-06-08 13:06:16 +04:00
ldb_binary_encode_string ( mem_ctx , realm ) ,
ldb_binary_encode_string ( mem_ctx , realm ) ) ;
2007-11-15 03:12:10 +03:00
if ( ldb_ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameUPN domain ref search failed: %s " , ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
switch ( domain_res - > count ) {
2007-04-07 07:04:33 +04:00
case 1 :
break ;
case 0 :
2007-08-27 06:31:51 +04:00
return dns_domain_from_principal ( mem_ctx , smb_krb5_context ,
2007-04-07 09:14:23 +04:00
name , info1 ) ;
2007-04-07 07:04:33 +04:00
default :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2006-11-07 09:59:56 +03:00
ret = krb5_unparse_name_flags ( smb_krb5_context - > krb5_context , principal ,
KRB5_PRINCIPAL_UNPARSE_NO_REALM , & unparsed_name_short ) ;
2005-09-02 07:19:27 +04:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
if ( ret ) {
free ( unparsed_name_short ) ;
return WERR_NOMEM ;
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* This may need to be extended for more userPrincipalName variations */
result_filter = talloc_asprintf ( mem_ctx , " (&(objectClass=user)(samAccountName=%s)) " ,
2005-12-19 10:07:11 +03:00
ldb_binary_encode_string ( mem_ctx , unparsed_name_short ) ) ;
2007-11-15 03:12:10 +03:00
2008-03-13 08:35:53 +03:00
domain_filter = talloc_asprintf ( mem_ctx , " (distinguishedName=%s) " , ldb_dn_get_linearized ( domain_res - > msgs [ 0 ] - > dn ) ) ;
2007-11-15 03:12:10 +03:00
2005-09-02 07:19:27 +04:00
if ( ! result_filter | | ! domain_filter ) {
free ( unparsed_name_short ) ;
return WERR_NOMEM ;
}
2005-10-20 15:19:52 +04:00
status = DsCrackNameOneFilter ( sam_ctx , mem_ctx ,
2005-09-02 07:19:27 +04:00
smb_krb5_context ,
format_flags , format_offered , format_desired ,
NULL , unparsed_name_short , domain_filter , result_filter ,
info1 ) ;
free ( unparsed_name_short ) ;
2007-04-07 07:04:33 +04:00
2005-09-02 07:19:27 +04:00
return status ;
}
2004-10-14 13:56:04 +04:00
2005-12-19 10:07:11 +03:00
/* Crack a single 'name', from format_offered into format_desired, returning the result in info1 */
2005-10-24 02:20:42 +04:00
WERROR DsCrackNameOneName ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
2010-09-20 20:41:00 +04:00
uint32_t format_flags , enum drsuapi_DsNameFormat format_offered ,
enum drsuapi_DsNameFormat format_desired ,
2005-10-24 02:20:42 +04:00
const char * name , struct drsuapi_DsNameInfo1 * info1 )
2004-10-14 13:56:04 +04:00
{
2005-09-02 07:19:27 +04:00
krb5_error_code ret ;
2004-11-16 17:43:28 +03:00
const char * domain_filter = NULL ;
2004-11-16 13:56:51 +03:00
const char * result_filter = NULL ;
2005-09-03 04:52:34 +04:00
struct ldb_dn * name_dn = NULL ;
2005-09-02 07:19:27 +04:00
2008-10-01 01:24:58 +04:00
struct smb_krb5_context * smb_krb5_context = NULL ;
2004-11-16 13:56:51 +03:00
2004-10-14 13:56:04 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
info1 - > dns_domain_name = NULL ;
info1 - > result_name = NULL ;
2004-11-16 17:43:28 +03:00
if ( ! name ) {
return WERR_INVALID_PARAM ;
}
/* TODO: - fill the correct names in all cases!
* - handle format_flags
*/
/* here we need to set the domain_filter and/or the result_filter */
2004-10-14 13:56:04 +04:00
switch ( format_offered ) {
2008-10-01 01:24:58 +04:00
case DRSUAPI_DS_NAME_FORMAT_UNKNOWN :
{
2009-11-06 22:14:41 +03:00
unsigned int i ;
2008-10-01 01:24:58 +04:00
enum drsuapi_DsNameFormat formats [ ] = {
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 , DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL ,
DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT , DRSUAPI_DS_NAME_FORMAT_CANONICAL ,
DRSUAPI_DS_NAME_FORMAT_GUID , DRSUAPI_DS_NAME_FORMAT_DISPLAY ,
DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL ,
DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY ,
DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX
} ;
WERROR werr ;
for ( i = 0 ; i < ARRAY_SIZE ( formats ) ; i + + ) {
werr = DsCrackNameOneName ( sam_ctx , mem_ctx , format_flags , formats [ i ] , format_desired , name , info1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
if ( info1 - > status ! = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ) {
return werr ;
}
}
return werr ;
}
2006-12-28 06:33:52 +03:00
case DRSUAPI_DS_NAME_FORMAT_CANONICAL :
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX :
{
char * str , * s , * account ;
2009-07-06 01:15:34 +04:00
2006-12-28 06:33:52 +03:00
if ( strlen ( name ) = = 0 ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
str = talloc_strdup ( mem_ctx , name ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( str ) ;
2009-07-06 01:15:34 +04:00
2006-12-28 06:33:52 +03:00
if ( format_offered = = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX ) {
/* Look backwards for the \n, and replace it with / */
s = strrchr ( str , ' \n ' ) ;
if ( ! s ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
s [ 0 ] = ' / ' ;
}
s = strchr ( str , ' / ' ) ;
if ( ! s ) {
/* there must be at least one / */
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2006-12-28 06:33:52 +03:00
s [ 0 ] = ' \0 ' ;
s + + ;
domain_filter = talloc_asprintf ( mem_ctx , " (&(objectClass=crossRef)(ncName=%s)) " ,
ldb_dn_get_linearized ( samdb_dns_domain_to_dn ( sam_ctx , mem_ctx , str ) ) ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( domain_filter ) ;
2006-12-28 06:33:52 +03:00
/* There may not be anything after the domain component (search for the domain itself) */
if ( s [ 0 ] ) {
2009-07-06 01:15:34 +04:00
2006-12-28 06:33:52 +03:00
account = strrchr ( s , ' / ' ) ;
if ( ! account ) {
account = s ;
} else {
account + + ;
}
account = ldb_binary_encode_string ( mem_ctx , account ) ;
W_ERROR_HAVE_NO_MEMORY ( account ) ;
result_filter = talloc_asprintf ( mem_ctx , " (name=%s) " ,
account ) ;
W_ERROR_HAVE_NO_MEMORY ( result_filter ) ;
}
2005-09-02 07:19:27 +04:00
break ;
}
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT : {
char * p ;
char * domain ;
2010-08-17 07:19:53 +04:00
struct ldb_dn * dn_domain ;
2005-09-02 07:19:27 +04:00
const char * account = NULL ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
domain = talloc_strdup ( mem_ctx , name ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( domain ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
p = strchr ( domain , ' \\ ' ) ;
if ( ! p ) {
/* invalid input format */
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
p [ 0 ] = ' \0 ' ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
if ( p [ 1 ] ) {
account = & p [ 1 ] ;
}
2009-07-06 01:15:34 +04:00
2010-08-17 07:19:53 +04:00
/* it could be in DNS domain form */
dn_domain = samdb_dns_domain_to_dn ( sam_ctx , mem_ctx , domain ) ;
W_ERROR_HAVE_NO_MEMORY ( dn_domain ) ;
2005-09-02 07:19:27 +04:00
domain_filter = talloc_asprintf ( mem_ctx ,
2010-08-17 07:19:53 +04:00
" (&(&(|(nETBIOSName=%s)(nCName=%s))(objectclass=crossRef))(ncName=*)) " ,
ldb_binary_encode_string ( mem_ctx , domain ) ,
ldb_dn_get_linearized ( dn_domain ) ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( domain_filter ) ;
2005-09-02 07:19:27 +04:00
if ( account ) {
result_filter = talloc_asprintf ( mem_ctx , " (sAMAccountName=%s) " ,
2005-12-19 10:07:11 +03:00
ldb_binary_encode_string ( mem_ctx , account ) ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( result_filter ) ;
2005-09-02 07:19:27 +04:00
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
talloc_free ( domain ) ;
break ;
}
2006-01-31 06:15:16 +03:00
/* A LDAP DN as a string */
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_FQDN_1779 : {
domain_filter = NULL ;
2006-11-22 03:59:34 +03:00
name_dn = ldb_dn_new ( mem_ctx , sam_ctx , name ) ;
if ( ! ldb_dn_validate ( name_dn ) ) {
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
break ;
}
2006-01-31 06:15:16 +03:00
/* A GUID as a string */
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_GUID : {
struct GUID guid ;
char * ldap_guid ;
NTSTATUS nt_status ;
domain_filter = NULL ;
nt_status = GUID_from_string ( name , & guid ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
ldap_guid = ldap_encode_ndr_GUID ( mem_ctx , & guid ) ;
if ( ! ldap_guid ) {
return WERR_NOMEM ;
2004-11-16 13:56:51 +03:00
}
2005-09-02 07:19:27 +04:00
result_filter = talloc_asprintf ( mem_ctx , " (objectGUID=%s) " ,
ldap_guid ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( result_filter ) ;
2005-09-02 07:19:27 +04:00
break ;
}
2005-10-13 08:24:49 +04:00
case DRSUAPI_DS_NAME_FORMAT_DISPLAY : {
domain_filter = NULL ;
result_filter = talloc_asprintf ( mem_ctx , " (|(displayName=%s)(samAccountName=%s)) " ,
2005-12-19 10:07:11 +03:00
ldb_binary_encode_string ( mem_ctx , name ) ,
ldb_binary_encode_string ( mem_ctx , name ) ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( result_filter ) ;
2005-10-13 08:24:49 +04:00
break ;
}
2009-07-06 01:15:34 +04:00
2006-01-31 06:15:16 +03:00
/* A S-1234-5678 style string */
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY : {
struct dom_sid * sid = dom_sid_parse_talloc ( mem_ctx , name ) ;
char * ldap_sid ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
domain_filter = NULL ;
if ( ! sid ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
2004-10-14 13:56:04 +04:00
}
2005-09-02 07:19:27 +04:00
ldap_sid = ldap_encode_ndr_dom_sid ( mem_ctx ,
sid ) ;
if ( ! ldap_sid ) {
return WERR_NOMEM ;
}
result_filter = talloc_asprintf ( mem_ctx , " (objectSid=%s) " ,
ldap_sid ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( result_filter ) ;
2005-09-02 07:19:27 +04:00
break ;
}
case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL : {
krb5_principal principal ;
char * unparsed_name ;
2008-10-01 01:24:58 +04:00
ret = smb_krb5_init_context ( mem_ctx ,
ldb_get_event_context ( sam_ctx ) ,
( struct loadparm_context * ) ldb_get_opaque ( sam_ctx , " loadparm " ) ,
& smb_krb5_context ) ;
2009-07-06 01:15:34 +04:00
2008-10-01 01:24:58 +04:00
if ( ret ) {
return WERR_NOMEM ;
}
2009-06-30 04:19:19 +04:00
/* Ensure we reject compleate junk first */
2005-09-02 07:19:27 +04:00
ret = krb5_parse_name ( smb_krb5_context - > krb5_context , name , & principal ) ;
if ( ret ) {
2004-10-14 13:56:04 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
2004-10-15 15:08:14 +04:00
return WERR_OK ;
2004-10-14 13:56:04 +04:00
}
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
domain_filter = NULL ;
2009-07-06 01:15:34 +04:00
2009-06-30 04:19:19 +04:00
/* By getting the unparsed name here, we ensure the escaping is correct (and trust the client less) */
2005-09-02 07:19:27 +04:00
ret = krb5_unparse_name ( smb_krb5_context - > krb5_context , principal , & unparsed_name ) ;
if ( ret ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
return WERR_NOMEM ;
}
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2009-06-30 04:19:19 +04:00
/* The ldb_binary_encode_string() here avoid LDAP filter injection attacks */
2005-09-02 07:19:27 +04:00
result_filter = talloc_asprintf ( mem_ctx , " (&(objectClass=user)(userPrincipalName=%s)) " ,
2005-12-19 10:07:11 +03:00
ldb_binary_encode_string ( mem_ctx , unparsed_name ) ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
free ( unparsed_name ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( result_filter ) ;
2005-09-02 07:19:27 +04:00
break ;
2004-10-14 13:56:04 +04:00
}
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL : {
krb5_principal principal ;
char * unparsed_name_short ;
2005-12-19 10:07:11 +03:00
char * service ;
2008-10-01 01:24:58 +04:00
ret = smb_krb5_init_context ( mem_ctx ,
ldb_get_event_context ( sam_ctx ) ,
( struct loadparm_context * ) ldb_get_opaque ( sam_ctx , " loadparm " ) ,
& smb_krb5_context ) ;
2009-07-06 01:15:34 +04:00
2008-10-01 01:24:58 +04:00
if ( ret ) {
return WERR_NOMEM ;
}
2007-04-07 09:14:23 +04:00
ret = krb5_parse_name ( smb_krb5_context - > krb5_context , name , & principal ) ;
if ( ret = = 0 & & principal - > name . name_string . len < 2 ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
return WERR_OK ;
}
2006-11-07 09:59:56 +03:00
ret = krb5_parse_name_flags ( smb_krb5_context - > krb5_context , name ,
KRB5_PRINCIPAL_PARSE_NO_REALM , & principal ) ;
2005-10-28 09:14:51 +04:00
if ( ret ) {
2007-04-07 09:14:23 +04:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2007-08-27 06:31:51 +04:00
return dns_domain_from_principal ( mem_ctx , smb_krb5_context ,
2007-04-07 09:14:23 +04:00
name , info1 ) ;
2005-09-02 07:19:27 +04:00
}
2005-10-13 08:24:49 +04:00
2005-09-02 07:19:27 +04:00
domain_filter = NULL ;
2009-07-06 01:15:34 +04:00
2006-11-07 09:59:56 +03:00
ret = krb5_unparse_name_flags ( smb_krb5_context - > krb5_context , principal ,
KRB5_PRINCIPAL_UNPARSE_NO_REALM , & unparsed_name_short ) ;
2005-09-02 07:19:27 +04:00
if ( ret ) {
2005-12-19 10:07:11 +03:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2005-09-02 07:19:27 +04:00
return WERR_NOMEM ;
}
2005-12-19 14:50:28 +03:00
2005-12-19 10:07:11 +03:00
service = principal - > name . name_string . val [ 0 ] ;
if ( ( principal - > name . name_string . len = = 2 ) & & ( strcasecmp ( service , " host " ) = = 0 ) ) {
2005-12-19 14:50:28 +03:00
/* the 'cn' attribute is just the leading part of the name */
char * computer_name ;
computer_name = talloc_strndup ( mem_ctx , principal - > name . name_string . val [ 1 ] ,
strcspn ( principal - > name . name_string . val [ 1 ] , " . " ) ) ;
if ( computer_name = = NULL ) {
return WERR_NOMEM ;
}
2005-12-19 10:07:11 +03:00
result_filter = talloc_asprintf ( mem_ctx , " (|(&(servicePrincipalName=%s)(objectClass=user))(&(cn=%s)(objectClass=computer))) " ,
ldb_binary_encode_string ( mem_ctx , unparsed_name_short ) ,
2005-12-19 14:50:28 +03:00
ldb_binary_encode_string ( mem_ctx , computer_name ) ) ;
2005-12-19 10:07:11 +03:00
} else {
result_filter = talloc_asprintf ( mem_ctx , " (&(servicePrincipalName=%s)(objectClass=user)) " ,
ldb_binary_encode_string ( mem_ctx , unparsed_name_short ) ) ;
}
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2005-09-02 07:19:27 +04:00
free ( unparsed_name_short ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( result_filter ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
break ;
}
default : {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
}
2005-10-13 08:24:49 +04:00
if ( format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY ) {
return DsCrackNameOneSyntactical ( mem_ctx , format_offered , format_desired ,
name_dn , name , info1 ) ;
}
2009-07-06 01:15:34 +04:00
2005-10-20 15:19:52 +04:00
return DsCrackNameOneFilter ( sam_ctx , mem_ctx ,
2005-09-02 07:19:27 +04:00
smb_krb5_context ,
format_flags , format_offered , format_desired ,
name_dn , name ,
domain_filter , result_filter ,
info1 ) ;
}
2005-12-19 10:07:11 +03:00
/* Subcase of CrackNames. It is possible to translate a LDAP-style DN
* ( FQDN_1779 ) into a canoical name without actually searching the
* database */
2005-10-13 08:24:49 +04:00
static WERROR DsCrackNameOneSyntactical ( TALLOC_CTX * mem_ctx ,
2010-09-20 20:41:00 +04:00
enum drsuapi_DsNameFormat format_offered ,
enum drsuapi_DsNameFormat format_desired ,
2006-11-22 03:59:34 +03:00
struct ldb_dn * name_dn , const char * name ,
2005-10-13 08:24:49 +04:00
struct drsuapi_DsNameInfo1 * info1 )
{
char * cracked ;
if ( format_offered ! = DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING ;
return WERR_OK ;
}
switch ( format_desired ) {
case DRSUAPI_DS_NAME_FORMAT_CANONICAL :
cracked = ldb_dn_canonical_string ( mem_ctx , name_dn ) ;
break ;
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX :
cracked = ldb_dn_canonical_ex_string ( mem_ctx , name_dn ) ;
break ;
default :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING ;
return WERR_OK ;
}
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
info1 - > result_name = cracked ;
if ( ! cracked ) {
return WERR_NOMEM ;
}
2009-07-06 01:15:34 +04:00
2005-10-13 08:24:49 +04:00
return WERR_OK ;
}
2005-12-19 10:07:11 +03:00
/* Given a filter for the domain, and one for the result, perform the
* ldb search . The format offered and desired flags change the
* behaviours , including what attributes to return .
*
* The smb_krb5_context is required because we use the krb5 libs for principal parsing
*/
2005-10-20 15:19:52 +04:00
static WERROR DsCrackNameOneFilter ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
2005-09-02 07:19:27 +04:00
struct smb_krb5_context * smb_krb5_context ,
2010-09-20 20:41:00 +04:00
uint32_t format_flags , enum drsuapi_DsNameFormat format_offered ,
enum drsuapi_DsNameFormat format_desired ,
2006-11-22 03:59:34 +03:00
struct ldb_dn * name_dn , const char * name ,
2005-09-02 07:19:27 +04:00
const char * domain_filter , const char * result_filter ,
struct drsuapi_DsNameInfo1 * info1 )
{
int ldb_ret ;
2007-11-15 03:12:10 +03:00
struct ldb_result * domain_res = NULL ;
2005-09-02 07:19:27 +04:00
const char * const * domain_attrs ;
const char * const * result_attrs ;
struct ldb_message * * result_res = NULL ;
2006-12-28 06:33:52 +03:00
struct ldb_message * result = NULL ;
int i ;
2007-02-22 05:08:40 +03:00
char * p ;
2007-11-15 03:12:10 +03:00
struct ldb_dn * partitions_basedn = samdb_partitions_dn ( sam_ctx , mem_ctx ) ;
2004-10-14 13:56:04 +04:00
2006-03-15 08:24:13 +03:00
const char * const _domain_attrs_1779 [ ] = { " ncName " , " dnsRoot " , NULL } ;
const char * const _result_attrs_null [ ] = { NULL } ;
const char * const _domain_attrs_canonical [ ] = { " ncName " , " dnsRoot " , NULL } ;
const char * const _result_attrs_canonical [ ] = { " canonicalName " , NULL } ;
const char * const _domain_attrs_nt4 [ ] = { " ncName " , " dnsRoot " , " nETBIOSName " , NULL } ;
2006-12-28 07:52:45 +03:00
const char * const _result_attrs_nt4 [ ] = { " sAMAccountName " , " objectSid " , " objectClass " , NULL } ;
2009-07-06 01:15:34 +04:00
2006-03-15 08:24:13 +03:00
const char * const _domain_attrs_guid [ ] = { " ncName " , " dnsRoot " , NULL } ;
const char * const _result_attrs_guid [ ] = { " objectGUID " , NULL } ;
2009-07-06 01:15:34 +04:00
2006-03-15 08:24:13 +03:00
const char * const _domain_attrs_display [ ] = { " ncName " , " dnsRoot " , NULL } ;
const char * const _result_attrs_display [ ] = { " displayName " , " samAccountName " , NULL } ;
2007-05-24 16:40:46 +04:00
const char * const _domain_attrs_none [ ] = { " ncName " , " dnsRoot " , NULL } ;
2007-04-07 09:14:23 +04:00
const char * const _result_attrs_none [ ] = { NULL } ;
2004-11-16 17:43:28 +03:00
/* here we need to set the attrs lists for domain and result lookups */
2004-11-16 13:56:51 +03:00
switch ( format_desired ) {
2005-10-13 08:24:49 +04:00
case DRSUAPI_DS_NAME_FORMAT_FQDN_1779 :
2006-03-15 08:24:13 +03:00
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX :
domain_attrs = _domain_attrs_1779 ;
result_attrs = _result_attrs_null ;
2005-10-13 08:24:49 +04:00
break ;
2006-03-15 08:24:13 +03:00
case DRSUAPI_DS_NAME_FORMAT_CANONICAL :
domain_attrs = _domain_attrs_canonical ;
result_attrs = _result_attrs_canonical ;
2005-10-20 05:48:11 +04:00
break ;
2006-03-15 08:24:13 +03:00
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT :
domain_attrs = _domain_attrs_nt4 ;
result_attrs = _result_attrs_nt4 ;
2005-10-13 08:24:49 +04:00
break ;
2006-03-15 08:24:13 +03:00
case DRSUAPI_DS_NAME_FORMAT_GUID :
domain_attrs = _domain_attrs_guid ;
result_attrs = _result_attrs_guid ;
2005-10-13 08:24:49 +04:00
break ;
2006-03-15 08:24:13 +03:00
case DRSUAPI_DS_NAME_FORMAT_DISPLAY :
domain_attrs = _domain_attrs_display ;
result_attrs = _result_attrs_display ;
2005-10-13 08:24:49 +04:00
break ;
default :
2007-04-07 09:14:23 +04:00
domain_attrs = _domain_attrs_none ;
result_attrs = _result_attrs_none ;
break ;
2004-11-16 13:56:51 +03:00
}
2005-09-02 07:19:27 +04:00
if ( domain_filter ) {
/* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */
2008-09-23 22:30:06 +04:00
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res ,
2007-11-15 03:12:10 +03:00
partitions_basedn ,
LDB_SCOPE_ONELEVEL ,
domain_attrs ,
" %s " , domain_filter ) ;
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
if ( ldb_ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameOneFilter domain ref search failed: %s " , ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
switch ( domain_res - > count ) {
2007-02-22 05:08:40 +03:00
case 1 :
break ;
case 0 :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
default :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
}
2005-09-02 07:19:27 +04:00
2007-11-15 03:12:10 +03:00
info1 - > dns_domain_name = samdb_result_string ( domain_res - > msgs [ 0 ] , " dnsRoot " , NULL ) ;
2007-02-22 05:08:40 +03:00
W_ERROR_HAVE_NO_MEMORY ( info1 - > dns_domain_name ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY ;
} else {
info1 - > dns_domain_name = NULL ;
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
2004-11-16 13:56:51 +03:00
}
if ( result_filter ) {
2007-11-15 03:12:10 +03:00
int ret ;
struct ldb_result * res ;
2010-02-16 08:09:07 +03:00
uint32_t dsdb_flags = 0 ;
struct ldb_dn * search_dn ;
2009-07-06 01:15:34 +04:00
2010-02-16 08:09:07 +03:00
if ( domain_res ) {
dsdb_flags = 0 ;
search_dn = samdb_result_dn ( sam_ctx , mem_ctx , domain_res - > msgs [ 0 ] , " ncName " , NULL ) ;
2007-02-22 05:08:40 +03:00
} else {
2010-02-16 08:09:07 +03:00
dsdb_flags = DSDB_SEARCH_SEARCH_ALL_PARTITIONS ;
2010-04-13 10:41:10 +04:00
search_dn = ldb_get_root_basedn ( sam_ctx ) ;
2010-02-16 08:09:07 +03:00
}
2007-02-22 05:08:40 +03:00
2010-02-16 08:09:07 +03:00
/* search with the 'phantom root' flag */
ret = dsdb_search ( sam_ctx , mem_ctx , & res ,
search_dn ,
LDB_SCOPE_SUBTREE ,
result_attrs ,
DSDB_SEARCH_SEARCH_ALL_PARTITIONS ,
" %s " , result_filter ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameOneFilter phantom root search failed: %s " ,
ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
2007-02-22 05:08:40 +03:00
}
2010-02-16 08:09:07 +03:00
ldb_ret = res - > count ;
result_res = res - > msgs ;
2005-09-02 07:19:27 +04:00
} else if ( format_offered = = DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ) {
2005-10-20 15:19:52 +04:00
ldb_ret = gendb_search_dn ( sam_ctx , mem_ctx , name_dn , & result_res ,
2005-09-02 07:19:27 +04:00
result_attrs ) ;
2007-02-22 05:08:40 +03:00
} else if ( domain_res ) {
2007-11-15 03:12:10 +03:00
name_dn = samdb_result_dn ( sam_ctx , mem_ctx , domain_res - > msgs [ 0 ] , " ncName " , NULL ) ;
2005-10-20 15:19:52 +04:00
ldb_ret = gendb_search_dn ( sam_ctx , mem_ctx , name_dn , & result_res ,
2005-09-02 07:19:27 +04:00
result_attrs ) ;
2007-02-22 05:08:40 +03:00
} else {
/* Can't happen */
2010-06-01 11:33:53 +04:00
DEBUG ( 0 , ( " LOGIC ERROR: DsCrackNameOneFilter domain ref search not available: This can't happen... " ) ) ;
2007-02-22 05:08:40 +03:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
2005-09-02 07:19:27 +04:00
}
2004-11-16 17:43:28 +03:00
2005-09-02 07:19:27 +04:00
switch ( ldb_ret ) {
case 1 :
2006-12-28 06:33:52 +03:00
result = result_res [ 0 ] ;
2005-09-02 07:19:27 +04:00
break ;
case 0 :
switch ( format_offered ) {
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL :
2005-10-20 15:19:52 +04:00
return DsCrackNameSPNAlias ( sam_ctx , mem_ctx ,
2005-09-02 07:19:27 +04:00
smb_krb5_context ,
format_flags , format_offered , format_desired ,
2005-09-02 07:27:13 +04:00
name , info1 ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL :
2005-10-20 15:19:52 +04:00
return DsCrackNameUPN ( sam_ctx , mem_ctx , smb_krb5_context ,
2005-09-02 07:19:27 +04:00
format_flags , format_offered , format_desired ,
name , info1 ) ;
2010-09-20 20:41:00 +04:00
default :
break ;
2004-11-16 13:56:51 +03:00
}
2005-10-13 08:24:49 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
2005-09-02 07:19:27 +04:00
case - 1 :
2006-12-28 06:33:52 +03:00
DEBUG ( 2 , ( " DsCrackNameOneFilter result search failed: %s " , ldb_errstring ( sam_ctx ) ) ) ;
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
default :
2006-12-28 06:33:52 +03:00
switch ( format_offered ) {
case DRSUAPI_DS_NAME_FORMAT_CANONICAL :
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX :
{
2007-04-07 07:04:33 +04:00
const char * canonical_name = NULL ; /* Not required, but we get warnings... */
2006-12-28 06:33:52 +03:00
/* We may need to manually filter further */
for ( i = 0 ; i < ldb_ret ; i + + ) {
switch ( format_offered ) {
case DRSUAPI_DS_NAME_FORMAT_CANONICAL :
canonical_name = ldb_dn_canonical_string ( mem_ctx , result_res [ i ] - > dn ) ;
break ;
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX :
canonical_name = ldb_dn_canonical_ex_string ( mem_ctx , result_res [ i ] - > dn ) ;
break ;
2010-09-20 20:41:00 +04:00
default :
break ;
2006-12-28 06:33:52 +03:00
}
if ( strcasecmp_m ( canonical_name , name ) = = 0 ) {
result = result_res [ i ] ;
break ;
}
}
if ( ! result ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
}
}
default :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
}
2004-11-16 13:56:51 +03:00
}
2007-02-22 05:08:40 +03:00
info1 - > dns_domain_name = ldb_dn_canonical_string ( mem_ctx , result - > dn ) ;
W_ERROR_HAVE_NO_MEMORY ( info1 - > dns_domain_name ) ;
p = strchr ( info1 - > dns_domain_name , ' / ' ) ;
if ( p ) {
p [ 0 ] = ' \0 ' ;
}
2009-07-06 01:15:34 +04:00
2006-12-28 06:33:52 +03:00
/* here we can use result and domain_res[0] */
2004-11-16 13:56:51 +03:00
switch ( format_desired ) {
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_FQDN_1779 : {
2006-12-28 06:33:52 +03:00
info1 - > result_name = ldb_dn_alloc_linearized ( mem_ctx , result - > dn ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( info1 - > result_name ) ;
2004-11-16 17:43:28 +03:00
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
return WERR_OK ;
}
2005-10-20 05:48:11 +04:00
case DRSUAPI_DS_NAME_FORMAT_CANONICAL : {
2006-12-28 06:33:52 +03:00
info1 - > result_name = samdb_result_string ( result , " canonicalName " , NULL ) ;
2005-10-20 05:48:11 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
return WERR_OK ;
}
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX : {
/* Not in the virtual ldb attribute */
2005-10-13 08:24:49 +04:00
return DsCrackNameOneSyntactical ( mem_ctx ,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX ,
2006-12-28 06:33:52 +03:00
result - > dn , name , info1 ) ;
2005-10-20 05:48:11 +04:00
}
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT : {
2006-12-28 07:52:45 +03:00
2006-12-28 06:33:52 +03:00
const struct dom_sid * sid = samdb_result_dom_sid ( mem_ctx , result , " objectSid " ) ;
2005-09-03 04:52:34 +04:00
const char * _acc = " " , * _dom = " " ;
2009-07-06 01:15:34 +04:00
2006-12-28 07:52:45 +03:00
if ( samdb_find_attribute ( sam_ctx , result , " objectClass " , " domain " ) ) {
2007-11-15 03:12:10 +03:00
2008-09-23 22:30:06 +04:00
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res ,
2007-11-15 03:12:10 +03:00
partitions_basedn ,
LDB_SCOPE_ONELEVEL ,
domain_attrs ,
" (ncName=%s) " , ldb_dn_get_linearized ( result - > dn ) ) ;
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
if ( ldb_ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameOneFilter domain ref search failed: %s " , ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
switch ( domain_res - > count ) {
case 1 :
break ;
case 0 :
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
2007-11-15 03:12:10 +03:00
default :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
2005-09-02 07:19:27 +04:00
}
2007-11-15 03:12:10 +03:00
_dom = samdb_result_string ( domain_res - > msgs [ 0 ] , " nETBIOSName " , NULL ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( _dom ) ;
2006-12-28 07:52:45 +03:00
} else {
_acc = samdb_result_string ( result , " sAMAccountName " , NULL ) ;
if ( ! _acc ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING ;
2005-09-02 07:19:27 +04:00
return WERR_OK ;
}
2006-12-28 07:52:45 +03:00
if ( dom_sid_in_domain ( dom_sid_parse_talloc ( mem_ctx , SID_BUILTIN ) , sid ) ) {
_dom = " BUILTIN " ;
} else {
const char * attrs [ ] = { NULL } ;
2007-11-15 03:12:10 +03:00
struct ldb_result * domain_res2 ;
2006-12-28 07:52:45 +03:00
struct dom_sid * dom_sid = dom_sid_dup ( mem_ctx , sid ) ;
if ( ! dom_sid ) {
return WERR_OK ;
}
dom_sid - > num_auths - - ;
2008-09-23 22:30:06 +04:00
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res ,
2007-11-15 03:12:10 +03:00
NULL ,
LDB_SCOPE_BASE ,
attrs ,
" (&(objectSid=%s)(objectClass=domain)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , dom_sid ) ) ;
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
if ( ldb_ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameOneFilter domain search failed: %s " , ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
2006-12-28 07:52:45 +03:00
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
switch ( domain_res - > count ) {
case 1 :
break ;
case 0 :
2006-12-28 07:52:45 +03:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
2007-11-15 03:12:10 +03:00
default :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
2006-12-28 07:52:45 +03:00
}
2007-11-15 03:12:10 +03:00
2008-09-23 22:30:06 +04:00
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res2 ,
2007-11-15 03:12:10 +03:00
partitions_basedn ,
LDB_SCOPE_ONELEVEL ,
domain_attrs ,
" (ncName=%s) " , ldb_dn_get_linearized ( domain_res - > msgs [ 0 ] - > dn ) ) ;
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
if ( ldb_ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameOneFilter domain ref search failed: %s " , ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2007-11-15 03:12:10 +03:00
switch ( domain_res2 - > count ) {
case 1 :
break ;
case 0 :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
default :
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
}
_dom = samdb_result_string ( domain_res2 - > msgs [ 0 ] , " nETBIOSName " , NULL ) ;
2006-12-28 07:52:45 +03:00
W_ERROR_HAVE_NO_MEMORY ( _dom ) ;
2005-09-02 07:19:27 +04:00
}
2004-11-16 13:56:51 +03:00
}
2005-07-12 15:45:29 +04:00
2005-09-02 07:19:27 +04:00
info1 - > result_name = talloc_asprintf ( mem_ctx , " %s \\ %s " , _dom , _acc ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( info1 - > result_name ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
return WERR_OK ;
2004-11-16 13:56:51 +03:00
}
2005-09-02 07:19:27 +04:00
case DRSUAPI_DS_NAME_FORMAT_GUID : {
struct GUID guid ;
2009-07-06 01:15:34 +04:00
2006-12-28 06:33:52 +03:00
guid = samdb_result_guid ( result , " objectGUID " ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
info1 - > result_name = GUID_string2 ( mem_ctx , & guid ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( info1 - > result_name ) ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
return WERR_OK ;
}
2005-10-13 08:24:49 +04:00
case DRSUAPI_DS_NAME_FORMAT_DISPLAY : {
2006-12-28 06:33:52 +03:00
info1 - > result_name = samdb_result_string ( result , " displayName " , NULL ) ;
2005-10-13 08:24:49 +04:00
if ( ! info1 - > result_name ) {
2006-12-28 06:33:52 +03:00
info1 - > result_name = samdb_result_string ( result , " sAMAccountName " , NULL ) ;
2005-10-13 08:24:49 +04:00
}
if ( ! info1 - > result_name ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
} else {
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
}
return WERR_OK ;
}
2007-04-07 09:14:23 +04:00
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL : {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
}
case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN :
case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY : {
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2005-09-02 07:19:27 +04:00
default :
2006-12-29 01:51:56 +03:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING ;
2005-09-02 07:19:27 +04:00
return WERR_OK ;
}
2004-10-14 13:56:04 +04:00
}
2005-12-19 10:07:11 +03:00
/* Given a user Principal Name (such as foo@bar.com),
* return the user and domain DNs . This is used in the KDC to then
* return the Keys and evaluate policy */
2005-10-21 05:25:55 +04:00
NTSTATUS crack_user_principal_name ( struct ldb_context * sam_ctx ,
TALLOC_CTX * mem_ctx ,
const char * user_principal_name ,
struct ldb_dn * * user_dn ,
struct ldb_dn * * domain_dn )
{
WERROR werr ;
struct drsuapi_DsNameInfo1 info1 ;
werr = DsCrackNameOneName ( sam_ctx , mem_ctx , 0 ,
DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL ,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
user_principal_name ,
& info1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2005-10-24 02:20:42 +04:00
return werror_to_ntstatus ( werr ) ;
2005-10-21 05:25:55 +04:00
}
switch ( info1 . status ) {
case DRSUAPI_DS_NAME_STATUS_OK :
break ;
case DRSUAPI_DS_NAME_STATUS_NOT_FOUND :
2005-10-28 02:27:51 +04:00
case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY :
case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE :
return NT_STATUS_NO_SUCH_USER ;
case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR :
default :
return NT_STATUS_UNSUCCESSFUL ;
}
2009-07-06 01:15:34 +04:00
2006-11-22 03:59:34 +03:00
* user_dn = ldb_dn_new ( mem_ctx , sam_ctx , info1 . result_name ) ;
2009-07-06 01:15:34 +04:00
2005-10-28 02:27:51 +04:00
if ( domain_dn ) {
werr = DsCrackNameOneName ( sam_ctx , mem_ctx , 0 ,
DRSUAPI_DS_NAME_FORMAT_CANONICAL ,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
talloc_asprintf ( mem_ctx , " %s/ " ,
info1 . dns_domain_name ) ,
& info1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werror_to_ntstatus ( werr ) ;
}
switch ( info1 . status ) {
case DRSUAPI_DS_NAME_STATUS_OK :
break ;
case DRSUAPI_DS_NAME_STATUS_NOT_FOUND :
case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY :
case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE :
return NT_STATUS_NO_SUCH_USER ;
case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR :
default :
return NT_STATUS_UNSUCCESSFUL ;
}
2009-07-06 01:15:34 +04:00
2006-11-22 03:59:34 +03:00
* domain_dn = ldb_dn_new ( mem_ctx , sam_ctx , info1 . result_name ) ;
2005-10-28 02:27:51 +04:00
}
return NT_STATUS_OK ;
}
2005-12-19 10:07:11 +03:00
/* Given a Service Principal Name (such as host/foo.bar.com@BAR.COM),
* return the user and domain DNs . This is used in the KDC to then
* return the Keys and evaluate policy */
2005-10-28 02:27:51 +04:00
NTSTATUS crack_service_principal_name ( struct ldb_context * sam_ctx ,
TALLOC_CTX * mem_ctx ,
const char * service_principal_name ,
struct ldb_dn * * user_dn ,
struct ldb_dn * * domain_dn )
{
WERROR werr ;
struct drsuapi_DsNameInfo1 info1 ;
werr = DsCrackNameOneName ( sam_ctx , mem_ctx , 0 ,
DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL ,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
service_principal_name ,
& info1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werror_to_ntstatus ( werr ) ;
}
switch ( info1 . status ) {
case DRSUAPI_DS_NAME_STATUS_OK :
break ;
case DRSUAPI_DS_NAME_STATUS_NOT_FOUND :
2005-10-21 05:25:55 +04:00
case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY :
case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE :
return NT_STATUS_NO_SUCH_USER ;
case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR :
default :
return NT_STATUS_UNSUCCESSFUL ;
}
2009-07-06 01:15:34 +04:00
2006-11-22 03:59:34 +03:00
* user_dn = ldb_dn_new ( mem_ctx , sam_ctx , info1 . result_name ) ;
2009-07-06 01:15:34 +04:00
2005-10-21 05:25:55 +04:00
if ( domain_dn ) {
werr = DsCrackNameOneName ( sam_ctx , mem_ctx , 0 ,
DRSUAPI_DS_NAME_FORMAT_CANONICAL ,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
talloc_asprintf ( mem_ctx , " %s/ " ,
info1 . dns_domain_name ) ,
& info1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2005-10-24 02:20:42 +04:00
return werror_to_ntstatus ( werr ) ;
2005-10-21 05:25:55 +04:00
}
switch ( info1 . status ) {
case DRSUAPI_DS_NAME_STATUS_OK :
break ;
case DRSUAPI_DS_NAME_STATUS_NOT_FOUND :
case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY :
case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE :
return NT_STATUS_NO_SUCH_USER ;
case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR :
default :
return NT_STATUS_UNSUCCESSFUL ;
}
2009-07-06 01:15:34 +04:00
2006-11-22 03:59:34 +03:00
* domain_dn = ldb_dn_new ( mem_ctx , sam_ctx , info1 . result_name ) ;
2005-10-21 05:25:55 +04:00
}
return NT_STATUS_OK ;
}
2005-12-19 09:56:45 +03:00
2007-01-19 18:14:45 +03:00
NTSTATUS crack_name_to_nt4_name ( TALLOC_CTX * mem_ctx ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev_ctx ,
2007-12-02 23:14:16 +03:00
struct loadparm_context * lp_ctx ,
2010-09-20 20:41:00 +04:00
enum drsuapi_DsNameFormat format_offered ,
2007-01-19 18:14:45 +03:00
const char * name ,
const char * * nt4_domain , const char * * nt4_account )
2005-12-19 09:56:45 +03:00
{
WERROR werr ;
struct drsuapi_DsNameInfo1 info1 ;
struct ldb_context * ldb ;
char * p ;
2005-12-20 02:29:47 +03:00
/* Handle anonymous bind */
2007-01-19 18:14:45 +03:00
if ( ! name | | ! * name ) {
2005-12-20 02:29:47 +03:00
* nt4_domain = " " ;
* nt4_account = " " ;
2005-12-20 02:43:17 +03:00
return NT_STATUS_OK ;
2005-12-20 02:29:47 +03:00
}
2009-10-23 07:19:28 +04:00
ldb = samdb_connect ( mem_ctx , ev_ctx , lp_ctx , system_session ( lp_ctx ) ) ;
2005-12-19 09:56:45 +03:00
if ( ldb = = NULL ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
werr = DsCrackNameOneName ( ldb , mem_ctx , 0 ,
2007-01-19 18:14:45 +03:00
format_offered ,
2005-12-19 09:56:45 +03:00
DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT ,
2007-01-19 18:14:45 +03:00
name ,
2005-12-19 09:56:45 +03:00
& info1 ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werror_to_ntstatus ( werr ) ;
}
switch ( info1 . status ) {
case DRSUAPI_DS_NAME_STATUS_OK :
break ;
case DRSUAPI_DS_NAME_STATUS_NOT_FOUND :
case DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY :
case DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE :
return NT_STATUS_NO_SUCH_USER ;
case DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR :
default :
return NT_STATUS_UNSUCCESSFUL ;
}
2009-07-06 01:15:34 +04:00
2005-12-19 09:56:45 +03:00
* nt4_domain = talloc_strdup ( mem_ctx , info1 . result_name ) ;
2009-08-13 11:50:19 +04:00
if ( * nt4_domain = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2009-07-06 01:15:34 +04:00
2005-12-19 09:56:45 +03:00
p = strchr ( * nt4_domain , ' \\ ' ) ;
if ( ! p ) {
return NT_STATUS_INVALID_PARAMETER ;
}
p [ 0 ] = ' \0 ' ;
2009-07-06 01:15:34 +04:00
2009-09-26 04:37:21 +04:00
* nt4_account = talloc_strdup ( mem_ctx , & p [ 1 ] ) ;
if ( * nt4_account = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2005-12-19 09:56:45 +03:00
}
return NT_STATUS_OK ;
2007-01-19 18:14:45 +03:00
}
NTSTATUS crack_auto_name_to_nt4_name ( TALLOC_CTX * mem_ctx ,
2008-12-29 22:24:57 +03:00
struct tevent_context * ev_ctx ,
2007-12-02 23:14:16 +03:00
struct loadparm_context * lp_ctx ,
2007-01-19 18:14:45 +03:00
const char * name ,
const char * * nt4_domain ,
const char * * nt4_account )
{
2010-09-20 20:41:00 +04:00
enum drsuapi_DsNameFormat format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN ;
2007-01-19 18:14:45 +03:00
/* Handle anonymous bind */
if ( ! name | | ! * name ) {
* nt4_domain = " " ;
* nt4_account = " " ;
return NT_STATUS_OK ;
}
if ( strchr_m ( name , ' = ' ) ) {
format_offered = DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ;
} else if ( strchr_m ( name , ' @ ' ) ) {
format_offered = DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL ;
} else if ( strchr_m ( name , ' \\ ' ) ) {
format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT ;
} else if ( strchr_m ( name , ' / ' ) ) {
format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL ;
2008-10-01 01:24:58 +04:00
} else {
return NT_STATUS_NO_SUCH_USER ;
2007-01-19 18:14:45 +03:00
}
2008-04-17 14:23:44 +04:00
return crack_name_to_nt4_name ( mem_ctx , ev_ctx , lp_ctx , format_offered , name , nt4_domain , nt4_account ) ;
2005-12-19 09:56:45 +03:00
}
2010-09-20 20:46:10 +04:00
WERROR dcesrv_drsuapi_ListRoles ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
const struct drsuapi_DsNameRequest1 * req1 ,
struct drsuapi_DsNameCtr1 * * ctr1 )
{
struct drsuapi_DsNameInfo1 * names ;
uint32_t i ;
uint32_t count = 5 ; /*number of fsmo role owners we are going to return*/
* ctr1 = talloc ( mem_ctx , struct drsuapi_DsNameCtr1 ) ;
W_ERROR_HAVE_NO_MEMORY ( * ctr1 ) ;
names = talloc_array ( mem_ctx , struct drsuapi_DsNameInfo1 , count ) ;
W_ERROR_HAVE_NO_MEMORY ( names ) ;
for ( i = 0 ; i < count ; i + + ) {
WERROR werr ;
struct ldb_dn * role_owner_dn , * fsmo_role_dn , * server_dn ;
werr = dsdb_get_fsmo_role_info ( mem_ctx , sam_ctx , i ,
& fsmo_role_dn , & role_owner_dn ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
}
server_dn = ldb_dn_copy ( mem_ctx , role_owner_dn ) ;
ldb_dn_remove_child_components ( server_dn , 1 ) ;
names [ i ] . status = DRSUAPI_DS_NAME_STATUS_OK ;
names [ i ] . dns_domain_name = samdb_dn_to_dnshostname ( sam_ctx , mem_ctx ,
server_dn ) ;
if ( ! names [ i ] . dns_domain_name ) {
DEBUG ( 4 , ( " list_roles: Failed to find dNSHostName for server %s " ,
ldb_dn_get_linearized ( server_dn ) ) ) ;
}
names [ i ] . result_name = talloc_strdup ( mem_ctx , ldb_dn_get_linearized ( role_owner_dn ) ) ;
}
( * ctr1 ) - > count = count ;
( * ctr1 ) - > array = names ;
return WERR_OK ;
}
WERROR dcesrv_drsuapi_CrackNamesByNameFormat ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
const struct drsuapi_DsNameRequest1 * req1 ,
struct drsuapi_DsNameCtr1 * * ctr1 )
{
struct drsuapi_DsNameInfo1 * names ;
uint32_t i , count ;
WERROR status ;
* ctr1 = talloc ( mem_ctx , struct drsuapi_DsNameCtr1 ) ;
W_ERROR_HAVE_NO_MEMORY ( * ctr1 ) ;
count = req1 - > count ;
names = talloc_array ( mem_ctx , struct drsuapi_DsNameInfo1 , count ) ;
W_ERROR_HAVE_NO_MEMORY ( names ) ;
for ( i = 0 ; i < count ; i + + ) {
status = DsCrackNameOneName ( sam_ctx , mem_ctx ,
req1 - > format_flags ,
req1 - > format_offered ,
req1 - > format_desired ,
req1 - > names [ i ] . str ,
& names [ i ] ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return status ;
}
}
( * ctr1 ) - > count = count ;
( * ctr1 ) - > array = names ;
return WERR_OK ;
}