userdb.c revision d5abbb932a0a598f002da39a8b3326643b1b5efc
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include "common.h"
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include "array.h"
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include "auth-worker-server.h"
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include "userdb.h"
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include <stdlib.h>
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include <pwd.h>
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler#include <grp.h>
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic ARRAY_DEFINE(userdb_interfaces, struct userdb_module_interface *);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilerstatic struct userdb_module_interface *userdb_interface_find(const char *name)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler{
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler struct userdb_module_interface *const *ifaces;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler unsigned int i, count;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ifaces = array_get(&userdb_interfaces, &count);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler for (i = 0; i < count; i++) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (strcmp(ifaces[i]->name, name) == 0)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return ifaces[i];
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return NULL;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler}
aa8d013ec5b09cd1cd904173d6234ef126eb2126Peter Simons
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilervoid userdb_register_module(struct userdb_module_interface *iface)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler{
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (userdb_interface_find(iface->name) != NULL) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler i_panic("userdb_register_module(%s): Already registered",
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler iface->name);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler array_append(&userdb_interfaces, &iface, 1);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler}
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilervoid userdb_unregister_module(struct userdb_module_interface *iface)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler{
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler struct userdb_module_interface *const *ifaces;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler unsigned int i, count;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler ifaces = array_get(&userdb_interfaces, &count);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler for (i = 0; i < count; i++) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (ifaces[i] == iface) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler array_delete(&userdb_interfaces, i, 1);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler i_panic("userdb_unregister_module(%s): Not registered", iface->name);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler}
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engen
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engenuid_t userdb_parse_uid(struct auth_request *request, const char *str)
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engen{
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engen struct passwd *pw;
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engen uid_t uid;
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler char *p;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engen if (str == NULL)
b4578c5b380130a41a69b5b49c970157acaf1dbbDwight Engen return (uid_t)-1;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (*str >= '0' && *str <= '9') {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler uid = (uid_t)strtoul(str, &p, 10);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (*p == '\0')
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return uid;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler pw = getpwnam(str);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (pw == NULL) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (request != NULL) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler auth_request_log_error(request, "userdb",
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler "Invalid UID value '%s'", str);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return (uid_t)-1;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return pw->pw_uid;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler}
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilergid_t userdb_parse_gid(struct auth_request *request, const char *str)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler{
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler struct group *gr;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler gid_t gid;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler char *p;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (str == NULL)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return (gid_t)-1;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (*str >= '0' && *str <= '9') {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler gid = (gid_t)strtoul(str, &p, 10);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (*p == '\0')
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return gid;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler gr = getgrnam(str);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (gr == NULL) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (request != NULL) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler auth_request_log_error(request, "userdb",
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler "Invalid GID value '%s'", str);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return (gid_t)-1;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler return gr->gr_gid;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler}
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seilervoid userdb_preinit(struct auth *auth, const char *driver, const char *args)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler{
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler struct userdb_module_interface *iface;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler struct auth_userdb *auth_userdb, **dest;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (args == NULL) args = "";
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler auth_userdb = p_new(auth->pool, struct auth_userdb, 1);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler auth_userdb->auth = auth;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler auth_userdb->args = p_strdup(auth->pool, args);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler for (dest = &auth->userdbs; *dest != NULL; dest = &(*dest)->next)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler auth_userdb->num++;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler *dest = auth_userdb;
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler iface = userdb_interface_find(driver);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (iface == NULL)
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler i_fatal("Unknown userdb driver '%s'", driver);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (iface->lookup == NULL) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler i_fatal("Support not compiled in for userdb driver '%s'",
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler driver);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler }
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler if (iface->preinit == NULL) {
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler auth_userdb->userdb =
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler p_new(auth->pool, struct userdb_module, 1);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler } else {
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler auth_userdb->userdb =
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler iface->preinit(auth_userdb, auth_userdb->args);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler }
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler auth_userdb->userdb->iface = iface;
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler}
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler
037ba55cbee97bb9e1be95423c358ac1a7b33a2aDwight Engenvoid userdb_init(struct auth_userdb *userdb)
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler{
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler if (userdb->userdb->iface->init != NULL)
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler userdb->userdb->iface->init(userdb->userdb, userdb->args);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler if (userdb->userdb->blocking && !worker) {
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler /* blocking userdb - we need an auth server */
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler auth_worker_server_init();
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler }
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler}
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seilervoid userdb_deinit(struct auth_userdb *userdb)
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler{
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler if (userdb->userdb->iface->deinit != NULL)
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler userdb->userdb->iface->deinit(userdb->userdb);
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler}
e13eeea2db3743bf8d3fe2833e069a80e2c4102cChristian Seiler
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_prefetch;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_static;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_passwd;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_passwd_file;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_vpopmail;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_ldap;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_sql;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilerextern struct userdb_module_interface userdb_nss;
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilervoid userdbs_init(void)
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler{
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler i_array_init(&userdb_interfaces, 16);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_passwd);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_passwd_file);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_prefetch);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_static);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_vpopmail);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_ldap);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_sql);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler userdb_register_module(&userdb_nss);
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler}
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seilervoid userdbs_deinit(void)
7a0b0b5672a33c190eefb4b2d3e3693241c130f2Christian Seiler{
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler array_free(&userdb_interfaces);
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler}
49ee6cdcbf79d8b6fa617479ec8ab753ccca923dChristian Seiler