2b6cb0abecda0b1064403379e59fbed3ac8bfe58
[dragonfly.git] / libexec / dma / conf.c
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  * $DragonFly: src/libexec/dma/conf.c,v 1.2 2008/02/04 10:11:41 matthias Exp $
36  */
37
38 #include <err.h>
39 #include <errno.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <syslog.h>
44 #include <stdarg.h>
45
46 #include "dma.h"
47
48 #define DP      ": \t\n"
49 #define EQS     " \t\n"
50
51 extern struct virtusers virtusers;
52 extern struct authusers authusers;
53
54 /*
55  * Remove trailing \n's
56  */
57 void
58 trim_line(char *line)
59 {
60         size_t linelen;
61         char *p;
62
63         p = line;
64
65         if ((p = strchr(line, '\n')))
66                 *p = (char)0;
67
68         /* Escape leading dot in every case */
69         linelen = strlen(line);
70         if (line[0] == '.') {
71                 if ((linelen + 2) > 1000) {
72                         syslog(LOG_CRIT, "Cannot escape leading dot.  Buffer overflow");
73                         exit(1);
74                 }
75                 memmove((line + 1), line, (linelen + 1));
76                 line[0] = '.';
77         }
78 }
79
80 /*
81  * Add a virtual user entry to the list of virtual users
82  */
83 static void
84 add_virtuser(char *login, char *address)
85 {
86         struct virtuser *v;
87
88         v = malloc(sizeof(struct virtuser));
89         v->login = strdup(login);
90         v->address = strdup(address);
91         SLIST_INSERT_HEAD(&virtusers, v, next);
92 }
93
94 /*
95  * Read the virtual user table
96  */
97 int
98 parse_virtuser(const char *path)
99 {
100         FILE *v;
101         char *word;
102         char *data;
103         char line[2048];
104
105         v = fopen(path, "r");
106         if (v == NULL)
107                 return (-1);
108
109         while (!feof(v)) {
110                 if (fgets(line, sizeof(line), v) == NULL)
111                         break;
112                 /* We hit a comment */
113                 if (strchr(line, '#'))
114                         *strchr(line, '#') = 0;
115                 if ((word = strtok(line, DP)) != NULL) {
116                         data = strtok(NULL, DP);
117                         if (data != NULL) {
118                                 add_virtuser(word, data);
119                         }
120                 }
121         }
122
123         fclose(v);
124         return (0);
125 }
126
127 /*
128  * Add entry to the SMTP auth user list
129  */
130 static void
131 add_smtp_auth_user(char *userstring, char *password)
132 {
133         struct authuser *a;
134         char *temp;
135
136         a = malloc(sizeof(struct virtuser));
137         a->password= strdup(password);
138
139         temp = strrchr(userstring, '|');
140         if (temp == NULL)
141                 errx(1, "auth.conf file in wrong format");
142                 /* XXX don't use errx */
143
144         a->host = strdup(temp+1);
145         a->login = strdup(strtok(userstring, "|"));
146         if (a->login == NULL)
147                 errx(1, "auth.conf file in wrong format");
148
149         SLIST_INSERT_HEAD(&authusers, a, next);
150 }
151
152 /*
153  * Read the SMTP authentication config file
154  */
155 int
156 parse_authfile(const char *path)
157 {
158         FILE *a;
159         char *word;
160         char *data;
161         char line[2048];
162
163         a = fopen(path, "r");
164         if (a == NULL)
165                 return (-1);
166
167         while (!feof(a)) {
168                 if (fgets(line, sizeof(line), a) == NULL)
169                         break;
170                 /* We hit a comment */
171                 if (strchr(line, '#'))
172                         *strchr(line, '#') = 0;
173                 if ((word = strtok(line, DP)) != NULL) {
174                         data = strtok(NULL, DP);
175                         if (data != NULL) {
176                                 add_smtp_auth_user(word, data);
177                         }
178                 }
179         }
180
181         fclose(a);
182         return (0);
183 }
184
185 /*
186  * XXX TODO
187  * Check if the user supplied a value.  If not, fill in default
188  * Check for bad things[TM]
189  */
190 int
191 parse_conf(const char *config_path, struct config *config)
192 {
193         char *word;
194         char *data;
195         FILE *conf;
196         char line[2048];
197
198         conf = fopen(config_path, "r");
199         if (conf == NULL)
200                 return (-1);
201
202         /* Reset features */
203         config->features = 0;
204
205         while (!feof(conf)) {
206                 if (fgets(line, sizeof(line), conf) == NULL)
207                         break;
208                 /* We hit a comment */
209                 if (strchr(line, '#'))
210                         *strchr(line, '#') = 0;
211                 if ((word = strtok(line, EQS)) != NULL) {
212                         data = strtok(NULL, EQS);
213                         if (strcmp(word, "SMARTHOST") == 0) {
214                                 if (data != NULL)
215                                         config->smarthost = strdup(data);
216                         }
217                         else if (strcmp(word, "PORT") == 0) {
218                                 if (data != NULL)
219                                         config->port = atoi(strdup(data));
220                         }
221                         else if (strcmp(word, "ALIASES") == 0) {
222                                 if (data != NULL)
223                                         config->aliases = strdup(data);
224                         }
225                         else if (strcmp(word, "SPOOLDIR") == 0) {
226                                 if (data != NULL)
227                                         config->spooldir = strdup(data);
228                         }
229                         else if (strcmp(word, "VIRTPATH") == 0) {
230                                 if (data != NULL)
231                                         config->virtualpath = strdup(data);
232                         }
233                         else if (strcmp(word, "AUTHPATH") == 0) {
234                                 if (data != NULL)
235                                         config->authpath= strdup(data);
236                         }
237                         else if (strcmp(word, "CERTFILE") == 0) {
238                                 if (data != NULL)
239                                         config->certfile = strdup(data);
240                         }
241                         else if (strcmp(word, "MAILNAME") == 0) {
242                                 if (data != NULL)
243                                         config->mailname = strdup(data);
244                         }
245                         else if (strcmp(word, "MAILNAMEFILE") == 0) {
246                                 if (data != NULL)
247                                         config->mailnamefile = strdup(data);
248                         }
249                         else if (strcmp(word, "VIRTUAL") == 0)
250                                 config->features |= VIRTUAL;
251                         else if (strcmp(word, "STARTTLS") == 0)
252                                 config->features |= STARTTLS;
253                         else if (strcmp(word, "SECURETRANSFER") == 0)
254                                 config->features |= SECURETRANS;
255                         else if (strcmp(word, "DEFER") == 0)
256                                 config->features |= DEFER;
257                         else if (strcmp(word, "INSECURE") == 0)
258                                 config->features |= INSECURE;
259                         else if (strcmp(word, "FULLBOUNCE") == 0)
260                                 config->features |= FULLBOUNCE;
261                         else {
262                                 errno = EINVAL;
263                                 return (-1);
264                         }
265                 }
266         }
267
268         fclose(conf);
269         return (0);
270 }
271