xref: /openbsd/usr.sbin/smtpd/mailaddr.c (revision d3140113)
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