userdb-vpopmail.c revision d5abbb932a0a598f002da39a8b3326643b1b5efc
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* Thanks to Courier-IMAP for showing how the vpopmail API should be used */
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "common.h"
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen#include "userdb.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#if defined(PASSDB_VPOPMAIL) || defined(USERDB_VPOPMAIL)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "str.h"
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen#include "var-expand.h"
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen#include "userdb-vpopmail.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
18565c69efcd7db003dbf27cf625ed822e889fb1Timo Sirainenstruct vpopmail_userdb_module {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct userdb_module module;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *quota_template_key;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen const char *quota_template_value;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen};
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstruct vqpasswd *vpopmail_lookup_vqp(struct auth_request *request,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen char vpop_user[VPOPMAIL_LIMIT],
d22301419109ed4a38351715e6760011421dadecTimo Sirainen char vpop_domain[VPOPMAIL_LIMIT])
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct vqpasswd *vpw;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen /* vpop_user must be zero-filled or parse_email() leaves an
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen extra character after the user name. we'll fill vpop_domain
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen as well just to be sure... */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen memset(vpop_user, '\0', VPOPMAIL_LIMIT);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen memset(vpop_domain, '\0', VPOPMAIL_LIMIT);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (parse_email(request->user, vpop_user, vpop_domain,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen VPOPMAIL_LIMIT-1) < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen auth_request_log_info(request, "vpopmail",
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen "parse_email() failed");
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return NULL;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen auth_request_log_debug(request, "vpopmail",
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen "lookup user=%s domain=%s",
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen vpop_user, vpop_domain);
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (vpw == NULL) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen auth_request_log_info(request, "vpopmail", "unknown user");
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return NULL;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen return vpw;
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen}
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen#endif
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen#ifdef USERDB_VPOPMAIL
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainenstatic const char *
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenuserdb_vpopmail_get_quota(const char *template, const char *vpop_str)
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen{
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen const struct var_expand_table *tab;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen string_t *quota;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (template == NULL || *vpop_str == '\0' ||
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen strcmp(vpop_str, "NOQUOTA") == 0)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return "";
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen tab = var_expand_table_build('q', format_maildirquota(vpop_str), '\0');
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen quota = t_str_new(128);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen var_expand(quota, template, tab);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return str_c(quota);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic void vpopmail_lookup(struct auth_request *auth_request,
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen userdb_callback_t *callback)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen{
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct vpopmail_userdb_module *module =
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen (struct vpopmail_userdb_module *)_module;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT];
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen struct vqpasswd *vpw;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen const char *quota;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen uid_t uid;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen gid_t gid;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (vpw == NULL) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
597dce34068d603fb759b4dff404b34049213e51Timo Sirainen return;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen }
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* we have to get uid/gid separately, because the gid field in
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct vqpasswd isn't really gid at all but just some flags... */
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (vget_assign(vpop_domain, NULL, 0, &uid, &gid) == NULL) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen auth_request_log_info(auth_request, "vpopmail",
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen "vget_assign(%s) failed", vpop_domain);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
4b41116563110d00330896a568eff1078c382827Timo Sirainen return;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (auth_request->successful) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* update the last login only when we're really */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen vset_lastauth(vpop_user, vpop_domain,
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen t_strdup_noconst(auth_request->service));
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen if (vpw->pw_dir == NULL || vpw->pw_dir[0] == '\0') {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen /* user's homedir doesn't exist yet, create it */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen auth_request_log_info(auth_request, "vpopmail",
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen "pw_dir isn't set, creating");
4b41116563110d00330896a568eff1078c382827Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (make_user_dir(vpop_user, vpop_domain, uid, gid) == NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen auth_request_log_error(auth_request, "vpopmail",
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "make_user_dir(%s, %s) failed",
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen vpop_user, vpop_domain);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen /* get the user again so pw_dir is visible */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (vpw == NULL) {
4b41116563110d00330896a568eff1078c382827Timo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen auth_request_init_userdb_reply(auth_request);
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen auth_request_set_userdb_field(auth_request, "uid", dec2str(uid));
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen auth_request_set_userdb_field(auth_request, "gid", dec2str(gid));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen auth_request_set_userdb_field(auth_request, "home", vpw->pw_dir);
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen quota = userdb_vpopmail_get_quota(module->quota_template_value,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen vpw->pw_shell);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (*quota != '\0') {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen auth_request_set_userdb_field(auth_request,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen module->quota_template_key,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen quota);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen callback(USERDB_RESULT_OK, auth_request);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic struct userdb_module *
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenvpopmail_preinit(struct auth_userdb *auth_userdb, const char *args)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct vpopmail_userdb_module *module;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen const char *const *tmp, *p;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen pool_t pool = auth_userdb->auth->pool;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen module = p_new(pool, struct vpopmail_userdb_module, 1);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (strncmp(*tmp, "cache_key=", 10) == 0)
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen module->module.cache_key = p_strdup(pool, *tmp + 10);
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen else if (strncmp(*tmp, "quota_template=", 15) == 0) {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen p = strchr(*tmp + 15, '=');
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen if (p == NULL) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen i_fatal("vpopmail userdb: "
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen "quota_template missing '='");
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen }
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen module->quota_template_key =
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen p_strdup_until(pool, *tmp + 15, p);
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen module->quota_template_value = p_strdup(pool, p + 1);
e6aa82aeb50948cb47a45a1b61a9c16d6a162388Timo Sirainen } else
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen i_fatal("vpopmail userdb: Unknown args: %s", *tmp);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen }
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen return &module->module;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen}
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainenstruct userdb_module_interface userdb_vpopmail = {
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen "vpopmail",
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen vpopmail_preinit,
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen NULL,
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen NULL,
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen vpopmail_lookup
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen};
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen#else
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstruct userdb_module_interface userdb_vpopmail = {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen MEMBER(name) "vpopmail"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen};
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#endif
d22301419109ed4a38351715e6760011421dadecTimo Sirainen