userdb-vpopmail.c revision 806cb455553b71934314da98f1b4a694a3aa152e
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen/* Thanks to Courier-IMAP for showing how the vpopmail API should be used */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
d3d769026fae5d21c2d29614d3bc4579e8d79e81Timo Sirainen#include "common.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#if defined(PASSDB_VPOPMAIL) || defined(USERDB_VPOPMAIL)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen#include "str.h"
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen#include "var-expand.h"
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen#include "userdb.h"
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen#include "userdb-vpopmail.h"
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstruct vpopmail_userdb_module {
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen struct userdb_module module;
ab0d9eecd85f74acae18fe88529302e0776cc500Timo Sirainen
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen const char *quota_template_key;
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen const char *quota_template_value;
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen};
d3d769026fae5d21c2d29614d3bc4579e8d79e81Timo Sirainen
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainenstruct vqpasswd *vpopmail_lookup_vqp(struct auth_request *request,
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen char vpop_user[VPOPMAIL_LIMIT],
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen char vpop_domain[VPOPMAIL_LIMIT])
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen{
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen struct vqpasswd *vpw;
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen /* vpop_user must be zero-filled or parse_email() leaves an
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen extra character after the user name. we'll fill vpop_domain
d3d769026fae5d21c2d29614d3bc4579e8d79e81Timo Sirainen as well just to be sure... */
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen memset(vpop_user, '\0', VPOPMAIL_LIMIT);
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen memset(vpop_domain, '\0', VPOPMAIL_LIMIT);
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen if (parse_email(request->user, vpop_user, vpop_domain,
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen VPOPMAIL_LIMIT-1) < 0) {
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen auth_request_log_info(request, "vpopmail",
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen "parse_email() failed");
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen return NULL;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen }
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_log_debug(request, "vpopmail",
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen "lookup user=%s domain=%s",
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen vpop_user, vpop_domain);
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen if (vpw == NULL) {
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen auth_request_log_info(request, "vpopmail", "unknown user");
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen return NULL;
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen }
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen return vpw;
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen}
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen#ifdef USERDB_VPOPMAIL
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainenstatic const char *
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenuserdb_vpopmail_get_quota(const char *template, const char *vpop_str)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen{
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen const struct var_expand_table *tab;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen string_t *quota;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen if (template == NULL || *vpop_str == '\0' ||
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen strcmp(vpop_str, "NOQUOTA") == 0)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen return "";
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen tab = var_expand_table_build('q', format_maildirquota(vpop_str), '\0');
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen quota = t_str_new(128);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen var_expand(quota, template, tab);
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen return str_c(quota);
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen}
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic void vpopmail_lookup(struct auth_request *auth_request,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen userdb_callback_t *callback)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen{
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen struct userdb_module *_module = auth_request->userdb->userdb;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen struct vpopmail_userdb_module *module =
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen (struct vpopmail_userdb_module *)_module;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT];
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen struct vqpasswd *vpw;
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen struct auth_stream_reply *reply;
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen const char *quota;
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen uid_t uid;
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen gid_t gid;
4e35bae013cee5a06d281776a347b534b958aaa4Timo Sirainen
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain);
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen if (vpw == NULL) {
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request);
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen return;
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen }
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen /* we have to get uid/gid separately, because the gid field in
4e35bae013cee5a06d281776a347b534b958aaa4Timo Sirainen struct vqpasswd isn't really gid at all but just some flags... */
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen if (vget_assign(vpop_domain, NULL, 0, &uid, &gid) == NULL) {
4e35bae013cee5a06d281776a347b534b958aaa4Timo Sirainen auth_request_log_info(auth_request, "vpopmail",
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen "vget_assign(%s) failed", vpop_domain);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE, NULL, auth_request);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen return;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen if (auth_request->successful) {
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* update the last login only when we're really */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen vset_lastauth(vpop_user, vpop_domain,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen t_strdup_noconst(auth_request->service));
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen }
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen if (vpw->pw_dir == NULL || vpw->pw_dir[0] == '\0') {
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* user's homedir doesn't exist yet, create it */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_log_info(auth_request, "vpopmail",
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen "pw_dir isn't set, creating");
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen if (make_user_dir(vpop_user, vpop_domain, uid, gid) == NULL) {
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_request_log_error(auth_request, "vpopmail",
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen "make_user_dir(%s, %s) failed",
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen vpop_user, vpop_domain);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen NULL, auth_request);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen return;
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen }
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen
f77ffa31038d46ca9c6d24d93e3d76c9aa8d4d0cTimo Sirainen /* get the user again so pw_dir is visible */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen vpw = vauth_getpw(vpop_user, vpop_domain);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen if (vpw == NULL) {
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen callback(USERDB_RESULT_INTERNAL_FAILURE,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen NULL, auth_request);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen return;
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen }
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen }
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen reply = auth_stream_reply_init(auth_request);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_stream_reply_add(reply, NULL, auth_request->user);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_stream_reply_add(reply, "uid", dec2str(uid));
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_stream_reply_add(reply, "gid", dec2str(gid));
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_stream_reply_add(reply, "home", vpw->pw_dir);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen quota = userdb_vpopmail_get_quota(module->quota_template_value,
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen vpw->pw_shell);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen if (*quota != '\0')
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen auth_stream_reply_add(reply, module->quota_template_key, quota);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen callback(USERDB_RESULT_OK, reply, auth_request);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen}
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenstatic struct userdb_module *
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainenvpopmail_preinit(struct auth_userdb *auth_userdb, const char *args)
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen{
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen struct vpopmail_userdb_module *module;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen const char *const *tmp, *p;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen pool_t pool = auth_userdb->auth->pool;
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen module = p_new(pool, struct vpopmail_userdb_module, 1);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen for (tmp = t_strsplit(args, " "); *tmp != NULL; tmp++) {
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen if (strncmp(*tmp, "cache_key=", 10) == 0)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen module->module.cache_key = p_strdup(pool, *tmp + 10);
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen else if (strncmp(*tmp, "quota_template=", 15) == 0) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen p = strchr(*tmp + 15, '=');
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (p == NULL) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen i_fatal("vpopmail userdb: "
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen "quota_template missing '='");
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen module->quota_template_key =
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen p_strdup_until(pool, *tmp + 15, p);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen module->quota_template_value = p_strdup(pool, p + 1);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen } else
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen i_fatal("vpopmail userdb: Unknown args: %s", *tmp);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen return &module->module;
1d4f710106fb498750456724628da6063e012e6dTimo Sirainen}
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenstruct userdb_module_interface userdb_vpopmail = {
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen "vpopmail",
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen vpopmail_preinit,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen NULL,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen NULL,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen vpopmail_lookup
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen};
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen#endif
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen#endif
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen