Download | Plain Text | No Line Numbers


  1. /*
  2.  * Copyright (c) 2016, Manuel Mausz <manuel at mausz dot at>,
  3.  * All rights reserved.
  4.  *
  5.  * Some maildir specified code is copied from dovecot (dovecot.org),
  6.  * Copyright by Timo Sirainen <tss at iki dot fi> (and others).
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with this library; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  21.  * MA 02110-1301 USA
  22.  */
  23.  
  24. #include <ctype.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28.  
  29. #include <vpopmail.h>
  30. #include <vauth.h>
  31.  
  32. #define LOGPREFIX "USERLOOKUP: "
  33.  
  34. static void my_lowerit(char *s)
  35. {
  36. unsigned char x;
  37. while ((x = *s)) {
  38. if (isupper(x))
  39. *s = tolower(x);
  40. ++s;
  41. }
  42. }
  43.  
  44. struct my_email {
  45. char user[MAX_PW_NAME + 1];
  46. char domain[MAX_PW_DOMAIN + 1];
  47. };
  48.  
  49. static int my_parse_email(const char *address, struct my_email *email)
  50. {
  51. static char buf[MAX_BUFF] = { 0 };
  52. char *user, *domain;
  53.  
  54. if (strlcpy(buf, address, sizeof(buf)) >= sizeof(buf))
  55. return -1;
  56. if ((domain = strchr(buf, '@')) == NULL)
  57. return -1;
  58. *domain++ = '\0';
  59. user = buf;
  60.  
  61. my_lowerit(user);
  62. my_lowerit(domain);
  63. if (is_username_valid(user) != 0 || is_domain_valid(domain) != 0)
  64. return -1;
  65.  
  66. if (strlcpy(email->user, user, sizeof(email->user)) >= sizeof(email->user)
  67. || strlcpy(email->domain, domain, sizeof(email->domain)) >= sizeof(email->domain))
  68. return -1;
  69. return 0;
  70. }
  71.  
  72. int my_lookup_destination(const char *address, unsigned recursion)
  73. {
  74. if (recursion >= 10) {
  75. (void)fprintf(stderr, LOGPREFIX "Recursion limit reached\n");
  76. return -1;
  77. }
  78.  
  79. struct my_email email;
  80. if (my_parse_email(address, &email) != 0) {
  81. (void)fprintf(stderr, LOGPREFIX "Invalid email address\n");
  82. return -1;
  83. }
  84.  
  85. // lookup domain and do an in-place replace in case of an alias domain
  86. if (vget_assign(email.domain, NULL, 0, NULL, NULL) == NULL)
  87. return 0;
  88.  
  89. // lookup user
  90. struct vqpasswd *user_passwd = vauth_getpw(email.user, email.domain);
  91. if (user_passwd != NULL) {
  92. printf("SDTUSER=%s@%s\n", email.user, email.domain);
  93. return 0;
  94. }
  95.  
  96. // lookup alias/forwards. bail out if no or more than one forward
  97. char *action, *dash, *forward = NULL;
  98. static char buf[MAX_ALIAS_LINE];
  99. action = valias_select(email.user, email.domain);
  100. if ((action = valias_select(email.user, email.domain)) == NULL
  101. && (dash = strchr(email.user, '-')) != NULL) {
  102. *dash = '\0';
  103. strcat(email.user, "-default");
  104. action = valias_select(email.user, email.domain);
  105. }
  106. for (; action != NULL; action = valias_select_next()) {
  107. if (!*action || *action == '#' || *action == '|' || *action == '.' || *action == '/')
  108. continue;
  109. if (forward != NULL) // more than one forward
  110. return 0;
  111. if (strlcpy(buf, action, sizeof(buf)) >= sizeof(buf))
  112. return -1;
  113. forward = buf;
  114. }
  115. if (forward == NULL) // no forward found
  116. return 0;
  117.  
  118. if (*forward == '&')
  119. forward++;
  120. return my_lookup_destination(forward, ++recursion);
  121. }
  122.  
  123. int main()
  124. {
  125. const char *address;
  126. if ((address = getenv("SMTPRCPTTO")) != NULL)
  127. my_lookup_destination(address, 1);
  128.  
  129. return 0;
  130. }
  131.  
  132.