/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2002-2021 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #ifdef HAVE_SHADOW_H # include #endif #include #include #include #include #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SECURITY_PAM_APPL_H # include #endif #ifdef HAVE_CRYPT_H # include #endif #include #include #include #include #include /*FIXME!*/ #include #include #include #include #include #include #include #include #ifdef ENABLE_VIRTUAL_DOMAINS static char *pwddir = { SITE_VIRTUAL_PWDDIR }; static struct mu_cfg_param mu_virtdomain_param[] = { { "passwd-dir", mu_c_string, &pwddir, 0, NULL, N_("Name of the directory where virtual domain password files are " "located."), N_("dir") }, { NULL } }; #if !HAVE_FGETPWENT /* FIXME: A temporary solution. Need proper declaration in .h */ extern struct passwd *mu_fgetpwent (FILE *fp); #define fgetpwent mu_fgetpwent #endif static struct passwd * getpwnam_virtual (const char *u) { struct passwd *pw = NULL; FILE *pfile; size_t i = 0, len = strlen (u), delim = 0; char *filename; for (i = 0; i < len && delim == 0; i++) if (u[i] == '!' || u[i] == ':' || u[i] == '@') delim = i; if (delim == 0) return NULL; filename = mu_make_file_name (pwddir, &u[delim + 1]); if (filename == NULL) return NULL; pfile = fopen (filename, "r"); free (filename); if (pfile) { while ((pw = fgetpwent (pfile)) != NULL) { if (strlen (pw->pw_name) == delim && strncmp (u, pw->pw_name, delim) == 0) break; } fclose (pfile); } return pw; } static struct passwd * getpwnam_ip_virtual (const char *u) { struct sockaddr_in addr; struct passwd *pw = NULL; socklen_t len = sizeof (addr); if (getsockname (0, (struct sockaddr *)&addr, &len) == 0) { char *ip; char *user; struct hostent *info = gethostbyaddr ((char *)&addr.sin_addr, 4, AF_INET); if (info) { user = malloc (strlen (info->h_name) + strlen (u) + 2); if (user) { sprintf (user, "%s!%s", u, info->h_name); pw = getpwnam_virtual (user); free (user); } } if (!pw) { ip = inet_ntoa (addr.sin_addr); user = malloc (strlen (ip) + strlen (u) + 2); if (user) { sprintf (user, "%s!%s", u, ip); pw = getpwnam_virtual (user); free (user); } } } return pw; } /* Virtual domains */ static int mu_auth_virt_domain_by_name (struct mu_auth_data **return_data, const void *key, void *unused_func_data, void *unused_call_data) { int rc; struct passwd *pw; char *mailbox_name; if (!key) return EINVAL; pw = getpwnam_virtual (key); if (!pw) { pw = getpwnam_ip_virtual (key); if (!pw) return MU_ERR_AUTH_FAILURE; } mailbox_name = mu_make_file_name (pw->pw_dir, "INBOX"); if (!mailbox_name) return ENOMEM; rc = mu_auth_data_alloc (return_data, pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell, mailbox_name, 0); free (mailbox_name); return rc; } #else # define mu_virtdomain_param NULL # define mu_auth_virt_domain_by_name NULL #endif struct mu_auth_module mu_auth_virtual_module = { .name = "virtdomain", .cfg = mu_virtdomain_param, .handler = { [mu_auth_getpwnam] = mu_auth_virt_domain_by_name, } };