userdb-vpopmail.c revision 7bafda1813454621e03615e83d55bccfa7cc56bd
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen/* Thanks to Courier-IMAP for showing how the vpopmail API should be used */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "auth-common.h"
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen#include "userdb.h"
a1607f6001a9949e1cf9d49eb0aa936dbb4c77ffTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#if defined(PASSDB_VPOPMAIL) || defined(USERDB_VPOPMAIL)
00d58fcfe8191d6ce7efa801d289a5c0fe88d1aeTimo Sirainen#include "str.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "var-expand.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "userdb-vpopmail.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstruct vpopmail_userdb_module {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct userdb_module module;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const char *quota_template_key;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const char *quota_template_value;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen};
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct vqpasswd *vpopmail_lookup_vqp(struct auth_request *request,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen char vpop_user[VPOPMAIL_LIMIT],
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen char vpop_domain[VPOPMAIL_LIMIT])
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct vqpasswd *vpw;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* vpop_user must be zero-filled or parse_email() leaves an
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen extra character after the user name. we'll fill vpop_domain
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen as well just to be sure... */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen memset(vpop_user, '\0', VPOPMAIL_LIMIT);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen memset(vpop_domain, '\0', VPOPMAIL_LIMIT);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (parse_email(request->user, vpop_user, vpop_domain,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen VPOPMAIL_LIMIT-1) < 0) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen auth_request_log_info(request, "vpopmail",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "parse_email() failed");
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return NULL;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen auth_request_log_debug(request, "vpopmail",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "lookup user=%s domain=%s",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen vpop_user, vpop_domain);
4462bd7b4c7ef3de006f060e155a90e5de7cae21Timo Sirainen
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (vpw == NULL) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen auth_request_log_info(request, "vpopmail", "unknown user");
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return NULL;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return vpw;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#endif
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#ifdef USERDB_VPOPMAIL
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic const char *
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenuserdb_vpopmail_get_quota(const char *template, const char *vpop_str)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const struct var_expand_table *tab;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen string_t *quota;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (template == NULL || *vpop_str == '\0' ||
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen strcmp(vpop_str, "NOQUOTA") == 0)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return "";
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen tab = var_expand_table_build('q', format_maildirquota(vpop_str), '\0');
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen quota = t_str_new(128);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen var_expand(quota, template, tab);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return str_c(quota);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainenstatic void vpopmail_lookup(struct auth_request *auth_request,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen userdb_callback_t *callback)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen struct vpopmail_userdb_module *module =
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen (struct vpopmail_userdb_module *)_module;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT];
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct vqpasswd *vpw;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const char *quota;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uid_t uid;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen gid_t gid;
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (vpw == NULL) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen return;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen /* we have to get uid/gid separately, because the gid field in
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen struct vqpasswd isn't really gid at all but just some flags... */
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen if (vget_assign(vpop_domain, NULL, 0, &uid, &gid) == NULL) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen auth_request_log_info(auth_request, "vpopmail",
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen "vget_assign(%s) failed", vpop_domain);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen return;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (auth_request->successful) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* update the last login only when we're really */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen vset_lastauth(vpop_user, vpop_domain,
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen t_strdup_noconst(auth_request->service));
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (vpw->pw_dir == NULL || vpw->pw_dir[0] == '\0') {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* user's homedir doesn't exist yet, create it */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen auth_request_log_info(auth_request, "vpopmail",
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen "pw_dir isn't set, creating");
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (make_user_dir(vpop_user, vpop_domain, uid, gid) == NULL) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen auth_request_log_error(auth_request, "vpopmail",
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen "make_user_dir(%s, %s) failed",
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen vpop_user, vpop_domain);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen return;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* get the user again so pw_dir is visible */
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (vpw == NULL) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, auth_request);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen return;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen auth_request_init_userdb_reply(auth_request);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen auth_request_set_userdb_field(auth_request, "uid", dec2str(uid));
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen auth_request_set_userdb_field(auth_request, "gid", dec2str(gid));
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen auth_request_set_userdb_field(auth_request, "home", vpw->pw_dir);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen quota = userdb_vpopmail_get_quota(module->quota_template_value,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen vpw->pw_shell);
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen if (*quota != '\0') {
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen auth_request_set_userdb_field(auth_request,
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen module->quota_template_key,
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen quota);
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen }
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen callback(USERDB_RESULT_OK, auth_request);
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen}
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainenstatic struct userdb_module *
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainenvpopmail_preinit(struct auth_userdb *auth_userdb, const char *args)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct vpopmail_userdb_module *module;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const char *const *tmp, *p;
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen pool_t pool = auth_userdb->auth->pool;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen module = p_new(pool, struct vpopmail_userdb_module, 1);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen if (strncmp(*tmp, "cache_key=", 10) == 0)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen module->module.cache_key = p_strdup(pool, *tmp + 10);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen else if (strncmp(*tmp, "quota_template=", 15) == 0) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen p = strchr(*tmp + 15, '=');
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (p == NULL) {
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen i_fatal("vpopmail userdb: "
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "quota_template missing '='");
5d49cbcf87354f0ddf3b71bc5f0cefdc02b14f68Timo Sirainen }
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen module->quota_template_key =
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen p_strdup_until(pool, *tmp + 15, p);
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen module->quota_template_value = p_strdup(pool, p + 1);
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen } else
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen i_fatal("userdb vpopmail: Unknown setting: %s", *tmp);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return &module->module;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainenstruct userdb_module_interface userdb_vpopmail = {
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen "vpopmail",
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen vpopmail_preinit,
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen NULL,
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen NULL,
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen vpopmail_lookup,
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen NULL,
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen NULL,
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen NULL
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen};
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#else
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenstruct userdb_module_interface userdb_vpopmail = {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen .name = "vpopmail"
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen};
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#endif
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen