bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* Thanks to Courier-IMAP for showing how the vpopmail API should be used */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#include "userdb.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#if defined(PASSDB_VPOPMAIL) || defined(USERDB_VPOPMAIL)
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen#include "str.h"
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen#include "var-expand.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "userdb-vpopmail.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainenstruct vpopmail_userdb_module {
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen struct userdb_module module;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen const char *quota_template_key;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen const char *quota_template_value;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen};
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainenstruct vqpasswd *vpopmail_lookup_vqp(struct auth_request *request,
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen char vpop_user[VPOPMAIL_LIMIT],
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen char vpop_domain[VPOPMAIL_LIMIT])
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct vqpasswd *vpw;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen /* vpop_user must be zero-filled or parse_email() leaves an
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen extra character after the user name. we'll fill vpop_domain
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen as well just to be sure... */
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen memset(vpop_user, '\0', VPOPMAIL_LIMIT);
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen memset(vpop_domain, '\0', VPOPMAIL_LIMIT);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
356303df200c991580bd24041996a070ad08c05eTimo Sirainen if (parse_email(request->user, vpop_user, vpop_domain,
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen VPOPMAIL_LIMIT-1) < 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(request, AUTH_SUBSYS_DB,
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "parse_email() failed");
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen return NULL;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(request, AUTH_SUBSYS_DB,
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen "lookup user=%s domain=%s",
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen vpop_user, vpop_domain);
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (vpw == NULL) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_unknown_user(request, AUTH_SUBSYS_DB);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen return NULL;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen return vpw;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#endif
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#ifdef USERDB_VPOPMAIL
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomistatic int
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomiuserdb_vpopmail_get_quota(const char *template, const char *vpop_str,
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi const char **quota_r, const char **error_r)
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen{
e2d97f20ae7301e2647f175fa072fc3cd2764b05Aki Tuomi struct var_expand_table *tab;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen string_t *quota;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen if (template == NULL || *vpop_str == '\0' ||
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi strcmp(vpop_str, "NOQUOTA") == 0) {
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi *quota_r = "";
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi return 0;
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi }
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen
79fe1b28df44ba22b230326bee895583c1df5a28Stephan Bosch tab = t_new(struct var_expand_table, 2);
79fe1b28df44ba22b230326bee895583c1df5a28Stephan Bosch tab[0].key = 'q';
79fe1b28df44ba22b230326bee895583c1df5a28Stephan Bosch tab[0].value = format_maildirquota(vpop_str);
79fe1b28df44ba22b230326bee895583c1df5a28Stephan Bosch
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen quota = t_str_new(128);
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi if (var_expand(quota, template, tab, error_r) < 0)
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi return -1;
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi *quota_r = str_c(quota);
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi return 0;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen}
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen
3b94ff5951db4d4eddb7a80ed4e3f61207202635Timo Sirainenstatic void vpopmail_lookup(struct auth_request *auth_request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen userdb_callback_t *callback)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen struct vpopmail_userdb_module *module =
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen (struct vpopmail_userdb_module *)_module;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT];
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct vqpasswd *vpw;
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi const char *quota, *error;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen uid_t uid;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen gid_t gid;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain);
22535a9e685e29214082878e37a267157044618eTimo Sirainen if (vpw == NULL) {
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
22535a9e685e29214082878e37a267157044618eTimo Sirainen return;
22535a9e685e29214082878e37a267157044618eTimo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen /* we have to get uid/gid separately, because the gid field in
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct vqpasswd isn't really gid at all but just some flags... */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (vget_assign(vpop_domain, NULL, 0, &uid, &gid) == NULL) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_DB,
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "vget_assign(%s) failed", vpop_domain);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
22535a9e685e29214082878e37a267157044618eTimo Sirainen return;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
e15f1d736c225c7ce6f3d08a37c1b2ae66b57c50Timo Sirainen if (auth_request->successful) {
e15f1d736c225c7ce6f3d08a37c1b2ae66b57c50Timo Sirainen /* update the last login only when we're really */
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen vset_lastauth(vpop_user, vpop_domain,
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen t_strdup_noconst(auth_request->service));
e15f1d736c225c7ce6f3d08a37c1b2ae66b57c50Timo Sirainen }
e15f1d736c225c7ce6f3d08a37c1b2ae66b57c50Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (vpw->pw_dir == NULL || vpw->pw_dir[0] == '\0') {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen /* user's homedir doesn't exist yet, create it */
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_DB,
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "pw_dir isn't set, creating");
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (make_user_dir(vpop_user, vpop_domain, uid, gid) == NULL) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "make_user_dir(%s, %s) failed",
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen vpop_user, vpop_domain);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
22535a9e685e29214082878e37a267157044618eTimo Sirainen return;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen /* get the user again so pw_dir is visible */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
22535a9e685e29214082878e37a267157044618eTimo Sirainen if (vpw == NULL) {
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
22535a9e685e29214082878e37a267157044618eTimo Sirainen return;
22535a9e685e29214082878e37a267157044618eTimo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen }
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi if (userdb_vpopmail_get_quota(module->quota_template_value,
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi vpw->pw_shell, &quota, &error) < 0) {
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi auth_request_log_error(auth_request, AUTH_SUBSYS_DB,
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi "userdb_vpopmail_get_quota(%s, %s) failed: %s",
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi module->quota_template_value,
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi vpw->pw_shell, error);
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi return;
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi }
c6ae57a037d81f3932faead5ffb44c07b547e2f1Aki Tuomi
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_set_userdb_field(auth_request, "uid", dec2str(uid));
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_set_userdb_field(auth_request, "gid", dec2str(gid));
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_set_userdb_field(auth_request, "home", vpw->pw_dir);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen if (*quota != '\0') {
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_set_userdb_field(auth_request,
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen module->quota_template_key,
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen quota);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen }
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen callback(USERDB_RESULT_OK, auth_request);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainenstatic struct userdb_module *
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainenvpopmail_preinit(pool_t pool, const char *args)
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen{
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen struct vpopmail_userdb_module *module;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen const char *const *tmp, *p;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen module = p_new(pool, struct vpopmail_userdb_module, 1);
c64e714193097f841691dcfa2902c270cb47bff8Timo Sirainen module->module.blocking = TRUE;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen if (strncmp(*tmp, "cache_key=", 10) == 0)
74674a53a72dab535c61f455b2246ef2797844eaTimo Sirainen module->module.default_cache_key =
74674a53a72dab535c61f455b2246ef2797844eaTimo Sirainen p_strdup(pool, *tmp + 10);
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen else if (strncmp(*tmp, "quota_template=", 15) == 0) {
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen p = strchr(*tmp + 15, '=');
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen if (p == NULL) {
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen i_fatal("vpopmail userdb: "
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen "quota_template missing '='");
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen }
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen module->quota_template_key =
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen p_strdup_until(pool, *tmp + 15, p);
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen module->quota_template_value = p_strdup(pool, p + 1);
c64e714193097f841691dcfa2902c270cb47bff8Timo Sirainen } else if (strcmp(*tmp, "blocking=no") == 0) {
c64e714193097f841691dcfa2902c270cb47bff8Timo Sirainen module->module.blocking = FALSE;
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen } else
dd93aba1901a457346990f49c54a738947dc7128Timo Sirainen i_fatal("userdb vpopmail: Unknown setting: %s", *tmp);
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen }
806cb455553b71934314da98f1b4a694a3aa152eTimo Sirainen return &module->module;
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen}
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainenstruct userdb_module_interface userdb_vpopmail = {
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen "vpopmail",
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen vpopmail_preinit,
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen NULL,
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen NULL,
c5383a0ed56a188a7d5efaaa4c6f8243af432d65Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen vpopmail_lookup,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen NULL,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen NULL,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen NULL
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen};
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen#else
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainenstruct userdb_module_interface userdb_vpopmail = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .name = "vpopmail"
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen};
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#endif