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" 47 #define EQS " \t" 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 static void 77 chomp(char *str) 78 { 79 size_t len = strlen(str); 80 81 if (len == 0) 82 return; 83 if (str[len - 1] == '\n') 84 str[len - 1] = 0; 85 } 86 87 /* 88 * Read the virtual user table 89 */ 90 void 91 parse_virtuser(const char *path) 92 { 93 char line[2048]; 94 FILE *v; 95 char *data; 96 struct virtuser *vu; 97 int lineno = 0; 98 99 v = fopen(path, "r"); 100 if (v == NULL) { 101 errlog(1, "can not open virtuser file `%s'", path); 102 /* NOTREACHED */ 103 } 104 105 while (!feof(v)) { 106 if (fgets(line, sizeof(line), v) == NULL) 107 break; 108 lineno++; 109 110 chomp(line); 111 112 /* We hit a comment */ 113 if (*line == '#') 114 continue; 115 /* Ignore empty lines */ 116 if (*line == 0) 117 continue; 118 119 vu = calloc(1, sizeof(*vu)); 120 if (vu == NULL) 121 errlog(1, NULL); 122 123 data = strdup(line); 124 vu->login = strsep(&data, DP); 125 vu->address = data; 126 127 if (vu->login == NULL || 128 vu->address == NULL) { 129 errlogx(1, "syntax error in virtuser file %s:%d", 130 path, lineno); 131 /* NOTREACHED */ 132 } 133 134 SLIST_INSERT_HEAD(&virtusers, vu, next); 135 } 136 137 fclose(v); 138 } 139 140 /* 141 * Read the SMTP authentication config file 142 * 143 * file format is: 144 * user|host:password 145 * 146 * A line starting with # is treated as comment and ignored. 147 */ 148 void 149 parse_authfile(const char *path) 150 { 151 char line[2048]; 152 struct authuser *au; 153 FILE *a; 154 char *data; 155 int lineno = 0; 156 157 a = fopen(path, "r"); 158 if (a == NULL) { 159 errlog(1, "can not open auth file `%s'", path); 160 /* NOTREACHED */ 161 } 162 163 while (!feof(a)) { 164 if (fgets(line, sizeof(line), a) == NULL) 165 break; 166 lineno++; 167 168 chomp(line); 169 170 /* We hit a comment */ 171 if (*line == '#') 172 continue; 173 /* Ignore empty lines */ 174 if (*line == 0) 175 continue; 176 177 au = calloc(1, sizeof(*au)); 178 if (au == NULL) 179 errlog(1, NULL); 180 181 data = strdup(line); 182 au->login = strsep(&data, "|"); 183 au->host = strsep(&data, DP); 184 au->password = data; 185 186 if (au->login == NULL || 187 au->host == NULL || 188 au->password == NULL) { 189 errlogx(1, "syntax error in authfile %s:%d", 190 path, lineno); 191 /* NOTREACHED */ 192 } 193 194 SLIST_INSERT_HEAD(&authusers, au, next); 195 } 196 197 fclose(a); 198 } 199 200 /* 201 * XXX TODO 202 * Check for bad things[TM] 203 */ 204 void 205 parse_conf(const char *config_path) 206 { 207 char *word; 208 char *data; 209 FILE *conf; 210 char line[2048]; 211 int lineno = 0; 212 213 conf = fopen(config_path, "r"); 214 if (conf == NULL) { 215 /* Don't treat a non-existing config file as error */ 216 if (errno == ENOENT) 217 return; 218 errlog(1, "can not open config `%s'", config_path); 219 /* NOTREACHED */ 220 } 221 222 while (!feof(conf)) { 223 if (fgets(line, sizeof(line), conf) == NULL) 224 break; 225 lineno++; 226 227 chomp(line); 228 229 /* We hit a comment */ 230 if (strchr(line, '#')) 231 *strchr(line, '#') = 0; 232 233 data = line; 234 word = strsep(&data, EQS); 235 236 /* Ignore empty lines */ 237 if (word == NULL || *word == 0) 238 continue; 239 240 if (data != NULL && *data != 0) 241 data = strdup(data); 242 else 243 data = NULL; 244 245 if (strcmp(word, "SMARTHOST") == 0 && data != NULL) 246 config.smarthost = data; 247 else if (strcmp(word, "PORT") == 0 && data != NULL) 248 config.port = atoi(data); 249 else if (strcmp(word, "ALIASES") == 0 && data != NULL) 250 config.aliases = data; 251 else if (strcmp(word, "SPOOLDIR") == 0 && data != NULL) 252 config.spooldir = data; 253 else if (strcmp(word, "VIRTPATH") == 0 && data != NULL) 254 config.virtualpath = data; 255 else if (strcmp(word, "AUTHPATH") == 0 && data != NULL) 256 config.authpath= data; 257 else if (strcmp(word, "CERTFILE") == 0 && data != NULL) 258 config.certfile = data; 259 else if (strcmp(word, "MAILNAME") == 0 && data != NULL) 260 config.mailname = data; 261 else if (strcmp(word, "MAILNAMEFILE") == 0 && data != NULL) 262 config.mailnamefile = data; 263 else if (strcmp(word, "VIRTUAL") == 0 && data == NULL) 264 config.features |= VIRTUAL; 265 else if (strcmp(word, "STARTTLS") == 0 && data == NULL) 266 config.features |= STARTTLS; 267 else if (strcmp(word, "SECURETRANSFER") == 0 && data == NULL) 268 config.features |= SECURETRANS; 269 else if (strcmp(word, "DEFER") == 0 && data == NULL) 270 config.features |= DEFER; 271 else if (strcmp(word, "INSECURE") == 0 && data == NULL) 272 config.features |= INSECURE; 273 else if (strcmp(word, "FULLBOUNCE") == 0 && data == NULL) 274 config.features |= FULLBOUNCE; 275 else { 276 errlogx(1, "syntax error in %s:%d", config_path, lineno); 277 /* NOTREACHED */ 278 } 279 } 280 281 fclose(conf); 282 } 283