1 /* 2 * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthias Schmidt <matthias@dragonflybsd.org>, University of Marburg, 6 * Germany. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name of The DragonFly Project nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific, prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <err.h> 37 #include <errno.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <syslog.h> 42 #include <stdarg.h> 43 44 #include "dma.h" 45 46 #define DP ": \t\n" 47 #define EQS " \t\n" 48 49 50 /* 51 * Remove trailing \n's 52 */ 53 void 54 trim_line(char *line) 55 { 56 size_t linelen; 57 char *p; 58 59 p = line; 60 61 if ((p = strchr(line, '\n'))) 62 *p = (char)0; 63 64 /* Escape leading dot in every case */ 65 linelen = strlen(line); 66 if (line[0] == '.') { 67 if ((linelen + 2) > 1000) { 68 syslog(LOG_CRIT, "Cannot escape leading dot. Buffer overflow"); 69 exit(1); 70 } 71 memmove((line + 1), line, (linelen + 1)); 72 line[0] = '.'; 73 } 74 } 75 76 /* 77 * Add a virtual user entry to the list of virtual users 78 */ 79 static void 80 add_virtuser(char *login, char *address) 81 { 82 struct virtuser *v; 83 84 v = malloc(sizeof(struct virtuser)); 85 v->login = strdup(login); 86 v->address = strdup(address); 87 SLIST_INSERT_HEAD(&virtusers, v, next); 88 } 89 90 /* 91 * Read the virtual user table 92 */ 93 int 94 parse_virtuser(const char *path) 95 { 96 FILE *v; 97 char *word; 98 char *data; 99 char line[2048]; 100 101 v = fopen(path, "r"); 102 if (v == NULL) 103 return (-1); 104 105 while (!feof(v)) { 106 if (fgets(line, sizeof(line), v) == NULL) 107 break; 108 /* We hit a comment */ 109 if (strchr(line, '#')) 110 *strchr(line, '#') = 0; 111 if ((word = strtok(line, DP)) != NULL) { 112 data = strtok(NULL, DP); 113 if (data != NULL) { 114 add_virtuser(word, data); 115 } 116 } 117 } 118 119 fclose(v); 120 return (0); 121 } 122 123 /* 124 * Add entry to the SMTP auth user list 125 */ 126 static int 127 add_smtp_auth_user(char *userstring, char *password) 128 { 129 struct authuser *a; 130 char *temp; 131 132 a = malloc(sizeof(struct virtuser)); 133 a->password= strdup(password); 134 135 temp = strrchr(userstring, '|'); 136 if (temp == NULL) 137 return (-1); 138 139 a->host = strdup(temp+1); 140 a->login = strdup(strtok(userstring, "|")); 141 if (a->login == NULL) 142 return (-1); 143 144 SLIST_INSERT_HEAD(&authusers, a, next); 145 146 return (0); 147 } 148 149 /* 150 * Read the SMTP authentication config file 151 */ 152 int 153 parse_authfile(const char *path) 154 { 155 FILE *a; 156 char *word; 157 char *data; 158 char line[2048]; 159 160 a = fopen(path, "r"); 161 if (a == NULL) 162 return (-1); 163 164 while (!feof(a)) { 165 if (fgets(line, sizeof(line), a) == NULL) 166 break; 167 /* We hit a comment */ 168 if (strchr(line, '#')) 169 *strchr(line, '#') = 0; 170 if ((word = strtok(line, DP)) != NULL) { 171 data = strtok(NULL, DP); 172 if (data != NULL) { 173 if (add_smtp_auth_user(word, data) < 0) 174 return (-1); 175 } 176 } 177 } 178 179 fclose(a); 180 return (0); 181 } 182 183 /* 184 * XXX TODO 185 * Check if the user supplied a value. If not, fill in default 186 * Check for bad things[TM] 187 */ 188 int 189 parse_conf(const char *config_path) 190 { 191 char *word; 192 char *data; 193 FILE *conf; 194 char line[2048]; 195 196 conf = fopen(config_path, "r"); 197 if (conf == NULL) 198 return (-1); 199 200 /* Reset features */ 201 config->features = 0; 202 203 while (!feof(conf)) { 204 if (fgets(line, sizeof(line), conf) == NULL) 205 break; 206 /* We hit a comment */ 207 if (strchr(line, '#')) 208 *strchr(line, '#') = 0; 209 if ((word = strtok(line, EQS)) != NULL) { 210 data = strtok(NULL, EQS); 211 if (strcmp(word, "SMARTHOST") == 0) { 212 if (data != NULL) 213 config->smarthost = strdup(data); 214 } 215 else if (strcmp(word, "PORT") == 0) { 216 if (data != NULL) 217 config->port = atoi(strdup(data)); 218 } 219 else if (strcmp(word, "ALIASES") == 0) { 220 if (data != NULL) 221 config->aliases = strdup(data); 222 } 223 else if (strcmp(word, "SPOOLDIR") == 0) { 224 if (data != NULL) 225 config->spooldir = strdup(data); 226 } 227 else if (strcmp(word, "VIRTPATH") == 0) { 228 if (data != NULL) 229 config->virtualpath = strdup(data); 230 } 231 else if (strcmp(word, "AUTHPATH") == 0) { 232 if (data != NULL) 233 config->authpath= strdup(data); 234 } 235 else if (strcmp(word, "CERTFILE") == 0) { 236 if (data != NULL) 237 config->certfile = strdup(data); 238 } 239 else if (strcmp(word, "MAILNAME") == 0) { 240 if (data != NULL) 241 config->mailname = strdup(data); 242 } 243 else if (strcmp(word, "MAILNAMEFILE") == 0) { 244 if (data != NULL) 245 config->mailnamefile = strdup(data); 246 } 247 else if (strcmp(word, "VIRTUAL") == 0) 248 config->features |= VIRTUAL; 249 else if (strcmp(word, "STARTTLS") == 0) 250 config->features |= STARTTLS; 251 else if (strcmp(word, "SECURETRANSFER") == 0) 252 config->features |= SECURETRANS; 253 else if (strcmp(word, "DEFER") == 0) 254 config->features |= DEFER; 255 else if (strcmp(word, "INSECURE") == 0) 256 config->features |= INSECURE; 257 else if (strcmp(word, "FULLBOUNCE") == 0) 258 config->features |= FULLBOUNCE; 259 else { 260 errno = EINVAL; 261 return (-1); 262 } 263 } 264 } 265 266 fclose(conf); 267 return (0); 268 } 269 270