From 6a7eee414104783977c9f1459190742977eae254 Mon Sep 17 00:00:00 2001 From: Leonardo Arena Date: Thu, 4 Sep 2014 09:20:41 +0000 Subject: main/openldap: add an MQTT overlay --- main/openldap/APKBUILD | 25 +- main/openldap/openldap-mqtt-overlay.patch | 447 ++++++++++++++++++++++++++++++ 2 files changed, 470 insertions(+), 2 deletions(-) create mode 100644 main/openldap/openldap-mqtt-overlay.patch (limited to 'main') diff --git a/main/openldap/APKBUILD b/main/openldap/APKBUILD index 89d07d911..e02002278 100644 --- a/main/openldap/APKBUILD +++ b/main/openldap/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa pkgname=openldap pkgver=2.4.39 -pkgrel=0 +pkgrel=1 pkgdesc="LDAP Server" url="http://www.openldap.org/" arch="all" @@ -13,13 +13,16 @@ depends_dev="openssl-dev cyrus-sasl-dev util-linux-dev" makedepends="$depends_dev db-dev groff unixodbc-dev libtool" subpackages="$pkgname-dev $pkgname-doc libldap $pkgname-back-sql:sql $pkgname-back-bdb:bdb $pkgname-back-hdb:hdb $pkgname-back-ldap:ldap - $pkgname-back-meta:meta $pkgname-back-monitor:monitor $pkgname-clients" + $pkgname-back-meta:meta $pkgname-back-monitor:monitor $pkgname-clients + $pkgname-mqtt + " install="$pkgname.pre-install" source="ftp://ftp.$pkgname.org/pub/OpenLDAP/$pkgname-release/$pkgname-$pkgver.tgz openldap-2.4-ppolicy.patch openldap-2.4.11-libldap_r.patch 0001-dbd-enabled-by-default.patch + openldap-mqtt-overlay.patch slapd.initd slapd.confd slurpd.initd @@ -71,6 +74,10 @@ build () { || return 1 make || return 1 + + #build mqtt overlay + cd contrib/slapd-modules/mqtt + make prefix=/usr libexec=/usr/lib } package() { @@ -100,6 +107,11 @@ package() { install -Dm755 "$srcdir"/slurpd.initd "$pkgdir"/etc/init.d/slurpd # FIXME: symlinks in sbin are symlinked to /usr/lib/slapd ln -s /usr/sbin/slapd "$pkgdir"/usr/lib/slapd + + #install mqtt overlay + cd contrib/slapd-modules/mqtt + make DESTDIR="$pkgdir" prefix=/usr libexec=/usr/lib install || return 1 + find "$pkgdir" -iname *.la -delete } libldap() { @@ -130,11 +142,18 @@ clients() { mv "$pkgdir"/usr/bin "$subpkgdir"/usr/ } +mqtt() { + pkgdesc="OpenLDAP MQTT overlay" + depends=$pkgname + mkdir -p "$subpkgdir"/usr/lib/openldap + mv "$pkgdir"/usr/lib/openldap/mqtt.* "$subpkgdir"/usr/lib/openldap +} md5sums="b0d5ee4b252c841dec6b332d679cf943 openldap-2.4.39.tgz 2524e490ba334a760fa57057c16da7a9 openldap-2.4-ppolicy.patch d19d0502f046078ecd737e29e7552fa8 openldap-2.4.11-libldap_r.patch 7b4eec9a90d2f7f727e0f9cb4653887c 0001-dbd-enabled-by-default.patch +4982de0e6e060c54f8159f213ea09305 openldap-mqtt-overlay.patch 41d45b9ed59037dcdf640e395ace113c slapd.initd b672311fca605c398240cd37a2ae080a slapd.confd fa5ce0005ef5f1160b6ff126f97aaa1a slurpd.initd" @@ -142,6 +161,7 @@ sha256sums="8267c87347103fef56b783b24877c0feda1063d3cb85d070e503d076584bf8a7 op 355a8239355fcc5863ba7430d73af7ccad9e0211ae56180011d15d7418aa5b27 openldap-2.4-ppolicy.patch 3310a89d38bc39e6eb4333799d475411b274482b8bccab212b3edfd4385db70e openldap-2.4.11-libldap_r.patch 8d1ee24c52928302acb876bc99cc75757eb15b278a10bfd3d43cabb332bcd3c4 0001-dbd-enabled-by-default.patch +45a01923d837a1361a9f94cd28e058267eb2e61014732e4131de091f651bce50 openldap-mqtt-overlay.patch 726efdbaceb1b907bb085b7996222a0bc83610730c5d6b9646b062e09f2ef964 slapd.initd 1ccb8a3b78b65b125b24779dd065cf8000e2d5e4da267bb0a892e730edd2055d slapd.confd 9cfe54485585a1bd74dd167c27ad9e60a5dec7351b6a64804749f253bb6cfbad slurpd.initd" @@ -149,6 +169,7 @@ sha512sums="7b5ef2a69f79f0901a06f8be4ab50afc3b3e98ab1ea74a421569443d32cb43d3cf77 5d34d49eabe7cb66cf8284cc3bd9730fa23df4932df68549e242d250ee50d40c434ae074ebc720d5fbcd9d16587c9333c5598d30a5f1177caa61461ab7771f38 openldap-2.4-ppolicy.patch 44d97efb25d4f39ab10cd5571db43f3bfa7c617a5bb087085ae16c0298aca899b55c8742a502121ba743a73e6d77cd2056bc96cee63d6d0862dabc8fb5574357 openldap-2.4.11-libldap_r.patch b0892e049feab931d6439374ecf2497c54fbf46daef622f9949f02a26cd4b20f73de7cff1e1d64894539dc599793ffbd61d7a5bba6e026f3966295cf6a39f1be 0001-dbd-enabled-by-default.patch +7383aafcddad9ed6583014e450517808257b486fc97c3ef16100bbcc0267182ad3dd4f062888ae1804cf08ce6702134fa3f6ee6a3ebc06b71eef5b5301db319b openldap-mqtt-overlay.patch 723fb2546ac8a3672240139d4b7ec5041be961990fd8385171a53c737436d6307dc05671fcd190dd5e3b3ee21967a2a632ec8852fe84519fdea0c7f535c598ee slapd.initd 8290769b63b3a5863622de2deb9269a0711ba5f4a225eb230d7c5097937b9d4e8cf5a998ee99232824e2335ae1b6e0114357b61c9611bc2460ebd195d12eabae slapd.confd 69ee0d739d8c8c1cb2478d5c864f703cba215d0ceb399da941c0ebc91e7de87a4d99172670686a84a98e57bde94837777a8066d27f79b6b8bf4bcd72336ce775 slurpd.initd" diff --git a/main/openldap/openldap-mqtt-overlay.patch b/main/openldap/openldap-mqtt-overlay.patch new file mode 100644 index 000000000..47f31256f --- /dev/null +++ b/main/openldap/openldap-mqtt-overlay.patch @@ -0,0 +1,447 @@ +diff --git a/contrib/slapd-modules/mqtt/Makefile b/contrib/slapd-modules/mqtt/Makefile +new file mode 100644 +index 0000000..2cb4db7 +--- /dev/null ++++ b/contrib/slapd-modules/mqtt/Makefile +@@ -0,0 +1,45 @@ ++# $OpenLDAP$ ++ ++LDAP_SRC = ../../.. ++LDAP_BUILD = ../../.. ++LDAP_INC = -I$(LDAP_BUILD)/include -I$(LDAP_SRC)/include -I$(LDAP_SRC)/servers/slapd ++LDAP_LIB = $(LDAP_BUILD)/libraries/libldap_r/libldap_r.la \ ++ $(LDAP_BUILD)/libraries/liblber/liblber.la ++ ++LIBTOOL = $(LDAP_BUILD)/libtool ++CC = gcc ++OPT = -g -O2 -Wall ++DEFS = ++INCS = $(LDAP_INC) ++LIBS = $(LDAP_LIB) -lmosquitto ++ ++PROGRAMS = mqtt.la ++LTVER = 0:0:0 ++ ++prefix=/usr/local ++exec_prefix=$(prefix) ++ldap_subdir=/openldap ++ ++libdir=$(exec_prefix)/lib ++libexecdir=$(exec_prefix)/libexec ++moduledir = $(libdir)$(ldap_subdir) ++ ++.SUFFIXES: .c .o .lo ++ ++.c.lo: ++ $(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(INCS) -c $< ++ ++all: $(PROGRAMS) ++ ++mqtt.la: mqtt.lo ++ $(LIBTOOL) --mode=link $(CC) $(OPT) -version-info $(LTVER) \ ++ -rpath $(moduledir) -module -o $@ $? $(LIBS) ++ ++clean: ++ rm -rf *.o *.lo *.la .libs ++ ++install: $(PROGRAMS) ++ mkdir -p $(DESTDIR)$(moduledir) ++ for p in $(PROGRAMS) ; do \ ++ $(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(moduledir) ; \ ++ done +diff --git a/contrib/slapd-modules/mqtt/mqtt.c b/contrib/slapd-modules/mqtt/mqtt.c +new file mode 100644 +index 0000000..b3a0a31 +--- /dev/null ++++ b/contrib/slapd-modules/mqtt/mqtt.c +@@ -0,0 +1,389 @@ ++/* $OpenLDAP$ */ ++/* This work is part of OpenLDAP Software . ++ * ++ * Copyright 2014 Timo Teräs . ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted only as authorized by the OpenLDAP ++ * Public License. ++ * ++ * A copy of this license is available in file LICENSE in the ++ * top-level directory of the distribution or, alternatively, at ++ * http://www.OpenLDAP.org/license.html. ++ */ ++/* mqtt-overlay ++ * ++ * This is an OpenLDAP overlay that... */ ++ ++#include ++#include ++ ++#include "portable.h" ++#include "slap.h" ++#include "config.h" ++ ++typedef struct mqtt_notify_t { ++ struct mqtt_notify_t *next; ++ char *topic; ++ char *dn_group_str; ++ char *oc_group_str; ++ char *str_member; ++ ++ struct berval ndn_group; ++ ObjectClass *oc_group; ++ AttributeDescription *ad_member; ++ int notify_pending; ++} mqtt_notify_t; ++ ++typedef struct mqtt_t { ++ struct mosquitto *mq; ++ int port; ++ char *hostname, *username, *password; ++ mqtt_notify_t *notify_map; ++} mqtt_t; ++ ++static ConfigDriver mqtt_config_notify; ++ ++static ConfigTable mqttcfg[] = { ++ { "mqtt-hostname", "hostname", 2, 2, 0, ++ ARG_STRING|ARG_OFFSET, (void *)offsetof(mqtt_t, hostname), ++ "( OLcfgCtAt:5.1 NAME 'olcMqttHostname' " ++ "DESC 'Hostname of MQTT broker' " ++ "SYNTAX OMsDirectoryString SINGLE-VALUE )", ++ NULL, NULL }, ++ { "mqtt-port", "port", 2, 2, 0, ++ ARG_INT|ARG_OFFSET, (void *)offsetof(mqtt_t, port), ++ "( OLcfgCtAt:5.2 NAME 'olcMqttPort' " ++ "DESC 'Port of MQTT broker' " ++ "SYNTAX OMsInteger SINGLE-VALUE )", ++ NULL, NULL }, ++ { "mqtt-username", "username", 2, 2, 0, ++ ARG_STRING|ARG_OFFSET, (void *)offsetof(mqtt_t, username), ++ "( OLcfgCtAt:5.3 NAME 'olcMqttUsername' " ++ "DESC 'Username for MQTT broker' " ++ "SYNTAX OMsDirectoryString SINGLE-VALUE )", ++ NULL, NULL }, ++ { "mqtt-password", "password", 2, 2, 0, ++ ARG_STRING|ARG_OFFSET, (void *)offsetof(mqtt_t, password), ++ "( OLcfgCtAt:5.4 NAME 'olcMqttPassword' " ++ "DESC 'Password for MQTT broker' " ++ "SYNTAX OMsDirectoryString SINGLE-VALUE )", ++ NULL, NULL }, ++ { "mqtt-notify-password", "topic> , optionally checking that the object is in the specified group.'" ++ "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", ++ NULL, NULL }, ++ { NULL, NULL, 0, 0, 0, ARG_IGNORED } ++}; ++ ++static ConfigOCs mqttocs[] = { ++ { "( OLcfgCtOc:5.1 " ++ "NAME 'olcMqttConfig' " ++ "DESC 'MQTT configuration' " ++ "SUP olcOverlayConfig " ++ "MAY ( " ++ "olcMqttHostname " ++ "$ olcMqttPort" ++ "$ olcMqttUsername" ++ "$ olcMqttPassword" ++ "$ olcMqttNotifyPassword" ++ " ) )", ++ Cft_Overlay, mqttcfg }, ++ ++ { NULL, 0, NULL } ++}; ++ ++static int mqtt_init(BackendInfo *bi) ++{ ++ return mosquitto_lib_init(); ++} ++ ++static int mqtt_destroy(BackendInfo *bi) ++{ ++ return mosquitto_lib_cleanup(); ++} ++ ++static const char *ca_arg(ConfigArgs *c, int n) ++{ ++ return (c->argc <= n) ? NULL : c->argv[n]; ++} ++ ++static void free_notify(mqtt_notify_t *n) ++{ ++ ch_free(n->topic); ++ ch_free(n->oc_group_str); ++ ch_free(n->str_member); ++ ch_free(n->dn_group_str); ++ if (!BER_BVISNULL(&n->ndn_group)) ++ ber_memfree(n->ndn_group.bv_val); ++ ch_free(n); ++} ++ ++static void free_all_notifies(mqtt_t *mqtt) ++{ ++ mqtt_notify_t *n, *next; ++ ++ for (n = mqtt->notify_map; n; n = next) { ++ next = n->next; ++ free_notify(n); ++ } ++ mqtt->notify_map = NULL; ++} ++ ++static int mqtt_config_notify(ConfigArgs *c) ++{ ++ slap_overinst *on = (slap_overinst *)c->bi; ++ mqtt_t *mqtt = (mqtt_t *) on->on_bi.bi_private; ++ mqtt_notify_t *n, **pprev; ++ const char *text = NULL; ++ struct berval bv = BER_BVNULL, ndn = BER_BVNULL; ++ int rc, i; ++ ++ switch (c->op) { ++ case SLAP_CONFIG_EMIT: ++ for (i = 0, n = mqtt->notify_map; n; n = n->next, i++) { ++ char *ptr = c->cr_msg, *end = &c->cr_msg[sizeof(c->cr_msg)-1]; ++ ++ ptr += snprintf(ptr, end-ptr, SLAP_X_ORDERED_FMT "%s", i, n->topic); ++ if (n->dn_group_str) ++ ptr += snprintf(ptr, end-ptr, " \"%s\"", n->dn_group_str); ++ if (n->oc_group_str) ++ ptr += snprintf(ptr, end-ptr, " \"%s\"", n->oc_group_str); ++ if (n->str_member) ++ ptr += snprintf(ptr, end-ptr, " \"%s\"", n->str_member); ++ ++ bv.bv_val = c->cr_msg; ++ bv.bv_len = ptr - bv.bv_val; ++ value_add_one(&c->rvalue_vals, &bv); ++ } ++ return 0; ++ case LDAP_MOD_DELETE: ++ if (c->valx < 0) { ++ free_all_notifies(mqtt); ++ } else { ++ pprev = &mqtt->notify_map; ++ n = mqtt->notify_map; ++ for (i = 0; i < c->valx; i++) { ++ pprev = &n->next; ++ n = n->next; ++ } ++ *pprev = n->next; ++ free_notify(n); ++ } ++ return 0; ++ } ++ ++ const char *groupdn = ca_arg(c, 2); ++ const char *oc_name = ca_arg(c, 3); ++ const char *ad_name = ca_arg(c, 4); ++ ObjectClass *oc = NULL; ++ AttributeDescription *ad = NULL; ++ ++ if (groupdn) { ++ oc = oc_find(oc_name ?: SLAPD_GROUP_CLASS); ++ if (oc == NULL) { ++ Debug(LDAP_DEBUG_ANY, "mqtt_db_open: unable to find objectClass=\"%s\"\n", ++ oc_name, 0, 0); ++ return 1; ++ } ++ ++ rc = slap_str2ad(ad_name ?: SLAPD_GROUP_ATTR, &ad, &text); ++ if (rc != LDAP_SUCCESS) { ++ Debug(LDAP_DEBUG_ANY, "mqtt_db_config_notify: unable to find attribute=\"%s\": %s (%d)\n", ++ ad_name, text, rc); ++ return rc; ++ } ++ ++ ber_str2bv(groupdn, 0, 0, &bv); ++ rc = dnNormalize(0, NULL, NULL, &bv, &ndn, NULL); ++ if (rc != LDAP_SUCCESS) { ++ Debug(LDAP_DEBUG_ANY, "mqtt_db_config_notify: DN normalization failed for \"%s\": %d\n", ++ groupdn, rc, 0); ++ return rc; ++ } ++ } ++ ++ n = ch_calloc(1, sizeof(*n)); ++ n->topic = ch_strdup(c->argv[1]); ++ n->dn_group_str = groupdn ? ch_strdup(groupdn) : NULL; ++ n->oc_group_str = oc_name ? ch_strdup(oc_name) : NULL; ++ n->str_member = ad_name ? ch_strdup(ad_name) : NULL; ++ n->ndn_group = ndn; ++ n->oc_group = oc; ++ n->ad_member = ad; ++ ++ for (pprev = &mqtt->notify_map; *pprev; pprev = &(*pprev)->next); ++ *pprev = n; ++ ++ return 0; ++} ++ ++static void mqtt_send_notify(mqtt_t *mqtt, mqtt_notify_t *n) ++{ ++ Debug(LDAP_DEBUG_TRACE, "mqtt_send_notify: pub on topic '%s'\n", n->topic, 0, 0); ++ n->notify_pending = mosquitto_publish(mqtt->mq, NULL, n->topic, 0, NULL, 1, false) == MOSQ_ERR_NO_CONN; ++} ++ ++static void mqtt_on_connect(struct mosquitto *mq, void *obj, int rc) ++{ ++ slap_overinst *on = (slap_overinst *) obj; ++ mqtt_t *mqtt = (mqtt_t *) on->on_bi.bi_private; ++ mqtt_notify_t *n; ++ ++ Debug(LDAP_DEBUG_TRACE, "mqtt_on_connect: connected with status %d\n", rc, 0, 0); ++ if (rc != 0) ++ return; ++ ++ for (n = mqtt->notify_map; n; n = n->next) ++ if (n->notify_pending) ++ mqtt_send_notify(mqtt, n); ++} ++ ++static int mqtt_db_init(BackendDB *be, ConfigReply *cr) ++{ ++ slap_overinst *on = (slap_overinst *) be->bd_info; ++ ++ Debug(LDAP_DEBUG_TRACE, "mqtt_db_init: initialize overlay\n", 0, 0, 0); ++ on->on_bi.bi_private = ch_calloc(1, sizeof(mqtt_t)); ++ ++ return 0; ++} ++ ++static int mqtt_db_destroy(BackendDB *be, ConfigReply *cr) ++{ ++ slap_overinst *on = (slap_overinst *) be->bd_info; ++ mqtt_t *mqtt = on->on_bi.bi_private; ++ ++ Debug(LDAP_DEBUG_TRACE, "mqtt_db_destroy: destroy overlay\n", 0, 0, 0); ++ free_all_notifies(mqtt); ++ ch_free(mqtt); ++ ++ return 0; ++} ++ ++static int mqtt_db_open(BackendDB *be, ConfigReply *cr) ++{ ++ slap_overinst *on = (slap_overinst *) be->bd_info; ++ mqtt_t *mqtt = (mqtt_t *) on->on_bi.bi_private; ++ struct mosquitto *mq; ++ char id[256]; ++ int n; ++ ++ n = snprintf(id, sizeof(id), "openldap-mqtt/%d/", getpid()); ++ gethostname(&id[n], sizeof(id) - n); ++ ++ Debug(LDAP_DEBUG_TRACE, "mqtt_db_open, id='%s'\n", id, 0, 0); ++ mqtt->mq = mq = mosquitto_new(id, true, on); ++ if (!mq) return 1; ++ ++ if (mqtt->username && mqtt->password) ++ mosquitto_username_pw_set(mq, mqtt->username, mqtt->password); ++ ++ mosquitto_connect_callback_set(mq, mqtt_on_connect); ++ mosquitto_connect_async(mq, mqtt->hostname ?: "127.0.0.1", mqtt->port ?: 1883, 60); ++ mosquitto_loop_start(mq); ++ ++ return 0; ++} ++ ++static int mqtt_db_close(BackendDB *be, ConfigReply *cr) ++{ ++ slap_overinst *on = (slap_overinst *) be->bd_info; ++ mqtt_t *mqtt = (mqtt_t *) on->on_bi.bi_private; ++ ++ Debug(LDAP_DEBUG_TRACE, "mqtt_db_close\n", 0, 0, 0); ++ mosquitto_disconnect(mqtt->mq); ++ mosquitto_loop_stop(mqtt->mq, false); ++ mosquitto_destroy(mqtt->mq); ++ ++ free(mqtt->hostname); mqtt->hostname = NULL; ++ free(mqtt->username); mqtt->username = NULL; ++ free(mqtt->password); mqtt->password = NULL; ++ ++ return 0; ++} ++ ++static int mqtt_response(Operation *op, SlapReply *rs) ++{ ++ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; ++ mqtt_t *mqtt = (mqtt_t *) on->on_bi.bi_private; ++ Attribute *a; ++ Modifications *m; ++ bool change = false; ++ ++ switch (op->o_tag) { ++ case LDAP_REQ_ADD: ++ for (a = op->ora_e->e_attrs; a; a = a->a_next) { ++ if (a->a_desc == slap_schema.si_ad_userPassword) { ++ change = true; ++ break; ++ } ++ } ++ break; ++ case LDAP_REQ_MODIFY: ++ for (m = op->orm_modlist; m; m = m->sml_next) { ++ if (m->sml_desc == slap_schema.si_ad_userPassword) { ++ change = true; ++ break; ++ } ++ } ++ break; ++ case LDAP_REQ_EXTENDED: ++ if (ber_bvcmp(&slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid) == 0) ++ change = true; ++ break; ++ } ++ ++ if (change) { ++ mqtt_notify_t *n; ++ int r, cache; ++ ++ for (n = mqtt->notify_map; n; n = n->next) { ++ if (n->oc_group) { ++ cache = op->o_do_not_cache; ++ op->o_do_not_cache = 1; ++ r = backend_group(op, NULL, &n->ndn_group, &op->o_req_ndn, n->oc_group, n->ad_member); ++ op->o_do_not_cache = cache; ++ } else { ++ r = 0; ++ } ++ ++ Debug(LDAP_DEBUG_TRACE, "tested o_req_ndn='%s' in ndn_group='%s' r=%d\n", ++ op->o_req_ndn.bv_val, n->ndn_group.bv_val, r); ++ ++ if (r == 0) ++ mqtt_send_notify(mqtt, n); ++ } ++ } ++ ++ return SLAP_CB_CONTINUE; ++} ++ ++static int mqtt_init_overlay() ++{ ++ static slap_overinst ov; ++ int rc; ++ ++ ov.on_bi.bi_type = "mqtt"; ++ ov.on_bi.bi_init = mqtt_init; ++ ov.on_bi.bi_destroy = mqtt_destroy; ++ ov.on_bi.bi_db_init = mqtt_db_init; ++ ov.on_bi.bi_db_destroy = mqtt_db_destroy; ++ ov.on_bi.bi_db_open = mqtt_db_open; ++ ov.on_bi.bi_db_close = mqtt_db_close; ++ ov.on_bi.bi_cf_ocs = mqttocs; ++ ov.on_response = mqtt_response; ++ ++ rc = config_register_schema(mqttcfg, mqttocs); ++ if (rc) return rc; ++ ++ return overlay_register(&ov); ++} ++ ++int init_module(int argc, char *argv[]) ++{ ++ return mqtt_init_overlay(); ++} + -- cgit v1.2.3