comparison dbutil.c @ 641:2b1bb792cd4d dropbear-tfm

- Update tfm changes to current default tip
author Matt Johnston <matt@ucc.asn.au>
date Mon, 21 Nov 2011 19:52:28 +0800
parents 452bcf810e44
children df11cb6a3665 76e780c74a5e
comparison
equal deleted inserted replaced
640:76097ec1a29a 641:2b1bb792cd4d
55 #include "atomicio.h" 55 #include "atomicio.h"
56 56
57 #define MAX_FMT 100 57 #define MAX_FMT 100
58 58
59 static void generic_dropbear_exit(int exitcode, const char* format, 59 static void generic_dropbear_exit(int exitcode, const char* format,
60 va_list param); 60 va_list param) ATTRIB_NORETURN;
61 static void generic_dropbear_log(int priority, const char* format, 61 static void generic_dropbear_log(int priority, const char* format,
62 va_list param); 62 va_list param);
63 63
64 void (*_dropbear_exit)(int exitcode, const char* format, va_list param) 64 void (*_dropbear_exit)(int exitcode, const char* format, va_list param) ATTRIB_NORETURN
65 = generic_dropbear_exit; 65 = generic_dropbear_exit;
66 void (*_dropbear_log)(int priority, const char* format, va_list param) 66 void (*_dropbear_log)(int priority, const char* format, va_list param)
67 = generic_dropbear_log; 67 = generic_dropbear_log;
68 68
69 #ifdef DEBUG_TRACE 69 #ifdef DEBUG_TRACE
109 109
110 exit(exitcode); 110 exit(exitcode);
111 } 111 }
112 112
113 void fail_assert(const char* expr, const char* file, int line) { 113 void fail_assert(const char* expr, const char* file, int line) {
114 dropbear_exit("failed assertion (%s:%d): `%s'", file, line, expr); 114 dropbear_exit("Failed assertion (%s:%d): `%s'", file, line, expr);
115 } 115 }
116 116
117 static void generic_dropbear_log(int UNUSED(priority), const char* format, 117 static void generic_dropbear_log(int UNUSED(priority), const char* format,
118 va_list param) { 118 va_list param) {
119 119
159 159
160 /* disable nagle */ 160 /* disable nagle */
161 val = 1; 161 val = 1;
162 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val)); 162 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val));
163 163
164 /* set the TOS bit. note that this will fail for ipv6, I can't find any 164 /* set the TOS bit for either ipv4 or ipv6 */
165 * equivalent. */
166 #ifdef IPTOS_LOWDELAY 165 #ifdef IPTOS_LOWDELAY
167 val = IPTOS_LOWDELAY; 166 val = IPTOS_LOWDELAY;
167 #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
168 setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)&val, sizeof(val));
169 #endif
168 setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val)); 170 setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&val, sizeof(val));
169 #endif 171 #endif
170 172
171 #ifdef SO_PRIORITY 173 #ifdef SO_PRIORITY
172 /* linux specific, sets QoS class. 174 /* linux specific, sets QoS class.
252 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val)); 254 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val));
253 linger.l_onoff = 1; 255 linger.l_onoff = 1;
254 linger.l_linger = 5; 256 linger.l_linger = 5;
255 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger)); 257 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger));
256 258
259 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
260 if (res->ai_family == AF_INET6) {
261 int on = 1;
262 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
263 &on, sizeof(on)) == -1) {
264 dropbear_log(LOG_WARNING, "Couldn't set IPV6_V6ONLY");
265 }
266 }
267 #endif
268
257 set_sock_priority(sock); 269 set_sock_priority(sock);
258 270
259 if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { 271 if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
260 err = errno; 272 err = errno;
261 close(sock); 273 close(sock);
292 } 304 }
293 305
294 TRACE(("leave dropbear_listen: success, %d socks bound", nsock)) 306 TRACE(("leave dropbear_listen: success, %d socks bound", nsock))
295 return nsock; 307 return nsock;
296 } 308 }
309
310 /* Connect to a given unix socket. The socket is blocking */
311 #ifdef ENABLE_CONNECT_UNIX
312 int connect_unix(const char* path) {
313 struct sockaddr_un addr;
314 int fd = -1;
315
316 memset((void*)&addr, 0x0, sizeof(addr));
317 addr.sun_family = AF_UNIX;
318 strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
319 fd = socket(PF_UNIX, SOCK_STREAM, 0);
320 if (fd < 0) {
321 TRACE(("Failed to open unix socket"))
322 return -1;
323 }
324 if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
325 TRACE(("Failed to connect to '%s' socket", path))
326 m_close(fd);
327 return -1;
328 }
329 return fd;
330 }
331 #endif
297 332
298 /* Connect via TCP to a host. Connection will try ipv4 or ipv6, will 333 /* Connect via TCP to a host. Connection will try ipv4 or ipv6, will
299 * return immediately if nonblocking is set. On failure, if errstring 334 * return immediately if nonblocking is set. On failure, if errstring
300 * wasn't null, it will be a newly malloced error message */ 335 * wasn't null, it will be a newly malloced error message */
301 336
339 err = errno; 374 err = errno;
340 continue; 375 continue;
341 } 376 }
342 377
343 if (nonblocking) { 378 if (nonblocking) {
344 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { 379 setnonblocking(sock);
345 close(sock);
346 sock = -1;
347 if (errstring != NULL && *errstring == NULL) {
348 *errstring = m_strdup("Failed non-blocking");
349 }
350 TRACE(("Failed non-blocking: %s", strerror(errno)))
351 continue;
352 }
353 } 380 }
354 381
355 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { 382 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
356 if (errno == EINPROGRESS && nonblocking) { 383 if (errno == EINPROGRESS && nonblocking) {
357 TRACE(("Connect in progress")) 384 TRACE(("Connect in progress"))
439 466
440 if ((dup2(infds[FDIN], STDIN_FILENO) < 0) || 467 if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
441 (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) || 468 (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
442 (ret_errfd && dup2(errfds[FDOUT], STDERR_FILENO) < 0)) { 469 (ret_errfd && dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
443 TRACE(("leave noptycommand: error redirecting FDs")) 470 TRACE(("leave noptycommand: error redirecting FDs"))
444 dropbear_exit("child dup2() failure"); 471 dropbear_exit("Child dup2() failure");
445 } 472 }
446 473
447 close(infds[FDOUT]); 474 close(infds[FDOUT]);
448 close(infds[FDIN]); 475 close(infds[FDIN]);
449 close(outfds[FDIN]); 476 close(outfds[FDIN]);
523 } 550 }
524 551
525 execv(usershell, argv); 552 execv(usershell, argv);
526 } 553 }
527 554
555 void get_socket_address(int fd, char **local_host, char **local_port,
556 char **remote_host, char **remote_port, int host_lookup)
557 {
558 struct sockaddr_storage addr;
559 socklen_t addrlen;
560
561 if (local_host || local_port) {
562 addrlen = sizeof(addr);
563 if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
564 dropbear_exit("Failed socket address: %s", strerror(errno));
565 }
566 getaddrstring(&addr, local_host, local_port, host_lookup);
567 }
568 if (remote_host || remote_port) {
569 addrlen = sizeof(addr);
570 if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
571 dropbear_exit("Failed socket address: %s", strerror(errno));
572 }
573 getaddrstring(&addr, remote_host, remote_port, host_lookup);
574 }
575 }
576
528 /* Return a string representation of the socket address passed. The return 577 /* Return a string representation of the socket address passed. The return
529 * value is allocated with malloc() */ 578 * value is allocated with malloc() */
530 unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) { 579 void getaddrstring(struct sockaddr_storage* addr,
531 580 char **ret_host, char **ret_port,
532 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 581 int host_lookup) {
533 char *retstring = NULL; 582
583 char host[NI_MAXHOST+1], serv[NI_MAXSERV+1];
584 unsigned int len;
534 int ret; 585 int ret;
535 unsigned int len; 586
587 int flags = NI_NUMERICSERV | NI_NUMERICHOST;
588
589 #ifndef DO_HOST_LOOKUP
590 host_lookup = 0;
591 #endif
592
593 if (host_lookup) {
594 flags = NI_NUMERICSERV;
595 }
536 596
537 len = sizeof(struct sockaddr_storage); 597 len = sizeof(struct sockaddr_storage);
538 /* Some platforms such as Solaris 8 require that len is the length 598 /* Some platforms such as Solaris 8 require that len is the length
539 * of the specific structure. Some older linux systems (glibc 2.1.3 599 * of the specific structure. Some older linux systems (glibc 2.1.3
540 * such as debian potato) have sockaddr_storage.__ss_family instead 600 * such as debian potato) have sockaddr_storage.__ss_family instead
548 len = sizeof(struct sockaddr_in6); 608 len = sizeof(struct sockaddr_in6);
549 } 609 }
550 #endif 610 #endif
551 #endif 611 #endif
552 612
553 ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf), 613 ret = getnameinfo((struct sockaddr*)addr, len, host, sizeof(host)-1,
554 sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST); 614 serv, sizeof(serv)-1, flags);
555 615
556 if (ret != 0) { 616 if (ret != 0) {
557 /* This is a fairly bad failure - it'll fallback to IP if it 617 if (host_lookup) {
558 * just can't resolve */ 618 /* On some systems (Darwin does it) we get EINTR from getnameinfo
559 dropbear_exit("failed lookup (%d, %d)", ret, errno); 619 * somehow. Eew. So we'll just return the IP, since that doesn't seem
560 } 620 * to exhibit that behaviour. */
561 621 getaddrstring(addr, ret_host, ret_port, 0);
562 if (withport) { 622 return;
563 len = strlen(hbuf) + 2 + strlen(sbuf); 623 } else {
564 retstring = (char*)m_malloc(len); 624 /* if we can't do a numeric lookup, something's gone terribly wrong */
565 snprintf(retstring, len, "%s:%s", hbuf, sbuf); 625 dropbear_exit("Failed lookup: %s", gai_strerror(ret));
566 } else { 626 }
567 retstring = m_strdup(hbuf); 627 }
568 } 628
569 629 if (ret_host) {
570 return retstring; 630 *ret_host = m_strdup(host);
571 631 }
572 } 632 if (ret_port) {
573 633 *ret_port = m_strdup(serv);
574 /* Get the hostname corresponding to the address addr. On failure, the IP 634 }
575 * address is returned. The return value is allocated with strdup() */
576 char* getaddrhostname(struct sockaddr_storage * addr) {
577
578 char hbuf[NI_MAXHOST];
579 char sbuf[NI_MAXSERV];
580 int ret;
581 unsigned int len;
582 #ifdef DO_HOST_LOOKUP
583 const int flags = NI_NUMERICSERV;
584 #else
585 const int flags = NI_NUMERICHOST | NI_NUMERICSERV;
586 #endif
587
588 len = sizeof(struct sockaddr_storage);
589 /* Some platforms such as Solaris 8 require that len is the length
590 * of the specific structure. */
591 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
592 if (addr->ss_family == AF_INET) {
593 len = sizeof(struct sockaddr_in);
594 }
595 #ifdef AF_INET6
596 if (addr->ss_family == AF_INET6) {
597 len = sizeof(struct sockaddr_in6);
598 }
599 #endif
600 #endif
601
602
603 ret = getnameinfo((struct sockaddr*)addr, len, hbuf, sizeof(hbuf),
604 sbuf, sizeof(sbuf), flags);
605
606 if (ret != 0) {
607 /* On some systems (Darwin does it) we get EINTR from getnameinfo
608 * somehow. Eew. So we'll just return the IP, since that doesn't seem
609 * to exhibit that behaviour. */
610 return getaddrstring(addr, 0);
611 }
612
613 return m_strdup(hbuf);
614 } 635 }
615 636
616 #ifdef DEBUG_TRACE 637 #ifdef DEBUG_TRACE
617 void printhex(const char * label, const unsigned char * buf, int len) { 638 void printhex(const char * label, const unsigned char * buf, int len) {
618 639