summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c
diff options
context:
space:
mode:
Diffstat (limited to 'pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c')
-rw-r--r--pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c369
1 files changed, 369 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c
new file mode 100644
index 0000000..1c732db
--- /dev/null
+++ b/pigeonhole/src/lib-sieve/storage/ldap/sieve-ldap-script.c
@@ -0,0 +1,369 @@
+/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "time-util.h"
+#include "istream.h"
+
+#include "sieve-ldap-storage.h"
+
+#if defined(SIEVE_BUILTIN_LDAP) || defined(PLUGIN_BUILD)
+
+#include "str.h"
+#include "strfuncs.h"
+
+#include "sieve-error.h"
+#include "sieve-dump.h"
+#include "sieve-binary.h"
+
+/*
+ * Script file implementation
+ */
+
+static struct sieve_ldap_script *sieve_ldap_script_alloc(void)
+{
+ struct sieve_ldap_script *lscript;
+ pool_t pool;
+
+ pool = pool_alloconly_create("sieve_ldap_script", 1024);
+ lscript = p_new(pool, struct sieve_ldap_script, 1);
+ lscript->script = sieve_ldap_script;
+ lscript->script.pool = pool;
+
+ return lscript;
+}
+
+struct sieve_ldap_script *sieve_ldap_script_init
+(struct sieve_ldap_storage *lstorage, const char *name)
+{
+ struct sieve_storage *storage = &lstorage->storage;
+ struct sieve_ldap_script *lscript = NULL;
+ const char *location;
+
+ if ( name == NULL ) {
+ name = SIEVE_LDAP_SCRIPT_DEFAULT;
+ location = storage->location;
+ } else {
+ location = t_strconcat
+ (storage->location, ";name=", name, NULL);
+ }
+
+ lscript = sieve_ldap_script_alloc();
+ sieve_script_init(&lscript->script,
+ storage, &sieve_ldap_script, location, name);
+ return lscript;
+}
+
+static int sieve_ldap_script_open
+(struct sieve_script *script, enum sieve_error *error_r)
+{
+ struct sieve_ldap_script *lscript =
+ (struct sieve_ldap_script *)script;
+ struct sieve_storage *storage = script->storage;
+ struct sieve_ldap_storage *lstorage =
+ (struct sieve_ldap_storage *)storage;
+ int ret;
+
+ if ( sieve_ldap_db_connect(lstorage->conn) < 0 ) {
+ sieve_storage_set_critical(storage,
+ "Failed to connect to LDAP database");
+ *error_r = storage->error_code;
+ return -1;
+ }
+
+ if ( (ret=sieve_ldap_db_lookup_script(lstorage->conn,
+ script->name, &lscript->dn, &lscript->modattr)) <= 0 ) {
+ if ( ret == 0 ) {
+ e_debug(script->event, "Script entry not found");
+ sieve_script_set_error(script,
+ SIEVE_ERROR_NOT_FOUND,
+ "Sieve script not found");
+ } else {
+ sieve_script_set_internal_error(script);
+ }
+ *error_r = script->storage->error_code;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int sieve_ldap_script_get_stream
+(struct sieve_script *script, struct istream **stream_r,
+ enum sieve_error *error_r)
+{
+ struct sieve_ldap_script *lscript =
+ (struct sieve_ldap_script *)script;
+ struct sieve_storage *storage = script->storage;
+ struct sieve_ldap_storage *lstorage =
+ (struct sieve_ldap_storage *)storage;
+ int ret;
+
+ i_assert(lscript->dn != NULL);
+
+ if ( (ret=sieve_ldap_db_read_script(
+ lstorage->conn, lscript->dn, stream_r)) <= 0 ) {
+ if ( ret == 0 ) {
+ e_debug(script->event, "Script attribute not found");
+ sieve_script_set_error(script,
+ SIEVE_ERROR_NOT_FOUND,
+ "Sieve script not found");
+ } else {
+ sieve_script_set_internal_error(script);
+ }
+ *error_r = script->storage->error_code;
+ return -1;
+ }
+ return 0;
+}
+
+static int sieve_ldap_script_binary_read_metadata
+(struct sieve_script *script, struct sieve_binary_block *sblock,
+ sieve_size_t *offset)
+{
+ struct sieve_ldap_script *lscript =
+ (struct sieve_ldap_script *)script;
+ struct sieve_instance *svinst = script->storage->svinst;
+ struct sieve_ldap_storage *lstorage =
+ (struct sieve_ldap_storage *)script->storage;
+ struct sieve_binary *sbin =
+ sieve_binary_block_get_binary(sblock);
+ time_t bmtime = sieve_binary_mtime(sbin);
+ string_t *dn, *modattr;
+
+ /* config file changed? */
+ if ( bmtime <= lstorage->set_mtime ) {
+ if ( svinst->debug ) {
+ e_debug(script->event,
+ "Sieve binary `%s' is not newer "
+ "than the LDAP configuration `%s' (%s <= %s)",
+ sieve_binary_path(sbin), lstorage->config_file,
+ t_strflocaltime("%Y-%m-%d %H:%M:%S", bmtime),
+ t_strflocaltime("%Y-%m-%d %H:%M:%S", lstorage->set_mtime));
+ }
+ return 0;
+ }
+
+ /* open script if not open already */
+ if ( lscript->dn == NULL &&
+ sieve_script_open(script, NULL) < 0 )
+ return 0;
+
+ /* if modattr not found, recompile always */
+ if ( lscript->modattr == NULL || *lscript->modattr == '\0' ) {
+ e_error(script->event,
+ "LDAP entry for script `%s' "
+ "has no modified attribute `%s'",
+ sieve_script_location(script),
+ lstorage->set.sieve_ldap_mod_attr);
+ return 0;
+ }
+
+ /* compare DN in binary and from search result */
+ if ( !sieve_binary_read_string(sblock, offset, &dn) ) {
+ e_error(script->event,
+ "Binary `%s' has invalid metadata for script `%s': "
+ "Invalid DN",
+ sieve_binary_path(sbin), sieve_script_location(script));
+ return -1;
+ }
+ i_assert( lscript->dn != NULL );
+ if ( strcmp(str_c(dn), lscript->dn) != 0 ) {
+ e_debug(script->event,
+ "Binary `%s' reports different LDAP DN for script `%s' "
+ "(`%s' rather than `%s')",
+ sieve_binary_path(sbin), sieve_script_location(script),
+ str_c(dn), lscript->dn);
+ return 0;
+ }
+
+ /* compare modattr in binary and from search result */
+ if ( !sieve_binary_read_string(sblock, offset, &modattr) ) {
+ e_error(script->event,
+ "Binary `%s' has invalid metadata for script `%s': "
+ "Invalid modified attribute",
+ sieve_binary_path(sbin), sieve_script_location(script));
+ return -1;
+ }
+ if ( strcmp(str_c(modattr), lscript->modattr) != 0 ) {
+ e_debug(script->event,
+ "Binary `%s' reports different modified attribute content "
+ "for script `%s' (`%s' rather than `%s')",
+ sieve_binary_path(sbin), sieve_script_location(script),
+ str_c(modattr), lscript->modattr);
+ return 0;
+ }
+ return 1;
+}
+
+static void sieve_ldap_script_binary_write_metadata
+(struct sieve_script *script, struct sieve_binary_block *sblock)
+{
+ struct sieve_ldap_script *lscript =
+ (struct sieve_ldap_script *)script;
+
+ sieve_binary_emit_cstring(sblock, lscript->dn);
+ if (lscript->modattr == NULL)
+ sieve_binary_emit_cstring(sblock, "");
+ else
+ sieve_binary_emit_cstring(sblock, lscript->modattr);
+}
+
+static bool sieve_ldap_script_binary_dump_metadata
+(struct sieve_script *script ATTR_UNUSED, struct sieve_dumptime_env *denv,
+ struct sieve_binary_block *sblock, sieve_size_t *offset)
+{
+ string_t *dn, *modattr;
+
+ if ( !sieve_binary_read_string(sblock, offset, &dn) )
+ return FALSE;
+ sieve_binary_dumpf(denv, "ldap.dn = %s\n", str_c(dn));
+
+ if ( !sieve_binary_read_string(sblock, offset, &modattr) )
+ return FALSE;
+ sieve_binary_dumpf(denv, "ldap.mod_attr = %s\n", str_c(modattr));
+
+ return TRUE;
+}
+
+static const char *sieve_ldap_script_get_binpath
+(struct sieve_ldap_script *lscript)
+{
+ struct sieve_script *script = &lscript->script;
+ struct sieve_storage *storage = script->storage;
+
+ if ( lscript->binpath == NULL ) {
+ if ( storage->bin_dir == NULL )
+ return NULL;
+ lscript->binpath = p_strconcat(script->pool,
+ storage->bin_dir, "/",
+ sieve_binfile_from_name(script->name), NULL);
+ }
+
+ return lscript->binpath;
+}
+
+static struct sieve_binary *sieve_ldap_script_binary_load
+(struct sieve_script *script, enum sieve_error *error_r)
+{
+ struct sieve_storage *storage = script->storage;
+ struct sieve_ldap_script *lscript =
+ (struct sieve_ldap_script *)script;
+
+ if ( sieve_ldap_script_get_binpath(lscript) == NULL )
+ return NULL;
+
+ return sieve_binary_open(storage->svinst,
+ lscript->binpath, script, error_r);
+}
+
+static int sieve_ldap_script_binary_save
+(struct sieve_script *script, struct sieve_binary *sbin, bool update,
+ enum sieve_error *error_r)
+{
+ struct sieve_ldap_script *lscript =
+ (struct sieve_ldap_script *)script;
+
+ if ( sieve_ldap_script_get_binpath(lscript) == NULL )
+ return 0;
+
+ if ( sieve_storage_setup_bindir(script->storage, 0700) < 0 )
+ return -1;
+
+ return sieve_binary_save
+ (sbin, lscript->binpath, update, 0600, error_r);
+}
+
+static bool sieve_ldap_script_equals
+(const struct sieve_script *script, const struct sieve_script *other)
+{
+ struct sieve_storage *storage = script->storage;
+ struct sieve_storage *sother = other->storage;
+
+ if ( strcmp(storage->location, sother->location) != 0 )
+ return FALSE;
+
+ i_assert( script->name != NULL && other->name != NULL );
+
+ return ( strcmp(script->name, other->name) == 0 );
+}
+
+const struct sieve_script sieve_ldap_script = {
+ .driver_name = SIEVE_LDAP_STORAGE_DRIVER_NAME,
+ .v = {
+ .open = sieve_ldap_script_open,
+
+ .get_stream = sieve_ldap_script_get_stream,
+
+ .binary_read_metadata = sieve_ldap_script_binary_read_metadata,
+ .binary_write_metadata = sieve_ldap_script_binary_write_metadata,
+ .binary_dump_metadata = sieve_ldap_script_binary_dump_metadata,
+ .binary_load = sieve_ldap_script_binary_load,
+ .binary_save = sieve_ldap_script_binary_save,
+
+ .equals = sieve_ldap_script_equals
+ }
+};
+
+/*
+ * Script sequence
+ */
+
+struct sieve_ldap_script_sequence {
+ struct sieve_script_sequence seq;
+
+ bool done:1;
+};
+
+struct sieve_script_sequence *sieve_ldap_storage_get_script_sequence
+(struct sieve_storage *storage, enum sieve_error *error_r)
+{
+ struct sieve_ldap_script_sequence *lsec = NULL;
+
+ if ( error_r != NULL )
+ *error_r = SIEVE_ERROR_NONE;
+
+ /* Create sequence object */
+ lsec = i_new(struct sieve_ldap_script_sequence, 1);
+ sieve_script_sequence_init(&lsec->seq, storage);
+
+ return &lsec->seq;
+}
+
+struct sieve_script *sieve_ldap_script_sequence_next
+(struct sieve_script_sequence *seq, enum sieve_error *error_r)
+{
+ struct sieve_ldap_script_sequence *lsec =
+ (struct sieve_ldap_script_sequence *)seq;
+ struct sieve_ldap_storage *lstorage =
+ (struct sieve_ldap_storage *)seq->storage;
+ struct sieve_ldap_script *lscript;
+
+ if ( error_r != NULL )
+ *error_r = SIEVE_ERROR_NONE;
+
+ if ( lsec->done )
+ return NULL;
+ lsec->done = TRUE;
+
+ lscript = sieve_ldap_script_init
+ (lstorage, seq->storage->script_name);
+ if ( sieve_script_open(&lscript->script, error_r) < 0 ) {
+ struct sieve_script *script = &lscript->script;
+ sieve_script_unref(&script);
+ return NULL;
+ }
+
+ return &lscript->script;
+}
+
+void sieve_ldap_script_sequence_destroy
+(struct sieve_script_sequence *seq)
+{
+ struct sieve_ldap_script_sequence *lsec =
+ (struct sieve_ldap_script_sequence *)seq;
+ i_free(lsec);
+}
+
+
+#endif