1 /*	$OpenBSD: to.c,v 1.17 2014/04/19 14:27:29 gilles Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
5  * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
6  * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 #include <sys/tree.h>
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <sys/resource.h>
27 
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 
31 #include <ctype.h>
32 #include <err.h>
33 #include <errno.h>
34 #include <event.h>
35 #include <fcntl.h>
36 #include <fts.h>
37 #include <imsg.h>
38 #include <inttypes.h>
39 #include <libgen.h>
40 #include <netdb.h>
41 #include <pwd.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <unistd.h>
48 
49 #include "smtpd-defines.h"
50 #include <smtpd-api.h>
51 #include "log.h"
52 
53 static const char *in6addr_to_text(const struct in6_addr *);
54 
55 const char *
sockaddr_to_text(struct sockaddr * sa)56 sockaddr_to_text(struct sockaddr *sa)
57 {
58 	static char	buf[NI_MAXHOST];
59 
60 	if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0,
61 	    NI_NUMERICHOST))
62 		return ("(unknown)");
63 	else
64 		return (buf);
65 }
66 
67 static const char *
in6addr_to_text(const struct in6_addr * addr)68 in6addr_to_text(const struct in6_addr *addr)
69 {
70 	struct sockaddr_in6	sa_in6;
71 	uint16_t		tmp16;
72 
73 	memset(&sa_in6, 0, sizeof(sa_in6));
74 	sa_in6.sin6_len = sizeof(sa_in6);
75 	sa_in6.sin6_family = AF_INET6;
76 	memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr));
77 
78 	/* XXX thanks, KAME, for this ugliness... adopted from route/show.c */
79 	if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) ||
80 	    IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) {
81 		memcpy(&tmp16, &sa_in6.sin6_addr.s6_addr[2], sizeof(tmp16));
82 		sa_in6.sin6_scope_id = ntohs(tmp16);
83 		sa_in6.sin6_addr.s6_addr[2] = 0;
84 		sa_in6.sin6_addr.s6_addr[3] = 0;
85 	}
86 
87 	return (sockaddr_to_text((struct sockaddr *)&sa_in6));
88 }
89 
90 int
text_to_mailaddr(struct mailaddr * maddr,const char * email)91 text_to_mailaddr(struct mailaddr *maddr, const char *email)
92 {
93 	char *username;
94 	char *hostname;
95 	char  buffer[LINE_MAX];
96 
97 	if (strlcpy(buffer, email, sizeof buffer) >= sizeof buffer)
98 		return 0;
99 
100 	memset(maddr, 0, sizeof *maddr);
101 
102 	username = buffer;
103 	hostname = strrchr(username, '@');
104 
105 	if (hostname == NULL) {
106 		if (strlcpy(maddr->user, username, sizeof maddr->user)
107 		    >= sizeof maddr->user)
108 			return 0;
109 	}
110 	else if (username == hostname) {
111 		*hostname++ = '\0';
112 		if (strlcpy(maddr->domain, hostname, sizeof maddr->domain)
113 		    >= sizeof maddr->domain)
114 			return 0;
115 	}
116 	else {
117 		*hostname++ = '\0';
118 		if (strlcpy(maddr->user, username, sizeof maddr->user)
119 		    >= sizeof maddr->user)
120 			return 0;
121 		if (strlcpy(maddr->domain, hostname, sizeof maddr->domain)
122 		    >= sizeof maddr->domain)
123 			return 0;
124 	}
125 
126 	return 1;
127 }
128 
129 const char *
mailaddr_to_text(const struct mailaddr * maddr)130 mailaddr_to_text(const struct mailaddr *maddr)
131 {
132 	static char  buffer[LINE_MAX];
133 
134 	(void)strlcpy(buffer, maddr->user, sizeof buffer);
135 	(void)strlcat(buffer, "@", sizeof buffer);
136 	if (strlcat(buffer, maddr->domain, sizeof buffer) >= sizeof buffer)
137 		return NULL;
138 
139 	return buffer;
140 }
141 
142 
143 const char *
sa_to_text(const struct sockaddr * sa)144 sa_to_text(const struct sockaddr *sa)
145 {
146 	static char	 buf[NI_MAXHOST + 5];
147 	char		*p;
148 
149 	buf[0] = '\0';
150 	p = buf;
151 
152 	if (sa->sa_family == AF_LOCAL)
153 		(void)strlcpy(buf, "local", sizeof buf);
154 	else if (sa->sa_family == AF_INET) {
155 		in_addr_t addr;
156 
157 		addr = ((const struct sockaddr_in *)sa)->sin_addr.s_addr;
158 		addr = ntohl(addr);
159 		(void)snprintf(p, NI_MAXHOST, "%d.%d.%d.%d",
160 		    (addr >> 24) & 0xff, (addr >> 16) & 0xff,
161 		    (addr >> 8) & 0xff, addr & 0xff);
162 	}
163 	else if (sa->sa_family == AF_INET6) {
164 		const struct sockaddr_in6 *in6;
165 		const struct in6_addr	*in6_addr;
166 
167 		in6 = (const struct sockaddr_in6 *)sa;
168 		(void)strlcpy(buf, "IPv6:", sizeof(buf));
169 		p = buf + 5;
170 		in6_addr = &in6->sin6_addr;
171 		(void)snprintf(p, NI_MAXHOST, "%s", in6addr_to_text(in6_addr));
172 	}
173 
174 	return (buf);
175 }
176 
177 const char *
ss_to_text(const struct sockaddr_storage * ss)178 ss_to_text(const struct sockaddr_storage *ss)
179 {
180 	return (sa_to_text((const struct sockaddr*)ss));
181 }
182 
183 const char *
time_to_text(time_t when)184 time_to_text(time_t when)
185 {
186 	struct tm *lt;
187 	static char buf[40];
188 	char *day[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
189 	char *month[] = {"Jan","Feb","Mar","Apr","May","Jun",
190 			 "Jul","Aug","Sep","Oct","Nov","Dec"};
191 	int ret;
192 
193 	lt = localtime(&when);
194 	if (lt == NULL || when == 0)
195 		fatalx("time_to_text: localtime");
196 
197 	/* We do not use strftime because it is subject to locale substitution*/
198 	ret = snprintf(buf, sizeof(buf),
199 	    "%s, %d %s %d %02d:%02d:%02d %c%02d%02d (%s)",
200 	    day[lt->tm_wday], lt->tm_mday, month[lt->tm_mon],
201 	    lt->tm_year + 1900,
202 	    lt->tm_hour, lt->tm_min, lt->tm_sec,
203 	    lt->tm_gmtoff >= 0 ? '+' : '-',
204 	    abs((int)lt->tm_gmtoff / 3600),
205 	    abs((int)lt->tm_gmtoff % 3600) / 60,
206 	    lt->tm_zone);
207 	if (ret == -1 || ret >= sizeof (buf))
208 		fatalx("time_to_text: snprintf");
209 
210 	return buf;
211 }
212 
213 const char *
duration_to_text(time_t t)214 duration_to_text(time_t t)
215 {
216 	static char	dst[64];
217 	char		buf[64];
218 	int		h, m, s;
219 	long long	d;
220 
221 	if (t == 0) {
222 		(void)strlcpy(dst, "0s", sizeof dst);
223 		return (dst);
224 	}
225 
226 	dst[0] = '\0';
227 	if (t < 0) {
228 		(void)strlcpy(dst, "-", sizeof dst);
229 		t = -t;
230 	}
231 
232 	s = t % 60;
233 	t /= 60;
234 	m = t % 60;
235 	t /= 60;
236 	h = t % 24;
237 	d = t / 24;
238 
239 	if (d) {
240 		(void)snprintf(buf, sizeof buf, "%lldd", d);
241 		(void)strlcat(dst, buf, sizeof dst);
242 	}
243 	if (h) {
244 		(void)snprintf(buf, sizeof buf, "%dh", h);
245 		(void)strlcat(dst, buf, sizeof dst);
246 	}
247 	if (m) {
248 		(void)snprintf(buf, sizeof buf, "%dm", m);
249 		(void)strlcat(dst, buf, sizeof dst);
250 	}
251 	if (s) {
252 		(void)snprintf(buf, sizeof buf, "%ds", s);
253 		(void)strlcat(dst, buf, sizeof dst);
254 	}
255 
256 	return (dst);
257 }
258 
259 uint64_t
text_to_evpid(const char * s)260 text_to_evpid(const char *s)
261 {
262 	uint64_t ulval;
263 	char	 *ep;
264 
265 	errno = 0;
266 	ulval = strtoull(s, &ep, 16);
267 	if (s[0] == '\0' || *ep != '\0')
268 		return 0;
269 	if (errno == ERANGE && ulval == ULLONG_MAX)
270 		return 0;
271 	if (ulval == 0)
272 		return 0;
273 	return (ulval);
274 }
275 
276 uint32_t
text_to_msgid(const char * s)277 text_to_msgid(const char *s)
278 {
279 	uint64_t ulval;
280 	char	 *ep;
281 
282 	errno = 0;
283 	ulval = strtoull(s, &ep, 16);
284 	if (s[0] == '\0' || *ep != '\0')
285 		return 0;
286 	if (errno == ERANGE && ulval == ULLONG_MAX)
287 		return 0;
288 	if (ulval == 0)
289 		return 0;
290 	if (ulval > 0xffffffff)
291 		return 0;
292 	return (ulval & 0xffffffff);
293 }
294