#include "shared-storage.h"
#include <stdlib.h>
+#include <ctype.h>
#define SHARED_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, shared_mailbox_list_module)
storage->storage.pool = pool;
storage->storage.storage_class = &shared_storage;
+ storage->base_dir = p_strdup(pool, getenv("BASE_DIR"));
+ if (storage->base_dir == NULL)
+ storage->base_dir = PKG_RUNDIR;
+
return &storage->storage;
}
return 0;
}
-static const char *lookup_home(const char *user)
+static void shared_storage_destroy(struct mail_storage *_storage)
{
- const char *auth_socket;
- const char *home = NULL;
- struct auth_connection *conn;
- struct auth_user_reply *reply;
- pool_t userdb_pool;
- struct ioloop *userdb_ioloop;
-
- auth_socket = getenv("AUTH_SOCKET_PATH");
- if (auth_socket == NULL) {
- const char *base_dir = getenv("BASE_DIR");
- if (base_dir == NULL)
- base_dir = PKG_RUNDIR;
- auth_socket = t_strconcat(base_dir, "/auth-master",
- NULL);
- }
+ struct shared_storage *storage = (struct shared_storage *)_storage;
+
+ if (storage->auth_master_conn != NULL)
+ auth_master_deinit(&storage->auth_master_conn);
+ index_storage_destroy(_storage);
+}
+
+static void shared_storage_auth_master_init(struct shared_storage *storage)
+{
+ const char *auth_socket_path;
+ bool debug;
- userdb_pool = pool_alloconly_create("userdb lookup replys", 512);
- userdb_ioloop = io_loop_create();
- conn = auth_master_init(auth_socket, getenv("DEBUG") != NULL);
- reply = i_new(struct auth_user_reply, 1);
-
- switch (auth_master_user_lookup(conn, user, "shared-storage", userdb_pool, reply)) {
- case -1:
- /* Some error during lookup... */
- case 0:
- /* User not found
- FIXME: It might be a good idea to handle this special case... */
- break;
- case 1:
- home = i_strdup(reply->home);
+ auth_socket_path = getenv("AUTH_SOCKET_PATH");
+ if (auth_socket_path == NULL) {
+ auth_socket_path = t_strconcat(storage->base_dir,
+ "/auth-master", NULL);
}
-
- i_free(reply);
- if (conn != NULL)
- auth_master_deinit(conn);
- io_loop_destroy(&userdb_ioloop);
+
+ debug = (storage->storage.flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
+ storage->auth_master_conn = auth_master_init(auth_socket_path, debug);
+}
+
+static int
+shared_storage_lookup_home(struct shared_storage *storage,
+ const char *user, const char **home_r)
+{
+ struct auth_user_reply reply;
+ pool_t userdb_pool;
+ int ret;
+
+ if (storage->auth_master_conn == NULL)
+ shared_storage_auth_master_init(storage);
+
+ userdb_pool = pool_alloconly_create("userdb lookup", 512);
+ ret = auth_master_user_lookup(storage->auth_master_conn, user,
+ AUTH_SERVICE_INTERNAL,
+ userdb_pool, &reply);
+ if (ret > 0)
+ *home_r = t_strdup(reply.home);
pool_unref(&userdb_pool);
+ return ret;
+}
- return home;
+static void get_nonexisting_user_location(struct shared_storage *storage,
+ string_t *location)
+{
+ /* user wasn't found. we'll still need to create the storage
+ to avoid exposing which users exist and which don't. */
+ str_append(location, storage->storage_class->name);
+ str_append_c(location, ':');
+
+ /* use a reachable but non-existing path as the mail root directory */
+ str_append(location, storage->base_dir);
+ str_append(location, PKG_RUNDIR"/user-not-found");
}
int shared_storage_get_namespace(struct mail_storage *_storage,
};
struct var_expand_table *tab;
struct mail_namespace *ns;
- const char *domain = NULL, *username = NULL, *userdomain = NULL, *userhome = NULL;
+ const char *domain = NULL, *username = NULL, *userdomain = NULL;
const char *name, *p, *next, **dest, *error;
string_t *prefix, *location;
+ int ret;
+
+ *ns_r = NULL;
p = storage->ns_prefix_pattern;
for (name = *_name; *p != '\0';) {
}
}
- userhome = lookup_home(userdomain);
- if (userhome == NULL) {
- i_error("Namespace '%s': could not lookup home for user %s", _storage->ns->prefix, userdomain);
- return -1;
- }
-
/* expand the namespace prefix and see if it already exists.
this should normally happen only when the mailbox is being opened */
tab = t_malloc(sizeof(static_tab));
tab[0].value = userdomain;
tab[1].value = username;
tab[2].value = domain;
- tab[3].value = userhome;
+
prefix = t_str_new(128);
str_append(prefix, _storage->ns->prefix);
var_expand(prefix, storage->ns_prefix_pattern, tab);
return 0;
}
+ if (!var_has_key(storage->location, 'h'))
+ ret = 1;
+ else {
+ /* we'll need to look up the user's home directory */
+ ret = shared_storage_lookup_home(storage, userdomain,
+ &tab[3].value);
+ if (ret < 0) {
+ mail_storage_set_critical(_storage, "Namespace '%s': "
+ "Could not lookup home for user %s",
+ _storage->ns->prefix, userdomain);
+ return -1;
+ }
+ }
+
/* create the new namespace */
ns = p_new(user->pool, struct mail_namespace, 1);
ns->type = NAMESPACE_SHARED;
ns->sep = _storage->ns->sep;
location = t_str_new(256);
- var_expand(location, storage->location, tab);
+ if (ret > 0)
+ var_expand(location, storage->location, tab);
+ else
+ get_nonexisting_user_location(storage, location);
if (mail_storage_create(ns, NULL, str_c(location), _storage->flags,
_storage->lock_method, &error) < 0) {
mail_storage_set_critical(_storage, "Namespace '%s': %s",
if (shared_storage_get_namespace(storage, &name, &ns) < 0)
return -1;
+
ret = mail_storage_mailbox_create(ns->storage, name, directory);
if (ret < 0)
shared_mailbox_copy_error(storage, ns);
NULL,
shared_alloc,
shared_create,
- index_storage_destroy,
+ shared_storage_destroy,
NULL,
shared_mailbox_open,
shared_mailbox_create