Download | Plain Text | Line Numbers
/*
* Copyright (c) 2016, Manuel Mausz <manuel at mausz dot at>,
* All rights reserved.
*
* Some maildir specified code is copied from dovecot (dovecot.org),
* Copyright by Timo Sirainen <tss at iki dot fi> (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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vpopmail.h>
#include <vauth.h>
#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;
}