/* * Copyright (c) 2016, Manuel Mausz , * All rights reserved. * * Some maildir specified code is copied from dovecot (dovecot.org), * Copyright by Timo Sirainen (and others). * * 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 2.1 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include #include #include #include #include #include #define LOGPREFIX "USERLOOKUP: " static void my_lowerit(char *s) { unsigned char x; while ((x = *s)) { if (isupper(x)) *s = tolower(x); ++s; } } struct my_email { char user[MAX_PW_NAME + 1]; char domain[MAX_PW_DOMAIN + 1]; }; static int my_parse_email(const char *address, struct my_email *email) { static char buf[MAX_BUFF] = { 0 }; char *user, *domain; if (strlcpy(buf, address, sizeof(buf)) >= sizeof(buf)) return -1; if ((domain = strchr(buf, '@')) == NULL) return -1; *domain++ = '\0'; user = buf; my_lowerit(user); my_lowerit(domain); if (is_username_valid(user) != 0 || is_domain_valid(domain) != 0) return -1; if (strlcpy(email->user, user, sizeof(email->user)) >= sizeof(email->user) || strlcpy(email->domain, domain, sizeof(email->domain)) >= sizeof(email->domain)) return -1; return 0; } int my_lookup_destination(const char *address, unsigned recursion) { if (recursion >= 10) { (void)fprintf(stderr, LOGPREFIX "Recursion limit reached\n"); return -1; } struct my_email email; if (my_parse_email(address, &email) != 0) { (void)fprintf(stderr, LOGPREFIX "Invalid email address\n"); return -1; } // lookup domain and do an in-place replace in case of an alias domain if (vget_assign(email.domain, NULL, 0, NULL, NULL) == NULL) return 0; // lookup user struct vqpasswd *user_passwd = vauth_getpw(email.user, email.domain); if (user_passwd != NULL) { printf("SDTUSER=%s@%s\n", email.user, email.domain); return 0; } // lookup alias/forwards. bail out if no or more than one forward char *action, *dash, *forward = NULL; static char buf[MAX_ALIAS_LINE]; action = valias_select(email.user, email.domain); if ((action = valias_select(email.user, email.domain)) == NULL && (dash = strchr(email.user, '-')) != NULL) { *dash = '\0'; strcat(email.user, "-default"); action = valias_select(email.user, email.domain); } for (; action != NULL; action = valias_select_next()) { if (!*action || *action == '#' || *action == '|' || *action == '.' || *action == '/') continue; if (forward != NULL) // more than one forward return 0; if (strlcpy(buf, action, sizeof(buf)) >= sizeof(buf)) return -1; forward = buf; } if (forward == NULL) // no forward found return 0; if (*forward == '&') forward++; return my_lookup_destination(forward, ++recursion); } int main() { const char *address; if ((address = getenv("SMTPRCPTTO")) != NULL) my_lookup_destination(address, 1); return 0; }