diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 159 |
1 files changed, 147 insertions, 12 deletions
@@ -1,6 +1,7 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.65 2006/11/23 01:35:11 ray Exp $ */ | ||
1 | /* | 2 | /* |
2 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
3 | * Copyright (c) 2005 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
4 | * | 5 | * |
5 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions |
@@ -24,15 +25,35 @@ | |||
24 | */ | 25 | */ |
25 | 26 | ||
26 | #include "includes.h" | 27 | #include "includes.h" |
27 | RCSID("$OpenBSD: misc.c,v 1.42 2006/01/31 10:19:02 djm Exp $"); | ||
28 | 28 | ||
29 | #include <sys/types.h> | ||
30 | #include <sys/ioctl.h> | ||
31 | #include <sys/socket.h> | ||
32 | #include <sys/param.h> | ||
33 | |||
34 | #include <stdarg.h> | ||
35 | #include <stdio.h> | ||
36 | #include <stdlib.h> | ||
37 | #include <string.h> | ||
38 | #include <unistd.h> | ||
39 | |||
40 | #include <netinet/in.h> | ||
41 | #include <netinet/tcp.h> | ||
42 | |||
43 | #include <errno.h> | ||
44 | #include <fcntl.h> | ||
45 | #ifdef HAVE_PATHS_H | ||
46 | # include <paths.h> | ||
47 | #include <pwd.h> | ||
48 | #endif | ||
29 | #ifdef SSH_TUN_OPENBSD | 49 | #ifdef SSH_TUN_OPENBSD |
30 | #include <net/if.h> | 50 | #include <net/if.h> |
31 | #endif | 51 | #endif |
32 | 52 | ||
53 | #include "xmalloc.h" | ||
33 | #include "misc.h" | 54 | #include "misc.h" |
34 | #include "log.h" | 55 | #include "log.h" |
35 | #include "xmalloc.h" | 56 | #include "ssh.h" |
36 | 57 | ||
37 | /* remove newline at end of string */ | 58 | /* remove newline at end of string */ |
38 | char * | 59 | char * |
@@ -123,6 +144,7 @@ set_nodelay(int fd) | |||
123 | 144 | ||
124 | /* Characters considered whitespace in strsep calls. */ | 145 | /* Characters considered whitespace in strsep calls. */ |
125 | #define WHITESPACE " \t\r\n" | 146 | #define WHITESPACE " \t\r\n" |
147 | #define QUOTE "\"" | ||
126 | 148 | ||
127 | /* return next token in configuration line */ | 149 | /* return next token in configuration line */ |
128 | char * | 150 | char * |
@@ -136,15 +158,27 @@ strdelim(char **s) | |||
136 | 158 | ||
137 | old = *s; | 159 | old = *s; |
138 | 160 | ||
139 | *s = strpbrk(*s, WHITESPACE "="); | 161 | *s = strpbrk(*s, WHITESPACE QUOTE "="); |
140 | if (*s == NULL) | 162 | if (*s == NULL) |
141 | return (old); | 163 | return (old); |
142 | 164 | ||
165 | if (*s[0] == '\"') { | ||
166 | memmove(*s, *s + 1, strlen(*s)); /* move nul too */ | ||
167 | /* Find matching quote */ | ||
168 | if ((*s = strpbrk(*s, QUOTE)) == NULL) { | ||
169 | return (NULL); /* no matching quote */ | ||
170 | } else { | ||
171 | *s[0] = '\0'; | ||
172 | return (old); | ||
173 | } | ||
174 | } | ||
175 | |||
143 | /* Allow only one '=' to be skipped */ | 176 | /* Allow only one '=' to be skipped */ |
144 | if (*s[0] == '=') | 177 | if (*s[0] == '=') |
145 | wspace = 1; | 178 | wspace = 1; |
146 | *s[0] = '\0'; | 179 | *s[0] = '\0'; |
147 | 180 | ||
181 | /* Skip any extra whitespace after first token */ | ||
148 | *s += strspn(*s + 1, WHITESPACE) + 1; | 182 | *s += strspn(*s + 1, WHITESPACE) + 1; |
149 | if (*s[0] == '=' && !wspace) | 183 | if (*s[0] == '=' && !wspace) |
150 | *s += strspn(*s + 1, WHITESPACE) + 1; | 184 | *s += strspn(*s + 1, WHITESPACE) + 1; |
@@ -155,9 +189,8 @@ strdelim(char **s) | |||
155 | struct passwd * | 189 | struct passwd * |
156 | pwcopy(struct passwd *pw) | 190 | pwcopy(struct passwd *pw) |
157 | { | 191 | { |
158 | struct passwd *copy = xmalloc(sizeof(*copy)); | 192 | struct passwd *copy = xcalloc(1, sizeof(*copy)); |
159 | 193 | ||
160 | memset(copy, 0, sizeof(*copy)); | ||
161 | copy->pw_name = xstrdup(pw->pw_name); | 194 | copy->pw_name = xstrdup(pw->pw_name); |
162 | copy->pw_passwd = xstrdup(pw->pw_passwd); | 195 | copy->pw_passwd = xstrdup(pw->pw_passwd); |
163 | copy->pw_gecos = xstrdup(pw->pw_gecos); | 196 | copy->pw_gecos = xstrdup(pw->pw_gecos); |
@@ -280,6 +313,7 @@ convtime(const char *s) | |||
280 | switch (*endp++) { | 313 | switch (*endp++) { |
281 | case '\0': | 314 | case '\0': |
282 | endp--; | 315 | endp--; |
316 | break; | ||
283 | case 's': | 317 | case 's': |
284 | case 'S': | 318 | case 'S': |
285 | break; | 319 | break; |
@@ -312,6 +346,23 @@ convtime(const char *s) | |||
312 | } | 346 | } |
313 | 347 | ||
314 | /* | 348 | /* |
349 | * Returns a standardized host+port identifier string. | ||
350 | * Caller must free returned string. | ||
351 | */ | ||
352 | char * | ||
353 | put_host_port(const char *host, u_short port) | ||
354 | { | ||
355 | char *hoststr; | ||
356 | |||
357 | if (port == 0 || port == SSH_DEFAULT_PORT) | ||
358 | return(xstrdup(host)); | ||
359 | if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) | ||
360 | fatal("put_host_port: asprintf: %s", strerror(errno)); | ||
361 | debug3("put_host_port: %s", hoststr); | ||
362 | return hoststr; | ||
363 | } | ||
364 | |||
365 | /* | ||
315 | * Search for next delimiter between hostnames/addresses and ports. | 366 | * Search for next delimiter between hostnames/addresses and ports. |
316 | * Argument may be modified (for termination). | 367 | * Argument may be modified (for termination). |
317 | * Returns *cp if parsing succeeds. | 368 | * Returns *cp if parsing succeeds. |
@@ -408,7 +459,7 @@ addargs(arglist *args, char *fmt, ...) | |||
408 | } else if (args->num+2 >= nalloc) | 459 | } else if (args->num+2 >= nalloc) |
409 | nalloc *= 2; | 460 | nalloc *= 2; |
410 | 461 | ||
411 | args->list = xrealloc(args->list, nalloc * sizeof(char *)); | 462 | args->list = xrealloc(args->list, nalloc, sizeof(char *)); |
412 | args->nalloc = nalloc; | 463 | args->nalloc = nalloc; |
413 | args->list[args->num++] = cp; | 464 | args->list[args->num++] = cp; |
414 | args->list[args->num] = NULL; | 465 | args->list[args->num] = NULL; |
@@ -565,6 +616,8 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, | |||
565 | u_long *lineno) | 616 | u_long *lineno) |
566 | { | 617 | { |
567 | while (fgets(buf, bufsz, f) != NULL) { | 618 | while (fgets(buf, bufsz, f) != NULL) { |
619 | if (buf[0] == '\0') | ||
620 | continue; | ||
568 | (*lineno)++; | 621 | (*lineno)++; |
569 | if (buf[strlen(buf) - 1] == '\n' || feof(f)) { | 622 | if (buf[strlen(buf) - 1] == '\n' || feof(f)) { |
570 | return 0; | 623 | return 0; |
@@ -673,18 +726,100 @@ sanitise_stdfd(void) | |||
673 | } | 726 | } |
674 | 727 | ||
675 | char * | 728 | char * |
676 | tohex(const u_char *d, u_int l) | 729 | tohex(const void *vp, size_t l) |
677 | { | 730 | { |
731 | const u_char *p = (const u_char *)vp; | ||
678 | char b[3], *r; | 732 | char b[3], *r; |
679 | u_int i, hl; | 733 | size_t i, hl; |
734 | |||
735 | if (l > 65536) | ||
736 | return xstrdup("tohex: length > 65536"); | ||
680 | 737 | ||
681 | hl = l * 2 + 1; | 738 | hl = l * 2 + 1; |
682 | r = xmalloc(hl); | 739 | r = xcalloc(1, hl); |
683 | *r = '\0'; | ||
684 | for (i = 0; i < l; i++) { | 740 | for (i = 0; i < l; i++) { |
685 | snprintf(b, sizeof(b), "%02x", d[i]); | 741 | snprintf(b, sizeof(b), "%02x", p[i]); |
686 | strlcat(r, b, hl); | 742 | strlcat(r, b, hl); |
687 | } | 743 | } |
688 | return (r); | 744 | return (r); |
689 | } | 745 | } |
690 | 746 | ||
747 | u_int64_t | ||
748 | get_u64(const void *vp) | ||
749 | { | ||
750 | const u_char *p = (const u_char *)vp; | ||
751 | u_int64_t v; | ||
752 | |||
753 | v = (u_int64_t)p[0] << 56; | ||
754 | v |= (u_int64_t)p[1] << 48; | ||
755 | v |= (u_int64_t)p[2] << 40; | ||
756 | v |= (u_int64_t)p[3] << 32; | ||
757 | v |= (u_int64_t)p[4] << 24; | ||
758 | v |= (u_int64_t)p[5] << 16; | ||
759 | v |= (u_int64_t)p[6] << 8; | ||
760 | v |= (u_int64_t)p[7]; | ||
761 | |||
762 | return (v); | ||
763 | } | ||
764 | |||
765 | u_int32_t | ||
766 | get_u32(const void *vp) | ||
767 | { | ||
768 | const u_char *p = (const u_char *)vp; | ||
769 | u_int32_t v; | ||
770 | |||
771 | v = (u_int32_t)p[0] << 24; | ||
772 | v |= (u_int32_t)p[1] << 16; | ||
773 | v |= (u_int32_t)p[2] << 8; | ||
774 | v |= (u_int32_t)p[3]; | ||
775 | |||
776 | return (v); | ||
777 | } | ||
778 | |||
779 | u_int16_t | ||
780 | get_u16(const void *vp) | ||
781 | { | ||
782 | const u_char *p = (const u_char *)vp; | ||
783 | u_int16_t v; | ||
784 | |||
785 | v = (u_int16_t)p[0] << 8; | ||
786 | v |= (u_int16_t)p[1]; | ||
787 | |||
788 | return (v); | ||
789 | } | ||
790 | |||
791 | void | ||
792 | put_u64(void *vp, u_int64_t v) | ||
793 | { | ||
794 | u_char *p = (u_char *)vp; | ||
795 | |||
796 | p[0] = (u_char)(v >> 56) & 0xff; | ||
797 | p[1] = (u_char)(v >> 48) & 0xff; | ||
798 | p[2] = (u_char)(v >> 40) & 0xff; | ||
799 | p[3] = (u_char)(v >> 32) & 0xff; | ||
800 | p[4] = (u_char)(v >> 24) & 0xff; | ||
801 | p[5] = (u_char)(v >> 16) & 0xff; | ||
802 | p[6] = (u_char)(v >> 8) & 0xff; | ||
803 | p[7] = (u_char)v & 0xff; | ||
804 | } | ||
805 | |||
806 | void | ||
807 | put_u32(void *vp, u_int32_t v) | ||
808 | { | ||
809 | u_char *p = (u_char *)vp; | ||
810 | |||
811 | p[0] = (u_char)(v >> 24) & 0xff; | ||
812 | p[1] = (u_char)(v >> 16) & 0xff; | ||
813 | p[2] = (u_char)(v >> 8) & 0xff; | ||
814 | p[3] = (u_char)v & 0xff; | ||
815 | } | ||
816 | |||
817 | |||
818 | void | ||
819 | put_u16(void *vp, u_int16_t v) | ||
820 | { | ||
821 | u_char *p = (u_char *)vp; | ||
822 | |||
823 | p[0] = (u_char)(v >> 8) & 0xff; | ||
824 | p[1] = (u_char)v & 0xff; | ||
825 | } | ||