From 807402e4e9ac43d0fe7a7533698102a74e23844b Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Fri, 27 May 2011 11:44:16 +0200 Subject: Properly support IPv6 in LDAP URIs for IPA and LDAP providers Add utility function to return IP address as string Add a utility function to escape IPv6 address for use in URIs Use escaped IP addresses in LDAP provider Escape IPv6 IP addresses in the IPA provider https://fedorahosted.org/sssd/ticket/880 Fix bad merge We merged in a patch, but missed that it missed a dependency added by another earlier patch. --- src/providers/ipa/ipa_common.c | 32 +++++++++++++++------ src/providers/krb5/krb5_common.c | 11 ++----- src/providers/ldap/ldap_common.c | 62 ++++++++++++++++++++++++++++++++++++---- src/resolv/async_resolv.c | 24 ++++++++++++++++ src/resolv/async_resolv.h | 3 ++ src/util/sss_ldap.c | 8 ++++++ src/util/sss_ldap.h | 4 +++ 7 files changed, 121 insertions(+), 23 deletions(-) diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 7d7f04665..1a81bea75 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -555,15 +555,24 @@ done: static void ipa_resolve_callback(void *private_data, struct fo_server *server) { + TALLOC_CTX *tmp_ctx = NULL; struct ipa_service *service; struct hostent *srvaddr; char *address; + const char *safe_address; char *new_uri; int ret; + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(1, ("talloc_new failed\n")); + return; + } + service = talloc_get_type(private_data, struct ipa_service); if (!service) { DEBUG(1, ("FATAL: Bad private_data\n")); + talloc_free(tmp_ctx); return; } @@ -571,33 +580,39 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server) if (!srvaddr) { DEBUG(1, ("FATAL: No hostent available for server (%s)\n", fo_get_server_name(server))); + talloc_free(tmp_ctx); return; } - address = talloc_zero_size(service, 128); + address = resolv_get_string_address(tmp_ctx, srvaddr); if (address == NULL) { - DEBUG(1, ("talloc_zero failed.\n")); + DEBUG(1, ("resolv_get_string_address failed.\n")); + talloc_free(tmp_ctx); return; } - if (inet_ntop(srvaddr->h_addrtype, srvaddr->h_addr_list[0], - address, 128) == NULL) { - DEBUG(1, ("inet_ntop failed [%d][%s].\n", errno, strerror(errno))); + safe_address = sss_ldap_escape_ip_address(tmp_ctx, + srvaddr->h_addrtype, + address); + if (safe_address == NULL) { + DEBUG(1, ("sss_ldap_escape_ip_address failed.\n")); + talloc_free(tmp_ctx); return; } - new_uri = talloc_asprintf(service, "ldap://%s", address); + new_uri = talloc_asprintf(service, "ldap://%s", safe_address); if (!new_uri) { DEBUG(2, ("Failed to copy URI ...\n")); - talloc_free(address); + talloc_free(tmp_ctx); return; } + DEBUG(6, ("Constructed uri '%s'\n", new_uri)); /* free old one and replace with new one */ talloc_zfree(service->sdap->uri); service->sdap->uri = new_uri; talloc_zfree(service->krb5_service->address); - service->krb5_service->address = address; + service->krb5_service->address = talloc_steal(service, address); ret = write_krb5info_file(service->krb5_service->realm, address, SSS_KRB5KDC_FO_SRV); @@ -605,6 +620,7 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server) DEBUG(2, ("write_krb5info_file failed, authentication might fail.\n")); } + talloc_free(tmp_ctx); } int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c index 434fc7fbc..06c3cbac6 100644 --- a/src/providers/krb5/krb5_common.c +++ b/src/providers/krb5/krb5_common.c @@ -384,16 +384,9 @@ static void krb5_resolve_callback(void *private_data, struct fo_server *server) return; } - address = talloc_zero_size(krb5_service, 128); + address = resolv_get_string_address(krb5_service, srvaddr); if (address == NULL) { - DEBUG(1, ("talloc_zero failed.\n")); - return; - } - - if (inet_ntop(srvaddr->h_addrtype, srvaddr->h_addr_list[0], - address, 128) == NULL) { - ret = errno; - DEBUG(1, ("inet_ntop failed [%d][%s].\n", ret, strerror(ret))); + DEBUG(1, ("resolv_get_string_address failed.\n")); return; } diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index 8294e9225..295469268 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -527,35 +527,84 @@ int sdap_id_setup_tasks(struct sdap_id_ctx *ctx) static void sdap_uri_callback(void *private_data, struct fo_server *server) { + TALLOC_CTX *tmp_ctx = NULL; struct sdap_service *service; + struct hostent *srvaddr; + char *address; + const char *safe_address; const char *tmp; char *new_uri; + LDAPURLDesc *lud; + int ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(1, ("talloc_new failed\n")); + return; + } service = talloc_get_type(private_data, struct sdap_service); - if (!service) return; + if (!service) { + talloc_free(tmp_ctx); + return; + } tmp = (const char *)fo_get_server_user_data(server); + srvaddr = fo_get_server_hostent(server); + if (!srvaddr) { + DEBUG(1, ("FATAL: No hostent available for server (%s)\n", + fo_get_server_name(server))); + talloc_free(tmp_ctx); + return; + } + + address = resolv_get_string_address(tmp_ctx, srvaddr); + if (address == NULL) { + DEBUG(1, ("resolv_get_string_address failed.\n")); + talloc_free(tmp_ctx); + return; + } + + safe_address = sss_ldap_escape_ip_address(tmp_ctx, + srvaddr->h_addrtype, + address); + talloc_zfree(address); + if (safe_address == NULL) { + DEBUG(1, ("sss_ldap_escape_ip_address failed.\n")); + talloc_free(tmp_ctx); + return; + } + if (fo_is_srv_lookup(server)) { if (!tmp) { DEBUG(1, ("Unknown service, using ldap\n")); tmp = SSS_LDAP_SRV_NAME; } new_uri = talloc_asprintf(service, "%s://%s:%d", - tmp, - fo_get_server_name(server), + tmp, safe_address, fo_get_server_port(server)); } else { if (tmp && ldap_is_ldap_url(tmp)) { - new_uri = talloc_strdup(service, tmp); + ret = ldap_url_parse(tmp, &lud); + if (ret != LDAP_SUCCESS) { + DEBUG(0, ("Failed to parse ldap URI (%s)!\n", tmp)); + talloc_free(tmp_ctx); + return; + } + new_uri = talloc_asprintf(service, "%s://%s:%d", + lud->lud_scheme, + safe_address, + fo_get_server_port(server)); + ldap_free_urldesc(lud); } else { - new_uri = talloc_asprintf(service, "ldap://%s", - fo_get_server_name(server)); + new_uri = talloc_asprintf(service, "ldap://%s", safe_address); } } if (!new_uri) { DEBUG(2, ("Failed to copy URI ...\n")); + talloc_free(tmp_ctx); return; } @@ -564,6 +613,7 @@ static void sdap_uri_callback(void *private_data, struct fo_server *server) /* free old one and replace with new one */ talloc_zfree(service->uri); service->uri = new_uri; + talloc_free(tmp_ctx); } static void sdap_finalize(struct tevent_context *ev, diff --git a/src/resolv/async_resolv.c b/src/resolv/async_resolv.c index ff53aa441..13232097f 100644 --- a/src/resolv/async_resolv.c +++ b/src/resolv/async_resolv.c @@ -648,6 +648,30 @@ resolv_gethostbyname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, return EOK; } +char * +resolv_get_string_address(TALLOC_CTX *mem_ctx, struct hostent *hostent) +{ + char *address; + + if (!hostent) return NULL; + + address = talloc_zero_size(mem_ctx, 128); + if (address == NULL) { + DEBUG(1, ("talloc_zero failed.\n")); + return NULL; + } + + errno = 0; + if (inet_ntop(hostent->h_addrtype, hostent->h_addr_list[0], + address, 128) == NULL) { + DEBUG(1, ("inet_ntop failed [%d][%s].\n", errno, strerror(errno))); + talloc_free(address); + return NULL; + } + + return address; +} + static void ares_gethostbyname_wakeup(struct tevent_req *subreq) { diff --git a/src/resolv/async_resolv.h b/src/resolv/async_resolv.h index b6a13d7fa..d6cbe1494 100644 --- a/src/resolv/async_resolv.h +++ b/src/resolv/async_resolv.h @@ -76,6 +76,9 @@ int resolv_gethostbyname_recv(struct tevent_req *req, int *timeouts, struct hostent **hostent); +char * +resolv_get_string_address(TALLOC_CTX *mem_ctx, struct hostent *hostent); + /** Get SRV record **/ struct tevent_req *resolv_getsrv_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c index f098e7d6d..94a10386d 100644 --- a/src/util/sss_ldap.c +++ b/src/util/sss_ldap.c @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include +#include #include "config.h" @@ -68,3 +69,10 @@ int sss_ldap_control_create(const char *oid, int iscritical, return LDAP_SUCCESS; #endif } + +inline const char * +sss_ldap_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr) +{ + return family == AF_INET6 ? talloc_asprintf(mem_ctx, "[%s]", addr) : + talloc_strdup(mem_ctx, addr); +} diff --git a/src/util/sss_ldap.h b/src/util/sss_ldap.h index 14747dffc..619bde641 100644 --- a/src/util/sss_ldap.h +++ b/src/util/sss_ldap.h @@ -22,9 +22,13 @@ #define __SSS_LDAP_H__ #include +#include int sss_ldap_control_create(const char *oid, int iscritical, struct berval *value, int dupval, LDAPControl **ctrlp); +inline const char * +sss_ldap_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr); + #endif /* __SSS_LDAP_H__ */ -- cgit