1 /*
2  * PgBouncer - Lightweight connection pooler for PostgreSQL.
3  *
4  * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
5  *
6  * Permission to use, copy, modify, and/or 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 /*
20  * Random small utility functions
21  */
22 
23 #include "bouncer.h"
24 
25 #include <usual/crypto/md5.h>
26 #include <usual/crypto/csrandom.h>
27 
log_socket_prefix(enum LogLevel lev,void * ctx,char * dst,unsigned int dstlen)28 int log_socket_prefix(enum LogLevel lev, void *ctx, char *dst, unsigned int dstlen)
29 {
30 	const struct PgSocket *sock = ctx;
31 	const char *user, *db, *host;
32 	char host6[PGADDR_BUF];
33 	int port;
34 	char stype;
35 
36 	/* no prefix */
37 	if (!sock)
38 		return 0;
39 
40 	/* format prefix */
41 	stype = is_server_socket(sock) ? 'S' : 'C';
42 	port = pga_port(&sock->remote_addr);
43 	db = sock->pool ? sock->pool->db->name : "(nodb)";
44 	user = sock->login_user ? sock->login_user->name : "(nouser)";
45 	if (pga_is_unix(&sock->remote_addr)) {
46 		unsigned long pid = sock->remote_addr.scred.pid;
47 		if (pid) {
48 			snprintf(host6, sizeof(host6), "unix(%lu)", pid);
49 			host = host6;
50 		} else {
51 			host = "unix";
52 		}
53 	} else {
54 		host = pga_ntop(&sock->remote_addr, host6, sizeof(host6));
55 	}
56 
57 	if (pga_family(&sock->remote_addr) == AF_INET6) {
58 		return snprintf(dst, dstlen, "%c-%p: %s/%s@[%s]:%d ",
59 			stype, sock, db, user, host, port);
60 	} else {
61 		return snprintf(dst, dstlen, "%c-%p: %s/%s@%s:%d ",
62 			stype, sock, db, user, host, port);
63 	}
64 }
65 
bin2hex(const uint8_t * src,unsigned srclen,char * dst,unsigned dstlen)66 const char *bin2hex(const uint8_t *src, unsigned srclen, char *dst, unsigned dstlen)
67 {
68 	unsigned int i, j;
69 	static const char hextbl [] = "0123456789abcdef";
70 	if (!dstlen)
71 		return "";
72 	if (srclen*2+1 > dstlen)
73 		srclen = (dstlen - 1) / 2;
74 	for (i = j = 0; i < srclen; i++) {
75 		dst[j++] = hextbl[src[i] >> 4];
76 		dst[j++] = hextbl[src[i] & 15];
77 	}
78 	dst[j] = 0;
79 	return dst;
80 }
81 
82 /*
83  * PostgreSQL MD5 hashing.
84  */
85 
hash2hex(const uint8_t * hash,char * dst)86 static void hash2hex(const uint8_t *hash, char *dst)
87 {
88 	bin2hex(hash, MD5_DIGEST_LENGTH, dst, 16*2+1);
89 }
90 
pg_md5_encrypt(const char * part1,const char * part2,size_t part2len,char * dest)91 void pg_md5_encrypt(const char *part1,
92 		    const char *part2, size_t part2len,
93 		    char *dest)
94 {
95 	struct md5_ctx ctx;
96 	uint8_t hash[MD5_DIGEST_LENGTH];
97 
98 	md5_reset(&ctx);
99 	md5_update(&ctx, part1, strlen(part1));
100 	md5_update(&ctx, part2, part2len);
101 	md5_final(&ctx, hash);
102 
103 	memcpy(dest, "md5", 3);
104 	hash2hex(hash, dest + 3);
105 }
106 
107 /* wrapped for getting random bytes */
get_random_bytes(uint8_t * dest,int len)108 void get_random_bytes(uint8_t *dest, int len)
109 {
110 	csrandom_bytes(dest, len);
111 }
112 
113 /* set needed socket options */
tune_socket(int sock,bool is_unix)114 bool tune_socket(int sock, bool is_unix)
115 {
116 	int res;
117 	int val;
118 	const char *errpos;
119 	bool ok;
120 
121 	/*
122 	 * Generic stuff + nonblock.
123 	 */
124 	errpos = "socket_setup";
125 	ok = socket_setup(sock, true);
126 	if (!ok)
127 		goto fail;
128 
129 	/*
130 	 * Following options are for network sockets
131 	 */
132 	if (is_unix)
133 		return true;
134 
135 	/*
136 	 * TCP Keepalive
137 	 */
138 	errpos = "socket_set_keepalive";
139 	ok = socket_set_keepalive(sock, cf_tcp_keepalive, cf_tcp_keepidle,
140 				  cf_tcp_keepintvl, cf_tcp_keepcnt);
141 	if (!ok)
142 		goto fail;
143 
144 	/*
145 	 * TCP user timeout
146 	 */
147 	if (cf_tcp_user_timeout) {
148 		errpos = "setsockopt/TCP_USER_TIMEOUT";
149 #ifdef TCP_USER_TIMEOUT
150 		val = cf_tcp_user_timeout;
151 		res = setsockopt(sock, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, sizeof(val));
152 		if (res < 0)
153 			goto fail;
154 #else
155 		errno = EINVAL;
156 		goto fail;
157 #endif
158 	}
159 
160 	/*
161 	 * set in-kernel socket buffer size
162 	 */
163 	if (cf_tcp_socket_buffer) {
164 		val = cf_tcp_socket_buffer;
165 		errpos = "setsockopt/SO_SNDBUF";
166 		res = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
167 		if (res < 0)
168 			goto fail;
169 		val = cf_tcp_socket_buffer;
170 		errpos = "setsockopt/SO_RCVBUF";
171 		res = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val));
172 		if (res < 0)
173 			goto fail;
174 	}
175 
176 	/*
177 	 * Turn off kernel buffering, each send() will be one packet.
178 	 */
179 	val = 1;
180 	errpos = "setsockopt/TCP_NODELAY";
181 	res = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
182 	if (res < 0)
183 		goto fail;
184 	return true;
185 fail:
186 	log_warning("%s(%d) failed: %s", errpos, sock, strerror(errno));
187 	return false;
188 }
189 
190 /*
191  * Find a string in comma-separated list.
192  *
193  * It does not support space inside tokens.
194  */
strlist_contains(const char * liststr,const char * str)195 bool strlist_contains(const char *liststr, const char *str)
196 {
197 	int c, len = strlen(str);
198 	const char *p, *listpos = liststr;
199 
200 loop:
201 	/* find string fragment, later check if actual token */
202 	p = strstr(listpos, str);
203 	if (p == NULL)
204 		return false;
205 
206 	/* move listpos further */
207 	listpos = p + len;
208 	/* survive len=0 and avoid unnecessary compare */
209 	if (*listpos)
210 		listpos++;
211 
212 	/* check previous symbol */
213 	if (p > liststr) {
214 		c = *(p - 1);
215 		if (!isspace(c) && c != ',')
216 			goto loop;
217 	}
218 
219 	/* check following symbol */
220 	c = p[len];
221 	if (c != 0 && !isspace(c) && c != ',')
222 		goto loop;
223 
224 	return true;
225 }
226 
fill_remote_addr(PgSocket * sk,int fd,bool is_unix)227 void fill_remote_addr(PgSocket *sk, int fd, bool is_unix)
228 {
229 	PgAddr *dst = &sk->remote_addr;
230 	socklen_t len = sizeof(PgAddr);
231 	int err;
232 
233 	if (is_unix) {
234 		uid_t uid = 0;
235 		gid_t gid = 0;
236 		pid_t pid = 0;
237 		pga_set(dst, AF_UNIX, cf_listen_port);
238 		if (getpeercreds(fd, &uid, &gid, &pid) >= 0) {
239 			log_noise("unix peer uid: %d", (int)uid);
240 		} else if (errno != ENOSYS) {
241 			/*
242 			 * Check for ENOSYS, so we don't write a
243 			 * warning every time if the OS doesn't
244 			 * support this call.
245 			 */
246 			log_warning("unix peer uid failed: %s", strerror(errno));
247 		}
248 		dst->scred.uid = uid;
249 		dst->scred.pid = pid;
250 	} else {
251 		err = getpeername(fd, (struct sockaddr *)dst, &len);
252 		if (err < 0) {
253 			log_error("fill_remote_addr: getpeername(%d) = %s",
254 				  fd, strerror(errno));
255 		}
256 	}
257 }
258 
fill_local_addr(PgSocket * sk,int fd,bool is_unix)259 void fill_local_addr(PgSocket *sk, int fd, bool is_unix)
260 {
261 	PgAddr *dst = &sk->local_addr;
262 	socklen_t len = sizeof(PgAddr);
263 	int err;
264 
265 	if (is_unix) {
266 		pga_set(dst, AF_UNIX, cf_listen_port);
267 		dst->scred.uid = geteuid();
268 		dst->scred.pid = getpid();
269 	} else {
270 		err = getsockname(fd, (struct sockaddr *)dst, &len);
271 		if (err < 0) {
272 			log_error("fill_local_addr: getsockname(%d) = %s",
273 				  fd, strerror(errno));
274 		}
275 	}
276 }
277 
278 /*
279  * Error handling around evtimer_add() is nasty as the code
280  * may not be called again.  As there is fixed number of timers
281  * in pgbouncer, provider safe_evtimer_add() that stores args of
282  * failed calls in static array and retries later.
283  */
284 #define TIMER_BACKUP_SLOTS  10
285 
286 struct timer_slot {
287 	struct event *ev;
288 	struct timeval tv;
289 };
290 static struct timer_slot timer_backup_list[TIMER_BACKUP_SLOTS];
291 static int timer_backup_used = 0;
292 
safe_evtimer_add(struct event * ev,struct timeval * tv)293 void safe_evtimer_add(struct event *ev, struct timeval *tv)
294 {
295 	int res;
296 	struct timer_slot *ts;
297 
298 	res = evtimer_add(ev, tv);
299 	if (res >= 0)
300 		return;
301 
302 	if (timer_backup_used >= TIMER_BACKUP_SLOTS)
303 		fatal("TIMER_BACKUP_SLOTS full");
304 
305 	ts = &timer_backup_list[timer_backup_used++];
306 	ts->ev = ev;
307 	ts->tv = *tv;
308 }
309 
rescue_timers(void)310 void rescue_timers(void)
311 {
312 	struct timer_slot *ts;
313 	while (timer_backup_used) {
314 		ts = &timer_backup_list[timer_backup_used - 1];
315 		if (evtimer_add(ts->ev, &ts->tv) < 0)
316 			break;
317 		timer_backup_used--;
318 	}
319 }
320 
321 
322 /*
323  * PgAddr operations
324  */
325 
pga_port(const PgAddr * a)326 int pga_port(const PgAddr *a)
327 {
328 	if (a->sa.sa_family == AF_INET6) {
329 		return ntohs(a->sin6.sin6_port);
330 	} else {
331 		return ntohs(a->sin.sin_port);
332 	}
333 }
334 
335 /* set family and port */
pga_set(PgAddr * a,int af,int port)336 void pga_set(PgAddr *a, int af, int port)
337 {
338 	memset(a, 0, sizeof(*a));
339 	if (af == AF_INET6) {
340 		a->sin6.sin6_family = af;
341 		a->sin6.sin6_port = htons(port);
342 	} else {
343 		a->sin.sin_family = af;
344 		a->sin.sin_port = htons(port);
345 	}
346 }
347 
348 /* copy sockaddr_in/in6 to PgAddr */
pga_copy(PgAddr * a,const struct sockaddr * sa)349 void pga_copy(PgAddr *a, const struct sockaddr *sa)
350 {
351 	switch (sa->sa_family) {
352 	case AF_INET:
353 		memcpy(&a->sin, sa, sizeof(a->sin));
354 		break;
355 	case AF_INET6:
356 		memcpy(&a->sin6, sa, sizeof(a->sin6));
357 		break;
358 	case AF_UNIX:
359 		log_error("pga_copy: AF_UNIX copy not supported");
360 	}
361 }
362 
pga_cmp_addr(const PgAddr * a,const PgAddr * b)363 int pga_cmp_addr(const PgAddr *a, const PgAddr *b)
364 {
365     if (pga_family(a) != pga_family(b))
366 		return pga_family(a) - pga_family(b);
367 
368 	switch (pga_family(a)) {
369 	case AF_INET:
370 		return memcmp(&a->sin.sin_addr, &b->sin.sin_addr, sizeof(a->sin.sin_addr));
371 		break;
372 	case AF_INET6:
373 		return memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr, sizeof(a->sin6.sin6_addr));
374 		break;
375 	default:
376 		log_error("pga_cmp_addr: unsupported family");
377 		return 0;
378 	}
379 }
380 
381 /* convert pgaddr to string */
pga_ntop(const PgAddr * a,char * dst,int dstlen)382 const char *pga_ntop(const PgAddr *a, char *dst, int dstlen)
383 {
384 	const char *res = NULL;
385 	char buf[PGADDR_BUF];
386 
387 	memset(buf, 0, sizeof(buf));
388 
389 	switch (pga_family(a)) {
390 	case AF_UNIX:
391 		res = "unix";
392 		break;
393 	case AF_INET:
394 		res = inet_ntop(AF_INET, &a->sin.sin_addr, buf, sizeof(buf));
395 		break;
396 	case AF_INET6:
397 		res = inet_ntop(AF_INET6, &a->sin6.sin6_addr, buf, sizeof(buf));
398 		break;
399 	default:
400 		res = "(bad-af)";
401 	}
402 	if (res == NULL)
403 		res = "(err-ntop)";
404 
405 	strlcpy(dst, res, dstlen);
406 	return dst;
407 }
408 
409 /* parse address from string */
pga_pton(PgAddr * a,const char * s,int port)410 bool pga_pton(PgAddr *a, const char *s, int port)
411 {
412 	int res = 1;
413 	if (strcmp(s, "unix") == 0) {
414 		pga_set(a, AF_UNIX, port);
415 	} else if (strcmp(s, "*") == 0) {
416 		pga_set(a, AF_INET, port);
417 		a->sin.sin_addr.s_addr = htonl(INADDR_ANY);
418 	} else if (strchr(s, ':')) {
419 		pga_set(a, AF_INET6, port);
420 		res = inet_pton(AF_INET6, s, &a->sin6.sin6_addr);
421 	} else {
422 		pga_set(a, AF_INET, port);
423 		res = inet_pton(AF_INET, s, &a->sin.sin_addr);
424 	}
425 	if (res == 0)
426 		errno = EINVAL;
427 	return res > 0;
428 }
429 
pga_str(const PgAddr * a,char * dst,int dstlen)430 const char *pga_str(const PgAddr *a, char *dst, int dstlen)
431 {
432 	char buf[PGADDR_BUF];
433 	pga_ntop(a, buf, sizeof(buf));
434 	if (pga_family(a) == AF_INET6) {
435 		snprintf(dst, dstlen, "[%s]:%d", buf, pga_port(a));
436 	} else if (pga_family(a) == AF_UNIX && a->scred.pid) {
437 		snprintf(dst, dstlen, "%s:%d$%lu", buf, pga_port(a), (unsigned long)a->scred.pid);
438 	} else {
439 		snprintf(dst, dstlen, "%s:%d", buf, pga_port(a));
440 	}
441 	return dst;
442 }
443 
cached_hostname(void)444 static const char *cached_hostname(void)
445 {
446 	static char cache[256];
447 	int err;
448 
449 	if (cache[0] == 0) {
450 		err = gethostname(cache, sizeof(cache));
451 		if (err != 0)
452 			strlcpy(cache, "somehost", sizeof(cache));
453 	}
454 	return cache;
455 }
456 
pga_details(const PgAddr * a,char * dst,int dstlen)457 const char *pga_details(const PgAddr *a, char *dst, int dstlen)
458 {
459 	char buf[PGADDR_BUF];
460 	pga_ntop(a, buf, sizeof(buf));
461 	if (pga_family(a) == AF_INET6) {
462 		snprintf(dst, dstlen, "[%s]:%d", buf, pga_port(a));
463 	} else if (pga_family(a) == AF_UNIX && a->scred.pid) {
464 		snprintf(dst, dstlen, "%s(%lu@%s):%d", buf, (unsigned long)a->scred.pid, cached_hostname(), pga_port(a));
465 	} else {
466 		snprintf(dst, dstlen, "%s:%d", buf, pga_port(a));
467 	}
468 	return dst;
469 }
470