sdap_async_sudo_hostinfo.c revision 468f1c8d4763a65f24ab8d7523a5291ef6320db7
6de8046f8f7e07cd83895a528df25d977e502c76nd/*
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein Authors:
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd Pavel Březina <pbrezina@redhat.com>
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd Copyright (C) 2012 Red Hat
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd This program is free software; you can redistribute it and/or modify
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein it under the terms of the GNU General Public License as published by
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd the Free Software Foundation; either version 3 of the License, or
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd (at your option) any later version.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd This program is distributed in the hope that it will be useful,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd but WITHOUT ANY WARRANTY; without even the implied warranty of
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f4c310fd2555c6faca1f980f00b161eadb089023gstein GNU General Public License for more details.
aa552377469071a421252dab6568c204a99cf770gstein
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein You should have received a copy of the GNU General Public License
f4c310fd2555c6faca1f980f00b161eadb089023gstein along with this program. If not, see <http://www.gnu.org/licenses/>.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gstein
cd5c0afc86ca2eb23d6d12e14590e03cf2f80450gstein#include <errno.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <tevent.h>
c364a517c4f0db3d0a33c662c02f2d567a33e135martin#include <talloc.h>
f6b86fd524444dacf82f64148300d8be04918314gstein#include <sys/types.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <sys/socket.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <arpa/inet.h>
f69b31136266022effeb1272d153c92a09de072djerenkrantz#include <ifaddrs.h>
f69b31136266022effeb1272d153c92a09de072djerenkrantz
f6b86fd524444dacf82f64148300d8be04918314gstein#include "util/util.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "providers/ldap/sdap.h"
aa552377469071a421252dab6568c204a99cf770gstein#include "providers/ldap/sdap_id_op.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "providers/ldap/sdap_sudo.h"
aa552377469071a421252dab6568c204a99cf770gstein
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantzstatic int sdap_sudo_get_ip_addresses(TALLOC_CTX *mem_ctx, char ***_ip_addr);
3a02a42c92afc04c1cfca12eabdf19963784ae83nd
aa552377469071a421252dab6568c204a99cf770gsteinstruct sdap_sudo_get_hostinfo_state {
aa552377469071a421252dab6568c204a99cf770gstein char **hostnames;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz char **ip_addr;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz};
226b4a760e9b997415cf061bb3d979c0c31ae642jorton
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstruct tevent_req * sdap_sudo_get_hostinfo_send(TALLOC_CTX *mem_ctx,
aa552377469071a421252dab6568c204a99cf770gstein struct sdap_options *opts,
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz struct be_ctx *be_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz struct tevent_req *req = NULL;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz struct sdap_sudo_get_hostinfo_state *state = NULL;
f69b31136266022effeb1272d153c92a09de072djerenkrantz char *conf_hostnames = NULL;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz char *conf_ip_addr = NULL;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz int ret;
f69b31136266022effeb1272d153c92a09de072djerenkrantz
f69b31136266022effeb1272d153c92a09de072djerenkrantz /* create request */
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_get_hostinfo_state);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (req == NULL) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz DEBUG(SSSDBG_FATAL_FAILURE, ("tevent_req_create() failed\n"));
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz return NULL;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz state->hostnames = NULL;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz state->ip_addr = NULL;
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley /* load info from configuration */
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley conf_hostnames = dp_opt_get_string(opts->basic, SDAP_SUDO_HOSTNAMES);
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley conf_ip_addr = dp_opt_get_string(opts->basic, SDAP_SUDO_IP);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (conf_hostnames != NULL) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz ret = split_on_separator(state, conf_hostnames, ' ', true,
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz &state->hostnames, NULL);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (ret != EOK) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz DEBUG(SSSDBG_MINOR_FAILURE,
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz ("Unable to parse hostnames [%d]: %s\n", ret, strerror(ret)));
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz goto done;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz } else {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz DEBUG(SSSDBG_CONF_SETTINGS, ("Hostnames set to: %s\n", conf_hostnames));
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (conf_ip_addr != NULL) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz ret = split_on_separator(state, conf_ip_addr, ' ', true,
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz &state->ip_addr, NULL);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (ret != EOK) {
f69b31136266022effeb1272d153c92a09de072djerenkrantz DEBUG(SSSDBG_MINOR_FAILURE,
f69b31136266022effeb1272d153c92a09de072djerenkrantz ("Unable to parse IP addresses [%d]: %s\n", ret, strerror(ret)));
f69b31136266022effeb1272d153c92a09de072djerenkrantz goto done;
f69b31136266022effeb1272d153c92a09de072djerenkrantz } else {
f69b31136266022effeb1272d153c92a09de072djerenkrantz DEBUG(SSSDBG_CONF_SETTINGS, ("IP addresses set to: %s\n", conf_ip_addr));
226b4a760e9b997415cf061bb3d979c0c31ae642jorton }
f69b31136266022effeb1272d153c92a09de072djerenkrantz }
f69b31136266022effeb1272d153c92a09de072djerenkrantz
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if IP addresses are not specified, configure it automatically */
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (state->ip_addr == NULL) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz ret = sdap_sudo_get_ip_addresses(state, &state->ip_addr);
f69b31136266022effeb1272d153c92a09de072djerenkrantz if (ret != EOK) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
f69b31136266022effeb1272d153c92a09de072djerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantzdone:
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (ret != EAGAIN) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (ret == EOK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein tevent_req_done(req);
aa552377469071a421252dab6568c204a99cf770gstein } else {
aa552377469071a421252dab6568c204a99cf770gstein tevent_req_error(req, ret);
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gstein }
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz tevent_req_post(req, be_ctx->ev);
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz }
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz return req;
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz}
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gsteinint sdap_sudo_get_hostinfo_recv(TALLOC_CTX *mem_ctx,
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gstein struct tevent_req *req,
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gstein char ***hostnames, char ***ip_addr)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
c364a517c4f0db3d0a33c662c02f2d567a33e135martin struct sdap_sudo_get_hostinfo_state *state = NULL;
c364a517c4f0db3d0a33c662c02f2d567a33e135martin state = tevent_req_data(req, struct sdap_sudo_get_hostinfo_state);
c364a517c4f0db3d0a33c662c02f2d567a33e135martin
f4c310fd2555c6faca1f980f00b161eadb089023gstein TEVENT_REQ_RETURN_ON_ERROR(req);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein *hostnames = talloc_steal(mem_ctx, state->hostnames);
aa552377469071a421252dab6568c204a99cf770gstein *ip_addr = talloc_steal(mem_ctx, state->ip_addr);
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick
aa552377469071a421252dab6568c204a99cf770gstein return EOK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
aa552377469071a421252dab6568c204a99cf770gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int sdap_sudo_get_ip_addresses(TALLOC_CTX *mem_ctx, char ***_ip_addr_list)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
aa552377469071a421252dab6568c204a99cf770gstein TALLOC_CTX *tmp_ctx = NULL;
aa552377469071a421252dab6568c204a99cf770gstein char **ip_addr_list = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein struct ifaddrs *ifaces = NULL;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz struct ifaddrs *iface = NULL;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz struct sockaddr_in *ip4_addr = NULL;
aa552377469071a421252dab6568c204a99cf770gstein struct sockaddr_in *ip4_network = NULL;
226b4a760e9b997415cf061bb3d979c0c31ae642jorton struct sockaddr_in6 *ip6_addr = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein struct sockaddr_in6 *ip6_network = NULL;
char ip_addr[INET6_ADDRSTRLEN + 1];
char network_addr[INET6_ADDRSTRLEN + 1];
in_addr_t ip4_netmask = 0;
uint32_t ip6_netmask = 0;
unsigned int netmask = 0;
void *sinx_addr = NULL;
void *sinx_network = NULL;
int addr_count = 0;
int ret;
int i;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
return ENOMEM;
}
errno = 0;
ret = getifaddrs(&ifaces);
if (ret == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE, ("Could not read interfaces [%d][%s]\n",
ret, strerror(ret)));
goto done;
}
for (iface = ifaces; iface != NULL; iface = iface->ifa_next) {
netmask = 0;
switch (iface->ifa_addr->sa_family) {
case AF_INET:
ip4_addr = (struct sockaddr_in*)(iface->ifa_addr);
ip4_network = (struct sockaddr_in*)(iface->ifa_netmask);
/* ignore loopback */
if (inet_netof(ip4_addr->sin_addr) == IN_LOOPBACKNET) {
continue;
}
/* ignore multicast */
if (IN_MULTICAST(ip4_addr->sin_addr.s_addr)) {
continue;
}
/* ignore broadcast */
if (ntohl(ip4_addr->sin_addr.s_addr) == INADDR_BROADCAST) {
continue;
}
/* get network mask length */
ip4_netmask = ntohl(ip4_network->sin_addr.s_addr);
while (ip4_netmask) {
netmask++;
ip4_netmask <<= 1;
}
/* get network address */
ip4_network->sin_addr.s_addr = ip4_addr->sin_addr.s_addr
& ip4_network->sin_addr.s_addr;
sinx_addr = &ip4_addr->sin_addr;
sinx_network = &ip4_network->sin_addr;
break;
case AF_INET6:
ip6_addr = (struct sockaddr_in6*)(iface->ifa_addr);
ip6_network = (struct sockaddr_in6*)(iface->ifa_netmask);
/* ignore loopback */
if (IN6_IS_ADDR_LOOPBACK(&ip6_addr->sin6_addr)) {
continue;
}
/* ignore multicast */
if (IN6_IS_ADDR_MULTICAST(&ip6_addr->sin6_addr)) {
continue;
}
/* get network mask length */
for (i = 0; i < 4; i++) {
ip6_netmask = ntohl(((uint32_t*)(&ip6_network->sin6_addr))[i]);
while (ip6_netmask) {
netmask++;
ip6_netmask <<= 1;
}
}
/* get network address */
for (i = 0; i < 4; i++) {
((uint32_t*)(&ip6_network->sin6_addr))[i] =
((uint32_t*)(&ip6_addr->sin6_addr))[i]
& ((uint32_t*)(&ip6_network->sin6_addr))[i];
}
sinx_addr = &ip6_addr->sin6_addr;
sinx_network = &ip6_network->sin6_addr;
break;
default:
/* skip other families */
continue;
}
/* ip address */
errno = 0;
if (inet_ntop(iface->ifa_addr->sa_family, sinx_addr,
ip_addr, INET6_ADDRSTRLEN) == NULL) {
ret = errno;
DEBUG(SSSDBG_MINOR_FAILURE, ("inet_ntop() failed [%d]: %s\n",
ret, strerror(ret)));
goto done;
}
/* network */
errno = 0;
if (inet_ntop(iface->ifa_addr->sa_family, sinx_network,
network_addr, INET6_ADDRSTRLEN) == NULL) {
ret = errno;
DEBUG(SSSDBG_MINOR_FAILURE, ("inet_ntop() failed [%d]: %s\n",
ret, strerror(ret)));
goto done;
}
addr_count += 2;
ip_addr_list = talloc_realloc(tmp_ctx, ip_addr_list, char*,
addr_count + 1);
if (ip_addr_list == NULL) {
ret = ENOMEM;
goto done;
}
ip_addr_list[addr_count - 2] = talloc_strdup(ip_addr_list, ip_addr);
if (ip_addr_list[addr_count - 2] == NULL) {
ret = ENOMEM;
goto done;
}
ip_addr_list[addr_count - 1] = talloc_asprintf(ip_addr_list, "%s/%d",
network_addr, netmask);
if (ip_addr_list[addr_count - 1] == NULL) {
ret = ENOMEM;
goto done;
}
DEBUG(SSSDBG_TRACE_INTERNAL,
("Found IP address: %s in network %s/%d\n",
ip_addr, network_addr, netmask));
}
ip_addr_list[addr_count] = NULL;
*_ip_addr_list = talloc_steal(mem_ctx, ip_addr_list);
done:
freeifaddrs(ifaces);
talloc_free(tmp_ctx);
return ret;
}