xref: /openbsd/usr.sbin/smtpd/mailaddr.c (revision 4cfece93)
1 /*	$OpenBSD: mailaddr.c,v 1.3 2018/05/31 21:06:12 gilles 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 <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/tree.h>
22 #include <sys/socket.h>
23 
24 #include <ctype.h>
25 #include <event.h>
26 #include <imsg.h>
27 #include <stdio.h>
28 #include <limits.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "smtpd.h"
33 #include "log.h"
34 
35 static int
36 mailaddr_line_split(char **line, char **ret)
37 {
38 	static char	buffer[LINE_MAX];
39 	int		esc, dq, sq;
40 	size_t		i;
41 	char	       *s;
42 
43 	memset(buffer, 0, sizeof buffer);
44 	esc = dq = sq = 0;
45 	i = 0;
46 	for (s = *line; (*s) && (i < sizeof(buffer)); ++s) {
47 		if (esc) {
48 			buffer[i++] = *s;
49 			esc = 0;
50 			continue;
51 		}
52 		if (*s == '\\') {
53 			esc = 1;
54 			continue;
55 		}
56 		if (*s == ',' && !dq && !sq) {
57 			*ret = buffer;
58 			*line = s+1;
59 			return (1);
60 		}
61 
62 		buffer[i++] = *s;
63 		esc = 0;
64 
65 		if (*s == '"' && !sq)
66 			dq ^= 1;
67 		if (*s == '\'' && !dq)
68 			sq ^= 1;
69 	}
70 
71 	if (esc || dq || sq || i == sizeof(buffer))
72 		return (-1);
73 
74 	*ret = buffer;
75 	*line = s;
76 	return (i ? 1 : 0);
77 }
78 
79 int
80 mailaddr_line(struct maddrmap *maddrmap, const char *s)
81 {
82 	struct maddrnode	mn;
83 	char			buffer[LINE_MAX];
84 	char		       *p, *subrcpt;
85 	int			ret;
86 
87 	memset(buffer, 0, sizeof buffer);
88 	if (strlcpy(buffer, s, sizeof buffer) >= sizeof buffer)
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 			return 0;
98 		log_debug("subrcpt: [%s]", subrcpt);
99 		maddrmap_insert(maddrmap, &mn);
100 	}
101 
102 	if (ret >= 0)
103 		return 1;
104 	/* expand_line_split() returned < 0 */
105 	return 0;
106 }
107 
108 void
109 maddrmap_init(struct maddrmap *maddrmap)
110 {
111 	TAILQ_INIT(&maddrmap->queue);
112 }
113 
114 void
115 maddrmap_insert(struct maddrmap *maddrmap, struct maddrnode *maddrnode)
116 {
117 	struct maddrnode	*mn;
118 
119 	mn = xmemdup(maddrnode, sizeof *maddrnode);
120 	TAILQ_INSERT_TAIL(&maddrmap->queue, mn, entries);
121 }
122 
123 void
124 maddrmap_free(struct maddrmap *maddrmap)
125 {
126 	struct maddrnode       *mn;
127 
128 	while ((mn = TAILQ_FIRST(&maddrmap->queue))) {
129 		TAILQ_REMOVE(&maddrmap->queue, mn, entries);
130 		free(mn);
131 	}
132 	free(maddrmap);
133 }
134