diff options
-rw-r--r-- | src/backend.c | 23 | ||||
-rw-r--r-- | src/dispatch.c | 160 | ||||
-rw-r--r-- | src/dispatch.h | 2 |
3 files changed, 180 insertions, 5 deletions
diff --git a/src/backend.c b/src/backend.c index 2f87b2d..264fe5d 100644 --- a/src/backend.c +++ b/src/backend.c @@ -45,6 +45,7 @@ #include "backend.h" #include "defaults.h" +#include "dispatch.h" #include "format.h" #include "plugin.h" #include "map.h" @@ -614,6 +615,7 @@ backend_read_params(struct plugin_state *state) char *attrs[] = { PLUGIN_CONFIGURATION_MAXVALUE_ATTR, PLUGIN_CONFIGURATION_MAXDGRAM_ATTR, + PLUGIN_CONFIGURATION_PORT_ATTR, PLUGIN_CONFIGURATION_SECURENET_ATTR, PLUGIN_CONFIGURATION_TCPWRAPNAME_ATTR, NULL, @@ -677,13 +679,16 @@ backend_read_params(struct plugin_state *state) "size %u\n", state->max_dgram_size); break; - case 2: /* securenet entry */ + case 3: /* securenet entry */ + dispatch_securenets_clear(state); while (j != -1) { - /* XXX */ + cvalue = slapi_value_get_string(value); + dispatch_securenets_add(state, + cvalue); j = slapi_valueset_next_value(values, j, &value); } break; - case 3: /* tcp-wrappers name */ + case 4: /* tcp-wrappers name */ #ifdef HAVE_TCPD_H cvalue = slapi_value_get_string(value); request_set(state->request_info, @@ -1314,6 +1319,7 @@ backend_modify_entry_cb(const char *domain, const char *map, void *backend_data, static int backend_modify_cb(Slapi_PBlock *pb) { + Slapi_DN *sdn; struct backend_modify_entry_cbdata cbdata; slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state); slapi_pblock_get(pb, SLAPI_MODIFY_TARGET, &cbdata.ndn); @@ -1368,6 +1374,17 @@ backend_modify_cb(Slapi_PBlock *pb) cbdata.ndn); backend_map_config_entry_add_cb(cbdata.e_post, cbdata.state); } + /* Lastly, if the entry is our own entry, re-read parameters. */ + sdn = slapi_sdn_new_dn_byref(cbdata.state->plugin_base); + if (sdn != NULL) { + if ((strcmp(slapi_entry_get_ndn(cbdata.e_pre), + slapi_sdn_get_ndn(sdn)) == 0) || + (strcmp(slapi_entry_get_ndn(cbdata.e_post), + slapi_sdn_get_ndn(sdn)) == 0)) { + backend_read_params(cbdata.state); + } + slapi_sdn_free(&sdn); + } map_unlock(); return 0; } diff --git a/src/dispatch.c b/src/dispatch.c index 1bbdea8..2cda7ab 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -103,12 +103,168 @@ struct dispatch_client_data { } dgram; }; +struct securenet_info { + int sn_family; + union { + struct { + struct in_addr address, netmask; + } sin; + struct { + struct in6_addr address, netmask; + } sin6; + } sn_addr; + struct securenet_info *sn_next; +}; + /* Perform securenets access control. */ +void +dispatch_securenets_clear(struct plugin_state *state) +{ + struct securenet_info *sn, *next; + next = state->securenet_info; + while (next != NULL) { + sn = next; + next = sn->sn_next; + free(sn); + } + state->securenet_info = NULL; + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "cleared securenets access list\n"); +} +void +dispatch_securenets_add(struct plugin_state *state, const char *value) +{ + struct securenet_info *sn; + const char *p, *q; + char *tmp; + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "adding securenets access entry \"%s\"\n", value); + sn = malloc(sizeof(*sn)); + if (sn == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "out of memory parsing securenets entry " + "\"%s\"\n", value); + return; + } + tmp = strdup(value); + if (tmp == NULL) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "out of memory parsing securenets entry " + "\"%s\"\n", value); + free(sn); + return; + } + + /* Pull out the first token. */ + p = value + strspn(value, " \t"); + q = p + strcspn(p, " \t"); + strncpy(tmp, p, q - p); + tmp[q - p] = '\0'; + + /* Try to parse it. */ + sn->sn_family = AF_UNSPEC; + if (inet_pton(AF_INET, tmp, &sn->sn_addr.sin.netmask) > 0) { + sn->sn_family = AF_INET; + } else { + if (inet_pton(AF_INET6, tmp, &sn->sn_addr.sin6.netmask) > 0) { + sn->sn_family = AF_INET6; + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "error parsing \"%s\" as an address, " + "ignoring\n", tmp); + } + } + if (sn->sn_family == AF_UNSPEC) { + free(tmp); + free(sn); + return; + } + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "parsed netmask(?) \"%s\" family=%d\n", tmp, + sn->sn_family); + + /* Pull out the second token. */ + p = q + strspn(q, " \t"); + q = p + strcspn(p, " \t#"); + strncpy(tmp, p, q - p); + tmp[q - p] = '\0'; + switch (sn->sn_family) { + case AF_INET: + if (inet_pton(AF_INET, tmp, &sn->sn_addr.sin.address) <= 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "error parsing %s as an IPv4 address, " + "ignoring\n", tmp); + sn->sn_family = AF_UNSPEC; + } + break; + case AF_INET6: + if (inet_pton(AF_INET6, tmp, &sn->sn_addr.sin6.address) <= 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "error parsing %s as an IPv6 address, " + "ignoring\n", tmp); + sn->sn_family = AF_UNSPEC; + } + break; + default: + break; + } + + if (sn->sn_family == AF_UNSPEC) { + free(sn); + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "parsed address \"%s\" family=%d\n", tmp, + sn->sn_family); + sn->sn_next = state->securenet_info; + state->securenet_info = sn; + } + + free(tmp); +} static bool_t dispatch_access(struct plugin_state *state, struct sockaddr *client_addr) { - /* XXX */ - return TRUE; + struct securenet_info *sn; + struct in_addr addr; + struct in6_addr addr6; + for (sn = state->securenet_info; sn != NULL; sn = sn->sn_next) { + switch (client_addr->sa_family) { + case AF_INET: + if (sn->sn_family != AF_INET) { + continue; + } + addr = ((struct sockaddr_in*) client_addr)->sin_addr; + if ((addr.s_addr & + sn->sn_addr.sin.netmask.s_addr) == + (sn->sn_addr.sin.address.s_addr & + sn->sn_addr.sin.netmask.s_addr)) { + return TRUE; + } + break; + case AF_INET6: + addr6 = ((struct sockaddr_in6*) client_addr)->sin6_addr; + if ((sn->sn_family == AF_INET) && + IN6_IS_ADDR_V4MAPPED(&addr6)) { + if ((((uint32_t*)addr6.s6_addr)[3] & + sn->sn_addr.sin.netmask.s_addr) == + (sn->sn_addr.sin.address.s_addr & + sn->sn_addr.sin.netmask.s_addr)) { + return TRUE; + } + } + break; + default: + break; + } + } + return state->securenet_info ? FALSE : TRUE; } /* Send a reply, unbuffered datagram version. */ diff --git a/src/dispatch.h b/src/dispatch.h index 86af859..ca94404 100644 --- a/src/dispatch.h +++ b/src/dispatch.h @@ -33,4 +33,6 @@ typedef bool_t (dispatch_reply_fragment)(struct plugin_state *state, typedef void (dispatch_reply)(struct plugin_state *state, struct dispatch_client_data *cdata, struct rpc_msg *reply, XDR *reply_xdrs); +void dispatch_securenets_clear(struct plugin_state *state); +void dispatch_securenets_add(struct plugin_state *state, const char *value); #endif |