1 /* $OpenBSD: misc.c,v 1.170 2021/09/26 14:01:03 djm Exp $ */
3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2005-2020 Damien Miller. All rights reserved.
5 * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include <sys/types.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <netinet/in_systm.h>
48 #include <netinet/ip.h>
49 #include <netinet/tcp.h>
50 #include <arpa/inet.h>
61 #ifdef SSH_TUN_OPENBSD
73 /* remove newline at end of string */
79 if (*t
== '\n' || *t
== '\r') {
89 /* remove whitespace from end of string */
95 if ((i
= strlen(s
)) == 0)
97 for (i
--; i
> 0; i
--) {
98 if (isspace((int)s
[i
]))
103 /* set/unset filedescriptor to non-blocking */
109 val
= fcntl(fd
, F_GETFL
);
111 error("fcntl(%d, F_GETFL): %s", fd
, strerror(errno
));
114 if (val
& O_NONBLOCK
) {
115 debug3("fd %d is O_NONBLOCK", fd
);
118 debug2("fd %d setting O_NONBLOCK", fd
);
120 if (fcntl(fd
, F_SETFL
, val
) == -1) {
121 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd
,
129 unset_nonblock(int fd
)
133 val
= fcntl(fd
, F_GETFL
);
135 error("fcntl(%d, F_GETFL): %s", fd
, strerror(errno
));
138 if (!(val
& O_NONBLOCK
)) {
139 debug3("fd %d is not O_NONBLOCK", fd
);
142 debug("fd %d clearing O_NONBLOCK", fd
);
144 if (fcntl(fd
, F_SETFL
, val
) == -1) {
145 debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
146 fd
, strerror(errno
));
153 ssh_gai_strerror(int gaierr
)
155 if (gaierr
== EAI_SYSTEM
&& errno
!= 0)
156 return strerror(errno
);
157 return gai_strerror(gaierr
);
160 /* disable nagle on socket */
168 if (getsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &opt
, &optlen
) == -1) {
169 debug("getsockopt TCP_NODELAY: %.100s", strerror(errno
));
173 debug2("fd %d is TCP_NODELAY", fd
);
177 debug2("fd %d setting TCP_NODELAY", fd
);
178 if (setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &opt
, sizeof opt
) == -1)
179 error("setsockopt TCP_NODELAY: %.100s", strerror(errno
));
182 /* Allow local port reuse in TIME_WAIT */
184 set_reuseaddr(int fd
)
188 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &on
, sizeof(on
)) == -1) {
189 error("setsockopt SO_REUSEADDR fd %d: %s", fd
, strerror(errno
));
195 /* Get/set routing domain */
199 #if defined(HAVE_SYS_GET_RDOMAIN)
200 return sys_get_rdomain(fd
);
201 #elif defined(__OpenBSD__)
204 socklen_t len
= sizeof(rtable
);
206 if (getsockopt(fd
, SOL_SOCKET
, SO_RTABLE
, &rtable
, &len
) == -1) {
207 error("Failed to get routing domain for fd %d: %s",
208 fd
, strerror(errno
));
211 xasprintf(&ret
, "%d", rtable
);
213 #else /* defined(__OpenBSD__) */
219 set_rdomain(int fd
, const char *name
)
221 #if defined(HAVE_SYS_SET_RDOMAIN)
222 return sys_set_rdomain(fd
, name
);
223 #elif defined(__OpenBSD__)
228 return 0; /* default table */
230 rtable
= (int)strtonum(name
, 0, 255, &errstr
);
231 if (errstr
!= NULL
) {
232 /* Shouldn't happen */
233 error("Invalid routing domain \"%s\": %s", name
, errstr
);
236 if (setsockopt(fd
, SOL_SOCKET
, SO_RTABLE
,
237 &rtable
, sizeof(rtable
)) == -1) {
238 error("Failed to set routing domain %d on fd %d: %s",
239 rtable
, fd
, strerror(errno
));
243 #else /* defined(__OpenBSD__) */
244 error("Setting routing domain is not supported on this platform");
252 struct sockaddr_storage to
;
253 socklen_t tolen
= sizeof(to
);
255 memset(&to
, 0, sizeof(to
));
256 if (getsockname(fd
, (struct sockaddr
*)&to
, &tolen
) == -1)
259 if (to
.ss_family
== AF_INET6
&&
260 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)&to
)->sin6_addr
))
267 set_sock_tos(int fd
, int tos
)
269 #ifndef IP_TOS_IS_BROKEN
272 switch ((af
= get_sock_af(fd
))) {
274 /* assume not a socket */
278 debug3_f("set socket %d IP_TOS 0x%02x", fd
, tos
);
279 if (setsockopt(fd
, IPPROTO_IP
, IP_TOS
,
280 &tos
, sizeof(tos
)) == -1) {
281 error("setsockopt socket %d IP_TOS %d: %s:",
282 fd
, tos
, strerror(errno
));
288 debug3_f("set socket %d IPV6_TCLASS 0x%02x", fd
, tos
);
289 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_TCLASS
,
290 &tos
, sizeof(tos
)) == -1) {
291 error("setsockopt socket %d IPV6_TCLASS %d: %.100s:",
292 fd
, tos
, strerror(errno
));
294 # endif /* IPV6_TCLASS */
297 debug2_f("unsupported socket family %d", af
);
300 #endif /* IP_TOS_IS_BROKEN */
304 * Wait up to *timeoutp milliseconds for events on fd. Updates
305 * *timeoutp with time remaining.
306 * Returns 0 if fd ready or -1 on timeout or error (see errno).
309 waitfd(int fd
, int *timeoutp
, short events
)
312 struct timeval t_start
;
317 for (; *timeoutp
>= 0;) {
318 monotime_tv(&t_start
);
319 r
= poll(&pfd
, 1, *timeoutp
);
321 ms_subtract_diff(&t_start
, timeoutp
);
325 else if (r
== -1 && errno
!= EAGAIN
&& errno
!= EINTR
)
336 * Wait up to *timeoutp milliseconds for fd to be readable. Updates
337 * *timeoutp with time remaining.
338 * Returns 0 if fd ready or -1 on timeout or error (see errno).
341 waitrfd(int fd
, int *timeoutp
) {
342 return waitfd(fd
, timeoutp
, POLLIN
);
346 * Attempt a non-blocking connect(2) to the specified address, waiting up to
347 * *timeoutp milliseconds for the connection to complete. If the timeout is
348 * <=0, then wait indefinitely.
350 * Returns 0 on success or -1 on failure.
353 timeout_connect(int sockfd
, const struct sockaddr
*serv_addr
,
354 socklen_t addrlen
, int *timeoutp
)
357 socklen_t optlen
= sizeof(optval
);
359 /* No timeout: just do a blocking connect() */
360 if (timeoutp
== NULL
|| *timeoutp
<= 0)
361 return connect(sockfd
, serv_addr
, addrlen
);
363 set_nonblock(sockfd
);
365 if (connect(sockfd
, serv_addr
, addrlen
) == 0) {
366 /* Succeeded already? */
367 unset_nonblock(sockfd
);
369 } else if (errno
== EINTR
)
371 else if (errno
!= EINPROGRESS
)
376 if (waitfd(sockfd
, timeoutp
, POLLIN
| POLLOUT
) == -1)
379 /* Completed or failed */
380 if (getsockopt(sockfd
, SOL_SOCKET
, SO_ERROR
, &optval
, &optlen
) == -1) {
381 debug("getsockopt: %s", strerror(errno
));
388 unset_nonblock(sockfd
);
392 /* Characters considered whitespace in strsep calls. */
393 #define WHITESPACE " \t\r\n"
396 /* return next token in configuration line */
398 strdelim_internal(char **s
, int split_equals
)
409 split_equals
? WHITESPACE QUOTE
"=" : WHITESPACE QUOTE
);
414 memmove(*s
, *s
+ 1, strlen(*s
)); /* move nul too */
415 /* Find matching quote */
416 if ((*s
= strpbrk(*s
, QUOTE
)) == NULL
) {
417 return (NULL
); /* no matching quote */
420 *s
+= strspn(*s
+ 1, WHITESPACE
) + 1;
425 /* Allow only one '=' to be skipped */
426 if (split_equals
&& *s
[0] == '=')
430 /* Skip any extra whitespace after first token */
431 *s
+= strspn(*s
+ 1, WHITESPACE
) + 1;
432 if (split_equals
&& *s
[0] == '=' && !wspace
)
433 *s
+= strspn(*s
+ 1, WHITESPACE
) + 1;
439 * Return next token in configuration line; splts on whitespace or a
440 * single '=' character.
445 return strdelim_internal(s
, 1);
449 * Return next token in configuration line; splts on whitespace only.
454 return strdelim_internal(s
, 0);
458 pwcopy(struct passwd
*pw
)
460 struct passwd
*copy
= xcalloc(1, sizeof(*copy
));
462 copy
->pw_name
= xstrdup(pw
->pw_name
);
463 copy
->pw_passwd
= xstrdup(pw
->pw_passwd
== NULL
? "*" : pw
->pw_passwd
);
464 #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
465 copy
->pw_gecos
= xstrdup(pw
->pw_gecos
);
467 copy
->pw_uid
= pw
->pw_uid
;
468 copy
->pw_gid
= pw
->pw_gid
;
469 #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
470 copy
->pw_expire
= pw
->pw_expire
;
472 #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
473 copy
->pw_change
= pw
->pw_change
;
475 #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
476 copy
->pw_class
= xstrdup(pw
->pw_class
);
478 copy
->pw_dir
= xstrdup(pw
->pw_dir
);
479 copy
->pw_shell
= xstrdup(pw
->pw_shell
);
484 * Convert ASCII string to TCP/IP port number.
485 * Port must be >=0 and <=65535.
486 * Return -1 if invalid.
489 a2port(const char *s
)
495 port
= strtonum(s
, 0, 65535, &errstr
);
498 if ((se
= getservbyname(s
, "tcp")) != NULL
)
499 return ntohs(se
->s_port
);
504 a2tun(const char *s
, int *remote
)
506 const char *errstr
= NULL
;
510 if (remote
!= NULL
) {
511 *remote
= SSH_TUNID_ANY
;
513 if ((ep
= strchr(sp
, ':')) == NULL
) {
515 return (a2tun(s
, NULL
));
518 *remote
= a2tun(ep
, NULL
);
519 tun
= a2tun(sp
, NULL
);
521 return (*remote
== SSH_TUNID_ERR
? *remote
: tun
);
524 if (strcasecmp(s
, "any") == 0)
525 return (SSH_TUNID_ANY
);
527 tun
= strtonum(s
, 0, SSH_TUNID_MAX
, &errstr
);
529 return (SSH_TUNID_ERR
);
535 #define MINUTES (SECONDS * 60)
536 #define HOURS (MINUTES * 60)
537 #define DAYS (HOURS * 24)
538 #define WEEKS (DAYS * 7)
541 * Convert a time string into seconds; format is
545 * Valid time qualifiers are:
559 * Return -1 if time string is invalid.
562 convtime(const char *s
)
564 long total
, secs
, multiplier
;
572 if (p
== NULL
|| *p
== '\0')
576 secs
= strtol(p
, &endp
, 10);
578 (errno
== ERANGE
&& (secs
== INT_MIN
|| secs
== INT_MAX
)) ||
592 multiplier
= MINUTES
;
609 if (secs
> INT_MAX
/ multiplier
)
612 if (total
> INT_MAX
- secs
)
627 fmt_timeframe(time_t t
)
630 static char tfbuf
[TF_BUFS
][TF_LEN
]; /* ring buffer */
632 unsigned int sec
, min
, hrs
, day
;
633 unsigned long long week
;
651 snprintf(buf
, TF_LEN
, "%02lluw%01ud%02uh", week
, day
, hrs
);
653 snprintf(buf
, TF_LEN
, "%01ud%02uh%02um", day
, hrs
, min
);
655 snprintf(buf
, TF_LEN
, "%02u:%02u:%02u", hrs
, min
, sec
);
661 * Returns a standardized host+port identifier string.
662 * Caller must free returned string.
665 put_host_port(const char *host
, u_short port
)
669 if (port
== 0 || port
== SSH_DEFAULT_PORT
)
670 return(xstrdup(host
));
671 if (asprintf(&hoststr
, "[%s]:%d", host
, (int)port
) == -1)
672 fatal("put_host_port: asprintf: %s", strerror(errno
));
673 debug3("put_host_port: %s", hoststr
);
678 * Search for next delimiter between hostnames/addresses and ports.
679 * Argument may be modified (for termination).
680 * Returns *cp if parsing succeeds.
681 * *cp is set to the start of the next field, if one was found.
682 * The delimiter char, if present, is stored in delim.
683 * If this is the last field, *cp is set to NULL.
686 hpdelim2(char **cp
, char *delim
)
690 if (cp
== NULL
|| *cp
== NULL
)
695 if ((s
= strchr(s
, ']')) == NULL
)
699 } else if ((s
= strpbrk(s
, ":/")) == NULL
)
700 s
= *cp
+ strlen(*cp
); /* skip to end (see first case below) */
704 *cp
= NULL
; /* no more fields*/
711 *s
= '\0'; /* terminate */
725 return hpdelim2(cp
, NULL
);
729 cleanhostname(char *host
)
731 if (*host
== '[' && host
[strlen(host
) - 1] == ']') {
732 host
[strlen(host
) - 1] = '\0';
743 if (*cp
== ':') /* Leading colon is part of file name. */
749 if (*cp
== '@' && *(cp
+1) == '[')
751 if (*cp
== ']' && *(cp
+1) == ':' && flag
)
753 if (*cp
== ':' && !flag
)
762 * Parse a [user@]host:[path] string.
763 * Caller must free returned user, host and path.
764 * Any of the pointer return arguments may be NULL (useful for syntax checking).
765 * If user was not specified then *userp will be set to NULL.
766 * If host was not specified then *hostp will be set to NULL.
767 * If path was not specified then *pathp will be set to ".".
768 * Returns 0 on success, -1 on failure.
771 parse_user_host_path(const char *s
, char **userp
, char **hostp
, char **pathp
)
773 char *user
= NULL
, *host
= NULL
, *path
= NULL
;
786 /* Check for remote syntax: [user@]host:[path] */
787 if ((tmp
= colon(sdup
)) == NULL
)
790 /* Extract optional path */
796 /* Extract optional user and mandatory host */
797 tmp
= strrchr(sdup
, '@');
800 host
= xstrdup(cleanhostname(tmp
));
802 user
= xstrdup(sdup
);
804 host
= xstrdup(cleanhostname(sdup
));
831 * Parse a [user@]host[:port] string.
832 * Caller must free returned user and host.
833 * Any of the pointer return arguments may be NULL (useful for syntax checking).
834 * If user was not specified then *userp will be set to NULL.
835 * If port was not specified then *portp will be -1.
836 * Returns 0 on success, -1 on failure.
839 parse_user_host_port(const char *s
, char **userp
, char **hostp
, int *portp
)
841 char *sdup
, *cp
, *tmp
;
842 char *user
= NULL
, *host
= NULL
;
843 int port
= -1, ret
= -1;
852 if ((sdup
= tmp
= strdup(s
)) == NULL
)
854 /* Extract optional username */
855 if ((cp
= strrchr(tmp
, '@')) != NULL
) {
859 if ((user
= strdup(tmp
)) == NULL
)
863 /* Extract mandatory hostname */
864 if ((cp
= hpdelim(&tmp
)) == NULL
|| *cp
== '\0')
866 host
= xstrdup(cleanhostname(cp
));
867 /* Convert and verify optional port */
868 if (tmp
!= NULL
&& *tmp
!= '\0') {
869 if ((port
= a2port(tmp
)) <= 0)
892 * Converts a two-byte hex string to decimal.
893 * Returns the decimal value or -1 for invalid input.
896 hexchar(const char *s
)
898 unsigned char result
[2];
901 for (i
= 0; i
< 2; i
++) {
902 if (s
[i
] >= '0' && s
[i
] <= '9')
903 result
[i
] = (unsigned char)(s
[i
] - '0');
904 else if (s
[i
] >= 'a' && s
[i
] <= 'f')
905 result
[i
] = (unsigned char)(s
[i
] - 'a') + 10;
906 else if (s
[i
] >= 'A' && s
[i
] <= 'F')
907 result
[i
] = (unsigned char)(s
[i
] - 'A') + 10;
911 return (result
[0] << 4) | result
[1];
915 * Decode an url-encoded string.
916 * Returns a newly allocated string on success or NULL on failure.
919 urldecode(const char *src
)
924 ret
= xmalloc(strlen(src
) + 1);
925 for (dst
= ret
; *src
!= '\0'; src
++) {
931 if (!isxdigit((unsigned char)src
[1]) ||
932 !isxdigit((unsigned char)src
[2]) ||
933 (ch
= hexchar(src
+ 1)) == -1) {
951 * Parse an (scp|ssh|sftp)://[user@]host[:port][/path] URI.
952 * See https://tools.ietf.org/html/draft-ietf-secsh-scp-sftp-ssh-uri-04
953 * Either user or path may be url-encoded (but not host or port).
954 * Caller must free returned user, host and path.
955 * Any of the pointer return arguments may be NULL (useful for syntax checking)
956 * but the scheme must always be specified.
957 * If user was not specified then *userp will be set to NULL.
958 * If port was not specified then *portp will be -1.
959 * If path was not specified then *pathp will be set to NULL.
960 * Returns 0 on success, 1 if non-uri/wrong scheme, -1 on error/invalid uri.
963 parse_uri(const char *scheme
, const char *uri
, char **userp
, char **hostp
,
964 int *portp
, char **pathp
)
966 char *uridup
, *cp
, *tmp
, ch
;
967 char *user
= NULL
, *host
= NULL
, *path
= NULL
;
968 int port
= -1, ret
= -1;
971 len
= strlen(scheme
);
972 if (strncmp(uri
, scheme
, len
) != 0 || strncmp(uri
+ len
, "://", 3) != 0)
985 uridup
= tmp
= xstrdup(uri
);
987 /* Extract optional ssh-info (username + connection params) */
988 if ((cp
= strchr(tmp
, '@')) != NULL
) {
992 /* Extract username and connection params */
993 if ((delim
= strchr(tmp
, ';')) != NULL
) {
994 /* Just ignore connection params for now */
1001 if ((user
= urldecode(tmp
)) == NULL
)
1006 /* Extract mandatory hostname */
1007 if ((cp
= hpdelim2(&tmp
, &ch
)) == NULL
|| *cp
== '\0')
1009 host
= xstrdup(cleanhostname(cp
));
1010 if (!valid_domain(host
, 0, NULL
))
1013 if (tmp
!= NULL
&& *tmp
!= '\0') {
1015 /* Convert and verify port. */
1016 if ((cp
= strchr(tmp
, '/')) != NULL
)
1018 if ((port
= a2port(tmp
)) <= 0)
1020 tmp
= cp
? cp
+ 1 : NULL
;
1022 if (tmp
!= NULL
&& *tmp
!= '\0') {
1023 /* Extract optional path */
1024 if ((path
= urldecode(tmp
)) == NULL
)
1030 if (userp
!= NULL
) {
1034 if (hostp
!= NULL
) {
1040 if (pathp
!= NULL
) {
1053 /* function to assist building execv() arguments */
1055 addargs(arglist
*args
, char *fmt
, ...)
1063 r
= vasprintf(&cp
, fmt
, ap
);
1066 fatal("addargs: argument too long");
1068 nalloc
= args
->nalloc
;
1069 if (args
->list
== NULL
) {
1072 } else if (args
->num
+2 >= nalloc
)
1075 args
->list
= xrecallocarray(args
->list
, args
->nalloc
, nalloc
, sizeof(char *));
1076 args
->nalloc
= nalloc
;
1077 args
->list
[args
->num
++] = cp
;
1078 args
->list
[args
->num
] = NULL
;
1082 replacearg(arglist
*args
, u_int which
, char *fmt
, ...)
1089 r
= vasprintf(&cp
, fmt
, ap
);
1092 fatal("replacearg: argument too long");
1094 if (which
>= args
->num
)
1095 fatal("replacearg: tried to replace invalid arg %d >= %d",
1097 free(args
->list
[which
]);
1098 args
->list
[which
] = cp
;
1102 freeargs(arglist
*args
)
1106 if (args
->list
!= NULL
) {
1107 for (i
= 0; i
< args
->num
; i
++)
1108 free(args
->list
[i
]);
1110 args
->nalloc
= args
->num
= 0;
1116 * Expands tildes in the file name. Returns data allocated by xmalloc.
1117 * Warning: this calls getpw*.
1120 tilde_expand(const char *filename
, uid_t uid
, char **retp
)
1122 const char *path
, *sep
;
1123 char user
[128], *ret
;
1127 if (*filename
!= '~') {
1128 *retp
= xstrdup(filename
);
1133 path
= strchr(filename
, '/');
1134 if (path
!= NULL
&& path
> filename
) { /* ~user/path */
1135 slash
= path
- filename
;
1136 if (slash
> sizeof(user
) - 1) {
1137 error_f("~username too long");
1140 memcpy(user
, filename
, slash
);
1142 if ((pw
= getpwnam(user
)) == NULL
) {
1143 error_f("No such user %s", user
);
1146 } else if ((pw
= getpwuid(uid
)) == NULL
) { /* ~/path */
1147 error_f("No such uid %ld", (long)uid
);
1151 /* Make sure directory has a trailing '/' */
1152 len
= strlen(pw
->pw_dir
);
1153 if (len
== 0 || pw
->pw_dir
[len
- 1] != '/')
1158 /* Skip leading '/' from specified path */
1160 filename
= path
+ 1;
1162 if (xasprintf(&ret
, "%s%s%s", pw
->pw_dir
, sep
, filename
) >= PATH_MAX
) {
1163 error_f("Path too long");
1172 tilde_expand_filename(const char *filename
, uid_t uid
)
1176 if (tilde_expand(filename
, uid
, &ret
) != 0)
1182 * Expand a string with a set of %[char] escapes and/or ${ENVIRONMENT}
1183 * substitutions. A number of escapes may be specified as
1184 * (char *escape_chars, char *replacement) pairs. The list must be terminated
1185 * by a NULL escape_char. Returns replaced string in memory allocated by
1186 * xmalloc which the caller must free.
1189 vdollar_percent_expand(int *parseerror
, int dollar
, int percent
,
1190 const char *string
, va_list ap
)
1192 #define EXPAND_MAX_KEYS 16
1193 u_int num_keys
= 0, i
;
1197 } keys
[EXPAND_MAX_KEYS
];
1199 int r
, missingvar
= 0;
1200 char *ret
= NULL
, *var
, *varend
, *val
;
1203 if ((buf
= sshbuf_new()) == NULL
)
1204 fatal_f("sshbuf_new failed");
1205 if (parseerror
== NULL
)
1206 fatal_f("null parseerror arg");
1209 /* Gather keys if we're doing percent expansion. */
1211 for (num_keys
= 0; num_keys
< EXPAND_MAX_KEYS
; num_keys
++) {
1212 keys
[num_keys
].key
= va_arg(ap
, char *);
1213 if (keys
[num_keys
].key
== NULL
)
1215 keys
[num_keys
].repl
= va_arg(ap
, char *);
1216 if (keys
[num_keys
].repl
== NULL
) {
1217 fatal_f("NULL replacement for token %s",
1218 keys
[num_keys
].key
);
1221 if (num_keys
== EXPAND_MAX_KEYS
&& va_arg(ap
, char *) != NULL
)
1222 fatal_f("too many keys");
1224 fatal_f("percent expansion without token list");
1228 for (i
= 0; *string
!= '\0'; string
++) {
1229 /* Optionally process ${ENVIRONMENT} expansions. */
1230 if (dollar
&& string
[0] == '$' && string
[1] == '{') {
1231 string
+= 2; /* skip over '${' */
1232 if ((varend
= strchr(string
, '}')) == NULL
) {
1233 error_f("environment variable '%s' missing "
1234 "closing '}'", string
);
1237 len
= varend
- string
;
1239 error_f("zero-length environment variable");
1242 var
= xmalloc(len
+ 1);
1243 (void)strlcpy(var
, string
, len
+ 1);
1244 if ((val
= getenv(var
)) == NULL
) {
1245 error_f("env var ${%s} has no value", var
);
1248 debug3_f("expand ${%s} -> '%s'", var
, val
);
1249 if ((r
= sshbuf_put(buf
, val
, strlen(val
))) !=0)
1250 fatal_fr(r
, "sshbuf_put ${}");
1258 * Process percent expansions if we have a list of TOKENs.
1259 * If we're not doing percent expansion everything just gets
1262 if (*string
!= '%' || !percent
) {
1264 if ((r
= sshbuf_put_u8(buf
, *string
)) != 0)
1265 fatal_fr(r
, "sshbuf_put_u8 %%");
1272 if (*string
== '\0') {
1273 error_f("invalid format");
1276 for (i
= 0; i
< num_keys
; i
++) {
1277 if (strchr(keys
[i
].key
, *string
) != NULL
) {
1278 if ((r
= sshbuf_put(buf
, keys
[i
].repl
,
1279 strlen(keys
[i
].repl
))) != 0)
1280 fatal_fr(r
, "sshbuf_put %%-repl");
1284 if (i
>= num_keys
) {
1285 error_f("unknown key %%%c", *string
);
1289 if (!missingvar
&& (ret
= sshbuf_dup_string(buf
)) == NULL
)
1290 fatal_f("sshbuf_dup_string failed");
1294 return *parseerror
? NULL
: ret
;
1295 #undef EXPAND_MAX_KEYS
1299 * Expand only environment variables.
1300 * Note that although this function is variadic like the other similar
1301 * functions, any such arguments will be unused.
1305 dollar_expand(int *parseerr
, const char *string
, ...)
1311 va_start(ap
, string
);
1312 ret
= vdollar_percent_expand(&err
, 1, 0, string
, ap
);
1314 if (parseerr
!= NULL
)
1320 * Returns expanded string or NULL if a specified environment variable is
1321 * not defined, or calls fatal if the string is invalid.
1324 percent_expand(const char *string
, ...)
1330 va_start(ap
, string
);
1331 ret
= vdollar_percent_expand(&err
, 0, 1, string
, ap
);
1339 * Returns expanded string or NULL if a specified environment variable is
1340 * not defined, or calls fatal if the string is invalid.
1343 percent_dollar_expand(const char *string
, ...)
1349 va_start(ap
, string
);
1350 ret
= vdollar_percent_expand(&err
, 1, 1, string
, ap
);
1358 tun_open(int tun
, int mode
, char **ifname
)
1360 #if defined(CUSTOM_SYS_TUN_OPEN)
1361 return (sys_tun_open(tun
, mode
, ifname
));
1362 #elif defined(SSH_TUN_OPENBSD)
1366 const char *tunbase
= "tun";
1371 if (mode
== SSH_TUNMODE_ETHERNET
)
1374 /* Open the tunnel device */
1375 if (tun
<= SSH_TUNID_MAX
) {
1376 snprintf(name
, sizeof(name
), "/dev/%s%d", tunbase
, tun
);
1377 fd
= open(name
, O_RDWR
);
1378 } else if (tun
== SSH_TUNID_ANY
) {
1379 for (tun
= 100; tun
>= 0; tun
--) {
1380 snprintf(name
, sizeof(name
), "/dev/%s%d",
1382 if ((fd
= open(name
, O_RDWR
)) >= 0)
1386 debug_f("invalid tunnel %u", tun
);
1391 debug_f("%s open: %s", name
, strerror(errno
));
1395 debug_f("%s mode %d fd %d", name
, mode
, fd
);
1397 /* Bring interface up if it is not already */
1398 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d", tunbase
, tun
);
1399 if ((sock
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
1402 if (ioctl(sock
, SIOCGIFFLAGS
, &ifr
) == -1) {
1403 debug_f("get interface %s flags: %s", ifr
.ifr_name
,
1408 if (!(ifr
.ifr_flags
& IFF_UP
)) {
1409 ifr
.ifr_flags
|= IFF_UP
;
1410 if (ioctl(sock
, SIOCSIFFLAGS
, &ifr
) == -1) {
1411 debug_f("activate interface %s: %s", ifr
.ifr_name
,
1418 *ifname
= xstrdup(ifr
.ifr_name
);
1430 error("Tunnel interfaces are not supported on this platform");
1436 sanitise_stdfd(void)
1440 if ((nullfd
= dupfd
= open(_PATH_DEVNULL
, O_RDWR
)) == -1) {
1441 fprintf(stderr
, "Couldn't open /dev/null: %s\n",
1445 while (++dupfd
<= STDERR_FILENO
) {
1446 /* Only populate closed fds. */
1447 if (fcntl(dupfd
, F_GETFL
) == -1 && errno
== EBADF
) {
1448 if (dup2(nullfd
, dupfd
) == -1) {
1449 fprintf(stderr
, "dup2: %s\n", strerror(errno
));
1454 if (nullfd
> STDERR_FILENO
)
1459 tohex(const void *vp
, size_t l
)
1461 const u_char
*p
= (const u_char
*)vp
;
1466 return xstrdup("tohex: length > 65536");
1470 for (i
= 0; i
< l
; i
++) {
1471 snprintf(b
, sizeof(b
), "%02x", p
[i
]);
1478 * Extend string *sp by the specified format. If *sp is not NULL (or empty),
1479 * then the separator 'sep' will be prepended before the formatted arguments.
1480 * Extended strings are heap allocated.
1483 xextendf(char **sp
, const char *sep
, const char *fmt
, ...)
1489 xvasprintf(&tmp1
, fmt
, ap
);
1492 if (*sp
== NULL
|| **sp
== '\0') {
1497 xasprintf(&tmp2
, "%s%s%s", *sp
, sep
== NULL
? "" : sep
, tmp1
);
1505 get_u64(const void *vp
)
1507 const u_char
*p
= (const u_char
*)vp
;
1510 v
= (u_int64_t
)p
[0] << 56;
1511 v
|= (u_int64_t
)p
[1] << 48;
1512 v
|= (u_int64_t
)p
[2] << 40;
1513 v
|= (u_int64_t
)p
[3] << 32;
1514 v
|= (u_int64_t
)p
[4] << 24;
1515 v
|= (u_int64_t
)p
[5] << 16;
1516 v
|= (u_int64_t
)p
[6] << 8;
1517 v
|= (u_int64_t
)p
[7];
1523 get_u32(const void *vp
)
1525 const u_char
*p
= (const u_char
*)vp
;
1528 v
= (u_int32_t
)p
[0] << 24;
1529 v
|= (u_int32_t
)p
[1] << 16;
1530 v
|= (u_int32_t
)p
[2] << 8;
1531 v
|= (u_int32_t
)p
[3];
1537 get_u32_le(const void *vp
)
1539 const u_char
*p
= (const u_char
*)vp
;
1542 v
= (u_int32_t
)p
[0];
1543 v
|= (u_int32_t
)p
[1] << 8;
1544 v
|= (u_int32_t
)p
[2] << 16;
1545 v
|= (u_int32_t
)p
[3] << 24;
1551 get_u16(const void *vp
)
1553 const u_char
*p
= (const u_char
*)vp
;
1556 v
= (u_int16_t
)p
[0] << 8;
1557 v
|= (u_int16_t
)p
[1];
1563 put_u64(void *vp
, u_int64_t v
)
1565 u_char
*p
= (u_char
*)vp
;
1567 p
[0] = (u_char
)(v
>> 56) & 0xff;
1568 p
[1] = (u_char
)(v
>> 48) & 0xff;
1569 p
[2] = (u_char
)(v
>> 40) & 0xff;
1570 p
[3] = (u_char
)(v
>> 32) & 0xff;
1571 p
[4] = (u_char
)(v
>> 24) & 0xff;
1572 p
[5] = (u_char
)(v
>> 16) & 0xff;
1573 p
[6] = (u_char
)(v
>> 8) & 0xff;
1574 p
[7] = (u_char
)v
& 0xff;
1578 put_u32(void *vp
, u_int32_t v
)
1580 u_char
*p
= (u_char
*)vp
;
1582 p
[0] = (u_char
)(v
>> 24) & 0xff;
1583 p
[1] = (u_char
)(v
>> 16) & 0xff;
1584 p
[2] = (u_char
)(v
>> 8) & 0xff;
1585 p
[3] = (u_char
)v
& 0xff;
1589 put_u32_le(void *vp
, u_int32_t v
)
1591 u_char
*p
= (u_char
*)vp
;
1593 p
[0] = (u_char
)v
& 0xff;
1594 p
[1] = (u_char
)(v
>> 8) & 0xff;
1595 p
[2] = (u_char
)(v
>> 16) & 0xff;
1596 p
[3] = (u_char
)(v
>> 24) & 0xff;
1600 put_u16(void *vp
, u_int16_t v
)
1602 u_char
*p
= (u_char
*)vp
;
1604 p
[0] = (u_char
)(v
>> 8) & 0xff;
1605 p
[1] = (u_char
)v
& 0xff;
1609 ms_subtract_diff(struct timeval
*start
, int *ms
)
1611 struct timeval diff
, finish
;
1613 monotime_tv(&finish
);
1614 timersub(&finish
, start
, &diff
);
1615 *ms
-= (diff
.tv_sec
* 1000) + (diff
.tv_usec
/ 1000);
1619 ms_to_timeval(struct timeval
*tv
, int ms
)
1623 tv
->tv_sec
= ms
/ 1000;
1624 tv
->tv_usec
= (ms
% 1000) * 1000;
1628 monotime_ts(struct timespec
*ts
)
1631 #if defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_BOOTTIME) || \
1632 defined(CLOCK_MONOTONIC) || defined(CLOCK_REALTIME))
1633 static int gettime_failed
= 0;
1635 if (!gettime_failed
) {
1636 # ifdef CLOCK_BOOTTIME
1637 if (clock_gettime(CLOCK_BOOTTIME
, ts
) == 0)
1639 # endif /* CLOCK_BOOTTIME */
1640 # ifdef CLOCK_MONOTONIC
1641 if (clock_gettime(CLOCK_MONOTONIC
, ts
) == 0)
1643 # endif /* CLOCK_MONOTONIC */
1644 # ifdef CLOCK_REALTIME
1645 /* Not monotonic, but we're almost out of options here. */
1646 if (clock_gettime(CLOCK_REALTIME
, ts
) == 0)
1648 # endif /* CLOCK_REALTIME */
1649 debug3("clock_gettime: %s", strerror(errno
));
1652 #endif /* HAVE_CLOCK_GETTIME && (BOOTTIME || MONOTONIC || REALTIME) */
1653 gettimeofday(&tv
, NULL
);
1654 ts
->tv_sec
= tv
.tv_sec
;
1655 ts
->tv_nsec
= (long)tv
.tv_usec
* 1000;
1659 monotime_tv(struct timeval
*tv
)
1664 tv
->tv_sec
= ts
.tv_sec
;
1665 tv
->tv_usec
= ts
.tv_nsec
/ 1000;
1678 monotime_double(void)
1683 return ts
.tv_sec
+ ((double)ts
.tv_nsec
/ 1000000000);
1687 bandwidth_limit_init(struct bwlimit
*bw
, u_int64_t kbps
, size_t buflen
)
1689 bw
->buflen
= buflen
;
1691 bw
->thresh
= buflen
;
1693 timerclear(&bw
->bwstart
);
1694 timerclear(&bw
->bwend
);
1697 /* Callback from read/write loop to insert bandwidth-limiting delays */
1699 bandwidth_limit(struct bwlimit
*bw
, size_t read_len
)
1702 struct timespec ts
, rm
;
1704 bw
->lamt
+= read_len
;
1705 if (!timerisset(&bw
->bwstart
)) {
1706 monotime_tv(&bw
->bwstart
);
1709 if (bw
->lamt
< bw
->thresh
)
1712 monotime_tv(&bw
->bwend
);
1713 timersub(&bw
->bwend
, &bw
->bwstart
, &bw
->bwend
);
1714 if (!timerisset(&bw
->bwend
))
1718 waitlen
= (double)1000000L * bw
->lamt
/ bw
->rate
;
1720 bw
->bwstart
.tv_sec
= waitlen
/ 1000000L;
1721 bw
->bwstart
.tv_usec
= waitlen
% 1000000L;
1723 if (timercmp(&bw
->bwstart
, &bw
->bwend
, >)) {
1724 timersub(&bw
->bwstart
, &bw
->bwend
, &bw
->bwend
);
1726 /* Adjust the wait time */
1727 if (bw
->bwend
.tv_sec
) {
1729 if (bw
->thresh
< bw
->buflen
/ 4)
1730 bw
->thresh
= bw
->buflen
/ 4;
1731 } else if (bw
->bwend
.tv_usec
< 10000) {
1733 if (bw
->thresh
> bw
->buflen
* 8)
1734 bw
->thresh
= bw
->buflen
* 8;
1737 TIMEVAL_TO_TIMESPEC(&bw
->bwend
, &ts
);
1738 while (nanosleep(&ts
, &rm
) == -1) {
1746 monotime_tv(&bw
->bwstart
);
1749 /* Make a template filename for mk[sd]temp() */
1751 mktemp_proto(char *s
, size_t len
)
1756 if ((tmpdir
= getenv("TMPDIR")) != NULL
) {
1757 r
= snprintf(s
, len
, "%s/ssh-XXXXXXXXXXXX", tmpdir
);
1758 if (r
> 0 && (size_t)r
< len
)
1761 r
= snprintf(s
, len
, "/tmp/ssh-XXXXXXXXXXXX");
1762 if (r
< 0 || (size_t)r
>= len
)
1763 fatal_f("template string too short");
1766 static const struct {
1770 { "none", INT_MAX
}, /* can't use 0 here; that's CS0 */
1771 { "af11", IPTOS_DSCP_AF11
},
1772 { "af12", IPTOS_DSCP_AF12
},
1773 { "af13", IPTOS_DSCP_AF13
},
1774 { "af21", IPTOS_DSCP_AF21
},
1775 { "af22", IPTOS_DSCP_AF22
},
1776 { "af23", IPTOS_DSCP_AF23
},
1777 { "af31", IPTOS_DSCP_AF31
},
1778 { "af32", IPTOS_DSCP_AF32
},
1779 { "af33", IPTOS_DSCP_AF33
},
1780 { "af41", IPTOS_DSCP_AF41
},
1781 { "af42", IPTOS_DSCP_AF42
},
1782 { "af43", IPTOS_DSCP_AF43
},
1783 { "cs0", IPTOS_DSCP_CS0
},
1784 { "cs1", IPTOS_DSCP_CS1
},
1785 { "cs2", IPTOS_DSCP_CS2
},
1786 { "cs3", IPTOS_DSCP_CS3
},
1787 { "cs4", IPTOS_DSCP_CS4
},
1788 { "cs5", IPTOS_DSCP_CS5
},
1789 { "cs6", IPTOS_DSCP_CS6
},
1790 { "cs7", IPTOS_DSCP_CS7
},
1791 { "ef", IPTOS_DSCP_EF
},
1792 { "le", IPTOS_DSCP_LE
},
1793 { "lowdelay", IPTOS_LOWDELAY
},
1794 { "throughput", IPTOS_THROUGHPUT
},
1795 { "reliability", IPTOS_RELIABILITY
},
1800 parse_ipqos(const char *cp
)
1808 for (i
= 0; ipqos
[i
].name
!= NULL
; i
++) {
1809 if (strcasecmp(cp
, ipqos
[i
].name
) == 0)
1810 return ipqos
[i
].value
;
1812 /* Try parsing as an integer */
1813 val
= strtol(cp
, &ep
, 0);
1814 if (*cp
== '\0' || *ep
!= '\0' || val
< 0 || val
> 255)
1820 iptos2str(int iptos
)
1823 static char iptos_str
[sizeof "0xff"];
1825 for (i
= 0; ipqos
[i
].name
!= NULL
; i
++) {
1826 if (ipqos
[i
].value
== iptos
)
1827 return ipqos
[i
].name
;
1829 snprintf(iptos_str
, sizeof iptos_str
, "0x%02x", iptos
);
1837 *s
= tolower((u_char
)*s
);
1841 unix_listener(const char *path
, int backlog
, int unlink_first
)
1843 struct sockaddr_un sunaddr
;
1844 int saved_errno
, sock
;
1846 memset(&sunaddr
, 0, sizeof(sunaddr
));
1847 sunaddr
.sun_family
= AF_UNIX
;
1848 if (strlcpy(sunaddr
.sun_path
, path
,
1849 sizeof(sunaddr
.sun_path
)) >= sizeof(sunaddr
.sun_path
)) {
1850 error_f("path \"%s\" too long for Unix domain socket", path
);
1851 errno
= ENAMETOOLONG
;
1855 sock
= socket(PF_UNIX
, SOCK_STREAM
, 0);
1857 saved_errno
= errno
;
1858 error_f("socket: %.100s", strerror(errno
));
1859 errno
= saved_errno
;
1862 if (unlink_first
== 1) {
1863 if (unlink(path
) != 0 && errno
!= ENOENT
)
1864 error("unlink(%s): %.100s", path
, strerror(errno
));
1866 if (bind(sock
, (struct sockaddr
*)&sunaddr
, sizeof(sunaddr
)) == -1) {
1867 saved_errno
= errno
;
1868 error_f("cannot bind to path %s: %s", path
, strerror(errno
));
1870 errno
= saved_errno
;
1873 if (listen(sock
, backlog
) == -1) {
1874 saved_errno
= errno
;
1875 error_f("cannot listen on path %s: %s", path
, strerror(errno
));
1878 errno
= saved_errno
;
1885 sock_set_v6only(int s
)
1887 #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
1890 debug3("%s: set socket %d IPV6_V6ONLY", __func__
, s
);
1891 if (setsockopt(s
, IPPROTO_IPV6
, IPV6_V6ONLY
, &on
, sizeof(on
)) == -1)
1892 error("setsockopt IPV6_V6ONLY: %s", strerror(errno
));
1897 * Compares two strings that maybe be NULL. Returns non-zero if strings
1898 * are both NULL or are identical, returns zero otherwise.
1901 strcmp_maybe_null(const char *a
, const char *b
)
1903 if ((a
== NULL
&& b
!= NULL
) || (a
!= NULL
&& b
== NULL
))
1905 if (a
!= NULL
&& strcmp(a
, b
) != 0)
1911 * Compare two forwards, returning non-zero if they are identical or
1915 forward_equals(const struct Forward
*a
, const struct Forward
*b
)
1917 if (strcmp_maybe_null(a
->listen_host
, b
->listen_host
) == 0)
1919 if (a
->listen_port
!= b
->listen_port
)
1921 if (strcmp_maybe_null(a
->listen_path
, b
->listen_path
) == 0)
1923 if (strcmp_maybe_null(a
->connect_host
, b
->connect_host
) == 0)
1925 if (a
->connect_port
!= b
->connect_port
)
1927 if (strcmp_maybe_null(a
->connect_path
, b
->connect_path
) == 0)
1929 /* allocated_port and handle are not checked */
1933 /* returns 1 if process is already daemonized, 0 otherwise */
1939 if ((fd
= open(_PATH_TTY
, O_RDONLY
| O_NOCTTY
)) >= 0) {
1941 return 0; /* have controlling terminal */
1944 return 0; /* parent is not init */
1945 if (getsid(0) != getpid())
1946 return 0; /* not session leader */
1947 debug3("already daemonized");
1952 * Splits 's' into an argument vector. Handles quoted string and basic
1953 * escape characters (\\, \", \'). Caller must free the argument vector
1957 argv_split(const char *s
, int *argcp
, char ***argvp
, int terminate_on_comment
)
1959 int r
= SSH_ERR_INTERNAL_ERROR
;
1960 int argc
= 0, quote
, i
, j
;
1961 char *arg
, **argv
= xcalloc(1, sizeof(*argv
));
1966 for (i
= 0; s
[i
] != '\0'; i
++) {
1967 /* Skip leading whitespace */
1968 if (s
[i
] == ' ' || s
[i
] == '\t')
1970 if (terminate_on_comment
&& s
[i
] == '#')
1972 /* Start of a token */
1975 argv
= xreallocarray(argv
, (argc
+ 2), sizeof(*argv
));
1976 arg
= argv
[argc
++] = xcalloc(1, strlen(s
+ i
) + 1);
1979 /* Copy the token in, removing escapes */
1980 for (j
= 0; s
[i
] != '\0'; i
++) {
1982 if (s
[i
+ 1] == '\'' ||
1985 (quote
== 0 && s
[i
+ 1] == ' ')) {
1989 /* Unrecognised escape */
1992 } else if (quote
== 0 && (s
[i
] == ' ' || s
[i
] == '\t'))
1994 else if (quote
== 0 && (s
[i
] == '\"' || s
[i
] == '\''))
1995 quote
= s
[i
]; /* quote start */
1996 else if (quote
!= 0 && s
[i
] == quote
)
1997 quote
= 0; /* quote end */
2003 /* Ran out of string looking for close quote */
2004 r
= SSH_ERR_INVALID_FORMAT
;
2017 if (argc
!= 0 && argv
!= NULL
) {
2018 for (i
= 0; i
< argc
; i
++)
2026 * Reassemble an argument vector into a string, quoting and escaping as
2027 * necessary. Caller must free returned string.
2030 argv_assemble(int argc
, char **argv
)
2034 struct sshbuf
*buf
, *arg
;
2036 if ((buf
= sshbuf_new()) == NULL
|| (arg
= sshbuf_new()) == NULL
)
2037 fatal_f("sshbuf_new failed");
2039 for (i
= 0; i
< argc
; i
++) {
2042 for (j
= 0; argv
[i
][j
] != '\0'; j
++) {
2049 r
= sshbuf_put_u8(arg
, c
);
2054 if ((r
= sshbuf_put_u8(arg
, '\\')) != 0)
2058 r
= sshbuf_put_u8(arg
, c
);
2062 fatal_fr(r
, "sshbuf_put_u8");
2064 if ((i
!= 0 && (r
= sshbuf_put_u8(buf
, ' ')) != 0) ||
2065 (ws
!= 0 && (r
= sshbuf_put_u8(buf
, '"')) != 0) ||
2066 (r
= sshbuf_putb(buf
, arg
)) != 0 ||
2067 (ws
!= 0 && (r
= sshbuf_put_u8(buf
, '"')) != 0))
2068 fatal_fr(r
, "assemble");
2070 if ((ret
= malloc(sshbuf_len(buf
) + 1)) == NULL
)
2071 fatal_f("malloc failed");
2072 memcpy(ret
, sshbuf_ptr(buf
), sshbuf_len(buf
));
2073 ret
[sshbuf_len(buf
)] = '\0';
2080 argv_next(int *argcp
, char ***argvp
)
2082 char *ret
= (*argvp
)[0];
2084 if (*argcp
> 0 && ret
!= NULL
) {
2092 argv_consume(int *argcp
)
2098 argv_free(char **av
, int ac
)
2104 for (i
= 0; i
< ac
; i
++)
2109 /* Returns 0 if pid exited cleanly, non-zero otherwise */
2111 exited_cleanly(pid_t pid
, const char *tag
, const char *cmd
, int quiet
)
2115 while (waitpid(pid
, &status
, 0) == -1) {
2116 if (errno
!= EINTR
) {
2117 error("%s waitpid: %s", tag
, strerror(errno
));
2121 if (WIFSIGNALED(status
)) {
2122 error("%s %s exited on signal %d", tag
, cmd
, WTERMSIG(status
));
2124 } else if (WEXITSTATUS(status
) != 0) {
2125 do_log2(quiet
? SYSLOG_LEVEL_DEBUG1
: SYSLOG_LEVEL_INFO
,
2126 "%s %s failed, status %d", tag
, cmd
, WEXITSTATUS(status
));
2133 * Check a given path for security. This is defined as all components
2134 * of the path to the file must be owned by either the owner of
2135 * of the file or root and no directories must be group or world writable.
2137 * XXX Should any specific check be done for sym links ?
2139 * Takes a file name, its stat information (preferably from fstat() to
2140 * avoid races), the uid of the expected owner, their home directory and an
2141 * error buffer plus max size as arguments.
2143 * Returns 0 on success and -1 on failure
2146 safe_path(const char *name
, struct stat
*stp
, const char *pw_dir
,
2147 uid_t uid
, char *err
, size_t errlen
)
2149 char buf
[PATH_MAX
], homedir
[PATH_MAX
];
2151 int comparehome
= 0;
2154 if (realpath(name
, buf
) == NULL
) {
2155 snprintf(err
, errlen
, "realpath %s failed: %s", name
,
2159 if (pw_dir
!= NULL
&& realpath(pw_dir
, homedir
) != NULL
)
2162 if (!S_ISREG(stp
->st_mode
)) {
2163 snprintf(err
, errlen
, "%s is not a regular file", buf
);
2166 if ((!platform_sys_dir_uid(stp
->st_uid
) && stp
->st_uid
!= uid
) ||
2167 (stp
->st_mode
& 022) != 0) {
2168 snprintf(err
, errlen
, "bad ownership or modes for file %s",
2173 /* for each component of the canonical path, walking upwards */
2175 if ((cp
= dirname(buf
)) == NULL
) {
2176 snprintf(err
, errlen
, "dirname() failed");
2179 strlcpy(buf
, cp
, sizeof(buf
));
2181 if (stat(buf
, &st
) == -1 ||
2182 (!platform_sys_dir_uid(st
.st_uid
) && st
.st_uid
!= uid
) ||
2183 (st
.st_mode
& 022) != 0) {
2184 snprintf(err
, errlen
,
2185 "bad ownership or modes for directory %s", buf
);
2189 /* If are past the homedir then we can stop */
2190 if (comparehome
&& strcmp(homedir
, buf
) == 0)
2194 * dirname should always complete with a "/" path,
2195 * but we can be paranoid and check for "." too
2197 if ((strcmp("/", buf
) == 0) || (strcmp(".", buf
) == 0))
2204 * Version of safe_path() that accepts an open file descriptor to
2207 * Returns 0 on success and -1 on failure
2210 safe_path_fd(int fd
, const char *file
, struct passwd
*pw
,
2211 char *err
, size_t errlen
)
2215 /* check the open file to avoid races */
2216 if (fstat(fd
, &st
) == -1) {
2217 snprintf(err
, errlen
, "cannot stat file %s: %s",
2218 file
, strerror(errno
));
2221 return safe_path(file
, &st
, pw
->pw_dir
, pw
->pw_uid
, err
, errlen
);
2225 * Sets the value of the given variable in the environment. If the variable
2226 * already exists, its value is overridden.
2229 child_set_env(char ***envp
, u_int
*envsizep
, const char *name
,
2236 if (strchr(name
, '=') != NULL
) {
2237 error("Invalid environment variable \"%.100s\"", name
);
2242 * If we're passed an uninitialized list, allocate a single null
2243 * entry before continuing.
2245 if (*envp
== NULL
&& *envsizep
== 0) {
2246 *envp
= xmalloc(sizeof(char *));
2252 * Find the slot where the value should be stored. If the variable
2253 * already exists, we reuse the slot; otherwise we append a new slot
2254 * at the end of the array, expanding if necessary.
2257 namelen
= strlen(name
);
2258 for (i
= 0; env
[i
]; i
++)
2259 if (strncmp(env
[i
], name
, namelen
) == 0 && env
[i
][namelen
] == '=')
2262 /* Reuse the slot. */
2265 /* New variable. Expand if necessary. */
2266 envsize
= *envsizep
;
2267 if (i
>= envsize
- 1) {
2268 if (envsize
>= 1000)
2269 fatal("child_set_env: too many env vars");
2271 env
= (*envp
) = xreallocarray(env
, envsize
, sizeof(char *));
2272 *envsizep
= envsize
;
2274 /* Need to set the NULL pointer at end of array beyond the new slot. */
2278 /* Allocate space and format the variable in the appropriate slot. */
2280 env
[i
] = xmalloc(strlen(name
) + 1 + strlen(value
) + 1);
2281 snprintf(env
[i
], strlen(name
) + 1 + strlen(value
) + 1, "%s=%s", name
, value
);
2285 * Check and optionally lowercase a domain name, also removes trailing '.'
2286 * Returns 1 on success and 0 on failure, storing an error message in errstr.
2289 valid_domain(char *name
, int makelower
, const char **errstr
)
2291 size_t i
, l
= strlen(name
);
2292 u_char c
, last
= '\0';
2293 static char errbuf
[256];
2296 strlcpy(errbuf
, "empty domain name", sizeof(errbuf
));
2299 if (!isalpha((u_char
)name
[0]) && !isdigit((u_char
)name
[0])) {
2300 snprintf(errbuf
, sizeof(errbuf
), "domain name \"%.100s\" "
2301 "starts with invalid character", name
);
2304 for (i
= 0; i
< l
; i
++) {
2305 c
= tolower((u_char
)name
[i
]);
2308 if (last
== '.' && c
== '.') {
2309 snprintf(errbuf
, sizeof(errbuf
), "domain name "
2310 "\"%.100s\" contains consecutive separators", name
);
2313 if (c
!= '.' && c
!= '-' && !isalnum(c
) &&
2314 c
!= '_') /* technically invalid, but common */ {
2315 snprintf(errbuf
, sizeof(errbuf
), "domain name "
2316 "\"%.100s\" contains invalid characters", name
);
2321 if (name
[l
- 1] == '.')
2333 * Verify that a environment variable name (not including initial '$') is
2334 * valid; consisting of one or more alphanumeric or underscore characters only.
2335 * Returns 1 on valid, 0 otherwise.
2338 valid_env_name(const char *name
)
2342 if (name
[0] == '\0')
2344 for (cp
= name
; *cp
!= '\0'; cp
++) {
2345 if (!isalnum((u_char
)*cp
) && *cp
!= '_')
2352 atoi_err(const char *nptr
, int *val
)
2354 const char *errstr
= NULL
;
2357 if (nptr
== NULL
|| *nptr
== '\0')
2359 num
= strtonum(nptr
, 0, INT_MAX
, &errstr
);
2366 parse_absolute_time(const char *s
, uint64_t *tp
)
2375 * POSIX strptime says "The application shall ensure that there
2376 * is white-space or other non-alphanumeric characters between
2377 * any two conversion specifications" so arrange things this way.
2379 switch (strlen(s
)) {
2380 case 8: /* YYYYMMDD */
2382 snprintf(buf
, sizeof(buf
), "%.4s-%.2s-%.2s", s
, s
+ 4, s
+ 6);
2384 case 12: /* YYYYMMDDHHMM */
2385 fmt
= "%Y-%m-%dT%H:%M";
2386 snprintf(buf
, sizeof(buf
), "%.4s-%.2s-%.2sT%.2s:%.2s",
2387 s
, s
+ 4, s
+ 6, s
+ 8, s
+ 10);
2389 case 14: /* YYYYMMDDHHMMSS */
2390 fmt
= "%Y-%m-%dT%H:%M:%S";
2391 snprintf(buf
, sizeof(buf
), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s",
2392 s
, s
+ 4, s
+ 6, s
+ 8, s
+ 10, s
+ 12);
2395 return SSH_ERR_INVALID_FORMAT
;
2398 memset(&tm
, 0, sizeof(tm
));
2399 if (strptime(buf
, fmt
, &tm
) == NULL
)
2400 return SSH_ERR_INVALID_FORMAT
;
2401 if ((tt
= mktime(&tm
)) < 0)
2402 return SSH_ERR_INVALID_FORMAT
;
2408 /* On OpenBSD time_t is int64_t which is long long. */
2409 /* #define SSH_TIME_T_MAX LLONG_MAX */
2412 format_absolute_time(uint64_t t
, char *buf
, size_t len
)
2414 time_t tt
= t
> SSH_TIME_T_MAX
? SSH_TIME_T_MAX
: t
;
2417 localtime_r(&tt
, &tm
);
2418 strftime(buf
, len
, "%Y-%m-%dT%H:%M:%S", &tm
);
2421 /* check if path is absolute */
2423 path_absolute(const char *path
)
2425 return (*path
== '/') ? 1 : 0;
2429 skip_space(char **cpp
)
2433 for (cp
= *cpp
; *cp
== ' ' || *cp
== '\t'; cp
++)
2438 /* authorized_key-style options parsing helpers */
2441 * Match flag 'opt' in *optsp, and if allow_negate is set then also match
2442 * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0
2443 * if negated option matches.
2444 * If the option or negated option matches, then *optsp is updated to
2445 * point to the first character after the option.
2448 opt_flag(const char *opt
, int allow_negate
, const char **optsp
)
2450 size_t opt_len
= strlen(opt
);
2451 const char *opts
= *optsp
;
2454 if (allow_negate
&& strncasecmp(opts
, "no-", 3) == 0) {
2458 if (strncasecmp(opts
, opt
, opt_len
) == 0) {
2459 *optsp
= opts
+ opt_len
;
2460 return negate
? 0 : 1;
2466 opt_dequote(const char **sp
, const char **errstrp
)
2468 const char *s
= *sp
;
2474 *errstrp
= "missing start quote";
2478 if ((ret
= malloc(strlen((s
)) + 1)) == NULL
) {
2479 *errstrp
= "memory allocation failed";
2482 for (i
= 0; *s
!= '\0' && *s
!= '"';) {
2483 if (s
[0] == '\\' && s
[1] == '"')
2488 *errstrp
= "missing end quote";
2499 opt_match(const char **opts
, const char *term
)
2501 if (strncasecmp((*opts
), term
, strlen(term
)) == 0 &&
2502 (*opts
)[strlen(term
)] == '=') {
2503 *opts
+= strlen(term
) + 1;
2510 opt_array_append2(const char *file
, const int line
, const char *directive
,
2511 char ***array
, int **iarray
, u_int
*lp
, const char *s
, int i
)
2515 fatal("%s line %d: Too many %s entries", file
, line
, directive
);
2517 if (iarray
!= NULL
) {
2518 *iarray
= xrecallocarray(*iarray
, *lp
, *lp
+ 1,
2523 *array
= xrecallocarray(*array
, *lp
, *lp
+ 1, sizeof(**array
));
2524 (*array
)[*lp
] = xstrdup(s
);
2529 opt_array_append(const char *file
, const int line
, const char *directive
,
2530 char ***array
, u_int
*lp
, const char *s
)
2532 opt_array_append2(file
, line
, directive
, array
, NULL
, lp
, s
, 0);
2536 ssh_signal(int signum
, sshsig_t handler
)
2538 struct sigaction sa
, osa
;
2540 /* mask all other signals while in handler */
2541 memset(&sa
, 0, sizeof(sa
));
2542 sa
.sa_handler
= handler
;
2543 sigfillset(&sa
.sa_mask
);
2544 #if defined(SA_RESTART) && !defined(NO_SA_RESTART)
2545 if (signum
!= SIGALRM
)
2546 sa
.sa_flags
= SA_RESTART
;
2548 if (sigaction(signum
, &sa
, &osa
) == -1) {
2549 debug3("sigaction(%s): %s", strsignal(signum
), strerror(errno
));
2552 return osa
.sa_handler
;
2556 stdfd_devnull(int do_stdin
, int do_stdout
, int do_stderr
)
2558 int devnull
, ret
= 0;
2560 if ((devnull
= open(_PATH_DEVNULL
, O_RDWR
)) == -1) {
2561 error_f("open %s: %s", _PATH_DEVNULL
,
2565 if ((do_stdin
&& dup2(devnull
, STDIN_FILENO
) == -1) ||
2566 (do_stdout
&& dup2(devnull
, STDOUT_FILENO
) == -1) ||
2567 (do_stderr
&& dup2(devnull
, STDERR_FILENO
) == -1)) {
2568 error_f("dup2: %s", strerror(errno
));
2571 if (devnull
> STDERR_FILENO
)
2577 * Runs command in a subprocess with a minimal environment.
2578 * Returns pid on success, 0 on failure.
2579 * The child stdout and stderr maybe captured, left attached or sent to
2580 * /dev/null depending on the contents of flags.
2581 * "tag" is prepended to log messages.
2582 * NB. "command" is only used for logging; the actual command executed is
2586 subprocess(const char *tag
, const char *command
,
2587 int ac
, char **av
, FILE **child
, u_int flags
,
2588 struct passwd
*pw
, privdrop_fn
*drop_privs
, privrestore_fn
*restore_privs
)
2592 int fd
, devnull
, p
[2], i
;
2594 char *cp
, errmsg
[512];
2598 /* If dropping privs, then must specify user and restore function */
2599 if (drop_privs
!= NULL
&& (pw
== NULL
|| restore_privs
== NULL
)) {
2600 error("%s: inconsistent arguments", tag
); /* XXX fatal? */
2603 if (pw
== NULL
&& (pw
= getpwuid(getuid())) == NULL
) {
2604 error("%s: no user for current uid", tag
);
2610 debug3_f("%s command \"%s\" running as %s (flags 0x%x)",
2611 tag
, command
, pw
->pw_name
, flags
);
2613 /* Check consistency */
2614 if ((flags
& SSH_SUBPROCESS_STDOUT_DISCARD
) != 0 &&
2615 (flags
& SSH_SUBPROCESS_STDOUT_CAPTURE
) != 0) {
2616 error_f("inconsistent flags");
2619 if (((flags
& SSH_SUBPROCESS_STDOUT_CAPTURE
) == 0) != (child
== NULL
)) {
2620 error_f("inconsistent flags/output");
2625 * If executing an explicit binary, then verify the it exists
2626 * and appears safe-ish to execute
2628 if (!path_absolute(av
[0])) {
2629 error("%s path is not absolute", tag
);
2632 if (drop_privs
!= NULL
)
2634 if (stat(av
[0], &st
) == -1) {
2635 error("Could not stat %s \"%s\": %s", tag
,
2636 av
[0], strerror(errno
));
2637 goto restore_return
;
2639 if ((flags
& SSH_SUBPROCESS_UNSAFE_PATH
) == 0 &&
2640 safe_path(av
[0], &st
, NULL
, 0, errmsg
, sizeof(errmsg
)) != 0) {
2641 error("Unsafe %s \"%s\": %s", tag
, av
[0], errmsg
);
2642 goto restore_return
;
2644 /* Prepare to keep the child's stdout if requested */
2645 if (pipe(p
) == -1) {
2646 error("%s: pipe: %s", tag
, strerror(errno
));
2648 if (restore_privs
!= NULL
)
2652 if (restore_privs
!= NULL
)
2655 switch ((pid
= fork())) {
2656 case -1: /* error */
2657 error("%s: fork: %s", tag
, strerror(errno
));
2662 /* Prepare a minimal environment for the child. */
2663 if ((flags
& SSH_SUBPROCESS_PRESERVE_ENV
) == 0) {
2665 env
= xcalloc(sizeof(*env
), nenv
);
2666 child_set_env(&env
, &nenv
, "PATH", _PATH_STDPATH
);
2667 child_set_env(&env
, &nenv
, "USER", pw
->pw_name
);
2668 child_set_env(&env
, &nenv
, "LOGNAME", pw
->pw_name
);
2669 child_set_env(&env
, &nenv
, "HOME", pw
->pw_dir
);
2670 if ((cp
= getenv("LANG")) != NULL
)
2671 child_set_env(&env
, &nenv
, "LANG", cp
);
2674 for (i
= 1; i
< NSIG
; i
++)
2675 ssh_signal(i
, SIG_DFL
);
2677 if ((devnull
= open(_PATH_DEVNULL
, O_RDWR
)) == -1) {
2678 error("%s: open %s: %s", tag
, _PATH_DEVNULL
,
2682 if (dup2(devnull
, STDIN_FILENO
) == -1) {
2683 error("%s: dup2: %s", tag
, strerror(errno
));
2687 /* Set up stdout as requested; leave stderr in place for now. */
2689 if ((flags
& SSH_SUBPROCESS_STDOUT_CAPTURE
) != 0)
2691 else if ((flags
& SSH_SUBPROCESS_STDOUT_DISCARD
) != 0)
2693 if (fd
!= -1 && dup2(fd
, STDOUT_FILENO
) == -1) {
2694 error("%s: dup2: %s", tag
, strerror(errno
));
2697 closefrom(STDERR_FILENO
+ 1);
2699 if (geteuid() == 0 &&
2700 initgroups(pw
->pw_name
, pw
->pw_gid
) == -1) {
2701 error("%s: initgroups(%s, %u): %s", tag
,
2702 pw
->pw_name
, (u_int
)pw
->pw_gid
, strerror(errno
));
2705 if (setresgid(pw
->pw_gid
, pw
->pw_gid
, pw
->pw_gid
) == -1) {
2706 error("%s: setresgid %u: %s", tag
, (u_int
)pw
->pw_gid
,
2710 if (setresuid(pw
->pw_uid
, pw
->pw_uid
, pw
->pw_uid
) == -1) {
2711 error("%s: setresuid %u: %s", tag
, (u_int
)pw
->pw_uid
,
2715 /* stdin is pointed to /dev/null at this point */
2716 if ((flags
& SSH_SUBPROCESS_STDOUT_DISCARD
) != 0 &&
2717 dup2(STDIN_FILENO
, STDERR_FILENO
) == -1) {
2718 error("%s: dup2: %s", tag
, strerror(errno
));
2722 execve(av
[0], av
, env
);
2725 error("%s %s \"%s\": %s", tag
, env
== NULL
? "execv" : "execve",
2726 command
, strerror(errno
));
2728 default: /* parent */
2733 if ((flags
& SSH_SUBPROCESS_STDOUT_CAPTURE
) == 0)
2735 else if ((f
= fdopen(p
[0], "r")) == NULL
) {
2736 error("%s: fdopen: %s", tag
, strerror(errno
));
2738 /* Don't leave zombie child */
2740 while (waitpid(pid
, NULL
, 0) == -1 && errno
== EINTR
)
2745 debug3_f("%s pid %ld", tag
, (long)pid
);
2752 lookup_env_in_list(const char *env
, char * const *envs
, size_t nenvs
)
2756 envlen
= strlen(env
);
2757 for (i
= 0; i
< nenvs
; i
++) {
2758 if (strncmp(envs
[i
], env
, envlen
) == 0 &&
2759 envs
[i
][envlen
] == '=') {
2760 return envs
[i
] + envlen
+ 1;