git ssb

0+

cel / sslh



Tree: 26b4bcd089f6c3a3c43d1380969c939e600b3ef2

Files: 26b4bcd089f6c3a3c43d1380969c939e600b3ef2 / common.c

19878 bytesRaw
1/* Code and variables that is common to both fork and select-based
2 * servers.
3 *
4 * No code here should assume whether sockets are blocking or not.
5 **/
6
7#define _GNU_SOURCE
8#include <sys/types.h>
9#include <fcntl.h>
10#include <string.h>
11#include <unistd.h>
12#include <stdlib.h>
13#include <stdarg.h>
14#include <stdio.h>
15#include <signal.h>
16#include <sys/socket.h>
17#include <sys/wait.h>
18#include <netinet/in.h>
19#include <arpa/inet.h>
20#include <netdb.h>
21#include <pwd.h>
22#include <syslog.h>
23#include <libgen.h>
24#include <getopt.h>
25
26#include "common.h"
27
28/* Added to make the code compilable under CYGWIN
29 * */
30#ifndef SA_NOCLDWAIT
31#define SA_NOCLDWAIT 0
32#endif
33
34int is_ssh_protocol(const char *p, int len);
35int is_openvpn_protocol(const char *p, int len);
36int is_tinc_protocol(const char *p, int len);
37int is_xmpp_protocol(const char *p, int len);
38int is_http_protocol(const char *p, int len);
39int is_true(const char *p, int len) { return 1; }
40
41/* Table of all the protocols we know how to connect to.
42 *
43 * The first protocol in the table is where we connect in case of timeout
44 * (client didn't speak: typically this is SSH.)
45 *
46 * The last protocol in the table is where we connect if client spoke but we
47 * couldn't probe what it's saying.
48 */
49struct proto protocols[] = {
50 /* affected description service saddr probe */
51 { 0, "ssh", "sshd", {0}, is_ssh_protocol },
52 { 0, "openvpn", NULL, {0}, is_openvpn_protocol },
53 { 0, "tinc", NULL, {0}, is_tinc_protocol },
54 { 0, "xmpp", NULL, {0}, is_xmpp_protocol },
55 { 0, "http", NULL, {0}, is_http_protocol },
56 /* probe for SSL always successes: it's the default, and must be tried last
57 **/
58 { 0, "ssl", NULL, {0}, is_true }
59};
60int num_known_protocols = ARRAY_SIZE(protocols);
61
62/*
63 * Settings that depend on the command line. They're set in main(), but also
64 * used in other places in common.c, and it'd be heavy-handed to pass it all as
65 * parameters
66 */
67int verbose = 0;
68int probing_timeout = 2;
69int inetd = 0;
70int foreground = 0;
71int numeric = 0;
72char *user_name, *pid_file;
73
74struct addrinfo *addr_listen = NULL; /* what addresses do we listen to? */
75
76#ifdef LIBWRAP
77#include <tcpd.h>
78int allow_severity =0, deny_severity = 0;
79#endif
80
81
82/* check result and die, printing the offending address and error */
83void check_res_dumpdie(int res, struct addrinfo *addr, char* syscall)
84{
85 char buf[NI_MAXHOST];
86
87 if (res == -1) {
88 fprintf(stderr, "%s:%s: %s\n",
89 sprintaddr(buf, sizeof(buf), addr),
90 syscall,
91 strerror(errno));
92 exit(1);
93 }
94}
95
96/* Starts listening sockets on specified addresses.
97 * IN: addr[], num_addr
98 * OUT: *sockfd[] pointer to newly-allocated array of file descriptors
99 * Returns number of addresses bound
100 * Bound file descriptors are returned in newly-allocated *sockfd pointer
101 */
102int start_listen_sockets(int *sockfd[], struct addrinfo *addr_list)
103{
104 struct sockaddr_storage *saddr;
105 struct addrinfo *addr;
106 int i, res, reuse;
107 int num_addr = 0;
108
109 for (addr = addr_list; addr; addr = addr->ai_next)
110 num_addr++;
111
112 if (verbose)
113 fprintf(stderr, "listening to %d addresses\n", num_addr);
114
115 *sockfd = malloc(num_addr * sizeof(*sockfd[0]));
116
117 for (i = 0, addr = addr_list; i < num_addr && addr; i++, addr = addr->ai_next) {
118 if (!addr) {
119 fprintf(stderr, "FATAL: Inconsistent listen number. This should not happen.\n");
120 exit(1);
121 }
122 saddr = (struct sockaddr_storage*)addr->ai_addr;
123
124 (*sockfd)[i] = socket(saddr->ss_family, SOCK_STREAM, 0);
125 check_res_dumpdie((*sockfd)[i], addr, "socket");
126
127 reuse = 1;
128 res = setsockopt((*sockfd)[i], SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse));
129 check_res_dumpdie(res, addr, "setsockopt");
130
131 res = bind((*sockfd)[i], addr->ai_addr, addr->ai_addrlen);
132 check_res_dumpdie(res, addr, "bind");
133
134 res = listen ((*sockfd)[i], 50);
135 check_res_dumpdie(res, addr, "listen");
136
137 }
138
139 return num_addr;
140}
141
142/* Connect to first address that works and returns a file descriptor, or -1 if
143 * none work. cnx_name points to the name of the service (for logging) */
144int connect_addr(struct addrinfo *addr, char* cnx_name)
145{
146 struct addrinfo *a;
147 char buf[NI_MAXHOST];
148 int fd, res;
149
150 for (a = addr; a; a = a->ai_next) {
151 if (verbose)
152 fprintf(stderr, "connecting to %s family %d len %d\n",
153 sprintaddr(buf, sizeof(buf), a),
154 a->ai_addr->sa_family, a->ai_addrlen);
155 fd = socket(a->ai_family, SOCK_STREAM, 0);
156 if (fd == -1) {
157 log_message(LOG_ERR, "forward to %s failed:socket: %s\n", cnx_name, strerror(errno));
158 } else {
159 res = connect(fd, a->ai_addr, a->ai_addrlen);
160 if (res == -1) {
161 log_message(LOG_ERR, "forward to %s failed:connect: %s\n",
162 cnx_name, strerror(errno));
163 } else {
164 return fd;
165 }
166 }
167 }
168 return -1;
169}
170
171/* Store some data to write to the queue later */
172int defer_write(struct queue *q, void* data, int data_size)
173{
174 if (verbose)
175 fprintf(stderr, "**** writing defered on fd %d\n", q->fd);
176 q->defered_data = malloc(data_size);
177 q->begin_defered_data = q->defered_data;
178 q->defered_data_size = data_size;
179 memcpy(q->defered_data, data, data_size);
180
181 return 0;
182}
183
184/* tries to flush some of the data for specified queue
185 * Upon success, the number of bytes written is returned.
186 * Upon failure, -1 returned (e.g. connexion closed)
187 * */
188int flush_defered(struct queue *q)
189{
190 int n;
191
192 if (verbose)
193 fprintf(stderr, "flushing defered data to fd %d\n", q->fd);
194
195 n = write(q->fd, q->defered_data, q->defered_data_size);
196 if (n == -1)
197 return n;
198
199 if (n == q->defered_data_size) {
200 /* All has been written -- release the memory */
201 free(q->begin_defered_data);
202 q->begin_defered_data = NULL;
203 q->defered_data = NULL;
204 q->defered_data_size = 0;
205 } else {
206 /* There is data left */
207 q->defered_data += n;
208 q->defered_data_size -= n;
209 }
210
211
212 return n;
213}
214
215
216void init_cnx(struct connection *cnx)
217{
218 memset(cnx, 0, sizeof(*cnx));
219 cnx->q[0].fd = -1;
220 cnx->q[1].fd = -1;
221}
222
223void dump_connection(struct connection *cnx)
224{
225 printf("state: %d\n", cnx->state);
226 printf("fd %d, %d defered\n", cnx->q[0].fd, cnx->q[0].defered_data_size);
227 printf("fd %d, %d defered\n", cnx->q[1].fd, cnx->q[1].defered_data_size);
228}
229
230
231/*
232 * moves data from one fd to other
233 *
234 * retuns number of bytes copied if success
235 * returns 0 (FD_CNXCLOSED) if incoming socket closed
236 * returns FD_NODATA if no data was available
237 * returns FD_STALLED if data was read, could not be written, and has been
238 * stored in temporary buffer.
239 *
240 * slot for debug only and may go away at some point
241 */
242int fd2fd(struct queue *target_q, struct queue *from_q)
243{
244 char buffer[BUFSIZ];
245 int target, from, size_r, size_w;
246
247 target = target_q->fd;
248 from = from_q->fd;
249
250 size_r = read(from, buffer, sizeof(buffer));
251 if (size_r == -1) {
252 switch (errno) {
253 case EAGAIN:
254 if (verbose)
255 fprintf(stderr, "reading 0 from %d\n", from);
256 return FD_NODATA;
257
258 case ECONNRESET:
259 case EPIPE:
260 return FD_CNXCLOSED;
261 }
262 }
263
264 CHECK_RES_RETURN(size_r, "read");
265
266 if (size_r == 0)
267 return FD_CNXCLOSED;
268
269 size_w = write(target, buffer, size_r);
270 /* process -1 when we know how to deal with it */
271 if ((size_w == -1)) {
272 switch (errno) {
273 case EAGAIN:
274 /* write blocked: Defer data */
275 defer_write(target_q, buffer, size_r);
276 return FD_STALLED;
277
278 case ECONNRESET:
279 case EPIPE:
280 /* remove end closed -- drop the connection */
281 return FD_CNXCLOSED;
282 }
283 } else if (size_w < size_r) {
284 /* incomplete write -- defer the rest of the data */
285 defer_write(target_q, buffer + size_w, size_r - size_w);
286 return FD_STALLED;
287 }
288
289 CHECK_RES_RETURN(size_w, "write");
290
291 return size_w;
292}
293
294/* If the client wrote something first, read it and check if it's a SSH banner.
295 * Data is left in appropriate defered write buffer.
296 */
297int is_ssh_protocol(const char *p, int len)
298{
299 if (!strncmp(p, "SSH-", 4)) {
300 return 1;
301 }
302 return 0;
303}
304
305/* Is the buffer the beginning of an OpenVPN connection?
306 * (code lifted from OpenVPN port-share option)
307 */
308int is_openvpn_protocol (const char*p,int len)
309{
310#define P_OPCODE_SHIFT 3
311#define P_CONTROL_HARD_RESET_CLIENT_V2 7
312 if (len >= 3)
313 {
314 return p[0] == 0
315 && p[1] >= 14
316 && p[2] == (P_CONTROL_HARD_RESET_CLIENT_V2<<P_OPCODE_SHIFT);
317 }
318 else if (len >= 2)
319 {
320 return p[0] == 0 && p[1] >= 14;
321 }
322 else
323 return 0;
324}
325
326/* Is the buffer the beginning of a tinc connections?
327 * (protocol is undocumented, but starts with "0 " in 1.0.15)
328 * */
329int is_tinc_protocol( const char *p, int len)
330{
331 return !strncmp(p, "0 ", 2);
332}
333
334/* Is the buffer the beginning of a jabber (XMPP) connections?
335 * (Protocol is documented (http://tools.ietf.org/html/rfc6120) but for lazy
336 * clients, just checking first frame containing "jabber" in xml entity)
337 * */
338int is_xmpp_protocol( const char *p, int len)
339{
340 return strstr(p, "jabber") ? 1 : 0;
341}
342
343int probe_http_method(const char *p, const char *opt)
344{
345 return !strncmp(p, opt, strlen(opt)-1);
346}
347
348/* Is the buffer the beginnin of an HTTP connection? */
349int is_http_protocol(const char *p, int len)
350{
351 /* If it's got HTTP in the request (HTTP/1.1) then it's HTTP */
352 if (strstr(p, "HTTP"))
353 return 1;
354
355 /* Otherwise it could be HTTP/1.0 without version: check if it's got an
356 * HTTP method (RFC2616 5.1.1) */
357 probe_http_method(p, "OPTIONS");
358 probe_http_method(p, "GET");
359 probe_http_method(p, "HEAD");
360 probe_http_method(p, "POST");
361 probe_http_method(p, "PUT");
362 probe_http_method(p, "DELETE");
363 probe_http_method(p, "TRACE");
364 probe_http_method(p, "CONNECT");
365
366 return 0;
367}
368
369
370/*
371 * Read the beginning of data coming from the client connection and check if
372 * it's a known protocol. Then leave the data on the defered
373 * write buffer of the connection and returns the protocol index in the
374 * protocols[] array *
375 */
376T_PROTO_ID probe_client_protocol(struct connection *cnx)
377{
378 char buffer[BUFSIZ];
379 int n, i;
380
381 n = read(cnx->q[0].fd, buffer, sizeof(buffer));
382 /* It's possible that read() returns an error, e.g. if the client
383 * disconnected between the previous call to select() and now. If that
384 * happens, we just connect to the default protocol so the caller of this
385 * function does not have to deal with a specific failure condition (the
386 * connection will just fail later normally). */
387 if (n > 0) {
388 defer_write(&cnx->q[1], buffer, n);
389
390 for (i = 0; i < ARRAY_SIZE(protocols); i++) {
391 if (protocols[i].affected) {
392 if (protocols[i].probe(buffer, n)) {
393 return i;
394 }
395 }
396 }
397 }
398
399 /* If none worked, return the first one affected (that's completely
400 * arbitrary) */
401 for (i = 0; i < ARRAY_SIZE(protocols); i++)
402 if (protocols[i].affected)
403 return i;
404
405 /* At this stage... nothing is affected. This shouldn't happen as we check
406 * at least one target exists when we parse the commnand line */
407 fprintf(stderr, "FATAL: No protocol affected. This should not happen.\n");
408 exit(1);
409}
410
411/* returns a string that prints the IP and port of the sockaddr */
412char* sprintaddr(char* buf, size_t size, struct addrinfo *a)
413{
414 char host[NI_MAXHOST], serv[NI_MAXSERV];
415 int res;
416
417 res = getnameinfo(a->ai_addr, a->ai_addrlen,
418 host, sizeof(host),
419 serv, sizeof(serv),
420 numeric ? NI_NUMERICHOST | NI_NUMERICSERV : 0 );
421
422 if (res) {
423 log_message(LOG_ERR, "sprintaddr:getnameinfo: %s\n", gai_strerror(res));
424 /* Name resolution failed: do it numerically instead */
425 res = getnameinfo(a->ai_addr, a->ai_addrlen,
426 host, sizeof(host),
427 serv, sizeof(serv),
428 NI_NUMERICHOST | NI_NUMERICSERV);
429 /* should not fail but... */
430 if (res) {
431 log_message(LOG_ERR, "sprintaddr:getnameinfo(NUM): %s\n", gai_strerror(res));
432 strcpy(host, "?");
433 strcpy(serv, "?");
434 }
435 }
436
437 snprintf(buf, size, "%s:%s", host, serv);
438
439 return buf;
440}
441
442/* turns a "hostname:port" string into a list of struct addrinfo;
443out: list of newly allocated addrinfo (see getaddrinfo(3)); freeaddrinfo(3) when done
444fullname: input string -- it gets clobbered
445*/
446void resolve_name(struct addrinfo **out, char* fullname)
447{
448 struct addrinfo hint;
449 char *serv, *host;
450 int res;
451
452 char *sep = strrchr(fullname, ':');
453
454 if (!sep) /* No separator: parameter is just a port */
455 {
456 fprintf(stderr, "names must be fully specified as hostname:port\n");
457 exit(1);
458 }
459
460 host = fullname;
461 serv = sep+1;
462 *sep = 0;
463
464 memset(&hint, 0, sizeof(hint));
465 hint.ai_family = PF_UNSPEC;
466 hint.ai_socktype = SOCK_STREAM;
467
468 res = getaddrinfo(host, serv, &hint, out);
469 if (res) {
470 fprintf(stderr, "%s `%s'\n", gai_strerror(res), fullname);
471 if (res == EAI_SERVICE)
472 fprintf(stderr, "(Check you have specified all ports)\n");
473 exit(4);
474 }
475}
476
477/* Log to syslog or stderr if foreground */
478void log_message(int type, char* msg, ...)
479{
480 va_list ap;
481
482 va_start(ap, msg);
483 if (foreground)
484 vfprintf(stderr, msg, ap);
485 else
486 vsyslog(type, msg, ap);
487 va_end(ap);
488}
489
490/* syslogs who connected to where */
491void log_connection(struct connection *cnx)
492{
493 struct addrinfo addr;
494 struct sockaddr_storage ss;
495#define MAX_NAMELENGTH (NI_MAXHOST + NI_MAXSERV + 1)
496 char peer[MAX_NAMELENGTH], service[MAX_NAMELENGTH],
497 local[MAX_NAMELENGTH], target[MAX_NAMELENGTH];
498 int res;
499
500 addr.ai_addr = (struct sockaddr*)&ss;
501 addr.ai_addrlen = sizeof(ss);
502
503 res = getpeername(cnx->q[0].fd, addr.ai_addr, &addr.ai_addrlen);
504 if (res == -1) return; /* that should never happen, right? */
505 sprintaddr(peer, sizeof(peer), &addr);
506
507 addr.ai_addrlen = sizeof(ss);
508 res = getsockname(cnx->q[0].fd, addr.ai_addr, &addr.ai_addrlen);
509 if (res == -1) return;
510 sprintaddr(service, sizeof(service), &addr);
511
512 addr.ai_addrlen = sizeof(ss);
513 res = getpeername(cnx->q[1].fd, addr.ai_addr, &addr.ai_addrlen);
514 if (res == -1) return;
515 sprintaddr(target, sizeof(target), &addr);
516
517 addr.ai_addrlen = sizeof(ss);
518 res = getsockname(cnx->q[1].fd, addr.ai_addr, &addr.ai_addrlen);
519 if (res == -1) return;
520 sprintaddr(local, sizeof(local), &addr);
521
522 log_message(LOG_INFO, "connection from %s to %s forwarded from %s to %s\n",
523 peer,
524 service,
525 local,
526 target);
527}
528
529
530/* libwrap (tcpd): check the connection is legal. This is necessary because
531 * the actual server will only see a connection coming from localhost and can't
532 * apply the rules itself.
533 *
534 * Returns -1 if access is denied, 0 otherwise
535 */
536int check_access_rights(int in_socket, char* service)
537{
538#ifdef LIBWRAP
539 struct sockaddr peeraddr;
540 socklen_t size = sizeof(peeraddr);
541 char addr_str[NI_MAXHOST], host[NI_MAXHOST];
542 int res;
543
544 res = getpeername(in_socket, &peeraddr, &size);
545 CHECK_RES_DIE(res, "getpeername");
546
547 /* extract peer address */
548 res = getnameinfo(&peeraddr, size, addr_str, sizeof(addr_str), NULL, 0, NI_NUMERICHOST);
549 if (res) {
550 if (verbose)
551 fprintf(stderr, "getnameinfo(NI_NUMERICHOST):%s\n", gai_strerror(res));
552 strcpy(addr_str, STRING_UNKNOWN);
553 }
554 /* extract peer name */
555 strcpy(host, STRING_UNKNOWN);
556 if (!numeric) {
557 res = getnameinfo(&peeraddr, size, host, sizeof(host), NULL, 0, NI_NAMEREQD);
558 if (res) {
559 if (verbose)
560 fprintf(stderr, "getnameinfo(NI_NAMEREQD):%s\n", gai_strerror(res));
561 }
562 }
563
564 if (!hosts_ctl(service, host, addr_str, STRING_UNKNOWN)) {
565 if (verbose)
566 fprintf(stderr, "access denied\n");
567 log_message(LOG_INFO, "connection from %s(%s): access denied", host, addr_str);
568 close(in_socket);
569 return -1;
570 }
571#endif
572 return 0;
573}
574
575
576void setup_signals(void)
577{
578 int res;
579 struct sigaction action;
580
581 /* Request no SIGCHLD is sent upon termination of
582 * the children */
583 memset(&action, 0, sizeof(action));
584 action.sa_handler = NULL;
585 action.sa_flags = SA_NOCLDWAIT;
586 res = sigaction(SIGCHLD, &action, NULL);
587 CHECK_RES_DIE(res, "sigaction");
588
589
590 /* Set SIGTERM to exit. For some reason if it's not set explicitely,
591 * coverage information is lost when killing the process */
592 memset(&action, 0, sizeof(action));
593 action.sa_handler = exit;
594 res = sigaction(SIGTERM, &action, NULL);
595 CHECK_RES_DIE(res, "sigaction");
596}
597
598/* Open syslog connection with appropriate banner;
599 * banner is made up of basename(bin_name)+"[pid]" */
600void setup_syslog(char* bin_name) {
601 char *name1, *name2;
602
603 name1 = strdup(bin_name);
604 asprintf(&name2, "%s[%d]", basename(name1), getpid());
605 openlog(name2, LOG_CONS, LOG_AUTH);
606 free(name1);
607 /* Don't free name2, as openlog(3) uses it (at least in glibc) */
608
609 log_message(LOG_INFO, "%s %s started\n", server_type, VERSION);
610}
611
612/* We don't want to run as root -- drop priviledges if required */
613void drop_privileges(char* user_name)
614{
615 int res;
616 struct passwd *pw = getpwnam(user_name);
617 if (!pw) {
618 fprintf(stderr, "%s: not found\n", user_name);
619 exit(2);
620 }
621 if (verbose)
622 fprintf(stderr, "turning into %s\n", user_name);
623
624 res = setgid(pw->pw_gid);
625 CHECK_RES_DIE(res, "setgid");
626 setuid(pw->pw_uid);
627 CHECK_RES_DIE(res, "setuid");
628}
629
630/* Writes my PID */
631void write_pid_file(char* pidfile)
632{
633 FILE *f;
634
635 f = fopen(pidfile, "w");
636 if (!f) {
637 perror(pidfile);
638 exit(3);
639 }
640
641 fprintf(f, "%d\n", getpid());
642 fclose(f);
643}
644
645void printsettings(void)
646{
647 char buf[NI_MAXHOST];
648 struct addrinfo *a;
649 int i;
650
651 for (i = 0; i < ARRAY_SIZE(protocols); i++) {
652 if (protocols[i].affected)
653 fprintf(stderr,
654 "%s addr: %s. libwrap service: %s family %d %d\n",
655 protocols[i].description,
656 sprintaddr(buf, sizeof(buf), &protocols[i].saddr),
657 protocols[i].service,
658 protocols[i].saddr.ai_family,
659 protocols[i].saddr.ai_addr->sa_family);
660 }
661 fprintf(stderr, "listening on:\n");
662 for (a = addr_listen; a; a = a->ai_next) {
663 fprintf(stderr, "\t%s\n", sprintaddr(buf, sizeof(buf), a));
664 }
665 fprintf(stderr, "timeout to ssh: %d\n", probing_timeout);
666}
667
668/* Adds protocols to the list of options, so command-line parsing uses the
669 * protocol definition array
670 * options: array of options to add to; must be big enough
671 * n_opts: number of options in *options before calling (i.e. where to append)
672 * prot: array of protocols
673 * n_prots: number of protocols in *prot
674 * */
675void append_protocols(struct option *options, int n_opts, struct proto *prot, int n_prots)
676{
677 int o, p;
678
679 for (o = n_opts, p = 0; p < n_prots; o++, p++) {
680 options[o].name = prot[p].description;
681 options[o].has_arg = required_argument;
682 options[o].flag = 0;
683 options[o].val = p + PROT_SHIFT;
684 }
685}
686
687

Built with git-ssb-web