git ssb

0+

cel / sslh



Tree: ae008179f033c8409c69b13787a539351bace626

Files: ae008179f033c8409c69b13787a539351bace626 / common.c

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

Built with git-ssb-web