summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/backend.c23
-rw-r--r--src/dispatch.c160
-rw-r--r--src/dispatch.h2
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