1 /* $OpenBSD: mailaddr.c,v 1.4 2020/09/22 18:04:27 martijn Exp $ */
2
3 /*
4 * Copyright (c) 2015 Gilles Chehade <gilles@poolp.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include "includes.h"
20
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 #include <sys/tree.h>
24 #include <sys/socket.h>
25
26 #include <ctype.h>
27 #include <event.h>
28 #include <imsg.h>
29 #include <stdio.h>
30 #include <limits.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "smtpd.h"
35 #include "log.h"
36
37 static int
mailaddr_line_split(char ** line,char ** ret)38 mailaddr_line_split(char **line, char **ret)
39 {
40 static char buffer[LINE_MAX];
41 int esc, dq, sq;
42 size_t i;
43 char *s;
44
45 memset(buffer, 0, sizeof buffer);
46 esc = dq = sq = 0;
47 i = 0;
48 for (s = *line; (*s) && (i < sizeof(buffer)); ++s) {
49 if (esc) {
50 buffer[i++] = *s;
51 esc = 0;
52 continue;
53 }
54 if (*s == '\\') {
55 esc = 1;
56 continue;
57 }
58 if (*s == ',' && !dq && !sq) {
59 *ret = buffer;
60 *line = s+1;
61 return (1);
62 }
63
64 buffer[i++] = *s;
65 esc = 0;
66
67 if (*s == '"' && !sq)
68 dq ^= 1;
69 if (*s == '\'' && !dq)
70 sq ^= 1;
71 }
72
73 if (esc || dq || sq || i == sizeof(buffer))
74 return (-1);
75
76 *ret = buffer;
77 *line = s;
78 return (i ? 1 : 0);
79 }
80
81 int
mailaddr_line(struct maddrmap * maddrmap,const char * s)82 mailaddr_line(struct maddrmap *maddrmap, const char *s)
83 {
84 struct maddrnode mn;
85 char *p, *subrcpt, *buffer;
86 int ret;
87
88 if ((buffer = strdup(s)) == NULL)
89 return 0;
90
91 p = buffer;
92 while ((ret = mailaddr_line_split(&p, &subrcpt)) > 0) {
93 subrcpt = strip(subrcpt);
94 if (subrcpt[0] == '\0')
95 continue;
96 if (!text_to_mailaddr(&mn.mailaddr, subrcpt)) {
97 free(buffer);
98 return 0;
99 }
100 log_debug("subrcpt: [%s]", subrcpt);
101 maddrmap_insert(maddrmap, &mn);
102 }
103
104 free(buffer);
105
106 if (ret >= 0)
107 return 1;
108 /* expand_line_split() returned < 0 */
109 return 0;
110 }
111
112 void
maddrmap_init(struct maddrmap * maddrmap)113 maddrmap_init(struct maddrmap *maddrmap)
114 {
115 TAILQ_INIT(&maddrmap->queue);
116 }
117
118 void
maddrmap_insert(struct maddrmap * maddrmap,struct maddrnode * maddrnode)119 maddrmap_insert(struct maddrmap *maddrmap, struct maddrnode *maddrnode)
120 {
121 struct maddrnode *mn;
122
123 mn = xmemdup(maddrnode, sizeof *maddrnode);
124 TAILQ_INSERT_TAIL(&maddrmap->queue, mn, entries);
125 }
126
127 void
maddrmap_free(struct maddrmap * maddrmap)128 maddrmap_free(struct maddrmap *maddrmap)
129 {
130 struct maddrnode *mn;
131
132 while ((mn = TAILQ_FIRST(&maddrmap->queue))) {
133 TAILQ_REMOVE(&maddrmap->queue, mn, entries);
134 free(mn);
135 }
136 free(maddrmap);
137 }
138