1 /* $OpenBSD: mailaddr.c,v 1.5 2021/06/14 17:58:15 eric 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 <stdlib.h>
20 #include <string.h>
21
22 #include "smtpd.h"
23 #include "log.h"
24
25 static int
mailaddr_line_split(char ** line,char ** ret)26 mailaddr_line_split(char **line, char **ret)
27 {
28 static char buffer[LINE_MAX];
29 int esc, dq, sq;
30 size_t i;
31 char *s;
32
33 memset(buffer, 0, sizeof buffer);
34 esc = dq = sq = 0;
35 i = 0;
36 for (s = *line; (*s) && (i < sizeof(buffer)); ++s) {
37 if (esc) {
38 buffer[i++] = *s;
39 esc = 0;
40 continue;
41 }
42 if (*s == '\\') {
43 esc = 1;
44 continue;
45 }
46 if (*s == ',' && !dq && !sq) {
47 *ret = buffer;
48 *line = s+1;
49 return (1);
50 }
51
52 buffer[i++] = *s;
53 esc = 0;
54
55 if (*s == '"' && !sq)
56 dq ^= 1;
57 if (*s == '\'' && !dq)
58 sq ^= 1;
59 }
60
61 if (esc || dq || sq || i == sizeof(buffer))
62 return (-1);
63
64 *ret = buffer;
65 *line = s;
66 return (i ? 1 : 0);
67 }
68
69 int
mailaddr_line(struct maddrmap * maddrmap,const char * s)70 mailaddr_line(struct maddrmap *maddrmap, const char *s)
71 {
72 struct maddrnode mn;
73 char *p, *subrcpt, *buffer;
74 int ret;
75
76 if ((buffer = strdup(s)) == NULL)
77 return 0;
78
79 p = buffer;
80 while ((ret = mailaddr_line_split(&p, &subrcpt)) > 0) {
81 subrcpt = strip(subrcpt);
82 if (subrcpt[0] == '\0')
83 continue;
84 if (!text_to_mailaddr(&mn.mailaddr, subrcpt)) {
85 free(buffer);
86 return 0;
87 }
88 log_debug("subrcpt: [%s]", subrcpt);
89 maddrmap_insert(maddrmap, &mn);
90 }
91
92 free(buffer);
93
94 if (ret >= 0)
95 return 1;
96 /* expand_line_split() returned < 0 */
97 return 0;
98 }
99
100 void
maddrmap_init(struct maddrmap * maddrmap)101 maddrmap_init(struct maddrmap *maddrmap)
102 {
103 TAILQ_INIT(&maddrmap->queue);
104 }
105
106 void
maddrmap_insert(struct maddrmap * maddrmap,struct maddrnode * maddrnode)107 maddrmap_insert(struct maddrmap *maddrmap, struct maddrnode *maddrnode)
108 {
109 struct maddrnode *mn;
110
111 mn = xmemdup(maddrnode, sizeof *maddrnode);
112 TAILQ_INSERT_TAIL(&maddrmap->queue, mn, entries);
113 }
114
115 void
maddrmap_free(struct maddrmap * maddrmap)116 maddrmap_free(struct maddrmap *maddrmap)
117 {
118 struct maddrnode *mn;
119
120 while ((mn = TAILQ_FIRST(&maddrmap->queue))) {
121 TAILQ_REMOVE(&maddrmap->queue, mn, entries);
122 free(mn);
123 }
124 free(maddrmap);
125 }
126