mirror of
https://github.com/samba-team/samba.git
synced 2025-02-23 09:57:40 +03:00
libads: Add API call to connect to a global catalog server.
Extends ads_connect() to a new call ads_connect_gc() which connects on port 3268 rather than port 389. Also makes ads_try_connect() static and only used internally to ldap.c (This used to be commit f4c37dbe2c986fb7bfe510cdff3b4a9fbc06d079)
This commit is contained in:
parent
e08943f8d8
commit
9ff1ffcbee
@ -53,7 +53,9 @@ typedef struct ads_struct {
|
||||
char *realm;
|
||||
char *workgroup;
|
||||
char *ldap_server;
|
||||
int foreign; /* set to 1 if connecting to a foreign realm */
|
||||
int foreign; /* set to 1 if connecting to a foreign
|
||||
* realm */
|
||||
bool gc; /* Is this a global catalog server? */
|
||||
} server;
|
||||
|
||||
/* info needed to authenticate */
|
||||
|
@ -2063,7 +2063,6 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
|
||||
|
||||
bool ads_sitename_match(ADS_STRUCT *ads);
|
||||
bool ads_closest_dc(ADS_STRUCT *ads);
|
||||
bool ads_try_connect(ADS_STRUCT *ads, const char *server );
|
||||
ADS_STATUS ads_connect(ADS_STRUCT *ads);
|
||||
ADS_STATUS ads_connect_user_creds(ADS_STRUCT *ads);
|
||||
void ads_disconnect(ADS_STRUCT *ads);
|
||||
|
@ -1847,6 +1847,7 @@ typedef struct _smb_iconv_t {
|
||||
#ifndef LDAP_PORT
|
||||
#define LDAP_PORT 389
|
||||
#endif
|
||||
#define LDAP_GC_PORT 3268
|
||||
|
||||
/* used by the IP comparison function */
|
||||
struct ip_service {
|
||||
|
@ -173,7 +173,7 @@ bool ads_closest_dc(ADS_STRUCT *ads)
|
||||
try a connection to a given ldap server, returning True and setting the servers IP
|
||||
in the ads struct if successful
|
||||
*/
|
||||
bool ads_try_connect(ADS_STRUCT *ads, const char *server )
|
||||
static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
|
||||
{
|
||||
char *srv;
|
||||
struct nbt_cldap_netlogon_5 cldap_reply;
|
||||
@ -238,7 +238,7 @@ bool ads_try_connect(ADS_STRUCT *ads, const char *server )
|
||||
}
|
||||
ads->server.workgroup = SMB_STRDUP(cldap_reply.domain);
|
||||
|
||||
ads->ldap.port = LDAP_PORT;
|
||||
ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT;
|
||||
if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) {
|
||||
DEBUG(1,("ads_try_connect: unable to convert %s "
|
||||
"to an address\n",
|
||||
@ -358,7 +358,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
|
||||
}
|
||||
}
|
||||
|
||||
if ( ads_try_connect(ads, server) ) {
|
||||
if ( ads_try_connect(ads, server, false) ) {
|
||||
SAFE_FREE(ip_list);
|
||||
SAFE_FREE(sitename);
|
||||
return NT_STATUS_OK;
|
||||
@ -385,6 +385,141 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
|
||||
return NT_STATUS_NO_LOGON_SERVERS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
static NTSTATUS ads_lookup_site(void)
|
||||
{
|
||||
ADS_STRUCT *ads = NULL;
|
||||
ADS_STATUS ads_status;
|
||||
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
||||
struct nbt_cldap_netlogon_5 cldap_reply;
|
||||
|
||||
ZERO_STRUCT(cldap_reply);
|
||||
|
||||
ads = ads_init(lp_realm(), NULL, NULL);
|
||||
if (!ads) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* The NO_BIND here will find a DC and set the client site
|
||||
but not establish the TCP connection */
|
||||
|
||||
ads->auth.flags = ADS_AUTH_NO_BIND;
|
||||
ads_status = ads_connect(ads);
|
||||
if (!ADS_ERR_OK(ads_status)) {
|
||||
DEBUG(4, ("ads_lookup_site: ads_connect to our realm failed! (%s)\n",
|
||||
ads_errstr(ads_status)));
|
||||
}
|
||||
nt_status = ads_ntstatus(ads_status);
|
||||
|
||||
if (ads) {
|
||||
ads_destroy(&ads);
|
||||
}
|
||||
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
static const char* host_dns_domain(const char *fqdn)
|
||||
{
|
||||
const char *p = fqdn;
|
||||
|
||||
/* go to next char following '.' */
|
||||
|
||||
if ((p = strchr_m(fqdn, '.')) != NULL) {
|
||||
p++;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connect to the Global Catalog server
|
||||
* @param ads Pointer to an existing ADS_STRUCT
|
||||
* @return status of connection
|
||||
*
|
||||
* Simple wrapper around ads_connect() that fills in the
|
||||
* GC ldap server information
|
||||
**/
|
||||
|
||||
ADS_STATUS ads_connect_gc(ADS_STRUCT *ads)
|
||||
{
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct dns_rr_srv *gcs_list;
|
||||
int num_gcs;
|
||||
char *realm = ads->server.realm;
|
||||
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
||||
ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
|
||||
int i;
|
||||
bool done = false;
|
||||
char *sitename = NULL;
|
||||
|
||||
if (!realm)
|
||||
realm = lp_realm();
|
||||
|
||||
if ((sitename = sitename_fetch(realm)) == NULL) {
|
||||
ads_lookup_site();
|
||||
sitename = sitename_fetch(realm);
|
||||
}
|
||||
|
||||
do {
|
||||
/* We try once with a sitename and once without
|
||||
(unless we don't have a sitename and then we're
|
||||
done */
|
||||
|
||||
if (sitename == NULL)
|
||||
done = true;
|
||||
|
||||
nt_status = ads_dns_query_gcs(frame, realm, sitename,
|
||||
&gcs_list, &num_gcs);
|
||||
|
||||
SAFE_FREE(sitename);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
ads_status = ADS_ERROR_NT(nt_status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Loop until we get a successful connection or have gone
|
||||
through them all. When connecting a GC server, make sure that
|
||||
the realm is the server's DNS name and not the forest root */
|
||||
|
||||
for (i=0; i<num_gcs; i++) {
|
||||
ads->server.gc = true;
|
||||
ads->server.ldap_server = SMB_STRDUP(gcs_list[i].hostname);
|
||||
ads->server.realm = SMB_STRDUP(host_dns_domain(ads->server.ldap_server));
|
||||
ads_status = ads_connect(ads);
|
||||
if (ADS_ERR_OK(ads_status)) {
|
||||
/* Reset the bind_dn to "". A Global Catalog server
|
||||
may host multiple domain trees in a forest.
|
||||
Windows 2003 GC server will accept "" as the search
|
||||
path to imply search all domain trees in the forest */
|
||||
|
||||
SAFE_FREE(ads->config.bind_path);
|
||||
ads->config.bind_path = SMB_STRDUP("");
|
||||
|
||||
|
||||
goto done;
|
||||
}
|
||||
SAFE_FREE(ads->server.ldap_server);
|
||||
SAFE_FREE(ads->server.realm);
|
||||
}
|
||||
|
||||
TALLOC_FREE(gcs_list);
|
||||
num_gcs = 0;
|
||||
} while (!done);
|
||||
|
||||
done:
|
||||
SAFE_FREE(sitename);
|
||||
talloc_destroy(frame);
|
||||
|
||||
return ads_status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connect to the LDAP server
|
||||
@ -412,7 +547,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
|
||||
}
|
||||
|
||||
if (ads->server.ldap_server &&
|
||||
ads_try_connect(ads, ads->server.ldap_server)) {
|
||||
ads_try_connect(ads, ads->server.ldap_server, ads->server.gc)) {
|
||||
goto got_connection;
|
||||
}
|
||||
|
||||
@ -472,7 +607,7 @@ got_connection:
|
||||
/* Otherwise setup the TCP LDAP session */
|
||||
|
||||
ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
|
||||
LDAP_PORT, lp_ldap_timeout());
|
||||
ads->ldap.port, lp_ldap_timeout());
|
||||
if (ads->ldap.ld == NULL) {
|
||||
status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
|
||||
goto out;
|
||||
|
@ -1043,14 +1043,16 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx,
|
||||
|
||||
if (lp_security() == SEC_ADS) {
|
||||
ADS_STRUCT *ads;
|
||||
ADS_STATUS ads_status;
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
|
||||
print_sockaddr(addr, sizeof(addr), pss);
|
||||
|
||||
ads = ads_init(domain->alt_name, domain->name, NULL);
|
||||
ads = ads_init(domain->alt_name, domain->name, addr);
|
||||
ads->auth.flags |= ADS_AUTH_NO_BIND;
|
||||
|
||||
if (ads_try_connect(ads, addr)) {
|
||||
ads_status = ads_connect(ads);
|
||||
if (ADS_ERR_OK(ads_status)) {
|
||||
/* We got a cldap packet. */
|
||||
fstrcpy(name, ads->config.ldap_server_name);
|
||||
namecache_store(name, 0x20, 1, &ip_list);
|
||||
|
Loading…
x
Reference in New Issue
Block a user