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