2024-01-11 05:05:07 +03:00
/*
2004-10-14 13:56:04 +04:00
Unix SMB / CIFS implementation .
2012-05-17 10:52:30 +04:00
crachnames implementation for the drsuapi pipe
2004-10-14 13:56:04 +04:00
DsCrackNames ( )
Copyright ( C ) Stefan Metzmacher 2004
2005-09-02 07:19:27 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2005
2012-05-17 10:52:30 +04:00
Copyright ( C ) Matthieu Patou < mat @ matws . net > 2012
2017-07-05 02:15:04 +03:00
Copyright ( C ) Catalyst . Net Ltd 2017
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"
2011-02-10 06:12:51 +03:00
# include <ldb.h>
# include <ldb_errors.h>
2005-09-02 07:19:27 +04:00
# 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"
2010-10-17 16:27:18 +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
2020-08-07 23:27:39 +03:00
# undef strcasecmp
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 ,
2024-01-11 05:05:07 +03:00
struct ldb_dn * name_dn , const char * name ,
const char * domain_filter , const char * result_filter ,
2012-05-17 10:52:30 +04:00
struct drsuapi_DsNameInfo1 * info1 , int scope , struct ldb_dn * search_dn ) ;
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 ,
2024-01-11 05:05:07 +03:00
struct ldb_dn * name_dn , const char * name ,
2005-10-13 08:24:49 +04:00
struct drsuapi_DsNameInfo1 * info1 ) ;
2024-01-11 05:05:07 +03:00
static WERROR dns_domain_from_principal ( TALLOC_CTX * mem_ctx , struct smb_krb5_context * smb_krb5_context ,
const char * name ,
struct drsuapi_DsNameInfo1 * info1 )
2007-04-07 07:04:33 +04:00
{
krb5_error_code ret ;
krb5_principal principal ;
/* perhaps it's a principal with a realm, so return the right 'domain only' response */
2024-01-11 05:05:07 +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 ) ;
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
2018-11-20 19:45:11 +03:00
info1 - > dns_domain_name = smb_krb5_principal_get_realm (
mem_ctx , smb_krb5_context - > krb5_context , principal ) ;
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 ;
2021-08-11 02:02:36 +03:00
}
2007-04-07 07:04:33 +04:00
2021-08-11 02:02:36 +03:00
static enum drsuapi_DsNameStatus LDB_lookup_spn_alias ( 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
{
2021-08-12 12:53:16 +03:00
/*
* Some of the logic of this function is mirrored in find_spn_alias ( )
2024-01-11 05:05:22 +03:00
* in source4 / dsdb / samdb / ldb_modules / samldb . c . If you change this to
2021-08-12 12:53:16 +03:00
* not return the first matched alias , you will need to rethink that
* function too .
*/
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 [ ] = {
2024-01-11 05:05:07 +03:00
" sPNMappings " ,
2006-02-01 01:41:53 +03:00
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 ) ) ) {
2021-08-11 07:56:07 +03:00
talloc_free ( tmp_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 ) {
2021-08-11 07:56:07 +03:00
talloc_free ( tmp_ctx ) ;
2006-11-22 03:59:34 +03:00
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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 1 , ( " ldb_search: dn: %s not found: %s \n " , service_dn_str , ldb_errstring ( ldb_ctx ) ) ) ;
2021-08-11 07:56:07 +03:00
talloc_free ( tmp_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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 1 , ( " ldb_search: dn: %s not found \n " , service_dn_str ) ) ;
2021-08-11 07:56:07 +03:00
talloc_free ( tmp_ctx ) ;
2007-11-27 04:47:57 +03:00
return DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
} else if ( res - > count ! = 1 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 1 , ( " ldb_search: dn: %s not found \n " , service_dn_str ) ) ;
2021-08-11 07:56:07 +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-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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 1 , ( " ldb_search: dn: %s no sPNMappings attribute \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 ;
}
for ( i = 0 ; i < spnmappings - > num_values ; i + + ) {
char * mapping , * p , * str ;
2024-01-11 05:05:07 +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 ) {
2024-01-11 05:05:07 +03: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 ;
2023-09-05 07:38:23 +03:00
krb5_data component ;
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 */
2024-01-11 05:05:07 +03:00
ret = krb5_parse_name_flags ( smb_krb5_context - > krb5_context ,
2006-11-07 09:59:56 +03:00
name , KRB5_PRINCIPAL_PARSE_NO_REALM , & principal ) ;
2005-09-02 07:19:27 +04:00
if ( ret ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 2 , ( " Could not parse principal: %s: %s \n " ,
2024-01-11 05:05:07 +03:00
name , smb_get_krb5_error_message ( smb_krb5_context - > krb5_context ,
2005-09-02 07:19:27 +04:00
ret , mem_ctx ) ) ) ;
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-09-02 07:19:27 +04:00
}
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
2023-09-05 07:38:23 +03:00
ret = smb_krb5_princ_component ( smb_krb5_context - > krb5_context ,
principal , 0 , & component ) ;
if ( ret ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
return WERR_OK ;
}
service = ( const char * ) component . data ;
ret = smb_krb5_princ_component ( smb_krb5_context - > krb5_context ,
principal , 1 , & component ) ;
if ( ret ) {
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
2010-12-02 13:49:56 +03:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2005-09-02 07:19:27 +04:00
return WERR_OK ;
}
2023-09-05 07:38:23 +03:00
dns_name = ( const char * ) component . data ;
2009-07-06 01:15:34 +04:00
2005-09-02 07:19:27 +04:00
/* MAP it */
2021-08-11 02:02:36 +03:00
namestatus = LDB_lookup_spn_alias ( 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 ) {
2010-12-02 13:49:56 +03:00
wret = WERR_OK ;
2007-04-07 09:14:23 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY ;
info1 - > dns_domain_name = talloc_strdup ( mem_ctx , dns_name ) ;
if ( ! info1 - > dns_domain_name ) {
2015-12-03 17:24:18 +03:00
wret = WERR_NOT_ENOUGH_MEMORY ;
2007-04-07 09:14:23 +04:00
}
2010-12-02 13:49:56 +03:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
return wret ;
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-10-13 08:24:49 +04:00
/* reform principal */
2012-04-22 00:55:35 +04:00
new_princ = talloc_asprintf ( mem_ctx , " %s/%s " , new_service , dns_name ) ;
if ( ! new_princ ) {
2007-04-07 09:14:23 +04:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-09-02 07:19:27 +04:00
}
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 ) ;
2012-04-22 00:55:35 +04:00
talloc_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 ) {
2015-12-03 17:24:18 +03:00
wret = WERR_NOT_ENOUGH_MEMORY ;
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 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 ;
2014-05-15 11:46:21 +04:00
char * realm ;
2023-05-09 07:10:59 +03:00
char * realm_encoded = NULL ;
2005-09-02 07:19:27 +04:00
char * unparsed_name_short ;
2023-05-09 07:10:59 +03:00
const char * unparsed_name_short_encoded = NULL ;
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 ;
}
2024-01-11 05:05:07 +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
2018-11-20 19:45:11 +03:00
realm = smb_krb5_principal_get_realm (
mem_ctx , smb_krb5_context - > krb5_context , principal ) ;
2023-05-09 07:12:03 +03:00
if ( realm = = NULL ) {
return WERR_NOT_ENOUGH_MEMORY ;
}
2007-11-15 03:12:10 +03:00
2023-05-09 07:10:59 +03:00
realm_encoded = ldb_binary_encode_string ( mem_ctx , realm ) ;
if ( realm_encoded = = NULL ) {
return WERR_NOT_ENOUGH_MEMORY ;
}
2008-09-23 22:30:06 +04:00
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res ,
2011-09-05 10:46:35 +04:00
samdb_partitions_dn ( sam_ctx , mem_ctx ) ,
LDB_SCOPE_ONELEVEL ,
domain_attrs ,
2022-12-16 02:41:03 +03:00
" (&(objectClass=crossRef)(|(dnsRoot=%s)(netbiosName=%s)) "
" (systemFlags: " LDB_OID_COMPARATOR_AND " :=%u)) " ,
2023-05-09 07:10:59 +03:00
realm_encoded ,
realm_encoded ,
2011-09-05 10:46:35 +04:00
SYSTEM_FLAG_CR_NTDS_DOMAIN ) ;
2023-05-09 07:10:59 +03:00
TALLOC_FREE ( realm_encoded ) ;
2018-11-20 19:45:11 +03:00
TALLOC_FREE ( realm ) ;
2007-11-15 03:12:10 +03:00
if ( ldb_ret ! = LDB_SUCCESS ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 2 , ( " DsCrackNameUPN domain ref search failed: %s \n " , ldb_errstring ( sam_ctx ) ) ) ;
2007-11-15 03:12:10 +03:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
2010-12-02 13:49:56 +03:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2007-11-15 03:12:10 +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 ) {
2007-04-07 07:04:33 +04:00
case 1 :
break ;
case 0 :
2010-12-02 13:49:56 +03:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2024-01-11 05:05:07 +03: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 ;
2010-12-02 13:49:56 +03:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2007-04-07 07:04:33 +04:00
return WERR_OK ;
}
2009-07-06 01:15:34 +04:00
2015-03-12 03:29:56 +03:00
/*
* The important thing here is that a samAccountName may have
* a space in it , and this must not be kerberos escaped to
* match this filter , so we specify
* KRB5_PRINCIPAL_UNPARSE_DISPLAY
*/
2024-01-11 05:05:07 +03:00
ret = krb5_unparse_name_flags ( smb_krb5_context - > krb5_context , principal ,
2015-03-12 03:29:56 +03:00
KRB5_PRINCIPAL_UNPARSE_NO_REALM |
KRB5_PRINCIPAL_UNPARSE_DISPLAY ,
& 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 ) ;
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-09-02 07:19:27 +04:00
}
2009-07-06 01:15:34 +04:00
2023-05-09 07:10:59 +03:00
unparsed_name_short_encoded = ldb_binary_encode_string ( mem_ctx , unparsed_name_short ) ;
if ( unparsed_name_short_encoded = = NULL ) {
free ( unparsed_name_short ) ;
return WERR_NOT_ENOUGH_MEMORY ;
}
2005-09-02 07:19:27 +04:00
/* This may need to be extended for more userPrincipalName variations */
2019-01-23 06:16:16 +03:00
result_filter = talloc_asprintf ( mem_ctx , " (&(samAccountName=%s)(objectClass=user)) " ,
2023-05-09 07:10:59 +03:00
unparsed_name_short_encoded ) ;
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 ) ;
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-09-02 07:19:27 +04:00
}
2024-01-11 05:05:07 +03:00
status = DsCrackNameOneFilter ( sam_ctx , mem_ctx ,
smb_krb5_context ,
format_flags , format_offered , format_desired ,
NULL , unparsed_name_short , domain_filter , result_filter ,
2012-05-17 10:52:30 +04:00
info1 , LDB_SCOPE_SUBTREE , NULL ) ;
2005-09-02 07:19:27 +04:00
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
2012-05-17 10:52:30 +04:00
/*
* This function will workout the filtering parameter in order to be able to do
2023-08-02 11:41:31 +03:00
* the adapted search when the incoming format is format_functional .
2012-05-17 10:52:30 +04:00
* This boils down to defining the search_dn ( passed as pointer to ldb_dn * ) and the
* ldap filter request .
* Main input parameters are :
* * name , which is the portion of the functional name after the
* first ' / ' .
* * domain_filter , which is a ldap search filter used to find the NC DN given the
* function name to crack .
*/
static WERROR get_format_functional_filtering_param ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
char * name , struct drsuapi_DsNameInfo1 * info1 ,
struct ldb_dn * * psearch_dn , const char * domain_filter , const char * * presult_filter )
{
struct ldb_result * domain_res = NULL ;
const char * const domain_attrs [ ] = { " ncName " , NULL } ;
struct ldb_dn * partitions_basedn = samdb_partitions_dn ( sam_ctx , mem_ctx ) ;
int ldb_ret ;
char * account , * s , * result_filter = NULL ;
struct ldb_dn * search_dn = NULL ;
* psearch_dn = NULL ;
* presult_filter = NULL ;
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res ,
partitions_basedn ,
LDB_SCOPE_ONELEVEL ,
domain_attrs ,
" %s " , domain_filter ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameOne domain ref search failed: %s \n " , ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_FOOBAR ;
}
if ( domain_res - > count = = 1 ) {
struct ldb_dn * tmp_dn = samdb_result_dn ( sam_ctx , mem_ctx , domain_res - > msgs [ 0 ] , " ncName " , NULL ) ;
const char * const name_attrs [ ] = { " name " , NULL } ;
account = name ;
s = strchr ( account , ' / ' ) ;
2012-12-24 22:01:30 +04:00
talloc_free ( domain_res ) ;
2012-05-17 10:52:30 +04:00
while ( s ) {
s [ 0 ] = ' \0 ' ;
s + + ;
ldb_ret = ldb_search ( sam_ctx , mem_ctx , & domain_res ,
tmp_dn ,
LDB_SCOPE_ONELEVEL ,
name_attrs ,
" name=%s " , account ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " DsCrackNameOne domain ref search failed: %s \n " , ldb_errstring ( sam_ctx ) ) ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2012-12-24 22:01:30 +04:00
talloc_free ( tmp_dn ) ;
2012-05-17 10:52:30 +04:00
switch ( domain_res - > count ) {
case 1 :
break ;
case 0 :
2012-12-24 22:01:30 +04:00
talloc_free ( domain_res ) ;
2012-05-17 10:52:30 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
default :
2012-12-24 22:01:30 +04:00
talloc_free ( domain_res ) ;
2012-05-17 10:52:30 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
}
tmp_dn = talloc_steal ( mem_ctx , domain_res - > msgs [ 0 ] - > dn ) ;
talloc_free ( domain_res ) ;
search_dn = tmp_dn ;
account = s ;
s = strchr ( 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 ) ;
}
* psearch_dn = search_dn ;
* presult_filter = result_filter ;
return WERR_OK ;
}
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 ;
2012-05-17 10:52:30 +04:00
struct ldb_dn * search_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 ;
2012-05-17 10:52:30 +04:00
int scope = LDB_SCOPE_SUBTREE ;
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 ) {
2015-12-03 17:24:26 +03:00
return WERR_INVALID_PARAMETER ;
2004-11-16 17:43:28 +03:00
}
/* TODO: - fill the correct names in all cases!
* - handle format_flags
*/
2013-07-01 07:44:22 +04:00
if ( format_desired = = DRSUAPI_DS_NAME_FORMAT_UNKNOWN ) {
return WERR_OK ;
}
2004-11-16 17:43:28 +03:00
/* 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 ;
}
2013-06-30 03:02:32 +04:00
if ( info1 - > status ! = DRSUAPI_DS_NAME_STATUS_NOT_FOUND & &
( formats [ i ] ! = DRSUAPI_DS_NAME_FORMAT_CANONICAL | |
info1 - > status ! = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ) )
{
2008-10-01 01:24:58 +04:00
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 ;
2023-05-09 07:10:59 +03:00
const char * str_encoded = NULL ;
2012-05-17 10:52:30 +04:00
scope = LDB_SCOPE_ONELEVEL ;
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 + + ;
2023-05-09 07:10:59 +03:00
str_encoded = ldb_binary_encode_string ( mem_ctx , str ) ;
if ( str_encoded = = NULL ) {
return WERR_NOT_ENOUGH_MEMORY ;
}
2011-09-07 11:18:24 +04:00
domain_filter = talloc_asprintf ( mem_ctx , " (&(objectClass=crossRef)(dnsRoot=%s)(systemFlags:%s:=%u)) " ,
2023-05-09 07:10:59 +03:00
str_encoded ,
2011-09-07 11:18:24 +04:00
LDB_OID_COMPARATOR_AND ,
SYSTEM_FLAG_CR_NTDS_DOMAIN ) ;
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) */
2012-05-17 10:52:30 +04:00
account = s ;
if ( account & & * account ) {
WERROR werr = get_format_functional_filtering_param ( sam_ctx ,
mem_ctx ,
account ,
info1 ,
& search_dn ,
domain_filter ,
& result_filter ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
2006-12-28 06:33:52 +03:00
}
2012-05-17 10:52:30 +04:00
if ( info1 - > status ! = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR )
return WERR_OK ;
2006-12-28 06:33:52 +03:00
}
2005-09-02 07:19:27 +04:00
break ;
}
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT : {
char * p ;
char * domain ;
2023-05-09 07:10:59 +03:00
char * domain_encoded = NULL ;
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
2023-05-09 07:10:59 +03:00
domain_encoded = ldb_binary_encode_string ( mem_ctx , domain ) ;
if ( domain_encoded = = NULL ) {
return WERR_NOT_ENOUGH_MEMORY ;
}
2024-01-11 05:05:07 +03:00
domain_filter = talloc_asprintf ( mem_ctx ,
2013-06-30 13:03:02 +04:00
" (&(objectClass=crossRef)(netbiosName=%s)(systemFlags:%s:=%u)) " ,
2023-05-09 07:10:59 +03:00
domain_encoded ,
2011-09-05 10:46:35 +04:00
LDB_OID_COMPARATOR_AND ,
SYSTEM_FLAG_CR_NTDS_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 ) {
2023-05-09 07:10:59 +03:00
const char * account_encoded = NULL ;
account_encoded = ldb_binary_encode_string ( mem_ctx , account ) ;
if ( account_encoded = = NULL ) {
return WERR_NOT_ENOUGH_MEMORY ;
}
2005-09-02 07:19:27 +04:00
result_filter = talloc_asprintf ( mem_ctx , " (sAMAccountName=%s) " ,
2023-05-09 07:10:59 +03:00
account_encoded ) ;
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 ) {
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
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 : {
2023-05-09 07:10:59 +03:00
const char * name_encoded = NULL ;
2005-10-13 08:24:49 +04:00
domain_filter = NULL ;
2023-05-09 07:10:59 +03:00
name_encoded = ldb_binary_encode_string ( mem_ctx , name ) ;
if ( name_encoded = = NULL ) {
return WERR_NOT_ENOUGH_MEMORY ;
}
2005-10-13 08:24:49 +04:00
result_filter = talloc_asprintf ( mem_ctx , " (|(displayName=%s)(samAccountName=%s)) " ,
2023-05-09 07:10:59 +03:00
name_encoded ,
name_encoded ) ;
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 ) {
2012-09-25 21:51:47 +04:00
info1 - > dns_domain_name = NULL ;
2005-09-02 07:19:27 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
2004-10-14 13:56:04 +04:00
}
2024-01-11 05:05:07 +03:00
ldap_sid = ldap_encode_ndr_dom_sid ( mem_ctx ,
2005-09-02 07:19:27 +04:00
sid ) ;
if ( ! ldap_sid ) {
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-09-02 07:19:27 +04:00
}
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 ;
2023-05-09 07:10:59 +03:00
const char * unparsed_name_encoded = NULL ;
2008-10-01 01:24:58 +04:00
2024-01-11 05:05:07 +03:00
ret = smb_krb5_init_context ( mem_ctx ,
( struct loadparm_context * ) ldb_get_opaque ( sam_ctx , " loadparm " ) ,
2008-10-01 01:24:58 +04:00
& smb_krb5_context ) ;
2009-07-06 01:15:34 +04:00
2008-10-01 01:24:58 +04:00
if ( ret ) {
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2008-10-01 01:24:58 +04:00
}
2017-02-26 15:06:05 +03:00
/* Ensure we reject complete 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
2015-03-12 02:50:23 +03:00
/*
* By getting the unparsed name here , we ensure the
* escaping is removed correctly ( and trust the client
* less ) . The important thing here is that a
* userPrincipalName may have a space in it , and this
* must not be kerberos escaped to match this filter ,
* so we specify KRB5_PRINCIPAL_UNPARSE_DISPLAY
*/
ret = krb5_unparse_name_flags ( smb_krb5_context - > krb5_context ,
principal ,
KRB5_PRINCIPAL_UNPARSE_DISPLAY ,
& unparsed_name ) ;
2005-09-02 07:19:27 +04:00
if ( ret ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-09-02 07:19:27 +04:00
}
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2009-06-30 04:19:19 +04:00
2023-06-22 05:31:12 +03:00
/* The ldb_binary_encode_string() here avoids LDAP filter injection attacks */
2023-05-09 07:10:59 +03:00
unparsed_name_encoded = ldb_binary_encode_string ( mem_ctx , unparsed_name ) ;
if ( unparsed_name_encoded = = NULL ) {
return WERR_NOT_ENOUGH_MEMORY ;
}
2019-01-23 06:16:16 +03:00
result_filter = talloc_asprintf ( mem_ctx , " (&(userPrincipalName=%s)(objectClass=user)) " ,
2023-05-09 07:10:59 +03:00
unparsed_name_encoded ) ;
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 ;
2023-05-09 07:10:59 +03:00
const char * unparsed_name_short_encoded = NULL ;
2023-09-05 07:38:23 +03:00
bool principal_is_host = false ;
2008-10-01 01:24:58 +04:00
2024-01-11 05:05:07 +03:00
ret = smb_krb5_init_context ( mem_ctx ,
( struct loadparm_context * ) ldb_get_opaque ( sam_ctx , " loadparm " ) ,
2008-10-01 01:24:58 +04:00
& smb_krb5_context ) ;
2009-07-06 01:15:34 +04:00
2008-10-01 01:24:58 +04:00
if ( ret ) {
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2008-10-01 01:24:58 +04:00
}
2007-04-07 09:14:23 +04:00
ret = krb5_parse_name ( smb_krb5_context - > krb5_context , name , & principal ) ;
2012-04-22 00:55:35 +04:00
if ( ret = = 0 & &
krb5_princ_size ( smb_krb5_context - > krb5_context ,
principal ) < 2 ) {
2007-04-07 09:14:23 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
return WERR_OK ;
2010-12-02 13:49:56 +03:00
} else if ( ret = = 0 ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2007-04-07 09:14:23 +04:00
}
2024-01-11 05:05:07 +03:00
ret = krb5_parse_name_flags ( smb_krb5_context - > krb5_context , name ,
2006-11-07 09:59:56 +03:00
KRB5_PRINCIPAL_PARSE_NO_REALM , & principal ) ;
2005-10-28 09:14:51 +04:00
if ( ret ) {
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
2024-01-11 05:05:07 +03:00
ret = krb5_unparse_name_flags ( smb_krb5_context - > krb5_context , principal ,
2006-11-07 09:59:56 +03:00
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 ) ;
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-09-02 07:19:27 +04:00
}
2005-12-19 14:50:28 +03:00
2023-05-09 07:10:59 +03:00
unparsed_name_short_encoded = ldb_binary_encode_string ( mem_ctx , unparsed_name_short ) ;
if ( unparsed_name_short_encoded = = NULL ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
free ( unparsed_name_short ) ;
return WERR_NOT_ENOUGH_MEMORY ;
}
2023-09-05 07:38:23 +03:00
if ( ( krb5_princ_size ( smb_krb5_context - > krb5_context , principal ) = = 2 ) ) {
krb5_data component ;
ret = smb_krb5_princ_component ( smb_krb5_context - > krb5_context ,
principal , 0 , & component ) ;
if ( ret ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
free ( unparsed_name_short ) ;
return WERR_INTERNAL_ERROR ;
}
principal_is_host = strcasecmp ( component . data , " host " ) = = 0 ;
}
if ( principal_is_host ) {
2005-12-19 14:50:28 +03:00
/* the 'cn' attribute is just the leading part of the name */
2023-09-05 07:38:23 +03:00
krb5_data component ;
2005-12-19 14:50:28 +03:00
char * computer_name ;
2023-05-09 07:10:59 +03:00
const char * computer_name_encoded = NULL ;
2023-09-05 07:38:23 +03:00
ret = smb_krb5_princ_component (
smb_krb5_context - > krb5_context ,
principal , 1 , & component ) ;
if ( ret ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
free ( unparsed_name_short ) ;
return WERR_INTERNAL_ERROR ;
}
computer_name = talloc_strndup ( mem_ctx , ( char * ) component . data ,
strcspn ( ( char * ) component . data , " . " ) ) ;
2005-12-19 14:50:28 +03:00
if ( computer_name = = NULL ) {
2010-12-02 13:49:56 +03:00
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
2010-12-04 18:39:01 +03:00
free ( unparsed_name_short ) ;
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-12-19 14:50:28 +03:00
}
2023-05-09 07:10:59 +03:00
computer_name_encoded = ldb_binary_encode_string ( mem_ctx , computer_name ) ;
if ( computer_name_encoded = = NULL ) {
krb5_free_principal ( smb_krb5_context - > krb5_context , principal ) ;
free ( unparsed_name_short ) ;
return WERR_NOT_ENOUGH_MEMORY ;
}
2024-01-11 05:05:07 +03:00
result_filter = talloc_asprintf ( mem_ctx , " (|(&(servicePrincipalName=%s)(objectClass=user))(&(cn=%s)(objectClass=computer))) " ,
2023-05-09 07:10:59 +03:00
unparsed_name_short_encoded ,
computer_name_encoded ) ;
2005-12-19 10:07:11 +03:00
} else {
result_filter = talloc_asprintf ( mem_ctx , " (&(servicePrincipalName=%s)(objectClass=user)) " ,
2023-05-09 07:10:59 +03:00
unparsed_name_short_encoded ) ;
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
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
2024-01-11 05:05:07 +03:00
return DsCrackNameOneFilter ( sam_ctx , mem_ctx ,
smb_krb5_context ,
format_flags , format_offered , format_desired ,
name_dn , name ,
domain_filter , result_filter ,
2012-05-17 10:52:30 +04:00
info1 , scope , search_dn ) ;
2005-09-02 07:19:27 +04:00
}
2005-12-19 10:07:11 +03:00
/* Subcase of CrackNames. It is possible to translate a LDAP-style DN
2023-08-02 11:41:31 +03:00
* ( FQDN_1779 ) into a canonical name without actually searching the
2005-12-19 10:07:11 +03:00
* 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 ,
2024-01-11 05:05:07 +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 ) {
2024-01-11 05:05:07 +03:00
case DRSUAPI_DS_NAME_FORMAT_CANONICAL :
2005-10-13 08:24:49 +04:00
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 ) {
2015-12-03 17:24:18 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2005-10-13 08:24:49 +04:00
}
2009-07-06 01:15:34 +04:00
2024-01-11 05:05:07 +03:00
return WERR_OK ;
2005-10-13 08:24:49 +04:00
}
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 ,
2024-01-11 05:05:07 +03:00
struct ldb_dn * name_dn , const char * name ,
const char * domain_filter , const char * result_filter ,
2012-05-17 10:52:30 +04:00
struct drsuapi_DsNameInfo1 * info1 ,
int scope , struct ldb_dn * search_dn )
2005-09-02 07:19:27 +04:00
{
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
2017-07-05 07:08:11 +03:00
const char * const _domain_attrs_upn [ ] = { " ncName " , " dnsRoot " , NULL } ;
const char * const _result_attrs_upn [ ] = { " userPrincipalName " , NULL } ;
const char * const _domain_attrs_spn [ ] = { " ncName " , " dnsRoot " , NULL } ;
const char * const _result_attrs_spn [ ] = { " servicePrincipalName " , NULL } ;
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 } ;
2021-03-30 06:00:04 +03:00
const char * const _domain_attrs_sid [ ] = { " ncName " , " dnsRoot " , NULL } ;
const char * const _result_attrs_sid [ ] = { " objectSid " , 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 ;
2024-01-11 05:05:07 +03:00
case DRSUAPI_DS_NAME_FORMAT_GUID :
2006-03-15 08:24:13 +03:00
domain_attrs = _domain_attrs_guid ;
result_attrs = _result_attrs_guid ;
2005-10-13 08:24:49 +04:00
break ;
2024-01-11 05:05:07 +03:00
case DRSUAPI_DS_NAME_FORMAT_DISPLAY :
2006-03-15 08:24:13 +03:00
domain_attrs = _domain_attrs_display ;
result_attrs = _result_attrs_display ;
2005-10-13 08:24:49 +04:00
break ;
2017-07-05 07:08:11 +03:00
case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL :
domain_attrs = _domain_attrs_upn ;
result_attrs = _result_attrs_upn ;
break ;
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL :
domain_attrs = _domain_attrs_spn ;
result_attrs = _result_attrs_spn ;
break ;
2021-03-30 06:00:04 +03:00
case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY :
domain_attrs = _domain_attrs_sid ;
result_attrs = _result_attrs_sid ;
break ;
2005-10-13 08:24:49 +04:00
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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 2 , ( " DsCrackNameOneFilter domain ref search failed: %s \n " , ldb_errstring ( sam_ctx ) ) ) ;
2007-11-15 03:12:10 +03:00
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
2010-10-14 11:41:42 +04:00
info1 - > dns_domain_name = ldb_msg_find_attr_as_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 ;
2013-07-01 07:44:22 +04:00
struct ldb_dn * real_search_dn = NULL ;
2013-06-30 13:04:20 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
2009-07-06 01:15:34 +04:00
2013-07-01 07:44:22 +04:00
/*
* From 4.1 .4 .2 .11 of MS - DRSR
* if DS_NAME_FLAG_GCVERIFY in flags then
* rt : = select all O from all
* where attrValue in GetAttrVals ( O , att , false )
* else
* rt : = select all O from subtree DefaultNC ( )
* where attrValue in GetAttrVals ( O , att , false )
* endif
* return rt
*/
if ( format_flags & DRSUAPI_DS_NAME_FLAG_GCVERIFY | |
format_offered = = DRSUAPI_DS_NAME_FORMAT_GUID )
{
dsdb_flags = DSDB_SEARCH_SEARCH_ALL_PARTITIONS ;
} else if ( domain_res ) {
2012-05-17 10:52:30 +04:00
if ( ! search_dn ) {
struct ldb_dn * tmp_dn = samdb_result_dn ( sam_ctx , mem_ctx , domain_res - > msgs [ 0 ] , " ncName " , NULL ) ;
real_search_dn = tmp_dn ;
} else {
real_search_dn = search_dn ;
}
2007-02-22 05:08:40 +03:00
} else {
2013-07-01 07:44:22 +04:00
real_search_dn = ldb_get_default_basedn ( sam_ctx ) ;
2010-02-16 08:09:07 +03:00
}
2017-07-05 02:15:04 +03:00
if ( format_offered = = DRSUAPI_DS_NAME_FORMAT_GUID ) {
2013-06-10 16:00:01 +04:00
dsdb_flags | = DSDB_SEARCH_SHOW_RECYCLED ;
2011-07-31 00:54:01 +04:00
}
2010-02-16 08:09:07 +03:00
/* search with the 'phantom root' flag */
ret = dsdb_search ( sam_ctx , mem_ctx , & res ,
2012-05-17 10:52:30 +04:00
real_search_dn ,
scope ,
2010-02-16 08:09:07 +03:00
result_attrs ,
2011-07-31 00:54:01 +04:00
dsdb_flags ,
2010-02-16 08:09:07 +03:00
" %s " , result_filter ) ;
if ( ret ! = LDB_SUCCESS ) {
2014-08-18 02:08:24 +04:00
DEBUG ( 2 , ( " DsCrackNameOneFilter search from '%s' with flags 0x%08x failed: %s \n " ,
ldb_dn_get_linearized ( real_search_dn ) ,
dsdb_flags ,
2010-02-16 08:09:07 +03:00
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 */
2011-08-24 09:46:53 +04:00
DEBUG ( 0 , ( " LOGIC ERROR: DsCrackNameOneFilter domain ref search not available: This can't happen... \n " ) ) ;
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 ) {
2024-01-11 05:05:07 +03:00
case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL :
return DsCrackNameSPNAlias ( sam_ctx , mem_ctx ,
smb_krb5_context ,
2005-09-02 07:19:27 +04:00
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 :
2024-01-11 05:05:07 +03: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 :
2011-08-24 09:46:53 +04:00
DEBUG ( 2 , ( " DsCrackNameOneFilter result search failed: %s \n " , 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 ;
}
}
2017-07-26 18:21:02 +03:00
FALL_THROUGH ;
2006-12-28 06:33:52 +03:00
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 : {
2010-10-14 11:41:42 +04:00
info1 - > result_name = ldb_msg_find_attr_as_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 */
2024-01-11 05:05:07 +03:00
return DsCrackNameOneSyntactical ( mem_ctx ,
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
2005-10-13 08:24:49 +04:00
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 = " " ;
2012-10-24 09:41:52 +04:00
if ( sid = = NULL ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING ;
return WERR_OK ;
2012-11-03 12:36:29 +04:00
}
if ( samdb_find_attribute ( sam_ctx , result , " objectClass " ,
" domain " ) ) {
2012-10-24 09:41:52 +04:00
/* This can also find a DomainDNSZones entry,
* but it won ' t have the SID we just
* checked . */
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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 2 , ( " DsCrackNameOneFilter domain ref search failed: %s \n " , ldb_errstring ( sam_ctx ) ) ) ;
2007-11-15 03:12:10 +03:00
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
}
2010-10-14 11:41:42 +04:00
_dom = ldb_msg_find_attr_as_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 {
2010-10-14 11:41:42 +04:00
_acc = ldb_msg_find_attr_as_string ( result , " sAMAccountName " , NULL ) ;
2006-12-28 07:52:45 +03:00
if ( ! _acc ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING ;
2005-09-02 07:19:27 +04:00
return WERR_OK ;
}
2023-09-11 06:27:09 +03:00
if ( dom_sid_in_domain ( & global_sid_Builtin , sid ) ) {
2006-12-28 07:52:45 +03:00
_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 ,
2024-01-11 05:05:07 +03:00
" (&(objectSid=%s)(objectClass=domain)) " ,
2007-11-15 03:12:10 +03:00
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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 2 , ( " DsCrackNameOneFilter domain search failed: %s \n " , ldb_errstring ( sam_ctx ) ) ) ;
2007-11-15 03:12:10 +03:00
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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 2 , ( " DsCrackNameOneFilter domain ref search failed: %s \n " , ldb_errstring ( sam_ctx ) ) ) ;
2007-11-15 03:12:10 +03:00
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 ;
}
2010-10-14 11:41:42 +04:00
_dom = ldb_msg_find_attr_as_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 : {
2010-10-14 11:41:42 +04:00
info1 - > result_name = ldb_msg_find_attr_as_string ( result , " displayName " , NULL ) ;
2005-10-13 08:24:49 +04:00
if ( ! info1 - > result_name ) {
2010-10-14 11:41:42 +04:00
info1 - > result_name = ldb_msg_find_attr_as_string ( result , " sAMAccountName " , NULL ) ;
2024-01-11 05:05:07 +03:00
}
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 : {
2018-07-30 05:00:18 +03:00
struct ldb_message_element * el
= ldb_msg_find_element ( result ,
" servicePrincipalName " ) ;
if ( el = = NULL ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
return WERR_OK ;
} else if ( el - > num_values > 1 ) {
2017-07-05 07:08:11 +03:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE ;
return WERR_OK ;
}
info1 - > result_name = ldb_msg_find_attr_as_string ( result , " servicePrincipalName " , NULL ) ;
if ( ! info1 - > result_name ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING ;
} else {
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
}
2007-04-07 09:14:23 +04:00
return WERR_OK ;
}
2021-03-30 06:00:04 +03:00
case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN : {
2012-09-25 21:51:47 +04:00
info1 - > dns_domain_name = NULL ;
2007-04-07 09:14:23 +04:00
info1 - > status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR ;
return WERR_OK ;
}
2021-03-30 06:00:04 +03:00
case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY : {
const struct dom_sid * sid = samdb_result_dom_sid ( mem_ctx , result , " objectSid " ) ;
if ( sid = = NULL ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING ;
return WERR_OK ;
}
info1 - > result_name = dom_sid_string ( mem_ctx , sid ) ;
W_ERROR_HAVE_NO_MEMORY ( info1 - > result_name ) ;
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
return WERR_OK ;
}
2017-07-05 07:08:11 +03:00
case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL : {
info1 - > result_name = ldb_msg_find_attr_as_string ( result , " userPrincipalName " , NULL ) ;
if ( ! info1 - > result_name ) {
info1 - > status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING ;
} else {
info1 - > status = DRSUAPI_DS_NAME_STATUS_OK ;
}
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 */
2024-01-11 05:05:07 +03:00
NTSTATUS crack_user_principal_name ( struct ldb_context * sam_ctx ,
TALLOC_CTX * mem_ctx ,
const char * user_principal_name ,
2005-10-21 05:25:55 +04:00
struct ldb_dn * * user_dn ,
2024-01-11 05:05:07 +03:00
struct ldb_dn * * domain_dn )
2005-10-21 05:25:55 +04:00
{
WERROR werr ;
struct drsuapi_DsNameInfo1 info1 ;
werr = DsCrackNameOneName ( sam_ctx , mem_ctx , 0 ,
DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL ,
2024-01-11 05:05:07 +03:00
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
2005-10-21 05:25:55 +04:00
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 ,
2024-01-11 05:05:07 +03:00
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
talloc_asprintf ( mem_ctx , " %s/ " ,
2005-10-28 02:27:51 +04:00
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 */
2024-01-11 05:05:07 +03:00
NTSTATUS crack_service_principal_name ( struct ldb_context * sam_ctx ,
TALLOC_CTX * mem_ctx ,
const char * service_principal_name ,
2005-10-28 02:27:51 +04:00
struct ldb_dn * * user_dn ,
2024-01-11 05:05:07 +03:00
struct ldb_dn * * domain_dn )
2005-10-28 02:27:51 +04:00
{
WERROR werr ;
struct drsuapi_DsNameInfo1 info1 ;
werr = DsCrackNameOneName ( sam_ctx , mem_ctx , 0 ,
DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL ,
2024-01-11 05:05:07 +03:00
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
2005-10-28 02:27:51 +04:00
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 ,
2024-01-11 05:05:07 +03:00
DRSUAPI_DS_NAME_FORMAT_FQDN_1779 ,
talloc_asprintf ( mem_ctx , " %s/ " ,
2005-10-21 05:25:55 +04:00
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
2024-01-11 05:05:07 +03:00
NTSTATUS crack_name_to_nt4_name ( TALLOC_CTX * mem_ctx ,
2017-06-19 09:39:19 +03:00
struct ldb_context * ldb ,
2010-09-20 20:41:00 +04:00
enum drsuapi_DsNameFormat format_offered ,
2024-01-11 05:05:07 +03:00
const char * name ,
2007-01-19 18:14:45 +03:00
const char * * nt4_domain , const char * * nt4_account )
2005-12-19 09:56:45 +03:00
{
WERROR werr ;
struct drsuapi_DsNameInfo1 info1 ;
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
}
2005-12-19 09:56:45 +03:00
werr = DsCrackNameOneName ( ldb , mem_ctx , 0 ,
2024-01-11 05:05:07 +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 ,
2017-06-19 09:39:19 +03:00
struct ldb_context * ldb ,
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 ;
}
2021-03-30 06:00:04 +03:00
/*
* Here we only consider a subset of the possible name forms listed in
* [ MS - ADTS ] 5.1 .1 .1 .1 , and we don ' t retry with a different name form if
* the first attempt fails .
*/
2007-01-19 18:14:45 +03:00
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 ;
2021-03-30 06:02:27 +03:00
} else if ( strchr_m ( name , ' \n ' ) ) {
format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX ;
2007-01-19 18:14:45 +03:00
} else if ( strchr_m ( name , ' / ' ) ) {
format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL ;
2021-03-30 06:00:04 +03:00
} else if ( ( name [ 0 ] = = ' S ' | | name [ 0 ] = = ' s ' ) & & name [ 1 ] = = ' - ' ) {
format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY ;
2008-10-01 01:24:58 +04:00
} else {
return NT_STATUS_NO_SUCH_USER ;
2007-01-19 18:14:45 +03:00
}
2017-06-19 09:39:19 +03:00
return crack_name_to_nt4_name ( mem_ctx , ldb , 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 ) {
2011-08-24 09:46:53 +04:00
DEBUG ( 4 , ( " list_roles: Failed to find dNSHostName for server %s \n " ,
2010-09-20 20:46:10 +04:00
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 ;
2012-10-24 04:56:02 +04:00
* ctr1 = talloc_zero ( mem_ctx , struct drsuapi_DsNameCtr1 ) ;
2010-09-20 20:46:10 +04:00
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 ;
}
2012-09-25 08:34:02 +04:00
WERROR dcesrv_drsuapi_ListInfoServer ( struct ldb_context * sam_ctx , TALLOC_CTX * mem_ctx ,
const struct drsuapi_DsNameRequest1 * req1 ,
struct drsuapi_DsNameCtr1 * * _ctr1 )
{
struct drsuapi_DsNameInfo1 * names ;
struct ldb_result * res ;
struct ldb_dn * server_dn , * dn ;
struct drsuapi_DsNameCtr1 * ctr1 ;
int ret , i ;
const char * str ;
const char * attrs [ ] = {
" dNSHostName " ,
" serverReference " ,
NULL
} ;
* _ctr1 = NULL ;
ctr1 = talloc_zero ( mem_ctx , struct drsuapi_DsNameCtr1 ) ;
W_ERROR_HAVE_NO_MEMORY ( ctr1 ) ;
/*
* No magic value here , we have to return 3 entries according to the
* MS - DRSR . pdf
*/
ctr1 - > count = 3 ;
names = talloc_zero_array ( ctr1 , struct drsuapi_DsNameInfo1 ,
ctr1 - > count ) ;
W_ERROR_HAVE_NO_MEMORY ( names ) ;
ctr1 - > array = names ;
for ( i = 0 ; i < ctr1 - > count ; i + + ) {
names [ i ] . status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND ;
}
* _ctr1 = ctr1 ;
if ( req1 - > count ! = 1 ) {
DEBUG ( 1 , ( " Expected a count of 1 for the ListInfoServer crackname \n " ) ) ;
return WERR_OK ;
}
if ( req1 - > names [ 0 ] . str = = NULL ) {
return WERR_OK ;
}
server_dn = ldb_dn_new ( mem_ctx , sam_ctx , req1 - > names [ 0 ] . str ) ;
W_ERROR_HAVE_NO_MEMORY ( server_dn ) ;
ret = ldb_search ( sam_ctx , mem_ctx , & res , server_dn , LDB_SCOPE_ONELEVEL ,
NULL , " (objectClass=nTDSDSA) " ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 1 , ( " Search for objectClass=nTDSDSA "
" returned less than 1 objects \n " ) ) ;
return WERR_OK ;
}
if ( res - > count ! = 1 ) {
DEBUG ( 1 , ( " Search for objectClass=nTDSDSA "
" returned less than 1 objects \n " ) ) ;
return WERR_OK ;
}
if ( res - > msgs [ 0 ] - > dn ) {
names [ 0 ] . result_name = ldb_dn_alloc_linearized ( names , res - > msgs [ 0 ] - > dn ) ;
W_ERROR_HAVE_NO_MEMORY ( names [ 0 ] . result_name ) ;
names [ 0 ] . status = DRSUAPI_DS_NAME_STATUS_OK ;
}
talloc_free ( res ) ;
ret = ldb_search ( sam_ctx , mem_ctx , & res , server_dn , LDB_SCOPE_BASE ,
attrs , " (objectClass=*) " ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 1 , ( " Search for objectClass=* on dn %s "
" returned %s \n " , req1 - > names [ 0 ] . str ,
ldb_strerror ( ret ) ) ) ;
return WERR_OK ;
}
if ( res - > count ! = 1 ) {
DEBUG ( 1 , ( " Search for objectClass=* on dn %s "
" returned less than 1 objects \n " , req1 - > names [ 0 ] . str ) ) ;
return WERR_OK ;
}
str = ldb_msg_find_attr_as_string ( res - > msgs [ 0 ] , " dNSHostName " , NULL ) ;
if ( str ! = NULL ) {
names [ 1 ] . result_name = talloc_strdup ( names , str ) ;
W_ERROR_HAVE_NO_MEMORY ( names [ 1 ] . result_name ) ;
names [ 1 ] . status = DRSUAPI_DS_NAME_STATUS_OK ;
}
dn = ldb_msg_find_attr_as_dn ( sam_ctx , mem_ctx , res - > msgs [ 0 ] , " serverReference " ) ;
if ( dn ! = NULL ) {
names [ 2 ] . result_name = ldb_dn_alloc_linearized ( names , dn ) ;
W_ERROR_HAVE_NO_MEMORY ( names [ 2 ] . result_name ) ;
names [ 2 ] . status = DRSUAPI_DS_NAME_STATUS_OK ;
}
talloc_free ( dn ) ;
talloc_free ( res ) ;
return WERR_OK ;
}