diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 139 |
1 files changed, 115 insertions, 24 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.137 2019/01/23 21:50:56 dtucker Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.142 2019/09/03 08:32:11 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -97,7 +97,7 @@ set_nonblock(int fd) | |||
97 | int val; | 97 | int val; |
98 | 98 | ||
99 | val = fcntl(fd, F_GETFL); | 99 | val = fcntl(fd, F_GETFL); |
100 | if (val < 0) { | 100 | if (val == -1) { |
101 | error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); | 101 | error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); |
102 | return (-1); | 102 | return (-1); |
103 | } | 103 | } |
@@ -121,7 +121,7 @@ unset_nonblock(int fd) | |||
121 | int val; | 121 | int val; |
122 | 122 | ||
123 | val = fcntl(fd, F_GETFL); | 123 | val = fcntl(fd, F_GETFL); |
124 | if (val < 0) { | 124 | if (val == -1) { |
125 | error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); | 125 | error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); |
126 | return (-1); | 126 | return (-1); |
127 | } | 127 | } |
@@ -551,7 +551,7 @@ put_host_port(const char *host, u_short port) | |||
551 | 551 | ||
552 | if (port == 0 || port == SSH_DEFAULT_PORT) | 552 | if (port == 0 || port == SSH_DEFAULT_PORT) |
553 | return(xstrdup(host)); | 553 | return(xstrdup(host)); |
554 | if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) | 554 | if (asprintf(&hoststr, "[%s]:%d", host, (int)port) == -1) |
555 | fatal("put_host_port: asprintf: %s", strerror(errno)); | 555 | fatal("put_host_port: asprintf: %s", strerror(errno)); |
556 | debug3("put_host_port: %s", hoststr); | 556 | debug3("put_host_port: %s", hoststr); |
557 | return hoststr; | 557 | return hoststr; |
@@ -1050,13 +1050,18 @@ char * | |||
1050 | percent_expand(const char *string, ...) | 1050 | percent_expand(const char *string, ...) |
1051 | { | 1051 | { |
1052 | #define EXPAND_MAX_KEYS 16 | 1052 | #define EXPAND_MAX_KEYS 16 |
1053 | u_int num_keys, i, j; | 1053 | u_int num_keys, i; |
1054 | struct { | 1054 | struct { |
1055 | const char *key; | 1055 | const char *key; |
1056 | const char *repl; | 1056 | const char *repl; |
1057 | } keys[EXPAND_MAX_KEYS]; | 1057 | } keys[EXPAND_MAX_KEYS]; |
1058 | char buf[4096]; | 1058 | struct sshbuf *buf; |
1059 | va_list ap; | 1059 | va_list ap; |
1060 | int r; | ||
1061 | char *ret; | ||
1062 | |||
1063 | if ((buf = sshbuf_new()) == NULL) | ||
1064 | fatal("%s: sshbuf_new failed", __func__); | ||
1060 | 1065 | ||
1061 | /* Gather keys */ | 1066 | /* Gather keys */ |
1062 | va_start(ap, string); | 1067 | va_start(ap, string); |
@@ -1073,14 +1078,13 @@ percent_expand(const char *string, ...) | |||
1073 | va_end(ap); | 1078 | va_end(ap); |
1074 | 1079 | ||
1075 | /* Expand string */ | 1080 | /* Expand string */ |
1076 | *buf = '\0'; | ||
1077 | for (i = 0; *string != '\0'; string++) { | 1081 | for (i = 0; *string != '\0'; string++) { |
1078 | if (*string != '%') { | 1082 | if (*string != '%') { |
1079 | append: | 1083 | append: |
1080 | buf[i++] = *string; | 1084 | if ((r = sshbuf_put_u8(buf, *string)) != 0) { |
1081 | if (i >= sizeof(buf)) | 1085 | fatal("%s: sshbuf_put_u8: %s", |
1082 | fatal("%s: string too long", __func__); | 1086 | __func__, ssh_err(r)); |
1083 | buf[i] = '\0'; | 1087 | } |
1084 | continue; | 1088 | continue; |
1085 | } | 1089 | } |
1086 | string++; | 1090 | string++; |
@@ -1089,18 +1093,23 @@ percent_expand(const char *string, ...) | |||
1089 | goto append; | 1093 | goto append; |
1090 | if (*string == '\0') | 1094 | if (*string == '\0') |
1091 | fatal("%s: invalid format", __func__); | 1095 | fatal("%s: invalid format", __func__); |
1092 | for (j = 0; j < num_keys; j++) { | 1096 | for (i = 0; i < num_keys; i++) { |
1093 | if (strchr(keys[j].key, *string) != NULL) { | 1097 | if (strchr(keys[i].key, *string) != NULL) { |
1094 | i = strlcat(buf, keys[j].repl, sizeof(buf)); | 1098 | if ((r = sshbuf_put(buf, keys[i].repl, |
1095 | if (i >= sizeof(buf)) | 1099 | strlen(keys[i].repl))) != 0) { |
1096 | fatal("%s: string too long", __func__); | 1100 | fatal("%s: sshbuf_put: %s", |
1101 | __func__, ssh_err(r)); | ||
1102 | } | ||
1097 | break; | 1103 | break; |
1098 | } | 1104 | } |
1099 | } | 1105 | } |
1100 | if (j >= num_keys) | 1106 | if (i >= num_keys) |
1101 | fatal("%s: unknown key %%%c", __func__, *string); | 1107 | fatal("%s: unknown key %%%c", __func__, *string); |
1102 | } | 1108 | } |
1103 | return (xstrdup(buf)); | 1109 | if ((ret = sshbuf_dup_string(buf)) == NULL) |
1110 | fatal("%s: sshbuf_dup_string failed", __func__); | ||
1111 | sshbuf_free(buf); | ||
1112 | return ret; | ||
1104 | #undef EXPAND_MAX_KEYS | 1113 | #undef EXPAND_MAX_KEYS |
1105 | } | 1114 | } |
1106 | 1115 | ||
@@ -1186,7 +1195,7 @@ tun_open(int tun, int mode, char **ifname) | |||
1186 | return -1; | 1195 | return -1; |
1187 | } | 1196 | } |
1188 | 1197 | ||
1189 | if (fd < 0) { | 1198 | if (fd == -1) { |
1190 | debug("%s: %s open: %s", __func__, name, strerror(errno)); | 1199 | debug("%s: %s open: %s", __func__, name, strerror(errno)); |
1191 | return -1; | 1200 | return -1; |
1192 | } | 1201 | } |
@@ -1625,7 +1634,7 @@ unix_listener(const char *path, int backlog, int unlink_first) | |||
1625 | } | 1634 | } |
1626 | 1635 | ||
1627 | sock = socket(PF_UNIX, SOCK_STREAM, 0); | 1636 | sock = socket(PF_UNIX, SOCK_STREAM, 0); |
1628 | if (sock < 0) { | 1637 | if (sock == -1) { |
1629 | saved_errno = errno; | 1638 | saved_errno = errno; |
1630 | error("%s: socket: %.100s", __func__, strerror(errno)); | 1639 | error("%s: socket: %.100s", __func__, strerror(errno)); |
1631 | errno = saved_errno; | 1640 | errno = saved_errno; |
@@ -1635,7 +1644,7 @@ unix_listener(const char *path, int backlog, int unlink_first) | |||
1635 | if (unlink(path) != 0 && errno != ENOENT) | 1644 | if (unlink(path) != 0 && errno != ENOENT) |
1636 | error("unlink(%s): %.100s", path, strerror(errno)); | 1645 | error("unlink(%s): %.100s", path, strerror(errno)); |
1637 | } | 1646 | } |
1638 | if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { | 1647 | if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { |
1639 | saved_errno = errno; | 1648 | saved_errno = errno; |
1640 | error("%s: cannot bind to path %s: %s", | 1649 | error("%s: cannot bind to path %s: %s", |
1641 | __func__, path, strerror(errno)); | 1650 | __func__, path, strerror(errno)); |
@@ -1643,7 +1652,7 @@ unix_listener(const char *path, int backlog, int unlink_first) | |||
1643 | errno = saved_errno; | 1652 | errno = saved_errno; |
1644 | return -1; | 1653 | return -1; |
1645 | } | 1654 | } |
1646 | if (listen(sock, backlog) < 0) { | 1655 | if (listen(sock, backlog) == -1) { |
1647 | saved_errno = errno; | 1656 | saved_errno = errno; |
1648 | error("%s: cannot listen on path %s: %s", | 1657 | error("%s: cannot listen on path %s: %s", |
1649 | __func__, path, strerror(errno)); | 1658 | __func__, path, strerror(errno)); |
@@ -1924,7 +1933,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir, | |||
1924 | } | 1933 | } |
1925 | strlcpy(buf, cp, sizeof(buf)); | 1934 | strlcpy(buf, cp, sizeof(buf)); |
1926 | 1935 | ||
1927 | if (stat(buf, &st) < 0 || | 1936 | if (stat(buf, &st) == -1 || |
1928 | !secure_permissions(&st, uid)) { | 1937 | !secure_permissions(&st, uid)) { |
1929 | snprintf(err, errlen, | 1938 | snprintf(err, errlen, |
1930 | "bad ownership or modes for directory %s", buf); | 1939 | "bad ownership or modes for directory %s", buf); |
@@ -1958,7 +1967,7 @@ safe_path_fd(int fd, const char *file, struct passwd *pw, | |||
1958 | struct stat st; | 1967 | struct stat st; |
1959 | 1968 | ||
1960 | /* check the open file to avoid races */ | 1969 | /* check the open file to avoid races */ |
1961 | if (fstat(fd, &st) < 0) { | 1970 | if (fstat(fd, &st) == -1) { |
1962 | snprintf(err, errlen, "cannot stat file %s: %s", | 1971 | snprintf(err, errlen, "cannot stat file %s: %s", |
1963 | file, strerror(errno)); | 1972 | file, strerror(errno)); |
1964 | return -1; | 1973 | return -1; |
@@ -2166,3 +2175,85 @@ path_absolute(const char *path) | |||
2166 | { | 2175 | { |
2167 | return (*path == '/') ? 1 : 0; | 2176 | return (*path == '/') ? 1 : 0; |
2168 | } | 2177 | } |
2178 | |||
2179 | void | ||
2180 | skip_space(char **cpp) | ||
2181 | { | ||
2182 | char *cp; | ||
2183 | |||
2184 | for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) | ||
2185 | ; | ||
2186 | *cpp = cp; | ||
2187 | } | ||
2188 | |||
2189 | /* authorized_key-style options parsing helpers */ | ||
2190 | |||
2191 | /* | ||
2192 | * Match flag 'opt' in *optsp, and if allow_negate is set then also match | ||
2193 | * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0 | ||
2194 | * if negated option matches. | ||
2195 | * If the option or negated option matches, then *optsp is updated to | ||
2196 | * point to the first character after the option. | ||
2197 | */ | ||
2198 | int | ||
2199 | opt_flag(const char *opt, int allow_negate, const char **optsp) | ||
2200 | { | ||
2201 | size_t opt_len = strlen(opt); | ||
2202 | const char *opts = *optsp; | ||
2203 | int negate = 0; | ||
2204 | |||
2205 | if (allow_negate && strncasecmp(opts, "no-", 3) == 0) { | ||
2206 | opts += 3; | ||
2207 | negate = 1; | ||
2208 | } | ||
2209 | if (strncasecmp(opts, opt, opt_len) == 0) { | ||
2210 | *optsp = opts + opt_len; | ||
2211 | return negate ? 0 : 1; | ||
2212 | } | ||
2213 | return -1; | ||
2214 | } | ||
2215 | |||
2216 | char * | ||
2217 | opt_dequote(const char **sp, const char **errstrp) | ||
2218 | { | ||
2219 | const char *s = *sp; | ||
2220 | char *ret; | ||
2221 | size_t i; | ||
2222 | |||
2223 | *errstrp = NULL; | ||
2224 | if (*s != '"') { | ||
2225 | *errstrp = "missing start quote"; | ||
2226 | return NULL; | ||
2227 | } | ||
2228 | s++; | ||
2229 | if ((ret = malloc(strlen((s)) + 1)) == NULL) { | ||
2230 | *errstrp = "memory allocation failed"; | ||
2231 | return NULL; | ||
2232 | } | ||
2233 | for (i = 0; *s != '\0' && *s != '"';) { | ||
2234 | if (s[0] == '\\' && s[1] == '"') | ||
2235 | s++; | ||
2236 | ret[i++] = *s++; | ||
2237 | } | ||
2238 | if (*s == '\0') { | ||
2239 | *errstrp = "missing end quote"; | ||
2240 | free(ret); | ||
2241 | return NULL; | ||
2242 | } | ||
2243 | ret[i] = '\0'; | ||
2244 | s++; | ||
2245 | *sp = s; | ||
2246 | return ret; | ||
2247 | } | ||
2248 | |||
2249 | int | ||
2250 | opt_match(const char **opts, const char *term) | ||
2251 | { | ||
2252 | if (strncasecmp((*opts), term, strlen(term)) == 0 && | ||
2253 | (*opts)[strlen(term)] == '=') { | ||
2254 | *opts += strlen(term) + 1; | ||
2255 | return 1; | ||
2256 | } | ||
2257 | return 0; | ||
2258 | } | ||
2259 | |||