userdb-vpopmail.c revision f961dc4f99a1a5780c7575e84dfa667d1ab74830
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Thanks to Courier-IMAP for showing how the vpopmail API should be used */
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#if defined(PASSDB_VPOPMAIL) || defined(USERDB_VPOPMAIL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "var-expand.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "userdb.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "userdb-vpopmail.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct vpopmail_userdb_module {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct userdb_module module;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *quota_template_key;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen const char *quota_template_value;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen};
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
213b139965e8bde6c8aff02ffd9fd39a74c887a9Timo Sirainenstruct vqpasswd *vpopmail_lookup_vqp(struct auth_request *request,
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen char vpop_user[VPOPMAIL_LIMIT],
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen char vpop_domain[VPOPMAIL_LIMIT])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct vqpasswd *vpw;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* vpop_user must be zero-filled or parse_email() leaves an
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen extra character after the user name. we'll fill vpop_domain
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen as well just to be sure... */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(vpop_user, '\0', VPOPMAIL_LIMIT);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(vpop_domain, '\0', VPOPMAIL_LIMIT);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (parse_email(request->user, vpop_user, vpop_domain,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen VPOPMAIL_LIMIT-1) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request_log_info(request, "vpopmail",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "parse_email() failed");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
7888a9d2008eab9985096c46e1da9ee985c22a2aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen auth_request_log_debug(request, "vpopmail",
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen "lookup user=%s domain=%s",
213b139965e8bde6c8aff02ffd9fd39a74c887a9Timo Sirainen vpop_user, vpop_domain);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (vpw == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request_log_info(request, "vpopmail", "unknown user");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen return vpw;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen}
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen#ifdef USERDB_VPOPMAIL
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainenstatic const char *
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainenuserdb_vpopmail_get_quota(const char *template, const char *vpop_str)
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen{
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen const struct var_expand_table *tab;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen string_t *quota;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen if (template == NULL || *vpop_str == '\0' ||
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen strcmp(vpop_str, "NOQUOTA") == 0)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return "";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen tab = var_expand_table_build('q', format_maildirquota(vpop_str), '\0');
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen quota = t_str_new(128);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen var_expand(quota, template, tab);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return str_c(quota);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenstatic void vpopmail_lookup(struct auth_request *auth_request,
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen userdb_callback_t *callback)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen{
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen struct vpopmail_userdb_module *module =
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen (struct vpopmail_userdb_module *)_module;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT];
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen struct vqpasswd *vpw;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen const char *quota;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen uid_t uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen gid_t gid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen if (vpw == NULL) {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen return;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen /* we have to get uid/gid separately, because the gid field in
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen struct vqpasswd isn't really gid at all but just some flags... */
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen if (vget_assign(vpop_domain, NULL, 0, &uid, &gid) == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request_log_info(auth_request, "vpopmail",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "vget_assign(%s) failed", vpop_domain);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
5f78b33aa505b17e23cdf27b071a24e127b3db54Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (auth_request->successful) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* update the last login only when we're really */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vset_lastauth(vpop_user, vpop_domain,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_strdup_noconst(auth_request->service));
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (vpw->pw_dir == NULL || vpw->pw_dir[0] == '\0') {
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen /* user's homedir doesn't exist yet, create it */
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen auth_request_log_info(auth_request, "vpopmail",
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen "pw_dir isn't set, creating");
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen if (make_user_dir(vpop_user, vpop_domain, uid, gid) == NULL) {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen auth_request_log_error(auth_request, "vpopmail",
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen "make_user_dir(%s, %s) failed",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen vpop_user, vpop_domain);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* get the user again so pw_dir is visible */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (vpw == NULL) {
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen return;
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen }
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen }
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen auth_request_init_userdb_reply(auth_request);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen auth_request_set_userdb_field(auth_request, "uid", dec2str(uid));
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen auth_request_set_userdb_field(auth_request, "gid", dec2str(gid));
45e62043058738e294f89504c319d852e25943ccTimo Sirainen auth_request_set_userdb_field(auth_request, "home", vpw->pw_dir);
45e62043058738e294f89504c319d852e25943ccTimo Sirainen
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen quota = userdb_vpopmail_get_quota(module->quota_template_value,
45e62043058738e294f89504c319d852e25943ccTimo Sirainen vpw->pw_shell);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen if (*quota != '\0') {
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen auth_request_set_userdb_field(auth_request,
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen module->quota_template_key,
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen quota);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen }
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen callback(USERDB_RESULT_OK, auth_request);
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen}
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainenstatic struct userdb_module *
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainenvpopmail_preinit(struct auth_userdb *auth_userdb, const char *args)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen struct vpopmail_userdb_module *module;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen const char *const *tmp, *p;
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen pool_t pool = auth_userdb->auth->pool;
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen module = p_new(pool, struct vpopmail_userdb_module, 1);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen if (strncmp(*tmp, "cache_key=", 10) == 0)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen module->module.cache_key = p_strdup(pool, *tmp + 10);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen else if (strncmp(*tmp, "quota_template=", 15) == 0) {
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen p = strchr(*tmp + 15, '=');
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen if (p == NULL) {
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen i_fatal("vpopmail userdb: "
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen "quota_template missing '='");
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen }
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen module->quota_template_key =
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen p_strdup_until(pool, *tmp + 15, p);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen module->quota_template_value = p_strdup(pool, p + 1);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen } else
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen i_fatal("vpopmail userdb: Unknown args: %s", *tmp);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen }
8eeafcb306872435f3171e6acf5a9937aec3a175Timo Sirainen return &module->module;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct userdb_module_interface userdb_vpopmail = {
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen "vpopmail",
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vpopmail_preinit,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen NULL,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen NULL,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen vpopmail_lookup
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen};
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen#endif
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen#endif
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen